Unverified Commit dfe80556 authored by lufi42's avatar lufi42 Committed by GitHub
Browse files

Merge branch 'acmesh-official:dev' into dev

parents 6d2ab4d2 6ccf617d
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2] github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username patreon: # Replace with a single Patreon username
open_collective: acmesh open_collective: acmesh
ko_fi: # Replace with a single Ko-fi username ko_fi: neilpang
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username liberapay: # Replace with a single Liberapay username
......
...@@ -25,11 +25,11 @@ jobs: ...@@ -25,11 +25,11 @@ jobs:
CA: "" CA: ""
CA_EMAIL: "" CA_EMAIL: ""
TEST_PREFERRED_CHAIN: (STAGING) Pretend Pear X1 TEST_PREFERRED_CHAIN: (STAGING) Pretend Pear X1
- TEST_ACME_Server: "ZeroSSL.com" #- TEST_ACME_Server: "ZeroSSL.com"
CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA" # CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA"
CA: "ZeroSSL RSA Domain Secure Site CA" # CA: "ZeroSSL RSA Domain Secure Site CA"
CA_EMAIL: "githubtest@acme.sh" # CA_EMAIL: "githubtest@acme.sh"
TEST_PREFERRED_CHAIN: "" # TEST_PREFERRED_CHAIN: ""
runs-on: macos-10.15 runs-on: macos-10.15
env: env:
TEST_LOCAL: 1 TEST_LOCAL: 1
......
...@@ -25,6 +25,7 @@ jobs: ...@@ -25,6 +25,7 @@ jobs:
env: env:
TEST_LOCAL: 1 TEST_LOCAL: 1
TEST_PREFERRED_CHAIN: (STAGING) Pretend Pear X1 TEST_PREFERRED_CHAIN: (STAGING) Pretend Pear X1
TEST_ACME_Server: "LetsEncrypt.org_test"
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v2
- name: Clone acmetest - name: Clone acmetest
......
...@@ -25,11 +25,11 @@ jobs: ...@@ -25,11 +25,11 @@ jobs:
CA: "" CA: ""
CA_EMAIL: "" CA_EMAIL: ""
TEST_PREFERRED_CHAIN: (STAGING) Pretend Pear X1 TEST_PREFERRED_CHAIN: (STAGING) Pretend Pear X1
- TEST_ACME_Server: "ZeroSSL.com" #- TEST_ACME_Server: "ZeroSSL.com"
CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA" # CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA"
CA: "ZeroSSL RSA Domain Secure Site CA" # CA: "ZeroSSL RSA Domain Secure Site CA"
CA_EMAIL: "githubtest@acme.sh" # CA_EMAIL: "githubtest@acme.sh"
TEST_PREFERRED_CHAIN: "" # TEST_PREFERRED_CHAIN: ""
runs-on: macos-latest runs-on: macos-latest
env: env:
TEST_LOCAL: 1 TEST_LOCAL: 1
......
...@@ -25,11 +25,11 @@ jobs: ...@@ -25,11 +25,11 @@ jobs:
CA: "" CA: ""
CA_EMAIL: "" CA_EMAIL: ""
TEST_PREFERRED_CHAIN: (STAGING) Pretend Pear X1 TEST_PREFERRED_CHAIN: (STAGING) Pretend Pear X1
- TEST_ACME_Server: "ZeroSSL.com" #- TEST_ACME_Server: "ZeroSSL.com"
CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA" # CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA"
CA: "ZeroSSL RSA Domain Secure Site CA" # CA: "ZeroSSL RSA Domain Secure Site CA"
CA_EMAIL: "githubtest@acme.sh" # CA_EMAIL: "githubtest@acme.sh"
TEST_PREFERRED_CHAIN: "" # TEST_PREFERRED_CHAIN: ""
runs-on: macos-10.15 runs-on: macos-10.15
env: env:
TEST_LOCAL: 1 TEST_LOCAL: 1
......
...@@ -25,11 +25,11 @@ jobs: ...@@ -25,11 +25,11 @@ jobs:
CA: "" CA: ""
CA_EMAIL: "" CA_EMAIL: ""
TEST_PREFERRED_CHAIN: (STAGING) Pretend Pear X1 TEST_PREFERRED_CHAIN: (STAGING) Pretend Pear X1
- TEST_ACME_Server: "ZeroSSL.com" #- TEST_ACME_Server: "ZeroSSL.com"
CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA" # CA_ECDSA: "ZeroSSL ECC Domain Secure Site CA"
CA: "ZeroSSL RSA Domain Secure Site CA" # CA: "ZeroSSL RSA Domain Secure Site CA"
CA_EMAIL: "githubtest@acme.sh" # CA_EMAIL: "githubtest@acme.sh"
TEST_PREFERRED_CHAIN: "" # TEST_PREFERRED_CHAIN: ""
runs-on: windows-latest runs-on: windows-latest
env: env:
TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }} TEST_ACME_Server: ${{ matrix.TEST_ACME_Server }}
......
...@@ -65,7 +65,8 @@ RUN for verb in help \ ...@@ -65,7 +65,8 @@ 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 \
trap \"echo stop && killall crond && exit 0\" SIGTERM SIGINT \n \ trap \"echo stop && killall crond && exit 0\" SIGTERM SIGINT \n \
crond && while true; do sleep 1; done;\n \ crond && sleep infinity &\n \
wait \n \
else \n \ else \n \
exec -- \"\$@\"\n \ exec -- \"\$@\"\n \
fi" >/entry.sh && chmod +x /entry.sh fi" >/entry.sh && chmod +x /entry.sh
......
...@@ -95,6 +95,7 @@ https://github.com/acmesh-official/acmetest ...@@ -95,6 +95,7 @@ https://github.com/acmesh-official/acmetest
- Letsencrypt.org CA - Letsencrypt.org CA
- [BuyPass.com CA](https://github.com/acmesh-official/acme.sh/wiki/BuyPass.com-CA) - [BuyPass.com CA](https://github.com/acmesh-official/acme.sh/wiki/BuyPass.com-CA)
- [SSL.com CA](https://github.com/acmesh-official/acme.sh/wiki/SSL.com-CA) - [SSL.com CA](https://github.com/acmesh-official/acme.sh/wiki/SSL.com-CA)
- [Google.com Public CA](https://github.com/acmesh-official/acme.sh/wiki/Google-Public-CA)
- [Pebble strict Mode](https://github.com/letsencrypt/pebble) - [Pebble strict Mode](https://github.com/letsencrypt/pebble)
- Any other [RFC8555](https://tools.ietf.org/html/rfc8555)-compliant CA - Any other [RFC8555](https://tools.ietf.org/html/rfc8555)-compliant CA
......
#!/usr/bin/env sh #!/usr/bin/env sh
VER=3.0.3 VER=3.0.5
PROJECT_NAME="acme.sh" PROJECT_NAME="acme.sh"
...@@ -20,8 +20,6 @@ _SUB_FOLDER_DEPLOY="deploy" ...@@ -20,8 +20,6 @@ _SUB_FOLDER_DEPLOY="deploy"
_SUB_FOLDERS="$_SUB_FOLDER_DNSAPI $_SUB_FOLDER_DEPLOY $_SUB_FOLDER_NOTIFY" _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="https://acme-v02.api.letsencrypt.org/directory"
CA_LETSENCRYPT_V2_TEST="https://acme-staging-v02.api.letsencrypt.org/directory" CA_LETSENCRYPT_V2_TEST="https://acme-staging-v02.api.letsencrypt.org/directory"
...@@ -34,6 +32,9 @@ _ZERO_EAB_ENDPOINT="https://api.zerossl.com/acme/eab-credentials-email" ...@@ -34,6 +32,9 @@ _ZERO_EAB_ENDPOINT="https://api.zerossl.com/acme/eab-credentials-email"
CA_SSLCOM_RSA="https://acme.ssl.com/sslcom-dv-rsa" CA_SSLCOM_RSA="https://acme.ssl.com/sslcom-dv-rsa"
CA_SSLCOM_ECC="https://acme.ssl.com/sslcom-dv-ecc" CA_SSLCOM_ECC="https://acme.ssl.com/sslcom-dv-ecc"
CA_GOOGLE="https://dv.acme-v02.api.pki.goog/directory"
CA_GOOGLE_TEST="https://dv.acme-v02.test-api.pki.goog/directory"
DEFAULT_CA=$CA_ZEROSSL DEFAULT_CA=$CA_ZEROSSL
DEFAULT_STAGING_CA=$CA_LETSENCRYPT_V2_TEST DEFAULT_STAGING_CA=$CA_LETSENCRYPT_V2_TEST
...@@ -44,9 +45,11 @@ LetsEncrypt.org_test,letsencrypt_test,letsencrypttest ...@@ -44,9 +45,11 @@ LetsEncrypt.org_test,letsencrypt_test,letsencrypttest
BuyPass.com,buypass BuyPass.com,buypass
BuyPass.com_test,buypass_test,buypasstest BuyPass.com_test,buypass_test,buypasstest
SSL.com,sslcom SSL.com,sslcom
Google.com,google
Google.com_test,googletest,google_test
" "
CA_SERVERS="$CA_ZEROSSL,$CA_LETSENCRYPT_V2,$CA_LETSENCRYPT_V2_TEST,$CA_BUYPASS,$CA_BUYPASS_TEST,$CA_SSLCOM_RSA" CA_SERVERS="$CA_ZEROSSL,$CA_LETSENCRYPT_V2,$CA_LETSENCRYPT_V2_TEST,$CA_BUYPASS,$CA_BUYPASS_TEST,$CA_SSLCOM_RSA,$CA_GOOGLE,$CA_GOOGLE_TEST"
DEFAULT_USER_AGENT="$PROJECT_NAME/$VER ($PROJECT)" DEFAULT_USER_AGENT="$PROJECT_NAME/$VER ($PROJECT)"
...@@ -172,6 +175,8 @@ _SERVER_WIKI="https://github.com/acmesh-official/acme.sh/wiki/Server" ...@@ -172,6 +175,8 @@ _SERVER_WIKI="https://github.com/acmesh-official/acme.sh/wiki/Server"
_PREFERRED_CHAIN_WIKI="https://github.com/acmesh-official/acme.sh/wiki/Preferred-Chain" _PREFERRED_CHAIN_WIKI="https://github.com/acmesh-official/acme.sh/wiki/Preferred-Chain"
_VALIDITY_WIKI="https://github.com/acmesh-official/acme.sh/wiki/Validity"
_DNSCHECK_WIKI="https://github.com/acmesh-official/acme.sh/wiki/dnscheck" _DNSCHECK_WIKI="https://github.com/acmesh-official/acme.sh/wiki/dnscheck"
_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."
...@@ -976,9 +981,9 @@ _base64() { ...@@ -976,9 +981,9 @@ _base64() {
#Usage: multiline #Usage: multiline
_dbase64() { _dbase64() {
if [ "$1" ]; then if [ "$1" ]; then
${ACME_OPENSSL_BIN:-openssl} base64 -d -A
else
${ACME_OPENSSL_BIN:-openssl} base64 -d ${ACME_OPENSSL_BIN:-openssl} base64 -d
else
${ACME_OPENSSL_BIN:-openssl} base64 -d -A
fi fi
} }
...@@ -1598,23 +1603,22 @@ _durl_replace_base64() { ...@@ -1598,23 +1603,22 @@ _durl_replace_base64() {
_time2str() { _time2str() {
#BSD #BSD
if date -u -r "$1" 2>/dev/null; then if date -u -r "$1" -j "+%Y-%m-%dT%H:%M:%SZ" 2>/dev/null; then
return return
fi fi
#Linux #Linux
if date -u -d@"$1" 2>/dev/null; then if date -u --date=@"$1" "+%Y-%m-%dT%H:%M:%SZ" 2>/dev/null; then
return return
fi fi
#Solaris #Solaris
if _exists adb; then if printf "%(%Y-%m-%dT%H:%M:%SZ)T\n" $1 2>/dev/null; then
_t_s_a=$(echo "0t${1}=Y" | adb) return
echo "$_t_s_a"
fi fi
#Busybox #Busybox
if echo "$1" | awk '{ print strftime("%c", $0); }' 2>/dev/null; then if echo "$1" | awk '{ print strftime("%Y-%m-%dT%H:%M:%SZ", $0); }' 2>/dev/null; then
return return
fi fi
} }
...@@ -1773,6 +1777,27 @@ _time() { ...@@ -1773,6 +1777,27 @@ _time() {
date -u "+%s" date -u "+%s"
} }
#support 2 formats:
# 2022-04-01 08:10:33 to 1648800633
#or 2022-04-01T08:10:33Z to 1648800633
_date2time() {
#Linux
if date -u -d "$(echo "$1" | tr -d "Z" | tr "T" ' ')" +"%s" 2>/dev/null; then
return
fi
#Solaris
if gdate -u -d "$(echo "$1" | tr -d "Z" | tr "T" ' ')" +"%s" 2>/dev/null; then
return
fi
#Mac/BSD
if date -u -j -f "%Y-%m-%d %H:%M:%S" "$(echo "$1" | tr -d "Z" | tr "T" ' ')" +"%s" 2>/dev/null; then
return
fi
_err "Can not parse _date2time $1"
return 1
}
_utc_date() { _utc_date() {
date -u "+%Y-%m-%d %H:%M:%S" date -u "+%Y-%m-%d %H:%M:%S"
} }
...@@ -1845,7 +1870,9 @@ _inithttp() { ...@@ -1845,7 +1870,9 @@ _inithttp() {
_ACME_WGET="$_ACME_WGET --max-redirect 0 " _ACME_WGET="$_ACME_WGET --max-redirect 0 "
fi fi
if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then
_ACME_WGET="$_ACME_WGET -d " if [ "$_ACME_WGET" ] && _contains "$($_ACME_WGET --help 2>&1)" "--debug"; then
_ACME_WGET="$_ACME_WGET -d "
fi
fi fi
if [ "$CA_PATH" ]; then if [ "$CA_PATH" ]; then
_ACME_WGET="$_ACME_WGET --ca-directory=$CA_PATH " _ACME_WGET="$_ACME_WGET --ca-directory=$CA_PATH "
...@@ -2662,6 +2689,12 @@ _initAPI() { ...@@ -2662,6 +2689,12 @@ _initAPI() {
return 1 return 1
} }
_clearCA() {
export CA_CONF=
export ACCOUNT_KEY_PATH=
export ACCOUNT_JSON_PATH=
}
#[domain] [keylength or isEcc flag] #[domain] [keylength or isEcc flag]
_initpath() { _initpath() {
domain="$1" domain="$1"
...@@ -3751,7 +3784,7 @@ updateaccount() { ...@@ -3751,7 +3784,7 @@ updateaccount() {
_email="$(_getAccountEmail)" _email="$(_getAccountEmail)"
if [ "$ACCOUNT_EMAIL" ]; then if [ "$_email" ]; then
updjson='{"contact": ["mailto:'$_email'"]}' updjson='{"contact": ["mailto:'$_email'"]}'
else else
updjson='{"contact": []}' updjson='{"contact": []}'
...@@ -3761,7 +3794,7 @@ updateaccount() { ...@@ -3761,7 +3794,7 @@ updateaccount() {
if [ "$code" = '200' ]; then if [ "$code" = '200' ]; then
echo "$response" >"$ACCOUNT_JSON_PATH" echo "$response" >"$ACCOUNT_JSON_PATH"
_info "account update success for $_accUri." _info "Account update success for $_accUri."
else else
_info "Error. The account was not updated." _info "Error. The account was not updated."
return 1 return 1
...@@ -4200,6 +4233,40 @@ _getIdType() { ...@@ -4200,6 +4233,40 @@ _getIdType() {
fi fi
} }
# beginTime dateTo
# beginTime is full string format("2022-04-01T08:10:33Z"), beginTime can be empty, to use current time
# dateTo can be ether in full string format("2022-04-01T08:10:33Z") or in delta format(+5d or +20h)
_convertValidaty() {
_beginTime="$1"
_dateTo="$2"
_debug2 "_beginTime" "$_beginTime"
_debug2 "_dateTo" "$_dateTo"
if _startswith "$_dateTo" "+"; then
_v_begin=$(_time)
if [ "$_beginTime" ]; then
_v_begin="$(_date2time "$_beginTime")"
fi
_debug2 "_v_begin" "$_v_begin"
if _endswith "$_dateTo" "h"; then
_v_end=$(_math "$_v_begin + 60 * 60 * $(echo "$_dateTo" | tr -d '+h')")
elif _endswith "$_dateTo" "d"; then
_v_end=$(_math "$_v_begin + 60 * 60 * 24 * $(echo "$_dateTo" | tr -d '+d')")
else
_err "Not recognized format for _dateTo: $_dateTo"
return 1
fi
_debug2 "_v_end" "$_v_end"
_time2str "$_v_end"
else
if [ "$(_time)" -gt "$(_date2time "$_dateTo")" ]; then
_err "The validaty to is in the past: _dateTo = $_dateTo"
return 1
fi
echo "$_dateTo"
fi
}
#webroot, domain domainlist keylength #webroot, domain domainlist keylength
issue() { issue() {
if [ -z "$2" ]; then if [ -z "$2" ]; then
...@@ -4233,6 +4300,8 @@ issue() { ...@@ -4233,6 +4300,8 @@ issue() {
_local_addr="${13}" _local_addr="${13}"
_challenge_alias="${14}" _challenge_alias="${14}"
_preferred_chain="${15}" _preferred_chain="${15}"
_valid_from="${16}"
_valid_to="${17}"
if [ -z "$_ACME_IS_RENEW" ]; then if [ -z "$_ACME_IS_RENEW" ]; then
_initpath "$_main_domain" "$_key_length" _initpath "$_main_domain" "$_key_length"
...@@ -4252,11 +4321,24 @@ issue() { ...@@ -4252,11 +4321,24 @@ issue() {
Le_NextRenewTime=$(_readdomainconf Le_NextRenewTime) Le_NextRenewTime=$(_readdomainconf Le_NextRenewTime)
_debug Le_NextRenewTime "$Le_NextRenewTime" _debug Le_NextRenewTime "$Le_NextRenewTime"
if [ -z "$FORCE" ] && [ "$Le_NextRenewTime" ] && [ "$(_time)" -lt "$Le_NextRenewTime" ]; then if [ -z "$FORCE" ] && [ "$Le_NextRenewTime" ] && [ "$(_time)" -lt "$Le_NextRenewTime" ]; then
_valid_to_saved=$(_readdomainconf Le_Valid_to)
if [ "$_valid_to_saved" ] && ! _startswith "$_valid_to_saved" "+"; then
_info "The domain is set to be valid to: $_valid_to_saved"
_info "It can not be renewed automatically"
_info "See: $_VALIDITY_WIKI"
return $RENEW_SKIP
fi
_saved_domain=$(_readdomainconf Le_Domain) _saved_domain=$(_readdomainconf Le_Domain)
_debug _saved_domain "$_saved_domain" _debug _saved_domain "$_saved_domain"
_saved_alt=$(_readdomainconf Le_Alt) _saved_alt=$(_readdomainconf Le_Alt)
_debug _saved_alt "$_saved_alt" _debug _saved_alt "$_saved_alt"
if [ "$_saved_domain,$_saved_alt" = "$_main_domain,$_alt_domains" ]; then _normized_saved_domains="$(echo "$_saved_domain,$_saved_alt" | tr "," "\n" | sort | tr '\n' ',')"
_debug _normized_saved_domains "$_normized_saved_domains"
_normized_domains="$(echo "$_main_domain,$_alt_domains" | tr "," "\n" | sort | tr '\n' ',')"
_debug _normized_domains "$_normized_domains"
if [ "$_normized_saved_domains" = "$_normized_domains" ]; then
_info "Domains not changed." _info "Domains not changed."
_info "Skip, Next renewal time is: $(__green "$(_readdomainconf Le_NextRenewTimeStr)")" _info "Skip, Next renewal time is: $(__green "$(_readdomainconf Le_NextRenewTimeStr)")"
_info "Add '$(__red '--force')' to force to renew." _info "Add '$(__red '--force')' to force to renew."
...@@ -4304,10 +4386,6 @@ issue() { ...@@ -4304,10 +4386,6 @@ issue() {
_alt_domains="" _alt_domains=""
fi fi
if [ "$_key_length" = "$NO_VALUE" ]; then
_key_length=""
fi
if ! _on_before_issue "$_web_roots" "$_main_domain" "$_alt_domains" "$_pre_hook" "$_local_addr"; then if ! _on_before_issue "$_web_roots" "$_main_domain" "$_alt_domains" "$_pre_hook" "$_local_addr"; then
_err "_on_before_issue." _err "_on_before_issue."
return 1 return 1
...@@ -4328,7 +4406,13 @@ issue() { ...@@ -4328,7 +4406,13 @@ issue() {
if [ -f "$CSR_PATH" ] && [ ! -f "$CERT_KEY_PATH" ]; then if [ -f "$CSR_PATH" ] && [ ! -f "$CERT_KEY_PATH" ]; then
_info "Signing from existing CSR." _info "Signing from existing CSR."
else else
# When renewing from an old version, the empty Le_Keylength means 2048.
# Note, do not use DEFAULT_DOMAIN_KEY_LENGTH as that value may change over
# time but an empty value implies 2048 specifically.
_key=$(_readdomainconf Le_Keylength) _key=$(_readdomainconf Le_Keylength)
if [ -z "$_key" ]; then
_key=2048
fi
_debug "Read key length:$_key" _debug "Read key length:$_key"
if [ ! -f "$CERT_KEY_PATH" ] || [ "$_key_length" != "$_key" ] || [ "$Le_ForceNewDomainKey" = "1" ]; 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
...@@ -4368,12 +4452,52 @@ issue() { ...@@ -4368,12 +4452,52 @@ issue() {
_identifiers="$_identifiers,{\"type\":\"$(_getIdType "$d")\",\"value\":\"$(_idn "$d")\"}" _identifiers="$_identifiers,{\"type\":\"$(_getIdType "$d")\",\"value\":\"$(_idn "$d")\"}"
done done
_debug2 _identifiers "$_identifiers" _debug2 _identifiers "$_identifiers"
if ! _send_signed_request "$ACME_NEW_ORDER" "{\"identifiers\": [$_identifiers]}"; then _notBefore=""
_notAfter=""
if [ "$_valid_from" ]; then
_savedomainconf "Le_Valid_From" "$_valid_from"
_debug2 "_valid_from" "$_valid_from"
_notBefore="$(_convertValidaty "" "$_valid_from")"
if [ "$?" != "0" ]; then
_err "Can not parse _valid_from: $_valid_from"
return 1
fi
if [ "$(_time)" -gt "$(_date2time "$_notBefore")" ]; then
_notBefore=""
fi
else
_cleardomainconf "Le_Valid_From"
fi
_debug2 _notBefore "$_notBefore"
if [ "$_valid_to" ]; then
_debug2 "_valid_to" "$_valid_to"
_savedomainconf "Le_Valid_To" "$_valid_to"
_notAfter="$(_convertValidaty "$_notBefore" "$_valid_to")"
if [ "$?" != "0" ]; then
_err "Can not parse _valid_to: $_valid_to"
return 1
fi
else
_cleardomainconf "Le_Valid_To"
fi
_debug2 "_notAfter" "$_notAfter"
_newOrderObj="{\"identifiers\": [$_identifiers]"
if [ "$_notBefore" ]; then
_newOrderObj="$_newOrderObj,\"notBefore\": \"$_notBefore\""
fi
if [ "$_notAfter" ]; then
_newOrderObj="$_newOrderObj,\"notAfter\": \"$_notAfter\""
fi
if ! _send_signed_request "$ACME_NEW_ORDER" "$_newOrderObj}"; then
_err "Create new order error." _err "Create new order error."
_clearup _clearup
_on_issue_err "$_post_hook" _on_issue_err "$_post_hook"
return 1 return 1
fi fi
Le_LinkOrder="$(echo "$responseHeaders" | grep -i '^Location.*$' | _tail_n 1 | tr -d "\r\n " | cut -d ":" -f 2-)" Le_LinkOrder="$(echo "$responseHeaders" | grep -i '^Location.*$' | _tail_n 1 | tr -d "\r\n " | cut -d ":" -f 2-)"
_debug Le_LinkOrder "$Le_LinkOrder" _debug Le_LinkOrder "$Le_LinkOrder"
Le_OrderFinalize="$(echo "$response" | _egrep_o '"finalize" *: *"[^"]*"' | cut -d '"' -f 4)" Le_OrderFinalize="$(echo "$response" | _egrep_o '"finalize" *: *"[^"]*"' | cut -d '"' -f 4)"
...@@ -4412,7 +4536,7 @@ issue() { ...@@ -4412,7 +4536,7 @@ issue() {
response="$(echo "$response" | _normalizeJson)" response="$(echo "$response" | _normalizeJson)"
_debug2 response "$response" _debug2 response "$response"
_d="$(echo "$response" | _egrep_o '"value" *: *"[^"]*"' | cut -d : -f 2 | tr -d ' "')" _d="$(echo "$response" | _egrep_o '"value" *: *"[^"]*"' | cut -d : -f 2- | tr -d ' "')"
if _contains "$response" "\"wildcard\" *: *true"; then if _contains "$response" "\"wildcard\" *: *true"; then
_d="*.$_d" _d="*.$_d"
fi fi
...@@ -4562,6 +4686,7 @@ $_authorizations_map" ...@@ -4562,6 +4686,7 @@ $_authorizations_map"
_dns_root_d="$(echo "$_dns_root_d" | sed 's/*.//')" _dns_root_d="$(echo "$_dns_root_d" | sed 's/*.//')"
fi fi
_d_alias="$(_getfield "$_challenge_alias" "$_alias_index")" _d_alias="$(_getfield "$_challenge_alias" "$_alias_index")"
test "$_d_alias" = "$NO_VALUE" && _d_alias=""
_alias_index="$(_math "$_alias_index" + 1)" _alias_index="$(_math "$_alias_index" + 1)"
_debug "_d_alias" "$_d_alias" _debug "_d_alias" "$_d_alias"
if [ "$_d_alias" ]; then if [ "$_d_alias" ]; then
...@@ -4856,7 +4981,7 @@ $_authorizations_map" ...@@ -4856,7 +4981,7 @@ $_authorizations_map"
return 1 return 1
fi fi
_debug "sleep 2 secs to verify again" _debug "sleep 2 secs to verify again"
sleep 2 _sleep 2
_debug "checking" _debug "checking"
_send_signed_request "$uri" _send_signed_request "$uri"
...@@ -5033,7 +5158,7 @@ $_authorizations_map" ...@@ -5033,7 +5158,7 @@ $_authorizations_map"
Le_CertCreateTime=$(_time) Le_CertCreateTime=$(_time)
_savedomainconf "Le_CertCreateTime" "$Le_CertCreateTime" _savedomainconf "Le_CertCreateTime" "$Le_CertCreateTime"
Le_CertCreateTimeStr=$(date -u) Le_CertCreateTimeStr=$(_time2str "$Le_CertCreateTime")
_savedomainconf "Le_CertCreateTimeStr" "$Le_CertCreateTimeStr" _savedomainconf "Le_CertCreateTimeStr" "$Le_CertCreateTimeStr"
if [ -z "$Le_RenewalDays" ] || [ "$Le_RenewalDays" -lt "0" ]; then if [ -z "$Le_RenewalDays" ] || [ "$Le_RenewalDays" -lt "0" ]; then
...@@ -5073,13 +5198,20 @@ $_authorizations_map" ...@@ -5073,13 +5198,20 @@ $_authorizations_map"
else else
_cleardomainconf Le_ForceNewDomainKey _cleardomainconf Le_ForceNewDomainKey
fi fi
if [ "$_notAfter" ]; then
Le_NextRenewTime=$(_math "$Le_CertCreateTime" + "$Le_RenewalDays" \* 24 \* 60 \* 60) Le_NextRenewTime=$(_date2time "$_notAfter")
Le_NextRenewTimeStr="$_notAfter"
Le_NextRenewTimeStr=$(_time2str "$Le_NextRenewTime") if [ "$_valid_to" ] && ! _startswith "$_valid_to" "+"; then
_info "The domain is set to be valid to: $_valid_to"
_info "It can not be renewed automatically"
_info "See: $_VALIDITY_WIKI"
fi
else
Le_NextRenewTime=$(_math "$Le_CertCreateTime" + "$Le_RenewalDays" \* 24 \* 60 \* 60)
Le_NextRenewTimeStr=$(_time2str "$Le_NextRenewTime")
Le_NextRenewTime=$(_math "$Le_NextRenewTime" - 86400)
fi
_savedomainconf "Le_NextRenewTimeStr" "$Le_NextRenewTimeStr" _savedomainconf "Le_NextRenewTimeStr" "$Le_NextRenewTimeStr"
Le_NextRenewTime=$(_math "$Le_NextRenewTime" - 86400)
_savedomainconf "Le_NextRenewTime" "$Le_NextRenewTime" _savedomainconf "Le_NextRenewTime" "$Le_NextRenewTime"
if [ "$_real_cert$_real_key$_real_ca$_reload_cmd$_real_fullchain" ]; then if [ "$_real_cert$_real_key$_real_ca$_reload_cmd$_real_fullchain" ]; then
...@@ -5115,17 +5247,20 @@ _split_cert_chain() { ...@@ -5115,17 +5247,20 @@ _split_cert_chain() {
fi fi
} }
#domain [isEcc] #domain [isEcc] [server]
renew() { renew() {
Le_Domain="$1" Le_Domain="$1"
if [ -z "$Le_Domain" ]; then if [ -z "$Le_Domain" ]; then
_usage "Usage: $PROJECT_ENTRY --renew --domain <domain.tld> [--ecc]" _usage "Usage: $PROJECT_ENTRY --renew --domain <domain.tld> [--ecc] [--server server]"
return 1 return 1
fi fi
_isEcc="$2" _isEcc="$2"
_renewServer="$3"
_debug "_renewServer" "$_renewServer"
_initpath "$Le_Domain" "$_isEcc" _initpath "$Le_Domain" "$_isEcc"
_set_level=${NOTIFY_LEVEL:-$NOTIFY_LEVEL_DEFAULT} _set_level=${NOTIFY_LEVEL:-$NOTIFY_LEVEL_DEFAULT}
_info "$(__green "Renew: '$Le_Domain'")" _info "$(__green "Renew: '$Le_Domain'")"
if [ ! -f "$DOMAIN_CONF" ]; then if [ ! -f "$DOMAIN_CONF" ]; then
...@@ -5139,24 +5274,34 @@ renew() { ...@@ -5139,24 +5274,34 @@ renew() {
. "$DOMAIN_CONF" . "$DOMAIN_CONF"
_debug Le_API "$Le_API" _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, case "$Le_API" in
#so, we force to use letsencrypt server "$CA_LETSENCRYPT_V2_TEST")
_info "Switching back to $CA_LETSENCRYPT_V2"
Le_API="$CA_LETSENCRYPT_V2" Le_API="$CA_LETSENCRYPT_V2"
fi ;;
"$CA_BUYPASS_TEST")
_info "Switching back to $CA_BUYPASS"
Le_API="$CA_BUYPASS"
;;
"$CA_GOOGLE_TEST")
_info "Switching back to $CA_GOOGLE"
Le_API="$CA_GOOGLE"
;;
esac
if [ "$Le_API" ]; then if [ "$_server" ]; then
if [ "$Le_API" != "$ACME_DIRECTORY" ]; then Le_API="$_server"
_clearAPI
fi
export ACME_DIRECTORY="$Le_API"
#reload ca configs
ACCOUNT_KEY_PATH=""
ACCOUNT_JSON_PATH=""
CA_CONF=""
_debug3 "initpath again."
_initpath "$Le_Domain" "$_isEcc"
fi 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 if [ -z "$FORCE" ] && [ "$Le_NextRenewTime" ] && [ "$(_time)" -lt "$Le_NextRenewTime" ]; then
_info "Skip, Next renewal time is: $(__green "$Le_NextRenewTimeStr")" _info "Skip, Next renewal time is: $(__green "$Le_NextRenewTimeStr")"
...@@ -5180,7 +5325,14 @@ renew() { ...@@ -5180,7 +5325,14 @@ renew() {
Le_PostHook="$(_readdomainconf Le_PostHook)" Le_PostHook="$(_readdomainconf Le_PostHook)"
Le_RenewHook="$(_readdomainconf Le_RenewHook)" Le_RenewHook="$(_readdomainconf Le_RenewHook)"
Le_Preferred_Chain="$(_readdomainconf Le_Preferred_Chain)" Le_Preferred_Chain="$(_readdomainconf Le_Preferred_Chain)"
issue "$Le_Webroot" "$Le_Domain" "$Le_Alt" "$Le_Keylength" "$Le_RealCertPath" "$Le_RealKeyPath" "$Le_RealCACertPath" "$Le_ReloadCmd" "$Le_RealFullChainPath" "$Le_PreHook" "$Le_PostHook" "$Le_RenewHook" "$Le_LocalAddress" "$Le_ChallengeAlias" "$Le_Preferred_Chain" # When renewing from an old version, the empty Le_Keylength means 2048.
# Note, do not use DEFAULT_DOMAIN_KEY_LENGTH as that value may change over
# time but an empty value implies 2048 specifically.
Le_Keylength="$(_readdomainconf Le_Keylength)"
if [ -z "$Le_Keylength" ]; then
Le_Keylength=2048
fi
issue "$Le_Webroot" "$Le_Domain" "$Le_Alt" "$Le_Keylength" "$Le_RealCertPath" "$Le_RealKeyPath" "$Le_RealCACertPath" "$Le_ReloadCmd" "$Le_RealFullChainPath" "$Le_PreHook" "$Le_PostHook" "$Le_RenewHook" "$Le_LocalAddress" "$Le_ChallengeAlias" "$Le_Preferred_Chain" "$Le_Valid_From" "$Le_Valid_To"
res="$?" res="$?"
if [ "$res" != "0" ]; then if [ "$res" != "0" ]; then
return "$res" return "$res"
...@@ -5207,11 +5359,16 @@ renew() { ...@@ -5207,11 +5359,16 @@ renew() {
return "$res" return "$res"
} }
#renewAll [stopRenewOnError] #renewAll [stopRenewOnError] [server]
renewAll() { renewAll() {
_initpath _initpath
_clearCA
_stopRenewOnError="$1" _stopRenewOnError="$1"
_debug "_stopRenewOnError" "$_stopRenewOnError" _debug "_stopRenewOnError" "$_stopRenewOnError"
_server="$2"
_debug "_server" "$_server"
_ret="0" _ret="0"
_success_msg="" _success_msg=""
_error_msg="" _error_msg=""
...@@ -5234,7 +5391,7 @@ renewAll() { ...@@ -5234,7 +5391,7 @@ renewAll() {
_isEcc=$(echo "$d" | cut -d "$ECC_SEP" -f 2) _isEcc=$(echo "$d" | cut -d "$ECC_SEP" -f 2)
d=$(echo "$d" | cut -d "$ECC_SEP" -f 1) d=$(echo "$d" | cut -d "$ECC_SEP" -f 1)
fi fi
renew "$d" "$_isEcc" renew "$d" "$_isEcc" "$_server"
) )
rc="$?" rc="$?"
_debug "Return code: $rc" _debug "Return code: $rc"
...@@ -5400,10 +5557,13 @@ showcsr() { ...@@ -5400,10 +5557,13 @@ showcsr() {
_initpath _initpath
_csrsubj=$(_readSubjectFromCSR "$_csrfile") _csrsubj=$(_readSubjectFromCSR "$_csrfile")
if [ "$?" != "0" ] || [ -z "$_csrsubj" ]; then if [ "$?" != "0" ]; then
_err "Can not read subject from csr: $_csrfile" _err "Can not read subject from csr: $_csrfile"
return 1 return 1
fi fi
if [ -z "$_csrsubj" ]; then
_info "The Subject is empty"
fi
_info "Subject=$_csrsubj" _info "Subject=$_csrsubj"
...@@ -5592,7 +5752,9 @@ _installcert() { ...@@ -5592,7 +5752,9 @@ _installcert() {
if [ -f "$_real_cert" ] && [ ! "$_ACME_IS_RENEW" ]; then if [ -f "$_real_cert" ] && [ ! "$_ACME_IS_RENEW" ]; then
cp "$_real_cert" "$_backup_path/cert.bak" cp "$_real_cert" "$_backup_path/cert.bak"
fi fi
cat "$CERT_PATH" >"$_real_cert" || return 1 if [ "$CERT_PATH" != "$_real_cert" ]; then
cat "$CERT_PATH" >"$_real_cert" || return 1
fi
fi fi
if [ "$_real_ca" ]; then if [ "$_real_ca" ]; then
...@@ -5604,7 +5766,9 @@ _installcert() { ...@@ -5604,7 +5766,9 @@ _installcert() {
if [ -f "$_real_ca" ] && [ ! "$_ACME_IS_RENEW" ]; then if [ -f "$_real_ca" ] && [ ! "$_ACME_IS_RENEW" ]; then
cp "$_real_ca" "$_backup_path/ca.bak" cp "$_real_ca" "$_backup_path/ca.bak"
fi fi
cat "$CA_CERT_PATH" >"$_real_ca" || return 1 if [ "$CA_CERT_PATH" != "$_real_ca" ]; then
cat "$CA_CERT_PATH" >"$_real_ca" || return 1
fi
fi fi
fi fi
...@@ -5613,12 +5777,14 @@ _installcert() { ...@@ -5613,12 +5777,14 @@ _installcert() {
if [ -f "$_real_key" ] && [ ! "$_ACME_IS_RENEW" ]; then if [ -f "$_real_key" ] && [ ! "$_ACME_IS_RENEW" ]; then
cp "$_real_key" "$_backup_path/key.bak" cp "$_real_key" "$_backup_path/key.bak"
fi fi
if [ -f "$_real_key" ]; then if [ "$CERT_KEY_PATH" != "$_real_key" ]; then
cat "$CERT_KEY_PATH" >"$_real_key" || return 1 if [ -f "$_real_key" ]; then
else cat "$CERT_KEY_PATH" >"$_real_key" || return 1
touch "$_real_key" || return 1 else
chmod 600 "$_real_key" touch "$_real_key" || return 1
cat "$CERT_KEY_PATH" >"$_real_key" || return 1 chmod 600 "$_real_key"
cat "$CERT_KEY_PATH" >"$_real_key" || return 1
fi
fi fi
fi fi
...@@ -5627,7 +5793,9 @@ _installcert() { ...@@ -5627,7 +5793,9 @@ _installcert() {
if [ -f "$_real_fullchain" ] && [ ! "$_ACME_IS_RENEW" ]; then if [ -f "$_real_fullchain" ] && [ ! "$_ACME_IS_RENEW" ]; then
cp "$_real_fullchain" "$_backup_path/fullchain.bak" cp "$_real_fullchain" "$_backup_path/fullchain.bak"
fi fi
cat "$CERT_FULLCHAIN_PATH" >"$_real_fullchain" || return 1 if [ "$_real_fullchain" != "$CERT_FULLCHAIN_PATH" ]; then
cat "$CERT_FULLCHAIN_PATH" >"$_real_fullchain" || return 1
fi
fi fi
if [ "$_reload_cmd" ]; then if [ "$_reload_cmd" ]; then
...@@ -6616,6 +6784,11 @@ Parameters: ...@@ -6616,6 +6784,11 @@ Parameters:
If no match, the default offered chain will be used. (default: empty) If no match, the default offered chain will be used. (default: empty)
See: $_PREFERRED_CHAIN_WIKI See: $_PREFERRED_CHAIN_WIKI
--valid-to <date-time> Request the NotAfter field of the cert.
See: $_VALIDITY_WIKI
--valid-from <date-time> Request the NotBefore field of the cert.
See: $_VALIDITY_WIKI
-f, --force Force install, force cert renewal or override sudo restrictions. -f, --force Force install, force cert renewal or override sudo restrictions.
--staging, --test Use staging server, for testing. --staging, --test Use staging server, for testing.
--debug [0|1|2|3] Output debug info. Defaults to 1 if argument is omitted. --debug [0|1|2|3] Output debug info. Defaults to 1 if argument is omitted.
...@@ -6807,6 +6980,10 @@ _processAccountConf() { ...@@ -6807,6 +6980,10 @@ _processAccountConf() {
} }
_checkSudo() { _checkSudo() {
if [ -z "__INTERACTIVE" ]; then
#don't check if it's not in an interactive shell
return 0
fi
if [ "$SUDO_GID" ] && [ "$SUDO_COMMAND" ] && [ "$SUDO_USER" ] && [ "$SUDO_UID" ]; then if [ "$SUDO_GID" ] && [ "$SUDO_COMMAND" ] && [ "$SUDO_USER" ] && [ "$SUDO_UID" ]; then
if [ "$SUDO_USER" = "root" ] && [ "$SUDO_UID" = "0" ]; then if [ "$SUDO_USER" = "root" ] && [ "$SUDO_UID" = "0" ]; then
#it's root using sudo, no matter it's using sudo or not, just fine #it's root using sudo, no matter it's using sudo or not, just fine
...@@ -6928,8 +7105,8 @@ _process() { ...@@ -6928,8 +7105,8 @@ _process() {
_altdomains="$NO_VALUE" _altdomains="$NO_VALUE"
_webroot="" _webroot=""
_challenge_alias="" _challenge_alias=""
_keylength="" _keylength="$DEFAULT_DOMAIN_KEY_LENGTH"
_accountkeylength="" _accountkeylength="$DEFAULT_ACCOUNT_KEY_LENGTH"
_cert_file="" _cert_file=""
_key_file="" _key_file=""
_ca_file="" _ca_file=""
...@@ -6976,6 +7153,8 @@ _process() { ...@@ -6976,6 +7153,8 @@ _process() {
_eab_kid="" _eab_kid=""
_eab_hmac_key="" _eab_hmac_key=""
_preferred_chain="" _preferred_chain=""
_valid_from=""
_valid_to=""
while [ ${#} -gt 0 ]; do while [ ${#} -gt 0 ]; do
case "${1}" in case "${1}" in
...@@ -7283,6 +7462,14 @@ _process() { ...@@ -7283,6 +7462,14 @@ _process() {
Le_RenewalDays="$_days" Le_RenewalDays="$_days"
shift shift
;; ;;
--valid-from)
_valid_from="$2"
shift
;;
--valid-to)
_valid_to="$2"
shift
;;
--httpport) --httpport)
_httpport="$2" _httpport="$2"
Le_HTTPPort="$_httpport" Le_HTTPPort="$_httpport"
...@@ -7485,6 +7672,7 @@ _process() { ...@@ -7485,6 +7672,7 @@ _process() {
if [ "$_server" ]; then if [ "$_server" ]; then
_selectServer "$_server" "${_ecc:-$_keylength}" _selectServer "$_server" "${_ecc:-$_keylength}"
_server="$ACME_DIRECTORY"
fi fi
if [ "${_CMD}" != "install" ]; then if [ "${_CMD}" != "install" ]; then
...@@ -7544,7 +7732,7 @@ _process() { ...@@ -7544,7 +7732,7 @@ _process() {
uninstall) uninstall "$_nocron" ;; uninstall) uninstall "$_nocron" ;;
upgrade) upgrade ;; upgrade) upgrade ;;
issue) issue)
issue "$_webroot" "$_domain" "$_altdomains" "$_keylength" "$_cert_file" "$_key_file" "$_ca_file" "$_reloadcmd" "$_fullchain_file" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_address" "$_challenge_alias" "$_preferred_chain" issue "$_webroot" "$_domain" "$_altdomains" "$_keylength" "$_cert_file" "$_key_file" "$_ca_file" "$_reloadcmd" "$_fullchain_file" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_address" "$_challenge_alias" "$_preferred_chain" "$_valid_from" "$_valid_to"
;; ;;
deploy) deploy)
deploy "$_domain" "$_deploy_hook" "$_ecc" deploy "$_domain" "$_deploy_hook" "$_ecc"
...@@ -7559,10 +7747,10 @@ _process() { ...@@ -7559,10 +7747,10 @@ _process() {
installcert "$_domain" "$_cert_file" "$_key_file" "$_ca_file" "$_reloadcmd" "$_fullchain_file" "$_ecc" installcert "$_domain" "$_cert_file" "$_key_file" "$_ca_file" "$_reloadcmd" "$_fullchain_file" "$_ecc"
;; ;;
renew) renew)
renew "$_domain" "$_ecc" renew "$_domain" "$_ecc" "$_server"
;; ;;
renewAll) renewAll)
renewAll "$_stopRenewOnError" renewAll "$_stopRenewOnError" "$_server"
;; ;;
revoke) revoke)
revoke "$_domain" "$_ecc" "$_revoke_reason" revoke "$_domain" "$_ecc" "$_revoke_reason"
......
...@@ -20,18 +20,23 @@ mailcow_deploy() { ...@@ -20,18 +20,23 @@ mailcow_deploy() {
_debug _cca "$_cca" _debug _cca "$_cca"
_debug _cfullchain "$_cfullchain" _debug _cfullchain "$_cfullchain"
_mailcow_path="${DEPLOY_MAILCOW_PATH}" _getdeployconf DEPLOY_MAILCOW_PATH
_getdeployconf DEPLOY_MAILCOW_RELOAD
if [ -z "$_mailcow_path" ]; then _debug DEPLOY_MAILCOW_PATH "$DEPLOY_MAILCOW_PATH"
_debug DEPLOY_MAILCOW_RELOAD "$DEPLOY_MAILCOW_RELOAD"
if [ -z "$DEPLOY_MAILCOW_PATH" ]; then
_err "Mailcow path is not found, please define DEPLOY_MAILCOW_PATH." _err "Mailcow path is not found, please define DEPLOY_MAILCOW_PATH."
return 1 return 1
fi fi
#Tests if _ssl_path is the mailcow root directory. _savedeployconf DEPLOY_MAILCOW_PATH "$DEPLOY_MAILCOW_PATH"
if [ -f "${_mailcow_path}/generate_config.sh" ]; then [ -n "$DEPLOY_MAILCOW_RELOAD" ] && _savedeployconf DEPLOY_MAILCOW_RELOAD "$DEPLOY_MAILCOW_RELOAD"
_ssl_path="${_mailcow_path}/data/assets/ssl/"
else _ssl_path="$DEPLOY_MAILCOW_PATH"
_ssl_path="${_mailcow_path}" if [ -f "$DEPLOY_MAILCOW_PATH/generate_config.sh" ]; then
_ssl_path="$DEPLOY_MAILCOW_PATH/data/assets/ssl/"
fi fi
if [ ! -d "$_ssl_path" ]; then if [ ! -d "$_ssl_path" ]; then
...@@ -40,16 +45,15 @@ mailcow_deploy() { ...@@ -40,16 +45,15 @@ mailcow_deploy() {
fi fi
# ECC or RSA # ECC or RSA
if [ -z "${Le_Keylength}" ]; then length=$(_readdomainconf Le_Keylength)
Le_Keylength="" if _isEccKey "$length"; then
fi
if _isEccKey "${Le_Keylength}"; then
_info "ECC key type detected" _info "ECC key type detected"
_cert_name_prefix="ecdsa-" _cert_name_prefix="ecdsa-"
else else
_info "RSA key type detected" _info "RSA key type detected"
_cert_name_prefix="" _cert_name_prefix=""
fi fi
_info "Copying key and cert" _info "Copying key and cert"
_real_key="$_ssl_path/${_cert_name_prefix}key.pem" _real_key="$_ssl_path/${_cert_name_prefix}key.pem"
if ! cat "$_ckey" >"$_real_key"; then if ! cat "$_ckey" >"$_real_key"; then
...@@ -63,7 +67,7 @@ mailcow_deploy() { ...@@ -63,7 +67,7 @@ mailcow_deploy() {
return 1 return 1
fi fi
DEFAULT_MAILCOW_RELOAD="docker restart $(docker ps -qaf name=postfix-mailcow); docker restart $(docker ps -qaf name=nginx-mailcow); docker restart $(docker ps -qaf name=dovecot-mailcow)" DEFAULT_MAILCOW_RELOAD="docker restart \$(docker ps --quiet --filter name=nginx-mailcow --filter name=dovecot-mailcow)"
_reload="${DEPLOY_MAILCOW_RELOAD:-$DEFAULT_MAILCOW_RELOAD}" _reload="${DEPLOY_MAILCOW_RELOAD:-$DEFAULT_MAILCOW_RELOAD}"
_info "Run reload: $_reload" _info "Run reload: $_reload"
......
...@@ -53,7 +53,7 @@ qiniu_deploy() { ...@@ -53,7 +53,7 @@ qiniu_deploy() {
sslcert_access_token="$(_make_access_token "$sslcert_path")" sslcert_access_token="$(_make_access_token "$sslcert_path")"
_debug sslcert_access_token "$sslcert_access_token" _debug sslcert_access_token "$sslcert_access_token"
export _H1="Authorization: QBox $sslcert_access_token" export _H1="Authorization: QBox $sslcert_access_token"
sslcert_response=$(_post "$sslcerl_body" "$QINIU_API_BASE$sslcert_path" 0 "POST" "application/json" | _dbase64 "multiline") sslcert_response=$(_post "$sslcerl_body" "$QINIU_API_BASE$sslcert_path" 0 "POST" "application/json" | _dbase64)
if ! _contains "$sslcert_response" "certID"; then if ! _contains "$sslcert_response" "certID"; then
_err "Error in creating certificate:" _err "Error in creating certificate:"
...@@ -75,7 +75,7 @@ qiniu_deploy() { ...@@ -75,7 +75,7 @@ qiniu_deploy() {
update_access_token="$(_make_access_token "$update_path")" update_access_token="$(_make_access_token "$update_path")"
_debug update_access_token "$update_access_token" _debug update_access_token "$update_access_token"
export _H1="Authorization: QBox $update_access_token" export _H1="Authorization: QBox $update_access_token"
update_response=$(_post "$update_body" "$QINIU_API_BASE$update_path" 0 "PUT" "application/json" | _dbase64 "multiline") update_response=$(_post "$update_body" "$QINIU_API_BASE$update_path" 0 "PUT" "application/json" | _dbase64)
if _contains "$update_response" "error"; then if _contains "$update_response" "error"; then
_err "Error in updating domain $domain httpsconf:" _err "Error in updating domain $domain httpsconf:"
......
...@@ -70,6 +70,7 @@ routeros_deploy() { ...@@ -70,6 +70,7 @@ routeros_deploy() {
_ccert="$3" _ccert="$3"
_cca="$4" _cca="$4"
_cfullchain="$5" _cfullchain="$5"
_err_code=0
_debug _cdomain "$_cdomain" _debug _cdomain "$_cdomain"
_debug _ckey "$_ckey" _debug _ckey "$_ckey"
...@@ -126,11 +127,17 @@ routeros_deploy() { ...@@ -126,11 +127,17 @@ routeros_deploy() {
_savedeployconf ROUTER_OS_SCP_CMD "$ROUTER_OS_SCP_CMD" _savedeployconf ROUTER_OS_SCP_CMD "$ROUTER_OS_SCP_CMD"
_savedeployconf ROUTER_OS_ADDITIONAL_SERVICES "$ROUTER_OS_ADDITIONAL_SERVICES" _savedeployconf ROUTER_OS_ADDITIONAL_SERVICES "$ROUTER_OS_ADDITIONAL_SERVICES"
_info "Trying to push key '$_ckey' to router" # push key to routeros
$ROUTER_OS_SCP_CMD "$_ckey" "$ROUTER_OS_USERNAME@$ROUTER_OS_HOST:$_cdomain.key" if ! _scp_certificate "$_ckey" "$ROUTER_OS_USERNAME@$ROUTER_OS_HOST:$_cdomain.key"; then
_info "Trying to push cert '$_cfullchain' to router" return $_err_code
$ROUTER_OS_SCP_CMD "$_cfullchain" "$ROUTER_OS_USERNAME@$ROUTER_OS_HOST:$_cdomain.cer" fi
DEPLOY_SCRIPT_CMD="/system script add name=\"LE Cert Deploy - $_cdomain\" owner=$ROUTER_OS_USER \
# push certificate chain to routeros
if ! _scp_certificate "$_cfullchain" "$ROUTER_OS_USERNAME@$ROUTER_OS_HOST:$_cdomain.cer"; then
return $_err_code
fi
DEPLOY_SCRIPT_CMD="/system script add name=\"LE Cert Deploy - $_cdomain\" owner=$ROUTER_OS_USERNAME \
comment=\"generated by routeros deploy script in acme.sh\" \ comment=\"generated by routeros deploy script in acme.sh\" \
source=\"/certificate remove [ find name=$_cdomain.cer_0 ];\ source=\"/certificate remove [ find name=$_cdomain.cer_0 ];\
\n/certificate remove [ find name=$_cdomain.cer_1 ];\ \n/certificate remove [ find name=$_cdomain.cer_1 ];\
...@@ -146,12 +153,51 @@ source=\"/certificate remove [ find name=$_cdomain.cer_0 ];\ ...@@ -146,12 +153,51 @@ source=\"/certificate remove [ find name=$_cdomain.cer_0 ];\
\n$ROUTER_OS_ADDITIONAL_SERVICES;\ \n$ROUTER_OS_ADDITIONAL_SERVICES;\
\n\" \n\"
" "
# shellcheck disable=SC2029
$ROUTER_OS_SSH_CMD "$ROUTER_OS_USERNAME@$ROUTER_OS_HOST" "$DEPLOY_SCRIPT_CMD" if ! _ssh_remote_cmd "$DEPLOY_SCRIPT_CMD"; then
# shellcheck disable=SC2029 return $_err_code
$ROUTER_OS_SSH_CMD "$ROUTER_OS_USERNAME@$ROUTER_OS_HOST" "/system script run \"LE Cert Deploy - $_cdomain\"" fi
# shellcheck disable=SC2029
$ROUTER_OS_SSH_CMD "$ROUTER_OS_USERNAME@$ROUTER_OS_HOST" "/system script remove \"LE Cert Deploy - $_cdomain\"" if ! _ssh_remote_cmd "/system script run \"LE Cert Deploy - $_cdomain\""; then
return $_err_code
fi
if ! _ssh_remote_cmd "/system script remove \"LE Cert Deploy - $_cdomain\""; then
return $_err_code
fi
return 0 return 0
} }
# inspired by deploy/ssh.sh
_ssh_remote_cmd() {
_cmd="$1"
_secure_debug "Remote commands to execute: $_cmd"
_info "Submitting sequence of commands to routeros"
# quotations in bash cmd below intended. Squash travis spellcheck error
# shellcheck disable=SC2029
$ROUTER_OS_SSH_CMD "$ROUTER_OS_USERNAME@$ROUTER_OS_HOST" "$_cmd"
_err_code="$?"
if [ "$_err_code" != "0" ]; then
_err "Error code $_err_code returned from routeros"
fi
return $_err_code
}
_scp_certificate() {
_src="$1"
_dst="$2"
_secure_debug "scp '$_src' to '$_dst'"
_info "Push key '$_src' to routeros"
$ROUTER_OS_SCP_CMD "$_src" "$_dst"
_err_code="$?"
if [ "$_err_code" != "0" ]; then
_err "Error code $_err_code returned from scp"
fi
return $_err_code
}
...@@ -38,7 +38,7 @@ truenas_deploy() { ...@@ -38,7 +38,7 @@ truenas_deploy() {
_getdeployconf DEPLOY_TRUENAS_APIKEY _getdeployconf DEPLOY_TRUENAS_APIKEY
if [ -z "$DEPLOY_TRUENAS_APIKEY" ]; then if [ -z "$DEPLOY_TRUENAS_APIKEY" ]; then
_err "TrueNAS Api Key is not found, please define DEPLOY_TRUENAS_APIKEY." _err "TrueNAS API key not found, please set the DEPLOY_TRUENAS_APIKEY environment variable."
return 1 return 1
fi fi
_secure_debug2 DEPLOY_TRUENAS_APIKEY "$DEPLOY_TRUENAS_APIKEY" _secure_debug2 DEPLOY_TRUENAS_APIKEY "$DEPLOY_TRUENAS_APIKEY"
...@@ -62,15 +62,14 @@ truenas_deploy() { ...@@ -62,15 +62,14 @@ truenas_deploy() {
_info "Testing Connection TrueNAS" _info "Testing Connection TrueNAS"
_response=$(_get "$_api_url/system/state") _response=$(_get "$_api_url/system/state")
_info "TrueNAS System State: $_response." _info "TrueNAS system state: $_response."
if [ -z "$_response" ]; then if [ -z "$_response" ]; then
_err "Unable to authenticate to $_api_url." _err "Unable to authenticate to $_api_url."
_err 'Check your Connection and set DEPLOY_TRUENAS_HOSTNAME="192.168.178.x".' _err 'Check your connection settings are correct, e.g.'
_err 'or' _err 'DEPLOY_TRUENAS_HOSTNAME="192.168.x.y" or DEPLOY_TRUENAS_HOSTNAME="truenas.example.com".'
_err 'set DEPLOY_TRUENAS_HOSTNAME="<truenas_dnsname>".' _err 'DEPLOY_TRUENAS_SCHEME="https" or DEPLOY_TRUENAS_SCHEME="http".'
_err 'Check your Connection and set DEPLOY_TRUENAS_SCHEME="https".' _err "Verify your TrueNAS API key is valid and set correctly, e.g. DEPLOY_TRUENAS_APIKEY=xxxx...."
_err "Check your Api Key."
return 1 return 1
fi fi
...@@ -78,7 +77,7 @@ truenas_deploy() { ...@@ -78,7 +77,7 @@ truenas_deploy() {
_savedeployconf DEPLOY_TRUENAS_HOSTNAME "$DEPLOY_TRUENAS_HOSTNAME" _savedeployconf DEPLOY_TRUENAS_HOSTNAME "$DEPLOY_TRUENAS_HOSTNAME"
_savedeployconf DEPLOY_TRUENAS_SCHEME "$DEPLOY_TRUENAS_SCHEME" _savedeployconf DEPLOY_TRUENAS_SCHEME "$DEPLOY_TRUENAS_SCHEME"
_info "Getting active certificate from TrueNAS" _info "Getting current active certificate from TrueNAS"
_response=$(_get "$_api_url/system/general") _response=$(_get "$_api_url/system/general")
_active_cert_id=$(echo "$_response" | grep -B2 '"name":' | grep 'id' | tr -d -- '"id: ,') _active_cert_id=$(echo "$_response" | grep -B2 '"name":' | grep 'id' | tr -d -- '"id: ,')
_active_cert_name=$(echo "$_response" | grep '"name":' | sed -n 's/.*: "\(.\{1,\}\)",$/\1/p') _active_cert_name=$(echo "$_response" | grep '"name":' | sed -n 's/.*: "\(.\{1,\}\)",$/\1/p')
...@@ -88,14 +87,14 @@ truenas_deploy() { ...@@ -88,14 +87,14 @@ truenas_deploy() {
_debug Active_UI_http_redirect "$_param_httpsredirect" _debug Active_UI_http_redirect "$_param_httpsredirect"
if [ "$DEPLOY_TRUENAS_SCHEME" = "http" ] && [ "$_param_httpsredirect" = "true" ]; then if [ "$DEPLOY_TRUENAS_SCHEME" = "http" ] && [ "$_param_httpsredirect" = "true" ]; then
_info "http Redirect active" _info "HTTP->HTTPS redirection is enabled"
_info "Setting DEPLOY_TRUENAS_SCHEME to 'https'" _info "Setting DEPLOY_TRUENAS_SCHEME to 'https'"
DEPLOY_TRUENAS_SCHEME="https" DEPLOY_TRUENAS_SCHEME="https"
_api_url="$DEPLOY_TRUENAS_SCHEME://$DEPLOY_TRUENAS_HOSTNAME/api/v2.0" _api_url="$DEPLOY_TRUENAS_SCHEME://$DEPLOY_TRUENAS_HOSTNAME/api/v2.0"
_savedeployconf DEPLOY_TRUENAS_SCHEME "$DEPLOY_TRUENAS_SCHEME" _savedeployconf DEPLOY_TRUENAS_SCHEME "$DEPLOY_TRUENAS_SCHEME"
fi fi
_info "Upload new certifikate to TrueNAS" _info "Uploading new certificate to TrueNAS"
_certname="Letsencrypt_$(_utc_date | tr ' ' '_' | tr -d -- ':')" _certname="Letsencrypt_$(_utc_date | tr ' ' '_' | tr -d -- ':')"
_debug3 _certname "$_certname" _debug3 _certname "$_certname"
...@@ -104,30 +103,30 @@ truenas_deploy() { ...@@ -104,30 +103,30 @@ truenas_deploy() {
_debug3 _add_cert_result "$_add_cert_result" _debug3 _add_cert_result "$_add_cert_result"
_info "Getting Certificate list to get new Cert ID" _info "Fetching list of installed certificates"
_cert_list=$(_get "$_api_url/system/general/ui_certificate_choices") _cert_list=$(_get "$_api_url/system/general/ui_certificate_choices")
_cert_id=$(echo "$_cert_list" | grep "$_certname" | sed -n 's/.*"\([0-9]\{1,\}\)".*$/\1/p') _cert_id=$(echo "$_cert_list" | grep "$_certname" | sed -n 's/.*"\([0-9]\{1,\}\)".*$/\1/p')
_debug3 _cert_id "$_cert_id" _debug3 _cert_id "$_cert_id"
_info "Activate Certificate ID: $_cert_id" _info "Current activate certificate ID: $_cert_id"
_activateData="{\"ui_certificate\": \"${_cert_id}\"}" _activateData="{\"ui_certificate\": \"${_cert_id}\"}"
_activate_result="$(_post "$_activateData" "$_api_url/system/general" "" "PUT" "application/json")" _activate_result="$(_post "$_activateData" "$_api_url/system/general" "" "PUT" "application/json")"
_debug3 _activate_result "$_activate_result" _debug3 _activate_result "$_activate_result"
_info "Check if WebDAV certificate is the same as the WEB UI" _info "Checking if WebDAV certificate is the same as the TrueNAS web UI"
_webdav_list=$(_get "$_api_url/webdav") _webdav_list=$(_get "$_api_url/webdav")
_webdav_cert_id=$(echo "$_webdav_list" | grep '"certssl":' | tr -d -- '"certsl: ,') _webdav_cert_id=$(echo "$_webdav_list" | grep '"certssl":' | tr -d -- '"certsl: ,')
if [ "$_webdav_cert_id" = "$_active_cert_id" ]; then if [ "$_webdav_cert_id" = "$_active_cert_id" ]; then
_info "Update the WebDAV Certificate" _info "Updating the WebDAV certificate"
_debug _webdav_cert_id "$_webdav_cert_id" _debug _webdav_cert_id "$_webdav_cert_id"
_webdav_data="{\"certssl\": \"${_cert_id}\"}" _webdav_data="{\"certssl\": \"${_cert_id}\"}"
_activate_webdav_cert="$(_post "$_webdav_data" "$_api_url/webdav" "" "PUT" "application/json")" _activate_webdav_cert="$(_post "$_webdav_data" "$_api_url/webdav" "" "PUT" "application/json")"
_webdav_new_cert_id=$(echo "$_activate_webdav_cert" | _json_decode | sed -n 's/.*: \([0-9]\{1,\}\) }$/\1/p') _webdav_new_cert_id=$(echo "$_activate_webdav_cert" | _json_decode | grep '"certssl":' | sed -n 's/.*: \([0-9]\{1,\}\),\{0,1\}$/\1/p')
if [ "$_webdav_new_cert_id" -eq "$_cert_id" ]; then if [ "$_webdav_new_cert_id" -eq "$_cert_id" ]; then
_info "WebDAV Certificate update successfully" _info "WebDAV certificate updated successfully"
else else
_err "Unable to set WebDAV certificate" _err "Unable to set WebDAV certificate"
_debug3 _activate_webdav_cert "$_activate_webdav_cert" _debug3 _activate_webdav_cert "$_activate_webdav_cert"
...@@ -136,21 +135,21 @@ truenas_deploy() { ...@@ -136,21 +135,21 @@ truenas_deploy() {
fi fi
_debug3 _webdav_new_cert_id "$_webdav_new_cert_id" _debug3 _webdav_new_cert_id "$_webdav_new_cert_id"
else else
_info "WebDAV certificate not set or not the same as Web UI" _info "WebDAV certificate is not configured or is not the same as TrueNAS web UI"
fi fi
_info "Check if FTP certificate is the same as the WEB UI" _info "Checking if FTP certificate is the same as the TrueNAS web UI"
_ftp_list=$(_get "$_api_url/ftp") _ftp_list=$(_get "$_api_url/ftp")
_ftp_cert_id=$(echo "$_ftp_list" | grep '"ssltls_certificate":' | tr -d -- '"certislfa:_ ,') _ftp_cert_id=$(echo "$_ftp_list" | grep '"ssltls_certificate":' | tr -d -- '"certislfa:_ ,')
if [ "$_ftp_cert_id" = "$_active_cert_id" ]; then if [ "$_ftp_cert_id" = "$_active_cert_id" ]; then
_info "Update the FTP Certificate" _info "Updating the FTP certificate"
_debug _ftp_cert_id "$_ftp_cert_id" _debug _ftp_cert_id "$_ftp_cert_id"
_ftp_data="{\"ssltls_certificate\": \"${_cert_id}\"}" _ftp_data="{\"ssltls_certificate\": \"${_cert_id}\"}"
_activate_ftp_cert="$(_post "$_ftp_data" "$_api_url/ftp" "" "PUT" "application/json")" _activate_ftp_cert="$(_post "$_ftp_data" "$_api_url/ftp" "" "PUT" "application/json")"
_ftp_new_cert_id=$(echo "$_activate_ftp_cert" | _json_decode | sed -n 's/.*: \([0-9]\{1,\}\) }$/\1/p') _ftp_new_cert_id=$(echo "$_activate_ftp_cert" | _json_decode | grep '"ssltls_certificate":' | sed -n 's/.*: \([0-9]\{1,\}\),\{0,1\}$/\1/p')
if [ "$_ftp_new_cert_id" -eq "$_cert_id" ]; then if [ "$_ftp_new_cert_id" -eq "$_cert_id" ]; then
_info "FTP Certificate update successfully" _info "FTP certificate updated successfully"
else else
_err "Unable to set FTP certificate" _err "Unable to set FTP certificate"
_debug3 _activate_ftp_cert "$_activate_ftp_cert" _debug3 _activate_ftp_cert "$_activate_ftp_cert"
...@@ -159,22 +158,45 @@ truenas_deploy() { ...@@ -159,22 +158,45 @@ truenas_deploy() {
fi fi
_debug3 _activate_ftp_cert "$_activate_ftp_cert" _debug3 _activate_ftp_cert "$_activate_ftp_cert"
else else
_info "FTP certificate not set or not the same as Web UI" _info "FTP certificate is not configured or is not the same as TrueNAS web UI"
fi fi
_info "Delete old Certificate" _info "Checking if S3 certificate is the same as the TrueNAS web UI"
_s3_list=$(_get "$_api_url/s3")
_s3_cert_id=$(echo "$_s3_list" | grep '"certificate":' | tr -d -- '"certifa:_ ,')
if [ "$_s3_cert_id" = "$_active_cert_id" ]; then
_info "Updating the S3 certificate"
_debug _s3_cert_id "$_s3_cert_id"
_s3_data="{\"certificate\": \"${_cert_id}\"}"
_activate_s3_cert="$(_post "$_s3_data" "$_api_url/s3" "" "PUT" "application/json")"
_s3_new_cert_id=$(echo "$_activate_s3_cert" | _json_decode | grep '"certificate":' | sed -n 's/.*: \([0-9]\{1,\}\),\{0,1\}$/\1/p')
if [ "$_s3_new_cert_id" -eq "$_cert_id" ]; then
_info "S3 certificate updated successfully"
else
_err "Unable to set S3 certificate"
_debug3 _activate_s3_cert "$_activate_s3_cert"
_debug3 _s3_new_cert_id "$_s3_new_cert_id"
return 1
fi
_debug3 _activate_s3_cert "$_activate_s3_cert"
else
_info "S3 certificate is not configured or is not the same as TrueNAS web UI"
fi
_info "Deleting old certificate"
_delete_result="$(_post "" "$_api_url/certificate/id/$_active_cert_id" "" "DELETE" "application/json")" _delete_result="$(_post "" "$_api_url/certificate/id/$_active_cert_id" "" "DELETE" "application/json")"
_debug3 _delete_result "$_delete_result" _debug3 _delete_result "$_delete_result"
_info "Reload WebUI from TrueNAS" _info "Reloading TrueNAS web UI"
_restart_UI=$(_get "$_api_url/system/general/ui_restart") _restart_UI=$(_get "$_api_url/system/general/ui_restart")
_debug2 _restart_UI "$_restart_UI" _debug2 _restart_UI "$_restart_UI"
if [ -n "$_add_cert_result" ] && [ -n "$_activate_result" ]; then if [ -n "$_add_cert_result" ] && [ -n "$_activate_result" ]; then
return 0 return 0
else else
_err "Certupdate was not succesfull, please use --debug" _err "Certificate update was not succesful, please try again with --debug"
return 1 return 1
fi fi
} }
...@@ -42,7 +42,7 @@ dns_1984hosting_add() { ...@@ -42,7 +42,7 @@ dns_1984hosting_add() {
_debug "Add TXT record $fulldomain with value '$txtvalue'" _debug "Add TXT record $fulldomain with value '$txtvalue'"
value="$(printf '%s' "$txtvalue" | _url_encode)" value="$(printf '%s' "$txtvalue" | _url_encode)"
url="https://management.1984hosting.com/domains/entry/" url="https://1984.hosting/domains/entry/"
postdata="entry=new" postdata="entry=new"
postdata="$postdata&type=TXT" postdata="$postdata&type=TXT"
...@@ -95,7 +95,7 @@ dns_1984hosting_rm() { ...@@ -95,7 +95,7 @@ dns_1984hosting_rm() {
_debug _domain "$_domain" _debug _domain "$_domain"
_debug "Delete $fulldomain TXT record" _debug "Delete $fulldomain TXT record"
url="https://management.1984hosting.com/domains" url="https://1984.hosting/domains"
if ! _get_zone_id "$url" "$_domain"; then if ! _get_zone_id "$url" "$_domain"; then
_err "invalid zone" "$_domain" _err "invalid zone" "$_domain"
return 1 return 1
...@@ -138,7 +138,7 @@ _1984hosting_login() { ...@@ -138,7 +138,7 @@ _1984hosting_login() {
_debug "Login to 1984Hosting as user $One984HOSTING_Username" _debug "Login to 1984Hosting as user $One984HOSTING_Username"
username=$(printf '%s' "$One984HOSTING_Username" | _url_encode) username=$(printf '%s' "$One984HOSTING_Username" | _url_encode)
password=$(printf '%s' "$One984HOSTING_Password" | _url_encode) password=$(printf '%s' "$One984HOSTING_Password" | _url_encode)
url="https://management.1984hosting.com/accounts/checkuserauth/" url="https://1984.hosting/accounts/checkuserauth/"
response="$(_post "username=$username&password=$password&otpkey=" $url)" response="$(_post "username=$username&password=$password&otpkey=" $url)"
response="$(echo "$response" | _normalizeJson)" response="$(echo "$response" | _normalizeJson)"
...@@ -175,7 +175,7 @@ _check_cookies() { ...@@ -175,7 +175,7 @@ _check_cookies() {
return 1 return 1
fi fi
_authget "https://management.1984hosting.com/accounts/loginstatus/" _authget "https://1984.hosting/accounts/loginstatus/"
if _contains "$response" '"ok": true'; then if _contains "$response" '"ok": true'; then
_debug "Cached cookies still valid" _debug "Cached cookies still valid"
return 0 return 0
...@@ -204,7 +204,7 @@ _get_root() { ...@@ -204,7 +204,7 @@ _get_root() {
return 1 return 1
fi fi
_authget "https://management.1984hosting.com/domains/soacheck/?zone=$h&nameserver=ns0.1984.is." _authget "https://1984.hosting/domains/soacheck/?zone=$h&nameserver=ns0.1984.is."
if _contains "$_response" "serial" && ! _contains "$_response" "null"; then if _contains "$_response" "serial" && ! _contains "$_response" "null"; 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"
...@@ -251,11 +251,11 @@ _htmlget() { ...@@ -251,11 +251,11 @@ _htmlget() {
# add extra headers to request # add extra headers to request
_authpost() { _authpost() {
url="https://management.1984hosting.com/domains" url="https://1984.hosting/domains"
_get_zone_id "$url" "$_domain" _get_zone_id "$url" "$_domain"
csrf_header="$(echo "$One984HOSTING_CSRFTOKEN_COOKIE" | _egrep_o "=[^=][0-9a-zA-Z]*" | tr -d "=")" csrf_header="$(echo "$One984HOSTING_CSRFTOKEN_COOKIE" | _egrep_o "=[^=][0-9a-zA-Z]*" | tr -d "=")"
export _H1="Cookie: $One984HOSTING_CSRFTOKEN_COOKIE;$One984HOSTING_SESSIONID_COOKIE" export _H1="Cookie: $One984HOSTING_CSRFTOKEN_COOKIE;$One984HOSTING_SESSIONID_COOKIE"
export _H2="Referer: https://management.1984hosting.com/domains/$_zone_id" export _H2="Referer: https://1984.hosting/domains/$_zone_id"
export _H3="X-CSRFToken: $csrf_header" export _H3="X-CSRFToken: $csrf_header"
_response=$(_post "$1" "$2") _response=$(_post "$1" "$2")
} }
...@@ -152,34 +152,23 @@ dns_aws_rm() { ...@@ -152,34 +152,23 @@ dns_aws_rm() {
_get_root() { _get_root() {
domain=$1 domain=$1
i=2 i=1
p=1 p=1
if aws_rest GET "2013-04-01/hostedzone"; then # iterate over names (a.b.c.d -> b.c.d -> c.d -> d)
while true; do while true; do
h=$(printf "%s" "$domain" | cut -d . -f $i-100) h=$(printf "%s" "$domain" | cut -d . -f $i-100)
_debug2 "Checking domain: $h" _debug "Checking domain: $h"
if [ -z "$h" ]; then if [ -z "$h" ]; then
if _contains "$response" "<IsTruncated>true</IsTruncated>" && _contains "$response" "<NextMarker>"; then _error "invalid domain"
_debug "IsTruncated" return 1
_nextMarker="$(echo "$response" | _egrep_o "<NextMarker>.*</NextMarker>" | cut -d '>' -f 2 | cut -d '<' -f 1)" fi
_debug "NextMarker" "$_nextMarker"
if aws_rest GET "2013-04-01/hostedzone" "marker=$_nextMarker"; then
_debug "Truncated request OK"
i=2
p=1
continue
else
_err "Truncated request error."
fi
fi
#not valid
_err "Invalid domain"
return 1
fi
# iterate over paginated result for list_hosted_zones
aws_rest GET "2013-04-01/hostedzone"
while true; do
if _contains "$response" "<Name>$h.</Name>"; then if _contains "$response" "<Name>$h.</Name>"; then
hostedzone="$(echo "$response" | sed 's/<HostedZone>/#&/g' | tr '#' '\n' | _egrep_o "<HostedZone><Id>[^<]*<.Id><Name>$h.<.Name>.*<PrivateZone>false<.PrivateZone>.*<.HostedZone>")" hostedzone="$(echo "$response" | tr -d '\n' | sed 's/<HostedZone>/#&/g' | tr '#' '\n' | _egrep_o "<HostedZone><Id>[^<]*<.Id><Name>$h.<.Name>.*<PrivateZone>false<.PrivateZone>.*<.HostedZone>")"
_debug hostedzone "$hostedzone" _debug hostedzone "$hostedzone"
if [ "$hostedzone" ]; then if [ "$hostedzone" ]; then
_domain_id=$(printf "%s\n" "$hostedzone" | _egrep_o "<Id>.*<.Id>" | head -n 1 | _egrep_o ">.*<" | tr -d "<>") _domain_id=$(printf "%s\n" "$hostedzone" | _egrep_o "<Id>.*<.Id>" | head -n 1 | _egrep_o ">.*<" | tr -d "<>")
...@@ -192,10 +181,19 @@ _get_root() { ...@@ -192,10 +181,19 @@ _get_root() {
return 1 return 1
fi fi
fi fi
p=$i if _contains "$response" "<IsTruncated>true</IsTruncated>" && _contains "$response" "<NextMarker>"; then
i=$(_math "$i" + 1) _debug "IsTruncated"
_nextMarker="$(echo "$response" | _egrep_o "<NextMarker>.*</NextMarker>" | cut -d '>' -f 2 | cut -d '<' -f 1)"
_debug "NextMarker" "$_nextMarker"
else
break
fi
_debug "Checking domain: $h - Next Page "
aws_rest GET "2013-04-01/hostedzone" "marker=$_nextMarker"
done done
fi p=$i
i=$(_math "$i" + 1)
done
return 1 return 1
} }
......
...@@ -32,7 +32,8 @@ dns_cf_add() { ...@@ -32,7 +32,8 @@ dns_cf_add() {
else else
_saveaccountconf_mutable CF_Token "$CF_Token" _saveaccountconf_mutable CF_Token "$CF_Token"
_saveaccountconf_mutable CF_Account_ID "$CF_Account_ID" _saveaccountconf_mutable CF_Account_ID "$CF_Account_ID"
_saveaccountconf_mutable CF_Zone_ID "$CF_Zone_ID" _clearaccountconf_mutable CF_Zone_ID
_clearaccountconf CF_Zone_ID
fi fi
else else
if [ -z "$CF_Key" ] || [ -z "$CF_Email" ]; then if [ -z "$CF_Key" ] || [ -z "$CF_Email" ]; then
...@@ -51,6 +52,14 @@ dns_cf_add() { ...@@ -51,6 +52,14 @@ dns_cf_add() {
#save the api key and email to the account conf file. #save the api key and email to the account conf file.
_saveaccountconf_mutable CF_Key "$CF_Key" _saveaccountconf_mutable CF_Key "$CF_Key"
_saveaccountconf_mutable CF_Email "$CF_Email" _saveaccountconf_mutable CF_Email "$CF_Email"
_clearaccountconf_mutable CF_Token
_clearaccountconf_mutable CF_Account_ID
_clearaccountconf_mutable CF_Zone_ID
_clearaccountconf CF_Token
_clearaccountconf CF_Account_ID
_clearaccountconf CF_Zone_ID
fi fi
_debug "First detect the root zone" _debug "First detect the root zone"
......
#!/usr/bin/env sh
# CloudXNS Domain api
#
#CX_Key="1234"
#
#CX_Secret="sADDsdasdgdsf"
CX_Api="https://www.cloudxns.net/api2"
#REST_API
######## Public functions #####################
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_cx_add() {
fulldomain=$1
txtvalue=$2
CX_Key="${CX_Key:-$(_readaccountconf_mutable CX_Key)}"
CX_Secret="${CX_Secret:-$(_readaccountconf_mutable CX_Secret)}"
if [ -z "$CX_Key" ] || [ -z "$CX_Secret" ]; then
CX_Key=""
CX_Secret=""
_err "You don't specify cloudxns.net api key or secret yet."
_err "Please create you key and try again."
return 1
fi
REST_API="$CX_Api"
#save the api key and email to the account conf file.
_saveaccountconf_mutable CX_Key "$CX_Key"
_saveaccountconf_mutable CX_Secret "$CX_Secret"
_debug "First detect the root zone"
if ! _get_root "$fulldomain"; then
_err "invalid domain"
return 1
fi
add_record "$_domain" "$_sub_domain" "$txtvalue"
}
#fulldomain txtvalue
dns_cx_rm() {
fulldomain=$1
txtvalue=$2
CX_Key="${CX_Key:-$(_readaccountconf_mutable CX_Key)}"
CX_Secret="${CX_Secret:-$(_readaccountconf_mutable CX_Secret)}"
REST_API="$CX_Api"
if _get_root "$fulldomain"; then
record_id=""
existing_records "$_domain" "$_sub_domain" "$txtvalue"
if [ "$record_id" ]; then
_rest DELETE "record/$record_id/$_domain_id" "{}"
_info "Deleted record ${fulldomain}"
fi
fi
}
#usage: root sub
#return if the sub record already exists.
#echos the existing records count.
# '0' means doesn't exist
existing_records() {
_debug "Getting txt records"
root=$1
sub=$2
if ! _rest GET "record/$_domain_id?:domain_id?host_id=0&offset=0&row_num=100"; then
return 1
fi
seg=$(printf "%s\n" "$response" | _egrep_o '"record_id":[^{]*host":"'"$_sub_domain"'"[^}]*\}')
_debug seg "$seg"
if [ -z "$seg" ]; then
return 0
fi
if printf "%s" "$response" | grep '"type":"TXT"' >/dev/null; then
record_id=$(printf "%s\n" "$seg" | _egrep_o '"record_id":"[^"]*"' | cut -d : -f 2 | tr -d \" | _head_n 1)
_debug record_id "$record_id"
return 0
fi
}
#add the txt record.
#usage: root sub txtvalue
add_record() {
root=$1
sub=$2
txtvalue=$3
fulldomain="$sub.$root"
_info "Adding record"
if ! _rest POST "record" "{\"domain_id\": $_domain_id, \"host\":\"$_sub_domain\", \"value\":\"$txtvalue\", \"type\":\"TXT\",\"ttl\":600, \"line_id\":1}"; then
return 1
fi
return 0
}
#################### Private functions below ##################################
#_acme-challenge.www.domain.com
#returns
# _sub_domain=_acme-challenge.www
# _domain=domain.com
# _domain_id=sdjkglgdfewsdfg
_get_root() {
domain=$1
i=2
p=1
if ! _rest GET "domain"; then
return 1
fi
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 _contains "$response" "$h."; then
seg=$(printf "%s\n" "$response" | _egrep_o '"id":[^{]*"'"$h"'."[^}]*}')
_debug seg "$seg"
_domain_id=$(printf "%s\n" "$seg" | _egrep_o "\"id\":\"[^\"]*\"" | cut -d : -f 2 | tr -d \")
_debug _domain_id "$_domain_id"
if [ "$_domain_id" ]; then
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
_debug _sub_domain "$_sub_domain"
_domain="$h"
_debug _domain "$_domain"
return 0
fi
return 1
fi
p="$i"
i=$(_math "$i" + 1)
done
return 1
}
#Usage: method URI data
_rest() {
m=$1
ep="$2"
_debug ep "$ep"
url="$REST_API/$ep"
_debug url "$url"
cdate=$(date -u "+%Y-%m-%d %H:%M:%S UTC")
_debug cdate "$cdate"
data="$3"
_debug data "$data"
sec="$CX_Key$url$data$cdate$CX_Secret"
_debug sec "$sec"
hmac=$(printf "%s" "$sec" | _digest md5 hex)
_debug hmac "$hmac"
export _H1="API-KEY: $CX_Key"
export _H2="API-REQUEST-DATE: $cdate"
export _H3="API-HMAC: $hmac"
export _H4="Content-Type: application/json"
if [ "$data" ]; then
response="$(_post "$data" "$url" "" "$m")"
else
response="$(_get "$url")"
fi
if [ "$?" != "0" ]; then
_err "error $ep"
return 1
fi
_debug2 response "$response"
_contains "$response" '"code":1'
}
...@@ -44,7 +44,7 @@ dns_cyon_rm() { ...@@ -44,7 +44,7 @@ dns_cyon_rm() {
_cyon_load_credentials() { _cyon_load_credentials() {
# Convert loaded password to/from base64 as needed. # Convert loaded password to/from base64 as needed.
if [ "${CY_Password_B64}" ]; then if [ "${CY_Password_B64}" ]; then
CY_Password="$(printf "%s" "${CY_Password_B64}" | _dbase64 "multiline")" CY_Password="$(printf "%s" "${CY_Password_B64}" | _dbase64)"
elif [ "${CY_Password}" ]; then elif [ "${CY_Password}" ]; then
CY_Password_B64="$(printf "%s" "${CY_Password}" | _base64)" CY_Password_B64="$(printf "%s" "${CY_Password}" | _base64)"
fi fi
......
...@@ -176,6 +176,7 @@ _EDGEDNS_credentials() { ...@@ -176,6 +176,7 @@ _EDGEDNS_credentials() {
_debug "GettingEdge DNS credentials" _debug "GettingEdge DNS credentials"
_log "$(printf "ACME DNSAPI Edge DNS version %s" ${ACME_EDGEDNS_VERSION})" _log "$(printf "ACME DNSAPI Edge DNS version %s" ${ACME_EDGEDNS_VERSION})"
args_missing=0 args_missing=0
AKAMAI_ACCESS_TOKEN="${AKAMAI_ACCESS_TOKEN:-$(_readaccountconf_mutable AKAMAI_ACCESS_TOKEN)}"
if [ -z "$AKAMAI_ACCESS_TOKEN" ]; then if [ -z "$AKAMAI_ACCESS_TOKEN" ]; then
AKAMAI_ACCESS_TOKEN="" AKAMAI_ACCESS_TOKEN=""
AKAMAI_CLIENT_TOKEN="" AKAMAI_CLIENT_TOKEN=""
...@@ -184,6 +185,7 @@ _EDGEDNS_credentials() { ...@@ -184,6 +185,7 @@ _EDGEDNS_credentials() {
_err "AKAMAI_ACCESS_TOKEN is missing" _err "AKAMAI_ACCESS_TOKEN is missing"
args_missing=1 args_missing=1
fi fi
AKAMAI_CLIENT_TOKEN="${AKAMAI_CLIENT_TOKEN:-$(_readaccountconf_mutable AKAMAI_CLIENT_TOKEN)}"
if [ -z "$AKAMAI_CLIENT_TOKEN" ]; then if [ -z "$AKAMAI_CLIENT_TOKEN" ]; then
AKAMAI_ACCESS_TOKEN="" AKAMAI_ACCESS_TOKEN=""
AKAMAI_CLIENT_TOKEN="" AKAMAI_CLIENT_TOKEN=""
...@@ -192,6 +194,7 @@ _EDGEDNS_credentials() { ...@@ -192,6 +194,7 @@ _EDGEDNS_credentials() {
_err "AKAMAI_CLIENT_TOKEN is missing" _err "AKAMAI_CLIENT_TOKEN is missing"
args_missing=1 args_missing=1
fi fi
AKAMAI_HOST="${AKAMAI_HOST:-$(_readaccountconf_mutable AKAMAI_HOST)}"
if [ -z "$AKAMAI_HOST" ]; then if [ -z "$AKAMAI_HOST" ]; then
AKAMAI_ACCESS_TOKEN="" AKAMAI_ACCESS_TOKEN=""
AKAMAI_CLIENT_TOKEN="" AKAMAI_CLIENT_TOKEN=""
...@@ -200,6 +203,7 @@ _EDGEDNS_credentials() { ...@@ -200,6 +203,7 @@ _EDGEDNS_credentials() {
_err "AKAMAI_HOST is missing" _err "AKAMAI_HOST is missing"
args_missing=1 args_missing=1
fi fi
AKAMAI_CLIENT_SECRET="${AKAMAI_CLIENT_SECRET:-$(_readaccountconf_mutable AKAMAI_CLIENT_SECRET)}"
if [ -z "$AKAMAI_CLIENT_SECRET" ]; then if [ -z "$AKAMAI_CLIENT_SECRET" ]; then
AKAMAI_ACCESS_TOKEN="" AKAMAI_ACCESS_TOKEN=""
AKAMAI_CLIENT_TOKEN="" AKAMAI_CLIENT_TOKEN=""
......
#!/usr/bin/env sh
#Author: Timur Umarov <inbox@tumarov.com>
FORNEX_API_URL="https://fornex.com/api/dns/v0.1"
######## Public functions #####################
#Usage: dns_fornex_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
dns_fornex_add() {
fulldomain=$1
txtvalue=$2
if ! _Fornex_API; then
return 1
fi
if ! _get_root "$fulldomain"; then
_err "Unable to determine root domain"
return 1
else
_debug _domain "$_domain"
fi
_info "Adding record"
if _rest POST "$_domain/entry_set/add/" "host=$fulldomain&type=TXT&value=$txtvalue&apikey=$FORNEX_API_KEY"; then
_debug _response "$response"
if _contains "$response" '"ok": true' || _contains "$response" 'Такая запись уже существует.'; then
_info "Added, OK"
return 0
fi
fi
_err "Add txt record error."
return 1
}
#Usage: dns_fornex_rm _acme-challenge.www.domain.com
dns_fornex_rm() {
fulldomain=$1
txtvalue=$2
if ! _Fornex_API; then
return 1
fi
if ! _get_root "$fulldomain"; then
_err "Unable to determine root domain"
return 1
else
_debug _domain "$_domain"
fi
_debug "Getting txt records"
_rest GET "$_domain/entry_set.json?apikey=$FORNEX_API_KEY"
if ! _contains "$response" "$txtvalue"; then
_err "Txt record not found"
return 1
fi
_record_id="$(echo "$response" | _egrep_o "{[^{]*\"value\"*:*\"$txtvalue\"[^}]*}" | sed -n -e 's#.*"id": \([0-9]*\).*#\1#p')"
_debug "_record_id" "$_record_id"
if [ -z "$_record_id" ]; then
_err "can not find _record_id"
return 1
fi
if ! _rest POST "$_domain/entry_set/$_record_id/delete/" "apikey=$FORNEX_API_KEY"; then
_err "Delete record error."
return 1
fi
return 0
}
#################### 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
#not valid
return 1
fi
if ! _rest GET "domain_list.json?q=$h&apikey=$FORNEX_API_KEY"; 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
}
_Fornex_API() {
FORNEX_API_KEY="${FORNEX_API_KEY:-$(_readaccountconf_mutable FORNEX_API_KEY)}"
if [ -z "$FORNEX_API_KEY" ]; then
FORNEX_API_KEY=""
_err "You didn't specify the Fornex API key yet."
_err "Please create your key and try again."
return 1
fi
_saveaccountconf_mutable FORNEX_API_KEY "$FORNEX_API_KEY"
}
#method method action data
_rest() {
m=$1
ep="$2"
data="$3"
_debug "$ep"
export _H1="Accept: application/json"
if [ "$m" != "GET" ]; then
_debug data "$data"
response="$(_post "$data" "$FORNEX_API_URL/$ep" "" "$m")"
else
response="$(_get "$FORNEX_API_URL/$ep" | _normalizeJson)"
fi
_ret="$?"
if [ "$_ret" != "0" ]; then
_err "error $ep"
return 1
fi
_debug2 response "$response"
return 0
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment