Browse Source

Don't query CF for domains twice, do strict json parsing, report errors

pull/160/head
Tomasz Słodkowicz 9 years ago
parent
commit
f0d5f0362a
1 changed files with 31 additions and 31 deletions
  1. +31
    -31
      dns_scripts/dns_add_cloudflare

+ 31
- 31
dns_scripts/dns_add_cloudflare View File

@ -1,44 +1,44 @@
#!/usr/bin/env bash
# need to add your email address and API key to cloudflare below or set as env variables
email=${CF_EMAIL:-''}
key=${CF_KEY:-''}
# need to add your email address and key to cloudflare below
email=''
key=''
fulldomain="$1"
token="$2"
fulldomain="${1:?Need full domain name as first parameter}"
token="${2:?Need Let’s Encrypt challenge token as second parameter}"
API='https://api.cloudflare.com/client/v4/zones'
AUTH=( -H "X-Auth-Email: $email" -H "X-Auth-Key: $key" -H "Content-Type: application/json" )
PARAMS=( -H "X-Auth-Email: $email" -H "X-Auth-Key: $key" -H 'Content-Type: application/json' )
# get a list of all domain names from cloudflare
# If you have a lot, you may need add "&page=1&per_page=1000"
resp=$(curl --silent "${AUTH[@]}" -X GET "$API?match=all&status=active")
# If you have a lot, you may need add "&page=1&per_page=1000" and/or "&status=active"
resp=$(curl --silent "${PARAMS[@]}" -X GET "$API?match=all")
re='"result":\[(([^][]*\[[^][]*])+[^][]*)]' # find result section
[[ "${resp// }" =~ $re ]] && resp="${BASH_REMATCH[1]}"
while [[ "$resp" ]]; do # iterate through domains returned
re='[^}{]*\{(([^}{]*\{[^}{]*})+[^}{]*)}(.*)'
[[ "$resp" =~ $re ]]; first="${BASH_REMATCH[1]}"; resp="${BASH_REMATCH[3]}"
# treat all names with dot as domain names
while read -d ' ' i; do
[[ $i =~ \"name\":\"([^\"]+\.[^\"]+)\" ]] && all_domains="${all_domains:+$all_domains }${BASH_REMATCH[1]}"
done <<<${resp//[ ,\[\{\}\]]/ }
# remove subsections - leave only domain level
while [[ "$first" =~ (.*)[\[\{][^]\{\}[]*[\]\}](.*) ]]; do first="${BASH_REMATCH[1]}${BASH_REMATCH[2]}"; done
[ -z "$all_domains" ] && { echo 'no active domains found on your cloudflare account'; exit 1; }
re='"name":"([^"]*)"'; [[ "$first" =~ $re ]] && domains=( "${domains[@]}" "${BASH_REMATCH[1]}" )
re='"id":"([^"]*)"'; [[ "$first" =~ $re ]] && ids=( "${ids[@]}" "${BASH_REMATCH[1]}" )
done
# select right CF domain (longest one)
# select right cloudflare domain (longest one)
domain=$fulldomain.
while [[ "$domain" && ! "$all_domains" =~ "${domain%?}" ]]; do domain=${domain#*.}; done
# shellcheck disable=SC2076
while [[ "$domain" && ! "${domains[@]/#/@}" == *"@${domain%?}"* ]]; do domain=${domain#*.}; done
domain=${domain%?}
[ -z "$domain" ] && { echo 'domain name not found on your cloudflare account'; exit 1; }
resp=$(curl --silent "${AUTH[@]}" -X GET "$API?name=$domain&match=any&status=active")
# select result section
[[ "$resp" =~ \"result\"[^\{]*\{([^\{\}]*\{[^\{\}]*\}[^\{\}]*)+\} ]]
resp="${BASH_REMATCH[0]%\}*}"; resp="${resp#*\{}"
# remove subsections - leave only domain level
while [[ "$resp" =~ (.*)[\[\{][^]\{\}[]*[\]\}](.*) ]]; do resp="${BASH_REMATCH[1]}${BASH_REMATCH[2]}"; done
# must match - we ask for already verified domain
[[ "${resp// }" =~ \"id\":\"([^\"]+)\" ]]
domain_id=${BASH_REMATCH[1]}
for i in "${!domains[@]}"; do [[ ${domains[i]} == "$domain" ]] && break; done
domain_id=${ids[i]}
curl --silent "${AUTH[@]}" -X POST "$API/$domain_id/dns_records" \
--data "{\"type\":\"TXT\",\"name\":\"_acme-challenge.${fulldomain%.$domain}\",\"content\":\"$token\",\"ttl\":300}"
resp=$(curl --silent "${PARAMS[@]}" -X POST "$API/$domain_id/dns_records" \
--data "{\"type\":\"TXT\",\"name\":\"_acme-challenge.${fulldomain%.$domain}\",\"content\":\"$token\",\"ttl\":300}")
# code 81057 = The record already exists.
if [[ "${resp// }" == *'"success":false'* && ! "${resp// }" == *'"code":81057[^0-9]'* ]]; then
re='"message":"([^"]+)"'; [[ "$resp" =~ $re ]]
echo "Error: DNS challenge not added: ${BASH_REMATCH[1]:-unknown error}"; exit 2
fi

Loading…
Cancel
Save