Merge pull request #3478 from acmesh-official/dev

sync
This commit is contained in:
neil 2021-04-07 22:04:08 +08:00 committed by GitHub
commit edd46eb3d1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 317 additions and 66 deletions

View File

@ -184,7 +184,7 @@ jobs:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Clone acmetest - name: Clone acmetest
run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
- uses: vmactions/freebsd-vm@v0.1.2 - uses: vmactions/freebsd-vm@v0.1.3
with: with:
envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}' envs: 'TEST_DNS TestingDomain TEST_DNS_NO_WILDCARD TEST_DNS_SLEEP CASE TEST_LOCAL DEBUG ${{ secrets.TokenName1}} ${{ secrets.TokenName2}} ${{ secrets.TokenName3}} ${{ secrets.TokenName4}} ${{ secrets.TokenName5}}'
prepare: pkg install -y socat curl prepare: pkg install -y socat curl

View File

@ -111,7 +111,7 @@ jobs:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Clone acmetest - name: Clone acmetest
run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/ run: cd .. && git clone https://github.com/acmesh-official/acmetest.git && cp -r acme.sh acmetest/
- uses: vmactions/freebsd-vm@v0.1.2 - uses: vmactions/freebsd-vm@v0.1.3
with: with:
envs: 'NGROK_TOKEN TEST_LOCAL' envs: 'NGROK_TOKEN TEST_LOCAL'
prepare: pkg install -y socat curl prepare: pkg install -y socat curl

23
acme.sh
View File

