mirror of
https://github.com/plantroon/acme.sh.git
synced 2024-12-22 13:11:41 +00:00
Merge branch 'dev' into feature/ssh_scp
This commit is contained in:
commit
ed58f32052
2
.github/FUNDING.yml
vendored
2
.github/FUNDING.yml
vendored
@ -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
|
||||||
|
10
.github/workflows/FreeBSD.yml
vendored
10
.github/workflows/FreeBSD.yml
vendored
@ -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
|
||||||
|
1
.github/workflows/Linux.yml
vendored
1
.github/workflows/Linux.yml
vendored
@ -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
|
||||||
|
10
.github/workflows/MacOS.yml
vendored
10
.github/workflows/MacOS.yml
vendored
@ -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
|
||||||
|
10
.github/workflows/Solaris.yml
vendored
10
.github/workflows/Solaris.yml
vendored
@ -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
|
||||||
|
10
.github/workflows/Windows.yml
vendored
10
.github/workflows/Windows.yml
vendored
@ -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 \
|
|||||||
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
|
|||||||
- 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
|
||||||
|
|
||||||
|
314
acme.sh
314
acme.sh
@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env sh
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
VER=3.0.2
|
VER=3.0.5
|
||||||
|
|
||||||
PROJECT_NAME="acme.sh"
|
PROJECT_NAME="acme.sh"
|
||||||
|
|
||||||
@ -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"
|
|||||||
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
|
|||||||
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"
|
|||||||
|
|
||||||
_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() {
|
|||||||
#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
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1141,13 +1146,19 @@ _createkey() {
|
|||||||
|
|
||||||
_debug "Use length $length"
|
_debug "Use length $length"
|
||||||
|
|
||||||
if ! touch "$f" >/dev/null 2>&1; then
|
if ! [ -e "$f" ]; then
|
||||||
_f_path="$(dirname "$f")"
|
if ! touch "$f" >/dev/null 2>&1; then
|
||||||
_debug _f_path "$_f_path"
|
_f_path="$(dirname "$f")"
|
||||||
if ! mkdir -p "$_f_path"; then
|
_debug _f_path "$_f_path"
|
||||||
_err "Can not create path: $_f_path"
|
if ! mkdir -p "$_f_path"; then
|
||||||
|
_err "Can not create path: $_f_path"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if ! touch "$f" >/dev/null 2>&1; then
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
chmod 600 "$f"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if _isEccKey "$length"; then
|
if _isEccKey "$length"; then
|
||||||
@ -1495,7 +1506,6 @@ _create_account_key() {
|
|||||||
else
|
else
|
||||||
#generate account key
|
#generate account key
|
||||||
if _createkey "$length" "$ACCOUNT_KEY_PATH"; then
|
if _createkey "$length" "$ACCOUNT_KEY_PATH"; then
|
||||||
chmod 600 "$ACCOUNT_KEY_PATH"
|
|
||||||
_info "Create account key ok."
|
_info "Create account key ok."
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
@ -1593,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
|
||||||
}
|
}
|
||||||
@ -1768,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"
|
||||||
}
|
}
|
||||||
@ -1840,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 "
|
||||||
@ -2657,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"
|
||||||
@ -3746,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": []}'
|
||||||
@ -3756,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
|
||||||
@ -4195,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
|
||||||
@ -4228,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"
|
||||||
@ -4247,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."
|
||||||
@ -4299,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
|
||||||
@ -4323,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
|
||||||
@ -4363,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)"
|
||||||
@ -4407,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
|
||||||
@ -4557,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
|
||||||
@ -4851,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"
|
||||||
@ -5028,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
|
||||||
@ -5068,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
|
||||||
@ -5110,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
|
||||||
@ -5134,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,
|
|
||||||
#so, we force to use letsencrypt server
|
|
||||||
Le_API="$CA_LETSENCRYPT_V2"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$Le_API" ]; then
|
case "$Le_API" in
|
||||||
if [ "$Le_API" != "$ACME_DIRECTORY" ]; then
|
"$CA_LETSENCRYPT_V2_TEST")
|
||||||
_clearAPI
|
_info "Switching back to $CA_LETSENCRYPT_V2"
|
||||||
fi
|
Le_API="$CA_LETSENCRYPT_V2"
|
||||||
export ACME_DIRECTORY="$Le_API"
|
;;
|
||||||
#reload ca configs
|
"$CA_BUYPASS_TEST")
|
||||||
ACCOUNT_KEY_PATH=""
|
_info "Switching back to $CA_BUYPASS"
|
||||||
ACCOUNT_JSON_PATH=""
|
Le_API="$CA_BUYPASS"
|
||||||
CA_CONF=""
|
;;
|
||||||
_debug3 "initpath again."
|
"$CA_GOOGLE_TEST")
|
||||||
_initpath "$Le_Domain" "$_isEcc"
|
_info "Switching back to $CA_GOOGLE"
|
||||||
|
Le_API="$CA_GOOGLE"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ "$_server" ]; then
|
||||||
|
Le_API="$_server"
|
||||||
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")"
|
||||||
@ -5175,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"
|
||||||
@ -5202,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=""
|
||||||
@ -5229,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"
|
||||||
@ -5395,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"
|
||||||
|
|
||||||
@ -5611,8 +5776,9 @@ _installcert() {
|
|||||||
if [ -f "$_real_key" ]; then
|
if [ -f "$_real_key" ]; then
|
||||||
cat "$CERT_KEY_PATH" >"$_real_key" || return 1
|
cat "$CERT_KEY_PATH" >"$_real_key" || return 1
|
||||||
else
|
else
|
||||||
cat "$CERT_KEY_PATH" >"$_real_key" || return 1
|
touch "$_real_key" || return 1
|
||||||
chmod 600 "$_real_key"
|
chmod 600 "$_real_key"
|
||||||
|
cat "$CERT_KEY_PATH" >"$_real_key" || return 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -6610,6 +6776,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.
|
||||||
@ -6801,6 +6972,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
|
||||||
@ -6922,8 +7097,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=""
|
||||||
@ -6970,6 +7145,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
|
||||||
|
|
||||||
@ -7277,6 +7454,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"
|
||||||
@ -7479,6 +7664,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
|
||||||
@ -7538,7 +7724,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"
|
||||||
@ -7553,10 +7739,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() {
|
|||||||
_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() {
|
|||||||
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() {
|
|||||||
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"
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
# ```sh
|
# ```sh
|
||||||
# export ROUTER_OS_USERNAME=certuser
|
# export ROUTER_OS_USERNAME=certuser
|
||||||
# export ROUTER_OS_HOST=router.example.com
|
# export ROUTER_OS_HOST=router.example.com
|
||||||
|
# export ROUTER_OS_PORT=22
|
||||||
#
|
#
|
||||||
# acme.sh --deploy -d ftp.example.com --deploy-hook routeros
|
# acme.sh --deploy -d ftp.example.com --deploy-hook routeros
|
||||||
# ```
|
# ```
|
||||||
@ -48,6 +49,16 @@
|
|||||||
# One optional thing to do as well is to create a script that updates
|
# One optional thing to do as well is to create a script that updates
|
||||||
# all the required services and run that script in a single command.
|
# all the required services and run that script in a single command.
|
||||||
#
|
#
|
||||||
|
# To adopt parameters to `scp` and/or `ssh` set the optional
|
||||||
|
# `ROUTER_OS_SSH_CMD` and `ROUTER_OS_SCP_CMD` variables accordingly,
|
||||||
|
# see ssh(1) and scp(1) for parameters to those commands.
|
||||||
|
#
|
||||||
|
# Example:
|
||||||
|
# ```ssh
|
||||||
|
# export ROUTER_OS_SSH_CMD="ssh -i /acme.sh/.ssh/router.example.com -o UserKnownHostsFile=/acme.sh/.ssh/known_hosts"
|
||||||
|
# export ROUTER_OS_SCP_CMD="scp -i /acme.sh/.ssh/router.example.com -o UserKnownHostsFile=/acme.sh/.ssh/known_hosts"
|
||||||
|
# ````
|
||||||
|
#
|
||||||
# returns 0 means success, otherwise error.
|
# returns 0 means success, otherwise error.
|
||||||
|
|
||||||
######## Public functions #####################
|
######## Public functions #####################
|
||||||
@ -59,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"
|
||||||
@ -80,6 +92,27 @@ routeros_deploy() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
_getdeployconf ROUTER_OS_PORT
|
||||||
|
|
||||||
|
if [ -z "$ROUTER_OS_PORT" ]; then
|
||||||
|
_debug "Using default port 22 as ROUTER_OS_PORT, please set if not correct."
|
||||||
|
ROUTER_OS_PORT=22
|
||||||
|
fi
|
||||||
|
|
||||||
|
_getdeployconf ROUTER_OS_SSH_CMD
|
||||||
|
|
||||||
|
if [ -z "$ROUTER_OS_SSH_CMD" ]; then
|
||||||
|
_debug "Use default ssh setup."
|
||||||
|
ROUTER_OS_SSH_CMD="ssh -p $ROUTER_OS_PORT"
|
||||||
|
fi
|
||||||
|
|
||||||
|
_getdeployconf ROUTER_OS_SCP_CMD
|
||||||
|
|
||||||
|
if [ -z "$ROUTER_OS_SCP_CMD" ]; then
|
||||||
|
_debug "USe default scp setup."
|
||||||
|
ROUTER_OS_SCP_CMD="scp -P $ROUTER_OS_PORT"
|
||||||
|
fi
|
||||||
|
|
||||||
_getdeployconf ROUTER_OS_ADDITIONAL_SERVICES
|
_getdeployconf ROUTER_OS_ADDITIONAL_SERVICES
|
||||||
|
|
||||||
if [ -z "$ROUTER_OS_ADDITIONAL_SERVICES" ]; then
|
if [ -z "$ROUTER_OS_ADDITIONAL_SERVICES" ]; then
|
||||||
@ -89,16 +122,26 @@ routeros_deploy() {
|
|||||||
|
|
||||||
_savedeployconf ROUTER_OS_HOST "$ROUTER_OS_HOST"
|
_savedeployconf ROUTER_OS_HOST "$ROUTER_OS_HOST"
|
||||||
_savedeployconf ROUTER_OS_USERNAME "$ROUTER_OS_USERNAME"
|
_savedeployconf ROUTER_OS_USERNAME "$ROUTER_OS_USERNAME"
|
||||||
|
_savedeployconf ROUTER_OS_PORT "$ROUTER_OS_PORT"
|
||||||
|
_savedeployconf ROUTER_OS_SSH_CMD "$ROUTER_OS_SSH_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
|
||||||
scp "$_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
|
||||||
scp "$_cfullchain" "$ROUTER_OS_USERNAME@$ROUTER_OS_HOST:$_cdomain.cer"
|
fi
|
||||||
DEPLOY_SCRIPT_CMD="/system script add name=\"LE Cert Deploy - $_cdomain\" owner=admin policy=ftp,read,write,password,sensitive \
|
|
||||||
source=\"## generated by routeros deploy script in acme.sh;\
|
# push certificate chain to routeros
|
||||||
\n/certificate remove [ find name=$_cdomain.cer_0 ];\
|
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\" \
|
||||||
|
source=\"/certificate remove [ find name=$_cdomain.cer_0 ];\
|
||||||
\n/certificate remove [ find name=$_cdomain.cer_1 ];\
|
\n/certificate remove [ find name=$_cdomain.cer_1 ];\
|
||||||
|
\n/certificate remove [ find name=$_cdomain.cer_2 ];\
|
||||||
\ndelay 1;\
|
\ndelay 1;\
|
||||||
\n/certificate import file-name=$_cdomain.cer passphrase=\\\"\\\";\
|
\n/certificate import file-name=$_cdomain.cer passphrase=\\\"\\\";\
|
||||||
\n/certificate import file-name=$_cdomain.key passphrase=\\\"\\\";\
|
\n/certificate import file-name=$_cdomain.key passphrase=\\\"\\\";\
|
||||||
@ -110,12 +153,51 @@ source=\"## generated by routeros deploy script in acme.sh;\
|
|||||||
\n$ROUTER_OS_ADDITIONAL_SERVICES;\
|
\n$ROUTER_OS_ADDITIONAL_SERVICES;\
|
||||||
\n\"
|
\n\"
|
||||||
"
|
"
|
||||||
# shellcheck disable=SC2029
|
|
||||||
ssh "$ROUTER_OS_USERNAME@$ROUTER_OS_HOST" "$DEPLOY_SCRIPT_CMD"
|
if ! _ssh_remote_cmd "$DEPLOY_SCRIPT_CMD"; then
|
||||||
# shellcheck disable=SC2029
|
return $_err_code
|
||||||
ssh "$ROUTER_OS_USERNAME@$ROUTER_OS_HOST" "/system script run \"LE Cert Deploy - $_cdomain\""
|
fi
|
||||||
# shellcheck disable=SC2029
|
|
||||||
ssh "$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
|
||||||
|
}
|
||||||
|
@ -94,7 +94,12 @@ synology_dsm_deploy() {
|
|||||||
|
|
||||||
otp_code=""
|
otp_code=""
|
||||||
if [ -n "$SYNO_TOTP_SECRET" ]; then
|
if [ -n "$SYNO_TOTP_SECRET" ]; then
|
||||||
otp_code="$(oathtool --base32 --totp "${SYNO_TOTP_SECRET}" 2>/dev/null)"
|
if _exists oathtool; then
|
||||||
|
otp_code="$(oathtool --base32 --totp "${SYNO_TOTP_SECRET}" 2>/dev/null)"
|
||||||
|
else
|
||||||
|
_err "oathtool could not be found, install oathtool to use SYNO_TOTP_SECRET"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -n "$SYNO_DID" ]; then
|
if [ -n "$SYNO_DID" ]; then
|
||||||
|
@ -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() {
|
|||||||
|
|
||||||
_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() {
|
|||||||
_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() {
|
|||||||
_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() {
|
|||||||
|
|
||||||
_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() {
|
|||||||
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() {
|
|||||||
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() {
|
|||||||
|
|
||||||
_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() {
|
|||||||
_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() {
|
|||||||
_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() {
|
|||||||
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() {
|
|||||||
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() {
|
|||||||
|
|
||||||
# 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,7 +152,7 @@ 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
|
if aws_rest GET "2013-04-01/hostedzone"; then
|
||||||
|
@ -25,9 +25,15 @@ dns_cf_add() {
|
|||||||
CF_Email="${CF_Email:-$(_readaccountconf_mutable CF_Email)}"
|
CF_Email="${CF_Email:-$(_readaccountconf_mutable CF_Email)}"
|
||||||
|
|
||||||
if [ "$CF_Token" ]; then
|
if [ "$CF_Token" ]; then
|
||||||
_saveaccountconf_mutable CF_Token "$CF_Token"
|
if [ "$CF_Zone_ID" ]; then
|
||||||
_saveaccountconf_mutable CF_Account_ID "$CF_Account_ID"
|
_savedomainconf CF_Token "$CF_Token"
|
||||||
_saveaccountconf_mutable CF_Zone_ID "$CF_Zone_ID"
|
_savedomainconf CF_Account_ID "$CF_Account_ID"
|
||||||
|
_savedomainconf CF_Zone_ID "$CF_Zone_ID"
|
||||||
|
else
|
||||||
|
_saveaccountconf_mutable CF_Token "$CF_Token"
|
||||||
|
_saveaccountconf_mutable CF_Account_ID "$CF_Account_ID"
|
||||||
|
_saveaccountconf_mutable CF_Zone_ID "$CF_Zone_ID"
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
if [ -z "$CF_Key" ] || [ -z "$CF_Email" ]; then
|
if [ -z "$CF_Key" ] || [ -z "$CF_Email" ]; then
|
||||||
CF_Key=""
|
CF_Key=""
|
||||||
|
159
dnsapi/dns_curanet.sh
Normal file
159
dnsapi/dns_curanet.sh
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
#Script to use with curanet.dk, scannet.dk, wannafind.dk, dandomain.dk DNS management.
|
||||||
|
#Requires api credentials with scope: dns
|
||||||
|
#Author: Peter L. Hansen <peter@r12.dk>
|
||||||
|
#Version 1.0
|
||||||
|
|
||||||
|
CURANET_REST_URL="https://api.curanet.dk/dns/v1/Domains"
|
||||||
|
CURANET_AUTH_URL="https://apiauth.dk.team.blue/auth/realms/Curanet/protocol/openid-connect/token"
|
||||||
|
CURANET_ACCESS_TOKEN=""
|
||||||
|
|
||||||
|
######## Public functions #####################
|
||||||
|
|
||||||
|
#Usage: dns_curanet_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||||
|
dns_curanet_add() {
|
||||||
|
fulldomain=$1
|
||||||
|
txtvalue=$2
|
||||||
|
_info "Using curanet"
|
||||||
|
_debug fulldomain "$fulldomain"
|
||||||
|
_debug txtvalue "$txtvalue"
|
||||||
|
|
||||||
|
CURANET_AUTHCLIENTID="${CURANET_AUTHCLIENTID:-$(_readaccountconf_mutable CURANET_AUTHCLIENTID)}"
|
||||||
|
CURANET_AUTHSECRET="${CURANET_AUTHSECRET:-$(_readaccountconf_mutable CURANET_AUTHSECRET)}"
|
||||||
|
if [ -z "$CURANET_AUTHCLIENTID" ] || [ -z "$CURANET_AUTHSECRET" ]; then
|
||||||
|
CURANET_AUTHCLIENTID=""
|
||||||
|
CURANET_AUTHSECRET=""
|
||||||
|
_err "You don't specify curanet api client and secret."
|
||||||
|
_err "Please create your auth info and try again."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
#save the credentials to the account conf file.
|
||||||
|
_saveaccountconf_mutable CURANET_AUTHCLIENTID "$CURANET_AUTHCLIENTID"
|
||||||
|
_saveaccountconf_mutable CURANET_AUTHSECRET "$CURANET_AUTHSECRET"
|
||||||
|
|
||||||
|
if ! _get_token; then
|
||||||
|
_err "Unable to get token"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! _get_root "$fulldomain"; then
|
||||||
|
_err "Invalid domain"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
export _H1="Content-Type: application/json-patch+json"
|
||||||
|
export _H2="Accept: application/json"
|
||||||
|
export _H3="Authorization: Bearer $CURANET_ACCESS_TOKEN"
|
||||||
|
data="{\"name\": \"$fulldomain\",\"type\": \"TXT\",\"ttl\": 60,\"priority\": 0,\"data\": \"$txtvalue\"}"
|
||||||
|
response="$(_post "$data" "$CURANET_REST_URL/${_domain}/Records" "" "")"
|
||||||
|
|
||||||
|
if _contains "$response" "$txtvalue"; then
|
||||||
|
_debug "TXT record added OK"
|
||||||
|
else
|
||||||
|
_err "Unable to add TXT record"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
#Usage: fulldomain txtvalue
|
||||||
|
#Remove the txt record after validation.
|
||||||
|
dns_curanet_rm() {
|
||||||
|
fulldomain=$1
|
||||||
|
txtvalue=$2
|
||||||
|
_info "Using curanet"
|
||||||
|
_debug fulldomain "$fulldomain"
|
||||||
|
_debug txtvalue "$txtvalue"
|
||||||
|
|
||||||
|
CURANET_AUTHCLIENTID="${CURANET_AUTHCLIENTID:-$(_readaccountconf_mutable CURANET_AUTHCLIENTID)}"
|
||||||
|
CURANET_AUTHSECRET="${CURANET_AUTHSECRET:-$(_readaccountconf_mutable CURANET_AUTHSECRET)}"
|
||||||
|
|
||||||
|
if ! _get_token; then
|
||||||
|
_err "Unable to get token"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! _get_root "$fulldomain"; then
|
||||||
|
_err "Invalid domain"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_debug "Getting current record list to identify TXT to delete"
|
||||||
|
|
||||||
|
export _H1="Content-Type: application/json"
|
||||||
|
export _H2="Accept: application/json"
|
||||||
|
export _H3="Authorization: Bearer $CURANET_ACCESS_TOKEN"
|
||||||
|
|
||||||
|
response="$(_get "$CURANET_REST_URL/${_domain}/Records" "" "")"
|
||||||
|
|
||||||
|
if ! _contains "$response" "$txtvalue"; then
|
||||||
|
_err "Unable to delete record (does not contain $txtvalue )"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
recordid=$(echo "$response" | _egrep_o "{\"id\":[0-9]+,\"name\":\"$fulldomain\",\"type\":\"TXT\",\"ttl\":60,\"priority\":0,\"data\":\"..$txtvalue" | _egrep_o "id\":[0-9]+" | cut -c 5-)
|
||||||
|
|
||||||
|
if [ -z "$recordid" ]; then
|
||||||
|
_err "Unable to get recordid"
|
||||||
|
_debug "regex {\"id\":[0-9]+,\"name\":\"$fulldomain\",\"type\":\"TXT\",\"ttl\":60,\"priority\":0,\"data\":\"..$txtvalue"
|
||||||
|
_debug "response $response"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_debug "Deleting recordID $recordid"
|
||||||
|
response="$(_post "" "$CURANET_REST_URL/${_domain}/Records/$recordid" "" "DELETE")"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
#################### Private functions below ##################################
|
||||||
|
|
||||||
|
_get_token() {
|
||||||
|
response="$(_post "grant_type=client_credentials&client_id=$CURANET_AUTHCLIENTID&client_secret=$CURANET_AUTHSECRET&scope=dns" "$CURANET_AUTH_URL" "" "")"
|
||||||
|
if ! _contains "$response" "access_token"; then
|
||||||
|
_err "Unable get access token"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
CURANET_ACCESS_TOKEN=$(echo "$response" | _egrep_o "\"access_token\":\"[^\"]+" | cut -c 17-)
|
||||||
|
|
||||||
|
if [ -z "$CURANET_ACCESS_TOKEN" ]; then
|
||||||
|
_err "Unable to get token"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#_acme-challenge.www.domain.com
|
||||||
|
#returns
|
||||||
|
# _domain=domain.com
|
||||||
|
# _domain_id=sdjkglgdfewsdfg
|
||||||
|
_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
|
||||||
|
|
||||||
|
export _H1="Content-Type: application/json"
|
||||||
|
export _H2="Accept: application/json"
|
||||||
|
export _H3="Authorization: Bearer $CURANET_ACCESS_TOKEN"
|
||||||
|
response="$(_get "$CURANET_REST_URL/$h/Records" "" "")"
|
||||||
|
|
||||||
|
if [ ! "$(echo "$response" | _egrep_o "Entity not found")" ]; then
|
||||||
|
_domain=$h
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
i=$(_math "$i" + 1)
|
||||||
|
done
|
||||||
|
return 1
|
||||||
|
}
|
185
dnsapi/dns_cx.sh
185
dnsapi/dns_cx.sh
@ -1,185 +0,0 @@
|
|||||||
#!/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'
|
|
||||||
|
|
||||||
}
|
|
146
dnsapi/dns_fornex.sh
Normal file
146
dnsapi/dns_fornex.sh
Normal file
@ -0,0 +1,146 @@
|
|||||||
|
#!/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
|
||||||
|
}
|
@ -1,177 +0,0 @@
|
|||||||
#!/usr/bin/env sh
|
|
||||||
#Author: Herman Sletteng
|
|
||||||
#Report Bugs here: https://github.com/loial/acme.sh
|
|
||||||
#
|
|
||||||
#
|
|
||||||
# Note, gratisdns requires a login first, so the script needs to handle
|
|
||||||
# temporary cookies. Since acme.sh _get/_post currently don't directly support
|
|
||||||
# cookies, I've defined wrapper functions _myget/_mypost to set the headers
|
|
||||||
|
|
||||||
GDNSDK_API="https://admin.gratisdns.com"
|
|
||||||
######## Public functions #####################
|
|
||||||
#Usage: dns_gdnsdk_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
|
||||||
dns_gdnsdk_add() {
|
|
||||||
fulldomain=$1
|
|
||||||
txtvalue=$2
|
|
||||||
_info "Using gratisdns.dk"
|
|
||||||
_debug fulldomain "$fulldomain"
|
|
||||||
_debug txtvalue "$txtvalue"
|
|
||||||
if ! _gratisdns_login; then
|
|
||||||
_err "Login failed!"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
#finding domain zone
|
|
||||||
if ! _get_domain; then
|
|
||||||
_err "No matching root domain for $fulldomain found"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
# adding entry
|
|
||||||
_info "Adding the entry"
|
|
||||||
_mypost "action=dns_primary_record_added_txt&user_domain=$_domain&name=$fulldomain&txtdata=$txtvalue&ttl=1"
|
|
||||||
if _successful_update; then return 0; fi
|
|
||||||
_err "Couldn't create entry!"
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
#Usage: fulldomain txtvalue
|
|
||||||
#Remove the txt record after validation.
|
|
||||||
dns_gdnsdk_rm() {
|
|
||||||
fulldomain=$1
|
|
||||||
txtvalue=$2
|
|
||||||
_info "Using gratisdns.dk"
|
|
||||||
_debug fulldomain "$fulldomain"
|
|
||||||
_debug txtvalue "$txtvalue"
|
|
||||||
if ! _gratisdns_login; then
|
|
||||||
_err "Login failed!"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
if ! _get_domain; then
|
|
||||||
_err "No matching root domain for $fulldomain found"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
_findentry "$fulldomain" "$txtvalue"
|
|
||||||
if [ -z "$_id" ]; then
|
|
||||||
_info "Entry doesn't exist, nothing to delete"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
_debug "Deleting record..."
|
|
||||||
_mypost "action=dns_primary_delete_txt&user_domain=$_domain&id=$_id"
|
|
||||||
# removing entry
|
|
||||||
|
|
||||||
if _successful_update; then return 0; fi
|
|
||||||
_err "Couldn't delete entry!"
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
#################### Private functions below ##################################
|
|
||||||
|
|
||||||
_checkcredentials() {
|
|
||||||
GDNSDK_Username="${GDNSDK_Username:-$(_readaccountconf_mutable GDNSDK_Username)}"
|
|
||||||
GDNSDK_Password="${GDNSDK_Password:-$(_readaccountconf_mutable GDNSDK_Password)}"
|
|
||||||
|
|
||||||
if [ -z "$GDNSDK_Username" ] || [ -z "$GDNSDK_Password" ]; then
|
|
||||||
GDNSDK_Username=""
|
|
||||||
GDNSDK_Password=""
|
|
||||||
_err "You haven't specified gratisdns.dk username and password yet."
|
|
||||||
_err "Please add credentials and try again."
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
#save the credentials to the account conf file.
|
|
||||||
_saveaccountconf_mutable GDNSDK_Username "$GDNSDK_Username"
|
|
||||||
_saveaccountconf_mutable GDNSDK_Password "$GDNSDK_Password"
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
_checkcookie() {
|
|
||||||
GDNSDK_Cookie="${GDNSDK_Cookie:-$(_readaccountconf_mutable GDNSDK_Cookie)}"
|
|
||||||
if [ -z "$GDNSDK_Cookie" ]; then
|
|
||||||
_debug "No cached cookie found"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
_myget "action="
|
|
||||||
if (echo "$_result" | grep -q "logmeout"); then
|
|
||||||
_debug "Cached cookie still valid"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
_debug "Cached cookie no longer valid"
|
|
||||||
GDNSDK_Cookie=""
|
|
||||||
_saveaccountconf_mutable GDNSDK_Cookie "$GDNSDK_Cookie"
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
_gratisdns_login() {
|
|
||||||
if ! _checkcredentials; then return 1; fi
|
|
||||||
|
|
||||||
if _checkcookie; then
|
|
||||||
_debug "Already logged in"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
_debug "Logging into GratisDNS with user $GDNSDK_Username"
|
|
||||||
|
|
||||||
if ! _mypost "login=$GDNSDK_Username&password=$GDNSDK_Password&action=logmein"; then
|
|
||||||
_err "GratisDNS login failed for user $GDNSDK_Username bad RC from _post"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
GDNSDK_Cookie="$(grep -A 15 '302 Found' "$HTTP_HEADER" | _egrep_o 'Cookie: [^;]*' | _head_n 1 | cut -d ' ' -f2)"
|
|
||||||
|
|
||||||
if [ -z "$GDNSDK_Cookie" ]; then
|
|
||||||
_err "GratisDNS login failed for user $GDNSDK_Username. Check $HTTP_HEADER file"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
export GDNSDK_Cookie
|
|
||||||
_saveaccountconf_mutable GDNSDK_Cookie "$GDNSDK_Cookie"
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
_myget() {
|
|
||||||
#Adds cookie to request
|
|
||||||
export _H1="Cookie: $GDNSDK_Cookie"
|
|
||||||
_result=$(_get "$GDNSDK_API?$1")
|
|
||||||
}
|
|
||||||
_mypost() {
|
|
||||||
#Adds cookie to request
|
|
||||||
export _H1="Cookie: $GDNSDK_Cookie"
|
|
||||||
_result=$(_post "$1" "$GDNSDK_API")
|
|
||||||
}
|
|
||||||
|
|
||||||
_get_domain() {
|
|
||||||
_myget 'action=dns_primarydns'
|
|
||||||
_domains=$(echo "$_result" | _egrep_o ' domain="[[:alnum:]._-]+' | sed 's/^.*"//')
|
|
||||||
if [ -z "$_domains" ]; then
|
|
||||||
_err "Primary domain list not found!"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
for _domain in $_domains; do
|
|
||||||
if (_endswith "$fulldomain" "$_domain"); then
|
|
||||||
_debug "Root domain: $_domain"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
done
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
_successful_update() {
|
|
||||||
if (echo "$_result" | grep -q 'table-success'); then return 0; fi
|
|
||||||
return 1
|
|
||||||
}
|
|
||||||
|
|
||||||
_findentry() {
|
|
||||||
#args $1: fulldomain, $2: txtvalue
|
|
||||||
#returns id of dns entry, if it exists
|
|
||||||
_myget "action=dns_primary_changeDNSsetup&user_domain=$_domain"
|
|
||||||
_debug3 "_result: $_result"
|
|
||||||
|
|
||||||
_tmp_result=$(echo "$_result" | tr -d '\n\r' | _egrep_o "<td>$1</td>\s*<td>$2</td>[^?]*[^&]*&id=[^&]*")
|
|
||||||
_debug _tmp_result "$_tmp_result"
|
|
||||||
if [ -z "${_tmp_result:-}" ]; then
|
|
||||||
_debug "The variable is _tmp_result is not supposed to be empty, there may be something wrong with the script"
|
|
||||||
fi
|
|
||||||
|
|
||||||
_id=$(echo "$_tmp_result" | sed 's/^.*=//')
|
|
||||||
if [ -n "$_id" ]; then
|
|
||||||
_debug "Entry found with _id=$_id"
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
return 1
|
|
||||||
}
|
|
232
dnsapi/dns_geoscaling.sh
Executable file
232
dnsapi/dns_geoscaling.sh
Executable file
@ -0,0 +1,232 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
# Geoscaling hook script for acme.sh
|
||||||
|
#
|
||||||
|
# Environment variables:
|
||||||
|
#
|
||||||
|
# - $GEOSCALING_Username (your Geoscaling username - this is usually NOT an amail address)
|
||||||
|
# - $GEOSCALING_Password (your Geoscaling password)
|
||||||
|
|
||||||
|
#-- dns_geoscaling_add() - Add TXT record --------------------------------------
|
||||||
|
# Usage: dns_geoscaling_add _acme-challenge.subdomain.domain.com "XyZ123..."
|
||||||
|
|
||||||
|
dns_geoscaling_add() {
|
||||||
|
full_domain=$1
|
||||||
|
txt_value=$2
|
||||||
|
_info "Using DNS-01 Geoscaling DNS2 hook"
|
||||||
|
|
||||||
|
GEOSCALING_Username="${GEOSCALING_Username:-$(_readaccountconf_mutable GEOSCALING_Username)}"
|
||||||
|
GEOSCALING_Password="${GEOSCALING_Password:-$(_readaccountconf_mutable GEOSCALING_Password)}"
|
||||||
|
if [ -z "$GEOSCALING_Username" ] || [ -z "$GEOSCALING_Password" ]; then
|
||||||
|
GEOSCALING_Username=
|
||||||
|
GEOSCALING_Password=
|
||||||
|
_err "No auth details provided. Please set user credentials using the \$GEOSCALING_Username and \$GEOSCALING_Password environment variables."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_saveaccountconf_mutable GEOSCALING_Username "${GEOSCALING_Username}"
|
||||||
|
_saveaccountconf_mutable GEOSCALING_Password "${GEOSCALING_Password}"
|
||||||
|
|
||||||
|
# Fills in the $zone_id and $zone_name
|
||||||
|
find_zone "${full_domain}" || return 1
|
||||||
|
_debug "Zone id '${zone_id}' will be used."
|
||||||
|
|
||||||
|
# We're logged in here
|
||||||
|
|
||||||
|
# we should add ${full_domain} minus the trailing ${zone_name}
|
||||||
|
|
||||||
|
prefix=$(echo "${full_domain}" | sed "s|\\.${zone_name}\$||")
|
||||||
|
|
||||||
|
body="id=${zone_id}&name=${prefix}&type=TXT&content=${txt_value}&ttl=300&prio=0"
|
||||||
|
|
||||||
|
do_post "$body" "https://www.geoscaling.com/dns2/ajax/add_record.php"
|
||||||
|
exit_code="$?"
|
||||||
|
if [ "${exit_code}" -eq 0 ]; then
|
||||||
|
_info "TXT record added successfully."
|
||||||
|
else
|
||||||
|
_err "Couldn't add the TXT record."
|
||||||
|
fi
|
||||||
|
do_logout
|
||||||
|
return "${exit_code}"
|
||||||
|
}
|
||||||
|
|
||||||
|
#-- dns_geoscaling_rm() - Remove TXT record ------------------------------------
|
||||||
|
# Usage: dns_geoscaling_rm _acme-challenge.subdomain.domain.com "XyZ123..."
|
||||||
|
|
||||||
|
dns_geoscaling_rm() {
|
||||||
|
full_domain=$1
|
||||||
|
txt_value=$2
|
||||||
|
_info "Cleaning up after DNS-01 Geoscaling DNS2 hook"
|
||||||
|
|
||||||
|
GEOSCALING_Username="${GEOSCALING_Username:-$(_readaccountconf_mutable GEOSCALING_Username)}"
|
||||||
|
GEOSCALING_Password="${GEOSCALING_Password:-$(_readaccountconf_mutable GEOSCALING_Password)}"
|
||||||
|
if [ -z "$GEOSCALING_Username" ] || [ -z "$GEOSCALING_Password" ]; then
|
||||||
|
GEOSCALING_Username=
|
||||||
|
GEOSCALING_Password=
|
||||||
|
_err "No auth details provided. Please set user credentials using the \$GEOSCALING_Username and \$GEOSCALING_Password environment variables."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_saveaccountconf_mutable GEOSCALING_Username "${GEOSCALING_Username}"
|
||||||
|
_saveaccountconf_mutable GEOSCALING_Password "${GEOSCALING_Password}"
|
||||||
|
|
||||||
|
# fills in the $zone_id
|
||||||
|
find_zone "${full_domain}" || return 1
|
||||||
|
_debug "Zone id '${zone_id}' will be used."
|
||||||
|
|
||||||
|
# Here we're logged in
|
||||||
|
# Find the record id to clean
|
||||||
|
|
||||||
|
# get the domain
|
||||||
|
response=$(do_get "https://www.geoscaling.com/dns2/index.php?module=domain&id=${zone_id}")
|
||||||
|
_debug2 "response" "$response"
|
||||||
|
|
||||||
|
table="$(echo "${response}" | tr -d '\n' | sed 's|.*<div class="box"><div class="boxtitle">Basic Records</div><div class="boxtext"><table|<table|; s|</table>.*|</table>|')"
|
||||||
|
_debug2 table "${table}"
|
||||||
|
names=$(echo "${table}" | _egrep_o 'id="[0-9]+\.name">[^<]*</td>' | sed 's|</td>||; s|.*>||')
|
||||||
|
ids=$(echo "${table}" | _egrep_o 'id="[0-9]+\.name">[^<]*</td>' | sed 's|\.name">.*||; s|id="||')
|
||||||
|
types=$(echo "${table}" | _egrep_o 'id="[0-9]+\.type">[^<]*</td>' | sed 's|</td>||; s|.*>||')
|
||||||
|
values=$(echo "${table}" | _egrep_o 'id="[0-9]+\.content">[^<]*</td>' | sed 's|</td>||; s|.*>||')
|
||||||
|
|
||||||
|
_debug2 names "${names}"
|
||||||
|
_debug2 ids "${ids}"
|
||||||
|
_debug2 types "${types}"
|
||||||
|
_debug2 values "${values}"
|
||||||
|
|
||||||
|
# look for line whose name is ${full_domain}, whose type is TXT, and whose value is ${txt_value}
|
||||||
|
line_num="$(echo "${values}" | grep -F -n -- "${txt_value}" | _head_n 1 | cut -d ':' -f 1)"
|
||||||
|
_debug2 line_num "${line_num}"
|
||||||
|
found_id=
|
||||||
|
if [ -n "$line_num" ]; then
|
||||||
|
type=$(echo "${types}" | sed -n "${line_num}p")
|
||||||
|
name=$(echo "${names}" | sed -n "${line_num}p")
|
||||||
|
id=$(echo "${ids}" | sed -n "${line_num}p")
|
||||||
|
|
||||||
|
_debug2 type "$type"
|
||||||
|
_debug2 name "$name"
|
||||||
|
_debug2 id "$id"
|
||||||
|
_debug2 full_domain "$full_domain"
|
||||||
|
|
||||||
|
if [ "${type}" = "TXT" ] && [ "${name}" = "${full_domain}" ]; then
|
||||||
|
found_id=${id}
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${found_id}" = "" ]; then
|
||||||
|
_err "Can not find record id."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Remove the record
|
||||||
|
body="id=${zone_id}&record_id=${found_id}"
|
||||||
|
response=$(do_post "$body" "https://www.geoscaling.com/dns2/ajax/delete_record.php")
|
||||||
|
exit_code="$?"
|
||||||
|
if [ "$exit_code" -eq 0 ]; then
|
||||||
|
_info "Record removed successfully."
|
||||||
|
else
|
||||||
|
_err "Could not clean (remove) up the record. Please go to Geoscaling administration interface and clean it by hand."
|
||||||
|
fi
|
||||||
|
do_logout
|
||||||
|
return "${exit_code}"
|
||||||
|
}
|
||||||
|
|
||||||
|
########################## PRIVATE FUNCTIONS ###########################
|
||||||
|
|
||||||
|
do_get() {
|
||||||
|
_url=$1
|
||||||
|
export _H1="Cookie: $geoscaling_phpsessid_cookie"
|
||||||
|
_get "${_url}"
|
||||||
|
}
|
||||||
|
|
||||||
|
do_post() {
|
||||||
|
_body=$1
|
||||||
|
_url=$2
|
||||||
|
export _H1="Cookie: $geoscaling_phpsessid_cookie"
|
||||||
|
_post "${_body}" "${_url}"
|
||||||
|
}
|
||||||
|
|
||||||
|
do_login() {
|
||||||
|
|
||||||
|
_info "Logging in..."
|
||||||
|
|
||||||
|
username_encoded="$(printf "%s" "${GEOSCALING_Username}" | _url_encode)"
|
||||||
|
password_encoded="$(printf "%s" "${GEOSCALING_Password}" | _url_encode)"
|
||||||
|
body="username=${username_encoded}&password=${password_encoded}"
|
||||||
|
|
||||||
|
response=$(_post "$body" "https://www.geoscaling.com/dns2/index.php?module=auth")
|
||||||
|
_debug2 response "${response}"
|
||||||
|
|
||||||
|
#retcode=$(grep '^HTTP[^ ]*' "${HTTP_HEADER}" | _head_n 1 | _egrep_o '[0-9]+$')
|
||||||
|
retcode=$(grep '^HTTP[^ ]*' "${HTTP_HEADER}" | _head_n 1 | cut -d ' ' -f 2)
|
||||||
|
|
||||||
|
if [ "$retcode" != "302" ]; then
|
||||||
|
_err "Geoscaling login failed for user ${GEOSCALING_Username}. Check ${HTTP_HEADER} file"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
geoscaling_phpsessid_cookie="$(grep -i '^set-cookie:' "${HTTP_HEADER}" | _egrep_o 'PHPSESSID=[^;]*;' | tr -d ';')"
|
||||||
|
return 0
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
do_logout() {
|
||||||
|
_info "Logging out."
|
||||||
|
response="$(do_get "https://www.geoscaling.com/dns2/index.php?module=auth")"
|
||||||
|
_debug2 response "$response"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
find_zone() {
|
||||||
|
domain="$1"
|
||||||
|
|
||||||
|
# do login
|
||||||
|
do_login || return 1
|
||||||
|
|
||||||
|
# get zones
|
||||||
|
response="$(do_get "https://www.geoscaling.com/dns2/index.php?module=domains")"
|
||||||
|
|
||||||
|
table="$(echo "${response}" | tr -d '\n' | sed 's|.*<div class="box"><div class="boxtitle">Your domains</div><div class="boxtext"><table|<table|; s|</table>.*|</table>|')"
|
||||||
|
_debug2 table "${table}"
|
||||||
|
zone_names="$(echo "${table}" | _egrep_o '<b>[^<]*</b>' | sed 's|<b>||;s|</b>||')"
|
||||||
|
_debug2 _matches "${zone_names}"
|
||||||
|
# Zone names and zone IDs are in same order
|
||||||
|
zone_ids=$(echo "${table}" | _egrep_o '<a href=.index\.php\?module=domain&id=[0-9]+. onclick="javascript:show_loader\(\);">' | sed 's|.*id=||;s|. .*||')
|
||||||
|
|
||||||
|
_debug2 "These are the zones on this Geoscaling account:"
|
||||||
|
_debug2 "zone_names" "${zone_names}"
|
||||||
|
_debug2 "And these are their respective IDs:"
|
||||||
|
_debug2 "zone_ids" "${zone_ids}"
|
||||||
|
if [ -z "${zone_names}" ] || [ -z "${zone_ids}" ]; then
|
||||||
|
_err "Can not get zone names or IDs."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
# Walk through all possible zone names
|
||||||
|
strip_counter=1
|
||||||
|
while true; do
|
||||||
|
attempted_zone=$(echo "${domain}" | cut -d . -f ${strip_counter}-)
|
||||||
|
|
||||||
|
# All possible zone names have been tried
|
||||||
|
if [ -z "${attempted_zone}" ]; then
|
||||||
|
_err "No zone for domain '${domain}' found."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_debug "Looking for zone '${attempted_zone}'"
|
||||||
|
|
||||||
|
line_num="$(echo "${zone_names}" | grep -n "^${attempted_zone}\$" | _head_n 1 | cut -d : -f 1)"
|
||||||
|
_debug2 line_num "${line_num}"
|
||||||
|
if [ "$line_num" ]; then
|
||||||
|
zone_id=$(echo "${zone_ids}" | sed -n "${line_num}p")
|
||||||
|
zone_name=$(echo "${zone_names}" | sed -n "${line_num}p")
|
||||||
|
if [ -z "${zone_id}" ]; then
|
||||||
|
_err "Can not find zone id."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_debug "Found relevant zone '${attempted_zone}' with id '${zone_id}' - will be used for domain '${domain}'."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
_debug "Zone '${attempted_zone}' doesn't exist, let's try a less specific zone."
|
||||||
|
strip_counter=$(_math "${strip_counter}" + 1)
|
||||||
|
done
|
||||||
|
}
|
||||||
|
# vim: et:ts=2:sw=2:
|
@ -32,7 +32,7 @@ dns_ispconfig_rm() {
|
|||||||
#################### Private functions below ##################################
|
#################### Private functions below ##################################
|
||||||
|
|
||||||
_ISPC_credentials() {
|
_ISPC_credentials() {
|
||||||
if [ -z "${ISPC_User}" ] || [ -z "$ISPC_Password" ] || [ -z "${ISPC_Api}" ] || [ -n "${ISPC_Api_Insecure}" ]; then
|
if [ -z "${ISPC_User}" ] || [ -z "${ISPC_Password}" ] || [ -z "${ISPC_Api}" ] || [ -z "${ISPC_Api_Insecure}" ]; then
|
||||||
ISPC_User=""
|
ISPC_User=""
|
||||||
ISPC_Password=""
|
ISPC_Password=""
|
||||||
ISPC_Api=""
|
ISPC_Api=""
|
||||||
|
@ -32,8 +32,12 @@ dns_loopia_add() {
|
|||||||
|
|
||||||
_info "Adding record"
|
_info "Adding record"
|
||||||
|
|
||||||
_loopia_add_sub_domain "$_domain" "$_sub_domain"
|
if ! _loopia_add_sub_domain "$_domain" "$_sub_domain"; then
|
||||||
_loopia_add_record "$_domain" "$_sub_domain" "$txtvalue"
|
return 1
|
||||||
|
fi
|
||||||
|
if ! _loopia_add_record "$_domain" "$_sub_domain" "$txtvalue"; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,12 +74,13 @@ dns_loopia_rm() {
|
|||||||
<value><string>%s</string></value>
|
<value><string>%s</string></value>
|
||||||
</param>
|
</param>
|
||||||
</params>
|
</params>
|
||||||
</methodCall>' "$LOOPIA_User" "$LOOPIA_Password" "$_domain" "$_sub_domain")
|
</methodCall>' "$LOOPIA_User" "$Encoded_Password" "$_domain" "$_sub_domain")
|
||||||
|
|
||||||
response="$(_post "$xml_content" "$LOOPIA_Api" "" "POST")"
|
response="$(_post "$xml_content" "$LOOPIA_Api" "" "POST")"
|
||||||
|
|
||||||
if ! _contains "$response" "OK"; then
|
if ! _contains "$response" "OK"; then
|
||||||
_err "Error could not get txt records"
|
err_response=$(echo "$response" | sed 's/.*<string>\(.*\)<\/string>.*/\1/')
|
||||||
|
_err "Error could not get txt records: $err_response"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
@ -101,6 +106,12 @@ _loopia_load_config() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if _contains "$LOOPIA_Password" "'" || _contains "$LOOPIA_Password" '"'; then
|
||||||
|
_err "Password contains quoute or double quoute and this is not supported by dns_loopia.sh"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
Encoded_Password=$(_xml_encode "$LOOPIA_Password")
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -133,11 +144,12 @@ _loopia_get_records() {
|
|||||||
<value><string>%s</string></value>
|
<value><string>%s</string></value>
|
||||||
</param>
|
</param>
|
||||||
</params>
|
</params>
|
||||||
</methodCall>' $LOOPIA_User $LOOPIA_Password "$domain" "$sub_domain")
|
</methodCall>' "$LOOPIA_User" "$Encoded_Password" "$domain" "$sub_domain")
|
||||||
|
|
||||||
response="$(_post "$xml_content" "$LOOPIA_Api" "" "POST")"
|
response="$(_post "$xml_content" "$LOOPIA_Api" "" "POST")"
|
||||||
if ! _contains "$response" "<array>"; then
|
if ! _contains "$response" "<array>"; then
|
||||||
_err "Error"
|
err_response=$(echo "$response" | sed 's/.*<string>\(.*\)<\/string>.*/\1/')
|
||||||
|
_err "Error: $err_response"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
return 0
|
return 0
|
||||||
@ -162,7 +174,7 @@ _get_root() {
|
|||||||
<value><string>%s</string></value>
|
<value><string>%s</string></value>
|
||||||
</param>
|
</param>
|
||||||
</params>
|
</params>
|
||||||
</methodCall>' $LOOPIA_User $LOOPIA_Password)
|
</methodCall>' "$LOOPIA_User" "$Encoded_Password")
|
||||||
|
|
||||||
response="$(_post "$xml_content" "$LOOPIA_Api" "" "POST")"
|
response="$(_post "$xml_content" "$LOOPIA_Api" "" "POST")"
|
||||||
while true; do
|
while true; do
|
||||||
@ -206,32 +218,35 @@ _loopia_add_record() {
|
|||||||
<value><string>%s</string></value>
|
<value><string>%s</string></value>
|
||||||
</param>
|
</param>
|
||||||
<param>
|
<param>
|
||||||
<struct>
|
<value>
|
||||||
<member>
|
<struct>
|
||||||
<name>type</name>
|
<member>
|
||||||
<value><string>TXT</string></value>
|
<name>type</name>
|
||||||
</member>
|
<value><string>TXT</string></value>
|
||||||
<member>
|
</member>
|
||||||
<name>priority</name>
|
<member>
|
||||||
<value><int>0</int></value>
|
<name>priority</name>
|
||||||
</member>
|
<value><int>0</int></value>
|
||||||
<member>
|
</member>
|
||||||
<name>ttl</name>
|
<member>
|
||||||
<value><int>300</int></value>
|
<name>ttl</name>
|
||||||
</member>
|
<value><int>300</int></value>
|
||||||
<member>
|
</member>
|
||||||
<name>rdata</name>
|
<member>
|
||||||
<value><string>%s</string></value>
|
<name>rdata</name>
|
||||||
</member>
|
<value><string>%s</string></value>
|
||||||
</struct>
|
</member>
|
||||||
|
</struct>
|
||||||
|
</value>
|
||||||
</param>
|
</param>
|
||||||
</params>
|
</params>
|
||||||
</methodCall>' $LOOPIA_User $LOOPIA_Password "$domain" "$sub_domain" "$txtval")
|
</methodCall>' "$LOOPIA_User" "$Encoded_Password" "$domain" "$sub_domain" "$txtval")
|
||||||
|
|
||||||
response="$(_post "$xml_content" "$LOOPIA_Api" "" "POST")"
|
response="$(_post "$xml_content" "$LOOPIA_Api" "" "POST")"
|
||||||
|
|
||||||
if ! _contains "$response" "OK"; then
|
if ! _contains "$response" "OK"; then
|
||||||
_err "Error"
|
err_response=$(echo "$response" | sed 's/.*<string>\(.*\)<\/string>.*/\1/')
|
||||||
|
_err "Error: $err_response"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
return 0
|
return 0
|
||||||
@ -255,7 +270,7 @@ _sub_domain_exists() {
|
|||||||
<value><string>%s</string></value>
|
<value><string>%s</string></value>
|
||||||
</param>
|
</param>
|
||||||
</params>
|
</params>
|
||||||
</methodCall>' $LOOPIA_User $LOOPIA_Password "$domain")
|
</methodCall>' "$LOOPIA_User" "$Encoded_Password" "$domain")
|
||||||
|
|
||||||
response="$(_post "$xml_content" "$LOOPIA_Api" "" "POST")"
|
response="$(_post "$xml_content" "$LOOPIA_Api" "" "POST")"
|
||||||
|
|
||||||
@ -290,13 +305,22 @@ _loopia_add_sub_domain() {
|
|||||||
<value><string>%s</string></value>
|
<value><string>%s</string></value>
|
||||||
</param>
|
</param>
|
||||||
</params>
|
</params>
|
||||||
</methodCall>' $LOOPIA_User $LOOPIA_Password "$domain" "$sub_domain")
|
</methodCall>' "$LOOPIA_User" "$Encoded_Password" "$domain" "$sub_domain")
|
||||||
|
|
||||||
response="$(_post "$xml_content" "$LOOPIA_Api" "" "POST")"
|
response="$(_post "$xml_content" "$LOOPIA_Api" "" "POST")"
|
||||||
|
|
||||||
if ! _contains "$response" "OK"; then
|
if ! _contains "$response" "OK"; then
|
||||||
_err "Error"
|
err_response=$(echo "$response" | sed 's/.*<string>\(.*\)<\/string>.*/\1/')
|
||||||
|
_err "Error: $err_response"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_xml_encode() {
|
||||||
|
encoded_string=$1
|
||||||
|
encoded_string=$(echo "$encoded_string" | sed 's/&/\&/')
|
||||||
|
encoded_string=$(echo "$encoded_string" | sed 's/</\</')
|
||||||
|
encoded_string=$(echo "$encoded_string" | sed 's/>/\>/')
|
||||||
|
printf "%s" "$encoded_string"
|
||||||
|
}
|
||||||
|
@ -74,7 +74,7 @@ dns_mydevil_rm() {
|
|||||||
validRecords="^${num}${w}${fulldomain}${w}TXT${w}${any}${txtvalue}$"
|
validRecords="^${num}${w}${fulldomain}${w}TXT${w}${any}${txtvalue}$"
|
||||||
for id in $(devil dns list "$domain" | tail -n+2 | grep "${validRecords}" | cut -w -s -f 1); do
|
for id in $(devil dns list "$domain" | tail -n+2 | grep "${validRecords}" | cut -w -s -f 1); do
|
||||||
_info "Removing record $id from domain $domain"
|
_info "Removing record $id from domain $domain"
|
||||||
devil dns del "$domain" "$id" || _err "Could not remove DNS record."
|
echo "y" | devil dns del "$domain" "$id" || _err "Could not remove DNS record."
|
||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,7 +87,9 @@ mydevil_get_domain() {
|
|||||||
domain=""
|
domain=""
|
||||||
|
|
||||||
for domain in $(devil dns list | cut -w -s -f 1 | tail -n+2); do
|
for domain in $(devil dns list | cut -w -s -f 1 | tail -n+2); do
|
||||||
|
_debug "Checking domain: $domain"
|
||||||
if _endswith "$fulldomain" "$domain"; then
|
if _endswith "$fulldomain" "$domain"; then
|
||||||
|
_debug "Fulldomain '$fulldomain' matches '$domain'"
|
||||||
printf -- "%s" "$domain"
|
printf -- "%s" "$domain"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
@ -114,7 +114,7 @@ _get_root() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if _contains "$response" "\"name\":\"$h\"" >/dev/null; then
|
if _contains "$response" "\"name\":\"$h\"" >/dev/null; then
|
||||||
_domain_id=$(echo "$response" | _egrep_o "\"[^\"]*\",\"name\":\"$h" | cut -d , -f 1 | tr -d \")
|
_domain_id=$(echo "$response" | _egrep_o "\"[^\"]*\",\"name\":\"$h\"" | cut -d , -f 1 | tr -d \")
|
||||||
if [ "$_domain_id" ]; then
|
if [ "$_domain_id" ]; then
|
||||||
if [ "$i" = 1 ]; then
|
if [ "$i" = 1 ]; then
|
||||||
#create the record at the domain apex (@) if only the domain name was provided as --domain-alias
|
#create the record at the domain apex (@) if only the domain name was provided as --domain-alias
|
||||||
|
@ -150,8 +150,7 @@ _get_root() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
_debug h "$h"
|
_debug h "$h"
|
||||||
id=$(echo "$_domain_response" | _egrep_o "\"[^\"]*\":{\"enabled\":\"1\",\"type\":{\"master\":{\"value\":\"master\",\"selected\":1},\"slave\":{\"value\":\"slave\",\"selected\":0}},\"masterip\":{\"\":{[^}]*}}(,\"allownotifyslave\":{\"\":{[^}]*}},|,)\"domainname\":\"${h}\"" | cut -d ':' -f 1 | cut -d '"' -f 2)
|
id=$(echo "$_domain_response" | _egrep_o "\"[^\"]*\":{\"enabled\":\"1\",\"type\":{\"master\":{\"value\":\"master\",\"selected\":1},\"slave\":{\"value\":\"slave\",\"selected\":0}},\"masterip\":{\"[^\"]*\":{[^}]*}},\"transferkeyalgo\":{[^{]*{[^{]*{[^{]*{[^{]*{[^{]*{[^{]*{[^{]*{[^}]*}},\"transferkey\":\"[^\"]*\"(,\"allownotifyslave\":{\"\":{[^}]*}},|,)\"domainname\":\"${h}\"" | cut -d ':' -f 1 | cut -d '"' -f 2)
|
||||||
|
|
||||||
if [ -n "$id" ]; then
|
if [ -n "$id" ]; then
|
||||||
_debug id "$id"
|
_debug id "$id"
|
||||||
_host=$(printf "%s" "$domain" | cut -d . -f 1-$p)
|
_host=$(printf "%s" "$domain" | cut -d . -f 1-$p)
|
||||||
|
@ -198,6 +198,8 @@ dns_ovh_rm() {
|
|||||||
if ! _ovh_rest DELETE "domain/zone/$_domain/record/$rid"; then
|
if ! _ovh_rest DELETE "domain/zone/$_domain/record/$rid"; then
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
_ovh_rest POST "domain/zone/$_domain/refresh"
|
||||||
|
_debug "Refresh:$response"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
@ -5,8 +5,8 @@
|
|||||||
#SIMPLY_AccountName="accountname"
|
#SIMPLY_AccountName="accountname"
|
||||||
#SIMPLY_ApiKey="apikey"
|
#SIMPLY_ApiKey="apikey"
|
||||||
#
|
#
|
||||||
#SIMPLY_Api="https://api.simply.com/1/[ACCOUNTNAME]/[APIKEY]"
|
#SIMPLY_Api="https://api.simply.com/2/"
|
||||||
SIMPLY_Api_Default="https://api.simply.com/1"
|
SIMPLY_Api_Default="https://api.simply.com/2"
|
||||||
|
|
||||||
#This is used for determining success of REST call
|
#This is used for determining success of REST call
|
||||||
SIMPLY_SUCCESS_CODE='"status":200'
|
SIMPLY_SUCCESS_CODE='"status":200'
|
||||||
@ -237,12 +237,18 @@ _simply_rest() {
|
|||||||
_debug2 ep "$ep"
|
_debug2 ep "$ep"
|
||||||
_debug2 m "$m"
|
_debug2 m "$m"
|
||||||
|
|
||||||
export _H1="Content-Type: application/json"
|
basicauth=$(printf "%s:%s" "$SIMPLY_AccountName" "$SIMPLY_ApiKey" | _base64)
|
||||||
|
|
||||||
|
if [ "$basicauth" ]; then
|
||||||
|
export _H1="Authorization: Basic $basicauth"
|
||||||
|
fi
|
||||||
|
|
||||||
|
export _H2="Content-Type: application/json"
|
||||||
|
|
||||||
if [ "$m" != "GET" ]; then
|
if [ "$m" != "GET" ]; then
|
||||||
response="$(_post "$data" "$SIMPLY_Api/$SIMPLY_AccountName/$SIMPLY_ApiKey/$ep" "" "$m")"
|
response="$(_post "$data" "$SIMPLY_Api/$ep" "" "$m")"
|
||||||
else
|
else
|
||||||
response="$(_get "$SIMPLY_Api/$SIMPLY_AccountName/$SIMPLY_ApiKey/$ep")"
|
response="$(_get "$SIMPLY_Api/$ep")"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$?" != "0" ]; then
|
if [ "$?" != "0" ]; then
|
||||||
|
160
dnsapi/dns_udr.sh
Normal file
160
dnsapi/dns_udr.sh
Normal file
@ -0,0 +1,160 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
# united-domains Reselling (https://www.ud-reselling.com/) DNS API
|
||||||
|
# Author: Andreas Scherer (https://github.com/andischerer)
|
||||||
|
# Created: 2021-02-01
|
||||||
|
#
|
||||||
|
# Set the environment variables as below:
|
||||||
|
#
|
||||||
|
# export UDR_USER="your_username_goes_here"
|
||||||
|
# export UDR_PASS="some_password_goes_here"
|
||||||
|
#
|
||||||
|
|
||||||
|
UDR_API="https://api.domainreselling.de/api/call.cgi"
|
||||||
|
UDR_TTL="30"
|
||||||
|
|
||||||
|
######## Public functions #####################
|
||||||
|
|
||||||
|
#Usage: add _acme-challenge.www.domain.com "some_long_string_of_characters_go_here_from_lets_encrypt"
|
||||||
|
dns_udr_add() {
|
||||||
|
fulldomain=$1
|
||||||
|
txtvalue=$2
|
||||||
|
|
||||||
|
UDR_USER="${UDR_USER:-$(_readaccountconf_mutable UDR_USER)}"
|
||||||
|
UDR_PASS="${UDR_PASS:-$(_readaccountconf_mutable UDR_PASS)}"
|
||||||
|
if [ -z "$UDR_USER" ] || [ -z "$UDR_PASS" ]; then
|
||||||
|
UDR_USER=""
|
||||||
|
UDR_PASS=""
|
||||||
|
_err "You didn't specify an UD-Reselling username and password yet"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
# save the username and password to the account conf file.
|
||||||
|
_saveaccountconf_mutable UDR_USER "$UDR_USER"
|
||||||
|
_saveaccountconf_mutable UDR_PASS "$UDR_PASS"
|
||||||
|
_debug "First detect the root zone"
|
||||||
|
if ! _get_root "$fulldomain"; then
|
||||||
|
_err "invalid domain"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_debug _dnszone "${_dnszone}"
|
||||||
|
|
||||||
|
_debug "Getting txt records"
|
||||||
|
if ! _udr_rest "QueryDNSZoneRRList" "dnszone=${_dnszone}"; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
rr="${fulldomain}. ${UDR_TTL} IN TXT ${txtvalue}"
|
||||||
|
_debug resource_record "${rr}"
|
||||||
|
if _contains "$response" "$rr" >/dev/null; then
|
||||||
|
_err "Error, it would appear that this record already exists. Please review existing TXT records for this domain."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_info "Adding record"
|
||||||
|
if ! _udr_rest "UpdateDNSZone" "dnszone=${_dnszone}&addrr0=${rr}"; then
|
||||||
|
_err "Adding the record did not succeed, please verify/check."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_info "Added, OK"
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
dns_udr_rm() {
|
||||||
|
fulldomain=$1
|
||||||
|
txtvalue=$2
|
||||||
|
|
||||||
|
UDR_USER="${UDR_USER:-$(_readaccountconf_mutable UDR_USER)}"
|
||||||
|
UDR_PASS="${UDR_PASS:-$(_readaccountconf_mutable UDR_PASS)}"
|
||||||
|
if [ -z "$UDR_USER" ] || [ -z "$UDR_PASS" ]; then
|
||||||
|
UDR_USER=""
|
||||||
|
UDR_PASS=""
|
||||||
|
_err "You didn't specify an UD-Reselling username and password yet"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_debug "First detect the root zone"
|
||||||
|
if ! _get_root "$fulldomain"; then
|
||||||
|
_err "invalid domain"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_debug _dnszone "${_dnszone}"
|
||||||
|
|
||||||
|
_debug "Getting txt records"
|
||||||
|
if ! _udr_rest "QueryDNSZoneRRList" "dnszone=${_dnszone}"; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
rr="${fulldomain}. ${UDR_TTL} IN TXT ${txtvalue}"
|
||||||
|
_debug resource_record "${rr}"
|
||||||
|
if _contains "$response" "$rr" >/dev/null; then
|
||||||
|
if ! _udr_rest "UpdateDNSZone" "dnszone=${_dnszone}&delrr0=${rr}"; then
|
||||||
|
_err "Deleting the record did not succeed, please verify/check."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_info "Removed, OK"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
_info "Text record is not present, will not delete anything."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
#################### Private functions below ##################################
|
||||||
|
#_acme-challenge.www.domain.com
|
||||||
|
#returns
|
||||||
|
# _sub_domain=_acme-challenge.www
|
||||||
|
# _domain=domain.com
|
||||||
|
_get_root() {
|
||||||
|
domain=$1
|
||||||
|
i=1
|
||||||
|
|
||||||
|
if ! _udr_rest "QueryDNSZoneList" ""; 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}." >/dev/null; then
|
||||||
|
_dnszone=$(echo "$response" | _egrep_o "${h}")
|
||||||
|
if [ "$_dnszone" ]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
i=$(_math "$i" + 1)
|
||||||
|
done
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
_udr_rest() {
|
||||||
|
if [ -n "$2" ]; then
|
||||||
|
data="command=$1&$2"
|
||||||
|
else
|
||||||
|
data="command=$1"
|
||||||
|
fi
|
||||||
|
|
||||||
|
_debug data "${data}"
|
||||||
|
response="$(_post "${data}" "${UDR_API}?s_login=${UDR_USER}&s_pw=${UDR_PASS}" "" "POST")"
|
||||||
|
|
||||||
|
_code=$(echo "$response" | _egrep_o "code = ([0-9]+)" | _head_n 1 | cut -d = -f 2 | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')
|
||||||
|
_description=$(echo "$response" | _egrep_o "description = .*" | _head_n 1 | cut -d = -f 2 | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')
|
||||||
|
|
||||||
|
_debug response_code "$_code"
|
||||||
|
_debug response_description "$_description"
|
||||||
|
|
||||||
|
if [ ! "$_code" = "200" ]; then
|
||||||
|
_err "DNS-API-Error: $_description"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
142
dnsapi/dns_vercel.sh
Normal file
142
dnsapi/dns_vercel.sh
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
# Vercel DNS API
|
||||||
|
#
|
||||||
|
# This is your API token which can be acquired on the account page.
|
||||||
|
# https://vercel.com/account/tokens
|
||||||
|
#
|
||||||
|
# VERCEL_TOKEN="sdfsdfsdfljlbjkljlkjsdfoiwje"
|
||||||
|
|
||||||
|
VERCEL_API="https://api.vercel.com"
|
||||||
|
|
||||||
|
#Usage: add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||||
|
dns_vercel_add() {
|
||||||
|
fulldomain=$1
|
||||||
|
txtvalue=$2
|
||||||
|
_debug fulldomain "$fulldomain"
|
||||||
|
_debug txtvalue "$txtvalue"
|
||||||
|
|
||||||
|
VERCEL_TOKEN="${VERCEL_TOKEN:-$(_readaccountconf_mutable VERCEL_TOKEN)}"
|
||||||
|
|
||||||
|
if [ -z "$VERCEL_TOKEN" ]; then
|
||||||
|
VERCEL_TOKEN=""
|
||||||
|
_err "You have not set the Vercel API token yet."
|
||||||
|
_err "Please visit https://vercel.com/account/tokens to generate it."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_saveaccountconf_mutable VERCEL_TOKEN "$VERCEL_TOKEN"
|
||||||
|
|
||||||
|
if ! _get_root "$fulldomain"; then
|
||||||
|
_err "invalid domain"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_debug _sub_domain "$_sub_domain"
|
||||||
|
_debug _domain "$_domain"
|
||||||
|
|
||||||
|
_info "Adding record"
|
||||||
|
if _vercel_rest POST "v2/domains/$_domain/records" "{\"type\":\"TXT\",\"name\":\"$_sub_domain\",\"value\":\"$txtvalue\"}"; then
|
||||||
|
if printf -- "%s" "$response" | grep "\"uid\":\"" >/dev/null; then
|
||||||
|
_info "Added"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
_err "Unexpected response while adding text record."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
_err "Add txt record error."
|
||||||
|
}
|
||||||
|
|
||||||
|
dns_vercel_rm() {
|
||||||
|
fulldomain=$1
|
||||||
|
txtvalue=$2
|
||||||
|
|
||||||
|
if ! _get_root "$fulldomain"; then
|
||||||
|
_err "invalid domain"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_vercel_rest GET "v2/domains/$_domain/records"
|
||||||
|
|
||||||
|
count=$(printf "%s\n" "$response" | _egrep_o "\"name\":\"$_sub_domain\",[^{]*\"type\":\"TXT\"" | wc -l | tr -d " ")
|
||||||
|
|
||||||
|
if [ "$count" = "0" ]; then
|
||||||
|
_info "Don't need to remove."
|
||||||
|
else
|
||||||
|
_record_id=$(printf "%s" "$response" | _egrep_o "\"id\":[^,]*,\"slug\":\"[^,]*\",\"name\":\"$_sub_domain\",[^{]*\"type\":\"TXT\",\"value\":\"$txtvalue\"" | cut -d: -f2 | cut -d, -f1 | tr -d '"')
|
||||||
|
|
||||||
|
if [ "$_record_id" ]; then
|
||||||
|
echo "$_record_id" | while read -r item; do
|
||||||
|
if _vercel_rest DELETE "v2/domains/$_domain/records/$item"; then
|
||||||
|
_info "removed record" "$item"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
_err "failed to remove record" "$item"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
#################### Private functions below ##################################
|
||||||
|
#_acme-challenge.www.domain.com
|
||||||
|
#returns
|
||||||
|
# _sub_domain=_acme-challenge.www
|
||||||
|
# _domain=domain.com
|
||||||
|
_get_root() {
|
||||||
|
domain="$1"
|
||||||
|
ep="$2"
|
||||||
|
i=1
|
||||||
|
p=1
|
||||||
|
while true; do
|
||||||
|
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
|
||||||
|
if [ -z "$h" ]; then
|
||||||
|
#not valid
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! _vercel_rest GET "v4/domains/$h"; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if _contains "$response" "\"name\":\"$h\"" >/dev/null; then
|
||||||
|
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
|
||||||
|
_domain=$h
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
p=$i
|
||||||
|
i=$(_math "$i" + 1)
|
||||||
|
done
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
_vercel_rest() {
|
||||||
|
m="$1"
|
||||||
|
ep="$2"
|
||||||
|
data="$3"
|
||||||
|
|
||||||
|
path="$VERCEL_API/$ep"
|
||||||
|
|
||||||
|
export _H1="Content-Type: application/json"
|
||||||
|
export _H2="Authorization: Bearer $VERCEL_TOKEN"
|
||||||
|
|
||||||
|
if [ "$m" != "GET" ]; then
|
||||||
|
_secure_debug2 data "$data"
|
||||||
|
response="$(_post "$data" "$path" "" "$m")"
|
||||||
|
else
|
||||||
|
response="$(_get "$path")"
|
||||||
|
fi
|
||||||
|
_ret="$?"
|
||||||
|
_code="$(grep "^HTTP" "$HTTP_HEADER" | _tail_n 1 | cut -d " " -f 2 | tr -d "\\r\\n")"
|
||||||
|
_debug "http response code $_code"
|
||||||
|
_secure_debug2 response "$response"
|
||||||
|
if [ "$_ret" != "0" ]; then
|
||||||
|
_err "error $ep"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
response="$(printf "%s" "$response" | _normalizeJson)"
|
||||||
|
return 0
|
||||||
|
}
|
@ -24,7 +24,7 @@ dns_world4you_add() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
export _H1="Cookie: W4YSESSID=$sessid"
|
export _H1="Cookie: W4YSESSID=$sessid"
|
||||||
form=$(_get "$WORLD4YOU_API/dashboard/paketuebersicht")
|
form=$(_get "$WORLD4YOU_API/")
|
||||||
_get_paketnr "$fqdn" "$form"
|
_get_paketnr "$fqdn" "$form"
|
||||||
paketnr="$PAKETNR"
|
paketnr="$PAKETNR"
|
||||||
if [ -z "$paketnr" ]; then
|
if [ -z "$paketnr" ]; then
|
||||||
@ -54,15 +54,14 @@ dns_world4you_add() {
|
|||||||
if _contains "$res" "successfully"; then
|
if _contains "$res" "successfully"; then
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
msg=$(echo "$res" | tr '\n' '\t' | sed 's/.*<h3 class="mb-5">[^\t]*\t *\([^\t]*\)\t.*/\1/')
|
msg=$(echo "$res" | grep -A 15 'data-type="danger"' | grep "<h3[^>]*>[^<]" | sed 's/<[^>]*>\|^\s*//g')
|
||||||
if _contains "$msg" '^<\!DOCTYPE html>'; then
|
if [ "$msg" = '' ]; then
|
||||||
msg='Unknown error'
|
_err "Unable to add record: Unknown error"
|
||||||
fi
|
|
||||||
_err "Unable to add record: $msg"
|
|
||||||
if _contains "$msg" '^<\!DOCTYPE html>'; then
|
|
||||||
echo "$ret" >'error-01.html'
|
echo "$ret" >'error-01.html'
|
||||||
echo "$res" >'error-02.html'
|
echo "$res" >'error-02.html'
|
||||||
_err "View error-01.html and error-02.html for debugging"
|
_err "View error-01.html and error-02.html for debugging"
|
||||||
|
else
|
||||||
|
_err "Unable to add record: my.world4you.com: $msg"
|
||||||
fi
|
fi
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
@ -87,7 +86,7 @@ dns_world4you_rm() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
export _H1="Cookie: W4YSESSID=$sessid"
|
export _H1="Cookie: W4YSESSID=$sessid"
|
||||||
form=$(_get "$WORLD4YOU_API/dashboard/paketuebersicht")
|
form=$(_get "$WORLD4YOU_API/")
|
||||||
_get_paketnr "$fqdn" "$form"
|
_get_paketnr "$fqdn" "$form"
|
||||||
paketnr="$PAKETNR"
|
paketnr="$PAKETNR"
|
||||||
if [ -z "$paketnr" ]; then
|
if [ -z "$paketnr" ]; then
|
||||||
@ -119,15 +118,14 @@ dns_world4you_rm() {
|
|||||||
if _contains "$res" "successfully"; then
|
if _contains "$res" "successfully"; then
|
||||||
return 0
|
return 0
|
||||||
else
|
else
|
||||||
msg=$(echo "$res" | tr '\n' '\t' | sed 's/.*<h3 class="mb-5">[^\t]*\t *\([^\t]*\)\t.*/\1/')
|
msg=$(echo "$res" | grep -A 15 'data-type="danger"' | grep "<h3[^>]*>[^<]" | sed 's/<[^>]*>\|^\s*//g')
|
||||||
if _contains "$msg" '^<\!DOCTYPE html>'; then
|
if [ "$msg" = '' ]; then
|
||||||
msg='Unknown error'
|
_err "Unable to remove record: Unknown error"
|
||||||
fi
|
|
||||||
_err "Unable to remove record: $msg"
|
|
||||||
if _contains "$msg" '^<\!DOCTYPE html>'; then
|
|
||||||
echo "$ret" >'error-01.html'
|
echo "$ret" >'error-01.html'
|
||||||
echo "$res" >'error-02.html'
|
echo "$res" >'error-02.html'
|
||||||
_err "View error-01.html and error-02.html for debugging"
|
_err "View error-01.html and error-02.html for debugging"
|
||||||
|
else
|
||||||
|
_err "Unable to remove record: my.world4you.com: $msg"
|
||||||
fi
|
fi
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
@ -184,7 +182,7 @@ _get_paketnr() {
|
|||||||
fqdn="$1"
|
fqdn="$1"
|
||||||
form="$2"
|
form="$2"
|
||||||
|
|
||||||
domains=$(echo "$form" | grep '^ *[A-Za-z0-9_\.-]*\.[A-Za-z0-9_-]*$' | sed 's/^ *\(.*\)$/\1/')
|
domains=$(echo "$form" | grep 'header-paket-domain' | sed 's/<[^>]*>//g' | sed 's/^.*>\([^>]*\)$/\1/')
|
||||||
domain=''
|
domain=''
|
||||||
for domain in $domains; do
|
for domain in $domains; do
|
||||||
if _contains "$fqdn" "$domain\$"; then
|
if _contains "$fqdn" "$domain\$"; then
|
||||||
@ -199,6 +197,6 @@ _get_paketnr() {
|
|||||||
TLD="$domain"
|
TLD="$domain"
|
||||||
_debug domain "$domain"
|
_debug domain "$domain"
|
||||||
RECORD=$(echo "$fqdn" | cut -c"1-$((${#fqdn} - ${#TLD} - 1))")
|
RECORD=$(echo "$fqdn" | cut -c"1-$((${#fqdn} - ${#TLD} - 1))")
|
||||||
PAKETNR=$(echo "$form" | grep "data-textfilter=\".* $domain " | _head_n 1 | sed 's/^.* \([0-9]*\) .*$/\1/')
|
PAKETNR=$(echo "$form" | grep "data-textfilter=\".* $domain " | _tail_n 1 | sed "s|.*$WORLD4YOU_API/\\([0-9]*\\)/.*|\\1|")
|
||||||
return 0
|
return 0
|
||||||
}
|
}
|
||||||
|
44
notify/callmebotWhatsApp.sh
Normal file
44
notify/callmebotWhatsApp.sh
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
#Support CallMeBot Whatsapp webhooks
|
||||||
|
|
||||||
|
#CALLMEBOT_YOUR_PHONE_NO=""
|
||||||
|
#CALLMEBOT_API_KEY=""
|
||||||
|
|
||||||
|
callmebotWhatsApp_send() {
|
||||||
|
_subject="$1"
|
||||||
|
_content="$2"
|
||||||
|
_statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped
|
||||||
|
_debug "_statusCode" "$_statusCode"
|
||||||
|
|
||||||
|
CALLMEBOT_YOUR_PHONE_NO="${CALLMEBOT_YOUR_PHONE_NO:-$(_readaccountconf_mutable CALLMEBOT_YOUR_PHONE_NO)}"
|
||||||
|
if [ -z "$CALLMEBOT_YOUR_PHONE_NO" ]; then
|
||||||
|
CALLMEBOT_YOUR_PHONE_NO=""
|
||||||
|
_err "You didn't specify a Slack webhook url CALLMEBOT_YOUR_PHONE_NO yet."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_saveaccountconf_mutable CALLMEBOT_YOUR_PHONE_NO "$CALLMEBOT_YOUR_PHONE_NO"
|
||||||
|
|
||||||
|
CALLMEBOT_API_KEY="${CALLMEBOT_API_KEY:-$(_readaccountconf_mutable CALLMEBOT_API_KEY)}"
|
||||||
|
if [ "$CALLMEBOT_API_KEY" ]; then
|
||||||
|
_saveaccountconf_mutable CALLMEBOT_API_KEY "$CALLMEBOT_API_KEY"
|
||||||
|
fi
|
||||||
|
|
||||||
|
_waUrl="https://api.callmebot.com/whatsapp.php"
|
||||||
|
|
||||||
|
_Phone_No="$(printf "%s" "$CALLMEBOT_YOUR_PHONE_NO" | _url_encode)"
|
||||||
|
_apikey="$(printf "%s" "$CALLMEBOT_API_KEY" | _url_encode)"
|
||||||
|
_message="$(printf "*%s*\\n%s" "$_subject" "$_content" | _url_encode)"
|
||||||
|
|
||||||
|
_finalUrl="$_waUrl?phone=$_Phone_No&apikey=$_apikey&text=$_message"
|
||||||
|
response="$(_get "$_finalUrl")"
|
||||||
|
|
||||||
|
if [ "$?" = "0" ] && _contains ".<p><b>Message queued.</b> You will receive it in a few seconds."; then
|
||||||
|
_info "wa send success."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
_err "wa send error."
|
||||||
|
_debug "URL" "$_finalUrl"
|
||||||
|
_debug "Response" "$response"
|
||||||
|
return 1
|
||||||
|
}
|
57
notify/discord.sh
Normal file
57
notify/discord.sh
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
#Support Discord webhooks
|
||||||
|
|
||||||
|
# Required:
|
||||||
|
#DISCORD_WEBHOOK_URL=""
|
||||||
|
# Optional:
|
||||||
|
#DISCORD_USERNAME=""
|
||||||
|
#DISCORD_AVATAR_URL=""
|
||||||
|
|
||||||
|
discord_send() {
|
||||||
|
_subject="$1"
|
||||||
|
_content="$2"
|
||||||
|
_statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped
|
||||||
|
_debug "_statusCode" "$_statusCode"
|
||||||
|
|
||||||
|
DISCORD_WEBHOOK_URL="${DISCORD_WEBHOOK_URL:-$(_readaccountconf_mutable DISCORD_WEBHOOK_URL)}"
|
||||||
|
if [ -z "$DISCORD_WEBHOOK_URL" ]; then
|
||||||
|
DISCORD_WEBHOOK_URL=""
|
||||||
|
_err "You didn't specify a Discord webhook url DISCORD_WEBHOOK_URL yet."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_saveaccountconf_mutable DISCORD_WEBHOOK_URL "$DISCORD_WEBHOOK_URL"
|
||||||
|
|
||||||
|
DISCORD_USERNAME="${DISCORD_USERNAME:-$(_readaccountconf_mutable DISCORD_USERNAME)}"
|
||||||
|
if [ "$DISCORD_USERNAME" ]; then
|
||||||
|
_saveaccountconf_mutable DISCORD_USERNAME "$DISCORD_USERNAME"
|
||||||
|
fi
|
||||||
|
|
||||||
|
DISCORD_AVATAR_URL="${DISCORD_AVATAR_URL:-$(_readaccountconf_mutable DISCORD_AVATAR_URL)}"
|
||||||
|
if [ "$DISCORD_AVATAR_URL" ]; then
|
||||||
|
_saveaccountconf_mutable DISCORD_AVATAR_URL "$DISCORD_AVATAR_URL"
|
||||||
|
fi
|
||||||
|
|
||||||
|
export _H1="Content-Type: application/json"
|
||||||
|
|
||||||
|
_content="$(printf "**%s**\n%s" "$_subject" "$_content" | _json_encode)"
|
||||||
|
_data="{\"content\": \"$_content\" "
|
||||||
|
if [ "$DISCORD_USERNAME" ]; then
|
||||||
|
_data="$_data, \"username\": \"$DISCORD_USERNAME\" "
|
||||||
|
fi
|
||||||
|
if [ "$DISCORD_AVATAR_URL" ]; then
|
||||||
|
_data="$_data, \"avatar_url\": \"$DISCORD_AVATAR_URL\" "
|
||||||
|
fi
|
||||||
|
_data="$_data}"
|
||||||
|
|
||||||
|
if _post "$_data" "$DISCORD_WEBHOOK_URL?wait=true"; then
|
||||||
|
# shellcheck disable=SC2154
|
||||||
|
if [ "$response" ]; then
|
||||||
|
_info "discord send success."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
_err "discord send error."
|
||||||
|
_err "$response"
|
||||||
|
return 1
|
||||||
|
}
|
49
notify/weixin_work.sh
Normal file
49
notify/weixin_work.sh
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
#Support weixin work webhooks api
|
||||||
|
|
||||||
|
#WEIXIN_WORK_WEBHOOK="xxxx"
|
||||||
|
|
||||||
|
#optional
|
||||||
|
#WEIXIN_WORK_KEYWORD="yyyy"
|
||||||
|
|
||||||
|
#`WEIXIN_WORK_SIGNING_KEY`="SEC08ffdbd403cbc3fc8a65xxxxxxxxxxxxxxxxxxxx"
|
||||||
|
|
||||||
|
# subject content statusCode
|
||||||
|
weixin_work_send() {
|
||||||
|
_subject="$1"
|
||||||
|
_content="$2"
|
||||||
|
_statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped
|
||||||
|
_debug "_subject" "$_subject"
|
||||||
|
_debug "_content" "$_content"
|
||||||
|
_debug "_statusCode" "$_statusCode"
|
||||||
|
|
||||||
|
WEIXIN_WORK_WEBHOOK="${WEIXIN_WORK_WEBHOOK:-$(_readaccountconf_mutable WEIXIN_WORK_WEBHOOK)}"
|
||||||
|
if [ -z "$WEIXIN_WORK_WEBHOOK" ]; then
|
||||||
|
WEIXIN_WORK_WEBHOOK=""
|
||||||
|
_err "You didn't specify a weixin_work webhooks WEIXIN_WORK_WEBHOOK yet."
|
||||||
|
_err "You can get yours from https://work.weixin.qq.com/api/doc/90000/90136/91770"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_saveaccountconf_mutable WEIXIN_WORK_WEBHOOK "$WEIXIN_WORK_WEBHOOK"
|
||||||
|
|
||||||
|
WEIXIN_WORK_KEYWORD="${WEIXIN_WORK_KEYWORD:-$(_readaccountconf_mutable WEIXIN_WORK_KEYWORD)}"
|
||||||
|
if [ "$WEIXIN_WORK_KEYWORD" ]; then
|
||||||
|
_saveaccountconf_mutable WEIXIN_WORK_KEYWORD "$WEIXIN_WORK_KEYWORD"
|
||||||
|
fi
|
||||||
|
|
||||||
|
_content=$(echo "$_content" | _json_encode)
|
||||||
|
_subject=$(echo "$_subject" | _json_encode)
|
||||||
|
_data="{\"msgtype\": \"text\", \"text\": {\"content\": \"[$WEIXIN_WORK_KEYWORD]\n$_subject\n$_content\"}}"
|
||||||
|
|
||||||
|
response="$(_post "$_data" "$WEIXIN_WORK_WEBHOOK" "" "POST" "application/json")"
|
||||||
|
|
||||||
|
if [ "$?" = "0" ] && _contains "$response" "errmsg\":\"ok"; then
|
||||||
|
_info "weixin_work webhooks event fired success."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
_err "weixin_work webhooks event fired error."
|
||||||
|
_err "$response"
|
||||||
|
return 1
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user