Compare commits

...
98 Commits
16 changed files with 468 additions and 129 deletions
+21 -30
View File
@@ -37,6 +37,8 @@ Twitter: [@neilpangxa](https://twitter.com/neilpangxa)
- [splynx](https://forum.splynx.com/t/free-ssl-cert-for-splynx-lets-encrypt/297) - [splynx](https://forum.splynx.com/t/free-ssl-cert-for-splynx-lets-encrypt/297)
- [archlinux](https://aur.archlinux.org/packages/acme.sh-git/) - [archlinux](https://aur.archlinux.org/packages/acme.sh-git/)
- [opnsense.org](https://github.com/opnsense/plugins/tree/master/security/acme-client/src/opnsense/scripts/OPNsense/AcmeClient) - [opnsense.org](https://github.com/opnsense/plugins/tree/master/security/acme-client/src/opnsense/scripts/OPNsense/AcmeClient)
- [CentOS Web Panel](http://centos-webpanel.com/)
- [lnmp.org](https://lnmp.org/)
- [more...](https://github.com/Neilpang/acme.sh/wiki/Blogs-and-tutorials) - [more...](https://github.com/Neilpang/acme.sh/wiki/Blogs-and-tutorials)
# Tested OS # Tested OS
@@ -220,22 +222,7 @@ acme.sh --issue --standalone -d example.com -d www.example.com -d cp.example.com
More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert
# 5. Use Standalone TLS server to issue cert # 5. Use Apache mode
**(requires you to be root/sudoer or have permission to listen on port 443 (TCP))**
acme.sh supports `tls-sni-01` validation.
Port `443` (TCP) **MUST** be free to listen on, otherwise you will be prompted to free it and try again.
```bash
acme.sh --issue --tls -d example.com -d www.example.com -d cp.example.com
```
More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert
# 6. Use Apache mode
**(requires you to be root/sudoer, since it is required to interact with Apache server)** **(requires you to be root/sudoer, since it is required to interact with Apache server)**
@@ -255,7 +242,7 @@ We don't want to mess your apache server, don't worry.**
More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert
# 7. Use Nginx mode # 6. Use Nginx mode
**(requires you to be root/sudoer, since it is required to interact with Nginx server)** **(requires you to be root/sudoer, since it is required to interact with Nginx server)**
@@ -279,7 +266,7 @@ We don't want to mess your nginx server, don't worry.**
More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert More examples: https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert
# 8. Automatic DNS API integration # 7. Automatic DNS API integration
If your DNS provider supports API access, we can use that API to automatically issue the certs. If your DNS provider supports API access, we can use that API to automatically issue the certs.
@@ -328,6 +315,8 @@ You don't have to do anything manually!
1. zonomi.com DNS API 1. zonomi.com DNS API
1. DreamHost.com API 1. DreamHost.com API
1. DirectAdmin API 1. DirectAdmin API
1. KingHost (https://www.kinghost.com.br/)
1. Zilore (https://zilore.com)
And: And:
@@ -342,7 +331,9 @@ If your DNS provider is not on the supported list above, you can write your own
For more details: [How to use DNS API](dnsapi) For more details: [How to use DNS API](dnsapi)
# 9. Use DNS manual mode: # 8. Use DNS manual mode:
See: https://github.com/Neilpang/acme.sh/wiki/dns-manual-mode first.
If your dns provider doesn't support any api access, you can add the txt record by your hand. If your dns provider doesn't support any api access, you can add the txt record by your hand.
@@ -376,7 +367,7 @@ Ok, it's done.
**Please use dns api mode instead.** **Please use dns api mode instead.**
# 10. Issue ECC certificates # 9. Issue ECC certificates
`Let's Encrypt` can now issue **ECDSA** certificates. `Let's Encrypt` can now issue **ECDSA** certificates.
@@ -408,17 +399,17 @@ Valid values are:
# 11. Issue Wildcard certificates # 10. Issue Wildcard certificates
It's simple, just give a wildcard domain as the `-d` parameter. It's simple, just give a wildcard domain as the `-d` parameter.
```sh ```sh
acme.sh --issue -d example.com -d *.example.com --dns dns_cf acme.sh --issue -d example.com -d '*.example.com' --dns dns_cf
``` ```
# 12. How to renew the certs # 11. How to renew the certs
No, you don't need to renew the certs manually. All the certs will be renewed automatically every **60** days. No, you don't need to renew the certs manually. All the certs will be renewed automatically every **60** days.
@@ -435,7 +426,7 @@ acme.sh --renew -d example.com --force --ecc
``` ```
# 13. How to stop cert renewal # 12. How to stop cert renewal
To stop renewal of a cert, you can execute the following to remove the cert from the renewal list: To stop renewal of a cert, you can execute the following to remove the cert from the renewal list:
@@ -448,7 +439,7 @@ The cert/key file is not removed from the disk.
You can remove the respective directory (e.g. `~/.acme.sh/example.com`) by yourself. You can remove the respective directory (e.g. `~/.acme.sh/example.com`) by yourself.
# 14. How to upgrade `acme.sh` # 13. How to upgrade `acme.sh`
acme.sh is in constant development, so it's strongly recommended to use the latest code. acme.sh is in constant development, so it's strongly recommended to use the latest code.
@@ -473,25 +464,25 @@ acme.sh --upgrade --auto-upgrade 0
``` ```
# 15. Issue a cert from an existing CSR # 14. Issue a cert from an existing CSR
https://github.com/Neilpang/acme.sh/wiki/Issue-a-cert-from-existing-CSR https://github.com/Neilpang/acme.sh/wiki/Issue-a-cert-from-existing-CSR
# 16. Under the Hood # 15. Under the Hood
Speak ACME language using shell, directly to "Let's Encrypt". Speak ACME language using shell, directly to "Let's Encrypt".
TODO: TODO:
# 17. Acknowledgments # 16. Acknowledgments
1. Acme-tiny: https://github.com/diafygi/acme-tiny 1. Acme-tiny: https://github.com/diafygi/acme-tiny
2. ACME protocol: https://github.com/ietf-wg-acme/acme 2. ACME protocol: https://github.com/ietf-wg-acme/acme
# 18. License & Others # 17. License & Others
License is GPLv3 License is GPLv3
@@ -500,7 +491,7 @@ Please Star and Fork me.
[Issues](https://github.com/Neilpang/acme.sh/issues) and [pull requests](https://github.com/Neilpang/acme.sh/pulls) are welcome. [Issues](https://github.com/Neilpang/acme.sh/issues) and [pull requests](https://github.com/Neilpang/acme.sh/pulls) are welcome.
# 19. Donate # 18. Donate
Your donation makes **acme.sh** better: Your donation makes **acme.sh** better:
1. PayPal/Alipay(支付宝)/Wechat(微信): [https://donate.acme.sh/](https://donate.acme.sh/) 1. PayPal/Alipay(支付宝)/Wechat(微信): [https://donate.acme.sh/](https://donate.acme.sh/)
+100 -32
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env sh #!/usr/bin/env sh
VER=2.7.7 VER=2.7.8
PROJECT_NAME="acme.sh" PROJECT_NAME="acme.sh"
@@ -47,6 +47,7 @@ DEFAULT_DNS_SLEEP=120
NO_VALUE="no" NO_VALUE="no"
W_TLS="tls" W_TLS="tls"
W_DNS="dns"
DNS_ALIAS_PREFIX="=" DNS_ALIAS_PREFIX="="
MODE_STATELESS="stateless" MODE_STATELESS="stateless"
@@ -109,10 +110,14 @@ _STATELESS_WIKI="https://github.com/Neilpang/acme.sh/wiki/Stateless-Mode"
_DNS_ALIAS_WIKI="https://github.com/Neilpang/acme.sh/wiki/DNS-alias-mode" _DNS_ALIAS_WIKI="https://github.com/Neilpang/acme.sh/wiki/DNS-alias-mode"
_DNS_MANUAL_WIKI="https://github.com/Neilpang/acme.sh/wiki/dns-manual-mode"
_DNS_MANUAL_ERR="The dns manual mode can not renew automatically, you must issue it again manually. You'd better use the other modes instead." _DNS_MANUAL_ERR="The dns manual mode can not renew automatically, you must issue it again manually. You'd better use the other modes instead."
_DNS_MANUAL_WARN="It seems that you are using dns manual mode. please take care: $_DNS_MANUAL_ERR" _DNS_MANUAL_WARN="It seems that you are using dns manual mode. please take care: $_DNS_MANUAL_ERR"
_DNS_MANUAL_ERROR="It seems that you are using dns manual mode. Read this link first: $_DNS_MANUAL_WIKI"
__INTERACTIVE="" __INTERACTIVE=""
if [ -t 1 ]; then if [ -t 1 ]; then
__INTERACTIVE="1" __INTERACTIVE="1"
@@ -1616,6 +1621,7 @@ _post() {
_debug $httpmethod _debug $httpmethod
_debug "_post_url" "$_post_url" _debug "_post_url" "$_post_url"
_debug2 "body" "$body" _debug2 "body" "$body"
_debug2 "_postContentType" "$_postContentType"
_inithttp _inithttp
@@ -1624,14 +1630,19 @@ _post() {
if [ "$HTTPS_INSECURE" ]; then if [ "$HTTPS_INSECURE" ]; then
_CURL="$_CURL --insecure " _CURL="$_CURL --insecure "
fi fi
if [ "$_postContentType" ]; then
_CURL="$_CURL -H \"Content-Type: $_postContentType\" "
fi
_debug "_CURL" "$_CURL" _debug "_CURL" "$_CURL"
if [ "$needbase64" ]; then if [ "$needbase64" ]; then
response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url" | _base64)" if [ "$_postContentType" ]; then
response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "Content-Type: $_postContentType" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url" | _base64)"
else
response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url" | _base64)"
fi
else else
response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url")" if [ "$_postContentType" ]; then
response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "Content-Type: $_postContentType" -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url")"
else
response="$($_CURL --user-agent "$USER_AGENT" -X $httpmethod -H "$_H1" -H "$_H2" -H "$_H3" -H "$_H4" -H "$_H5" --data "$body" "$_post_url")"
fi
fi fi
_ret="$?" _ret="$?"
if [ "$_ret" != "0" ]; then if [ "$_ret" != "0" ]; then
@@ -1784,19 +1795,25 @@ _send_signed_request() {
return 1 return 1
fi fi
if [ "$ACME_VERSION" = "2" ]; then
__request_conent_type="$CONTENT_TYPE_JSON"
else
__request_conent_type=""
fi
payload64=$(printf "%s" "$payload" | _base64 | _url_replace) payload64=$(printf "%s" "$payload" | _base64 | _url_replace)
_debug3 payload64 "$payload64" _debug3 payload64 "$payload64"
MAX_REQUEST_RETRY_TIMES=5 MAX_REQUEST_RETRY_TIMES=5
_request_retry_times=0 _request_retry_times=0
while [ "${_request_retry_times}" -lt "$MAX_REQUEST_RETRY_TIMES" ]; do while [ "${_request_retry_times}" -lt "$MAX_REQUEST_RETRY_TIMES" ]; do
_request_retry_times=$(_math "$_request_retry_times" + 1)
_debug3 _request_retry_times "$_request_retry_times" _debug3 _request_retry_times "$_request_retry_times"
if [ -z "$_CACHED_NONCE" ]; then if [ -z "$_CACHED_NONCE" ]; then
_headers="" _headers=""
if [ "$ACME_NEW_NONCE" ]; then if [ "$ACME_NEW_NONCE" ]; then
_debug2 "Get nonce. ACME_NEW_NONCE" "$ACME_NEW_NONCE" _debug2 "Get nonce. ACME_NEW_NONCE" "$ACME_NEW_NONCE"
nonceurl="$ACME_NEW_NONCE" nonceurl="$ACME_NEW_NONCE"
if _post "" "$nonceurl" "" "HEAD" "$CONTENT_TYPE_JSON"; then if _post "" "$nonceurl" "" "HEAD" "$__request_conent_type"; then
_headers="$(cat "$HTTP_HEADER")" _headers="$(cat "$HTTP_HEADER")"
fi fi
fi fi
@@ -1820,7 +1837,11 @@ _send_signed_request() {
fi fi
nonce="$_CACHED_NONCE" nonce="$_CACHED_NONCE"
_debug2 nonce "$nonce" _debug2 nonce "$nonce"
if [ -z "$nonce" ]; then
_info "Could not get nonce, let's try again."
_sleep 2
continue
fi
if [ "$ACME_VERSION" = "2" ]; then if [ "$ACME_VERSION" = "2" ]; then
if [ "$url" = "$ACME_NEW_ACCOUNT" ] || [ "$url" = "$ACME_REVOKE_CERT" ]; then if [ "$url" = "$ACME_NEW_ACCOUNT" ] || [ "$url" = "$ACME_REVOKE_CERT" ]; then
protected="$JWK_HEADERPLACE_PART1$nonce\", \"url\": \"${url}$JWK_HEADERPLACE_PART2, \"jwk\": $jwk"'}' protected="$JWK_HEADERPLACE_PART1$nonce\", \"url\": \"${url}$JWK_HEADERPLACE_PART2, \"jwk\": $jwk"'}'
@@ -1851,7 +1872,7 @@ _send_signed_request() {
fi fi
_debug3 body "$body" _debug3 body "$body"
response="$(_post "$body" "$url" "$needbase64" "POST" "$CONTENT_TYPE_JSON")" response="$(_post "$body" "$url" "$needbase64" "POST" "$__request_conent_type")"
_CACHED_NONCE="" _CACHED_NONCE=""
if [ "$?" != "0" ]; then if [ "$?" != "0" ]; then
@@ -1878,7 +1899,6 @@ _send_signed_request() {
if _contains "$_body" "JWS has invalid anti-replay nonce"; then if _contains "$_body" "JWS has invalid anti-replay nonce"; then
_info "It seems the CA server is busy now, let's wait and retry." _info "It seems the CA server is busy now, let's wait and retry."
_request_retry_times=$(_math "$_request_retry_times" + 1)
_sleep 5 _sleep 5
continue continue
fi fi
@@ -2341,7 +2361,7 @@ _initpath() {
fi fi
fi fi
_debug2 ACME_DIRECTORY "$ACME_DIRECTORY" _debug ACME_DIRECTORY "$ACME_DIRECTORY"
_ACME_SERVER_HOST="$(echo "$ACME_DIRECTORY" | cut -d : -f 2 | tr -s / | cut -d / -f 2)" _ACME_SERVER_HOST="$(echo "$ACME_DIRECTORY" | cut -d : -f 2 | tr -s / | cut -d / -f 2)"
_debug2 "_ACME_SERVER_HOST" "$_ACME_SERVER_HOST" _debug2 "_ACME_SERVER_HOST" "$_ACME_SERVER_HOST"
@@ -2998,6 +3018,8 @@ _on_before_issue() {
_chk_pre_hook="$4" _chk_pre_hook="$4"
_chk_local_addr="$5" _chk_local_addr="$5"
_debug _on_before_issue _debug _on_before_issue
_debug _chk_main_domain "$_chk_main_domain"
_debug _chk_alt_domains "$_chk_alt_domains"
#run pre hook #run pre hook
if [ "$_chk_pre_hook" ]; then if [ "$_chk_pre_hook" ]; then
_info "Run pre hook:'$_chk_pre_hook'" _info "Run pre hook:'$_chk_pre_hook'"
@@ -3018,11 +3040,17 @@ _on_before_issue() {
_debug Le_LocalAddress "$_chk_local_addr" _debug Le_LocalAddress "$_chk_local_addr"
alldomains=$(echo "$_chk_main_domain,$_chk_alt_domains" | tr ',' ' ')
_index=1 _index=1
_currentRoot="" _currentRoot=""
_addrIndex=1 _addrIndex=1
for d in $alldomains; do _w_index=1
while true; do
d="$(echo "$_chk_main_domain,$_chk_alt_domains," | cut -d , -f "$_w_index")"
_w_index="$(_math "$_w_index" + 1)"
_debug d "$d"
if [ -z "$d" ]; then
break
fi
_debug "Check for domain" "$d" _debug "Check for domain" "$d"
_currentRoot="$(_getfield "$_chk_web_roots" $_index)" _currentRoot="$(_getfield "$_chk_web_roots" $_index)"
_debug "_currentRoot" "$_currentRoot" _debug "_currentRoot" "$_currentRoot"
@@ -3118,7 +3146,7 @@ _on_issue_err() {
) )
fi fi
if [ "$IS_RENEW" = "1" ] && _hasfield "$Le_Webroot" "dns"; then if [ "$IS_RENEW" = "1" ] && _hasfield "$Le_Webroot" "$W_DNS"; then
_err "$_DNS_MANUAL_ERR" _err "$_DNS_MANUAL_ERR"
fi fi
@@ -3154,7 +3182,7 @@ _on_issue_success() {
fi fi
fi fi
if _hasfield "$Le_Webroot" "dns"; then if _hasfield "$Le_Webroot" "$W_DNS"; then
_err "$_DNS_MANUAL_WARN" _err "$_DNS_MANUAL_WARN"
fi fi
@@ -3238,10 +3266,16 @@ _regAccount() {
return 1 return 1
fi fi
_debug2 responseHeaders "$responseHeaders"
_accUri="$(echo "$responseHeaders" | grep "^Location:" | _head_n 1 | cut -d ' ' -f 2 | tr -d "\r\n")" _accUri="$(echo "$responseHeaders" | grep "^Location:" | _head_n 1 | cut -d ' ' -f 2 | tr -d "\r\n")"
_debug "_accUri" "$_accUri" _debug "_accUri" "$_accUri"
if [ -z "$_accUri" ]; then
_err "Can not find account id url."
_err "$responseHeaders"
return 1
fi
_savecaconf "ACCOUNT_URL" "$_accUri" _savecaconf "ACCOUNT_URL" "$_accUri"
export ACCOUNT_URL="$ACCOUNT_URL" export ACCOUNT_URL="$_accUri"
CA_KEY_HASH="$(__calcAccountKeyHash)" CA_KEY_HASH="$(__calcAccountKeyHash)"
_debug "Calc CA_KEY_HASH" "$CA_KEY_HASH" _debug "Calc CA_KEY_HASH" "$CA_KEY_HASH"
@@ -3421,6 +3455,9 @@ issue() {
_main_domain=$(echo "$2,$3" | cut -d , -f 1) _main_domain=$(echo "$2,$3" | cut -d , -f 1)
_alt_domains=$(echo "$2,$3" | cut -d , -f 2- | sed "s/,${NO_VALUE}$//") _alt_domains=$(echo "$2,$3" | cut -d , -f 2- | sed "s/,${NO_VALUE}$//")
fi fi
_debug _main_domain "$_main_domain"
_debug _alt_domains "$_alt_domains"
_key_length="$4" _key_length="$4"
_real_cert="$5" _real_cert="$5"
_real_key="$6" _real_key="$6"
@@ -3448,6 +3485,11 @@ issue() {
mkdir -p "$DOMAIN_PATH" mkdir -p "$DOMAIN_PATH"
fi fi
if _hasfield "$_web_roots" "$W_DNS" && [ -z "$FORCE_DNS_MANUAL" ]; then
_err "$_DNS_MANUAL_ERROR"
return 1
fi
_debug "Using ACME_DIRECTORY: $ACME_DIRECTORY" _debug "Using ACME_DIRECTORY: $ACME_DIRECTORY"
_initAPI _initAPI
@@ -3509,7 +3551,7 @@ issue() {
_saved_account_key_hash="$(_readcaconf "CA_KEY_HASH")" _saved_account_key_hash="$(_readcaconf "CA_KEY_HASH")"
_debug2 _saved_account_key_hash "$_saved_account_key_hash" _debug2 _saved_account_key_hash "$_saved_account_key_hash"
if [ -z "$_saved_account_key_hash" ] || [ "$_saved_account_key_hash" != "$(__calcAccountKeyHash)" ]; then if [ -z "$ACCOUNT_URL" ] || [ -z "$_saved_account_key_hash" ] || [ "$_saved_account_key_hash" != "$(__calcAccountKeyHash)" ]; then
if ! _regAccount "$_accountkeylength"; then if ! _regAccount "$_accountkeylength"; then
_on_issue_err "$_post_hook" _on_issue_err "$_post_hook"
return 1 return 1
@@ -3551,10 +3593,15 @@ issue() {
if [ "$ACME_VERSION" = "2" ]; then if [ "$ACME_VERSION" = "2" ]; then
#make new order request #make new order request
_identifiers="{\"type\":\"dns\",\"value\":\"$_main_domain\"}" _identifiers="{\"type\":\"dns\",\"value\":\"$_main_domain\"}"
for d in $(echo "$_alt_domains" | tr ',' ' '); do _w_index=1
if [ "$d" ]; then while true; do
_identifiers="$_identifiers,{\"type\":\"dns\",\"value\":\"$d\"}" d="$(echo "$_alt_domains," | cut -d , -f "$_w_index")"
_w_index="$(_math "$_w_index" + 1)"
_debug d "$d"
if [ -z "$d" ]; then
break
fi fi
_identifiers="$_identifiers,{\"type\":\"dns\",\"value\":\"$d\"}"
done done
_debug2 _identifiers "$_identifiers" _debug2 _identifiers "$_identifiers"
if ! _send_signed_request "$ACME_NEW_ORDER" "{\"identifiers\": [$_identifiers]}"; then if ! _send_signed_request "$ACME_NEW_ORDER" "{\"identifiers\": [$_identifiers]}"; then
@@ -3591,6 +3638,8 @@ issue() {
_debug2 "_authz_url" "$_authz_url" _debug2 "_authz_url" "$_authz_url"
if ! response="$(_get "$_authz_url")"; then if ! response="$(_get "$_authz_url")"; then
_err "get to authz error." _err "get to authz error."
_err "_authorizations_seg" "$_authorizations_seg"
_err "_authz_url" "$_authz_url"
_clearup _clearup
_on_issue_err "$_post_hook" _on_issue_err "$_post_hook"
return 1 return 1
@@ -3609,10 +3658,16 @@ $_authorizations_map"
_debug2 _authorizations_map "$_authorizations_map" _debug2 _authorizations_map "$_authorizations_map"
fi fi
alldomains=$(echo "$_main_domain,$_alt_domains" | tr ',' ' ')
_index=0 _index=0
_currentRoot="" _currentRoot=""
for d in $alldomains; do _w_index=1
while true; do
d="$(echo "$_main_domain,$_alt_domains," | cut -d , -f "$_w_index")"
_w_index="$(_math "$_w_index" + 1)"
_debug d "$d"
if [ -z "$d" ]; then
break
fi
_info "Getting webroot for domain" "$d" _info "Getting webroot for domain" "$d"
_index=$(_math $_index + 1) _index=$(_math $_index + 1)
_w="$(echo $_web_roots | cut -d , -f $_index)" _w="$(echo $_web_roots | cut -d , -f $_index)"
@@ -3624,7 +3679,7 @@ $_authorizations_map"
vtype="$VTYPE_HTTP" vtype="$VTYPE_HTTP"
#todo, v2 wildcard force to use dns #todo, v2 wildcard force to use dns
if _startswith "$_currentRoot" "dns"; then if _startswith "$_currentRoot" "$W_DNS"; then
vtype="$VTYPE_DNS" vtype="$VTYPE_DNS"
fi fi
@@ -3641,6 +3696,7 @@ $_authorizations_map"
_debug2 "response" "$response" _debug2 "response" "$response"
if [ -z "$response" ]; then if [ -z "$response" ]; then
_err "get to authz error." _err "get to authz error."
_err "_authorizations_map" "$_authorizations_map"
_clearup _clearup
_on_issue_err "$_post_hook" _on_issue_err "$_post_hook"
return 1 return 1
@@ -3751,6 +3807,10 @@ $_authorizations_map"
if [ "$d_api" ]; then if [ "$d_api" ]; then
_info "Found domain api file: $d_api" _info "Found domain api file: $d_api"
else else
if [ "$_currentRoot" != "$W_DNS" ]; then
_err "Can not find dns api hook for: $_currentRoot"
_info "You need to add the txt record manually."
fi
_info "$(__red "Add the following TXT record:")" _info "$(__red "Add the following TXT record:")"
_info "$(__red "Domain: '$(__green "$txtdomain")'")" _info "$(__red "Domain: '$(__green "$txtdomain")'")"
_info "$(__red "TXT value: '$(__green "$txt")'")" _info "$(__red "TXT value: '$(__green "$txt")'")"
@@ -3789,7 +3849,7 @@ $_authorizations_map"
if [ "$dnsadded" = '0' ]; then if [ "$dnsadded" = '0' ]; then
_savedomainconf "Le_Vlist" "$vlist" _savedomainconf "Le_Vlist" "$vlist"
_debug "Dns record not added yet, so, save to $DOMAIN_CONF and exit." _debug "Dns record not added yet, so, save to $DOMAIN_CONF and exit."
_err "Please add the TXT records to the domains, and retry again." _err "Please add the TXT records to the domains, and re-run with --renew."
_clearup _clearup
_on_issue_err "$_post_hook" _on_issue_err "$_post_hook"
return 1 return 1
@@ -4053,13 +4113,15 @@ $_authorizations_map"
fi fi
if [ "$code" != "200" ]; then if [ "$code" != "200" ]; then
_err "Sign failed, code is not 200." _err "Sign failed, code is not 200."
_err "$response"
_on_issue_err "$_post_hook" _on_issue_err "$_post_hook"
return 1 return 1
fi fi
Le_LinkCert="$(echo "$response" | tr -d '\r\n' | _egrep_o '"certificate" *: *"[^"]*"' | cut -d '"' -f 4)" Le_LinkCert="$(echo "$response" | tr -d '\r\n' | _egrep_o '"certificate" *: *"[^"]*"' | cut -d '"' -f 4)"
if ! _get "$Le_LinkCert" >"$CERT_PATH"; then if ! _get "$Le_LinkCert" >"$CERT_PATH"; then
_err "Sign failed, code is not 200." _err "Sign failed, can not download cert:$Le_LinkCert."
_err "$response"
_on_issue_err "$_post_hook" _on_issue_err "$_post_hook"
return 1 return 1
fi fi
@@ -4075,12 +4137,12 @@ $_authorizations_map"
fi fi
else else
if ! _send_signed_request "${ACME_NEW_ORDER}" "{\"resource\": \"$ACME_NEW_ORDER_RES\", \"csr\": \"$der\"}" "needbase64"; then if ! _send_signed_request "${ACME_NEW_ORDER}" "{\"resource\": \"$ACME_NEW_ORDER_RES\", \"csr\": \"$der\"}" "needbase64"; then
_err "Sign failed." _err "Sign failed. $response"
_on_issue_err "$_post_hook" _on_issue_err "$_post_hook"
return 1 return 1
fi fi
_rcert="$response" _rcert="$response"
Le_LinkCert="$(grep -i '^Location.*$' "$HTTP_HEADER" | _head_n 1 | tr -d "\r\n" | cut -d " " -f 2)" Le_LinkCert="$(grep -i '^Location.*$' "$HTTP_HEADER" | _tail_n 1 | tr -d "\r\n" | cut -d " " -f 2)"
echo "$BEGIN_CERT" >"$CERT_PATH" echo "$BEGIN_CERT" >"$CERT_PATH"
#if ! _get "$Le_LinkCert" | _base64 "multiline" >> "$CERT_PATH" ; then #if ! _get "$Le_LinkCert" | _base64 "multiline" >> "$CERT_PATH" ; then
@@ -4151,7 +4213,7 @@ $_authorizations_map"
echo "$BEGIN_CERT" >"$CA_CERT_PATH" echo "$BEGIN_CERT" >"$CA_CERT_PATH"
_base64 "multiline" <"$CA_CERT_PATH.der" >>"$CA_CERT_PATH" _base64 "multiline" <"$CA_CERT_PATH.der" >>"$CA_CERT_PATH"
echo "$END_CERT" >>"$CA_CERT_PATH" echo "$END_CERT" >>"$CA_CERT_PATH"
if !_checkcert "$CA_CERT_PATH"; then if ! _checkcert "$CA_CERT_PATH"; then
_err "Can not get the ca cert." _err "Can not get the ca cert."
break break
fi fi
@@ -4264,7 +4326,7 @@ renew() {
fi fi
. "$DOMAIN_CONF" . "$DOMAIN_CONF"
_debug Le_API "$Le_API"
if [ "$Le_API" ]; then if [ "$Le_API" ]; then
if [ "$_OLD_CA_HOST" = "$Le_API" ]; then if [ "$_OLD_CA_HOST" = "$Le_API" ]; then
export Le_API="$DEFAULT_CA" export Le_API="$DEFAULT_CA"
@@ -4868,6 +4930,8 @@ _deactivate() {
_debug2 "authzUri" "$authzUri" _debug2 "authzUri" "$authzUri"
if ! response="$(_get "$authzUri")"; then if ! response="$(_get "$authzUri")"; then
_err "get to authz error." _err "get to authz error."
_err "_authorizations_seg" "$_authorizations_seg"
_err "authzUri" "$authzUri"
_clearup _clearup
_on_issue_err "$_post_hook" _on_issue_err "$_post_hook"
return 1 return 1
@@ -5424,8 +5488,8 @@ Parameters:
--cert-home Specifies the home dir to save all the certs, only valid for '--install' command. --cert-home Specifies the home dir to save all the certs, only valid for '--install' command.
--config-home Specifies the home dir to save all the configurations. --config-home Specifies the home dir to save all the configurations.
--useragent Specifies the user agent string. it will be saved for future use too. --useragent Specifies the user agent string. it will be saved for future use too.
--accountemail Specifies the account email for registering, Only valid for the '--install' command. --accountemail Specifies the account email, only valid for the '--install' and '--update-account' command.
--accountkey Specifies the account key path, Only valid for the '--install' command. --accountkey Specifies the account key path, only valid for the '--install' command.
--days Specifies the days to renew the cert when using '--issue' command. The max value is $MAX_RENEW days. --days Specifies the days to renew the cert when using '--issue' command. The max value is $MAX_RENEW days.
--httpport Specifies the standalone listening port. Only valid if the server is behind a reverse proxy or load balancer. --httpport Specifies the standalone listening port. Only valid if the server is behind a reverse proxy or load balancer.
--local-address Specifies the standalone/tls server listening address, in case you have multiple ip addresses. --local-address Specifies the standalone/tls server listening address, in case you have multiple ip addresses.
@@ -5449,6 +5513,7 @@ Parameters:
--listen-v6 Force standalone/tls server to listen at ipv6. --listen-v6 Force standalone/tls server to listen at ipv6.
--openssl-bin Specifies a custom openssl bin location. --openssl-bin Specifies a custom openssl bin location.
--use-wget Force to use wget, if you have both curl and wget installed. --use-wget Force to use wget, if you have both curl and wget installed.
--yes-I-know-dns-manual-mode-enough-go-ahead-please Force to use dns manual mode: $_DNS_MANUAL_WIKI
" "
} }
@@ -5779,7 +5844,7 @@ _process() {
fi fi
;; ;;
--dns) --dns)
wvalue="dns" wvalue="$W_DNS"
if [ "$2" ] && ! _startswith "$2" "-"; then if [ "$2" ] && ! _startswith "$2" "-"; then
wvalue="$2" wvalue="$2"
shift shift
@@ -5937,6 +6002,9 @@ _process() {
shift shift
fi fi
;; ;;
--yes-I-know-dns-manual-mode-enough-go-ahead-please)
export FORCE_DNS_MANUAL=1
;;
--log | --logfile) --log | --logfile)
_log="1" _log="1"
_logfile="$2" _logfile="$2"
-6
View File
@@ -1,11 +1,5 @@
#!/usr/bin/env sh #!/usr/bin/env sh
#Here is a sample custom api script.
#This file name is "myapi.sh"
#So, here must be a method myapi_deploy()
#Which will be called by acme.sh to deploy the cert
#returns 0 means success, otherwise error.
######## Public functions ##################### ######## Public functions #####################
#domain keyfile certfile cafile fullchain #domain keyfile certfile cafile fullchain
+1
View File
@@ -51,6 +51,7 @@ vault_cli_deploy() {
$VAULT_CMD write "${VAULT_PREFIX}/${_cdomain}/cert.pem" value=@"$_ccert" || return 1 $VAULT_CMD write "${VAULT_PREFIX}/${_cdomain}/cert.pem" value=@"$_ccert" || return 1
$VAULT_CMD write "${VAULT_PREFIX}/${_cdomain}/cert.key" value=@"$_ckey" || return 1 $VAULT_CMD write "${VAULT_PREFIX}/${_cdomain}/cert.key" value=@"$_ckey" || return 1
$VAULT_CMD write "${VAULT_PREFIX}/${_cdomain}/chain.pem" value=@"$_cca" || return 1
$VAULT_CMD write "${VAULT_PREFIX}/${_cdomain}/fullchain.pem" value=@"$_cfullchain" || return 1 $VAULT_CMD write "${VAULT_PREFIX}/${_cdomain}/fullchain.pem" value=@"$_cfullchain" || return 1
} }
+31 -2
View File
@@ -325,6 +325,8 @@ The `CY_Username`, `CY_Password` and `CY_OTP_Secret` will be saved in `~/.acme.s
## 17. Use Domain-Offensive/Resellerinterface/Domainrobot API ## 17. Use Domain-Offensive/Resellerinterface/Domainrobot API
ATTENTION: You need to be a registered Reseller to be able to use the ResellerInterface. As a normal user you can not use this method.
You will need your login credentials (Partner ID+Password) to the Resellerinterface, and export them before you run `acme.sh`: You will need your login credentials (Partner ID+Password) to the Resellerinterface, and export them before you run `acme.sh`:
``` ```
export DO_PID="KD-1234567" export DO_PID="KD-1234567"
@@ -525,8 +527,9 @@ For issues, please report to https://github.com/raidenii/acme.sh/issues.
## 28. Use Name.com API ## 28. Use Name.com API
You'll need to fill out the form at https://www.name.com/reseller/apply to apply Create your API token here: https://www.name.com/account/settings/api
for API username and token.
Note: `Namecom_Username` should be your Name.com username and not the token name. If you accidentally run the script with the token name as the username see `~/.acme.sh/account.conf` to fix the issue
``` ```
export Namecom_Username="testuser" export Namecom_Username="testuser"
@@ -784,6 +787,32 @@ acme.sh --issue --dns dns_da -d example.com -d www.example.com
The `DA_Api` and `DA_Api_Insecure` will be saved in `~/.acme.sh/account.conf` and will be reused when needed. The `DA_Api` and `DA_Api_Insecure` will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
## 42. Use KingHost DNS API
API access must be enabled at https://painel.kinghost.com.br/painel.api.php
```
export KINGHOST_Username="yourusername"
export KINGHOST_Password="yourpassword"
acme.sh --issue --dns dns_kinghost -d example.com -d *.example.com
```
The `KINGHOST_username` and `KINGHOST_Password` will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
## 43. Use Zilore DNS API
First, get your API key at https://my.zilore.com/account/api
```
export Zilore_Key="5dcad3a2-36cb-50e8-cb92-000002f9"
```
Ok, let's issue a cert now:
```
acme.sh --issue --dns dns_zilore -d example.com -d *.example.com
```
The `Zilore_Key` will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
# Use custom API # Use custom API
+6 -2
View File
@@ -99,6 +99,7 @@ dns_azure_add() {
_azure_rest PUT "$acmeRecordURI" "$body" "$accesstoken" _azure_rest PUT "$acmeRecordURI" "$body" "$accesstoken"
if [ "$_code" = "200" ] || [ "$_code" = '201' ]; then if [ "$_code" = "200" ] || [ "$_code" = '201' ]; then
_info "validation value added" _info "validation value added"
return 0
else else
_err "error adding validation value ($_code)" _err "error adding validation value ($_code)"
return 1 return 1
@@ -194,6 +195,7 @@ dns_azure_rm() {
_azure_rest PUT "$acmeRecordURI" "$body" "$accesstoken" _azure_rest PUT "$acmeRecordURI" "$body" "$accesstoken"
if [ "$_code" = "200" ] || [ "$_code" = '201' ]; then if [ "$_code" = "200" ] || [ "$_code" = '201' ]; then
_info "validation value removed" _info "validation value removed"
return 0
else else
_err "error removing validation value ($_code)" _err "error removing validation value ($_code)"
return 1 return 1
@@ -226,6 +228,7 @@ _azure_rest() {
else else
response="$(_get "$ep")" response="$(_get "$ep")"
fi fi
_ret="$?"
_secure_debug2 "response $response" _secure_debug2 "response $response"
_code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\r\n")" _code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\r\n")"
_debug "http response code $_code" _debug "http response code $_code"
@@ -236,7 +239,7 @@ _azure_rest() {
return 1 return 1
fi fi
# See https://docs.microsoft.com/en-us/azure/architecture/best-practices/retry-service-specific#general-rest-and-retry-guidelines for retryable HTTP codes # See https://docs.microsoft.com/en-us/azure/architecture/best-practices/retry-service-specific#general-rest-and-retry-guidelines for retryable HTTP codes
if [ "$?" != "0" ] || [ -z "$_code" ] || [ "$_code" = "408" ] || [ "$_code" = "500" ] || [ "$_code" = "503" ] || [ "$_code" = "504" ]; then if [ "$_ret" != "0" ] || [ -z "$_code" ] || [ "$_code" = "408" ] || [ "$_code" = "500" ] || [ "$_code" = "503" ] || [ "$_code" = "504" ]; then
_request_retry_times="$(_math "$_request_retry_times" + 1)" _request_retry_times="$(_math "$_request_retry_times" + 1)"
_info "REST call error $_code retrying $ep in $_request_retry_times s" _info "REST call error $_code retrying $ep in $_request_retry_times s"
_sleep "$_request_retry_times" _sleep "$_request_retry_times"
@@ -281,6 +284,7 @@ _azure_getaccess_token() {
body="resource=$(printf "%s" 'https://management.core.windows.net/' | _url_encode)&client_id=$(printf "%s" "$clientID" | _url_encode)&client_secret=$(printf "%s" "$clientSecret" | _url_encode)&grant_type=client_credentials" body="resource=$(printf "%s" 'https://management.core.windows.net/' | _url_encode)&client_id=$(printf "%s" "$clientID" | _url_encode)&client_secret=$(printf "%s" "$clientSecret" | _url_encode)&grant_type=client_credentials"
_secure_debug2 "data $body" _secure_debug2 "data $body"
response="$(_post "$body" "https://login.microsoftonline.com/$tenantID/oauth2/token" "" "POST")" response="$(_post "$body" "https://login.microsoftonline.com/$tenantID/oauth2/token" "" "POST")"
_ret="$?"
_secure_debug2 "response $response" _secure_debug2 "response $response"
response="$(echo "$response" | _normalizeJson)" response="$(echo "$response" | _normalizeJson)"
accesstoken=$(echo "$response" | _egrep_o "\"access_token\":\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \") accesstoken=$(echo "$response" | _egrep_o "\"access_token\":\"[^\"]*\"" | _head_n 1 | cut -d : -f 2 | tr -d \")
@@ -290,7 +294,7 @@ _azure_getaccess_token() {
_err "no acccess token received. Check your Azure settings see $WIKI" _err "no acccess token received. Check your Azure settings see $WIKI"
return 1 return 1
fi fi
if [ "$?" != "0" ]; then if [ "$_ret" != "0" ]; then
_err "error $response" _err "error $response"
return 1 return 1
fi fi
+4 -4
View File
@@ -19,8 +19,8 @@ dns_cf_add() {
if [ -z "$CF_Key" ] || [ -z "$CF_Email" ]; then if [ -z "$CF_Key" ] || [ -z "$CF_Email" ]; then
CF_Key="" CF_Key=""
CF_Email="" CF_Email=""
_err "You don't specify cloudflare api key and email yet." _err "You didn't specify a cloudflare api key and email yet."
_err "Please create you key and try again." _err "Please create the key and try again."
return 1 return 1
fi fi
@@ -94,8 +94,8 @@ dns_cf_rm() {
if [ -z "$CF_Key" ] || [ -z "$CF_Email" ]; then if [ -z "$CF_Key" ] || [ -z "$CF_Email" ]; then
CF_Key="" CF_Key=""
CF_Email="" CF_Email=""
_err "You don't specify cloudflare api key and email yet." _err "You didn't specify a cloudflare api key and email yet."
_err "Please create you key and try again." _err "Please create the key and try again."
return 1 return 1
fi fi
+25 -5
View File
@@ -20,12 +20,22 @@
dns_dgon_add() { dns_dgon_add() {
fulldomain="$(echo "$1" | _lower_case)" fulldomain="$(echo "$1" | _lower_case)"
txtvalue=$2 txtvalue=$2
DO_API_KEY="${DO_API_KEY:-$(_readaccountconf_mutable DO_API_KEY)}"
# Check if API Key Exist
if [ -z "$DO_API_KEY" ]; then
DO_API_KEY=""
_err "You did not specify DigitalOcean API key."
_err "Please export DO_API_KEY and try again."
return 1
fi
_info "Using digitalocean dns validation - add record" _info "Using digitalocean dns validation - add record"
_debug fulldomain "$fulldomain" _debug fulldomain "$fulldomain"
_debug txtvalue "$txtvalue" _debug txtvalue "$txtvalue"
## save the env vars (key and domain split location) for later automated use ## save the env vars (key and domain split location) for later automated use
_saveaccountconf DO_API_KEY "$DO_API_KEY" _saveaccountconf_mutable DO_API_KEY "$DO_API_KEY"
## split the domain for DO API ## split the domain for DO API
if ! _get_base_domain "$fulldomain"; then if ! _get_base_domain "$fulldomain"; then
@@ -39,7 +49,7 @@ dns_dgon_add() {
export _H1="Content-Type: application/json" export _H1="Content-Type: application/json"
export _H2="Authorization: Bearer $DO_API_KEY" export _H2="Authorization: Bearer $DO_API_KEY"
PURL='https://api.digitalocean.com/v2/domains/'$_domain'/records' PURL='https://api.digitalocean.com/v2/domains/'$_domain'/records'
PBODY='{"type":"TXT","name":"'$_sub_domain'","data":"'$txtvalue'"}' PBODY='{"type":"TXT","name":"'$_sub_domain'","data":"'$txtvalue'","ttl":120}'
_debug PURL "$PURL" _debug PURL "$PURL"
_debug PBODY "$PBODY" _debug PBODY "$PBODY"
@@ -65,6 +75,16 @@ dns_dgon_add() {
dns_dgon_rm() { dns_dgon_rm() {
fulldomain="$(echo "$1" | _lower_case)" fulldomain="$(echo "$1" | _lower_case)"
txtvalue=$2 txtvalue=$2
DO_API_KEY="${DO_API_KEY:-$(_readaccountconf_mutable DO_API_KEY)}"
# Check if API Key Exist
if [ -z "$DO_API_KEY" ]; then
DO_API_KEY=""
_err "You did not specify DigitalOcean API key."
_err "Please export DO_API_KEY and try again."
return 1
fi
_info "Using digitalocean dns validation - remove record" _info "Using digitalocean dns validation - remove record"
_debug fulldomain "$fulldomain" _debug fulldomain "$fulldomain"
_debug txtvalue "$txtvalue" _debug txtvalue "$txtvalue"
@@ -92,11 +112,11 @@ dns_dgon_rm() {
domain_list="$(_get "$GURL")" domain_list="$(_get "$GURL")"
## 2) find record ## 2) find record
## check for what we are looing for: "type":"A","name":"$_sub_domain" ## check for what we are looing for: "type":"A","name":"$_sub_domain"
record="$(echo "$domain_list" | _egrep_o "\"id\"\s*\:\s*\"*\d+\"*[^}]*\"name\"\s*\:\s*\"$_sub_domain\"[^}]*\"data\"\s*\:\s*\"$txtvalue\"")" record="$(echo "$domain_list" | _egrep_o "\"id\"\s*\:\s*\"*[0-9]+\"*[^}]*\"name\"\s*\:\s*\"$_sub_domain\"[^}]*\"data\"\s*\:\s*\"$txtvalue\"")"
## 3) check record and get next page ## 3) check record and get next page
if [ -z "$record" ]; then if [ -z "$record" ]; then
## find the next page if we dont have a match ## find the next page if we dont have a match
nextpage="$(echo "$domain_list" | _egrep_o "\"links\".*" | _egrep_o "\"next\".*" | _egrep_o "http.*page\=\d+")" nextpage="$(echo "$domain_list" | _egrep_o "\"links\".*" | _egrep_o "\"next\".*" | _egrep_o "http.*page\=[0-9]+")"
if [ -z "$nextpage" ]; then if [ -z "$nextpage" ]; then
_err "no record and no nextpage in digital ocean DNS removal" _err "no record and no nextpage in digital ocean DNS removal"
return 1 return 1
@@ -108,7 +128,7 @@ dns_dgon_rm() {
done done
## we found the record ## we found the record
rec_id="$(echo "$record" | _egrep_o "id\"\s*\:\s*\"*\d+" | _egrep_o "\d+")" rec_id="$(echo "$record" | _egrep_o "id\"\s*\:\s*\"*[0-9]+" | _egrep_o "[0-9]+")"
_debug rec_id "$rec_id" _debug rec_id "$rec_id"
## delete the record ## delete the record
+18 -35
View File
@@ -39,34 +39,17 @@ dns_dnsimple_add() {
_get_records "$_account_id" "$_domain" "$_sub_domain" _get_records "$_account_id" "$_domain" "$_sub_domain"
if [ "$_records_count" = "0" ]; then _info "Adding record"
_info "Adding record" if _dnsimple_rest POST "$_account_id/zones/$_domain/records" "{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"content\":\"$txtvalue\",\"ttl\":120}"; then
if _dnsimple_rest POST "$_account_id/zones/$_domain/records" "{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"content\":\"$txtvalue\",\"ttl\":120}"; then if printf -- "%s" "$response" | grep "\"name\":\"$_sub_domain\"" >/dev/null; then
if printf -- "%s" "$response" | grep "\"name\":\"$_sub_domain\"" >/dev/null; then _info "Added"
_info "Added"
return 0
else
_err "Unexpected response while adding text record."
return 1
fi
fi
_err "Add txt record error."
else
_info "Updating record"
_extract_record_id "$_records" "$_sub_domain"
if _dnsimple_rest \
PATCH \
"$_account_id/zones/$_domain/records/$_record_id" \
"{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"content\":\"$txtvalue\",\"ttl\":120}"; then
_info "Updated!"
return 0 return 0
else
_err "Unexpected response while adding text record."
return 1
fi fi
_err "Update error"
return 1
fi fi
_err "Add txt record error."
} }
# fulldomain # fulldomain
@@ -84,19 +67,19 @@ dns_dnsimple_rm() {
fi fi
_get_records "$_account_id" "$_domain" "$_sub_domain" _get_records "$_account_id" "$_domain" "$_sub_domain"
_extract_record_id "$_records" "$_sub_domain" _extract_record_id "$_records" "$_sub_domain"
if [ "$_record_id" ]; then if [ "$_record_id" ]; then
echo "$_record_id" | while read -r item; do
if _dnsimple_rest DELETE "$_account_id/zones/$_domain/records/$_record_id"; then if _dnsimple_rest DELETE "$_account_id/zones/$_domain/records/$item"; then
_info "removed record" "$_record_id" _info "removed record" "$item"
return 0 return 0
fi else
_err "failed to remove record" "$item"
return 1
fi
done
fi fi
_err "failed to remove record" "$_record_id"
return 1
} }
#################### Private functions bellow ################################## #################### Private functions bellow ##################################
+1 -1
View File
@@ -279,7 +279,7 @@ _freedns_add_txt_record() {
domain_id="$2" domain_id="$2"
subdomain="$3" subdomain="$3"
value="$(printf '%s' "$4" | _url_encode)" value="$(printf '%s' "$4" | _url_encode)"
url="http://freedns.afraid.org/subdomain/save.php?step=2" url="https://freedns.afraid.org/subdomain/save.php?step=2"
htmlpage="$(_post "type=TXT&domain_id=$domain_id&subdomain=$subdomain&address=%22$value%22&send=Save%21" "$url")" htmlpage="$(_post "type=TXT&domain_id=$domain_id&subdomain=$subdomain&address=%22$value%22&send=Save%21" "$url")"
+1 -1
View File
@@ -143,7 +143,7 @@ _find_zone() {
_debug "Looking for zone \"${_attempted_zone}\"" _debug "Looking for zone \"${_attempted_zone}\""
line_num="$(echo "$_zone_names" | grep -n "$_attempted_zone" | cut -d : -f 1)" line_num="$(echo "$_zone_names" | grep -n "^$_attempted_zone" | cut -d : -f 1)"
if [ "$line_num" ]; then if [ "$line_num" ]; then
_zone_id=$(echo "$_zone_ids" | sed -n "${line_num}p") _zone_id=$(echo "$_zone_ids" | sed -n "${line_num}p")
+107
View File
@@ -0,0 +1,107 @@
#!/usr/bin/env sh
############################################################
# KingHost API support #
# http://api.kinghost.net/doc/ #
# #
# Author: Felipe Keller Braz <felipebraz@kinghost.com.br> #
# Report Bugs here: https://github.com/kinghost/acme.sh #
# #
# Values to export: #
# export KINGHOST_Username="email@provider.com" #
# export KINGHOST_Password="xxxxxxxxxx" #
############################################################
KING_Api="https://api.kinghost.net/acme"
# Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
# Used to add txt record
dns_kinghost_add() {
fulldomain=$1
txtvalue=$2
KINGHOST_Username="${KINGHOST_Username:-$(_readaccountconf_mutable KINGHOST_Username)}"
KINGHOST_Password="${KINGHOST_Password:-$(_readaccountconf_mutable KINGHOST_Password)}"
if [ -z "$KINGHOST_Username" ] || [ -z "$KINGHOST_Password" ]; then
KINGHOST_Username=""
KINGHOST_Password=""
_err "You don't specify KingHost api password and email yet."
_err "Please create you key and try again."
return 1
fi
#save the credentials to the account conf file.
_saveaccountconf_mutable KINGHOST_Username "$KINGHOST_Username"
_saveaccountconf_mutable KINGHOST_Password "$KINGHOST_Password"
_debug "Getting txt records"
_kinghost_rest GET "dns" "name=$fulldomain&content=$txtvalue"
#This API call returns "status":"ok" if dns record does not exists
#We are creating a new txt record here, so we expect the "ok" status
if ! echo "$response" | grep '"status":"ok"' >/dev/null; then
_err "Error"
_err "$response"
return 1
fi
_kinghost_rest POST "dns" "name=$fulldomain&content=$txtvalue"
if ! echo "$response" | grep '"status":"ok"' >/dev/null; then
_err "Error"
_err "$response"
return 1
fi
return 0
}
# Usage: fulldomain txtvalue
# Used to remove the txt record after validation
dns_kinghost_rm() {
fulldomain=$1
txtvalue=$2
KINGHOST_Password="${KINGHOST_Password:-$(_readaccountconf_mutable KINGHOST_Password)}"
KINGHOST_Username="${KINGHOST_Username:-$(_readaccountconf_mutable KINGHOST_Username)}"
if [ -z "$KINGHOST_Password" ] || [ -z "$KINGHOST_Username" ]; then
KINGHOST_Password=""
KINGHOST_Username=""
_err "You don't specify KingHost api key and email yet."
_err "Please create you key and try again."
return 1
fi
_kinghost_rest DELETE "dns" "name=$fulldomain&content=$txtvalue"
if ! echo "$response" | grep '"status":"ok"' >/dev/null; then
_err "Error"
_err "$response"
return 1
fi
return 0
}
#################### Private functions below ##################################
_kinghost_rest() {
method=$1
uri="$2"
data="$3"
_debug "$uri"
export _H1="X-Auth-Email: $KINGHOST_Username"
export _H2="X-Auth-Key: $KINGHOST_Password"
if [ "$method" != "GET" ]; then
_debug data "$data"
response="$(_post "$data" "$KING_Api/$uri.json" "" "$method")"
else
response="$(_get "$KING_Api/$uri.json?$data")"
fi
if [ "$?" != "0" ]; then
_err "error $uri"
return 1
fi
_debug2 response "$response"
return 0
}
+1 -1
View File
@@ -123,7 +123,7 @@ _namecom_login() {
# Auth string # Auth string
# Name.com API v4 uses http basic auth to authenticate # Name.com API v4 uses http basic auth to authenticate
# need to convert the token for http auth # need to convert the token for http auth
_namecom_auth=$(printf "%s:%s" "$Namecom_Username" "$Namecom_Token" | base64) _namecom_auth=$(printf "%s:%s" "$Namecom_Username" "$Namecom_Token" | _base64)
if _namecom_rest GET "hello"; then if _namecom_rest GET "hello"; then
retcode=$(printf "%s\n" "$response" | _egrep_o "\"username\"\:\"$Namecom_Username\"") retcode=$(printf "%s\n" "$response" | _egrep_o "\"username\"\:\"$Namecom_Username\"")
+10 -7
View File
@@ -90,7 +90,7 @@ set_record() {
full=$2 full=$2
txtvalue=$3 txtvalue=$3
if ! _pdns_rest "PATCH" "/api/v1/servers/$PDNS_ServerId/zones/$root." "{\"rrsets\": [{\"changetype\": \"REPLACE\", \"name\": \"$full.\", \"type\": \"TXT\", \"ttl\": $PDNS_Ttl, \"records\": [{\"name\": \"$full.\", \"type\": \"TXT\", \"content\": \"\\\"$txtvalue\\\"\", \"disabled\": false, \"ttl\": $PDNS_Ttl}]}]}"; then if ! _pdns_rest "PATCH" "/api/v1/servers/$PDNS_ServerId/zones/$root" "{\"rrsets\": [{\"changetype\": \"REPLACE\", \"name\": \"$full.\", \"type\": \"TXT\", \"ttl\": $PDNS_Ttl, \"records\": [{\"name\": \"$full.\", \"type\": \"TXT\", \"content\": \"\\\"$txtvalue\\\"\", \"disabled\": false, \"ttl\": $PDNS_Ttl}]}]}"; then
_err "Set txt record error." _err "Set txt record error."
return 1 return 1
fi fi
@@ -107,7 +107,7 @@ rm_record() {
root=$1 root=$1
full=$2 full=$2
if ! _pdns_rest "PATCH" "/api/v1/servers/$PDNS_ServerId/zones/$root." "{\"rrsets\": [{\"changetype\": \"DELETE\", \"name\": \"$full.\", \"type\": \"TXT\"}]}"; then if ! _pdns_rest "PATCH" "/api/v1/servers/$PDNS_ServerId/zones/$root" "{\"rrsets\": [{\"changetype\": \"DELETE\", \"name\": \"$full.\", \"type\": \"TXT\"}]}"; then
_err "Delete txt record error." _err "Delete txt record error."
return 1 return 1
fi fi
@@ -122,7 +122,7 @@ rm_record() {
notify_slaves() { notify_slaves() {
root=$1 root=$1
if ! _pdns_rest "PUT" "/api/v1/servers/$PDNS_ServerId/zones/$root./notify"; then if ! _pdns_rest "PUT" "/api/v1/servers/$PDNS_ServerId/zones/$root/notify"; then
_err "Notify slaves error." _err "Notify slaves error."
return 1 return 1
fi fi
@@ -144,15 +144,18 @@ _get_root() {
while true; do while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100) h=$(printf "%s" "$domain" | cut -d . -f $i-100)
if [ -z "$h" ]; then
return 1
fi
if _contains "$_zones_response" "\"name\": \"$h.\""; then if _contains "$_zones_response" "\"name\": \"$h.\""; then
_domain="$h" _domain="$h."
if [ -z "$h" ]; then
_domain="=2E"
fi
return 0 return 0
fi fi
if [ -z "$h" ]; then
return 1
fi
i=$(_math $i + 1) i=$(_math $i + 1)
done done
_debug "$domain not found" _debug "$domain not found"
+3 -3
View File
@@ -50,9 +50,9 @@ _PDD_get_domain() {
__last=0 __last=0
while [ $__last -eq 0 ]; do while [ $__last -eq 0 ]; do
uri1="https://pddimp.yandex.ru/api2/admin/domain/domains?page=${__page}&on_page=20" uri1="https://pddimp.yandex.ru/api2/admin/domain/domains?page=${__page}&on_page=20"
res1=$(_get "$uri1" | _normalizeJson) res1="$(_get "$uri1" | _normalizeJson)"
#_debug "$res1" _debug2 "res1" "$res1"
__found=$(echo "$res1" | sed -n -e 's#.* "found": \([^,]*\),.*#\1#p') __found="$(echo "$res1" | sed -n -e 's#.* "found": \([^,]*\),.*#\1#p')"
_debug "found: $__found results on page" _debug "found: $__found results on page"
if [ "$__found" -lt 20 ]; then if [ "$__found" -lt 20 ]; then
_debug "last page: $__page" _debug "last page: $__page"
+139
View File
@@ -0,0 +1,139 @@
#!/usr/bin/env sh
Zilore_API="https://api.zilore.com/dns/v1"
# Zilore_Key="YOUR-ZILORE-API-KEY"
######## Public functions #####################
dns_zilore_add() {
fulldomain=$1
txtvalue=$2
_info "Using Zilore"
_debug fulldomain "$fulldomain"
_debug txtvalue "$txtvalue"
Zilore_Key="${Zilore_Key:-$(_readaccountconf_mutable Zilore_Key)}"
if [ -z "$Zilore_Key" ]; then
Zilore_Key=""
_err "Please define Zilore API key"
return 1
fi
_saveaccountconf_mutable Zilore_Key "$Zilore_Key"
if ! _get_root "$fulldomain"; then
_err "Unable to determine root domain"
return 1
else
_debug _domain "$_domain"
fi
if _zilore_rest POST "domains/$_domain/records?record_type=TXT&record_ttl=600&record_name=$fulldomain&record_value=\"$txtvalue\""; then
if _contains "$response" '"added"' >/dev/null; then
_info "Added TXT record, waiting for validation"
return 0
else
_debug response "$response"
_err "Error while adding DNS records"
return 1
fi
fi
return 1
}
dns_zilore_rm() {
fulldomain=$1
txtvalue=$2
_info "Using Zilore"
_debug fulldomain "$fulldomain"
_debug txtvalue "$txtvalue"
Zilore_Key="${Zilore_Key:-$(_readaccountconf_mutable Zilore_Key)}"
if [ -z "$Zilore_Key" ]; then
Zilore_Key=""
_err "Please define Zilore API key"
return 1
fi
_saveaccountconf_mutable Zilore_Key "$Zilore_Key"
if ! _get_root "$fulldomain"; then
_err "Unable to determine root domain"
return 1
else
_debug _domain "$_domain"
fi
_debug "Getting TXT records"
_zilore_rest GET "domains/${_domain}/records?search_text=$txtvalue&search_record_type=TXT"
_debug response "$response"
if ! _contains "$response" '"ok"' >/dev/null; then
_err "Error while getting records list"
return 1
else
_record_id=$(printf "%s\n" "$response" | _egrep_o "\"record_id\":\"[^\"]+\"" | cut -d : -f 2 | tr -d \" | _head_n 1)
if [ -z "$_record_id" ]; then
_err "Cannot determine _record_id"
return 1
else
_debug _record_id "$_record_id"
fi
if ! _zilore_rest DELETE "domains/${_domain}/records?record_id=$_record_id"; then
_err "Error while deleting chosen record"
return 1
fi
_contains "$response" '"ok"'
fi
}
#################### Private functions below ##################################
_get_root() {
domain=$1
i=2
while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
_debug h "$h"
if [ -z "$h" ]; then
#not valid
return 1
fi
if ! _zilore_rest GET "domains?search_text=$h"; then
return 1
fi
if _contains "$response" "\"$h\"" >/dev/null; then
_domain=$h
return 0
else
_debug "$h not found"
fi
i=$(_math "$i" + 1)
done
return 1
}
_zilore_rest() {
method=$1
param=$2
data=$3
export _H1="X-Auth-Key: $Zilore_Key"
if [ "$method" != "GET" ]; then
response="$(_post "$data" "$Zilore_API/$param" "" "$method")"
else
response="$(_get "$Zilore_API/$param")"
fi
if [ "$?" != "0" ]; then
_err "error $param"
return 1
fi
_debug2 response "$response"
return 0
}