mirror of
https://github.com/plantroon/acme.sh.git
synced 2024-12-22 13:11:41 +00:00
Merge branch 'master' of https://github.com/Neilpang/acme.sh into ssh-deploy
This commit is contained in:
commit
c809b33161
@ -18,7 +18,7 @@ addons:
|
||||
|
||||
install:
|
||||
- if [ "$TRAVIS_OS_NAME" = 'osx' ]; then
|
||||
brew update && brew install openssl;
|
||||
brew update && brew install openssl socat;
|
||||
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/libssl.1.0.0.dylib /usr/local/lib/;
|
||||
@ -30,6 +30,7 @@ install:
|
||||
openssl version 2>&1 || true;
|
||||
$ACME_OPENSSL_BIN version 2>&1 || true;
|
||||
export PATH="$_old_path";
|
||||
else sudo apt-get install socat;
|
||||
fi
|
||||
|
||||
script:
|
||||
|
@ -4,7 +4,7 @@ RUN apk update -f \
|
||||
&& apk --no-cache add -f \
|
||||
openssl \
|
||||
curl \
|
||||
netcat-openbsd \
|
||||
socat \
|
||||
&& rm -rf /var/cache/apk/*
|
||||
|
||||
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 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 \
|
||||
version \
|
||||
|
173
acme.sh
173
acme.sh
@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
VER=2.7.3
|
||||
VER=2.7.4
|
||||
|
||||
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"
|
||||
|
||||
_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=""
|
||||
if [ -t 1 ]; then
|
||||
__INTERACTIVE="1"
|
||||
@ -160,11 +164,11 @@ _dlg_versions() {
|
||||
echo "nginx doesn't exists."
|
||||
fi
|
||||
|
||||
echo "nc:"
|
||||
if _exists "nc"; then
|
||||
nc -h 2>&1
|
||||
echo "socat:"
|
||||
if _exists "socat"; then
|
||||
socat -h 2>&1
|
||||
else
|
||||
_debug "nc doesn't exists."
|
||||
_debug "socat doesn't exists."
|
||||
fi
|
||||
}
|
||||
|
||||
@ -1367,6 +1371,10 @@ _time2str() {
|
||||
echo "$_t_s_a"
|
||||
fi
|
||||
|
||||
#Busybox
|
||||
if echo "$1" | awk '{ print strftime("%c", $0); }' 2>/dev/null; then
|
||||
return
|
||||
fi
|
||||
}
|
||||
|
||||
_normalizeJson() {
|
||||
@ -1806,7 +1814,13 @@ _send_signed_request() {
|
||||
|
||||
_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."
|
||||
_request_retry_times=$(_math "$_request_retry_times" + 1)
|
||||
_sleep 5
|
||||
@ -1959,68 +1973,22 @@ _startserver() {
|
||||
_debug "ncaddr" "$ncaddr"
|
||||
|
||||
_debug "startserver: $$"
|
||||
nchelp="$(nc -h 2>&1)"
|
||||
|
||||
_debug Le_HTTPPort "$Le_HTTPPort"
|
||||
_debug Le_Listen_V4 "$Le_Listen_V4"
|
||||
_debug Le_Listen_V6 "$Le_Listen_V6"
|
||||
_NC="nc"
|
||||
|
||||
_NC="socat"
|
||||
if [ "$Le_Listen_V4" ]; then
|
||||
_NC="$_NC -4"
|
||||
elif [ "$Le_Listen_V6" ]; then
|
||||
_NC="$_NC -6"
|
||||
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"
|
||||
|
||||
#for centos ncat
|
||||
if _contains "$nchelp" "nmap.org"; then
|
||||
_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
|
||||
#todo listen address
|
||||
$_NC TCP-LISTEN:$Le_HTTPPort,crlf,reuseaddr,fork SYSTEM:"sleep 0.5; echo HTTP/1.1 200 OK; echo ; echo $content; echo;" &
|
||||
serverproc="$!"
|
||||
}
|
||||
|
||||
_stopserver() {
|
||||
@ -2030,25 +1998,8 @@ _stopserver() {
|
||||
return
|
||||
fi
|
||||
|
||||
_debug2 "Le_HTTPPort" "$Le_HTTPPort"
|
||||
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
|
||||
kill $pid
|
||||
|
||||
_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
|
||||
@ -2103,7 +2054,7 @@ _starttlsserver() {
|
||||
return 1
|
||||
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
|
||||
__S_OPENSSL="$__S_OPENSSL -accept $opaddr:$port"
|
||||
else
|
||||
@ -2120,9 +2071,9 @@ _starttlsserver() {
|
||||
|
||||
_debug "$__S_OPENSSL"
|
||||
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
|
||||
(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
|
||||
|
||||
serverproc="$!"
|
||||
@ -2298,6 +2249,7 @@ _initpath() {
|
||||
fi
|
||||
fi
|
||||
|
||||
_debug2 ACME_DIRECTORY "$ACME_DIRECTORY"
|
||||
_ACME_SERVER_HOST="$(echo "$ACME_DIRECTORY" | cut -d : -f 2 | tr -s / | cut -d / -f 2)"
|
||||
_debug2 "_ACME_SERVER_HOST" "$_ACME_SERVER_HOST"
|
||||
|
||||
@ -2935,8 +2887,8 @@ _on_before_issue() {
|
||||
fi
|
||||
|
||||
if _hasfield "$_chk_web_roots" "$NO_VALUE"; then
|
||||
if ! _exists "nc"; then
|
||||
_err "Please install netcat(nc) tools first."
|
||||
if ! _exists "socat"; then
|
||||
_err "Please install socat tools first."
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
@ -3042,6 +2994,10 @@ _on_issue_err() {
|
||||
)
|
||||
fi
|
||||
|
||||
if [ "$IS_RENEW" = "1" ] && _hasfield "$Le_Webroot" "dns"; then
|
||||
_err "$_DNS_MANUAL_ERR"
|
||||
fi
|
||||
|
||||
if [ "$DEBUG" ] && [ "$DEBUG" -gt "0" ]; then
|
||||
_debug "$(_dlg_versions)"
|
||||
fi
|
||||
@ -3074,6 +3030,10 @@ _on_issue_success() {
|
||||
fi
|
||||
fi
|
||||
|
||||
if _hasfield "$Le_Webroot" "dns"; then
|
||||
_err "$_DNS_MANUAL_WARN"
|
||||
fi
|
||||
|
||||
}
|
||||
|
||||
updateaccount() {
|
||||
@ -3175,7 +3135,7 @@ _regAccount() {
|
||||
fi
|
||||
if [ "$code" = '202' ]; then
|
||||
_info "Update account tos info success."
|
||||
|
||||
echo "$response" >"$ACCOUNT_JSON_PATH"
|
||||
CA_KEY_HASH="$(__calcAccountKeyHash)"
|
||||
_debug "Calc CA_KEY_HASH" "$CA_KEY_HASH"
|
||||
_savecaconf CA_KEY_HASH "$CA_KEY_HASH"
|
||||
@ -3649,13 +3609,12 @@ issue() {
|
||||
_info "Standalone mode server"
|
||||
_ncaddr="$(_getfield "$_local_addr" "$_ncIndex")"
|
||||
_ncIndex="$(_math $_ncIndex + 1)"
|
||||
_startserver "$keyauthorization" "$_ncaddr" &
|
||||
_startserver "$keyauthorization" "$_ncaddr"
|
||||
if [ "$?" != "0" ]; then
|
||||
_clearup
|
||||
_on_issue_err "$_post_hook" "$vlist"
|
||||
return 1
|
||||
fi
|
||||
serverproc="$!"
|
||||
sleep 1
|
||||
_debug serverproc "$serverproc"
|
||||
elif [ "$_currentRoot" = "$MODE_STATELESS" ]; then
|
||||
@ -3990,7 +3949,10 @@ issue() {
|
||||
Le_NextRenewTime=$(_math "$Le_NextRenewTime" - 86400)
|
||||
_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
|
||||
_savedomainconf "Le_RealCertPath" "$_real_cert"
|
||||
@ -4417,15 +4379,19 @@ _installcert() {
|
||||
installcronjob() {
|
||||
_c_home="$1"
|
||||
_initpath
|
||||
if ! _exists "crontab"; then
|
||||
_err "crontab doesn't exist, so, we can not install cron jobs."
|
||||
_CRONTAB="crontab"
|
||||
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 "You must add your own cron job to call '$PROJECT_ENTRY --cron' everyday."
|
||||
return 1
|
||||
fi
|
||||
|
||||
_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
|
||||
lesh="\"$LE_WORKING_DIR\"/$PROJECT_ENTRY"
|
||||
else
|
||||
@ -4439,15 +4405,15 @@ installcronjob() {
|
||||
_t=$(_time)
|
||||
random_minute=$(_math $_t % 60)
|
||||
if _exists uname && uname -a | grep SunOS >/dev/null; then
|
||||
crontab -l | {
|
||||
$_CRONTAB -l | {
|
||||
cat
|
||||
echo "$random_minute 0 * * * $lesh --cron --home \"$LE_WORKING_DIR\" $_c_entry> /dev/null"
|
||||
} | crontab --
|
||||
} | $_CRONTAB --
|
||||
else
|
||||
crontab -l | {
|
||||
$_CRONTAB -l | {
|
||||
cat
|
||||
echo "$random_minute 0 * * * $lesh --cron --home \"$LE_WORKING_DIR\" $_c_entry> /dev/null"
|
||||
} | crontab -
|
||||
} | $_CRONTAB -
|
||||
fi
|
||||
fi
|
||||
if [ "$?" != "0" ]; then
|
||||
@ -4459,16 +4425,21 @@ installcronjob() {
|
||||
}
|
||||
|
||||
uninstallcronjob() {
|
||||
if ! _exists "crontab"; then
|
||||
_CRONTAB="crontab"
|
||||
if ! _exists "$_CRONTAB" && _exists "fcrontab"; then
|
||||
_CRONTAB="fcrontab"
|
||||
fi
|
||||
|
||||
if ! _exists "$_CRONTAB"; then
|
||||
return
|
||||
fi
|
||||
_info "Removing cron job"
|
||||
cr="$(crontab -l | grep "$PROJECT_ENTRY --cron")"
|
||||
cr="$($_CRONTAB -l | grep "$PROJECT_ENTRY --cron")"
|
||||
if [ "$cr" ]; 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
|
||||
crontab -l | sed "/$PROJECT_ENTRY --cron/d" | crontab -
|
||||
$_CRONTAB -l | sed "/$PROJECT_ENTRY --cron/d" | $_CRONTAB -
|
||||
fi
|
||||
LE_WORKING_DIR="$(echo "$cr" | cut -d ' ' -f 9 | tr -d '"')"
|
||||
_info LE_WORKING_DIR "$LE_WORKING_DIR"
|
||||
@ -4745,7 +4716,7 @@ _precheck() {
|
||||
fi
|
||||
|
||||
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 "We need to set cron job to renew the certs automatically."
|
||||
_err "Otherwise, your certs will not be able to be renewed automatically."
|
||||
@ -4763,9 +4734,9 @@ _precheck() {
|
||||
return 1
|
||||
fi
|
||||
|
||||
if ! _exists "nc"; then
|
||||
_err "It is recommended to install nc first, try to install 'nc' or 'netcat'."
|
||||
_err "We use nc for standalone server if you use standalone mode."
|
||||
if ! _exists "socat"; then
|
||||
_err "It is recommended to install socat first."
|
||||
_err "We use socat for standalone server if you use standalone mode."
|
||||
_err "If you don't use standalone mode, just ignore this warning."
|
||||
fi
|
||||
|
||||
@ -4865,10 +4836,12 @@ install() {
|
||||
_debug "Skip install cron job"
|
||||
fi
|
||||
|
||||
if [ "$IN_CRON" != "1" ]; then
|
||||
if ! _precheck "$_nocron"; then
|
||||
_err "Pre-check failed, can not install."
|
||||
return 1
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ -z "$_c_home" ] && [ "$LE_CONFIG_HOME" != "$LE_WORKING_DIR" ]; then
|
||||
_info "Using config home: $LE_CONFIG_HOME"
|
||||
@ -4920,7 +4893,9 @@ install() {
|
||||
|
||||
_info "Installed to $LE_WORKING_DIR/$PROJECT_ENTRY"
|
||||
|
||||
if [ "$IN_CRON" != "1" ]; then
|
||||
_installalias "$_c_home"
|
||||
fi
|
||||
|
||||
for subf in $_SUB_FOLDERS; do
|
||||
if [ -d "$subf" ]; then
|
||||
@ -5010,7 +4985,7 @@ _uninstallalias() {
|
||||
}
|
||||
|
||||
cron() {
|
||||
IN_CRON=1
|
||||
export IN_CRON=1
|
||||
_initpath
|
||||
_info "$(__green "===Starting cron===")"
|
||||
if [ "$AUTO_UPGRADE" = "1" ]; then
|
||||
|
@ -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.
|
||||
|
||||
## 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.)
|
||||
|
||||
@ -18,7 +20,7 @@ export DEPLOY_CPANEL_PASSWORD=PASSWORD
|
||||
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).
|
||||
Currently supports Kong-v0.10.x.
|
||||
@ -27,7 +29,7 @@ Currently supports Kong-v0.10.x.
|
||||
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
|
||||
|
||||
The ssh deploy plugin allows you to deploy certificates to a remote host
|
||||
using SSH command to connect to the remote server. The ssh plugin is invoked
|
||||
@ -170,7 +172,7 @@ export DEPLOY_SSH_BACKUP=no
|
||||
&& service unifi restart
|
||||
```
|
||||
|
||||
## 4. Deploy the cert to local vsftpd server.
|
||||
## 4. Deploy the cert to local vsftpd server
|
||||
|
||||
```sh
|
||||
acme.sh --deploy -d ftp.example.com --deploy-hook vsftpd
|
||||
@ -192,7 +194,7 @@ export DEPLOY_VSFTPD_RELOAD="/etc/init.d/vsftpd restart"
|
||||
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
|
||||
acme.sh --deploy -d ftp.example.com --deploy-hook exim4
|
||||
@ -219,3 +221,37 @@ acme.sh --deploy -d ftp.example.com --deploy-hook exim4
|
||||
```sh
|
||||
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
|
||||
|
||||
}
|
@ -420,6 +420,7 @@ Ok, let's issue a cert now:
|
||||
```
|
||||
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
|
||||
|
||||
@ -512,14 +513,11 @@ export DuckDNS_Token="aaaaaaaa-bbbb-cccc-dddd-eeeeeeeeeeee"
|
||||
```
|
||||
|
||||
Please note that since DuckDNS uses StartSSL as their cert provider, thus
|
||||
--insecure must be used when issuing certs:
|
||||
--insecure may need to be used when issuing certs:
|
||||
```
|
||||
acme.sh --insecure --issue --dns dns_duckdns -d mydomain.duckdns.org
|
||||
```
|
||||
|
||||
Also, DuckDNS uses the domain name as username for recording changing, so the
|
||||
account file will always store the lastly used domain name.
|
||||
|
||||
For issues, please report to https://github.com/raidenii/acme.sh/issues.
|
||||
|
||||
## 28. Use Name.com API
|
||||
|
@ -87,6 +87,7 @@ _get_root() {
|
||||
_debug "response" "$response"
|
||||
while true; do
|
||||
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
|
||||
_debug2 "Checking domain: $h"
|
||||
if [ -z "$h" ]; then
|
||||
if _contains "$response" "<IsTruncated>true</IsTruncated>" && _contains "$response" "<NextMarker>"; then
|
||||
_debug "IsTruncated"
|
||||
@ -102,24 +103,24 @@ _get_root() {
|
||||
fi
|
||||
fi
|
||||
#not valid
|
||||
_err "Invalid domain"
|
||||
return 1
|
||||
fi
|
||||
|
||||
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>")"
|
||||
_debug hostedzone "$hostedzone"
|
||||
if [ -z "$hostedzone" ]; then
|
||||
_err "Error, can not get hostedzone."
|
||||
return 1
|
||||
fi
|
||||
if [ "$hostedzone" ]; then
|
||||
_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
|
||||
fi
|
||||
fi
|
||||
p=$i
|
||||
i=$(_math "$i" + 1)
|
||||
done
|
||||
|
@ -96,6 +96,16 @@ _dns_cloudns_init_check() {
|
||||
return 0
|
||||
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
|
||||
_err "CLOUDNS_AUTH_ID is not configured"
|
||||
return 1
|
||||
@ -113,6 +123,10 @@ _dns_cloudns_init_check() {
|
||||
return 1
|
||||
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
|
||||
|
||||
return 0
|
||||
|
@ -3,11 +3,14 @@
|
||||
#Created by RaidenII, to use DuckDNS's API to add/remove text records
|
||||
#06/27/2017
|
||||
|
||||
# Currently only support single domain access
|
||||
# Due to the fact that DuckDNS uses StartSSL as cert provider, --insecure must be used with acme.sh
|
||||
# Pass credentials before "acme.sh --issue --dns dns_duckdns ..."
|
||||
# --
|
||||
# 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"
|
||||
API_Params="domains=$DuckDNS_Domain&token=$DuckDNS_Token"
|
||||
|
||||
######## Public functions #####################
|
||||
|
||||
@ -16,35 +19,36 @@ dns_duckdns_add() {
|
||||
fulldomain=$1
|
||||
txtvalue=$2
|
||||
|
||||
# We'll extract the domain/username from full domain
|
||||
DuckDNS_Domain=$(echo "$fulldomain" | _lower_case | _egrep_o '.[^.]*.duckdns.org' | cut -d . -f 2)
|
||||
|
||||
if [ -z "$DuckDNS_Domain" ]; then
|
||||
_err "Error extracting the domain."
|
||||
return 1
|
||||
fi
|
||||
|
||||
DuckDNS_Token="${DuckDNS_Token:-$(_readaccountconf_mutable DuckDNS_Token)}"
|
||||
if [ -z "$DuckDNS_Token" ]; then
|
||||
DuckDNS_Token=""
|
||||
_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
|
||||
|
||||
# Now save the credentials.
|
||||
_saveaccountconf DuckDNS_Domain "$DuckDNS_Domain"
|
||||
_saveaccountconf DuckDNS_Token "$DuckDNS_Token"
|
||||
_saveaccountconf_mutable DuckDNS_Token "$DuckDNS_Token"
|
||||
|
||||
# Unfortunately, DuckDNS does not seems to support lookup domain through API
|
||||
# So I assume your credentials (which are your domain and token) are correct
|
||||
# If something goes wrong, we will get a KO response from DuckDNS
|
||||
|
||||
if ! _duckdns_get_domain; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
# Now add the TXT record to DuckDNS
|
||||
_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
|
||||
if [ "$response" = "OK" ]; then
|
||||
_info "TXT record has been successfully added to your DuckDNS domain."
|
||||
_info "Note that all subdomains under this domain uses the same TXT record."
|
||||
return 0
|
||||
else
|
||||
_err "Errors happened during adding the TXT record, response=$response"
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
_err "Errors happened during adding the TXT record."
|
||||
return 1
|
||||
@ -57,11 +61,28 @@ dns_duckdns_rm() {
|
||||
fulldomain=$1
|
||||
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
|
||||
_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
|
||||
if [ "$response" = "OK" ]; then
|
||||
_info "TXT record has been successfully removed from your DuckDNS domain."
|
||||
return 0
|
||||
else
|
||||
_err "Errors happened during removing the TXT record, response=$response"
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
_err "Errors happened during removing the TXT record."
|
||||
return 1
|
||||
@ -70,6 +91,22 @@ dns_duckdns_rm() {
|
||||
|
||||
#################### 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
|
||||
_duckdns_rest() {
|
||||
method=$1
|
||||
|
@ -11,7 +11,7 @@
|
||||
#
|
||||
######## 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"
|
||||
dns_gandi_livedns_add() {
|
||||
|
@ -47,7 +47,7 @@ dns_he_add() {
|
||||
response="$(_post "$body" "https://dns.he.net/")"
|
||||
exit_code="$?"
|
||||
if [ "$exit_code" -eq 0 ]; then
|
||||
_info "TXT record added successfuly."
|
||||
_info "TXT record added successfully."
|
||||
else
|
||||
_err "Couldn't add the TXT record."
|
||||
fi
|
||||
@ -96,7 +96,7 @@ dns_he_rm() {
|
||||
>/dev/null
|
||||
exit_code="$?"
|
||||
if [ "$exit_code" -eq 0 ]; then
|
||||
_info "Record removed successfuly."
|
||||
_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"
|
||||
|
Loading…
Reference in New Issue
Block a user