@ -562,9 +562,17 @@ if _exists xargs && [ "$(printf %s '\\x41' | xargs printf)" = 'A' ]; then
fi fi
_h2b() { _h2b() {
if _exists xxd && xxd -r -p 2>/dev/null; then if _exists xxd; then
if _contains "$(xxd --help 2>&1)" "assumes -c30"; then
if xxd -r -p -c 9999 2>/dev/null; then
return return
fi fi
else
if xxd -r -p 2>/dev/null; then
return
fi
fi
fi
hex=$(cat) hex=$(cat)
ic="" ic=""
@ -1124,7 +1132,7 @@ _createkey() {
if _isEccKey "$length"; then if _isEccKey "$length"; then
_debug "Using ec name: $eccname" _debug "Using ec name: $eccname"
if _opkey="$(${ACME_OPENSSL_BIN:-openssl} ecparam -name "$eccname" -genkey 2>/dev/null)"; then if _opkey="$(${ACME_OPENSSL_BIN:-openssl} ecparam -name "$eccname" -noout -genkey 2>/dev/null)"; then
echo "$_opkey" >"$f" echo "$_opkey" >"$f"
else else
_err "error ecc key name: $eccname" _err "error ecc key name: $eccname"
@ -2125,6 +2133,12 @@ _send_signed_request() {
_sleep $_sleep_retry_sec _sleep $_sleep_retry_sec
continue continue
fi fi
if _contains "$_body" "The Replay Nonce is not recognized"; then
_info "The replay Nonce is not valid, let's get a new one, Sleeping $_sleep_retry_sec seconds."
_CACHED_NONCE=""
_sleep $_sleep_retry_sec
continue
fi
fi fi
return 0 return 0
done done
@ -5273,6 +5287,7 @@ signcsr() {
_renew_hook="${10}" _renew_hook="${10}"
_local_addr="${11}" _local_addr="${11}"
_challenge_alias="${12}" _challenge_alias="${12}"
_preferred_chain="${13}"
_csrsubj=$(_readSubjectFromCSR "$_csrfile") _csrsubj=$(_readSubjectFromCSR "$_csrfile")
if [ "$?" != "0" ]; then if [ "$?" != "0" ]; then
@ -5319,7 +5334,7 @@ signcsr() {
_info "Copy csr to: $CSR_PATH" _info "Copy csr to: $CSR_PATH"
cp "$_csrfile" "$CSR_PATH" cp "$_csrfile" "$CSR_PATH"
issue "$_csrW" "$_csrsubj" "$_csrdomainlist" "$_csrkeylength" "$_real_cert" "$_real_key" "$_real_ca" "$_reload_cmd" "$_real_fullchain" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_addr" "$_challenge_alias" issue "$_csrW" "$_csrsubj" "$_csrdomainlist" "$_csrkeylength" "$_real_cert" "$_real_key" "$_real_ca" "$_reload_cmd" "$_real_fullchain" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_addr" "$_challenge_alias" "$_preferred_chain"
} }
@ -7416,7 +7431,7 @@ _process() {
deploy "$_domain" "$_deploy_hook" "$_ecc" deploy "$_domain" "$_deploy_hook" "$_ecc"
;; ;;
signcsr) signcsr)
signcsr "$_csr" "$_webroot" "$_cert_file" "$_key_file" "$_ca_file" "$_reloadcmd" "$_fullchain_file" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_address" "$_challenge_alias" signcsr "$_csr" "$_webroot" "$_cert_file" "$_key_file" "$_ca_file" "$_reloadcmd" "$_fullchain_file" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_address" "$_challenge_alias" "$_preferred_chain"
;; ;;
showcsr) showcsr)
showcsr "$_csr" "$_domain" showcsr "$_csr" "$_domain"

View File

@ -17,6 +17,8 @@ cleverreach_deploy() {
_cca="$4" _cca="$4"
_cfullchain="$5" _cfullchain="$5"
_rest_endpoint="https://rest.cleverreach.com"
_debug _cdomain "$_cdomain" _debug _cdomain "$_cdomain"
_debug _ckey "$_ckey" _debug _ckey "$_ckey"
_debug _ccert "$_ccert" _debug _ccert "$_ccert"
@ -25,6 +27,7 @@ cleverreach_deploy() {
_getdeployconf DEPLOY_CLEVERREACH_CLIENT_ID _getdeployconf DEPLOY_CLEVERREACH_CLIENT_ID
_getdeployconf DEPLOY_CLEVERREACH_CLIENT_SECRET _getdeployconf DEPLOY_CLEVERREACH_CLIENT_SECRET
_getdeployconf DEPLOY_CLEVERREACH_SUBCLIENT_ID
if [ -z "${DEPLOY_CLEVERREACH_CLIENT_ID}" ]; then if [ -z "${DEPLOY_CLEVERREACH_CLIENT_ID}" ]; then
_err "CleverReach Client ID is not found, please define DEPLOY_CLEVERREACH_CLIENT_ID." _err "CleverReach Client ID is not found, please define DEPLOY_CLEVERREACH_CLIENT_ID."
@ -37,11 +40,12 @@ cleverreach_deploy() {
_savedeployconf DEPLOY_CLEVERREACH_CLIENT_ID "${DEPLOY_CLEVERREACH_CLIENT_ID}" _savedeployconf DEPLOY_CLEVERREACH_CLIENT_ID "${DEPLOY_CLEVERREACH_CLIENT_ID}"
_savedeployconf DEPLOY_CLEVERREACH_CLIENT_SECRET "${DEPLOY_CLEVERREACH_CLIENT_SECRET}" _savedeployconf DEPLOY_CLEVERREACH_CLIENT_SECRET "${DEPLOY_CLEVERREACH_CLIENT_SECRET}"
_savedeployconf DEPLOY_CLEVERREACH_SUBCLIENT_ID "${DEPLOY_CLEVERREACH_SUBCLIENT_ID}"
_info "Obtaining a CleverReach access token" _info "Obtaining a CleverReach access token"
_data="{\"grant_type\": \"client_credentials\", \"client_id\": \"${DEPLOY_CLEVERREACH_CLIENT_ID}\", \"client_secret\": \"${DEPLOY_CLEVERREACH_CLIENT_SECRET}\"}" _data="{\"grant_type\": \"client_credentials\", \"client_id\": \"${DEPLOY_CLEVERREACH_CLIENT_ID}\", \"client_secret\": \"${DEPLOY_CLEVERREACH_CLIENT_SECRET}\"}"
_auth_result="$(_post "$_data" "https://rest.cleverreach.com/oauth/token.php" "" "POST" "application/json")" _auth_result="$(_post "$_data" "$_rest_endpoint/oauth/token.php" "" "POST" "application/json")"
_debug _data "$_data" _debug _data "$_data"
_debug _auth_result "$_auth_result" _debug _auth_result "$_auth_result"
@ -50,14 +54,32 @@ cleverreach_deploy() {
_debug _regex "$_regex" _debug _regex "$_regex"
_access_token=$(echo "$_auth_result" | _json_decode | sed -n "s/$_regex/\1/p") _access_token=$(echo "$_auth_result" | _json_decode | sed -n "s/$_regex/\1/p")
_debug _subclient "${DEPLOY_CLEVERREACH_SUBCLIENT_ID}"
if [ -n "${DEPLOY_CLEVERREACH_SUBCLIENT_ID}" ]; then
_info "Obtaining token for sub-client ${DEPLOY_CLEVERREACH_SUBCLIENT_ID}"
export _H1="Authorization: Bearer ${_access_token}"
_subclient_token_result="$(_get "$_rest_endpoint/v3/clients/$DEPLOY_CLEVERREACH_SUBCLIENT_ID/token")"
_access_token=$(echo "$_subclient_token_result" | sed -n "s/\"//p")
_debug _subclient_token_result "$_access_token"
_info "Destroying parent token at CleverReach, as it not needed anymore"
_destroy_result="$(_post "" "$_rest_endpoint/v3/oauth/token.json" "" "DELETE" "application/json")"
_debug _destroy_result "$_destroy_result"
fi
_info "Uploading certificate and key to CleverReach" _info "Uploading certificate and key to CleverReach"
_certData="{\"cert\":\"$(_json_encode <"$_cfullchain")\", \"key\":\"$(_json_encode <"$_ckey")\"}" _certData="{\"cert\":\"$(_json_encode <"$_cfullchain")\", \"key\":\"$(_json_encode <"$_ckey")\"}"
export _H1="Authorization: Bearer ${_access_token}" export _H1="Authorization: Bearer ${_access_token}"
_add_cert_result="$(_post "$_certData" "https://rest.cleverreach.com/v3/ssl" "" "POST" "application/json")" _add_cert_result="$(_post "$_certData" "$_rest_endpoint/v3/ssl" "" "POST" "application/json")"
_debug "Destroying token at CleverReach" if [ -z "${DEPLOY_CLEVERREACH_SUBCLIENT_ID}" ]; then
_post "" "https://rest.cleverreach.com/v3/oauth/token.json" "" "DELETE" "application/json" _info "Destroying token at CleverReach, as it not needed anymore"
_destroy_result="$(_post "" "$_rest_endpoint/v3/oauth/token.json" "" "DELETE" "application/json")"
_debug _destroy_result "$_destroy_result"
fi
if ! echo "$_add_cert_result" | grep '"error":' >/dev/null; then if ! echo "$_add_cert_result" | grep '"error":' >/dev/null; then
_info "Uploaded certificate successfully" _info "Uploaded certificate successfully"

View File

@ -50,12 +50,12 @@ vault_cli_deploy() {
fi fi
if [ -n "$FABIO" ]; then if [ -n "$FABIO" ]; then
$VAULT_CMD write "${VAULT_PREFIX}/${_cdomain}" cert=@"$_cfullchain" key=@"$_ckey" || return 1 $VAULT_CMD kv put "${VAULT_PREFIX}/${_cdomain}" cert=@"$_cfullchain" key=@"$_ckey" || return 1
else else
$VAULT_CMD write "${VAULT_PREFIX}/${_cdomain}/cert.pem" value=@"$_ccert" || return 1 $VAULT_CMD kv put "${VAULT_PREFIX}/${_cdomain}/cert.pem" value=@"$_ccert" || return 1
$VAULT_CMD write "${VAULT_PREFIX}/${_cdomain}/cert.key" value=@"$_ckey" || return 1 $VAULT_CMD kv put "${VAULT_PREFIX}/${_cdomain}/cert.key" value=@"$_ckey" || return 1
$VAULT_CMD write "${VAULT_PREFIX}/${_cdomain}/chain.pem" value=@"$_cca" || return 1 $VAULT_CMD kv put "${VAULT_PREFIX}/${_cdomain}/chain.pem" value=@"$_cca" || return 1
$VAULT_CMD write "${VAULT_PREFIX}/${_cdomain}/fullchain.pem" value=@"$_cfullchain" || return 1 $VAULT_CMD kv put "${VAULT_PREFIX}/${_cdomain}/fullchain.pem" value=@"$_cfullchain" || return 1
fi fi
} }

View File

@ -30,16 +30,41 @@ dns_constellix_add() {
return 1 return 1
fi fi
# The TXT record might already exist when working with wildcard certificates. In that case, update the record by adding the new value.
_debug "Search TXT record"
if _constellix_rest GET "domains/${_domain_id}/records/TXT/search?exact=${_sub_domain}"; then
if printf -- "%s" "$response" | grep "{\"errors\":\[\"Requested record was not found\"\]}" >/dev/null; then
_info "Adding TXT record" _info "Adding TXT record"
if _constellix_rest POST "domains/${_domain_id}/records" "[{\"type\":\"txt\",\"add\":true,\"set\":{\"name\":\"${_sub_domain}\",\"ttl\":120,\"roundRobin\":[{\"value\":\"${txtvalue}\"}]}}]"; then if _constellix_rest POST "domains/${_domain_id}/records" "[{\"type\":\"txt\",\"add\":true,\"set\":{\"name\":\"${_sub_domain}\",\"ttl\":60,\"roundRobin\":[{\"value\":\"${txtvalue}\"}]}}]"; then
if printf -- "%s" "$response" | grep "{\"success\":\"1 record(s) added, 0 record(s) updated, 0 record(s) deleted\"}" >/dev/null; then if printf -- "%s" "$response" | grep "{\"success\":\"1 record(s) added, 0 record(s) updated, 0 record(s) deleted\"}" >/dev/null; then
_info "Added" _info "Added"
return 0 return 0
else else
_err "Error adding TXT record" _err "Error adding TXT record"
fi
fi
else
_record_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[0-9]*" | cut -d ':' -f 2)
if _constellix_rest GET "domains/${_domain_id}/records/TXT/${_record_id}"; then
_new_rr_values=$(printf "%s\n" "$response" | _egrep_o '"roundRobin":\[[^]]*\]' | sed "s/\]$/,{\"value\":\"${txtvalue}\"}]/")
_debug _new_rr_values "$_new_rr_values"
_info "Updating TXT record"
if _constellix_rest PUT "domains/${_domain_id}/records/TXT/${_record_id}" "{\"name\":\"${_sub_domain}\",\"ttl\":60,${_new_rr_values}}"; then
if printf -- "%s" "$response" | grep "{\"success\":\"Record.*updated successfully\"}" >/dev/null; then
_info "Updated"
return 0
elif printf -- "%s" "$response" | grep "{\"errors\":\[\"Contents are identical\"\]}" >/dev/null; then
_info "Already exists, no need to update"
return 0
else
_err "Error updating TXT record"
fi
fi
fi
fi
fi
return 1 return 1
fi
fi
} }
# Usage: fulldomain txtvalue # Usage: fulldomain txtvalue
@ -61,6 +86,13 @@ dns_constellix_rm() {
return 1 return 1
fi fi
# The TXT record might have been removed already when working with some wildcard certificates.
_debug "Search TXT record"
if _constellix_rest GET "domains/${_domain_id}/records/TXT/search?exact=${_sub_domain}"; then
if printf -- "%s" "$response" | grep "{\"errors\":\[\"Requested record was not found\"\]}" >/dev/null; then
_info "Removed"
return 0
else
_info "Removing TXT record" _info "Removing TXT record"
if _constellix_rest POST "domains/${_domain_id}/records" "[{\"type\":\"txt\",\"delete\":true,\"filter\":{\"field\":\"name\",\"op\":\"eq\",\"value\":\"${_sub_domain}\"}}]"; then if _constellix_rest POST "domains/${_domain_id}/records" "[{\"type\":\"txt\",\"delete\":true,\"filter\":{\"field\":\"name\",\"op\":\"eq\",\"value\":\"${_sub_domain}\"}}]"; then
if printf -- "%s" "$response" | grep "{\"success\":\"0 record(s) added, 0 record(s) updated, 1 record(s) deleted\"}" >/dev/null; then if printf -- "%s" "$response" | grep "{\"success\":\"0 record(s) added, 0 record(s) updated, 1 record(s) deleted\"}" >/dev/null; then
@ -68,9 +100,12 @@ dns_constellix_rm() {
return 0 return 0
else else
_err "Error removing TXT record" _err "Error removing TXT record"
fi
fi
fi
fi
return 1 return 1
fi
fi
} }
#################### Private functions below ################################## #################### Private functions below ##################################
@ -91,7 +126,7 @@ _get_root() {
fi fi
if _contains "$response" "\"name\":\"$h\""; then if _contains "$response" "\"name\":\"$h\""; then
_domain_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[0-9]+" | cut -d ':' -f 2) _domain_id=$(printf "%s\n" "$response" | _egrep_o "\"id\":[0-9]*" | cut -d ':' -f 2)
if [ "$_domain_id" ]; then if [ "$_domain_id" ]; then
_sub_domain=$(printf "%s" "$domain" | cut -d '.' -f 1-$p) _sub_domain=$(printf "%s" "$domain" | cut -d '.' -f 1-$p)
_domain="$h" _domain="$h"

View File

@ -89,7 +89,7 @@ add_record() {
_info "Adding record" _info "Adding record"
if ! _rest POST "Record.Create" "login_token=$DP_Id,$DP_Key&format=json&lang=en&domain_id=$_domain_id&sub_domain=$_sub_domain&record_type=TXT&value=$txtvalue&record_line=默认"; then if ! _rest POST "Record.Create" "login_token=$DP_Id,$DP_Key&format=json&lang=en&domain_id=$_domain_id&sub_domain=$_sub_domain&record_type=TXT&value=$txtvalue&record_line=%E9%BB%98%E8%AE%A4"; then
return 1 return 1
fi fi

View File

@ -24,20 +24,9 @@ dns_ionos_add() {
return 1 return 1
fi fi
_new_record="{\"name\":\"$_sub_domain.$_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"ttl\":$IONOS_TXT_TTL,\"prio\":$IONOS_TXT_PRIO,\"disabled\":false}" _body="[{\"name\":\"$_sub_domain.$_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"ttl\":$IONOS_TXT_TTL,\"prio\":$IONOS_TXT_PRIO,\"disabled\":false}]"
# As no POST route is supported by the API, check for existing records and include them in the PATCH request in order not delete them. if _ionos_rest POST "$IONOS_ROUTE_ZONES/$_zone_id/records" "$_body" && [ -z "$response" ]; then
# This is required to support ACME v2 wildcard certificate creation, where two TXT records for the same domain name are created.
_ionos_get_existing_records "$fulldomain" "$_zone_id"
if [ "$_existing_records" ]; then
_body="[$_new_record,$_existing_records]"
else
_body="[$_new_record]"
fi
if _ionos_rest PATCH "$IONOS_ROUTE_ZONES/$_zone_id" "$_body" && [ -z "$response" ]; then
_info "TXT record has been created successfully." _info "TXT record has been created successfully."
return 0 return 0
fi fi
@ -125,17 +114,6 @@ _get_root() {
return 1 return 1
} }
_ionos_get_existing_records() {
fulldomain=$1
zone_id=$2
if _ionos_rest GET "$IONOS_ROUTE_ZONES/$zone_id?recordName=$fulldomain&recordType=TXT"; then
response="$(echo "$response" | tr -d "\n")"
_existing_records="$(printf "%s\n" "$response" | _egrep_o "\"records\":\[.*\]" | _head_n 1 | cut -d '[' -f 2 | sed 's/]//')"
fi
}
_ionos_get_record() { _ionos_get_record() {
fulldomain=$1 fulldomain=$1
zone_id=$2 zone_id=$2
@ -168,7 +146,7 @@ _ionos_rest() {
export _H2="Accept: application/json" export _H2="Accept: application/json"
export _H3="Content-Type: application/json" export _H3="Content-Type: application/json"
response="$(_post "$data" "$IONOS_API$route" "" "$method")" response="$(_post "$data" "$IONOS_API$route" "" "$method" "application/json")"
else else
export _H2="Accept: */*" export _H2="Accept: */*"

View File

@ -208,7 +208,7 @@ _namecheap_parse_host() {
_hostid=$(echo "$_host" | _egrep_o ' HostId="[^"]*' | cut -d '"' -f 2) _hostid=$(echo "$_host" | _egrep_o ' HostId="[^"]*' | cut -d '"' -f 2)
_hostname=$(echo "$_host" | _egrep_o ' Name="[^"]*' | cut -d '"' -f 2) _hostname=$(echo "$_host" | _egrep_o ' Name="[^"]*' | cut -d '"' -f 2)
_hosttype=$(echo "$_host" | _egrep_o ' Type="[^"]*' | cut -d '"' -f 2) _hosttype=$(echo "$_host" | _egrep_o ' Type="[^"]*' | cut -d '"' -f 2)
_hostaddress=$(echo "$_host" | _egrep_o ' Address="[^"]*' | cut -d '"' -f 2) _hostaddress=$(echo "$_host" | _egrep_o ' Address="[^"]*' | cut -d '"' -f 2 | _xml_decode)
_hostmxpref=$(echo "$_host" | _egrep_o ' MXPref="[^"]*' | cut -d '"' -f 2) _hostmxpref=$(echo "$_host" | _egrep_o ' MXPref="[^"]*' | cut -d '"' -f 2)
_hostttl=$(echo "$_host" | _egrep_o ' TTL="[^"]*' | cut -d '"' -f 2) _hostttl=$(echo "$_host" | _egrep_o ' TTL="[^"]*' | cut -d '"' -f 2)
@ -405,3 +405,7 @@ _namecheap_set_tld_sld() {
done done
} }
_xml_decode() {
sed 's/&quot;/"/g'
}

157
dnsapi/dns_porkbun.sh Normal file
View File

@ -0,0 +1,157 @@
#!/usr/bin/env sh
#
#PORKBUN_API_KEY="pk1_0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
#PORKBUN_SECRET_API_KEY="sk1_0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef"
PORKBUN_Api="https://porkbun.com/api/json/v3"
######## Public functions #####################
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_porkbun_add() {
fulldomain=$1
txtvalue=$2
PORKBUN_API_KEY="${PORKBUN_API_KEY:-$(_readaccountconf_mutable PORKBUN_API_KEY)}"
PORKBUN_SECRET_API_KEY="${PORKBUN_SECRET_API_KEY:-$(_readaccountconf_mutable PORKBUN_SECRET_API_KEY)}"
if [ -z "$PORKBUN_API_KEY" ] || [ -z "$PORKBUN_SECRET_API_KEY" ]; then
PORKBUN_API_KEY=''
PORKBUN_SECRET_API_KEY=''
_err "You didn't specify a Porkbun api key and secret api key yet."
_err "You can get yours from here https://porkbun.com/account/api."
return 1
fi
#save the credentials to the account conf file.
_saveaccountconf_mutable PORKBUN_API_KEY "$PORKBUN_API_KEY"
_saveaccountconf_mutable PORKBUN_SECRET_API_KEY "$PORKBUN_SECRET_API_KEY"
_debug 'First detect the root zone'
if ! _get_root "$fulldomain"; then
return 1
fi
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
# For wildcard cert, the main root domain and the wildcard domain have the same txt subdomain name, so
# we can not use updating anymore.
# count=$(printf "%s\n" "$response" | _egrep_o "\"count\":[^,]*" | cut -d : -f 2)
# _debug count "$count"
# if [ "$count" = "0" ]; then
_info "Adding record"
if _porkbun_rest POST "dns/create/$_domain" "{\"name\":\"$_sub_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"ttl\":120}"; then
if _contains "$response" '\"status\":"SUCCESS"'; then
_info "Added, OK"
return 0
elif _contains "$response" "The record already exists"; then
_info "Already exists, OK"
return 0
else
_err "Add txt record error. ($response)"
return 1
fi
fi
_err "Add txt record error."
return 1
}
#fulldomain txtvalue
dns_porkbun_rm() {
fulldomain=$1
txtvalue=$2
PORKBUN_API_KEY="${PORKBUN_API_KEY:-$(_readaccountconf_mutable PORKBUN_API_KEY)}"
PORKBUN_SECRET_API_KEY="${PORKBUN_SECRET_API_KEY:-$(_readaccountconf_mutable PORKBUN_SECRET_API_KEY)}"
_debug 'First detect the root zone'
if ! _get_root "$fulldomain"; then
return 1
fi
_debug _sub_domain "$_sub_domain"
_debug _domain "$_domain"
count=$(echo "$response" | _egrep_o "\"count\": *[^,]*" | cut -d : -f 2 | tr -d " ")
_debug count "$count"
if [ "$count" = "0" ]; then
_info "Don't need to remove."
else
record_id=$(echo "$response" | tr '{' '\n' | grep "$txtvalue" | cut -d, -f1 | cut -d: -f2 | tr -d \")
_debug "record_id" "$record_id"
if [ -z "$record_id" ]; then
_err "Can not get record id to remove."
return 1
fi
if ! _porkbun_rest POST "dns/delete/$_domain/$record_id"; then
_err "Delete record error."
return 1
fi
echo "$response" | tr -d " " | grep '\"status\":"SUCCESS"' >/dev/null
fi
}
#################### Private functions below ##################################
#_acme-challenge.www.domain.com
#returns
# _sub_domain=_acme-challenge.www
# _domain=domain.com
_get_root() {
domain=$1
i=1
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
_debug h "$h"
if [ -z "$h" ]; then
return 1
fi
if _porkbun_rest POST "dns/retrieve/$h"; then
if _contains "$response" "\"status\":\"SUCCESS\""; then
_sub_domain="$(echo "$fulldomain" | sed "s/\\.$_domain\$//")"
_domain=$h
return 0
else
_debug "Go to next level of $_domain"
fi
else
_debug "Go to next level of $_domain"
fi
i=$(_math "$i" + 1)
done
return 1
}
_porkbun_rest() {
m=$1
ep="$2"
data="$3"
_debug "$ep"
api_key_trimmed=$(echo "$PORKBUN_API_KEY" | tr -d '"')
secret_api_key_trimmed=$(echo "$PORKBUN_SECRET_API_KEY" | tr -d '"')
test -z "$data" && data="{" || data="$(echo $data | cut -d'}' -f1),"
data="$data\"apikey\":\"$api_key_trimmed\",\"secretapikey\":\"$secret_api_key_trimmed\"}"
export _H1="Content-Type: application/json"
if [ "$m" != "GET" ]; then
_debug data "$data"
response="$(_post "$data" "$PORKBUN_Api/$ep" "" "$m")"
else
response="$(_get "$PORKBUN_Api/$ep")"
fi
_sleep 3 # prevent rate limit
if [ "$?" != "0" ]; then
_err "error $ep"
return 1
fi
_debug2 response "$response"
return 0
}

View File

@ -49,6 +49,30 @@ dns_servercow_add() {
_debug _sub_domain "$_sub_domain" _debug _sub_domain "$_sub_domain"
_debug _domain "$_domain" _debug _domain "$_domain"
# check whether a txt record already exists for the subdomain
if printf -- "%s" "$response" | grep "{\"name\":\"$_sub_domain\",\"ttl\":20,\"type\":\"TXT\"" >/dev/null; then
_info "A txt record with the same name already exists."
# trim the string on the left
txtvalue_old=${response#*{\"name\":\"$_sub_domain\",\"ttl\":20,\"type\":\"TXT\",\"content\":\"}
# trim the string on the right
txtvalue_old=${txtvalue_old%%\"*}
_debug txtvalue_old "$txtvalue_old"
_info "Add the new txtvalue to the existing txt record."
if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":[\"$txtvalue\",\"$txtvalue_old\"],\"ttl\":20}"; then
if printf -- "%s" "$response" | grep "ok" >/dev/null; then
_info "Added additional txtvalue, OK"
return 0
else
_err "add txt record error."
return 1
fi
fi
_err "add txt record error."
return 1
else
_info "There is no txt record with the name yet."
if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":\"$txtvalue\",\"ttl\":20}"; then if _servercow_api POST "$_domain" "{\"type\":\"TXT\",\"name\":\"$fulldomain\",\"content\":\"$txtvalue\",\"ttl\":20}"; then
if printf -- "%s" "$response" | grep "ok" >/dev/null; then if printf -- "%s" "$response" | grep "ok" >/dev/null; then
_info "Added, OK" _info "Added, OK"
@ -59,6 +83,8 @@ dns_servercow_add() {
fi fi
fi fi
_err "add txt record error." _err "add txt record error."
return 1
fi
return 1 return 1
} }

View File

@ -6,9 +6,11 @@
#SIMPLY_ApiKey="apikey" #SIMPLY_ApiKey="apikey"
# #
#SIMPLY_Api="https://api.simply.com/1/[ACCOUNTNAME]/[APIKEY]" #SIMPLY_Api="https://api.simply.com/1/[ACCOUNTNAME]/[APIKEY]"
SIMPLY_Api_Default="https://api.simply.com/1" SIMPLY_Api_Default="https://api.simply.com/1"
#This is used for determining success of REST call
SIMPLY_SUCCESS_CODE='"status": 200'
######## Public functions ##################### ######## Public functions #####################
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" #Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_simply_add() { dns_simply_add() {
@ -171,7 +173,7 @@ _get_root() {
return 1 return 1
fi fi
if _contains "$response" '"code":"NOT_FOUND"'; then if ! _contains "$response" "$SIMPLY_SUCCESS_CODE"; then
_debug "$h not found" _debug "$h not found"
else else
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
@ -196,6 +198,12 @@ _simply_add_record() {
return 1 return 1
fi fi
if ! _contains "$response" "$SIMPLY_SUCCESS_CODE"; then
_err "Call to API not sucessfull, see below message for more details"
_err "$response"
return 1
fi
return 0 return 0
} }
@ -211,6 +219,12 @@ _simply_delete_record() {
return 1 return 1
fi fi
if ! _contains "$response" "$SIMPLY_SUCCESS_CODE"; then
_err "Call to API not sucessfull, see below message for more details"
_err "$response"
return 1
fi
return 0 return 0
} }