The add/rm success check never rejected anything: for any non-empty API
response it always reported "Record added"/"Record deleted" and returned
0, so the _err branch was dead code. A valid key looked fine only because
the API call genuinely created the record; an invalid key returning
{"result":"error"} produced the same "Record added" output even though
nothing was created.
Root cause, in:
if [ -n "$response" ]; then
if [ ! "$(echo "$response" | _contains '"result":"success"')" ]; then
- _contains() ignores stdin (it reads only $1 and $2), so the piped
"$response" was discarded.
- The pattern '"result":"success"' was passed as $1 (the haystack),
leaving $2 (the needle) empty, so it ran:
echo '"result":"success"' | grep -- "" >/dev/null 2>&1
grep with an empty pattern always matches.
- That grep output is redirected to /dev/null, so the command
substitution always captured "", making [ ! "" ] always true.
Fix: call _contains "$response" '"result":"success"' directly and branch
on its exit code, so error responses now correctly fail (return 1).
Co-authored-by: neil <github@neilpang.com>
* fix(dns_desec): sleep after DNS record change to prevent rate limit issues
Also: make sure the subname is lowercase to fix tests where
the acmetestXyzRandomName subdomain is used.
* fix: make regexes POSIX-compatible (for OpenBSD)
* chore: use _sleep instead of sleep to follow acme.sh standards
* Add Level27 DNS API support
Implements dns_level27_add and dns_level27_rm for the Level27 (level27.eu) DNS API, used for ACME dns-01 challenges.
- Authenticates with a persistent API key via the Authorization header.
- Resolves the registered zone with domains?filter and exact fullname match (supports DNS alias mode).
- Removes the challenge record by its exact TXT value, leaving other records intact (wildcard-safe).
- Optional LEVEL27_API override for non-default/staging endpoints.
* A little better documentation
---------
Co-authored-by: Jeroen Moors <jeroen.moors@level27.be>
Firestorm.ch is a Swiss hosting provider with managed DNS (PowerDNS).
This plugin allows customers to automate Let's Encrypt DNS-01 challenges
via the Firestorm DNS API.
The error response also contains 'name' in 'zone_name' field,
causing false positives. Check for 'dnssec_status' which only
exists in valid zone responses.
- Added _opusdns_api() for all API requests
- Added _opusdns_init() for config initialization
- Removed duplicate code in add/rm functions
- Removed dead code (orphaned lines 173-178)
- Script now 158 lines (was 255, originally 379)
Instead of fetching all zones and matching, iterate through domain
parts and check each against the API until a valid zone is found.
Same approach as GoDaddy DNS plugin.
Example: _acme-challenge.test.example.com
- Try: test.example.com → 404
- Try: example.com → 200 ✓ → zone found!
Script reduced from 304 to 255 lines.
- Fixed jq path: .pagination.has_next_page instead of .has_next_page
- Fixed grep fallback: remove rrsets before extracting zone names
to avoid matching nested 'name' fields
- Simplified has_next_page detection with simple grep -q
- Added debug output for page zones and has_next status
acme.sh handles DNS propagation checking internally via --dnssleep
and _check_dns_record. Custom propagation checks are unnecessary
and can conflict with acme.sh's own timing.
Removed:
- _opusdns_wait_for_propagation() function
- OPUSDNS_Polling_Interval option
- OPUSDNS_Propagation_Timeout option
Script is now consistent with other DNS API implementations
(Cloudflare, AWS, etc.) which don't have custom propagation checks.