Merge branch 'dev' into master

This commit is contained in:
Lance Conry 2017-07-05 08:07:06 +10:00 committed by GitHub
commit 45f0f9d710
6 changed files with 510 additions and 55 deletions

View File

@ -50,9 +50,10 @@ RUN for verb in help \
RUN printf "%b" '#!'"/usr/bin/env sh\n \ RUN printf "%b" '#!'"/usr/bin/env sh\n \
if [ \"\$1\" = \"daemon\" ]; then \n \ if [ \"\$1\" = \"daemon\" ]; then \n \
crond -f\n \ trap \"echo stop && killall crond && exit 0\" SIGTERM SIGINT \n \
crond && while true; do sleep 1; done;\n \
else \n \ else \n \
/root/.acme.sh/acme.sh --config-home /acme.sh \"\$@\"\n \ exec -- \"\$@\"\n \
fi" >/entry.sh && chmod +x /entry.sh fi" >/entry.sh && chmod +x /entry.sh
VOLUME /acme.sh VOLUME /acme.sh

View File

@ -296,6 +296,9 @@ acme.sh --renew -d example.com
Ok, it's finished. Ok, it's finished.
**Take care, this is dns manual mode, it can not be renewed automatically. you will have to add a new txt record to your domain by your hand when you renew your cert.**
**Please use dns api mode instead.**
# 9. Automatic DNS API integration # 9. Automatic DNS API integration
@ -332,7 +335,8 @@ You don't have to do anything manually!
1. DNSimple API 1. DNSimple API
1. NS1.com API 1. NS1.com API
1. DreamHost.com API 1. DreamHost.com API
1. DuckDNS.org API
1. Name.com API
And: And:

199
acme.sh
View File

@ -366,6 +366,7 @@ _hasfield() {
return 1 #not contains return 1 #not contains
} }
# str index [sep]
_getfield() { _getfield() {
_str="$1" _str="$1"
_findex="$2" _findex="$2"
@ -453,7 +454,7 @@ if [ "$(printf '\x41')" != 'A' ]; then
fi fi
_ESCAPE_XARGS="" _ESCAPE_XARGS=""
if [ "$(printf %s '\\x41' | xargs printf)" = 'A' ]; then if _exists xargs && [ "$(printf %s '\\x41' | xargs printf)" = 'A' ]; then
_ESCAPE_XARGS=1 _ESCAPE_XARGS=1
fi fi
@ -1138,7 +1139,12 @@ _readKeyLengthFromCSR() {
echo "$_outcsr" | tr "\t" " " | _egrep_o "^ *ASN1 OID:.*" | cut -d ':' -f 2 | tr -d ' ' echo "$_outcsr" | tr "\t" " " | _egrep_o "^ *ASN1 OID:.*" | cut -d ':' -f 2 | tr -d ' '
else else
_debug "RSA CSR" _debug "RSA CSR"
echo "$_outcsr" | tr "\t" " " | (_egrep_o "^ *Public.Key:.*" || _egrep_o "RSA Public.Key:.*") | cut -d '(' -f 2 | cut -d ' ' -f 1 _rkl="$(echo "$_outcsr" | tr "\t" " " | _egrep_o "^ *Public.Key:.*" | cut -d '(' -f 2 | cut -d ' ' -f 1)"
if [ "$_rkl" ]; then
echo "$_rkl"
else
echo "$_outcsr" | tr "\t" " " | _egrep_o "RSA Public.Key:.*" | cut -d '(' -f 2 | cut -d ' ' -f 1
fi
fi fi
} }
@ -1147,7 +1153,7 @@ _ss() {
if _exists "ss"; then if _exists "ss"; then
_debug "Using: ss" _debug "Using: ss"
ss -ntpl | grep ":$_port " ss -ntpl 2>/dev/null | grep ":$_port "
return 0 return 0
fi fi
@ -1276,7 +1282,7 @@ createDomainKey() {
_initpath "$domain" "$_cdl" _initpath "$domain" "$_cdl"
if [ ! -f "$CERT_KEY_PATH" ] || ([ "$FORCE" ] && ! [ "$IS_RENEW" ]); then if [ ! -f "$CERT_KEY_PATH" ] || ([ "$FORCE" ] && ! [ "$IS_RENEW" ]) || [ "$Le_ForceNewDomainKey" = "1" ]; then
if _createkey "$_cdl" "$CERT_KEY_PATH"; then if _createkey "$_cdl" "$CERT_KEY_PATH"; then
_savedomainconf Le_Keylength "$_cdl" _savedomainconf Le_Keylength "$_cdl"
_info "The domain key is here: $(__green $CERT_KEY_PATH)" _info "The domain key is here: $(__green $CERT_KEY_PATH)"
@ -2191,7 +2197,9 @@ _initAPI() {
export ACME_KEY_CHANGE="https://acme-v01.api.letsencrypt.org/acme/key-change" export ACME_KEY_CHANGE="https://acme-v01.api.letsencrypt.org/acme/key-change"
export ACME_NEW_AUTHZ="https://acme-v01.api.letsencrypt.org/acme/new-authz" export ACME_NEW_AUTHZ="https://acme-v01.api.letsencrypt.org/acme/new-authz"
export ACME_NEW_ORDER="https://acme-v01.api.letsencrypt.org/acme/new-cert" export ACME_NEW_ORDER="https://acme-v01.api.letsencrypt.org/acme/new-cert"
export ACME_NEW_ORDER_RES="new-cert"
export ACME_NEW_ACCOUNT="https://acme-v01.api.letsencrypt.org/acme/new-reg" export ACME_NEW_ACCOUNT="https://acme-v01.api.letsencrypt.org/acme/new-reg"
export ACME_NEW_ACCOUNT_RES="new-reg"
export ACME_REVOKE_CERT="https://acme-v01.api.letsencrypt.org/acme/revoke-cert" export ACME_REVOKE_CERT="https://acme-v01.api.letsencrypt.org/acme/revoke-cert"
fi fi
@ -2211,16 +2219,22 @@ _initAPI() {
export ACME_NEW_AUTHZ export ACME_NEW_AUTHZ
ACME_NEW_ORDER=$(echo "$response" | _egrep_o 'new-cert" *: *"[^"]*"' | cut -d '"' -f 3) ACME_NEW_ORDER=$(echo "$response" | _egrep_o 'new-cert" *: *"[^"]*"' | cut -d '"' -f 3)
ACME_NEW_ORDER_RES="new-cert"
if [ -z "$ACME_NEW_ORDER" ]; then if [ -z "$ACME_NEW_ORDER" ]; then
ACME_NEW_ORDER=$(echo "$response" | _egrep_o 'new-order" *: *"[^"]*"' | cut -d '"' -f 3) ACME_NEW_ORDER=$(echo "$response" | _egrep_o 'new-order" *: *"[^"]*"' | cut -d '"' -f 3)
ACME_NEW_ORDER_RES="new-order"
fi fi
export ACME_NEW_ORDER export ACME_NEW_ORDER
export ACME_NEW_ORDER_RES
ACME_NEW_ACCOUNT=$(echo "$response" | _egrep_o 'new-reg" *: *"[^"]*"' | cut -d '"' -f 3) ACME_NEW_ACCOUNT=$(echo "$response" | _egrep_o 'new-reg" *: *"[^"]*"' | cut -d '"' -f 3)
ACME_NEW_ACCOUNT_RES="new-reg"
if [ -z "$ACME_NEW_ACCOUNT" ]; then if [ -z "$ACME_NEW_ACCOUNT" ]; then
ACME_NEW_ACCOUNT=$(echo "$response" | _egrep_o 'new-account" *: *"[^"]*"' | cut -d '"' -f 3) ACME_NEW_ACCOUNT=$(echo "$response" | _egrep_o 'new-account" *: *"[^"]*"' | cut -d '"' -f 3)
ACME_NEW_ACCOUNT_RES="new-account"
fi fi
export ACME_NEW_ACCOUNT export ACME_NEW_ACCOUNT
export ACME_NEW_ACCOUNT_RES
ACME_REVOKE_CERT=$(echo "$response" | _egrep_o 'revoke-cert" *: *"[^"]*"' | cut -d '"' -f 3) ACME_REVOKE_CERT=$(echo "$response" | _egrep_o 'revoke-cert" *: *"[^"]*"' | cut -d '"' -f 3)
export ACME_REVOKE_CERT export ACME_REVOKE_CERT
@ -2994,9 +3008,9 @@ _on_issue_err() {
fi fi
#trigger the validation to flush the pending authz #trigger the validation to flush the pending authz
_debug2 "_chk_vlist" "$_chk_vlist"
if [ "$_chk_vlist" ]; then if [ "$_chk_vlist" ]; then
( (
_debug2 "_chk_vlist" "$_chk_vlist"
_debug2 "start to deactivate authz" _debug2 "start to deactivate authz"
ventries=$(echo "$_chk_vlist" | tr "$dvsep" ' ') ventries=$(echo "$_chk_vlist" | tr "$dvsep" ' ')
for ventry in $ventries; do for ventry in $ventries; do
@ -3068,14 +3082,13 @@ _regAccount() {
_initpath _initpath
_reg_length="$1" _reg_length="$1"
if [ ! -f "$ACCOUNT_KEY_PATH" ] && [ -f "$_OLD_ACCOUNT_KEY" ]; then
mkdir -p "$CA_DIR" mkdir -p "$CA_DIR"
if [ ! -f "$ACCOUNT_KEY_PATH" ] && [ -f "$_OLD_ACCOUNT_KEY" ]; then
_info "mv $_OLD_ACCOUNT_KEY to $ACCOUNT_KEY_PATH" _info "mv $_OLD_ACCOUNT_KEY to $ACCOUNT_KEY_PATH"
mv "$_OLD_ACCOUNT_KEY" "$ACCOUNT_KEY_PATH" mv "$_OLD_ACCOUNT_KEY" "$ACCOUNT_KEY_PATH"
fi fi
if [ ! -f "$ACCOUNT_JSON_PATH" ] && [ -f "$_OLD_ACCOUNT_JSON" ]; then if [ ! -f "$ACCOUNT_JSON_PATH" ] && [ -f "$_OLD_ACCOUNT_JSON" ]; then
mkdir -p "$CA_DIR"
_info "mv $_OLD_ACCOUNT_JSON to $ACCOUNT_JSON_PATH" _info "mv $_OLD_ACCOUNT_JSON to $ACCOUNT_JSON_PATH"
mv "$_OLD_ACCOUNT_JSON" "$ACCOUNT_JSON_PATH" mv "$_OLD_ACCOUNT_JSON" "$ACCOUNT_JSON_PATH"
fi fi
@ -3092,7 +3105,7 @@ _regAccount() {
fi fi
_initAPI _initAPI
_updateTos="" _updateTos=""
_reg_res="new-reg" _reg_res="$ACME_NEW_ACCOUNT_RES"
while true; do while true; do
_debug AGREEMENT "$AGREEMENT" _debug AGREEMENT "$AGREEMENT"
@ -3122,7 +3135,7 @@ _regAccount() {
_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"
_savecaconf "ACCOUNT_URL" "$_accUri"
_tos="$(echo "$responseHeaders" | grep "^Link:.*rel=\"terms-of-service\"" | _head_n 1 | _egrep_o "<.*>" | tr -d '<>')" _tos="$(echo "$responseHeaders" | grep "^Link:.*rel=\"terms-of-service\"" | _head_n 1 | _egrep_o "<.*>" | tr -d '<>')"
_debug "_tos" "$_tos" _debug "_tos" "$_tos"
if [ -z "$_tos" ]; then if [ -z "$_tos" ]; then
@ -3143,11 +3156,14 @@ _regAccount() {
return 1 return 1
fi fi
if [ "$code" = '202' ]; then if [ "$code" = '202' ]; then
_info "Update success." _info "Update account tos info success."
CA_KEY_HASH="$(__calcAccountKeyHash)" CA_KEY_HASH="$(__calcAccountKeyHash)"
_debug "Calc CA_KEY_HASH" "$CA_KEY_HASH" _debug "Calc CA_KEY_HASH" "$CA_KEY_HASH"
_savecaconf CA_KEY_HASH "$CA_KEY_HASH" _savecaconf CA_KEY_HASH "$CA_KEY_HASH"
elif [ "$code" = '403' ]; then
_err "It seems that the account key is already deactivated, please use a new account key."
return 1
else else
_err "Update account error." _err "Update account error."
return 1 return 1
@ -3160,6 +3176,68 @@ _regAccount() {
} }
#Implement deactivate account
deactivateaccount() {
_initpath
if [ ! -f "$ACCOUNT_KEY_PATH" ] && [ -f "$_OLD_ACCOUNT_KEY" ]; then
_info "mv $_OLD_ACCOUNT_KEY to $ACCOUNT_KEY_PATH"
mv "$_OLD_ACCOUNT_KEY" "$ACCOUNT_KEY_PATH"
fi
if [ ! -f "$ACCOUNT_JSON_PATH" ] && [ -f "$_OLD_ACCOUNT_JSON" ]; then
_info "mv $_OLD_ACCOUNT_JSON to $ACCOUNT_JSON_PATH"
mv "$_OLD_ACCOUNT_JSON" "$ACCOUNT_JSON_PATH"
fi
if [ ! -f "$ACCOUNT_KEY_PATH" ]; then
_err "Account key is not found at: $ACCOUNT_KEY_PATH"
return 1
fi
_accUri=$(_readcaconf "ACCOUNT_URL")
_debug _accUri "$_accUri"
if [ -z "$_accUri" ]; then
_err "The account url is empty, please run '--update-account' first to update the account info first,"
_err "Then try again."
return 1
fi
if ! _calcjwk "$ACCOUNT_KEY_PATH"; then
return 1
fi
_initAPI
if _send_signed_request "$_accUri" "{\"resource\": \"reg\", \"status\":\"deactivated\"}" && _contains "$response" '"deactivated"'; then
_info "Deactivate account success for $_accUri."
_accid=$(echo "$response" | _egrep_o "\"id\" *: *[^,]*," | cut -d : -f 2 | tr -d ' ,')
elif [ "$code" = "403" ]; then
_info "The account is already deactivated."
_accid=$(_getfield "$_accUri" "999" "/")
else
_err "Deactivate: account failed for $_accUri."
return 1
fi
_debug "Account id: $_accid"
if [ "$_accid" ]; then
_deactivated_account_path="$CA_DIR/deactivated/$_accid"
_debug _deactivated_account_path "$_deactivated_account_path"
if mkdir -p "$_deactivated_account_path"; then
_info "Moving deactivated account info to $_deactivated_account_path/"
mv "$CA_CONF" "$_deactivated_account_path/"
mv "$ACCOUNT_JSON_PATH" "$_deactivated_account_path/"
mv "$ACCOUNT_KEY_PATH" "$_deactivated_account_path/"
else
_err "Can not create dir: $_deactivated_account_path, try to remove the deactivated account key."
rm -f "$CA_CONF"
rm -f "$ACCOUNT_JSON_PATH"
rm -f "$ACCOUNT_KEY_PATH"
fi
fi
}
# domain folder file # domain folder file
_findHook() { _findHook() {
_hookdomain="$1" _hookdomain="$1"
@ -3350,7 +3428,7 @@ issue() {
else else
_key=$(_readdomainconf Le_Keylength) _key=$(_readdomainconf Le_Keylength)
_debug "Read key length:$_key" _debug "Read key length:$_key"
if [ ! -f "$CERT_KEY_PATH" ] || [ "$_key_length" != "$_key" ]; then if [ ! -f "$CERT_KEY_PATH" ] || [ "$_key_length" != "$_key" ] || [ "$Le_ForceNewDomainKey" = "1" ]; then
if ! createDomainKey "$_main_domain" "$_key_length"; then if ! createDomainKey "$_main_domain" "$_key_length"; then
_err "Create domain key error." _err "Create domain key error."
_clearup _clearup
@ -3465,11 +3543,11 @@ issue() {
if [ "$d_api" ]; then if [ "$d_api" ]; then
_info "Found domain api file: $d_api" _info "Found domain api file: $d_api"
else else
_err "Add the following TXT record:" _info "$(__red "Add the following TXT record:")"
_err "Domain: '$(__green "$txtdomain")'" _info "$(__red "Domain: '$(__green "$txtdomain")'")"
_err "TXT value: '$(__green "$txt")'" _info "$(__red "TXT value: '$(__green "$txt")'")"
_err "Please be aware that you prepend _acme-challenge. before your domain" _info "$(__red "Please be aware that you prepend _acme-challenge. before your domain")"
_err "so the resulting subdomain will be: $txtdomain" _info "$(__red "so the resulting subdomain will be: $txtdomain")"
continue continue
fi fi
@ -3493,7 +3571,7 @@ issue() {
if [ "$?" != "0" ]; then if [ "$?" != "0" ]; then
_clearup _clearup
_on_issue_err "$_post_hook" _on_issue_err "$_post_hook" "$vlist"
return 1 return 1
fi fi
dnsadded='1' dnsadded='1'
@ -3756,7 +3834,7 @@ issue() {
_info "Verify finished, start to sign." _info "Verify finished, start to sign."
der="$(_getfile "${CSR_PATH}" "${BEGIN_CSR}" "${END_CSR}" | tr -d "\r\n" | _url_replace)" der="$(_getfile "${CSR_PATH}" "${BEGIN_CSR}" "${END_CSR}" | tr -d "\r\n" | _url_replace)"
if ! _send_signed_request "${ACME_NEW_ORDER}" "{\"resource\": \"new-cert\", \"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."
_on_issue_err "$_post_hook" _on_issue_err "$_post_hook"
return 1 return 1
@ -3880,6 +3958,12 @@ issue() {
_cleardomainconf Le_Listen_V4 _cleardomainconf Le_Listen_V4
fi fi
if [ "$Le_ForceNewDomainKey" = "1" ]; then
_savedomainconf "Le_ForceNewDomainKey" "$Le_ForceNewDomainKey"
else
_cleardomainconf Le_ForceNewDomainKey
fi
Le_NextRenewTime=$(_math "$Le_CertCreateTime" + "$Le_RenewalDays" \* 24 \* 60 \* 60) Le_NextRenewTime=$(_math "$Le_CertCreateTime" + "$Le_RenewalDays" \* 24 \* 60 \* 60)
Le_NextRenewTimeStr=$(_time2str "$Le_NextRenewTime") Le_NextRenewTimeStr=$(_time2str "$Le_NextRenewTime")
@ -4474,12 +4558,6 @@ _deactivate() {
_d_type="$2" _d_type="$2"
_initpath _initpath
_d_i=0
_d_max_retry=9
while [ "$_d_i" -lt "$_d_max_retry" ]; do
_info "Deactivate: $_d_domain"
_d_i="$(_math $_d_i + 1)"
if ! __get_domain_new_authz "$_d_domain"; then if ! __get_domain_new_authz "$_d_domain"; then
_err "Can not get domain new authz token." _err "Can not get domain new authz token."
return 1 return 1
@ -4488,12 +4566,43 @@ _deactivate() {
authzUri="$(echo "$responseHeaders" | grep "^Location:" | _head_n 1 | cut -d ' ' -f 2 | tr -d "\r\n")" authzUri="$(echo "$responseHeaders" | grep "^Location:" | _head_n 1 | cut -d ' ' -f 2 | tr -d "\r\n")"
_debug "authzUri" "$authzUri" _debug "authzUri" "$authzUri"
if [ ! -z "$code" ] && [ ! "$code" = '201' ]; then if [ "$code" ] && [ ! "$code" = '201' ]; then
_err "new-authz error: $response" _err "new-authz error: $response"
return 1 return 1
fi fi
entry="$(printf "%s\n" "$response" | _egrep_o '{"type":"[^"]*","status":"valid","uri"[^}]*')" entries="$(echo "$response" | _egrep_o '{ *"type":"[^"]*", *"status": *"valid", *"uri"[^}]*')"
if [ -z "$entries" ]; then
_info "No valid entries found."
if [ -z "$thumbprint" ]; then
thumbprint="$(__calc_account_thumbprint)"
fi
_debug "Trigger validation."
vtype="$VTYPE_HTTP"
entry="$(printf "%s\n" "$response" | _egrep_o '[^\{]*"type":"'$vtype'"[^\}]*')"
_debug entry "$entry"
if [ -z "$entry" ]; then
_err "Error, can not get domain token $d"
return 1
fi
token="$(printf "%s\n" "$entry" | _egrep_o '"token":"[^"]*' | cut -d : -f 2 | tr -d '"')"
_debug token "$token"
uri="$(printf "%s\n" "$entry" | _egrep_o '"uri":"[^"]*' | cut -d : -f 2,3 | tr -d '"')"
_debug uri "$uri"
keyauthorization="$token.$thumbprint"
_debug keyauthorization "$keyauthorization"
__trigger_validation "$uri" "$keyauthorization"
fi
_d_i=0
_d_max_retry=$(echo "$entries" | wc -l)
while [ "$_d_i" -lt "$_d_max_retry" ]; do
_info "Deactivate: $_d_domain"
_d_i="$(_math $_d_i + 1)"
entry="$(echo "$entries" | sed -n "${_d_i}p")"
_debug entry "$entry" _debug entry "$entry"
if [ -z "$entry" ]; then if [ -z "$entry" ]; then
@ -4515,16 +4624,16 @@ _deactivate() {
_info "Deactivate: $_vtype" _info "Deactivate: $_vtype"
if ! _send_signed_request "$authzUri" "{\"resource\": \"authz\", \"status\":\"deactivated\"}"; then if _send_signed_request "$authzUri" "{\"resource\": \"authz\", \"status\":\"deactivated\"}" && _contains "$response" '"deactivated"'; then
_err "Can not deactivate $_vtype."
return 1
fi
_info "Deactivate: $_vtype success." _info "Deactivate: $_vtype success."
else
_err "Can not deactivate $_vtype."
break
fi
done done
_debug "$_d_i" _debug "$_d_i"
if [ "$_d_i" -lt "$_d_max_retry" ]; then if [ "$_d_i" -eq "$_d_max_retry" ]; then
_info "Deactivated success!" _info "Deactivated success!"
else else
_err "Deactivate failed." _err "Deactivate failed."
@ -4584,9 +4693,7 @@ _detect_profile() {
fi fi
fi fi
if [ ! -z "$DETECTED_PROFILE" ]; then
echo "$DETECTED_PROFILE" echo "$DETECTED_PROFILE"
fi
} }
_initconf() { _initconf() {
@ -4674,6 +4781,8 @@ _installalias() {
_setopt "$_envfile" "export LE_WORKING_DIR" "=" "\"$LE_WORKING_DIR\"" _setopt "$_envfile" "export LE_WORKING_DIR" "=" "\"$LE_WORKING_DIR\""
if [ "$_c_home" ]; then if [ "$_c_home" ]; then
_setopt "$_envfile" "export LE_CONFIG_HOME" "=" "\"$LE_CONFIG_HOME\"" _setopt "$_envfile" "export LE_CONFIG_HOME" "=" "\"$LE_CONFIG_HOME\""
else
_sed_i "/^export LE_CONFIG_HOME/d" "$_envfile"
fi fi
_setopt "$_envfile" "alias $PROJECT_ENTRY" "=" "\"$LE_WORKING_DIR/$PROJECT_ENTRY$_c_entry\"" _setopt "$_envfile" "alias $PROJECT_ENTRY" "=" "\"$LE_WORKING_DIR/$PROJECT_ENTRY$_c_entry\""
@ -4695,6 +4804,8 @@ _installalias() {
_setopt "$_cshfile" "setenv LE_WORKING_DIR" " " "\"$LE_WORKING_DIR\"" _setopt "$_cshfile" "setenv LE_WORKING_DIR" " " "\"$LE_WORKING_DIR\""
if [ "$_c_home" ]; then if [ "$_c_home" ]; then
_setopt "$_cshfile" "setenv LE_CONFIG_HOME" " " "\"$LE_CONFIG_HOME\"" _setopt "$_cshfile" "setenv LE_CONFIG_HOME" " " "\"$LE_CONFIG_HOME\""
else
_sed_i "/^setenv LE_CONFIG_HOME/d" "$_cshfile"
fi fi
_setopt "$_cshfile" "alias $PROJECT_ENTRY" " " "\"$LE_WORKING_DIR/$PROJECT_ENTRY$_c_entry\"" _setopt "$_cshfile" "alias $PROJECT_ENTRY" " " "\"$LE_WORKING_DIR/$PROJECT_ENTRY$_c_entry\""
_setopt "$_csh_profile" "source \"$_cshfile\"" _setopt "$_csh_profile" "source \"$_cshfile\""
@ -4759,19 +4870,23 @@ install() {
_info "Installing to $LE_WORKING_DIR" _info "Installing to $LE_WORKING_DIR"
if [ ! -d "$LE_WORKING_DIR" ]; then
if ! mkdir -p "$LE_WORKING_DIR"; then if ! mkdir -p "$LE_WORKING_DIR"; then
_err "Can not create working dir: $LE_WORKING_DIR" _err "Can not create working dir: $LE_WORKING_DIR"
return 1 return 1
fi fi
chmod 700 "$LE_WORKING_DIR" chmod 700 "$LE_WORKING_DIR"
fi
if [ ! -d "$LE_CONFIG_HOME" ]; then
if ! mkdir -p "$LE_CONFIG_HOME"; then if ! mkdir -p "$LE_CONFIG_HOME"; then
_err "Can not create config dir: $LE_CONFIG_HOME" _err "Can not create config dir: $LE_CONFIG_HOME"
return 1 return 1
fi fi
chmod 700 "$LE_CONFIG_HOME" chmod 700 "$LE_CONFIG_HOME"
fi
cp "$PROJECT_ENTRY" "$LE_WORKING_DIR/" && chmod +x "$LE_WORKING_DIR/$PROJECT_ENTRY" cp "$PROJECT_ENTRY" "$LE_WORKING_DIR/" && chmod +x "$LE_WORKING_DIR/$PROJECT_ENTRY"
@ -4930,6 +5045,7 @@ Commands:
--toPkcs8 Convert to pkcs8 format. --toPkcs8 Convert to pkcs8 format.
--update-account Update account info. --update-account Update account info.
--register-account Register account key. --register-account Register account key.
--deactivate-account Deactivate the account.
--create-account-key Create an account private key, professional use. --create-account-key Create an account private key, professional use.
--create-domain-key Create an domain private key, professional use. --create-domain-key Create an domain private key, professional use.
--createCSR, -ccsr Create CSR , professional use. --createCSR, -ccsr Create CSR , professional use.
@ -4990,6 +5106,7 @@ Parameters:
--renew-hook Command to be run once for each successfully renewed certificate. --renew-hook Command to be run once for each successfully renewed certificate.
--deploy-hook The hook file to deploy cert --deploy-hook The hook file to deploy cert
--ocsp-must-staple, --ocsp Generate ocsp must Staple extension. --ocsp-must-staple, --ocsp Generate ocsp must Staple extension.
--always-force-new-domain-key Generate new domain key when renewal. Otherwise, the domain key is not changed by default.
--auto-upgrade [0|1] Valid for '--upgrade' command, indicating whether to upgrade automatically in future. --auto-upgrade [0|1] Valid for '--upgrade' command, indicating whether to upgrade automatically in future.
--listen-v4 Force standalone/tls server to listen at ipv4. --listen-v4 Force standalone/tls server to listen at ipv4.
--listen-v6 Force standalone/tls server to listen at ipv6. --listen-v6 Force standalone/tls server to listen at ipv6.
@ -5209,6 +5326,9 @@ _process() {
--registeraccount | --register-account) --registeraccount | --register-account)
_CMD="registeraccount" _CMD="registeraccount"
;; ;;
--deactivate-account)
_CMD="deactivateaccount"
;;
--domain | -d) --domain | -d)
_dvalue="$2" _dvalue="$2"
@ -5470,6 +5590,14 @@ _process() {
--ocsp-must-staple | --ocsp) --ocsp-must-staple | --ocsp)
Le_OCSP_Staple="1" Le_OCSP_Staple="1"
;; ;;
--always-force-new-domain-key)
if [ -z "$2" ] || _startswith "$2" "-"; then
Le_ForceNewDomainKey=1
else
Le_ForceNewDomainKey="$2"
shift
fi
;;
--log | --logfile) --log | --logfile)
_log="1" _log="1"
_logfile="$2" _logfile="$2"
@ -5616,6 +5744,9 @@ _process() {
updateaccount) updateaccount)
updateaccount updateaccount
;; ;;
deactivateaccount)
deactivateaccount
;;
list) list)
list "$_listraw" list "$_listraw"
;; ;;

View File

@ -505,7 +505,42 @@ Ok, let's issue a cert now:
acme.sh --issue --dns dns_nsone -d example.com -d www.example.com acme.sh --issue --dns dns_nsone -d example.com -d www.example.com
``` ```
## 27. Use DreamHost DNS API ## 27. Use DuckDNS.org API
```
export DuckDNS_Token="aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
```
Please note that since DuckDNS uses StartSSL as their cert provider, thus
--insecure must be used when issuing certs:
```
acme.sh --insecure --issue --dns dns_duckdns -d mydomain.duckdns.org
```
Also, DuckDNS uses the domain name as username for recording changing, so the
account file will always store the lastly used domain name.
For issues, please report to https://github.com/raidenii/acme.sh/issues.
## 28. Use Name.com API
You'll need to fill out the form at https://www.name.com/reseller/apply to apply
for API username and token.
```
export Namecom_Username="testuser"
export Namecom_Token="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
```
And now you can issue certs with:
```
acme.sh --issue --dns dns_namecom -d example.com -d www.example.com
```
For issues, please report to https://github.com/raidenii/acme.sh/issues.
## 29. Use DreamHost DNS API
DNS API keys may be created at https://panel.dreamhost.com/?tree=home.api. DNS API keys may be created at https://panel.dreamhost.com/?tree=home.api.
Ensure the created key has add and remove privelages. Ensure the created key has add and remove privelages.

91
dnsapi/dns_duckdns.sh Executable file
View File

@ -0,0 +1,91 @@
#!/usr/bin/env sh
#Created by RaidenII, to use DuckDNS's API to add/remove text records
#06/27/2017
# Currently only support single domain access
# Due to the fact that DuckDNS uses StartSSL as cert provider, --insecure must be used with acme.sh
DuckDNS_API="https://www.duckdns.org/update"
API_Params="domains=$DuckDNS_Domain&token=$DuckDNS_Token"
######## Public functions #####################
#Usage: dns_duckdns_add _acme-challenge.domain.duckdns.org "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_duckdns_add() {
fulldomain=$1
txtvalue=$2
# We'll extract the domain/username from full domain
DuckDNS_Domain=$(echo "$fulldomain" | _lower_case | _egrep_o '.[^.]*.duckdns.org' | cut -d . -f 2)
if [ -z "$DuckDNS_Domain" ]; then
_err "Error extracting the domain."
return 1
fi
if [ -z "$DuckDNS_Token" ]; then
DuckDNS_Token=""
_err "The token for your DuckDNS account is necessary."
_err "You can look it up in your DuckDNS account."
return 1
fi
# Now save the credentials.
_saveaccountconf DuckDNS_Domain "$DuckDNS_Domain"
_saveaccountconf DuckDNS_Token "$DuckDNS_Token"
# Unfortunately, DuckDNS does not seems to support lookup domain through API
# So I assume your credentials (which are your domain and token) are correct
# If something goes wrong, we will get a KO response from DuckDNS
# Now add the TXT record to DuckDNS
_info "Trying to add TXT record"
if _duckdns_rest GET "$API_Params&txt=$txtvalue" && [ "$response" = "OK" ]; then
_info "TXT record has been successfully added to your DuckDNS domain."
_info "Note that all subdomains under this domain uses the same TXT record."
return 0
else
_err "Errors happened during adding the TXT record."
return 1
fi
}
#Usage: fulldomain txtvalue
#Remove the txt record after validation.
dns_duckdns_rm() {
fulldomain=$1
txtvalue=$2
# Now remove the TXT record from DuckDNS
_info "Trying to remove TXT record"
if _duckdns_rest GET "$API_Params&txt=&clear=true" && [ "$response" = "OK" ]; then
_info "TXT record has been successfully removed from your DuckDNS domain."
return 0
else
_err "Errors happened during removing the TXT record."
return 1
fi
}
#################### Private functions below ##################################
#Usage: method URI
_duckdns_rest() {
method=$1
param="$2"
_debug param "$param"
url="$DuckDNS_API?$param"
_debug url "$url"
# DuckDNS uses GET to update domain info
if [ "$method" = "GET" ]; then
response="$(_get "$url")"
else
_err "Unsupported method"
return 1
fi
_debug2 response "$response"
return 0
}

193
dnsapi/dns_namecom.sh Executable file
View File

@ -0,0 +1,193 @@
#!/usr/bin/env sh
#Author: RaidneII
#Created 06/28/2017
#Utilize name.com API to finish dns-01 verifications.
######## Public functions #####################
Namecom_API="https://api.name.com/api"
#Usage: dns_namecom_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_namecom_add() {
fulldomain=$1
txtvalue=$2
# First we need name.com credentials.
if [ -z "$Namecom_Username" ]; then
Namecom_Username=""
_err "Username for name.com is missing."
_err "Please specify that in your environment variable."
return 1
fi
if [ -z "$Namecom_Token" ]; then
Namecom_Token=""
_err "API token for name.com is missing."
_err "Please specify that in your environment variable."
return 1
fi
# Save them in configuration.
_saveaccountconf Namecom_Username "$Namecom_Username"
_saveaccountconf Namecom_Token "$Namecom_Token"
# Login in using API
if ! _namecom_login; then
return 1
fi
# Find domain in domain list.
if ! _namecom_get_root "$fulldomain"; then
_err "Unable to find domain specified."
_namecom_logout
return 1
fi
# Add TXT record.
_namecom_addtxt_json="{\"hostname\":\"$_sub_domain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"ttl\":\"300\",\"priority\":\"10\"}"
if _namecom_rest POST "dns/create/$_domain" "$_namecom_addtxt_json"; then
retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100")
if [ "$retcode" ]; then
_info "Successfully added TXT record, ready for validation."
_namecom_logout
return 0
else
_err "Unable to add the DNS record."
_namecom_logout
return 1
fi
fi
}
#Usage: fulldomain txtvalue
#Remove the txt record after validation.
dns_namecom_rm() {
fulldomain=$1
txtvalue=$2
if ! _namecom_login; then
return 1
fi
# Find domain in domain list.
if ! _namecom_get_root "$fulldomain"; then
_err "Unable to find domain specified."
_namecom_logout
return 1
fi
# Get the record id.
if _namecom_rest GET "dns/list/$_domain"; then
retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100")
if [ "$retcode" ]; then
_record_id=$(printf "%s\n" "$response" | _egrep_o "\"record_id\":\"[0-9]+\",\"name\":\"$fulldomain\",\"type\":\"TXT\"" | cut -d \" -f 4)
_debug record_id "$_record_id"
_info "Successfully retrieved the record id for ACME challenge."
else
_err "Unable to retrieve the record id."
_namecom_logout
return 1
fi
fi
# Remove the DNS record using record id.
_namecom_rmtxt_json="{\"record_id\":\"$_record_id\"}"
if _namecom_rest POST "dns/delete/$_domain" "$_namecom_rmtxt_json"; then
retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100")
if [ "$retcode" ]; then
_info "Successfully removed the TXT record."
_namecom_logout
return 0
else
_err "Unable to remove the DNS record."
_namecom_logout
return 1
fi
fi
}
#################### Private functions below ##################################
_namecom_rest() {
method=$1
param=$2
data=$3
export _H1="Content-Type: application/json"
export _H2="Api-Session-Token: $sessionkey"
if [ "$method" != "GET" ]; then
response="$(_post "$data" "$Namecom_API/$param" "" "$method")"
else
response="$(_get "$Namecom_API/$param")"
fi
if [ "$?" != "0" ]; then
_err "error $param"
return 1
fi
_debug2 response "$response"
return 0
}
_namecom_login() {
namecom_login_json="{\"username\":\"$Namecom_Username\",\"api_token\":\"$Namecom_Token\"}"
if _namecom_rest POST "login" "$namecom_login_json"; then
retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100")
if [ "$retcode" ]; then
_info "Successfully logged in. Fetching session token..."
sessionkey=$(printf "%s\n" "$response" | _egrep_o "\"session_token\":\".+" | cut -d \" -f 4)
if [ ! -z "$sessionkey" ]; then
_debug sessionkey "$sessionkey"
_info "Session key obtained."
else
_err "Unable to get session key."
return 1
fi
else
_err "Logging in failed."
return 1
fi
fi
}
_namecom_logout() {
if _namecom_rest GET "logout"; then
retcode=$(printf "%s\n" "$response" | _egrep_o "\"code\":100")
if [ "$retcode" ]; then
_info "Successfully logged out."
else
_err "Error logging out."
return 1
fi
fi
}
_namecom_get_root() {
domain=$1
i=2
p=1
if ! _namecom_rest GET "domain/list"; then
return 1
fi
# Need to exclude the last field (tld)
numfields=$(echo "$domain" | _egrep_o "\." | wc -l)
while [ $i -le "$numfields" ]; do
host=$(printf "%s" "$domain" | cut -d . -f $i-100)
_debug host "$host"
if [ -z "$host" ]; then
return 1
fi
if _contains "$response" "$host"; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_domain="$host"
return 0
fi
p=$i
i=$(_math "$i" + 1)
done
return 1
}