| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234 |
- #!/usr/bin/env sh
- #This file name is "dns_dnsservices.sh"
- #Script for Danish DNS registra and DNS hosting provider https://dns.services
- #Author: Bjarke Bruun <[email protected]>
- #Report Bugs here: https://github.com/acmesh-official/acme.sh/issues/4152
- # Global variable to connect to the DNS.Services API
- DNSServices_API=https://dns.services/api
- ######## Public functions #####################
- #Usage: dns_dnsservices_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
- dns_dnsservices_add() {
- fulldomain=$1
- txtvalue=$2
- _info "Using dns.services to create ACME DNS challenge"
- _debug2 add_fulldomain "$fulldomain"
- _debug2 add_txtvalue "$txtvalue"
- # Read username/password from environment or .acme.sh/accounts.conf
- DnsServices_Username="${DnsServices_Username:-$(_readaccountconf_mutable DnsServices_Username)}"
- DnsServices_Password="${DnsServices_Password:-$(_readaccountconf_mutable DnsServices_Password)}"
- if [ -z "$DnsServices_Username" ] || [ -z "$DnsServices_Password" ]; then
- DnsServices_Username=""
- DnsServices_Password=""
- _err "You didn't specify dns.services api username and password yet."
- _err "Set environment variables DnsServices_Username and DnsServices_Password"
- return 1
- fi
- # Setup GET/POST/DELETE headers
- _setup_headers
- #save the credentials to the account conf file.
- _saveaccountconf_mutable DnsServices_Username "$DnsServices_Username"
- _saveaccountconf_mutable DnsServices_Password "$DnsServices_Password"
- if ! _contains "$DnsServices_Username" "@"; then
- _err "It seems that the username variable DnsServices_Username has not been set/left blank"
- _err "or is not a valid email. Please correct and try again."
- return 1
- fi
- if ! _get_root "${fulldomain}"; then
- _err "Invalid domain ${fulldomain}"
- return 1
- fi
- if ! createRecord "$fulldomain" "${txtvalue}"; then
- _err "Error creating TXT record in domain $fulldomain in $rootZoneName"
- return 1
- fi
- _debug2 challenge-created "Created $fulldomain"
- return 0
- }
- #Usage: fulldomain txtvalue
- #Description: Remove the txt record after validation.
- dns_dnsservices_rm() {
- fulldomain=$1
- txtvalue=$2
- _info "Using dns.services to remove DNS record $fulldomain TXT $txtvalue"
- _debug rm_fulldomain "$fulldomain"
- _debug rm_txtvalue "$txtvalue"
- # Read username/password from environment or .acme.sh/accounts.conf
- DnsServices_Username="${DnsServices_Username:-$(_readaccountconf_mutable DnsServices_Username)}"
- DnsServices_Password="${DnsServices_Password:-$(_readaccountconf_mutable DnsServices_Password)}"
- if [ -z "$DnsServices_Username" ] || [ -z "$DnsServices_Password" ]; then
- DnsServices_Username=""
- DnsServices_Password=""
- _err "You didn't specify dns.services api username and password yet."
- _err "Set environment variables DnsServices_Username and DnsServices_Password"
- return 1
- fi
- # Setup GET/POST/DELETE headers
- _setup_headers
- if ! _get_root "${fulldomain}"; then
- _err "Invalid domain ${fulldomain}"
- return 1
- fi
- _debug2 rm_rootDomainInfo "found root domain $rootZoneName for $fulldomain"
- if ! deleteRecord "${fulldomain}" "${txtvalue}"; then
- _err "Error removing record: $fulldomain TXT ${txtvalue}"
- return 1
- fi
- return 0
- }
- #################### Private functions below ##################################
- _setup_headers() {
- # Set up API Headers for _get() and _post()
- # The <function>_add or <function>_rm must have been called before to work
- if [ -z "$DnsServices_Username" ] || [ -z "$DnsServices_Password" ]; then
- _err "Could not setup BASIC authentication headers, they are missing"
- return 1
- fi
- DnsServiceCredentials="$(printf "%s" "$DnsServices_Username:$DnsServices_Password" | _base64)"
- export _H1="Authorization: Basic $DnsServiceCredentials"
- export _H2="Content-Type: application/json"
- # Just return if headers are set
- return 0
- }
- _get_root() {
- domain=$1
- _debug2 _get_root "Get the root domain of ${domain} for DNS API"
- # Setup _get() and _post() headers
- #_setup_headers
- result=$(_H1="$_H1" _H2="$_H2" _get "$DNSServices_API/dns")
- _debug2 _get_root "Got the following root domain(s) $result"
- _debug2 _get_root "- JSON: $result"
- if [ "$(echo "$result" | grep -c '"name"')" -gt "1" ]; then
- checkMultiZones="true"
- _debug2 _get_root "- multiple zones found"
- else
- checkMultiZones="false"
- fi
- # Find/isolate the root zone to work with in createRecord() and deleteRecord()
- rootZone=""
- if [ "$checkMultiZones" = "true" ]; then
- rootZone=$(for zone in $(echo "$result" | tr -d '\n' ' '); do
- if [ "$(echo "$domain" | grep "$zone")" != "" ]; then
- _debug2 _get_root "- trying to figure out if $zone is in $domain"
- echo "$zone"
- break
- fi
- done)
- else
- rootZone=$(echo "$result" | _egrep_o '"name":"[^"]*' | cut -d'"' -f4)
- _debug2 _get_root "- only found 1 domain in API: $rootZone"
- fi
- if [ -z "$rootZone" ]; then
- _err "Could not find root domain for $domain - is it correctly typed?"
- return 1
- fi
- # Setup variables used by other functions to communicate with DNS.Services API
- #zoneInfo=$(echo "$result" | sed "s,\"zones,\n&,g" | grep zones | cut -d'[' -f2 | cut -d']' -f1 | tr '}' '\n' | grep "\"$rootZone\"")
- zoneInfo=$(echo "$result" | sed -E 's,.*(zones)(.*),\1\2,g' | sed -E 's,^(.*"name":")([^"]*)"(.*)$,\2,g' | grep "\"$rootZone\"")
- rootZoneName="$rootZone"
- subDomainName="$(echo "$domain" | sed "s,\.$rootZone,,g")"
- subDomainNameClean="$(echo "$domain" | sed "s,_acme-challenge.,,g")"
- rootZoneDomainID=$(echo "$result" | sed -E 's,.*(zones)(.*),\1\2,g' | sed -E 's,^(.*"domain_id":")([^"]*)"(.*)$,\2,g')
- rootZoneServiceID=$(echo "$result" | sed -E 's,.*(zones)(.*),\1\2,g' | sed -E 's,^(.*"service_id":")([^"]*)"(.*)$,\2,g')
- _debug2 _zoneInfo "Zone info from API : $zoneInfo"
- _debug2 _get_root "Root zone name : $rootZoneName"
- _debug2 _get_root "Root zone domain ID : $rootZoneDomainID"
- _debug2 _get_root "Root zone service ID: $rootZoneServiceID"
- _debug2 _get_root "Sub domain : $subDomainName"
- _debug _get_root "Found valid root domain $rootZone for $subDomainNameClean"
- return 0
- }
- createRecord() {
- fulldomain=$1
- txtvalue="$2"
- # Get root domain information - needed for DNS.Services API communication
- if [ -z "$rootZoneName" ] || [ -z "$rootZoneDomainID" ] || [ -z "$rootZoneServiceID" ]; then
- _get_root "$fulldomain"
- fi
- _debug2 createRecord "CNAME TXT value is: $txtvalue"
- # Prepare data to send to API
- data="{\"name\":\"${fulldomain}\",\"type\":\"TXT\",\"content\":\"${txtvalue}\", \"ttl\":\"10\"}"
- _debug2 createRecord "data to API: $data"
- result=$(_post "$data" "$DNSServices_API/service/$rootZoneServiceID/dns/$rootZoneDomainID/records" "" "POST")
- _debug2 createRecord "result from API: $result"
- if [ "$(echo "$result" | _egrep_o "\"success\":true")" = "" ]; then
- _err "Failed to create TXT record $fulldomain with content $txtvalue in zone $rootZoneName"
- _err "$result"
- return 1
- fi
- _info "Record \"$fulldomain TXT $txtvalue\" has been created"
- return 0
- }
- deleteRecord() {
- fulldomain=$1
- txtvalue=$2
- _log deleteRecord "Deleting $fulldomain TXT $txtvalue record"
- if [ -z "$rootZoneName" ] || [ -z "$rootZoneDomainID" ] || [ -z "$rootZoneServiceID" ]; then
- _get_root "$fulldomain"
- fi
- result="$(_H1="$_H1" _H2="$_H2" _get "$DNSServices_API/service/$rootZoneServiceID/dns/$rootZoneDomainID")"
- recordInfo="$(echo "$result" | sed -e 's/:{/:{\n/g' -e 's/},/\n},\n/g' | grep "${txtvalue}")"
- recordID="$(echo "$recordInfo" | sed -e 's/:{/:{\n/g' -e 's/},/\n},\n/g' | grep "${txtvalue}" | sed -E 's,.*(zones)(.*),\1\2,g' | sed -E 's,^(.*"id":")([^"]*)"(.*)$,\2,g')"
- if [ -z "$recordID" ]; then
- _info "Record $fulldomain TXT $txtvalue not found or already deleted"
- return 0
- else
- _debug2 deleteRecord "Found recordID=$recordID"
- fi
- _debug2 deleteRecord "DELETE request $DNSServices_API/service/$rootZoneServiceID/dns/$rootZoneDomainID/records/$recordID"
- _log "curl DELETE request $DNSServices_API/service/$rootZoneServiceID/dns/$rootZoneDomainID/records/$recordID"
- result="$(_H1="$_H1" _H2="$_H2" _post "" "$DNSServices_API/service/$rootZoneServiceID/dns/$rootZoneDomainID/records/$recordID" "" "DELETE")"
- _debug2 deleteRecord "API Delete result \"$result\""
- _log "curl API Delete result \"$result\""
- # Return OK regardless
- return 0
- }
|