diff --git a/dnsapi/dns_opusdns.sh b/dnsapi/dns_opusdns.sh index f6bd507e..b9337b89 100755 --- a/dnsapi/dns_opusdns.sh +++ b/dnsapi/dns_opusdns.sh @@ -124,7 +124,8 @@ dns_opusdns_rm() { ######## Private functions ########### -# Detect zone from FQDN by querying OpusDNS API +# Detect zone from FQDN by checking against OpusDNS API +# Iterates through domain parts until a valid zone is found # Sets global variables: _zone, _record_name _get_zone() { domain=$1 @@ -133,100 +134,41 @@ _get_zone() { # Remove trailing dot if present domain=$(echo "$domain" | sed 's/\.$//') - # Get all zones from OpusDNS with pagination support export _H1="X-Api-Key: $OPUSDNS_API_Key" - zones="" - page=1 - has_more=1 - - while [ $has_more -eq 1 ]; do - _debug2 "Fetching zones page $page" - response=$(_get "$OPUSDNS_API_Endpoint/v1/dns?page=$page&page_size=100") - if [ $? -ne 0 ]; then - _err "Failed to query zones from OpusDNS API (page $page)" - _debug "Response: $response" + # Start from position 2 (skip first part like _acme-challenge) + i=2 + p=1 + while true; do + # Extract potential zone (domain parts from position i onwards) + h=$(printf "%s" "$domain" | cut -d . -f "$i"-100) + _debug "Trying zone: $h" + + if [ -z "$h" ]; then + # No more parts to try + _err "Could not find a valid zone for: $domain" return 1 fi - _debug2 "Zones response (page $page): $response" - - # Extract zone names from this page - # The API returns: {"results":[{"name":"zone.com.",...},...],"pagination":{"has_next_page":true,...}} - if _exists jq; then - page_zones=$(echo "$response" | jq -r '.results[].name' 2>/dev/null | sed 's/\.$//') - has_next=$(echo "$response" | jq -r '.pagination.has_next_page // false' 2>/dev/null) - else - # Fallback: extract zone names using grep/sed - # Extract only top-level zone names from results array (before rrsets) - # Pattern: "results":[{"...","name":"zonename.com.","domain_parts": - page_zones=$(echo "$response" | sed 's/,"rrsets":\[[^]]*\]//g' | grep -o '"results":\[.*\]' | grep -o '"name":"[^"]*"' | sed 's/"name":"//g;s/"//g;s/\.$//') - # Extract has_next_page from pagination object - if echo "$response" | grep -q '"has_next_page":true'; then - has_next="true" - else - has_next="false" - fi - fi - - _debug2 "Page $page zones: $page_zones" - _debug2 "Has next page: $has_next" - - # Append zones from this page - if [ -n "$page_zones" ]; then - if [ -z "$zones" ]; then - zones="$page_zones" - else - zones="$zones -$page_zones" - fi - fi + # Check if this zone exists in OpusDNS + response=$(_get "$OPUSDNS_API_Endpoint/v1/dns/$h") - # Check if there are more pages - if [ "$has_next" = "true" ]; then - page=$((page + 1)) - else - has_more=0 + if _contains "$response" '"name"'; then + # Zone found + _record_name=$(printf "%s" "$domain" | cut -d . -f 1-"$p") + _zone="$h" + _debug "Found zone: $_zone" + _debug "Record name: $_record_name" + return 0 fi - done - - if [ -z "$zones" ]; then - _err "No zones found in OpusDNS account" - _debug "API Response: $response" - return 1 - fi - _debug2 "Available zones (all pages): $zones" - - # Find longest matching zone - _zone="" - _zone_length=0 - - for zone in $zones; do - zone_with_dot="${zone}." - if _endswith "$domain." "$zone_with_dot"; then - zone_length=${#zone} - if [ "$zone_length" -gt "$_zone_length" ]; then - _zone="$zone" - _zone_length=$zone_length - fi - fi + _debug "$h not found, trying next" + p="$i" + i=$(_math "$i" + 1) done - if [ -z "$_zone" ]; then - _err "No matching zone found for domain: $domain" - _err "Available zones: $zones" - return 1 - fi - - # Calculate record name (subdomain part) - # Use parameter expansion instead of sed to avoid regex metacharacter issues - _record_name="${domain%."${_zone}"}" - # Handle case where domain equals zone (remove trailing dot if present) - if [ "$_record_name" = "$domain" ]; then - _record_name="${domain%"${_zone}"}" - _record_name="${_record_name%.}" - fi + return 1 +} if [ -z "$_record_name" ]; then _record_name="@"