mirror of
https://github.com/acmesh-official/acme.sh.git
synced 2025-07-07 03:52:45 +00:00
Merge remote-tracking branch 'upstream/master'
Manually changed $_CRONTAB
This commit is contained in:
commit
9391d2d9ac
@ -18,7 +18,7 @@ addons:
|
|||||||
|
|
||||||
install:
|
install:
|
||||||
- if [ "$TRAVIS_OS_NAME" = 'osx' ]; then
|
- if [ "$TRAVIS_OS_NAME" = 'osx' ]; then
|
||||||
brew update && brew install openssl;
|
brew update && brew install openssl socat;
|
||||||
brew info openssl;
|
brew info openssl;
|
||||||
ln -s /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/;
|
ln -s /usr/local/opt/openssl/lib/libcrypto.1.0.0.dylib /usr/local/lib/;
|
||||||
ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib /usr/local/lib/;
|
ln -s /usr/local/opt/openssl/lib/libssl.1.0.0.dylib /usr/local/lib/;
|
||||||
@ -30,6 +30,7 @@ install:
|
|||||||
openssl version 2>&1 || true;
|
openssl version 2>&1 || true;
|
||||||
$ACME_OPENSSL_BIN version 2>&1 || true;
|
$ACME_OPENSSL_BIN version 2>&1 || true;
|
||||||
export PATH="$_old_path";
|
export PATH="$_old_path";
|
||||||
|
else sudo apt-get install socat;
|
||||||
fi
|
fi
|
||||||
|
|
||||||
script:
|
script:
|
||||||
|
@ -4,7 +4,7 @@ RUN apk update -f \
|
|||||||
&& apk --no-cache add -f \
|
&& apk --no-cache add -f \
|
||||||
openssl \
|
openssl \
|
||||||
curl \
|
curl \
|
||||||
netcat-openbsd \
|
socat \
|
||||||
&& rm -rf /var/cache/apk/*
|
&& rm -rf /var/cache/apk/*
|
||||||
|
|
||||||
ENV LE_CONFIG_HOME /acme.sh
|
ENV LE_CONFIG_HOME /acme.sh
|
||||||
@ -16,7 +16,7 @@ ADD ./ /install_acme.sh/
|
|||||||
RUN cd /install_acme.sh && ([ -f /install_acme.sh/acme.sh ] && /install_acme.sh/acme.sh --install || curl https://get.acme.sh | sh) && rm -rf /install_acme.sh/
|
RUN cd /install_acme.sh && ([ -f /install_acme.sh/acme.sh ] && /install_acme.sh/acme.sh --install || curl https://get.acme.sh | sh) && rm -rf /install_acme.sh/
|
||||||
|
|
||||||
|
|
||||||
RUN ln -s /root/.acme.sh/acme.sh /usr/local/bin/acme.sh && crontab -l | sed 's#> /dev/null##' | crontab -
|
RUN ln -s /root/.acme.sh/acme.sh /usr/local/bin/acme.sh && crontab -l | grep acme.sh | sed 's#> /dev/null##' | crontab -
|
||||||
|
|
||||||
RUN for verb in help \
|
RUN for verb in help \
|
||||||
version \
|
version \
|
||||||
|
@ -338,6 +338,7 @@ You don't have to do anything manually!
|
|||||||
1. Name.com API
|
1. Name.com API
|
||||||
1. Dyn Managed DNS API
|
1. Dyn Managed DNS API
|
||||||
1. Yandex PDD API (https://pdd.yandex.ru)
|
1. Yandex PDD API (https://pdd.yandex.ru)
|
||||||
|
1. Hurricane Electric DNS service (https://dns.he.net)
|
||||||
|
|
||||||
|
|
||||||
And:
|
And:
|
||||||
|
213
acme.sh
213
acme.sh
@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env sh
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
VER=2.7.3
|
VER=2.7.5
|
||||||
|
|
||||||
PROJECT_NAME="acme.sh"
|
PROJECT_NAME="acme.sh"
|
||||||
|
|
||||||
@ -100,6 +100,10 @@ _PREPARE_LINK="https://github.com/Neilpang/acme.sh/wiki/Install-preparations"
|
|||||||
|
|
||||||
_STATELESS_WIKI="https://github.com/Neilpang/acme.sh/wiki/Stateless-Mode"
|
_STATELESS_WIKI="https://github.com/Neilpang/acme.sh/wiki/Stateless-Mode"
|
||||||
|
|
||||||
|
_DNS_MANUAL_ERR="The dns manual mode can not renew automatically, you must issue it again manually. You'd better use the other modes instead."
|
||||||
|
|
||||||
|
_DNS_MANUAL_WARN="It seems that you are using dns manual mode. please take care: $_DNS_MANUAL_ERR"
|
||||||
|
|
||||||
__INTERACTIVE=""
|
__INTERACTIVE=""
|
||||||
if [ -t 1 ]; then
|
if [ -t 1 ]; then
|
||||||
__INTERACTIVE="1"
|
__INTERACTIVE="1"
|
||||||
@ -160,11 +164,11 @@ _dlg_versions() {
|
|||||||
echo "nginx doesn't exists."
|
echo "nginx doesn't exists."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo "nc:"
|
echo "socat:"
|
||||||
if _exists "nc"; then
|
if _exists "socat"; then
|
||||||
nc -h 2>&1
|
socat -h 2>&1
|
||||||
else
|
else
|
||||||
_debug "nc doesn't exists."
|
_debug "socat doesn't exists."
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -926,7 +930,7 @@ _sign() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#keylength
|
#keylength or isEcc flag (empty str => not ecc)
|
||||||
_isEccKey() {
|
_isEccKey() {
|
||||||
_length="$1"
|
_length="$1"
|
||||||
|
|
||||||
@ -1182,6 +1186,28 @@ _ss() {
|
|||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#outfile key cert cacert [password [name [caname]]]
|
||||||
|
_toPkcs() {
|
||||||
|
_cpfx="$1"
|
||||||
|
_ckey="$2"
|
||||||
|
_ccert="$3"
|
||||||
|
_cca="$4"
|
||||||
|
pfxPassword="$5"
|
||||||
|
pfxName="$6"
|
||||||
|
pfxCaname="$7"
|
||||||
|
|
||||||
|
if [ "$pfxCaname" ]; then
|
||||||
|
${ACME_OPENSSL_BIN:-openssl} pkcs12 -export -out "$_cpfx" -inkey "$_ckey" -in "$_ccert" -certfile "$_cca" -password "pass:$pfxPassword" -name "$pfxName" -caname "$pfxCaname"
|
||||||
|
elif [ "$pfxName" ]; then
|
||||||
|
${ACME_OPENSSL_BIN:-openssl} pkcs12 -export -out "$_cpfx" -inkey "$_ckey" -in "$_ccert" -certfile "$_cca" -password "pass:$pfxPassword" -name "$pfxName"
|
||||||
|
elif [ "$pfxPassword" ]; then
|
||||||
|
${ACME_OPENSSL_BIN:-openssl} pkcs12 -export -out "$_cpfx" -inkey "$_ckey" -in "$_ccert" -certfile "$_cca" -password "pass:$pfxPassword"
|
||||||
|
else
|
||||||
|
${ACME_OPENSSL_BIN:-openssl} pkcs12 -export -out "$_cpfx" -inkey "$_ckey" -in "$_ccert" -certfile "$_cca"
|
||||||
|
fi
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#domain [password] [isEcc]
|
#domain [password] [isEcc]
|
||||||
toPkcs() {
|
toPkcs() {
|
||||||
domain="$1"
|
domain="$1"
|
||||||
@ -1195,11 +1221,7 @@ toPkcs() {
|
|||||||
|
|
||||||
_initpath "$domain" "$_isEcc"
|
_initpath "$domain" "$_isEcc"
|
||||||
|
|
||||||
if [ "$pfxPassword" ]; then
|
_toPkcs "$CERT_PFX_PATH" "$CERT_KEY_PATH" "$CERT_PATH" "$CA_CERT_PATH" "$pfxPassword"
|
||||||
${ACME_OPENSSL_BIN:-openssl} pkcs12 -export -out "$CERT_PFX_PATH" -inkey "$CERT_KEY_PATH" -in "$CERT_PATH" -certfile "$CA_CERT_PATH" -password "pass:$pfxPassword"
|
|
||||||
else
|
|
||||||
${ACME_OPENSSL_BIN:-openssl} pkcs12 -export -out "$CERT_PFX_PATH" -inkey "$CERT_KEY_PATH" -in "$CERT_PATH" -certfile "$CA_CERT_PATH"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$?" = "0" ]; then
|
if [ "$?" = "0" ]; then
|
||||||
_info "Success, Pfx is exported to: $CERT_PFX_PATH"
|
_info "Success, Pfx is exported to: $CERT_PFX_PATH"
|
||||||
@ -1349,6 +1371,10 @@ _time2str() {
|
|||||||
echo "$_t_s_a"
|
echo "$_t_s_a"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
#Busybox
|
||||||
|
if echo "$1" | awk '{ print strftime("%c", $0); }' 2>/dev/null; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
_normalizeJson() {
|
_normalizeJson() {
|
||||||
@ -1788,7 +1814,13 @@ _send_signed_request() {
|
|||||||
|
|
||||||
_CACHED_NONCE="$(echo "$responseHeaders" | grep "Replay-Nonce:" | _head_n 1 | tr -d "\r\n " | cut -d ':' -f 2)"
|
_CACHED_NONCE="$(echo "$responseHeaders" | grep "Replay-Nonce:" | _head_n 1 | tr -d "\r\n " | cut -d ':' -f 2)"
|
||||||
|
|
||||||
if _contains "$response" "JWS has invalid anti-replay nonce"; then
|
_body="$response"
|
||||||
|
if [ "$needbase64" ]; then
|
||||||
|
_body="$(echo "$_body" | _dbase64)"
|
||||||
|
_debug2 _body "$_body"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if _contains "$_body" "JWS has invalid anti-replay nonce"; then
|
||||||
_info "It seems the CA server is busy now, let's wait and retry."
|
_info "It seems the CA server is busy now, let's wait and retry."
|
||||||
_request_retry_times=$(_math "$_request_retry_times" + 1)
|
_request_retry_times=$(_math "$_request_retry_times" + 1)
|
||||||
_sleep 5
|
_sleep 5
|
||||||
@ -1941,68 +1973,22 @@ _startserver() {
|
|||||||
_debug "ncaddr" "$ncaddr"
|
_debug "ncaddr" "$ncaddr"
|
||||||
|
|
||||||
_debug "startserver: $$"
|
_debug "startserver: $$"
|
||||||
nchelp="$(nc -h 2>&1)"
|
|
||||||
|
|
||||||
_debug Le_HTTPPort "$Le_HTTPPort"
|
_debug Le_HTTPPort "$Le_HTTPPort"
|
||||||
_debug Le_Listen_V4 "$Le_Listen_V4"
|
_debug Le_Listen_V4 "$Le_Listen_V4"
|
||||||
_debug Le_Listen_V6 "$Le_Listen_V6"
|
_debug Le_Listen_V6 "$Le_Listen_V6"
|
||||||
_NC="nc"
|
|
||||||
|
|
||||||
|
_NC="socat"
|
||||||
if [ "$Le_Listen_V4" ]; then
|
if [ "$Le_Listen_V4" ]; then
|
||||||
_NC="$_NC -4"
|
_NC="$_NC -4"
|
||||||
elif [ "$Le_Listen_V6" ]; then
|
elif [ "$Le_Listen_V6" ]; then
|
||||||
_NC="$_NC -6"
|
_NC="$_NC -6"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$Le_Listen_V4$Le_Listen_V6$ncaddr" ]; then
|
|
||||||
if ! _contains "$nchelp" "-4"; then
|
|
||||||
_err "The nc doesn't support '-4', '-6' or local-address, please install 'netcat-openbsd' and try again."
|
|
||||||
_err "See $(__green $_PREPARE_LINK)"
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
if echo "$nchelp" | grep "\-q[ ,]" >/dev/null; then
|
|
||||||
_NC="$_NC -q 1 -l $ncaddr"
|
|
||||||
else
|
|
||||||
if echo "$nchelp" | grep "GNU netcat" >/dev/null && echo "$nchelp" | grep "\-c, \-\-close" >/dev/null; then
|
|
||||||
_NC="$_NC -c -l $ncaddr"
|
|
||||||
elif echo "$nchelp" | grep "\-N" | grep "Shutdown the network socket after EOF on stdin" >/dev/null; then
|
|
||||||
_NC="$_NC -N -l $ncaddr"
|
|
||||||
else
|
|
||||||
_NC="$_NC -l $ncaddr"
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
_debug "_NC" "$_NC"
|
_debug "_NC" "$_NC"
|
||||||
|
#todo listen address
|
||||||
#for centos ncat
|
$_NC TCP-LISTEN:$Le_HTTPPort,crlf,reuseaddr,fork SYSTEM:"sleep 0.5; echo HTTP/1.1 200 OK; echo ; echo $content; echo;" &
|
||||||
if _contains "$nchelp" "nmap.org"; then
|
serverproc="$!"
|
||||||
_debug "Using ncat: nmap.org"
|
|
||||||
if ! _exec "printf \"%s\r\n\r\n%s\" \"HTTP/1.1 200 OK\" \"$content\" | $_NC \"$Le_HTTPPort\" >&2"; then
|
|
||||||
_exec_err
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
if [ "$DEBUG" ]; then
|
|
||||||
_exec_err
|
|
||||||
fi
|
|
||||||
return
|
|
||||||
fi
|
|
||||||
|
|
||||||
# while true ; do
|
|
||||||
if ! _exec "printf \"%s\r\n\r\n%s\" \"HTTP/1.1 200 OK\" \"$content\" | $_NC -p \"$Le_HTTPPort\" >&2"; then
|
|
||||||
_exec "printf \"%s\r\n\r\n%s\" \"HTTP/1.1 200 OK\" \"$content\" | $_NC \"$Le_HTTPPort\" >&2"
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ "$?" != "0" ]; then
|
|
||||||
_err "nc listen error."
|
|
||||||
_exec_err
|
|
||||||
exit 1
|
|
||||||
fi
|
|
||||||
if [ "$DEBUG" ]; then
|
|
||||||
_exec_err
|
|
||||||
fi
|
|
||||||
# done
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_stopserver() {
|
_stopserver() {
|
||||||
@ -2012,25 +1998,8 @@ _stopserver() {
|
|||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
_debug2 "Le_HTTPPort" "$Le_HTTPPort"
|
kill $pid
|
||||||
if [ "$Le_HTTPPort" ]; then
|
|
||||||
if [ "$DEBUG" ] && [ "$DEBUG" -gt "3" ]; then
|
|
||||||
_get "http://localhost:$Le_HTTPPort" "" 1
|
|
||||||
else
|
|
||||||
_get "http://localhost:$Le_HTTPPort" "" 1 >/dev/null 2>&1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
|
|
||||||
_debug2 "Le_TLSPort" "$Le_TLSPort"
|
|
||||||
if [ "$Le_TLSPort" ]; then
|
|
||||||
if [ "$DEBUG" ] && [ "$DEBUG" -gt "3" ]; then
|
|
||||||
_get "https://localhost:$Le_TLSPort" "" 1
|
|
||||||
_get "https://localhost:$Le_TLSPort" "" 1
|
|
||||||
else
|
|
||||||
_get "https://localhost:$Le_TLSPort" "" 1 >/dev/null 2>&1
|
|
||||||
_get "https://localhost:$Le_TLSPort" "" 1 >/dev/null 2>&1
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
}
|
}
|
||||||
|
|
||||||
# sleep sec
|
# sleep sec
|
||||||
@ -2085,7 +2054,7 @@ _starttlsserver() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
__S_OPENSSL="${ACME_OPENSSL_BIN:-openssl} s_server -cert $TLS_CERT -key $TLS_KEY "
|
__S_OPENSSL="${ACME_OPENSSL_BIN:-openssl} s_server -www -cert $TLS_CERT -key $TLS_KEY "
|
||||||
if [ "$opaddr" ]; then
|
if [ "$opaddr" ]; then
|
||||||
__S_OPENSSL="$__S_OPENSSL -accept $opaddr:$port"
|
__S_OPENSSL="$__S_OPENSSL -accept $opaddr:$port"
|
||||||
else
|
else
|
||||||
@ -2102,9 +2071,9 @@ _starttlsserver() {
|
|||||||
|
|
||||||
_debug "$__S_OPENSSL"
|
_debug "$__S_OPENSSL"
|
||||||
if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then
|
if [ "$DEBUG" ] && [ "$DEBUG" -ge "2" ]; then
|
||||||
(printf "%s\r\n\r\n%s" "HTTP/1.1 200 OK" "$content" | $__S_OPENSSL -tlsextdebug) &
|
$__S_OPENSSL -tlsextdebug &
|
||||||
else
|
else
|
||||||
(printf "%s\r\n\r\n%s" "HTTP/1.1 200 OK" "$content" | $__S_OPENSSL >/dev/null 2>&1) &
|
$__S_OPENSSL >/dev/null 2>&1 &
|
||||||
fi
|
fi
|
||||||
|
|
||||||
serverproc="$!"
|
serverproc="$!"
|
||||||
@ -2251,7 +2220,7 @@ _initAPI() {
|
|||||||
_debug "ACME_REVOKE_CERT" "$ACME_REVOKE_CERT"
|
_debug "ACME_REVOKE_CERT" "$ACME_REVOKE_CERT"
|
||||||
}
|
}
|
||||||
|
|
||||||
#[domain] [keylength]
|
#[domain] [keylength or isEcc flag]
|
||||||
_initpath() {
|
_initpath() {
|
||||||
|
|
||||||
__initHome
|
__initHome
|
||||||
@ -2280,6 +2249,7 @@ _initpath() {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
_debug2 ACME_DIRECTORY "$ACME_DIRECTORY"
|
||||||
_ACME_SERVER_HOST="$(echo "$ACME_DIRECTORY" | cut -d : -f 2 | tr -s / | cut -d / -f 2)"
|
_ACME_SERVER_HOST="$(echo "$ACME_DIRECTORY" | cut -d : -f 2 | tr -s / | cut -d / -f 2)"
|
||||||
_debug2 "_ACME_SERVER_HOST" "$_ACME_SERVER_HOST"
|
_debug2 "_ACME_SERVER_HOST" "$_ACME_SERVER_HOST"
|
||||||
|
|
||||||
@ -2917,8 +2887,8 @@ _on_before_issue() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if _hasfield "$_chk_web_roots" "$NO_VALUE"; then
|
if _hasfield "$_chk_web_roots" "$NO_VALUE"; then
|
||||||
if ! _exists "nc"; then
|
if ! _exists "socat"; then
|
||||||
_err "Please install netcat(nc) tools first."
|
_err "Please install socat tools first."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@ -3024,6 +2994,10 @@ _on_issue_err() {
|
|||||||
)
|
)
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ "$IS_RENEW" = "1" ] && _hasfield "$Le_Webroot" "dns"; then
|
||||||
|
_err "$_DNS_MANUAL_ERR"
|
||||||
|
fi
|
||||||
|
|
||||||
if [ "$DEBUG" ] && [ "$DEBUG" -gt "0" ]; then
|
if [ "$DEBUG" ] && [ "$DEBUG" -gt "0" ]; then
|
||||||
_debug "$(_dlg_versions)"
|
_debug "$(_dlg_versions)"
|
||||||
fi
|
fi
|
||||||
@ -3056,6 +3030,10 @@ _on_issue_success() {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if _hasfield "$Le_Webroot" "dns"; then
|
||||||
|
_err "$_DNS_MANUAL_WARN"
|
||||||
|
fi
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
updateaccount() {
|
updateaccount() {
|
||||||
@ -3157,7 +3135,7 @@ _regAccount() {
|
|||||||
fi
|
fi
|
||||||
if [ "$code" = '202' ]; then
|
if [ "$code" = '202' ]; then
|
||||||
_info "Update account tos info success."
|
_info "Update account tos info success."
|
||||||
|
echo "$response" >"$ACCOUNT_JSON_PATH"
|
||||||
CA_KEY_HASH="$(__calcAccountKeyHash)"
|
CA_KEY_HASH="$(__calcAccountKeyHash)"
|
||||||
_debug "Calc CA_KEY_HASH" "$CA_KEY_HASH"
|
_debug "Calc CA_KEY_HASH" "$CA_KEY_HASH"
|
||||||
_savecaconf CA_KEY_HASH "$CA_KEY_HASH"
|
_savecaconf CA_KEY_HASH "$CA_KEY_HASH"
|
||||||
@ -3496,7 +3474,7 @@ issue() {
|
|||||||
token="$(printf "%s\n" "$entry" | _egrep_o '"token":"[^"]*' | cut -d : -f 2 | tr -d '"')"
|
token="$(printf "%s\n" "$entry" | _egrep_o '"token":"[^"]*' | cut -d : -f 2 | tr -d '"')"
|
||||||
_debug token "$token"
|
_debug token "$token"
|
||||||
|
|
||||||
uri="$(printf "%s\n" "$entry" | _egrep_o '"uri":"[^"]*' | cut -d : -f 2,3 | tr -d '"')"
|
uri="$(printf "%s\n" "$entry" | _egrep_o '"uri":"[^"]*' | cut -d '"' -f 4)"
|
||||||
_debug uri "$uri"
|
_debug uri "$uri"
|
||||||
|
|
||||||
keyauthorization="$token.$thumbprint"
|
keyauthorization="$token.$thumbprint"
|
||||||
@ -3631,13 +3609,12 @@ issue() {
|
|||||||
_info "Standalone mode server"
|
_info "Standalone mode server"
|
||||||
_ncaddr="$(_getfield "$_local_addr" "$_ncIndex")"
|
_ncaddr="$(_getfield "$_local_addr" "$_ncIndex")"
|
||||||
_ncIndex="$(_math $_ncIndex + 1)"
|
_ncIndex="$(_math $_ncIndex + 1)"
|
||||||
_startserver "$keyauthorization" "$_ncaddr" &
|
_startserver "$keyauthorization" "$_ncaddr"
|
||||||
if [ "$?" != "0" ]; then
|
if [ "$?" != "0" ]; then
|
||||||
_clearup
|
_clearup
|
||||||
_on_issue_err "$_post_hook" "$vlist"
|
_on_issue_err "$_post_hook" "$vlist"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
serverproc="$!"
|
|
||||||
sleep 1
|
sleep 1
|
||||||
_debug serverproc "$serverproc"
|
_debug serverproc "$serverproc"
|
||||||
elif [ "$_currentRoot" = "$MODE_STATELESS" ]; then
|
elif [ "$_currentRoot" = "$MODE_STATELESS" ]; then
|
||||||
@ -3972,7 +3949,10 @@ issue() {
|
|||||||
Le_NextRenewTime=$(_math "$Le_NextRenewTime" - 86400)
|
Le_NextRenewTime=$(_math "$Le_NextRenewTime" - 86400)
|
||||||
_savedomainconf "Le_NextRenewTime" "$Le_NextRenewTime"
|
_savedomainconf "Le_NextRenewTime" "$Le_NextRenewTime"
|
||||||
|
|
||||||
_on_issue_success "$_post_hook" "$_renew_hook"
|
if ! _on_issue_success "$_post_hook" "$_renew_hook"; then
|
||||||
|
_err "Call hook error."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
if [ "$_real_cert$_real_key$_real_ca$_reload_cmd$_real_fullchain" ]; then
|
if [ "$_real_cert$_real_key$_real_ca$_reload_cmd$_real_fullchain" ]; then
|
||||||
_savedomainconf "Le_RealCertPath" "$_real_cert"
|
_savedomainconf "Le_RealCertPath" "$_real_cert"
|
||||||
@ -4399,15 +4379,19 @@ _installcert() {
|
|||||||
installcronjob() {
|
installcronjob() {
|
||||||
_c_home="$1"
|
_c_home="$1"
|
||||||
_initpath
|
_initpath
|
||||||
if ! _exists "crontab"; then
|
_CRONTAB="crontab"
|
||||||
_err "crontab doesn't exist, so, we can not install cron jobs."
|
if ! _exists "$_CRONTAB" && _exists "fcrontab"; then
|
||||||
|
_CRONTAB="fcrontab"
|
||||||
|
fi
|
||||||
|
if ! _exists "$_CRONTAB"; then
|
||||||
|
_err "crontab/fcrontab doesn't exist, so, we can not install cron jobs."
|
||||||
_err "All your certs will not be renewed automatically."
|
_err "All your certs will not be renewed automatically."
|
||||||
_err "You must add your own cron job to call '$PROJECT_ENTRY --cron' everyday."
|
_err "You must add your own cron job to call '$PROJECT_ENTRY --cron' everyday."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
_info "Installing cron job"
|
_info "Installing cron job"
|
||||||
if ! crontab -l | grep "$PROJECT_ENTRY --cron"; then
|
if ! $_CRONTAB -l | grep "$PROJECT_ENTRY --cron"; then
|
||||||
if [ -f "$LE_WORKING_DIR/$PROJECT_ENTRY" ]; then
|
if [ -f "$LE_WORKING_DIR/$PROJECT_ENTRY" ]; then
|
||||||
lesh="\"$LE_WORKING_DIR\"/$PROJECT_ENTRY"
|
lesh="\"$LE_WORKING_DIR\"/$PROJECT_ENTRY"
|
||||||
else
|
else
|
||||||
@ -4427,10 +4411,10 @@ installcronjob() {
|
|||||||
else
|
else
|
||||||
ct_stdin=-
|
ct_stdin=-
|
||||||
fi
|
fi
|
||||||
crontab -l | {
|
$_CRONTAB -l | {
|
||||||
cat
|
cat
|
||||||
echo "$random_minute $random_hour1,$random_hour2 * * * $lesh --cron --home \"$LE_WORKING_DIR\" $_c_entry> /dev/null"
|
echo "$random_minute $random_hour1,$random_hour2 * * * $lesh --cron --home \"$LE_WORKING_DIR\" $_c_entry> /dev/null"
|
||||||
} | crontab $ct_stdin
|
} | $_CRONTAB $ct_stdin
|
||||||
fi
|
fi
|
||||||
if [ "$?" != "0" ]; then
|
if [ "$?" != "0" ]; then
|
||||||
_err "Install cron job failed. You need to manually renew your certs."
|
_err "Install cron job failed. You need to manually renew your certs."
|
||||||
@ -4441,16 +4425,21 @@ installcronjob() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
uninstallcronjob() {
|
uninstallcronjob() {
|
||||||
if ! _exists "crontab"; then
|
_CRONTAB="crontab"
|
||||||
|
if ! _exists "$_CRONTAB" && _exists "fcrontab"; then
|
||||||
|
_CRONTAB="fcrontab"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! _exists "$_CRONTAB"; then
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
_info "Removing cron job"
|
_info "Removing cron job"
|
||||||
cr="$(crontab -l | grep "$PROJECT_ENTRY --cron")"
|
cr="$($_CRONTAB -l | grep "$PROJECT_ENTRY --cron")"
|
||||||
if [ "$cr" ]; then
|
if [ "$cr" ]; then
|
||||||
if _exists uname && uname -a | grep solaris >/dev/null; then
|
if _exists uname && uname -a | grep solaris >/dev/null; then
|
||||||
crontab -l | sed "/$PROJECT_ENTRY --cron/d" | crontab --
|
$_CRONTAB -l | sed "/$PROJECT_ENTRY --cron/d" | $_CRONTAB --
|
||||||
else
|
else
|
||||||
crontab -l | sed "/$PROJECT_ENTRY --cron/d" | crontab -
|
$_CRONTAB -l | sed "/$PROJECT_ENTRY --cron/d" | $_CRONTAB -
|
||||||
fi
|
fi
|
||||||
LE_WORKING_DIR="$(echo "$cr" | cut -d ' ' -f 9 | tr -d '"')"
|
LE_WORKING_DIR="$(echo "$cr" | cut -d ' ' -f 9 | tr -d '"')"
|
||||||
_info LE_WORKING_DIR "$LE_WORKING_DIR"
|
_info LE_WORKING_DIR "$LE_WORKING_DIR"
|
||||||
@ -4727,7 +4716,7 @@ _precheck() {
|
|||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "$_nocron" ]; then
|
if [ -z "$_nocron" ]; then
|
||||||
if ! _exists "crontab"; then
|
if ! _exists "crontab" && ! _exists "fcrontab"; then
|
||||||
_err "It is recommended to install crontab first. try to install 'cron, crontab, crontabs or vixie-cron'."
|
_err "It is recommended to install crontab first. try to install 'cron, crontab, crontabs or vixie-cron'."
|
||||||
_err "We need to set cron job to renew the certs automatically."
|
_err "We need to set cron job to renew the certs automatically."
|
||||||
_err "Otherwise, your certs will not be able to be renewed automatically."
|
_err "Otherwise, your certs will not be able to be renewed automatically."
|
||||||
@ -4745,9 +4734,9 @@ _precheck() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! _exists "nc"; then
|
if ! _exists "socat"; then
|
||||||
_err "It is recommended to install nc first, try to install 'nc' or 'netcat'."
|
_err "It is recommended to install socat first."
|
||||||
_err "We use nc for standalone server if you use standalone mode."
|
_err "We use socat for standalone server if you use standalone mode."
|
||||||
_err "If you don't use standalone mode, just ignore this warning."
|
_err "If you don't use standalone mode, just ignore this warning."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@ -4847,9 +4836,11 @@ install() {
|
|||||||
_debug "Skip install cron job"
|
_debug "Skip install cron job"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! _precheck "$_nocron"; then
|
if [ "$IN_CRON" != "1" ]; then
|
||||||
_err "Pre-check failed, can not install."
|
if ! _precheck "$_nocron"; then
|
||||||
return 1
|
_err "Pre-check failed, can not install."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ -z "$_c_home" ] && [ "$LE_CONFIG_HOME" != "$LE_WORKING_DIR" ]; then
|
if [ -z "$_c_home" ] && [ "$LE_CONFIG_HOME" != "$LE_WORKING_DIR" ]; then
|
||||||
@ -4902,7 +4893,9 @@ install() {
|
|||||||
|
|
||||||
_info "Installed to $LE_WORKING_DIR/$PROJECT_ENTRY"
|
_info "Installed to $LE_WORKING_DIR/$PROJECT_ENTRY"
|
||||||
|
|
||||||
_installalias "$_c_home"
|
if [ "$IN_CRON" != "1" ]; then
|
||||||
|
_installalias "$_c_home"
|
||||||
|
fi
|
||||||
|
|
||||||
for subf in $_SUB_FOLDERS; do
|
for subf in $_SUB_FOLDERS; do
|
||||||
if [ -d "$subf" ]; then
|
if [ -d "$subf" ]; then
|
||||||
@ -4992,7 +4985,7 @@ _uninstallalias() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
cron() {
|
cron() {
|
||||||
IN_CRON=1
|
export IN_CRON=1
|
||||||
_initpath
|
_initpath
|
||||||
_info "$(__green "===Starting cron===")"
|
_info "$(__green "===Starting cron===")"
|
||||||
if [ "$AUTO_UPGRADE" = "1" ]; then
|
if [ "$AUTO_UPGRADE" = "1" ]; then
|
||||||
@ -5440,7 +5433,7 @@ _process() {
|
|||||||
;;
|
;;
|
||||||
--dns)
|
--dns)
|
||||||
wvalue="dns"
|
wvalue="dns"
|
||||||
if ! _startswith "$2" "-"; then
|
if [ "$2" ] && ! _startswith "$2" "-"; then
|
||||||
wvalue="$2"
|
wvalue="$2"
|
||||||
shift
|
shift
|
||||||
fi
|
fi
|
||||||
|
@ -4,7 +4,9 @@ Before you can deploy your cert, you must [issue the cert first](https://github.
|
|||||||
|
|
||||||
Here are the scripts to deploy the certs/key to the server/services.
|
Here are the scripts to deploy the certs/key to the server/services.
|
||||||
|
|
||||||
## 1. Deploy the certs to your cpanel host.
|
## 1. Deploy the certs to your cpanel host
|
||||||
|
|
||||||
|
If you want to deploy using cpanel UAPI see 7.
|
||||||
|
|
||||||
(cpanel deploy hook is not finished yet, this is just an example.)
|
(cpanel deploy hook is not finished yet, this is just an example.)
|
||||||
|
|
||||||
@ -18,7 +20,7 @@ export DEPLOY_CPANEL_PASSWORD=PASSWORD
|
|||||||
acme.sh --deploy -d example.com --deploy-hook cpanel
|
acme.sh --deploy -d example.com --deploy-hook cpanel
|
||||||
```
|
```
|
||||||
|
|
||||||
## 2. Deploy ssl cert on kong proxy engine based on api.
|
## 2. Deploy ssl cert on kong proxy engine based on api
|
||||||
|
|
||||||
Before you can deploy your cert, you must [issue the cert first](https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert).
|
Before you can deploy your cert, you must [issue the cert first](https://github.com/Neilpang/acme.sh/wiki/How-to-issue-a-cert).
|
||||||
Currently supports Kong-v0.10.x.
|
Currently supports Kong-v0.10.x.
|
||||||
@ -27,11 +29,11 @@ Currently supports Kong-v0.10.x.
|
|||||||
acme.sh --deploy -d ftp.example.com --deploy-hook kong
|
acme.sh --deploy -d ftp.example.com --deploy-hook kong
|
||||||
```
|
```
|
||||||
|
|
||||||
## 3. Deploy the cert to remote server through SSH access.
|
## 3. Deploy the cert to remote server through SSH access
|
||||||
|
|
||||||
(TODO)
|
(TODO)
|
||||||
|
|
||||||
## 4. Deploy the cert to local vsftpd server.
|
## 4. Deploy the cert to local vsftpd server
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
acme.sh --deploy -d ftp.example.com --deploy-hook vsftpd
|
acme.sh --deploy -d ftp.example.com --deploy-hook vsftpd
|
||||||
@ -53,7 +55,7 @@ export DEPLOY_VSFTPD_RELOAD="/etc/init.d/vsftpd restart"
|
|||||||
acme.sh --deploy -d ftp.example.com --deploy-hook vsftpd
|
acme.sh --deploy -d ftp.example.com --deploy-hook vsftpd
|
||||||
```
|
```
|
||||||
|
|
||||||
## 5. Deploy the cert to local exim4 server.
|
## 5. Deploy the cert to local exim4 server
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
acme.sh --deploy -d ftp.example.com --deploy-hook exim4
|
acme.sh --deploy -d ftp.example.com --deploy-hook exim4
|
||||||
@ -80,3 +82,37 @@ acme.sh --deploy -d ftp.example.com --deploy-hook exim4
|
|||||||
```sh
|
```sh
|
||||||
acme.sh --deploy -d ftp.example.com --deploy-hook keychain
|
acme.sh --deploy -d ftp.example.com --deploy-hook keychain
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## 7. Deploy to cpanel host using UAPI
|
||||||
|
|
||||||
|
This hook is using UAPI and works in cPanel & WHM version 56 or newer.
|
||||||
|
```
|
||||||
|
acme.sh --deploy -d example.com --deploy-hook cpanel_uapi
|
||||||
|
```
|
||||||
|
DEPLOY_CPANEL_USER is required only if you run the script as root and it should contain cpanel username.
|
||||||
|
```sh
|
||||||
|
export DEPLOY_CPANEL_USER=username
|
||||||
|
acme.sh --deploy -d example.com --deploy-hook cpanel_uapi
|
||||||
|
```
|
||||||
|
Please note, that the cpanel_uapi hook will deploy only the first domain when your certificate will automatically renew. Therefore you should issue a separete certificate for each domain.
|
||||||
|
|
||||||
|
## 8. Deploy the cert to your FRITZ!Box router
|
||||||
|
|
||||||
|
You must specify the credentials that have administrative privileges on the FRITZ!Box in order to deploy the certificate, plus the URL of your FRITZ!Box, through the following environment variables:
|
||||||
|
```sh
|
||||||
|
$ export DEPLOY_FRITZBOX_USERNAME=my_username
|
||||||
|
$ export DEPLOY_FRITZBOX_PASSWORD=the_password
|
||||||
|
$ export DEPLOY_FRITZBOX_URL=https://fritzbox.example.com
|
||||||
|
```
|
||||||
|
|
||||||
|
After the first deployment, these values will be stored in your $HOME/.acme.sh/account.conf. You may now deploy the certificate like this:
|
||||||
|
|
||||||
|
```sh
|
||||||
|
acme.sh --deploy -d fritzbox.example.com --deploy-hook fritzbox
|
||||||
|
```
|
||||||
|
|
||||||
|
## 9. Deploy the cert to strongswan
|
||||||
|
|
||||||
|
```sh
|
||||||
|
acme.sh --deploy -d ftp.example.com --deploy-hook strongswan
|
||||||
|
```
|
||||||
|
@ -1,29 +0,0 @@
|
|||||||
#!/usr/bin/env sh
|
|
||||||
|
|
||||||
#Here is the script to deploy the cert to your cpanel account by the cpanel APIs.
|
|
||||||
|
|
||||||
#returns 0 means success, otherwise error.
|
|
||||||
|
|
||||||
#export DEPLOY_CPANEL_USER=myusername
|
|
||||||
#export DEPLOY_CPANEL_PASSWORD=PASSWORD
|
|
||||||
|
|
||||||
######## Public functions #####################
|
|
||||||
|
|
||||||
#domain keyfile certfile cafile fullchain
|
|
||||||
cpanel_deploy() {
|
|
||||||
_cdomain="$1"
|
|
||||||
_ckey="$2"
|
|
||||||
_ccert="$3"
|
|
||||||
_cca="$4"
|
|
||||||
_cfullchain="$5"
|
|
||||||
|
|
||||||
_debug _cdomain "$_cdomain"
|
|
||||||
_debug _ckey "$_ckey"
|
|
||||||
_debug _ccert "$_ccert"
|
|
||||||
_debug _cca "$_cca"
|
|
||||||
_debug _cfullchain "$_cfullchain"
|
|
||||||
|
|
||||||
_err "Not implemented yet"
|
|
||||||
return 1
|
|
||||||
|
|
||||||
}
|
|
64
deploy/cpanel_uapi.sh
Normal file
64
deploy/cpanel_uapi.sh
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
# Here is the script to deploy the cert to your cpanel using the cpanel API.
|
||||||
|
# Uses command line uapi. --user option is needed only if run as root.
|
||||||
|
# Returns 0 when success.
|
||||||
|
# Written by Santeri Kannisto <santeri.kannisto@2globalnomads.info>
|
||||||
|
# Public domain, 2017
|
||||||
|
|
||||||
|
#export DEPLOY_CPANEL_USER=myusername
|
||||||
|
|
||||||
|
######## Public functions #####################
|
||||||
|
|
||||||
|
#domain keyfile certfile cafile fullchain
|
||||||
|
|
||||||
|
cpanel_uapi_deploy() {
|
||||||
|
_cdomain="$1"
|
||||||
|
_ckey="$2"
|
||||||
|
_ccert="$3"
|
||||||
|
_cca="$4"
|
||||||
|
_cfullchain="$5"
|
||||||
|
|
||||||
|
_debug _cdomain "$_cdomain"
|
||||||
|
_debug _ckey "$_ckey"
|
||||||
|
_debug _ccert "$_ccert"
|
||||||
|
_debug _cca "$_cca"
|
||||||
|
_debug _cfullchain "$_cfullchain"
|
||||||
|
|
||||||
|
if ! _exists uapi; then
|
||||||
|
_err "The command uapi is not found."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
if ! _exists php; then
|
||||||
|
_err "The command php is not found."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
# read cert and key files and urlencode both
|
||||||
|
_certstr=$(cat "$_ccert")
|
||||||
|
_keystr=$(cat "$_ckey")
|
||||||
|
_cert=$(php -r "echo urlencode(\"$_certstr\");")
|
||||||
|
_key=$(php -r "echo urlencode(\"$_keystr\");")
|
||||||
|
|
||||||
|
_debug _cert "$_cert"
|
||||||
|
_debug _key "$_key"
|
||||||
|
|
||||||
|
if [ "$(id -u)" = 0 ]; then
|
||||||
|
if [ -z "$DEPLOY_CPANEL_USER" ]; then
|
||||||
|
_err "It seems that you are root, please define the target user name: export DEPLOY_CPANEL_USER=username"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_savedomainconf DEPLOY_CPANEL_USER "$DEPLOY_CPANEL_USER"
|
||||||
|
_response=$(uapi --user="$DEPLOY_CPANEL_USER" SSL install_ssl domain="$_cdomain" cert="$_cert" key="$_key")
|
||||||
|
else
|
||||||
|
_response=$(uapi SSL install_ssl domain="$_cdomain" cert="$_cert" key="$_key")
|
||||||
|
fi
|
||||||
|
error_response="status: 0"
|
||||||
|
if test "${_response#*$error_response}" != "$_response"; then
|
||||||
|
_err "Error in deploying certificate:"
|
||||||
|
_err "$_response"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_debug response "$_response"
|
||||||
|
_info "Certificate successfully deployed"
|
||||||
|
return 0
|
||||||
|
}
|
108
deploy/fritzbox.sh
Normal file
108
deploy/fritzbox.sh
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
#Here is a script to deploy cert to an AVM FRITZ!Box router.
|
||||||
|
|
||||||
|
#returns 0 means success, otherwise error.
|
||||||
|
|
||||||
|
#DEPLOY_FRITZBOX_USERNAME="username"
|
||||||
|
#DEPLOY_FRITZBOX_PASSWORD="password"
|
||||||
|
#DEPLOY_FRITZBOX_URL="https://fritz.box"
|
||||||
|
|
||||||
|
# Kudos to wikrie at Github for his FRITZ!Box update script:
|
||||||
|
# https://gist.github.com/wikrie/f1d5747a714e0a34d0582981f7cb4cfb
|
||||||
|
|
||||||
|
######## Public functions #####################
|
||||||
|
|
||||||
|
#domain keyfile certfile cafile fullchain
|
||||||
|
fritzbox_deploy() {
|
||||||
|
_cdomain="$1"
|
||||||
|
_ckey="$2"
|
||||||
|
_ccert="$3"
|
||||||
|
_cca="$4"
|
||||||
|
_cfullchain="$5"
|
||||||
|
|
||||||
|
_debug _cdomain "$_cdomain"
|
||||||
|
_debug _ckey "$_ckey"
|
||||||
|
_debug _ccert "$_ccert"
|
||||||
|
_debug _cca "$_cca"
|
||||||
|
_debug _cfullchain "$_cfullchain"
|
||||||
|
|
||||||
|
if ! _exists iconv; then
|
||||||
|
_err "iconv not found"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_fritzbox_username="${DEPLOY_FRITZBOX_USERNAME}"
|
||||||
|
_fritzbox_password="${DEPLOY_FRITZBOX_PASSWORD}"
|
||||||
|
_fritzbox_url="${DEPLOY_FRITZBOX_URL}"
|
||||||
|
|
||||||
|
_debug _fritzbox_url "$_fritzbox_url"
|
||||||
|
_debug _fritzbox_username "$_fritzbox_username"
|
||||||
|
_secure_debug _fritzbox_password "$_fritzbox_password"
|
||||||
|
if [ -z "$_fritzbox_username" ]; then
|
||||||
|
_err "FRITZ!Box username is not found, please define DEPLOY_FRITZBOX_USERNAME."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
if [ -z "$_fritzbox_password" ]; then
|
||||||
|
_err "FRITZ!Box password is not found, please define DEPLOY_FRITZBOX_PASSWORD."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
if [ -z "$_fritzbox_url" ]; then
|
||||||
|
_err "FRITZ!Box url is not found, please define DEPLOY_FRITZBOX_URL."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_saveaccountconf DEPLOY_FRITZBOX_USERNAME "${_fritzbox_username}"
|
||||||
|
_saveaccountconf DEPLOY_FRITZBOX_PASSWORD "${_fritzbox_password}"
|
||||||
|
_saveaccountconf DEPLOY_FRITZBOX_URL "${_fritzbox_url}"
|
||||||
|
|
||||||
|
# Do not check for a valid SSL certificate, because initially the cert is not valid, so it could not install the LE generated certificate
|
||||||
|
export HTTPS_INSECURE=1
|
||||||
|
|
||||||
|
_info "Log in to the FRITZ!Box"
|
||||||
|
_fritzbox_challenge="$(_get "${_fritzbox_url}/login_sid.lua" | sed -e 's/^.*<Challenge>//' -e 's/<\/Challenge>.*$//')"
|
||||||
|
_fritzbox_hash="$(printf "%s-%s" "${_fritzbox_challenge}" "${_fritzbox_password}" | iconv -f ASCII -t UTF16LE | md5sum | awk '{print $1}')"
|
||||||
|
_fritzbox_sid="$(_get "${_fritzbox_url}/login_sid.lua?sid=0000000000000000&username=${_fritzbox_username}&response=${_fritzbox_challenge}-${_fritzbox_hash}" | sed -e 's/^.*<SID>//' -e 's/<\/SID>.*$//')"
|
||||||
|
|
||||||
|
if [ -z "${_fritzbox_sid}" ] || [ "${_fritzbox_sid}" = "0000000000000000" ]; then
|
||||||
|
_err "Logging in to the FRITZ!Box failed. Please check username, password and URL."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_info "Generate form POST request"
|
||||||
|
_post_request="$(_mktemp)"
|
||||||
|
_post_boundary="---------------------------$(date +%Y%m%d%H%M%S)"
|
||||||
|
# _CERTPASSWORD_ is unset because Let's Encrypt certificates don't have a password. But if they ever do, here's the place to use it!
|
||||||
|
_CERTPASSWORD_=
|
||||||
|
{
|
||||||
|
printf -- "--"
|
||||||
|
printf -- "%s\r\n" "${_post_boundary}"
|
||||||
|
printf "Content-Disposition: form-data; name=\"sid\"\r\n\r\n%s\r\n" "${_fritzbox_sid}"
|
||||||
|
printf -- "--"
|
||||||
|
printf -- "%s\r\n" "${_post_boundary}"
|
||||||
|
printf "Content-Disposition: form-data; name=\"BoxCertPassword\"\r\n\r\n%s\r\n" "${_CERTPASSWORD_}"
|
||||||
|
printf -- "--"
|
||||||
|
printf -- "%s\r\n" "${_post_boundary}"
|
||||||
|
printf "Content-Disposition: form-data; name=\"BoxCertImportFile\"; filename=\"BoxCert.pem\"\r\n"
|
||||||
|
printf "Content-Type: application/octet-stream\r\n\r\n"
|
||||||
|
cat "${_ckey}" "${_cfullchain}"
|
||||||
|
printf "\r\n"
|
||||||
|
printf -- "--"
|
||||||
|
printf -- "%s--" "${_post_boundary}"
|
||||||
|
} >>"${_post_request}"
|
||||||
|
|
||||||
|
_info "Upload certificate to the FRITZ!Box"
|
||||||
|
|
||||||
|
export _H1="Content-type: multipart/form-data boundary=${_post_boundary}"
|
||||||
|
_post "$(cat "${_post_request}")" "${_fritzbox_url}/cgi-bin/firmwarecfg" | grep SSL
|
||||||
|
|
||||||
|
retval=$?
|
||||||
|
if [ $retval = 0 ]; then
|
||||||
|
_info "Upload successful"
|
||||||
|
else
|
||||||
|
_err "Upload failed"
|
||||||
|
fi
|
||||||
|
rm "${_post_request}"
|
||||||
|
|
||||||
|
return $retval
|
||||||
|
}
|
32
deploy/strongswan.sh
Normal file
32
deploy/strongswan.sh
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
#Here is a sample custom api script.
|
||||||
|
#This file name is "myapi.sh"
|
||||||
|
#So, here must be a method myapi_deploy()
|
||||||
|
#Which will be called by acme.sh to deploy the cert
|
||||||
|
#returns 0 means success, otherwise error.
|
||||||
|
|
||||||
|
######## Public functions #####################
|
||||||
|
|
||||||
|
#domain keyfile certfile cafile fullchain
|
||||||
|
strongswan_deploy() {
|
||||||
|
_cdomain="$1"
|
||||||
|
_ckey="$2"
|
||||||
|
_ccert="$3"
|
||||||
|
_cca="$4"
|
||||||
|
_cfullchain="$5"
|
||||||
|
|
||||||
|
_debug _cdomain "$_cdomain"
|
||||||
|
_debug _ckey "$_ckey"
|
||||||
|
_debug _ccert "$_ccert"
|
||||||
|
_debug _cca "$_cca"
|
||||||
|
_debug _cfullchain "$_cfullchain"
|
||||||
|
|
||||||
|
cat "$_ckey" >"/etc/ipsec.d/private/$(basename "$_ckey")"
|
||||||
|
cat "$_ccert" >"/etc/ipsec.d/certs/$(basename "$_ccert")"
|
||||||
|
cat "$_cca" >"/etc/ipsec.d/cacerts/$(basename "$_cca")"
|
||||||
|
cat "$_cfullchain" >"/etc/ipsec.d/cacerts/$(basename "$_cfullchain")"
|
||||||
|
|
||||||
|
ipsec reload
|
||||||
|
|
||||||
|
}
|
100
deploy/unifi.sh
Normal file
100
deploy/unifi.sh
Normal file
@ -0,0 +1,100 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
#Here is a script to deploy cert to unifi server.
|
||||||
|
|
||||||
|
#returns 0 means success, otherwise error.
|
||||||
|
|
||||||
|
#DEPLOY_UNIFI_KEYSTORE="/usr/lib/unifi/data/keystore"
|
||||||
|
#DEPLOY_UNIFI_KEYPASS="aircontrolenterprise"
|
||||||
|
#DEPLOY_UNIFI_RELOAD="service unifi restart"
|
||||||
|
|
||||||
|
######## Public functions #####################
|
||||||
|
|
||||||
|
#domain keyfile certfile cafile fullchain
|
||||||
|
unifi_deploy() {
|
||||||
|
_cdomain="$1"
|
||||||
|
_ckey="$2"
|
||||||
|
_ccert="$3"
|
||||||
|
_cca="$4"
|
||||||
|
_cfullchain="$5"
|
||||||
|
|
||||||
|
_debug _cdomain "$_cdomain"
|
||||||
|
_debug _ckey "$_ckey"
|
||||||
|
_debug _ccert "$_ccert"
|
||||||
|
_debug _cca "$_cca"
|
||||||
|
_debug _cfullchain "$_cfullchain"
|
||||||
|
|
||||||
|
if ! _exists keytool; then
|
||||||
|
_err "keytool not found"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
DEFAULT_UNIFI_KEYSTORE="/usr/lib/unifi/data/keystore"
|
||||||
|
_unifi_keystore="${DEPLOY_UNIFI_KEYSTORE:-$DEFAULT_UNIFI_KEYSTORE}"
|
||||||
|
DEFAULT_UNIFI_KEYPASS="aircontrolenterprise"
|
||||||
|
_unifi_keypass="${DEPLOY_UNIFI_KEYPASS:-$DEFAULT_UNIFI_KEYPASS}"
|
||||||
|
DEFAULT_UNIFI_RELOAD="service unifi restart"
|
||||||
|
_reload="${DEPLOY_UNIFI_RELOAD:-$DEFAULT_UNIFI_RELOAD}"
|
||||||
|
|
||||||
|
_debug _unifi_keystore "$_unifi_keystore"
|
||||||
|
if [ ! -f "$_unifi_keystore" ]; then
|
||||||
|
if [ -z "$DEPLOY_UNIFI_KEYSTORE" ]; then
|
||||||
|
_err "unifi keystore is not found, please define DEPLOY_UNIFI_KEYSTORE"
|
||||||
|
return 1
|
||||||
|
else
|
||||||
|
_err "It seems that the specified unifi keystore is not valid, please check."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if [ ! -w "$_unifi_keystore" ]; then
|
||||||
|
_err "The file $_unifi_keystore is not writable, please change the permission."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_info "Generate import pkcs12"
|
||||||
|
_import_pkcs12="$(_mktemp)"
|
||||||
|
_toPkcs "$_import_pkcs12" "$_ckey" "$_ccert" "$_cca" "$_unifi_keypass" unifi root
|
||||||
|
if [ "$?" != "0" ]; then
|
||||||
|
_err "Oops, error creating import pkcs12, please report bug to us."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_info "Modify unifi keystore: $_unifi_keystore"
|
||||||
|
if keytool -importkeystore \
|
||||||
|
-deststorepass "$_unifi_keypass" -destkeypass "$_unifi_keypass" -destkeystore "$_unifi_keystore" \
|
||||||
|
-srckeystore "$_import_pkcs12" -srcstoretype PKCS12 -srcstorepass "$_unifi_keypass" \
|
||||||
|
-alias unifi -noprompt; then
|
||||||
|
_info "Import keystore success!"
|
||||||
|
rm "$_import_pkcs12"
|
||||||
|
else
|
||||||
|
_err "Import unifi keystore error, please report bug to us."
|
||||||
|
rm "$_import_pkcs12"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_info "Run reload: $_reload"
|
||||||
|
if eval "$_reload"; then
|
||||||
|
_info "Reload success!"
|
||||||
|
if [ "$DEPLOY_UNIFI_KEYSTORE" ]; then
|
||||||
|
_savedomainconf DEPLOY_UNIFI_KEYSTORE "$DEPLOY_UNIFI_KEYSTORE"
|
||||||
|
else
|
||||||
|
_cleardomainconf DEPLOY_UNIFI_KEYSTORE
|
||||||
|
fi
|
||||||
|
if [ "$DEPLOY_UNIFI_KEYPASS" ]; then
|
||||||
|
_savedomainconf DEPLOY_UNIFI_KEYPASS "$DEPLOY_UNIFI_KEYPASS"
|
||||||
|
else
|
||||||
|
_cleardomainconf DEPLOY_UNIFI_KEYPASS
|
||||||
|
fi
|
||||||
|
if [ "$DEPLOY_UNIFI_RELOAD" ]; then
|
||||||
|
_savedomainconf DEPLOY_UNIFI_RELOAD "$DEPLOY_UNIFI_RELOAD"
|
||||||
|
else
|
||||||
|
_cleardomainconf DEPLOY_UNIFI_RELOAD
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
_err "Reload error"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
return 0
|
||||||
|
|
||||||
|
}
|
@ -420,6 +420,7 @@ Ok, let's issue a cert now:
|
|||||||
```
|
```
|
||||||
acme.sh --issue --dns dns_cloudns -d example.com -d www.example.com
|
acme.sh --issue --dns dns_cloudns -d example.com -d www.example.com
|
||||||
```
|
```
|
||||||
|
The `CLOUDNS_AUTH_ID` and `CLOUDNS_AUTH_PASSWORD` will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
|
||||||
|
|
||||||
## 22. Use Infoblox API
|
## 22. Use Infoblox API
|
||||||
|
|
||||||
@ -512,14 +513,11 @@ export DuckDNS_Token="aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
|
|||||||
```
|
```
|
||||||
|
|
||||||
Please note that since DuckDNS uses StartSSL as their cert provider, thus
|
Please note that since DuckDNS uses StartSSL as their cert provider, thus
|
||||||
--insecure must be used when issuing certs:
|
--insecure may need to be used when issuing certs:
|
||||||
```
|
```
|
||||||
acme.sh --insecure --issue --dns dns_duckdns -d mydomain.duckdns.org
|
acme.sh --insecure --issue --dns dns_duckdns -d mydomain.duckdns.org
|
||||||
```
|
```
|
||||||
|
|
||||||
Also, DuckDNS uses the domain name as username for recording changing, so the
|
|
||||||
account file will always store the lastly used domain name.
|
|
||||||
|
|
||||||
For issues, please report to https://github.com/raidenii/acme.sh/issues.
|
For issues, please report to https://github.com/raidenii/acme.sh/issues.
|
||||||
|
|
||||||
## 28. Use Name.com API
|
## 28. Use Name.com API
|
||||||
@ -585,6 +583,25 @@ acme.sh --issue --dns dns_yandex -d mydomain.example.org
|
|||||||
|
|
||||||
For issues, please report to https://github.com/non7top/acme.sh/issues.
|
For issues, please report to https://github.com/non7top/acme.sh/issues.
|
||||||
|
|
||||||
|
## 31. Use Hurricane Electric
|
||||||
|
|
||||||
|
Hurricane Electric doesn't have an API so just set your login credentials like so:
|
||||||
|
|
||||||
|
```
|
||||||
|
export HE_Username="yourusername"
|
||||||
|
export HE_Password="password"
|
||||||
|
```
|
||||||
|
|
||||||
|
Then you can issue your certificate:
|
||||||
|
|
||||||
|
```
|
||||||
|
acme.sh --issue --dns dns_he -d example.com -d www.example.com
|
||||||
|
```
|
||||||
|
|
||||||
|
The `HE_Username` and `HE_Password` settings will be saved in `~/.acme.sh/account.conf` and will be reused when needed.
|
||||||
|
|
||||||
|
Please report any issues to https://github.com/angel333/acme.sh or to <me@ondrejsimek.com>.
|
||||||
|
|
||||||
# Use custom API
|
# Use custom API
|
||||||
|
|
||||||
If your API is not supported yet, you can write your own DNS API.
|
If your API is not supported yet, you can write your own DNS API.
|
||||||
@ -601,6 +618,7 @@ acme.sh --issue --dns dns_myapi -d example.com -d www.example.com
|
|||||||
|
|
||||||
For more details, please check our sample script: [dns_myapi.sh](dns_myapi.sh)
|
For more details, please check our sample script: [dns_myapi.sh](dns_myapi.sh)
|
||||||
|
|
||||||
|
See: https://github.com/Neilpang/acme.sh/wiki/DNS-API-Dev-Guide
|
||||||
|
|
||||||
# Use lexicon DNS API
|
# Use lexicon DNS API
|
||||||
|
|
||||||
|
@ -87,6 +87,7 @@ _get_root() {
|
|||||||
_debug "response" "$response"
|
_debug "response" "$response"
|
||||||
while true; do
|
while true; do
|
||||||
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
|
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
|
||||||
|
_debug2 "Checking domain: $h"
|
||||||
if [ -z "$h" ]; then
|
if [ -z "$h" ]; then
|
||||||
if _contains "$response" "<IsTruncated>true</IsTruncated>" && _contains "$response" "<NextMarker>"; then
|
if _contains "$response" "<IsTruncated>true</IsTruncated>" && _contains "$response" "<NextMarker>"; then
|
||||||
_debug "IsTruncated"
|
_debug "IsTruncated"
|
||||||
@ -102,23 +103,23 @@ _get_root() {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
#not valid
|
#not valid
|
||||||
|
_err "Invalid domain"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if _contains "$response" "<Name>$h.</Name>"; then
|
if _contains "$response" "<Name>$h.</Name>"; then
|
||||||
hostedzone="$(echo "$response" | sed 's/<HostedZone>/#&/g' | tr '#' '\n' | _egrep_o "<HostedZone><Id>[^<]*<.Id><Name>$h.<.Name>.*<PrivateZone>false<.PrivateZone>.*<.HostedZone>")"
|
hostedzone="$(echo "$response" | sed 's/<HostedZone>/#&/g' | tr '#' '\n' | _egrep_o "<HostedZone><Id>[^<]*<.Id><Name>$h.<.Name>.*<PrivateZone>false<.PrivateZone>.*<.HostedZone>")"
|
||||||
_debug hostedzone "$hostedzone"
|
_debug hostedzone "$hostedzone"
|
||||||
if [ -z "$hostedzone" ]; then
|
if [ "$hostedzone" ]; then
|
||||||
_err "Error, can not get hostedzone."
|
_domain_id=$(printf "%s\n" "$hostedzone" | _egrep_o "<Id>.*<.Id>" | head -n 1 | _egrep_o ">.*<" | tr -d "<>")
|
||||||
|
if [ "$_domain_id" ]; then
|
||||||
|
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
|
||||||
|
_domain=$h
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
_err "Can not find domain id: $h"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
_domain_id=$(printf "%s\n" "$hostedzone" | _egrep_o "<Id>.*<.Id>" | head -n 1 | _egrep_o ">.*<" | tr -d "<>")
|
|
||||||
if [ "$_domain_id" ]; then
|
|
||||||
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
|
|
||||||
_domain=$h
|
|
||||||
return 0
|
|
||||||
fi
|
|
||||||
return 1
|
|
||||||
fi
|
fi
|
||||||
p=$i
|
p=$i
|
||||||
i=$(_math "$i" + 1)
|
i=$(_math "$i" + 1)
|
||||||
|
@ -96,6 +96,16 @@ _dns_cloudns_init_check() {
|
|||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
CLOUDNS_AUTH_ID="${CLOUDNS_AUTH_ID:-$(_readaccountconf_mutable CLOUDNS_AUTH_ID)}"
|
||||||
|
CLOUDNS_AUTH_PASSWORD="${CLOUDNS_AUTH_PASSWORD:-$(_readaccountconf_mutable CLOUDNS_AUTH_PASSWORD)}"
|
||||||
|
if [ -z "$CLOUDNS_AUTH_ID" ] || [ -z "$CLOUDNS_AUTH_PASSWORD" ]; then
|
||||||
|
CLOUDNS_AUTH_ID=""
|
||||||
|
CLOUDNS_AUTH_PASSWORD=""
|
||||||
|
_err "You don't specify cloudns api id and password yet."
|
||||||
|
_err "Please create you id and password and try again."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
if [ -z "$CLOUDNS_AUTH_ID" ]; then
|
if [ -z "$CLOUDNS_AUTH_ID" ]; then
|
||||||
_err "CLOUDNS_AUTH_ID is not configured"
|
_err "CLOUDNS_AUTH_ID is not configured"
|
||||||
return 1
|
return 1
|
||||||
@ -113,6 +123,10 @@ _dns_cloudns_init_check() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
#save the api id and password to the account conf file.
|
||||||
|
_saveaccountconf_mutable CLOUDNS_AUTH_ID "$CLOUDNS_AUTH_ID"
|
||||||
|
_saveaccountconf_mutable CLOUDNS_AUTH_PASSWORD "$CLOUDNS_AUTH_PASSWORD"
|
||||||
|
|
||||||
CLOUDNS_INIT_CHECK_COMPLETED=1
|
CLOUDNS_INIT_CHECK_COMPLETED=1
|
||||||
|
|
||||||
return 0
|
return 0
|
||||||
|
@ -3,11 +3,14 @@
|
|||||||
#Created by RaidenII, to use DuckDNS's API to add/remove text records
|
#Created by RaidenII, to use DuckDNS's API to add/remove text records
|
||||||
#06/27/2017
|
#06/27/2017
|
||||||
|
|
||||||
# Currently only support single domain access
|
# Pass credentials before "acme.sh --issue --dns dns_duckdns ..."
|
||||||
# Due to the fact that DuckDNS uses StartSSL as cert provider, --insecure must be used with acme.sh
|
# --
|
||||||
|
# export DuckDNS_Token="aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
|
||||||
|
# --
|
||||||
|
#
|
||||||
|
# Due to the fact that DuckDNS uses StartSSL as cert provider, --insecure may need to be used with acme.sh
|
||||||
|
|
||||||
DuckDNS_API="https://www.duckdns.org/update"
|
DuckDNS_API="https://www.duckdns.org/update"
|
||||||
API_Params="domains=$DuckDNS_Domain&token=$DuckDNS_Token"
|
|
||||||
|
|
||||||
######## Public functions #####################
|
######## Public functions #####################
|
||||||
|
|
||||||
@ -16,35 +19,36 @@ dns_duckdns_add() {
|
|||||||
fulldomain=$1
|
fulldomain=$1
|
||||||
txtvalue=$2
|
txtvalue=$2
|
||||||
|
|
||||||
# We'll extract the domain/username from full domain
|
DuckDNS_Token="${DuckDNS_Token:-$(_readaccountconf_mutable DuckDNS_Token)}"
|
||||||
DuckDNS_Domain=$(echo "$fulldomain" | _lower_case | _egrep_o '.[^.]*.duckdns.org' | cut -d . -f 2)
|
|
||||||
|
|
||||||
if [ -z "$DuckDNS_Domain" ]; then
|
|
||||||
_err "Error extracting the domain."
|
|
||||||
return 1
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [ -z "$DuckDNS_Token" ]; then
|
if [ -z "$DuckDNS_Token" ]; then
|
||||||
DuckDNS_Token=""
|
_err "You must export variable: DuckDNS_Token"
|
||||||
_err "The token for your DuckDNS account is necessary."
|
_err "The token for your DuckDNS account is necessary."
|
||||||
_err "You can look it up in your DuckDNS account."
|
_err "You can look it up in your DuckDNS account."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Now save the credentials.
|
# Now save the credentials.
|
||||||
_saveaccountconf DuckDNS_Domain "$DuckDNS_Domain"
|
_saveaccountconf_mutable DuckDNS_Token "$DuckDNS_Token"
|
||||||
_saveaccountconf DuckDNS_Token "$DuckDNS_Token"
|
|
||||||
|
|
||||||
# Unfortunately, DuckDNS does not seems to support lookup domain through API
|
# Unfortunately, DuckDNS does not seems to support lookup domain through API
|
||||||
# So I assume your credentials (which are your domain and token) are correct
|
# So I assume your credentials (which are your domain and token) are correct
|
||||||
# If something goes wrong, we will get a KO response from DuckDNS
|
# If something goes wrong, we will get a KO response from DuckDNS
|
||||||
|
|
||||||
|
if ! _duckdns_get_domain; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
# Now add the TXT record to DuckDNS
|
# Now add the TXT record to DuckDNS
|
||||||
_info "Trying to add TXT record"
|
_info "Trying to add TXT record"
|
||||||
if _duckdns_rest GET "$API_Params&txt=$txtvalue" && [ "$response" = "OK" ]; then
|
if _duckdns_rest GET "domains=$_duckdns_domain&token=$DuckDNS_Token&txt=$txtvalue"; then
|
||||||
_info "TXT record has been successfully added to your DuckDNS domain."
|
if [ "$response" = "OK" ]; then
|
||||||
_info "Note that all subdomains under this domain uses the same TXT record."
|
_info "TXT record has been successfully added to your DuckDNS domain."
|
||||||
return 0
|
_info "Note that all subdomains under this domain uses the same TXT record."
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
_err "Errors happened during adding the TXT record, response=$response"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
_err "Errors happened during adding the TXT record."
|
_err "Errors happened during adding the TXT record."
|
||||||
return 1
|
return 1
|
||||||
@ -57,11 +61,28 @@ dns_duckdns_rm() {
|
|||||||
fulldomain=$1
|
fulldomain=$1
|
||||||
txtvalue=$2
|
txtvalue=$2
|
||||||
|
|
||||||
|
DuckDNS_Token="${DuckDNS_Token:-$(_readaccountconf_mutable DuckDNS_Token)}"
|
||||||
|
if [ -z "$DuckDNS_Token" ]; then
|
||||||
|
_err "You must export variable: DuckDNS_Token"
|
||||||
|
_err "The token for your DuckDNS account is necessary."
|
||||||
|
_err "You can look it up in your DuckDNS account."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! _duckdns_get_domain; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
# Now remove the TXT record from DuckDNS
|
# Now remove the TXT record from DuckDNS
|
||||||
_info "Trying to remove TXT record"
|
_info "Trying to remove TXT record"
|
||||||
if _duckdns_rest GET "$API_Params&txt=&clear=true" && [ "$response" = "OK" ]; then
|
if _duckdns_rest GET "domains=$_duckdns_domain&token=$DuckDNS_Token&txt=&clear=true"; then
|
||||||
_info "TXT record has been successfully removed from your DuckDNS domain."
|
if [ "$response" = "OK" ]; then
|
||||||
return 0
|
_info "TXT record has been successfully removed from your DuckDNS domain."
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
_err "Errors happened during removing the TXT record, response=$response"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
else
|
else
|
||||||
_err "Errors happened during removing the TXT record."
|
_err "Errors happened during removing the TXT record."
|
||||||
return 1
|
return 1
|
||||||
@ -70,6 +91,22 @@ dns_duckdns_rm() {
|
|||||||
|
|
||||||
#################### Private functions below ##################################
|
#################### Private functions below ##################################
|
||||||
|
|
||||||
|
#fulldomain=_acme-challenge.domain.duckdns.org
|
||||||
|
#returns
|
||||||
|
# _duckdns_domain=domain
|
||||||
|
_duckdns_get_domain() {
|
||||||
|
|
||||||
|
# We'll extract the domain/username from full domain
|
||||||
|
_duckdns_domain="$(printf "%s" "$fulldomain" | _lower_case | _egrep_o '[.][^.][^.]*[.]duckdns.org' | cut -d . -f 2)"
|
||||||
|
|
||||||
|
if [ -z "$_duckdns_domain" ]; then
|
||||||
|
_err "Error extracting the domain."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
#Usage: method URI
|
#Usage: method URI
|
||||||
_duckdns_rest() {
|
_duckdns_rest() {
|
||||||
method=$1
|
method=$1
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
#
|
#
|
||||||
######## Public functions #####################
|
######## Public functions #####################
|
||||||
|
|
||||||
GANDI_LIVEDNS_API="https://dns.beta.gandi.net/api/v5"
|
GANDI_LIVEDNS_API="https://dns.api.gandi.net/api/v5"
|
||||||
|
|
||||||
#Usage: dns_gandi_livedns_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
#Usage: dns_gandi_livedns_add _acme-challenge.www.domain.com "XKrxpRBosdIKFzxW_CT3KLZNf6q0HG9i01zxXp5CPBs"
|
||||||
dns_gandi_livedns_add() {
|
dns_gandi_livedns_add() {
|
||||||
|
175
dnsapi/dns_he.sh
Executable file
175
dnsapi/dns_he.sh
Executable file
@ -0,0 +1,175 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
# Hurricane Electric hook script for acme.sh
|
||||||
|
#
|
||||||
|
# Environment variables:
|
||||||
|
#
|
||||||
|
# - $HE_Username (your dns.he.net username)
|
||||||
|
# - $HE_Password (your dns.he.net password)
|
||||||
|
#
|
||||||
|
# Author: Ondrej Simek <me@ondrejsimek.com>
|
||||||
|
# Git repo: https://github.com/angel333/acme.sh
|
||||||
|
|
||||||
|
#-- dns_he_add() - Add TXT record --------------------------------------
|
||||||
|
# Usage: dns_he_add _acme-challenge.subdomain.domain.com "XyZ123..."
|
||||||
|
|
||||||
|
dns_he_add() {
|
||||||
|
_full_domain=$1
|
||||||
|
_txt_value=$2
|
||||||
|
_info "Using DNS-01 Hurricane Electric hook"
|
||||||
|
|
||||||
|
if [ -z "$HE_Username" ] || [ -z "$HE_Password" ]; then
|
||||||
|
HE_Username=
|
||||||
|
HE_Password=
|
||||||
|
_err "No auth details provided. Please set user credentials using the \$HE_Username and \$HE_Password envoronment variables."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_saveaccountconf HE_Username "$HE_Username"
|
||||||
|
_saveaccountconf HE_Password "$HE_Password"
|
||||||
|
|
||||||
|
# Fills in the $_zone_id
|
||||||
|
_find_zone "$_full_domain" || return 1
|
||||||
|
_debug "Zone id \"$_zone_id\" will be used."
|
||||||
|
|
||||||
|
body="email=${HE_Username}&pass=${HE_Password}"
|
||||||
|
body="$body&account="
|
||||||
|
body="$body&menu=edit_zone"
|
||||||
|
body="$body&Type=TXT"
|
||||||
|
body="$body&hosted_dns_zoneid=$_zone_id"
|
||||||
|
body="$body&hosted_dns_recordid="
|
||||||
|
body="$body&hosted_dns_editzone=1"
|
||||||
|
body="$body&Priority="
|
||||||
|
body="$body&Name=$_full_domain"
|
||||||
|
body="$body&Content=$_txt_value"
|
||||||
|
body="$body&TTL=300"
|
||||||
|
body="$body&hosted_dns_editrecord=Submit"
|
||||||
|
response="$(_post "$body" "https://dns.he.net/")"
|
||||||
|
exit_code="$?"
|
||||||
|
if [ "$exit_code" -eq 0 ]; then
|
||||||
|
_info "TXT record added successfully."
|
||||||
|
else
|
||||||
|
_err "Couldn't add the TXT record."
|
||||||
|
fi
|
||||||
|
_debug2 response "$response"
|
||||||
|
return "$exit_code"
|
||||||
|
}
|
||||||
|
|
||||||
|
#-- dns_he_rm() - Remove TXT record ------------------------------------
|
||||||
|
# Usage: dns_he_rm _acme-challenge.subdomain.domain.com "XyZ123..."
|
||||||
|
|
||||||
|
dns_he_rm() {
|
||||||
|
_full_domain=$1
|
||||||
|
_txt_value=$2
|
||||||
|
_info "Cleaning up after DNS-01 Hurricane Electric hook"
|
||||||
|
|
||||||
|
# fills in the $_zone_id
|
||||||
|
_find_zone "$_full_domain" || return 1
|
||||||
|
_debug "Zone id \"$_zone_id\" will be used."
|
||||||
|
|
||||||
|
# Find the record id to clean
|
||||||
|
body="email=${HE_Username}&pass=${HE_Password}"
|
||||||
|
body="$body&hosted_dns_zoneid=$_zone_id"
|
||||||
|
body="$body&menu=edit_zone"
|
||||||
|
body="$body&hosted_dns_editzone="
|
||||||
|
domain_regex="$(echo "$_full_domain" | sed 's/\./\\./g')" # escape dots
|
||||||
|
_record_id=$(_post "$body" "https://dns.he.net/" \
|
||||||
|
| tr -d '\n' \
|
||||||
|
| _egrep_o "data=\""${_txt_value}"([^>]+>){6}[^<]+<[^;]+;deleteRecord\('[0-9]+','${domain_regex}','TXT'\)" \
|
||||||
|
| _egrep_o "[0-9]+','${domain_regex}','TXT'\)$" \
|
||||||
|
| _egrep_o "^[0-9]+"
|
||||||
|
)
|
||||||
|
# The series of egreps above could have been done a bit shorter but
|
||||||
|
# I wanted to double-check whether it's the correct record (in case
|
||||||
|
# HE changes their website somehow).
|
||||||
|
|
||||||
|
# Remove the record
|
||||||
|
body="email=${HE_Username}&pass=${HE_Password}"
|
||||||
|
body="$body&menu=edit_zone"
|
||||||
|
body="$body&hosted_dns_zoneid=$_zone_id"
|
||||||
|
body="$body&hosted_dns_recordid=$_record_id"
|
||||||
|
body="$body&hosted_dns_editzone=1"
|
||||||
|
body="$body&hosted_dns_delrecord=1"
|
||||||
|
body="$body&hosted_dns_delconfirm=delete"
|
||||||
|
_post "$body" "https://dns.he.net/" \
|
||||||
|
| grep '<div id="dns_status" onClick="hideThis(this);">Successfully removed record.</div>' \
|
||||||
|
>/dev/null
|
||||||
|
exit_code="$?"
|
||||||
|
if [ "$exit_code" -eq 0 ]; then
|
||||||
|
_info "Record removed successfully."
|
||||||
|
else
|
||||||
|
_err "Could not clean (remove) up the record. Please go to HE administration interface and clean it by hand."
|
||||||
|
return "$exit_code"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
########################## PRIVATE FUNCTIONS ###########################
|
||||||
|
|
||||||
|
#-- _find_zone() -------------------------------------------------------
|
||||||
|
# Returns the most specific zone found in administration interface.
|
||||||
|
#
|
||||||
|
# Example:
|
||||||
|
#
|
||||||
|
# _find_zone first.second.third.co.uk
|
||||||
|
#
|
||||||
|
# ... will return the first zone that exists in admin out of these:
|
||||||
|
# - "first.second.third.co.uk"
|
||||||
|
# - "second.third.co.uk"
|
||||||
|
# - "third.co.uk"
|
||||||
|
# - "co.uk" <-- unlikely
|
||||||
|
# - "uk" <-'
|
||||||
|
#
|
||||||
|
# (another approach would be something like this:
|
||||||
|
# https://github.com/hlandau/acme/blob/master/_doc/dns.hook
|
||||||
|
# - that's better if there are multiple pages. It's so much simpler.
|
||||||
|
# )
|
||||||
|
|
||||||
|
_find_zone() {
|
||||||
|
|
||||||
|
_domain="$1"
|
||||||
|
|
||||||
|
body="email=${HE_Username}&pass=${HE_Password}"
|
||||||
|
_matches=$(_post "$body" "https://dns.he.net/" \
|
||||||
|
| _egrep_o "delete_dom.*name=\"[^\"]+\" value=\"[0-9]+"
|
||||||
|
)
|
||||||
|
# Zone names and zone IDs are in same order
|
||||||
|
_zone_ids=$(echo "$_matches" | cut -d '"' -f 5)
|
||||||
|
_zone_names=$(echo "$_matches" | cut -d '"' -f 3)
|
||||||
|
_debug2 "These are the zones on this HE account:"
|
||||||
|
_debug2 "$_zone_names"
|
||||||
|
_debug2 "And these are their respective IDs:"
|
||||||
|
_debug2 "$_zone_ids"
|
||||||
|
|
||||||
|
# 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}\""
|
||||||
|
|
||||||
|
# Take care of "." and only match whole lines. Note that grep -F
|
||||||
|
# cannot be used because there's no way to make it match whole
|
||||||
|
# lines.
|
||||||
|
regex="^$(echo "$_attempted_zone" | sed 's/\./\\./g')$"
|
||||||
|
line_num=$(echo "$_zone_names" \
|
||||||
|
| grep -n "$regex" \
|
||||||
|
| cut -d : -f 1
|
||||||
|
)
|
||||||
|
|
||||||
|
if [ -n "$line_num" ]; then
|
||||||
|
_zone_id=$(echo "$_zone_ids" | sed "${line_num}q;d")
|
||||||
|
_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:
|
@ -68,7 +68,7 @@ dns_linode_rm() {
|
|||||||
_parameters="&DomainID=$_domain_id"
|
_parameters="&DomainID=$_domain_id"
|
||||||
|
|
||||||
if _rest GET "domain.resource.list" "$_parameters" && [ -n "$response" ]; then
|
if _rest GET "domain.resource.list" "$_parameters" && [ -n "$response" ]; then
|
||||||
response="$(echo "$response" | tr -d "\n" | sed 's/{/\n&/g')"
|
response="$(echo "$response" | tr -d "\n" | tr '{' "|" | sed 's/|/&{/g' | tr "|" "\n")"
|
||||||
|
|
||||||
resource="$(echo "$response" | _egrep_o "{.*\"NAME\":\s*\"$_sub_domain\".*}")"
|
resource="$(echo "$response" | _egrep_o "{.*\"NAME\":\s*\"$_sub_domain\".*}")"
|
||||||
if [ "$resource" ]; then
|
if [ "$resource" ]; then
|
||||||
@ -128,7 +128,7 @@ _get_root() {
|
|||||||
p=1
|
p=1
|
||||||
|
|
||||||
if _rest GET "domain.list"; then
|
if _rest GET "domain.list"; then
|
||||||
response="$(echo "$response" | tr -d "\n" | sed 's/{/\n&/g')"
|
response="$(echo "$response" | tr -d "\n" | tr '{' "|" | sed 's/|/&{/g' | tr "|" "\n")"
|
||||||
while true; do
|
while true; do
|
||||||
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
|
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
|
||||||
_debug h "$h"
|
_debug h "$h"
|
||||||
|
Loading…
x
Reference in New Issue
Block a user