Browse Source
Merge pull request #4292 from nosilver4u/bunny
Merge pull request #4292 from nosilver4u/bunny
Add Bunny DNS API verification methodpull/4297/head
neil
2 years ago
committed by
GitHub
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
1 changed files with 248 additions and 0 deletions
@ -0,0 +1,248 @@ |
|||
#!/usr/bin/env sh |
|||
|
|||
## Will be called by acme.sh to add the TXT record via the Bunny DNS API. |
|||
## returns 0 means success, otherwise error. |
|||
|
|||
## Author: nosilver4u <nosilver4u at ewww.io> |
|||
## GitHub: https://github.com/nosilver4u/acme.sh |
|||
|
|||
## |
|||
## Environment Variables Required: |
|||
## |
|||
## BUNNY_API_KEY="75310dc4-ca77-9ac3-9a19-f6355db573b49ce92ae1-2655-3ebd-61ac-3a3ae34834cc" |
|||
## |
|||
|
|||
##################### Public functions ##################### |
|||
|
|||
## Create the text record for validation. |
|||
## Usage: fulldomain txtvalue |
|||
## EG: "_acme-challenge.www.other.domain.com" "XKrxpRBosdq0HG9i01zxXp5CPBs" |
|||
dns_bunny_add() { |
|||
fulldomain="$(echo "$1" | _lower_case)" |
|||
txtvalue=$2 |
|||
|
|||
BUNNY_API_KEY="${BUNNY_API_KEY:-$(_readaccountconf_mutable BUNNY_API_KEY)}" |
|||
# Check if API Key is set |
|||
if [ -z "$BUNNY_API_KEY" ]; then |
|||
BUNNY_API_KEY="" |
|||
_err "You did not specify Bunny.net API key." |
|||
_err "Please export BUNNY_API_KEY and try again." |
|||
return 1 |
|||
fi |
|||
|
|||
_info "Using Bunny.net dns validation - add record" |
|||
_debug fulldomain "$fulldomain" |
|||
_debug txtvalue "$txtvalue" |
|||
|
|||
## save the env vars (key and domain split location) for later automated use |
|||
_saveaccountconf_mutable BUNNY_API_KEY "$BUNNY_API_KEY" |
|||
|
|||
## split the domain for Bunny API |
|||
if ! _get_base_domain "$fulldomain"; then |
|||
_err "domain not found in your account for addition" |
|||
return 1 |
|||
fi |
|||
_debug _sub_domain "$_sub_domain" |
|||
_debug _domain "$_domain" |
|||
_debug _domain_id "$_domain_id" |
|||
|
|||
## Set the header with our post type and auth key |
|||
export _H1="Accept: application/json" |
|||
export _H2="AccessKey: $BUNNY_API_KEY" |
|||
export _H3="Content-Type: application/json" |
|||
PURL="https://api.bunny.net/dnszone/$_domain_id/records" |
|||
PBODY='{"Id":'$_domain_id',"Type":3,"Name":"'$_sub_domain'","Value":"'$txtvalue'","ttl":120}' |
|||
|
|||
_debug PURL "$PURL" |
|||
_debug PBODY "$PBODY" |
|||
|
|||
## the create request - POST |
|||
## args: BODY, URL, [need64, httpmethod] |
|||
response="$(_post "$PBODY" "$PURL" "" "PUT")" |
|||
|
|||
## check response |
|||
if [ "$?" != "0" ]; then |
|||
_err "error in response: $response" |
|||
return 1 |
|||
fi |
|||
_debug2 response "$response" |
|||
|
|||
## finished correctly |
|||
return 0 |
|||
} |
|||
|
|||
## Remove the txt record after validation. |
|||
## Usage: fulldomain txtvalue |
|||
## EG: "_acme-challenge.www.other.domain.com" "XKrxpRBosdq0HG9i01zxXp5CPBs" |
|||
dns_bunny_rm() { |
|||
fulldomain="$(echo "$1" | _lower_case)" |
|||
txtvalue=$2 |
|||
|
|||
BUNNY_API_KEY="${BUNNY_API_KEY:-$(_readaccountconf_mutable BUNNY_API_KEY)}" |
|||
# Check if API Key Exists |
|||
if [ -z "$BUNNY_API_KEY" ]; then |
|||
BUNNY_API_KEY="" |
|||
_err "You did not specify Bunny.net API key." |
|||
_err "Please export BUNNY_API_KEY and try again." |
|||
return 1 |
|||
fi |
|||
|
|||
_info "Using Bunny.net dns validation - remove record" |
|||
_debug fulldomain "$fulldomain" |
|||
_debug txtvalue "$txtvalue" |
|||
|
|||
## split the domain for Bunny API |
|||
if ! _get_base_domain "$fulldomain"; then |
|||
_err "Domain not found in your account for TXT record removal" |
|||
return 1 |
|||
fi |
|||
_debug _sub_domain "$_sub_domain" |
|||
_debug _domain "$_domain" |
|||
_debug _domain_id "$_domain_id" |
|||
|
|||
## Set the header with our post type and key auth key |
|||
export _H1="Accept: application/json" |
|||
export _H2="AccessKey: $BUNNY_API_KEY" |
|||
## get URL for the list of DNS records |
|||
GURL="https://api.bunny.net/dnszone/$_domain_id" |
|||
|
|||
## 1) Get the domain/zone records |
|||
## the fetch request - GET |
|||
## args: URL, [onlyheader, timeout] |
|||
domain_list="$(_get "$GURL")" |
|||
|
|||
## check response |
|||
if [ "$?" != "0" ]; then |
|||
_err "error in domain_list response: $domain_list" |
|||
return 1 |
|||
fi |
|||
_debug2 domain_list "$domain_list" |
|||
|
|||
## 2) search through records |
|||
## check for what we are looking for: "Type":3,"Value":"$txtvalue","Name":"$_sub_domain" |
|||
record="$(echo "$domain_list" | _egrep_o "\"Id\"\s*\:\s*\"*[0-9]+\"*,\s*\"Type\"[^}]*\"Value\"\s*\:\s*\"$txtvalue\"[^}]*\"Name\"\s*\:\s*\"$_sub_domain\"")" |
|||
|
|||
if [ -n "$record" ]; then |
|||
|
|||
## We found records |
|||
rec_ids="$(echo "$record" | _egrep_o "Id\"\s*\:\s*\"*[0-9]+" | _egrep_o "[0-9]+")" |
|||
_debug rec_ids "$rec_ids" |
|||
if [ -n "$rec_ids" ]; then |
|||
echo "$rec_ids" | while IFS= read -r rec_id; do |
|||
## delete the record |
|||
## delete URL for removing the one we dont want |
|||
DURL="https://api.bunny.net/dnszone/$_domain_id/records/$rec_id" |
|||
|
|||
## the removal request - DELETE |
|||
## args: BODY, URL, [need64, httpmethod] |
|||
response="$(_post "" "$DURL" "" "DELETE")" |
|||
|
|||
## check response (sort of) |
|||
if [ "$?" != "0" ]; then |
|||
_err "error in remove response: $response" |
|||
return 1 |
|||
fi |
|||
_debug2 response "$response" |
|||
|
|||
done |
|||
fi |
|||
fi |
|||
|
|||
## finished correctly |
|||
return 0 |
|||
} |
|||
|
|||
##################### Private functions below ##################### |
|||
|
|||
## Split the domain provided into the "base domain" and the "start prefix". |
|||
## This function searches for the longest subdomain in your account |
|||
## for the full domain given and splits it into the base domain (zone) |
|||
## and the prefix/record to be added/removed |
|||
## USAGE: fulldomain |
|||
## EG: "_acme-challenge.two.three.four.domain.com" |
|||
## returns |
|||
## _sub_domain="_acme-challenge.two" |
|||
## _domain="three.four.domain.com" *IF* zone "three.four.domain.com" exists |
|||
## _domain_id=234 |
|||
## if only "domain.com" exists it will return |
|||
## _sub_domain="_acme-challenge.two.three.four" |
|||
## _domain="domain.com" |
|||
## _domain_id=234 |
|||
_get_base_domain() { |
|||
# args |
|||
fulldomain="$(echo "$1" | _lower_case)" |
|||
_debug fulldomain "$fulldomain" |
|||
|
|||
# domain max legal length = 253 |
|||
MAX_DOM=255 |
|||
page=1 |
|||
|
|||
## get a list of domains for the account to check thru |
|||
## Set the headers |
|||
export _H1="Accept: application/json" |
|||
export _H2="AccessKey: $BUNNY_API_KEY" |
|||
_debug BUNNY_API_KEY "$BUNNY_API_KEY" |
|||
## get URL for the list of domains |
|||
## may get: "links":{"pages":{"last":".../v2/domains/DOM/records?page=2","next":".../v2/domains/DOM/records?page=2"}} |
|||
DOMURL="https://api.bunny.net/dnszone" |
|||
|
|||
## while we dont have a matching domain we keep going |
|||
while [ -z "$found" ]; do |
|||
## get the domain list (current page) |
|||
domain_list="$(_get "$DOMURL")" |
|||
|
|||
## check response |
|||
if [ "$?" != "0" ]; then |
|||
_err "error in domain_list response: $domain_list" |
|||
return 1 |
|||
fi |
|||
_debug2 domain_list "$domain_list" |
|||
|
|||
i=1 |
|||
while [ $i -gt 0 ]; do |
|||
## get next longest domain |
|||
_domain=$(printf "%s" "$fulldomain" | cut -d . -f "$i"-"$MAX_DOM") |
|||
## check we got something back from our cut (or are we at the end) |
|||
if [ -z "$_domain" ]; then |
|||
break |
|||
fi |
|||
## we got part of a domain back - grep it out |
|||
found="$(echo "$domain_list" | _egrep_o "\"Id\"\s*:\s*\"*[0-9]+\"*,\s*\"Domain\"\s*\:\s*\"$_domain\"")" |
|||
## check if it exists |
|||
if [ -n "$found" ]; then |
|||
## exists - exit loop returning the parts |
|||
sub_point=$(_math $i - 1) |
|||
_sub_domain=$(printf "%s" "$fulldomain" | cut -d . -f 1-"$sub_point") |
|||
_domain_id="$(echo "$found" | _egrep_o "Id\"\s*\:\s*\"*[0-9]+" | _egrep_o "[0-9]+")" |
|||
_debug _domain_id "$_domain_id" |
|||
_debug _domain "$_domain" |
|||
_debug _sub_domain "$_sub_domain" |
|||
found="" |
|||
return 0 |
|||
fi |
|||
## increment cut point $i |
|||
i=$(_math $i + 1) |
|||
done |
|||
|
|||
if [ -z "$found" ]; then |
|||
page=$(_math $page + 1) |
|||
nextpage="https://api.bunny.net/dnszone?page=$page" |
|||
## Find the next page if we don't have a match. |
|||
hasnextpage="$(echo "$domain_list" | _egrep_o "\"HasMoreItems\"\s*:\s*true")" |
|||
if [ -z "$hasnextpage" ]; then |
|||
_err "No record and no nextpage in Bunny.net domain search." |
|||
found="" |
|||
return 1 |
|||
fi |
|||
_debug2 nextpage "$nextpage" |
|||
DOMURL="$nextpage" |
|||
fi |
|||
|
|||
done |
|||
|
|||
## We went through the entire domain zone list and didn't find one that matched. |
|||
## If we ever get here, something is broken in the code... |
|||
_err "Domain not found in Bunny.net account, but we should never get here!" |
|||
found="" |
|||
return 1 |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue