diff --git a/acme.sh b/acme.sh index b958a02b..cd545aa4 100755 --- a/acme.sh +++ b/acme.sh @@ -1,6 +1,6 @@ #!/usr/bin/env sh -VER=3.0.4 +VER=3.0.5 PROJECT_NAME="acme.sh" @@ -20,8 +20,6 @@ _SUB_FOLDER_DEPLOY="deploy" _SUB_FOLDERS="$_SUB_FOLDER_DNSAPI $_SUB_FOLDER_DEPLOY $_SUB_FOLDER_NOTIFY" -CA_LETSENCRYPT_V1="https://acme-v01.api.letsencrypt.org/directory" - CA_LETSENCRYPT_V2="https://acme-v02.api.letsencrypt.org/directory" CA_LETSENCRYPT_V2_TEST="https://acme-staging-v02.api.letsencrypt.org/directory" @@ -2692,7 +2690,6 @@ _initAPI() { } _clearCA() { - export ACME_DIRECTORY= export CA_CONF= export ACCOUNT_KEY_PATH= export ACCOUNT_JSON_PATH= @@ -5244,18 +5241,20 @@ _split_cert_chain() { fi } -#domain [isEcc] +#domain [isEcc] [server] renew() { Le_Domain="$1" if [ -z "$Le_Domain" ]; then - _usage "Usage: $PROJECT_ENTRY --renew --domain [--ecc]" + _usage "Usage: $PROJECT_ENTRY --renew --domain [--ecc] [--server server]" return 1 fi _isEcc="$2" - #the server specified from commandline - _acme_server_back="$ACME_DIRECTORY" + _renewServer="$3" + _debug "_renewServer" "$_renewServer" + _initpath "$Le_Domain" "$_isEcc" + _set_level=${NOTIFY_LEVEL:-$NOTIFY_LEVEL_DEFAULT} _info "$(__green "Renew: '$Le_Domain'")" if [ ! -f "$DOMAIN_CONF" ]; then @@ -5269,17 +5268,6 @@ renew() { . "$DOMAIN_CONF" _debug Le_API "$Le_API" - if [ -z "$Le_API" ] || [ "$CA_LETSENCRYPT_V1" = "$Le_API" ]; then - #if this is from an old version, Le_API is empty, - #so, we force to use letsencrypt server - Le_API="$CA_LETSENCRYPT_V2" - fi - - if [ "$_acme_server_back" ]; then - export ACME_DIRECTORY="$_acme_server_back" - else - export ACME_DIRECTORY="$Le_API" - fi case "$Le_API" in "$CA_LETSENCRYPT_V2_TEST") @@ -5296,17 +5284,18 @@ renew() { ;; esac - if [ "$Le_API" ] && [ "$ACME_DIRECTORY" ]; then - if [ "$Le_API" != "$ACME_DIRECTORY" ]; then - _clearAPI - fi - #reload ca configs - ACCOUNT_KEY_PATH="" - ACCOUNT_JSON_PATH="" - CA_CONF="" - _debug2 "initpath again." - _initpath "$Le_Domain" "$_isEcc" + if [ "$_server" ]; then + Le_API="$_server" fi + _info "Renew to Le_API=$Le_API" + + _clearAPI + _clearCA + export ACME_DIRECTORY="$Le_API" + + #reload ca configs + _debug2 "initpath again." + _initpath "$Le_Domain" "$_isEcc" if [ -z "$FORCE" ] && [ "$Le_NextRenewTime" ] && [ "$(_time)" -lt "$Le_NextRenewTime" ]; then _info "Skip, Next renewal time is: $(__green "$Le_NextRenewTimeStr")" @@ -5361,12 +5350,16 @@ renew() { return "$res" } -#renewAll [stopRenewOnError] +#renewAll [stopRenewOnError] [server] renewAll() { _initpath _clearCA _stopRenewOnError="$1" _debug "_stopRenewOnError" "$_stopRenewOnError" + + _server="$2" + _debug "_server" "$_server" + _ret="0" _success_msg="" _error_msg="" @@ -5389,7 +5382,7 @@ renewAll() { _isEcc=$(echo "$d" | cut -d "$ECC_SEP" -f 2) d=$(echo "$d" | cut -d "$ECC_SEP" -f 1) fi - renew "$d" "$_isEcc" + renew "$d" "$_isEcc" "$_server" ) rc="$?" _debug "Return code: $rc" @@ -7662,6 +7655,7 @@ _process() { if [ "$_server" ]; then _selectServer "$_server" "${_ecc:-$_keylength}" + _server="$ACME_DIRECTORY" fi if [ "${_CMD}" != "install" ]; then @@ -7736,10 +7730,10 @@ _process() { installcert "$_domain" "$_cert_file" "$_key_file" "$_ca_file" "$_reloadcmd" "$_fullchain_file" "$_ecc" ;; renew) - renew "$_domain" "$_ecc" + renew "$_domain" "$_ecc" "$_server" ;; renewAll) - renewAll "$_stopRenewOnError" + renewAll "$_stopRenewOnError" "$_server" ;; revoke) revoke "$_domain" "$_ecc" "$_revoke_reason" diff --git a/dnsapi/dns_vercel.sh b/dnsapi/dns_vercel.sh new file mode 100644 index 00000000..7bf6b0e5 --- /dev/null +++ b/dnsapi/dns_vercel.sh @@ -0,0 +1,142 @@ +#!/usr/bin/env sh + +# Vercel DNS API +# +# This is your API token which can be acquired on the account page. +# https://vercel.com/account/tokens +# +# VERCEL_TOKEN="sdfsdfsdfljlbjkljlkjsdfoiwje" + +VERCEL_API="https://api.vercel.com" + +#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs" +dns_vercel_add() { + fulldomain=$1 + txtvalue=$2 + _debug fulldomain "$fulldomain" + _debug txtvalue "$txtvalue" + + VERCEL_TOKEN="${VERCEL_TOKEN:-$(_readaccountconf_mutable VERCEL_TOKEN)}" + + if [ -z "$VERCEL_TOKEN" ]; then + VERCEL_TOKEN="" + _err "You have not set the Vercel API token yet." + _err "Please visit https://vercel.com/account/tokens to generate it." + return 1 + fi + + _saveaccountconf_mutable VERCEL_TOKEN "$VERCEL_TOKEN" + + if ! _get_root "$fulldomain"; then + _err "invalid domain" + return 1 + fi + + _debug _sub_domain "$_sub_domain" + _debug _domain "$_domain" + + _info "Adding record" + if _vercel_rest POST "v2/domains/$_domain/records" "{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"value\":\"$txtvalue\"}"; then + if printf -- "%s" "$response" | grep "\"uid\":\"" >/dev/null; then + _info "Added" + return 0 + else + _err "Unexpected response while adding text record." + return 1 + fi + fi + _err "Add txt record error." +} + +dns_vercel_rm() { + fulldomain=$1 + txtvalue=$2 + + if ! _get_root "$fulldomain"; then + _err "invalid domain" + return 1 + fi + + _vercel_rest GET "v2/domains/$_domain/records" + + count=$(printf "%s\n" "$response" | _egrep_o "\"name\":\"$_sub_domain\",[^{]*\"type\":\"TXT\"" | wc -l | tr -d " ") + + if [ "$count" = "0" ]; then + _info "Don't need to remove." + else + _record_id=$(printf "%s" "$response" | _egrep_o "\"id\":[^,]*,\"slug\":\"[^,]*\",\"name\":\"$_sub_domain\",[^{]*\"type\":\"TXT\",\"value\":\"$txtvalue\"" | cut -d: -f2 | cut -d, -f1 | tr -d '"') + + if [ "$_record_id" ]; then + echo "$_record_id" | while read -r item; do + if _vercel_rest DELETE "v2/domains/$_domain/records/$item"; then + _info "removed record" "$item" + return 0 + else + _err "failed to remove record" "$item" + return 1 + fi + done + fi + fi +} + +#################### Private functions below ################################## +#_acme-challenge.www.domain.com +#returns +# _sub_domain=_acme-challenge.www +# _domain=domain.com +_get_root() { + domain="$1" + ep="$2" + i=1 + p=1 + while true; do + h=$(printf "%s" "$domain" | cut -d . -f $i-100) + if [ -z "$h" ]; then + #not valid + return 1 + fi + + if ! _vercel_rest GET "v4/domains/$h"; then + return 1 + fi + + if _contains "$response" "\"name\":\"$h\"" >/dev/null; then + _sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p) + _domain=$h + return 0 + fi + p=$i + i=$(_math "$i" + 1) + done + return 1 +} + +_vercel_rest() { + m="$1" + ep="$2" + data="$3" + + path="$VERCEL_API/$ep" + + export _H1="Content-Type: application/json" + export _H2="Authorization: Bearer $VERCEL_TOKEN" + + if [ "$m" != "GET" ]; then + _secure_debug2 data "$data" + response="$(_post "$data" "$path" "" "$m")" + else + response="$(_get "$path")" + fi + _ret="$?" + _code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\\r\\n")" + _debug "http response code $_code" + _secure_debug2 response "$response" + if [ "$_ret" != "0" ]; then + _err "error $ep" + return 1 + fi + + response="$(printf "%s" "$response" | _normalizeJson)" + return 0 +} diff --git a/notify/callmebotWhatsApp.sh b/notify/callmebotWhatsApp.sh new file mode 100644 index 00000000..1c15b283 --- /dev/null +++ b/notify/callmebotWhatsApp.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env sh + +#Support CallMeBot Whatsapp webhooks + +#CALLMEBOT_YOUR_PHONE_NO="" +#CALLMEBOT_API_KEY="" + +callmebotWhatsApp_send() { + _subject="$1" + _content="$2" + _statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped + _debug "_statusCode" "$_statusCode" + + CALLMEBOT_YOUR_PHONE_NO="${CALLMEBOT_YOUR_PHONE_NO:-$(_readaccountconf_mutable CALLMEBOT_YOUR_PHONE_NO)}" + if [ -z "$CALLMEBOT_YOUR_PHONE_NO" ]; then + CALLMEBOT_YOUR_PHONE_NO="" + _err "You didn't specify a Slack webhook url CALLMEBOT_YOUR_PHONE_NO yet." + return 1 + fi + _saveaccountconf_mutable CALLMEBOT_YOUR_PHONE_NO "$CALLMEBOT_YOUR_PHONE_NO" + + CALLMEBOT_API_KEY="${CALLMEBOT_API_KEY:-$(_readaccountconf_mutable CALLMEBOT_API_KEY)}" + if [ "$CALLMEBOT_API_KEY" ]; then + _saveaccountconf_mutable CALLMEBOT_API_KEY "$CALLMEBOT_API_KEY" + fi + + _waUrl="https://api.callmebot.com/whatsapp.php" + + _Phone_No="$(printf "%s" "$CALLMEBOT_YOUR_PHONE_NO" | _url_encode)" + _apikey="$(printf "%s" "$CALLMEBOT_API_KEY" | _url_encode)" + _message="$(printf "*%s*\\n%s" "$_subject" "$_content" | _url_encode)" + + _finalUrl="$_waUrl?phone=$_Phone_No&apikey=$_apikey&text=$_message" + response="$(_get "$_finalUrl")" + + if [ "$?" = "0" ] && _contains ".

Message queued. You will receive it in a few seconds."; then + _info "wa send success." + return 0 + fi + _err "wa send error." + _debug "URL" "$_finalUrl" + _debug "Response" "$response" + return 1 +}