mirror of
https://github.com/plantroon/acme.sh.git
synced 2024-12-22 13:11:41 +00:00
commit
0accdb9e34
14
README.md
14
README.md
@ -13,6 +13,7 @@
|
|||||||
- DOES NOT require `root/sudoer` access.
|
- DOES NOT require `root/sudoer` access.
|
||||||
- Docker friendly
|
- Docker friendly
|
||||||
- IPv6 support
|
- IPv6 support
|
||||||
|
- Cron job notifications for renewal or error etc.
|
||||||
|
|
||||||
It's probably the `easiest & smartest` shell script to automatically issue & renew the free certificates from Let's Encrypt.
|
It's probably the `easiest & smartest` shell script to automatically issue & renew the free certificates from Let's Encrypt.
|
||||||
|
|
||||||
@ -432,20 +433,25 @@ acme.sh --upgrade --auto-upgrade 0
|
|||||||
https://github.com/Neilpang/acme.sh/wiki/Issue-a-cert-from-existing-CSR
|
https://github.com/Neilpang/acme.sh/wiki/Issue-a-cert-from-existing-CSR
|
||||||
|
|
||||||
|
|
||||||
# 16. Under the Hood
|
# 16. Send notifications in cronjob
|
||||||
|
|
||||||
|
https://github.com/Neilpang/acme.sh/wiki/notify
|
||||||
|
|
||||||
|
|
||||||
|
# 17. Under the Hood
|
||||||
|
|
||||||
Speak ACME language using shell, directly to "Let's Encrypt".
|
Speak ACME language using shell, directly to "Let's Encrypt".
|
||||||
|
|
||||||
TODO:
|
TODO:
|
||||||
|
|
||||||
|
|
||||||
# 17. Acknowledgments
|
# 18. Acknowledgments
|
||||||
|
|
||||||
1. Acme-tiny: https://github.com/diafygi/acme-tiny
|
1. Acme-tiny: https://github.com/diafygi/acme-tiny
|
||||||
2. ACME protocol: https://github.com/ietf-wg-acme/acme
|
2. ACME protocol: https://github.com/ietf-wg-acme/acme
|
||||||
|
|
||||||
|
|
||||||
# 18. License & Others
|
# 19. License & Others
|
||||||
|
|
||||||
License is GPLv3
|
License is GPLv3
|
||||||
|
|
||||||
@ -454,7 +460,7 @@ Please Star and Fork me.
|
|||||||
[Issues](https://github.com/Neilpang/acme.sh/issues) and [pull requests](https://github.com/Neilpang/acme.sh/pulls) are welcome.
|
[Issues](https://github.com/Neilpang/acme.sh/issues) and [pull requests](https://github.com/Neilpang/acme.sh/pulls) are welcome.
|
||||||
|
|
||||||
|
|
||||||
# 19. Donate
|
# 20. Donate
|
||||||
Your donation makes **acme.sh** better:
|
Your donation makes **acme.sh** better:
|
||||||
|
|
||||||
1. PayPal/Alipay(支付宝)/Wechat(微信): [https://donate.acme.sh/](https://donate.acme.sh/)
|
1. PayPal/Alipay(支付宝)/Wechat(微信): [https://donate.acme.sh/](https://donate.acme.sh/)
|
||||||
|
282
acme.sh
282
acme.sh
@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env sh
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
VER=2.8.1
|
VER=2.8.2
|
||||||
|
|
||||||
PROJECT_NAME="acme.sh"
|
PROJECT_NAME="acme.sh"
|
||||||
|
|
||||||
@ -14,7 +14,11 @@ _WINDOWS_SCHEDULER_NAME="$PROJECT_NAME.cron"
|
|||||||
|
|
||||||
_SCRIPT_="$0"
|
_SCRIPT_="$0"
|
||||||
|
|
||||||
_SUB_FOLDERS="dnsapi deploy"
|
_SUB_FOLDER_NOTIFY="notify"
|
||||||
|
_SUB_FOLDER_DNSAPI="dnsapi"
|
||||||
|
_SUB_FOLDER_DEPLOY="deploy"
|
||||||
|
|
||||||
|
_SUB_FOLDERS="$_SUB_FOLDER_DNSAPI $_SUB_FOLDER_DEPLOY $_SUB_FOLDER_NOTIFY"
|
||||||
|
|
||||||
LETSENCRYPT_CA_V1="https://acme-v01.api.letsencrypt.org/directory"
|
LETSENCRYPT_CA_V1="https://acme-v01.api.letsencrypt.org/directory"
|
||||||
LETSENCRYPT_STAGING_CA_V1="https://acme-staging.api.letsencrypt.org/directory"
|
LETSENCRYPT_STAGING_CA_V1="https://acme-staging.api.letsencrypt.org/directory"
|
||||||
@ -107,6 +111,18 @@ SYSLOG_LEVEL_DEFAULT=$SYSLOG_LEVEL_ERROR
|
|||||||
#none
|
#none
|
||||||
SYSLOG_LEVEL_NONE=0
|
SYSLOG_LEVEL_NONE=0
|
||||||
|
|
||||||
|
NOTIFY_LEVEL_DISABLE=0
|
||||||
|
NOTIFY_LEVEL_ERROR=1
|
||||||
|
NOTIFY_LEVEL_RENEW=2
|
||||||
|
NOTIFY_LEVEL_SKIP=3
|
||||||
|
|
||||||
|
NOTIFY_LEVEL_DEFAULT=$NOTIFY_LEVEL_RENEW
|
||||||
|
|
||||||
|
NOTIFY_MODE_BULK=0
|
||||||
|
NOTIFY_MODE_CERT=1
|
||||||
|
|
||||||
|
NOTIFY_MODE_DEFAULT=$NOTIFY_MODE_BULK
|
||||||
|
|
||||||
_DEBUG_WIKI="https://github.com/Neilpang/acme.sh/wiki/How-to-debug-acme.sh"
|
_DEBUG_WIKI="https://github.com/Neilpang/acme.sh/wiki/How-to-debug-acme.sh"
|
||||||
|
|
||||||
_PREPARE_LINK="https://github.com/Neilpang/acme.sh/wiki/Install-preparations"
|
_PREPARE_LINK="https://github.com/Neilpang/acme.sh/wiki/Install-preparations"
|
||||||
@ -117,6 +133,8 @@ _DNS_ALIAS_WIKI="https://github.com/Neilpang/acme.sh/wiki/DNS-alias-mode"
|
|||||||
|
|
||||||
_DNS_MANUAL_WIKI="https://github.com/Neilpang/acme.sh/wiki/dns-manual-mode"
|
_DNS_MANUAL_WIKI="https://github.com/Neilpang/acme.sh/wiki/dns-manual-mode"
|
||||||
|
|
||||||
|
_NOTIFY_WIKI="https://github.com/Neilpang/acme.sh/wiki/notify"
|
||||||
|
|
||||||
_DNS_MANUAL_ERR="The dns manual mode can not renew automatically, you must issue it again manually. You'd better use the other modes instead."
|
_DNS_MANUAL_ERR="The dns manual mode can not renew automatically, you must issue it again manually. You'd better use the other modes instead."
|
||||||
|
|
||||||
_DNS_MANUAL_WARN="It seems that you are using dns manual mode. please take care: $_DNS_MANUAL_ERR"
|
_DNS_MANUAL_WARN="It seems that you are using dns manual mode. please take care: $_DNS_MANUAL_ERR"
|
||||||
@ -784,6 +802,13 @@ _url_encode() {
|
|||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_json_encode() {
|
||||||
|
_j_str="$(sed 's/"/\\"/g' | sed "s/\r/\\r/g")"
|
||||||
|
_debug3 "_json_encode"
|
||||||
|
_debug3 "_j_str" "$_j_str"
|
||||||
|
echo "$_j_str" | _hex_dump | _lower_case | sed 's/0a/5c 6e/g' | tr -d ' ' | _h2b | tr -d "\r\n"
|
||||||
|
}
|
||||||
|
|
||||||
#options file
|
#options file
|
||||||
_sed_i() {
|
_sed_i() {
|
||||||
options="$1"
|
options="$1"
|
||||||
@ -1094,9 +1119,9 @@ _createcsr() {
|
|||||||
domainlist="$(_idn "$domainlist")"
|
domainlist="$(_idn "$domainlist")"
|
||||||
_debug2 domainlist "$domainlist"
|
_debug2 domainlist "$domainlist"
|
||||||
if _contains "$domainlist" ","; then
|
if _contains "$domainlist" ","; then
|
||||||
alt="DNS:$domain,DNS:$(echo "$domainlist" | sed "s/,,/,/g" | sed "s/,/,DNS:/g")"
|
alt="DNS:$(_idn $domain),DNS:$(echo "$domainlist" | sed "s/,,/,/g" | sed "s/,/,DNS:/g")"
|
||||||
else
|
else
|
||||||
alt="DNS:$domain,DNS:$domainlist"
|
alt="DNS:$(_idn $domain),DNS:$domainlist"
|
||||||
fi
|
fi
|
||||||
#multi
|
#multi
|
||||||
_info "Multi domain" "$alt"
|
_info "Multi domain" "$alt"
|
||||||
@ -3168,6 +3193,14 @@ _on_issue_err() {
|
|||||||
_err "See: $_DEBUG_WIKI"
|
_err "See: $_DEBUG_WIKI"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ "$IN_CRON" ]; then
|
||||||
|
if [ "$NOTIFY_LEVEL" ] && [ $NOTIFY_LEVEL -ge $NOTIFY_LEVEL_ERROR ]; then
|
||||||
|
if [ "$NOTIFY_MODE" = "$NOTIFY_MODE_CERT" ]; then
|
||||||
|
_send_notify "Renew $_main_domain error" "There is an error." "$NOTIFY_HOOK" 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
#run the post hook
|
#run the post hook
|
||||||
if [ "$_chk_post_hook" ]; then
|
if [ "$_chk_post_hook" ]; then
|
||||||
_info "Run post hook:'$_chk_post_hook'"
|
_info "Run post hook:'$_chk_post_hook'"
|
||||||
@ -3210,6 +3243,13 @@ _on_issue_success() {
|
|||||||
_chk_post_hook="$1"
|
_chk_post_hook="$1"
|
||||||
_chk_renew_hook="$2"
|
_chk_renew_hook="$2"
|
||||||
_debug _on_issue_success
|
_debug _on_issue_success
|
||||||
|
if [ "$IN_CRON" ]; then
|
||||||
|
if [ "$NOTIFY_LEVEL" ] && [ $NOTIFY_LEVEL -ge $NOTIFY_LEVEL_RENEW ]; then
|
||||||
|
if [ "$NOTIFY_MODE" = "$NOTIFY_MODE_CERT" ]; then
|
||||||
|
_send_notify "Renew $_main_domain success" "Good, the cert is renewed." "$NOTIFY_HOOK" 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
#run the post hook
|
#run the post hook
|
||||||
if [ "$_chk_post_hook" ]; then
|
if [ "$_chk_post_hook" ]; then
|
||||||
_info "Run post hook:'$_chk_post_hook'"
|
_info "Run post hook:'$_chk_post_hook'"
|
||||||
@ -3467,9 +3507,9 @@ _findHook() {
|
|||||||
d_api="$_SCRIPT_HOME/$_hookcat/$_hookname"
|
d_api="$_SCRIPT_HOME/$_hookcat/$_hookname"
|
||||||
elif [ -f "$_SCRIPT_HOME/$_hookcat/$_hookname.sh" ]; then
|
elif [ -f "$_SCRIPT_HOME/$_hookcat/$_hookname.sh" ]; then
|
||||||
d_api="$_SCRIPT_HOME/$_hookcat/$_hookname.sh"
|
d_api="$_SCRIPT_HOME/$_hookcat/$_hookname.sh"
|
||||||
elif [ -f "$LE_WORKING_DIR/$_hookdomain/$_hookname" ]; then
|
elif [ "$_hookdomain" ] && [ -f "$LE_WORKING_DIR/$_hookdomain/$_hookname" ]; then
|
||||||
d_api="$LE_WORKING_DIR/$_hookdomain/$_hookname"
|
d_api="$LE_WORKING_DIR/$_hookdomain/$_hookname"
|
||||||
elif [ -f "$LE_WORKING_DIR/$_hookdomain/$_hookname.sh" ]; then
|
elif [ "$_hookdomain" ] && [ -f "$LE_WORKING_DIR/$_hookdomain/$_hookname.sh" ]; then
|
||||||
d_api="$LE_WORKING_DIR/$_hookdomain/$_hookname.sh"
|
d_api="$LE_WORKING_DIR/$_hookdomain/$_hookname.sh"
|
||||||
elif [ -f "$LE_WORKING_DIR/$_hookname" ]; then
|
elif [ -f "$LE_WORKING_DIR/$_hookname" ]; then
|
||||||
d_api="$LE_WORKING_DIR/$_hookname"
|
d_api="$LE_WORKING_DIR/$_hookname"
|
||||||
@ -3816,7 +3856,7 @@ issue() {
|
|||||||
if [ -z "$d" ]; then
|
if [ -z "$d" ]; then
|
||||||
break
|
break
|
||||||
fi
|
fi
|
||||||
_identifiers="$_identifiers,{\"type\":\"dns\",\"value\":\"$d\"}"
|
_identifiers="$_identifiers,{\"type\":\"dns\",\"value\":\"$(_idn $d)\"}"
|
||||||
done
|
done
|
||||||
_debug2 _identifiers "$_identifiers"
|
_debug2 _identifiers "$_identifiers"
|
||||||
if ! _send_signed_request "$ACME_NEW_ORDER" "{\"identifiers\": [$_identifiers]}"; then
|
if ! _send_signed_request "$ACME_NEW_ORDER" "{\"identifiers\": [$_identifiers]}"; then
|
||||||
@ -4017,7 +4057,7 @@ $_authorizations_map"
|
|||||||
txt="$(printf "%s" "$keyauthorization" | _digest "sha256" | _url_replace)"
|
txt="$(printf "%s" "$keyauthorization" | _digest "sha256" | _url_replace)"
|
||||||
_debug txt "$txt"
|
_debug txt "$txt"
|
||||||
|
|
||||||
d_api="$(_findHook "$_dns_root_d" dnsapi "$_currentRoot")"
|
d_api="$(_findHook "$_dns_root_d" $_SUB_FOLDER_DNSAPI "$_currentRoot")"
|
||||||
_debug d_api "$d_api"
|
_debug d_api "$d_api"
|
||||||
|
|
||||||
dns_entry="$dns_entry$dvsep$txt${dvsep}$d_api"
|
dns_entry="$dns_entry$dvsep$txt${dvsep}$d_api"
|
||||||
@ -4582,7 +4622,7 @@ renew() {
|
|||||||
_info "$(__green "Renew: '$Le_Domain'")"
|
_info "$(__green "Renew: '$Le_Domain'")"
|
||||||
if [ ! -f "$DOMAIN_CONF" ]; then
|
if [ ! -f "$DOMAIN_CONF" ]; then
|
||||||
_info "'$Le_Domain' is not a issued domain, skip."
|
_info "'$Le_Domain' is not a issued domain, skip."
|
||||||
return 0
|
return $RENEW_SKIP
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$Le_RenewalDays" ]; then
|
if [ "$Le_RenewalDays" ]; then
|
||||||
@ -4622,12 +4662,21 @@ renew() {
|
|||||||
if [ -z "$FORCE" ] && [ "$Le_NextRenewTime" ] && [ "$(_time)" -lt "$Le_NextRenewTime" ]; then
|
if [ -z "$FORCE" ] && [ "$Le_NextRenewTime" ] && [ "$(_time)" -lt "$Le_NextRenewTime" ]; then
|
||||||
_info "Skip, Next renewal time is: $(__green "$Le_NextRenewTimeStr")"
|
_info "Skip, Next renewal time is: $(__green "$Le_NextRenewTimeStr")"
|
||||||
_info "Add '$(__red '--force')' to force to renew."
|
_info "Add '$(__red '--force')' to force to renew."
|
||||||
|
|
||||||
|
if [ "$IN_CRON" = "1" ]; then
|
||||||
|
if [ "$NOTIFY_LEVEL" ] && [ $NOTIFY_LEVEL -ge $NOTIFY_LEVEL_SKIP ]; then
|
||||||
|
if [ "$NOTIFY_MODE" = "$NOTIFY_MODE_CERT" ]; then
|
||||||
|
_send_notify "Renew $Le_Domain skipped" "Good, the cert next renewal time is $Le_NextRenewTimeStr." "$NOTIFY_HOOK" "$RENEW_SKIP"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
return "$RENEW_SKIP"
|
return "$RENEW_SKIP"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$IN_CRON" = "1" ] && [ -z "$Le_CertCreateTime" ]; then
|
if [ "$IN_CRON" = "1" ] && [ -z "$Le_CertCreateTime" ]; then
|
||||||
_info "Skip invalid cert for: $Le_Domain"
|
_info "Skip invalid cert for: $Le_Domain"
|
||||||
return 0
|
return $RENEW_SKIP
|
||||||
fi
|
fi
|
||||||
|
|
||||||
IS_RENEW="1"
|
IS_RENEW="1"
|
||||||
@ -4657,7 +4706,9 @@ renewAll() {
|
|||||||
_stopRenewOnError="$1"
|
_stopRenewOnError="$1"
|
||||||
_debug "_stopRenewOnError" "$_stopRenewOnError"
|
_debug "_stopRenewOnError" "$_stopRenewOnError"
|
||||||
_ret="0"
|
_ret="0"
|
||||||
|
_success_msg=""
|
||||||
|
_error_msg=""
|
||||||
|
_skipped_msg=""
|
||||||
for di in "${CERT_HOME}"/*.*/; do
|
for di in "${CERT_HOME}"/*.*/; do
|
||||||
_debug di "$di"
|
_debug di "$di"
|
||||||
if ! [ -d "$di" ]; then
|
if ! [ -d "$di" ]; then
|
||||||
@ -4678,15 +4729,49 @@ renewAll() {
|
|||||||
if [ "$rc" != "0" ]; then
|
if [ "$rc" != "0" ]; then
|
||||||
if [ "$rc" = "$RENEW_SKIP" ]; then
|
if [ "$rc" = "$RENEW_SKIP" ]; then
|
||||||
_info "Skipped $d"
|
_info "Skipped $d"
|
||||||
elif [ "$_stopRenewOnError" ]; then
|
_skipped_msg="${_skipped_msg} $d
|
||||||
_err "Error renew $d, stop now."
|
"
|
||||||
return "$rc"
|
|
||||||
else
|
else
|
||||||
_ret="$rc"
|
_error_msg="${_error_msg} $d
|
||||||
_err "Error renew $d."
|
"
|
||||||
|
if [ "$_stopRenewOnError" ]; then
|
||||||
|
_err "Error renew $d, stop now."
|
||||||
|
_ret="$rc"
|
||||||
|
break
|
||||||
|
else
|
||||||
|
_ret="$rc"
|
||||||
|
_err "Error renew $d."
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
else
|
||||||
|
_success_msg="${_success_msg} $d
|
||||||
|
"
|
||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
if [ "$IN_CRON" = "1" ]; then
|
||||||
|
if [ -z "$NOTIFY_MODE" ] || [ "$NOTIFY_MODE" = "$NOTIFY_MODE_BULK" ]; then
|
||||||
|
_msg_subject="Renew"
|
||||||
|
if [ "$_error_msg" ]; then
|
||||||
|
_msg_subject="${_msg_subject} Error"
|
||||||
|
fi
|
||||||
|
if [ "$_success_msg" ]; then
|
||||||
|
_msg_subject="${_msg_subject} Success"
|
||||||
|
fi
|
||||||
|
if [ "$_skipped_msg" ]; then
|
||||||
|
_msg_subject="${_msg_subject} Skipped"
|
||||||
|
fi
|
||||||
|
_msg_data="Error certs:
|
||||||
|
${_error_msg}
|
||||||
|
Success certs:
|
||||||
|
${_success_msg}
|
||||||
|
Skipped certs:
|
||||||
|
$_skipped_msg
|
||||||
|
"
|
||||||
|
_send_notify "$_msg_subject" "$_msg_data" "$NOTIFY_HOOK" 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
return "$_ret"
|
return "$_ret"
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4835,7 +4920,7 @@ _deploy() {
|
|||||||
_hooks="$2"
|
_hooks="$2"
|
||||||
|
|
||||||
for _d_api in $(echo "$_hooks" | tr ',' " "); do
|
for _d_api in $(echo "$_hooks" | tr ',' " "); do
|
||||||
_deployApi="$(_findHook "$_d" deploy "$_d_api")"
|
_deployApi="$(_findHook "$_d" $_SUB_FOLDER_DEPLOY "$_d_api")"
|
||||||
if [ -z "$_deployApi" ]; then
|
if [ -z "$_deployApi" ]; then
|
||||||
_err "The deploy hook $_d_api is not found."
|
_err "The deploy hook $_d_api is not found."
|
||||||
return 1
|
return 1
|
||||||
@ -5785,6 +5870,113 @@ version() {
|
|||||||
echo "v$VER"
|
echo "v$VER"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# subject content hooks code
|
||||||
|
_send_notify() {
|
||||||
|
_nsubject="$1"
|
||||||
|
_ncontent="$2"
|
||||||
|
_nhooks="$3"
|
||||||
|
_nerror="$4"
|
||||||
|
|
||||||
|
if [ "$NOTIFY_LEVEL" = "$NOTIFY_LEVEL_DISABLE" ]; then
|
||||||
|
_debug "The NOTIFY_LEVEL is $NOTIFY_LEVEL, disabled, just return."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$_nhooks" ]; then
|
||||||
|
_debug "The NOTIFY_HOOK is empty, just return."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
_send_err=0
|
||||||
|
for _n_hook in $(echo "$_nhooks" | tr ',' " "); do
|
||||||
|
_n_hook_file="$(_findHook "" $_SUB_FOLDER_NOTIFY "$_n_hook")"
|
||||||
|
_info "Found $_n_hook_file"
|
||||||
|
|
||||||
|
if ! (
|
||||||
|
if ! . "$_n_hook_file"; then
|
||||||
|
_err "Load file $_n_hook_file error. Please check your api file and try again."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
d_command="${_n_hook}_send"
|
||||||
|
if ! _exists "$d_command"; then
|
||||||
|
_err "It seems that your api file is not correct, it must have a function named: $d_command"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if ! $d_command "$_nsubject" "$_ncontent" "$_nerror"; then
|
||||||
|
_err "Error send message by $d_command"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
|
); then
|
||||||
|
_err "Set $_n_hook_file error."
|
||||||
|
_send_err=1
|
||||||
|
else
|
||||||
|
_info "$_n_hook $(__green Success)"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
return $_send_err
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
# hook
|
||||||
|
_set_notify_hook() {
|
||||||
|
_nhooks="$1"
|
||||||
|
|
||||||
|
_test_subject="Hello, this is notification from $PROJECT_NAME"
|
||||||
|
_test_content="If you receive this email, your notification works."
|
||||||
|
|
||||||
|
_send_notify "$_test_subject" "$_test_content" "$_nhooks" 0
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#[hook] [level] [mode]
|
||||||
|
setnotify() {
|
||||||
|
_nhook="$1"
|
||||||
|
_nlevel="$2"
|
||||||
|
_nmode="$3"
|
||||||
|
|
||||||
|
_initpath
|
||||||
|
|
||||||
|
if [ -z "$_nhook$_nlevel$_nmode" ]; then
|
||||||
|
_usage "Usage: $PROJECT_ENTRY --set-notify [--notify-hook mailgun] [--notify-level $NOTIFY_LEVEL_DEFAULT] [--notify-mode $NOTIFY_MODE_DEFAULT]"
|
||||||
|
_usage "$_NOTIFY_WIKI"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$_nlevel" ]; then
|
||||||
|
_info "Set notify level to: $_nlevel"
|
||||||
|
export "NOTIFY_LEVEL=$_nlevel"
|
||||||
|
_saveaccountconf "NOTIFY_LEVEL" "$NOTIFY_LEVEL"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$_nmode" ]; then
|
||||||
|
_info "Set notify mode to: $_nmode"
|
||||||
|
export "NOTIFY_MODE=$_nmode"
|
||||||
|
_saveaccountconf "NOTIFY_MODE" "$NOTIFY_MODE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "$_nhook" ]; then
|
||||||
|
_info "Set notify hook to: $_nhook"
|
||||||
|
if [ "$_nhook" = "$NO_VALUE" ]; then
|
||||||
|
_info "Clear notify hook"
|
||||||
|
_clearaccountconf "NOTIFY_HOOK"
|
||||||
|
else
|
||||||
|
if _set_notify_hook "$_nhook"; then
|
||||||
|
export NOTIFY_HOOK="$_nhook"
|
||||||
|
_saveaccountconf "NOTIFY_HOOK" "$NOTIFY_HOOK"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
_err "Can not set notify hook to: $_nhook"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
showhelp() {
|
showhelp() {
|
||||||
_initpath
|
_initpath
|
||||||
version
|
version
|
||||||
@ -5817,6 +6009,8 @@ Commands:
|
|||||||
--create-domain-key Create an domain private key, professional use.
|
--create-domain-key Create an domain private key, professional use.
|
||||||
--createCSR, -ccsr Create CSR , professional use.
|
--createCSR, -ccsr Create CSR , professional use.
|
||||||
--deactivate Deactivate the domain authz, professional use.
|
--deactivate Deactivate the domain authz, professional use.
|
||||||
|
--set-notify Set the cron notification hook, level or mode.
|
||||||
|
|
||||||
|
|
||||||
Parameters:
|
Parameters:
|
||||||
--domain, -d domain.tld Specifies a domain, used to issue, renew or revoke etc.
|
--domain, -d domain.tld Specifies a domain, used to issue, renew or revoke etc.
|
||||||
@ -5885,7 +6079,18 @@ Parameters:
|
|||||||
--use-wget Force to use wget, if you have both curl and wget installed.
|
--use-wget Force to use wget, if you have both curl and wget installed.
|
||||||
--yes-I-know-dns-manual-mode-enough-go-ahead-please Force to use dns manual mode: $_DNS_MANUAL_WIKI
|
--yes-I-know-dns-manual-mode-enough-go-ahead-please Force to use dns manual mode: $_DNS_MANUAL_WIKI
|
||||||
--branch, -b Only valid for '--upgrade' command, specifies the branch name to upgrade to.
|
--branch, -b Only valid for '--upgrade' command, specifies the branch name to upgrade to.
|
||||||
"
|
|
||||||
|
--notify-level 0|1|2|3 Set the notification level: Default value is $NOTIFY_LEVEL_DEFAULT.
|
||||||
|
0: disabled, no notification will be sent.
|
||||||
|
1: send notification only when there is an error. No news is good news.
|
||||||
|
2: send notification when a cert is successfully renewed, or there is an error
|
||||||
|
3: send notification when a cert is skipped, renewdd, or error
|
||||||
|
--notify-mode 0|1 Set notification mode. Default value is $NOTIFY_MODE_DEFAULT.
|
||||||
|
0: Bulk mode. Send all the domain's notifications in one message(mail)
|
||||||
|
1: Cert mode. Send a message for every single cert.
|
||||||
|
--notify-hook [hookname] Set the notify hook
|
||||||
|
|
||||||
|
"
|
||||||
}
|
}
|
||||||
|
|
||||||
# nocron noprofile
|
# nocron noprofile
|
||||||
@ -6019,6 +6224,9 @@ _process() {
|
|||||||
_syslog=""
|
_syslog=""
|
||||||
_use_wget=""
|
_use_wget=""
|
||||||
_server=""
|
_server=""
|
||||||
|
_notify_hook=""
|
||||||
|
_notify_level=""
|
||||||
|
_notify_mode=""
|
||||||
while [ ${#} -gt 0 ]; do
|
while [ ${#} -gt 0 ]; do
|
||||||
case "${1}" in
|
case "${1}" in
|
||||||
|
|
||||||
@ -6105,6 +6313,9 @@ _process() {
|
|||||||
--deactivate-account)
|
--deactivate-account)
|
||||||
_CMD="deactivateaccount"
|
_CMD="deactivateaccount"
|
||||||
;;
|
;;
|
||||||
|
--set-notify)
|
||||||
|
_CMD="setnotify"
|
||||||
|
;;
|
||||||
--domain | -d)
|
--domain | -d)
|
||||||
_dvalue="$2"
|
_dvalue="$2"
|
||||||
|
|
||||||
@ -6453,6 +6664,37 @@ _process() {
|
|||||||
export BRANCH="$2"
|
export BRANCH="$2"
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
|
--notify-hook)
|
||||||
|
_nhook="$2"
|
||||||
|
if _startswith "$_nhook" "-"; then
|
||||||
|
_err "'$_nhook' is not a hook name for '$1'"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
if [ "$_notify_hook" ]; then
|
||||||
|
_notify_hook="$_notify_hook,$_nhook"
|
||||||
|
else
|
||||||
|
_notify_hook="$_nhook"
|
||||||
|
fi
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--notify-level)
|
||||||
|
_nlevel="$2"
|
||||||
|
if _startswith "$_nlevel" "-"; then
|
||||||
|
_err "'$_nlevel' is not a integer for '$1'"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_notify_level="$_nlevel"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
|
--notify-mode)
|
||||||
|
_nmode="$2"
|
||||||
|
if _startswith "$_nmode" "-"; then
|
||||||
|
_err "'$_nmode' is not a integer for '$1'"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_notify_mode="$_nmode"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
_err "Unknown parameter : $1"
|
_err "Unknown parameter : $1"
|
||||||
return 1
|
return 1
|
||||||
@ -6570,7 +6812,9 @@ _process() {
|
|||||||
createCSR)
|
createCSR)
|
||||||
createCSR "$_domain" "$_altdomains" "$_ecc"
|
createCSR "$_domain" "$_altdomains" "$_ecc"
|
||||||
;;
|
;;
|
||||||
|
setnotify)
|
||||||
|
setnotify "$_notify_hook" "$_notify_level" "$_notify_mode"
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
if [ "$_CMD" ]; then
|
if [ "$_CMD" ]; then
|
||||||
_err "Invalid command: $_CMD"
|
_err "Invalid command: $_CMD"
|
||||||
|
@ -27,8 +27,8 @@ gcore_cdn_deploy() {
|
|||||||
_debug _cca "$_cca"
|
_debug _cca "$_cca"
|
||||||
_debug _cfullchain "$_cfullchain"
|
_debug _cfullchain "$_cfullchain"
|
||||||
|
|
||||||
_fullchain=$(tr '\n\r' '@#' <"$_cfullchain" | sed 's/@/\\n/g;s/#/\\r/g')
|
_fullchain=$(tr '\r\n' '*#' <"$_cfullchain" | sed 's/*#/#/g;s/##/#/g;s/#/\\n/g')
|
||||||
_key=$(tr '\n\r' '@#' <"$_ckey" | sed 's/@/\\n/g;s/#/\\r/g')
|
_key=$(tr '\r\n' '*#' <"$_ckey" | sed 's/*#/#/g;s/#/\\n/g')
|
||||||
|
|
||||||
_debug _fullchain "$_fullchain"
|
_debug _fullchain "$_fullchain"
|
||||||
_debug _key "$_key"
|
_debug _key "$_key"
|
||||||
|
@ -1,8 +1,41 @@
|
|||||||
#!/usr/bin/env sh
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
#Here is a script to deploy cert to haproxy server.
|
# Script for acme.sh to deploy certificates to haproxy
|
||||||
|
#
|
||||||
#returns 0 means success, otherwise error.
|
# The following variables can be exported:
|
||||||
|
#
|
||||||
|
# export DEPLOY_HAPROXY_PEM_NAME="${domain}.pem"
|
||||||
|
#
|
||||||
|
# Defines the name of the PEM file.
|
||||||
|
# Defaults to "<domain>.pem"
|
||||||
|
#
|
||||||
|
# export DEPLOY_HAPROXY_PEM_PATH="/etc/haproxy"
|
||||||
|
#
|
||||||
|
# Defines location of PEM file for HAProxy.
|
||||||
|
# Defaults to /etc/haproxy
|
||||||
|
#
|
||||||
|
# export DEPLOY_HAPROXY_RELOAD="systemctl reload haproxy"
|
||||||
|
#
|
||||||
|
# OPTIONAL: Reload command used post deploy
|
||||||
|
# This defaults to be a no-op (ie "true").
|
||||||
|
# It is strongly recommended to set this something that makes sense
|
||||||
|
# for your distro.
|
||||||
|
#
|
||||||
|
# export DEPLOY_HAPROXY_ISSUER="no"
|
||||||
|
#
|
||||||
|
# OPTIONAL: Places CA file as "${DEPLOY_HAPROXY_PEM}.issuer"
|
||||||
|
# Note: Required for OCSP stapling to work
|
||||||
|
#
|
||||||
|
# export DEPLOY_HAPROXY_BUNDLE="no"
|
||||||
|
#
|
||||||
|
# OPTIONAL: Deploy this certificate as part of a multi-cert bundle
|
||||||
|
# This adds a suffix to the certificate based on the certificate type
|
||||||
|
# eg RSA certificates will have .rsa as a suffix to the file name
|
||||||
|
# HAProxy will load all certificates and provide one or the other
|
||||||
|
# depending on client capabilities
|
||||||
|
# Note: This functionality requires HAProxy was compiled against
|
||||||
|
# a version of OpenSSL that supports this.
|
||||||
|
#
|
||||||
|
|
||||||
######## Public functions #####################
|
######## Public functions #####################
|
||||||
|
|
||||||
@ -14,45 +47,226 @@ haproxy_deploy() {
|
|||||||
_cca="$4"
|
_cca="$4"
|
||||||
_cfullchain="$5"
|
_cfullchain="$5"
|
||||||
|
|
||||||
_debug _cdomain "$_cdomain"
|
# Some defaults
|
||||||
_debug _ckey "$_ckey"
|
DEPLOY_HAPROXY_PEM_PATH_DEFAULT="/etc/haproxy"
|
||||||
_debug _ccert "$_ccert"
|
DEPLOY_HAPROXY_PEM_NAME_DEFAULT="${_cdomain}.pem"
|
||||||
_debug _cca "$_cca"
|
DEPLOY_HAPROXY_BUNDLE_DEFAULT="no"
|
||||||
_debug _cfullchain "$_cfullchain"
|
DEPLOY_HAPROXY_ISSUER_DEFAULT="no"
|
||||||
|
DEPLOY_HAPROXY_RELOAD_DEFAULT="true"
|
||||||
|
|
||||||
# handle reload preference
|
if [ -f "${DOMAIN_CONF}" ]; then
|
||||||
DEFAULT_HAPROXY_RELOAD="/usr/sbin/service haproxy restart"
|
# shellcheck disable=SC1090
|
||||||
if [ -z "${DEPLOY_HAPROXY_RELOAD}" ]; then
|
. "${DOMAIN_CONF}"
|
||||||
_reload="${DEFAULT_HAPROXY_RELOAD}"
|
|
||||||
_cleardomainconf DEPLOY_HAPROXY_RELOAD
|
|
||||||
else
|
|
||||||
_reload="${DEPLOY_HAPROXY_RELOAD}"
|
|
||||||
_savedomainconf DEPLOY_HAPROXY_RELOAD "$DEPLOY_HAPROXY_RELOAD"
|
|
||||||
fi
|
fi
|
||||||
_savedomainconf DEPLOY_HAPROXY_PEM_PATH "$DEPLOY_HAPROXY_PEM_PATH"
|
|
||||||
|
|
||||||
# work out the path where the PEM file should go
|
_debug _cdomain "${_cdomain}"
|
||||||
_pem_path="${DEPLOY_HAPROXY_PEM_PATH}"
|
_debug _ckey "${_ckey}"
|
||||||
if [ -z "$_pem_path" ]; then
|
_debug _ccert "${_ccert}"
|
||||||
_err "Path to save PEM file not found. Please define DEPLOY_HAPROXY_PEM_PATH."
|
_debug _cca "${_cca}"
|
||||||
return 1
|
_debug _cfullchain "${_cfullchain}"
|
||||||
|
|
||||||
|
# PEM_PATH is optional. If not provided then assume "${DEPLOY_HAPROXY_PEM_PATH_DEFAULT}"
|
||||||
|
if [ -n "${DEPLOY_HAPROXY_PEM_PATH}" ]; then
|
||||||
|
Le_Deploy_haproxy_pem_path="${DEPLOY_HAPROXY_PEM_PATH}"
|
||||||
|
_savedomainconf Le_Deploy_haproxy_pem_path "${Le_Deploy_haproxy_pem_path}"
|
||||||
|
elif [ -z "${Le_Deploy_haproxy_pem_path}" ]; then
|
||||||
|
Le_Deploy_haproxy_pem_path="${DEPLOY_HAPROXY_PEM_PATH_DEFAULT}"
|
||||||
fi
|
fi
|
||||||
_pem_full_path="$_pem_path/$_cdomain.pem"
|
|
||||||
_info "Full path to PEM $_pem_full_path"
|
|
||||||
|
|
||||||
# combine the key and fullchain into a single pem and install
|
# Ensure PEM_PATH exists
|
||||||
cat "$_cfullchain" "$_ckey" >"$_pem_full_path"
|
if [ -d "${Le_Deploy_haproxy_pem_path}" ]; then
|
||||||
chmod 600 "$_pem_full_path"
|
_debug "PEM_PATH ${Le_Deploy_haproxy_pem_path} exists"
|
||||||
_info "Certificate successfully deployed"
|
|
||||||
|
|
||||||
# restart HAProxy
|
|
||||||
_info "Run reload: $_reload"
|
|
||||||
if eval "$_reload"; then
|
|
||||||
_info "Reload success!"
|
|
||||||
return 0
|
|
||||||
else
|
else
|
||||||
_err "Reload error"
|
_err "PEM_PATH ${Le_Deploy_haproxy_pem_path} does not exist"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
# PEM_NAME is optional. If not provided then assume "${DEPLOY_HAPROXY_PEM_NAME_DEFAULT}"
|
||||||
|
if [ -n "${DEPLOY_HAPROXY_PEM_NAME}" ]; then
|
||||||
|
Le_Deploy_haproxy_pem_name="${DEPLOY_HAPROXY_PEM_NAME}"
|
||||||
|
_savedomainconf Le_Deploy_haproxy_pem_name "${Le_Deploy_haproxy_pem_name}"
|
||||||
|
elif [ -z "${Le_Deploy_haproxy_pem_name}" ]; then
|
||||||
|
Le_Deploy_haproxy_pem_name="${DEPLOY_HAPROXY_PEM_NAME_DEFAULT}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# BUNDLE is optional. If not provided then assume "${DEPLOY_HAPROXY_BUNDLE_DEFAULT}"
|
||||||
|
if [ -n "${DEPLOY_HAPROXY_BUNDLE}" ]; then
|
||||||
|
Le_Deploy_haproxy_bundle="${DEPLOY_HAPROXY_BUNDLE}"
|
||||||
|
_savedomainconf Le_Deploy_haproxy_bundle "${Le_Deploy_haproxy_bundle}"
|
||||||
|
elif [ -z "${Le_Deploy_haproxy_bundle}" ]; then
|
||||||
|
Le_Deploy_haproxy_bundle="${DEPLOY_HAPROXY_BUNDLE_DEFAULT}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# ISSUER is optional. If not provided then assume "${DEPLOY_HAPROXY_ISSUER_DEFAULT}"
|
||||||
|
if [ -n "${DEPLOY_HAPROXY_ISSUER}" ]; then
|
||||||
|
Le_Deploy_haproxy_issuer="${DEPLOY_HAPROXY_ISSUER}"
|
||||||
|
_savedomainconf Le_Deploy_haproxy_issuer "${Le_Deploy_haproxy_issuer}"
|
||||||
|
elif [ -z "${Le_Deploy_haproxy_issuer}" ]; then
|
||||||
|
Le_Deploy_haproxy_issuer="${DEPLOY_HAPROXY_ISSUER_DEFAULT}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# RELOAD is optional. If not provided then assume "${DEPLOY_HAPROXY_RELOAD_DEFAULT}"
|
||||||
|
if [ -n "${DEPLOY_HAPROXY_RELOAD}" ]; then
|
||||||
|
Le_Deploy_haproxy_reload="${DEPLOY_HAPROXY_RELOAD}"
|
||||||
|
_savedomainconf Le_Deploy_haproxy_reload "${Le_Deploy_haproxy_reload}"
|
||||||
|
elif [ -z "${Le_Deploy_haproxy_reload}" ]; then
|
||||||
|
Le_Deploy_haproxy_reload="${DEPLOY_HAPROXY_RELOAD_DEFAULT}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Set the suffix depending if we are creating a bundle or not
|
||||||
|
if [ "${Le_Deploy_haproxy_bundle}" = "yes" ]; then
|
||||||
|
_info "Bundle creation requested"
|
||||||
|
# Initialise $Le_Keylength if its not already set
|
||||||
|
if [ -z "${Le_Keylength}" ]; then
|
||||||
|
Le_Keylength=""
|
||||||
|
fi
|
||||||
|
if _isEccKey "${Le_Keylength}"; then
|
||||||
|
_info "ECC key type detected"
|
||||||
|
_suffix=".ecdsa"
|
||||||
|
else
|
||||||
|
_info "RSA key type detected"
|
||||||
|
_suffix=".rsa"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
_suffix=""
|
||||||
|
fi
|
||||||
|
_debug _suffix "${_suffix}"
|
||||||
|
|
||||||
|
# Set variables for later
|
||||||
|
_pem="${Le_Deploy_haproxy_pem_path}/${Le_Deploy_haproxy_pem_name}${_suffix}"
|
||||||
|
_issuer="${_pem}.issuer"
|
||||||
|
_ocsp="${_pem}.ocsp"
|
||||||
|
_reload="${Le_Deploy_haproxy_reload}"
|
||||||
|
|
||||||
|
_info "Deploying PEM file"
|
||||||
|
# Create a temporary PEM file
|
||||||
|
_temppem="$(_mktemp)"
|
||||||
|
_debug _temppem "${_temppem}"
|
||||||
|
cat "${_ckey}" "${_ccert}" "${_cca}" >"${_temppem}"
|
||||||
|
_ret="$?"
|
||||||
|
|
||||||
|
# Check that we could create the temporary file
|
||||||
|
if [ "${_ret}" != "0" ]; then
|
||||||
|
_err "Error code ${_ret} returned during PEM file creation"
|
||||||
|
[ -f "${_temppem}" ] && rm -f "${_temppem}"
|
||||||
|
return ${_ret}
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Move PEM file into place
|
||||||
|
_info "Moving new certificate into place"
|
||||||
|
_debug _pem "${_pem}"
|
||||||
|
cat "${_temppem}" >"${_pem}"
|
||||||
|
_ret=$?
|
||||||
|
|
||||||
|
# Clean up temp file
|
||||||
|
[ -f "${_temppem}" ] && rm -f "${_temppem}"
|
||||||
|
|
||||||
|
# Deal with any failure of moving PEM file into place
|
||||||
|
if [ "${_ret}" != "0" ]; then
|
||||||
|
_err "Error code ${_ret} returned while moving new certificate into place"
|
||||||
|
return ${_ret}
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Update .issuer file if requested
|
||||||
|
if [ "${Le_Deploy_haproxy_issuer}" = "yes" ]; then
|
||||||
|
_info "Updating .issuer file"
|
||||||
|
_debug _issuer "${_issuer}"
|
||||||
|
cat "${_cca}" >"${_issuer}"
|
||||||
|
_ret="$?"
|
||||||
|
|
||||||
|
if [ "${_ret}" != "0" ]; then
|
||||||
|
_err "Error code ${_ret} returned while copying issuer/CA certificate into place"
|
||||||
|
return ${_ret}
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
[ -f "${_issuer}" ] _err "Issuer file update not requested but .issuer file exists"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Update .ocsp file if certificate was requested with --ocsp/--ocsp-must-staple option
|
||||||
|
if [ -z "${Le_OCSP_Staple}" ]; then
|
||||||
|
Le_OCSP_Staple="0"
|
||||||
|
fi
|
||||||
|
if [ "${Le_OCSP_Staple}" = "1" ]; then
|
||||||
|
_info "Updating OCSP stapling info"
|
||||||
|
_debug _ocsp "${_ocsp}"
|
||||||
|
_info "Extracting OCSP URL"
|
||||||
|
_ocsp_url=$(openssl x509 -noout -ocsp_uri -in "${_pem}")
|
||||||
|
_debug _ocsp_url "${_ocsp_url}"
|
||||||
|
|
||||||
|
# Only process OCSP if URL was present
|
||||||
|
if [ "${_ocsp_url}" != "" ]; then
|
||||||
|
# Extract the hostname from the OCSP URL
|
||||||
|
_info "Extracting OCSP URL"
|
||||||
|
_ocsp_host=$(echo "${_ocsp_url}" | cut -d/ -f3)
|
||||||
|
_debug _ocsp_host "${_ocsp_host}"
|
||||||
|
|
||||||
|
# Only process the certificate if we have a .issuer file
|
||||||
|
if [ -r "${_issuer}" ]; then
|
||||||
|
# Check if issuer cert is also a root CA cert
|
||||||
|
_subjectdn=$(openssl x509 -in "${_issuer}" -subject -noout | cut -d'/' -f2,3,4,5,6,7,8,9,10)
|
||||||
|
_debug _subjectdn "${_subjectdn}"
|
||||||
|
_issuerdn=$(openssl x509 -in "${_issuer}" -issuer -noout | cut -d'/' -f2,3,4,5,6,7,8,9,10)
|
||||||
|
_debug _issuerdn "${_issuerdn}"
|
||||||
|
_info "Requesting OCSP response"
|
||||||
|
# Request the OCSP response from the issuer and store it
|
||||||
|
if [ "${_subjectdn}" = "${_issuerdn}" ]; then
|
||||||
|
# If the issuer is a CA cert then our command line has "-CAfile" added
|
||||||
|
openssl ocsp \
|
||||||
|
-issuer "${_issuer}" \
|
||||||
|
-cert "${_pem}" \
|
||||||
|
-url "${_ocsp_url}" \
|
||||||
|
-header Host "${_ocsp_host}" \
|
||||||
|
-respout "${_ocsp}" \
|
||||||
|
-verify_other "${_issuer}" \
|
||||||
|
-no_nonce \
|
||||||
|
-CAfile "${_issuer}" \
|
||||||
|
| grep -q "${_pem}: good"
|
||||||
|
_ret=$?
|
||||||
|
else
|
||||||
|
# Issuer is not a root CA so no "-CAfile" option
|
||||||
|
openssl ocsp \
|
||||||
|
-issuer "${_issuer}" \
|
||||||
|
-cert "${_pem}" \
|
||||||
|
-url "${_ocsp_url}" \
|
||||||
|
-header Host "${_ocsp_host}" \
|
||||||
|
-respout "${_ocsp}" \
|
||||||
|
-verify_other "${_issuer}" \
|
||||||
|
-no_nonce \
|
||||||
|
| grep -q "${_pem}: good"
|
||||||
|
_ret=$?
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# Non fatal: No issuer file was present so no OCSP stapling file created
|
||||||
|
_err "OCSP stapling in use but no .issuer file was present"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# Non fatal: No OCSP url was found int the certificate
|
||||||
|
_err "OCSP update requested but no OCSP URL was found in certificate"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Non fatal: Check return code of openssl command
|
||||||
|
if [ "${_ret}" != "0" ]; then
|
||||||
|
_err "Updating OCSP stapling failed with return code ${_ret}"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
# An OCSP file was already present but certificate did not have OCSP extension
|
||||||
|
if [ -f "${_ocsp}" ]; then
|
||||||
|
_err "OCSP was not requested but .ocsp file exists."
|
||||||
|
# Could remove the file at this step, although HAProxy just ignores it in this case
|
||||||
|
# rm -f "${_ocsp}" || _err "Problem removing stale .ocsp file"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Reload HAProxy
|
||||||
|
_debug _reload "${_reload}"
|
||||||
|
eval "${_reload}"
|
||||||
|
_ret=$?
|
||||||
|
if [ "${_ret}" != "0" ]; then
|
||||||
|
_err "Error code ${_ret} during reload"
|
||||||
|
return ${_ret}
|
||||||
|
else
|
||||||
|
_info "Reload successful"
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 0
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
# How to use DNS API
|
# How to use DNS API
|
||||||
DNS api usage:
|
DNS api usage:
|
||||||
|
|
||||||
https://github.com/Neilpang/acme.sh/wiki/dnsapi
|
|
||||||
|
https://github.com/Neilpang/acme.sh/wiki/dnsapi
|
||||||
|
|
||||||
|
@ -119,7 +119,7 @@ _ddnss_rest() {
|
|||||||
|
|
||||||
# DDNSS uses GET to update domain info
|
# DDNSS uses GET to update domain info
|
||||||
if [ "$method" = "GET" ]; then
|
if [ "$method" = "GET" ]; then
|
||||||
response="$(_get "$url" | sed 's/<[^>]*>//g;/</N;//ba' | _tail_n 1)"
|
response="$(_get "$url" | sed 's/<[a-zA-Z\/][^>]*>//g' | _tail_n 1)"
|
||||||
else
|
else
|
||||||
_err "Unsupported method"
|
_err "Unsupported method"
|
||||||
return 1
|
return 1
|
||||||
|
64
dnsapi/dns_nsd.sh
Normal file
64
dnsapi/dns_nsd.sh
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
#Nsd_ZoneFile="/etc/nsd/zones/example.com.zone"
|
||||||
|
#Nsd_Command="sudo nsd-control reload"
|
||||||
|
|
||||||
|
# args: fulldomain txtvalue
|
||||||
|
dns_nsd_add() {
|
||||||
|
fulldomain=$1
|
||||||
|
txtvalue=$2
|
||||||
|
ttlvalue=300
|
||||||
|
|
||||||
|
Nsd_ZoneFile="${Nsd_ZoneFile:-$(_readdomainconf Nsd_ZoneFile)}"
|
||||||
|
Nsd_Command="${Nsd_Command:-$(_readdomainconf Nsd_Command)}"
|
||||||
|
|
||||||
|
# Arg checks
|
||||||
|
if [ -z "$Nsd_ZoneFile" ] || [ -z "$Nsd_Command" ]; then
|
||||||
|
Nsd_ZoneFile=""
|
||||||
|
Nsd_Command=""
|
||||||
|
_err "Specify ENV vars Nsd_ZoneFile and Nsd_Command"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -f "$Nsd_ZoneFile" ]; then
|
||||||
|
Nsd_ZoneFile=""
|
||||||
|
Nsd_Command=""
|
||||||
|
_err "No such file: $Nsd_ZoneFile"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_savedomainconf Nsd_ZoneFile "$Nsd_ZoneFile"
|
||||||
|
_savedomainconf Nsd_Command "$Nsd_Command"
|
||||||
|
|
||||||
|
echo "$fulldomain. $ttlvalue IN TXT \"$txtvalue\"" >>"$Nsd_ZoneFile"
|
||||||
|
_info "Added TXT record for $fulldomain"
|
||||||
|
_debug "Running $Nsd_Command"
|
||||||
|
if eval "$Nsd_Command"; then
|
||||||
|
_info "Successfully updated the zone"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
_err "Problem updating the zone"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
# args: fulldomain txtvalue
|
||||||
|
dns_nsd_rm() {
|
||||||
|
fulldomain=$1
|
||||||
|
txtvalue=$2
|
||||||
|
ttlvalue=300
|
||||||
|
|
||||||
|
Nsd_ZoneFile="${Nsd_ZoneFile:-$(_readdomainconf Nsd_ZoneFile)}"
|
||||||
|
Nsd_Command="${Nsd_Command:-$(_readdomainconf Nsd_Command)}"
|
||||||
|
|
||||||
|
sed -i "/$fulldomain. $ttlvalue IN TXT \"$txtvalue\"/d" "$Nsd_ZoneFile"
|
||||||
|
_info "Removed TXT record for $fulldomain"
|
||||||
|
_debug "Running $Nsd_Command"
|
||||||
|
if eval "$Nsd_Command"; then
|
||||||
|
_info "Successfully reloaded NSD "
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
_err "Problem reloading NSD"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
}
|
139
dnsapi/dns_one.sh
Normal file
139
dnsapi/dns_one.sh
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
# -*- mode: sh; tab-width: 2; indent-tabs-mode: s; coding: utf-8 -*-
|
||||||
|
|
||||||
|
# one.com ui wrapper for acme.sh
|
||||||
|
# Author: github: @diseq
|
||||||
|
# Created: 2019-02-17
|
||||||
|
#
|
||||||
|
# export ONECOM_User="username"
|
||||||
|
# export ONECOM_Password="password"
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# acme.sh --issue --dns dns_one -d example.com
|
||||||
|
#
|
||||||
|
# only single domain supported atm
|
||||||
|
|
||||||
|
dns_one_add() {
|
||||||
|
mysubdomain=$(printf -- "%s" "$1" | rev | cut -d"." -f3- | rev)
|
||||||
|
mydomain=$(printf -- "%s" "$1" | rev | cut -d"." -f1-2 | rev)
|
||||||
|
txtvalue=$2
|
||||||
|
|
||||||
|
# get credentials
|
||||||
|
ONECOM_User="${ONECOM_User:-$(_readaccountconf_mutable ONECOM_User)}"
|
||||||
|
ONECOM_Password="${ONECOM_Password:-$(_readaccountconf_mutable ONECOM_Password)}"
|
||||||
|
if [ -z "$ONECOM_User" ] || [ -z "$ONECOM_Password" ]; then
|
||||||
|
ONECOM_User=""
|
||||||
|
ONECOM_Password=""
|
||||||
|
_err "You didn't specify a one.com username and password yet."
|
||||||
|
_err "Please create the key and try again."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
#save the api key and email to the account conf file.
|
||||||
|
_saveaccountconf_mutable ONECOM_User "$ONECOM_User"
|
||||||
|
_saveaccountconf_mutable ONECOM_Password "$ONECOM_Password"
|
||||||
|
|
||||||
|
# Login with user and password
|
||||||
|
postdata="loginDomain=true"
|
||||||
|
postdata="$postdata&displayUsername=$ONECOM_User"
|
||||||
|
postdata="$postdata&username=$ONECOM_User"
|
||||||
|
postdata="$postdata&targetDomain=$mydomain"
|
||||||
|
postdata="$postdata&password1=$ONECOM_Password"
|
||||||
|
postdata="$postdata&loginTarget="
|
||||||
|
#_debug postdata "$postdata"
|
||||||
|
|
||||||
|
response="$(_post "$postdata" "https://www.one.com/admin/login.do" "" "POST" "application/x-www-form-urlencoded")"
|
||||||
|
#_debug response "$response"
|
||||||
|
|
||||||
|
JSESSIONID="$(grep "JSESSIONID" "$HTTP_HEADER" | grep "^[Ss]et-[Cc]ookie:" | _tail_n 1 | _egrep_o 'JSESSIONID=[^;]*;' | tr -d ';')"
|
||||||
|
_debug jsessionid "$JSESSIONID"
|
||||||
|
|
||||||
|
export _H1="Cookie: ${JSESSIONID}"
|
||||||
|
|
||||||
|
# get entries
|
||||||
|
response="$(_get "https://www.one.com/admin/api/domains/$mydomain/dns/custom_records")"
|
||||||
|
_debug response "$response"
|
||||||
|
|
||||||
|
CSRF_G_TOKEN="$(grep "CSRF_G_TOKEN=" "$HTTP_HEADER" | grep "^Set-Cookie:" | _tail_n 1 | _egrep_o 'CSRF_G_TOKEN=[^;]*;' | tr -d ';')"
|
||||||
|
export _H2="Cookie: ${CSRF_G_TOKEN}"
|
||||||
|
|
||||||
|
# Update the IP address for domain entry
|
||||||
|
postdata="{\"type\":\"dns_custom_records\",\"attributes\":{\"priority\":0,\"ttl\":600,\"type\":\"TXT\",\"prefix\":\"$mysubdomain\",\"content\":\"$txtvalue\"}}"
|
||||||
|
_debug postdata "$postdata"
|
||||||
|
response="$(_post "$postdata" "https://www.one.com/admin/api/domains/$mydomain/dns/custom_records" "" "POST" "application/json")"
|
||||||
|
response="$(echo "$response" | _normalizeJson)"
|
||||||
|
_debug response "$response"
|
||||||
|
|
||||||
|
id=$(echo "$response" | sed -n "s/{\"result\":{\"data\":{\"type\":\"dns_custom_records\",\"id\":\"\([^\"]*\)\",\"attributes\":{\"prefix\":\"$mysubdomain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"priority\":0,\"ttl\":600}}},\"metadata\":null}/\1/p")
|
||||||
|
|
||||||
|
if [ -z "$id" ]; then
|
||||||
|
_err "Add txt record error."
|
||||||
|
return 1
|
||||||
|
else
|
||||||
|
_info "Added, OK ($id)"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
dns_one_rm() {
|
||||||
|
mysubdomain=$(printf -- "%s" "$1" | rev | cut -d"." -f3- | rev)
|
||||||
|
mydomain=$(printf -- "%s" "$1" | rev | cut -d"." -f1-2 | rev)
|
||||||
|
txtvalue=$2
|
||||||
|
|
||||||
|
# get credentials
|
||||||
|
ONECOM_User="${ONECOM_User:-$(_readaccountconf_mutable ONECOM_User)}"
|
||||||
|
ONECOM_Password="${ONECOM_Password:-$(_readaccountconf_mutable ONECOM_Password)}"
|
||||||
|
if [ -z "$ONECOM_User" ] || [ -z "$ONECOM_Password" ]; then
|
||||||
|
ONECOM_User=""
|
||||||
|
ONECOM_Password=""
|
||||||
|
_err "You didn't specify a one.com username and password yet."
|
||||||
|
_err "Please create the key and try again."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Login with user and password
|
||||||
|
postdata="loginDomain=true"
|
||||||
|
postdata="$postdata&displayUsername=$ONECOM_User"
|
||||||
|
postdata="$postdata&username=$ONECOM_User"
|
||||||
|
postdata="$postdata&targetDomain=$mydomain"
|
||||||
|
postdata="$postdata&password1=$ONECOM_Password"
|
||||||
|
postdata="$postdata&loginTarget="
|
||||||
|
|
||||||
|
response="$(_post "$postdata" "https://www.one.com/admin/login.do" "" "POST" "application/x-www-form-urlencoded")"
|
||||||
|
#_debug response "$response"
|
||||||
|
|
||||||
|
JSESSIONID="$(grep "JSESSIONID" "$HTTP_HEADER" | grep "^[Ss]et-[Cc]ookie:" | _tail_n 1 | _egrep_o 'JSESSIONID=[^;]*;' | tr -d ';')"
|
||||||
|
_debug jsessionid "$JSESSIONID"
|
||||||
|
|
||||||
|
export _H1="Cookie: ${JSESSIONID}"
|
||||||
|
|
||||||
|
# get entries
|
||||||
|
response="$(_get "https://www.one.com/admin/api/domains/$mydomain/dns/custom_records")"
|
||||||
|
response="$(echo "$response" | _normalizeJson)"
|
||||||
|
_debug response "$response"
|
||||||
|
|
||||||
|
CSRF_G_TOKEN="$(grep "CSRF_G_TOKEN=" "$HTTP_HEADER" | grep "^Set-Cookie:" | _tail_n 1 | _egrep_o 'CSRF_G_TOKEN=[^;]*;' | tr -d ';')"
|
||||||
|
export _H2="Cookie: ${CSRF_G_TOKEN}"
|
||||||
|
|
||||||
|
id=$(printf -- "%s" "$response" | sed -n "s/.*{\"type\":\"dns_custom_records\",\"id\":\"\([^\"]*\)\",\"attributes\":{\"prefix\":\"$mysubdomain\",\"type\":\"TXT\",\"content\":\"$txtvalue\",\"priority\":0,\"ttl\":600}.*/\1/p")
|
||||||
|
|
||||||
|
if [ -z "$id" ]; then
|
||||||
|
_err "Txt record not found."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# delete entry
|
||||||
|
response="$(_post "$postdata" "https://www.one.com/admin/api/domains/$mydomain/dns/custom_records/$id" "" "DELETE" "application/json")"
|
||||||
|
response="$(echo "$response" | _normalizeJson)"
|
||||||
|
_debug response "$response"
|
||||||
|
|
||||||
|
if [ "$response" = '{"result":null,"metadata":null}' ]; then
|
||||||
|
_info "Removed, OK"
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
_err "Removing txt record error."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
}
|
261
dnsapi/dns_schlundtech.sh
Normal file
261
dnsapi/dns_schlundtech.sh
Normal file
@ -0,0 +1,261 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
# -*- mode: sh; tab-width: 2; indent-tabs-mode: s; coding: utf-8 -*-
|
||||||
|
|
||||||
|
# Schlundtech DNS API
|
||||||
|
# Author: mod242
|
||||||
|
# Created: 2019-40-29
|
||||||
|
# Completly based on the autoDNS xml api wrapper by auerswald@gmail.com
|
||||||
|
#
|
||||||
|
# export SCHLUNDTECH_USER="username"
|
||||||
|
# export SCHLUNDTECH_PASSWORD="password"
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# acme.sh --issue --dns dns_schlundtech -d example.com
|
||||||
|
|
||||||
|
SCHLUNDTECH_API="https://gateway.schlundtech.de"
|
||||||
|
|
||||||
|
# Arguments:
|
||||||
|
# txtdomain
|
||||||
|
# txt
|
||||||
|
dns_schlundtech_add() {
|
||||||
|
fulldomain="$1"
|
||||||
|
txtvalue="$2"
|
||||||
|
|
||||||
|
SCHLUNDTECH_USER="${SCHLUNDTECH_USER:-$(_readaccountconf_mutable SCHLUNDTECH_USER)}"
|
||||||
|
SCHLUNDTECH_PASSWORD="${SCHLUNDTECH_PASSWORD:-$(_readaccountconf_mutable SCHLUNDTECH_PASSWORD)}"
|
||||||
|
|
||||||
|
if [ -z "$SCHLUNDTECH_USER" ] || [ -z "$SCHLUNDTECH_PASSWORD" ]; then
|
||||||
|
_err "You didn't specify schlundtech user and password."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_saveaccountconf_mutable SCHLUNDTECH_USER "$SCHLUNDTECH_USER"
|
||||||
|
_saveaccountconf_mutable SCHLUNDTECH_PASSWORD "$SCHLUNDTECH_PASSWORD"
|
||||||
|
|
||||||
|
_debug "First detect the root zone"
|
||||||
|
|
||||||
|
if ! _get_autodns_zone "$fulldomain"; then
|
||||||
|
_err "invalid domain"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_debug _sub_domain "$_sub_domain"
|
||||||
|
_debug _zone "$_zone"
|
||||||
|
_debug _system_ns "$_system_ns"
|
||||||
|
|
||||||
|
_info "Adding TXT record"
|
||||||
|
|
||||||
|
autodns_response="$(_autodns_zone_update "$_zone" "$_sub_domain" "$txtvalue" "$_system_ns")"
|
||||||
|
|
||||||
|
if [ "$?" -eq "0" ]; then
|
||||||
|
_info "Added, OK"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
# Arguments:
|
||||||
|
# txtdomain
|
||||||
|
# txt
|
||||||
|
dns_schlundtech_rm() {
|
||||||
|
fulldomain="$1"
|
||||||
|
txtvalue="$2"
|
||||||
|
|
||||||
|
SCHLUNDTECH_USER="${SCHLUNDTECH_USER:-$(_readaccountconf_mutable SCHLUNDTECH_USER)}"
|
||||||
|
SCHLUNDTECH_PASSWORD="${SCHLUNDTECH_PASSWORD:-$(_readaccountconf_mutable SCHLUNDTECH_PASSWORD)}"
|
||||||
|
|
||||||
|
if [ -z "$SCHLUNDTECH_USER" ] || [ -z "$SCHLUNDTECH_PASSWORD" ]; then
|
||||||
|
_err "You didn't specify schlundtech user and password."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_debug "First detect the root zone"
|
||||||
|
|
||||||
|
if ! _get_autodns_zone "$fulldomain"; then
|
||||||
|
_err "zone not found"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_debug _sub_domain "$_sub_domain"
|
||||||
|
_debug _zone "$_zone"
|
||||||
|
_debug _system_ns "$_system_ns"
|
||||||
|
|
||||||
|
_info "Delete TXT record"
|
||||||
|
|
||||||
|
autodns_response="$(_autodns_zone_cleanup "$_zone" "$_sub_domain" "$txtvalue" "$_system_ns")"
|
||||||
|
|
||||||
|
if [ "$?" -eq "0" ]; then
|
||||||
|
_info "Deleted, OK"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
#################### Private functions below ##################################
|
||||||
|
|
||||||
|
# Arguments:
|
||||||
|
# fulldomain
|
||||||
|
# Returns:
|
||||||
|
# _sub_domain=_acme-challenge.www
|
||||||
|
# _zone=domain.com
|
||||||
|
# _system_ns
|
||||||
|
_get_autodns_zone() {
|
||||||
|
domain="$1"
|
||||||
|
|
||||||
|
i=2
|
||||||
|
p=1
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
h=$(printf "%s" "$domain" | cut -d . -f $i-100)
|
||||||
|
_debug h "$h"
|
||||||
|
|
||||||
|
if [ -z "$h" ]; then
|
||||||
|
# not valid
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
autodns_response="$(_autodns_zone_inquire "$h")"
|
||||||
|
|
||||||
|
if [ "$?" -ne "0" ]; then
|
||||||
|
_err "invalid domain"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if _contains "$autodns_response" "<summary>1</summary>" >/dev/null; then
|
||||||
|
_zone="$(echo "$autodns_response" | _egrep_o '<name>[^<]*</name>' | cut -d '>' -f 2 | cut -d '<' -f 1)"
|
||||||
|
_system_ns="$(echo "$autodns_response" | _egrep_o '<system_ns>[^<]*</system_ns>' | cut -d '>' -f 2 | cut -d '<' -f 1)"
|
||||||
|
_sub_domain=$(printf "%s" "$domain" | cut -d . -f 1-$p)
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
p=$i
|
||||||
|
i=$(_math "$i" + 1)
|
||||||
|
done
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
|
||||||
|
_build_request_auth_xml() {
|
||||||
|
printf "<auth>
|
||||||
|
<user>%s</user>
|
||||||
|
<password>%s</password>
|
||||||
|
<context>10</context>
|
||||||
|
</auth>" "$SCHLUNDTECH_USER" "$SCHLUNDTECH_PASSWORD"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Arguments:
|
||||||
|
# zone
|
||||||
|
_build_zone_inquire_xml() {
|
||||||
|
printf "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
|
||||||
|
<request>
|
||||||
|
%s
|
||||||
|
<task>
|
||||||
|
<code>0205</code>
|
||||||
|
<view>
|
||||||
|
<children>1</children>
|
||||||
|
<limit>1</limit>
|
||||||
|
</view>
|
||||||
|
<where>
|
||||||
|
<key>name</key>
|
||||||
|
<operator>eq</operator>
|
||||||
|
<value>%s</value>
|
||||||
|
</where>
|
||||||
|
</task>
|
||||||
|
</request>" "$(_build_request_auth_xml)" "$1"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Arguments:
|
||||||
|
# zone
|
||||||
|
# subdomain
|
||||||
|
# txtvalue
|
||||||
|
# system_ns
|
||||||
|
_build_zone_update_xml() {
|
||||||
|
printf "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
|
||||||
|
<request>
|
||||||
|
%s
|
||||||
|
<task>
|
||||||
|
<code>0202001</code>
|
||||||
|
<default>
|
||||||
|
<rr_add>
|
||||||
|
<name>%s</name>
|
||||||
|
<ttl>600</ttl>
|
||||||
|
<type>TXT</type>
|
||||||
|
<value>%s</value>
|
||||||
|
</rr_add>
|
||||||
|
</default>
|
||||||
|
<zone>
|
||||||
|
<name>%s</name>
|
||||||
|
<system_ns>%s</system_ns>
|
||||||
|
</zone>
|
||||||
|
</task>
|
||||||
|
</request>" "$(_build_request_auth_xml)" "$2" "$3" "$1" "$4"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Arguments:
|
||||||
|
# zone
|
||||||
|
_autodns_zone_inquire() {
|
||||||
|
request_data="$(_build_zone_inquire_xml "$1")"
|
||||||
|
autodns_response="$(_autodns_api_call "$request_data")"
|
||||||
|
ret="$?"
|
||||||
|
|
||||||
|
printf "%s" "$autodns_response"
|
||||||
|
return "$ret"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Arguments:
|
||||||
|
# zone
|
||||||
|
# subdomain
|
||||||
|
# txtvalue
|
||||||
|
# system_ns
|
||||||
|
_autodns_zone_update() {
|
||||||
|
request_data="$(_build_zone_update_xml "$1" "$2" "$3" "$4")"
|
||||||
|
autodns_response="$(_autodns_api_call "$request_data")"
|
||||||
|
ret="$?"
|
||||||
|
|
||||||
|
printf "%s" "$autodns_response"
|
||||||
|
return "$ret"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Arguments:
|
||||||
|
# zone
|
||||||
|
# subdomain
|
||||||
|
# txtvalue
|
||||||
|
# system_ns
|
||||||
|
_autodns_zone_cleanup() {
|
||||||
|
request_data="$(_build_zone_update_xml "$1" "$2" "$3" "$4")"
|
||||||
|
# replace 'rr_add>' with 'rr_rem>' in request_data
|
||||||
|
request_data="$(printf -- "%s" "$request_data" | sed 's/rr_add>/rr_rem>/g')"
|
||||||
|
autodns_response="$(_autodns_api_call "$request_data")"
|
||||||
|
ret="$?"
|
||||||
|
|
||||||
|
printf "%s" "$autodns_response"
|
||||||
|
return "$ret"
|
||||||
|
}
|
||||||
|
|
||||||
|
# Arguments:
|
||||||
|
# request_data
|
||||||
|
_autodns_api_call() {
|
||||||
|
request_data="$1"
|
||||||
|
|
||||||
|
_debug request_data "$request_data"
|
||||||
|
|
||||||
|
autodns_response="$(_post "$request_data" "$SCHLUNDTECH_API")"
|
||||||
|
ret="$?"
|
||||||
|
|
||||||
|
_debug autodns_response "$autodns_response"
|
||||||
|
|
||||||
|
if [ "$ret" -ne "0" ]; then
|
||||||
|
_err "error"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if _contains "$autodns_response" "<type>success</type>" >/dev/null; then
|
||||||
|
_info "success"
|
||||||
|
printf "%s" "$autodns_response"
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
return 1
|
||||||
|
}
|
15
notify/mail.sh
Normal file
15
notify/mail.sh
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
# support local mail app
|
||||||
|
|
||||||
|
mail_send() {
|
||||||
|
_subject="$1"
|
||||||
|
_content="$2"
|
||||||
|
_statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped
|
||||||
|
_debug "_subject" "$_subject"
|
||||||
|
_debug "_content" "$_content"
|
||||||
|
_debug "_statusCode" "$_statusCode"
|
||||||
|
|
||||||
|
_err "Not implemented yet."
|
||||||
|
return 1
|
||||||
|
}
|
123
notify/mailgun.sh
Normal file
123
notify/mailgun.sh
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
#Support mailgun.com api
|
||||||
|
|
||||||
|
#MAILGUN_API_KEY="xxxx"
|
||||||
|
#MAILGUN_TO="yyyy@gmail.com"
|
||||||
|
|
||||||
|
#MAILGUN_REGION="us|eu" #optional, use "us" as default
|
||||||
|
#MAILGUN_API_DOMAIN="xxxxxx.com" #optional, use the default sandbox domain
|
||||||
|
#MAILGUN_FROM="xxx@xxxxx.com" #optional, use the default sendbox account
|
||||||
|
|
||||||
|
_MAILGUN_BASE="https://api.mailgun.net/v3"
|
||||||
|
|
||||||
|
# subject content statusCode
|
||||||
|
mailgun_send() {
|
||||||
|
_subject="$1"
|
||||||
|
_content="$2"
|
||||||
|
_statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped
|
||||||
|
_debug "_statusCode" "$_statusCode"
|
||||||
|
|
||||||
|
MAILGUN_API_KEY="${MAILGUN_API_KEY:-$(_readaccountconf_mutable MAILGUN_API_KEY)}"
|
||||||
|
if [ -z "$MAILGUN_API_KEY" ]; then
|
||||||
|
MAILGUN_API_KEY=""
|
||||||
|
_err "You didn't specify a mailgun api key MAILGUN_API_KEY yet ."
|
||||||
|
_err "You can get yours from here https://mailgun.com"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_saveaccountconf_mutable MAILGUN_API_KEY "$MAILGUN_API_KEY"
|
||||||
|
|
||||||
|
MAILGUN_REGION="${MAILGUN_REGION:-$(_readaccountconf_mutable MAILGUN_REGION)}"
|
||||||
|
if [ -z "$MAILGUN_REGION" ]; then
|
||||||
|
MAILGUN_REGION=""
|
||||||
|
_debug "The MAILGUN_REGION is not set, so use the default us region."
|
||||||
|
_MAILGUN_BASE="https://api.mailgun.net/v3"
|
||||||
|
else
|
||||||
|
_saveaccountconf_mutable MAILGUN_REGION "$MAILGUN_REGION"
|
||||||
|
_MAILGUN_BASE="https://api.eu.mailgun.net/v3"
|
||||||
|
fi
|
||||||
|
|
||||||
|
MAILGUN_TO="${MAILGUN_TO:-$(_readaccountconf_mutable MAILGUN_TO)}"
|
||||||
|
if [ -z "$MAILGUN_TO" ]; then
|
||||||
|
MAILGUN_TO=""
|
||||||
|
_err "You didn't specify an email to MAILGUN_TO receive messages."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_saveaccountconf_mutable MAILGUN_TO "$MAILGUN_TO"
|
||||||
|
|
||||||
|
MAILGUN_API_DOMAIN="${MAILGUN_API_DOMAIN:-$(_readaccountconf_mutable MAILGUN_API_DOMAIN)}"
|
||||||
|
if [ -z "$MAILGUN_API_DOMAIN" ]; then
|
||||||
|
_info "The MAILGUN_API_DOMAIN is not set, try to get the default sending sandbox domain for you."
|
||||||
|
if ! _mailgun_rest GET "/domains"; then
|
||||||
|
_err "Can not get sandbox domain."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_sendboxDomain="$(echo "$response" | _egrep_o '"name": *"sandbox.*.mailgun.org"' | cut -d : -f 2 | tr -d '" ')"
|
||||||
|
_debug _sendboxDomain "$_sendboxDomain"
|
||||||
|
MAILGUN_API_DOMAIN="$_sendboxDomain"
|
||||||
|
if [ -z "$MAILGUN_API_DOMAIN" ]; then
|
||||||
|
_err "Can not get sandbox domain for MAILGUN_API_DOMAIN"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
_info "$(__green "When using sandbox domain, you must verify your email first.")"
|
||||||
|
#todo: add recepient
|
||||||
|
fi
|
||||||
|
if [ -z "$MAILGUN_API_DOMAIN" ]; then
|
||||||
|
_err "Can not get MAILGUN_API_DOMAIN"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_saveaccountconf_mutable MAILGUN_API_DOMAIN "$MAILGUN_API_DOMAIN"
|
||||||
|
|
||||||
|
MAILGUN_FROM="${MAILGUN_FROM:-$(_readaccountconf_mutable MAILGUN_FROM)}"
|
||||||
|
if [ -z "$MAILGUN_FROM" ]; then
|
||||||
|
MAILGUN_FROM="$PROJECT_NAME@$MAILGUN_API_DOMAIN"
|
||||||
|
_info "The MAILGUN_FROM is not set, so use the default value: $MAILGUN_FROM"
|
||||||
|
else
|
||||||
|
_debug MAILGUN_FROM "$MAILGUN_FROM"
|
||||||
|
_saveaccountconf_mutable MAILGUN_FROM "$MAILGUN_FROM"
|
||||||
|
fi
|
||||||
|
|
||||||
|
#send from url
|
||||||
|
_msg="/$MAILGUN_API_DOMAIN/messages?from=$(printf "%s" "$MAILGUN_FROM" | _url_encode)&to=$(printf "%s" "$MAILGUN_TO" | _url_encode)&subject=$(printf "%s" "$_subject" | _url_encode)&text=$(printf "%s" "$_content" | _url_encode)"
|
||||||
|
_debug "_msg" "$_msg"
|
||||||
|
_mailgun_rest POST "$_msg"
|
||||||
|
if _contains "$response" "Queued. Thank you."; then
|
||||||
|
_debug "mailgun send success."
|
||||||
|
return 0
|
||||||
|
else
|
||||||
|
_err "mailgun send error"
|
||||||
|
_err "$response"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
# method uri data
|
||||||
|
_mailgun_rest() {
|
||||||
|
_method="$1"
|
||||||
|
_mguri="$2"
|
||||||
|
_mgdata="$3"
|
||||||
|
_debug _mguri "$_mguri"
|
||||||
|
_mgurl="$_MAILGUN_BASE$_mguri"
|
||||||
|
_debug _mgurl "$_mgurl"
|
||||||
|
|
||||||
|
_auth="$(printf "%s" "api:$MAILGUN_API_KEY" | _base64)"
|
||||||
|
export _H1="Authorization: Basic $_auth"
|
||||||
|
export _H2="Content-Type: application/json"
|
||||||
|
|
||||||
|
if [ "$_method" = "GET" ]; then
|
||||||
|
response="$(_get "$_mgurl")"
|
||||||
|
else
|
||||||
|
_debug _mgdata "$_mgdata"
|
||||||
|
response="$(_post "$_mgdata" "$_mgurl" "" "$_method")"
|
||||||
|
fi
|
||||||
|
if [ "$?" != "0" ]; then
|
||||||
|
_err "Error: $_mguri"
|
||||||
|
_err "$response"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_debug2 response "$response"
|
||||||
|
return 0
|
||||||
|
|
||||||
|
}
|
15
notify/pop.sh
Normal file
15
notify/pop.sh
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
# support pop
|
||||||
|
|
||||||
|
pop_send() {
|
||||||
|
_subject="$1"
|
||||||
|
_content="$2"
|
||||||
|
_statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped
|
||||||
|
_debug "_subject" "$_subject"
|
||||||
|
_debug "_content" "$_content"
|
||||||
|
_debug "_statusCode" "$_statusCode"
|
||||||
|
|
||||||
|
_err "Not implemented yet."
|
||||||
|
return 1
|
||||||
|
}
|
56
notify/sendgrid.sh
Normal file
56
notify/sendgrid.sh
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
#Support SENDGRID.com api
|
||||||
|
|
||||||
|
#SENDGRID_API_KEY=""
|
||||||
|
#SENDGRID_TO="xxxx@xxx.com"
|
||||||
|
#SENDGRID_FROM="xxxx@cccc.com"
|
||||||
|
|
||||||
|
sendgrid_send() {
|
||||||
|
_subject="$1"
|
||||||
|
_content="$2"
|
||||||
|
_statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped
|
||||||
|
_debug "_statusCode" "$_statusCode"
|
||||||
|
|
||||||
|
SENDGRID_API_KEY="${SENDGRID_API_KEY:-$(_readaccountconf_mutable SENDGRID_API_KEY)}"
|
||||||
|
if [ -z "$SENDGRID_API_KEY" ]; then
|
||||||
|
SENDGRID_API_KEY=""
|
||||||
|
_err "You didn't specify a sendgrid api key SENDGRID_API_KEY yet ."
|
||||||
|
_err "You can get yours from here https://sendgrid.com"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_saveaccountconf_mutable SENDGRID_API_KEY "$SENDGRID_API_KEY"
|
||||||
|
|
||||||
|
SENDGRID_TO="${SENDGRID_TO:-$(_readaccountconf_mutable SENDGRID_TO)}"
|
||||||
|
if [ -z "$SENDGRID_TO" ]; then
|
||||||
|
SENDGRID_TO=""
|
||||||
|
_err "You didn't specify an email to SENDGRID_TO receive messages."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_saveaccountconf_mutable SENDGRID_TO "$SENDGRID_TO"
|
||||||
|
|
||||||
|
SENDGRID_FROM="${SENDGRID_FROM:-$(_readaccountconf_mutable SENDGRID_FROM)}"
|
||||||
|
if [ -z "$SENDGRID_FROM" ]; then
|
||||||
|
SENDGRID_FROM=""
|
||||||
|
_err "You didn't specify an email to SENDGRID_FROM receive messages."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
_saveaccountconf_mutable SENDGRID_FROM "$SENDGRID_FROM"
|
||||||
|
|
||||||
|
export _H1="Authorization: Bearer $SENDGRID_API_KEY"
|
||||||
|
export _H2="Content-Type: application/json"
|
||||||
|
|
||||||
|
_content="$(echo "$_content" | _json_encode)"
|
||||||
|
_data="{\"personalizations\": [{\"to\": [{\"email\": \"$SENDGRID_TO\"}]}],\"from\": {\"email\": \"$SENDGRID_FROM\"},\"subject\": \"$_subject\",\"content\": [{\"type\": \"text/plain\", \"value\": \"$_content\"}]}"
|
||||||
|
response="" #just make shellcheck happy
|
||||||
|
if _post "$_data" "https://api.sendgrid.com/v3/mail/send"; then
|
||||||
|
if [ -z "$response" ]; then
|
||||||
|
_info "sendgrid send sccess."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
_err "sendgrid send error."
|
||||||
|
_err "$response"
|
||||||
|
return 1
|
||||||
|
|
||||||
|
}
|
15
notify/smtp.sh
Normal file
15
notify/smtp.sh
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
|
# support smtp
|
||||||
|
|
||||||
|
smtp_send() {
|
||||||
|
_subject="$1"
|
||||||
|
_content="$2"
|
||||||
|
_statusCode="$3" #0: success, 1: error 2($RENEW_SKIP): skipped
|
||||||
|
_debug "_subject" "$_subject"
|
||||||
|
_debug "_content" "$_content"
|
||||||
|
_debug "_statusCode" "$_statusCode"
|
||||||
|
|
||||||
|
_err "Not implemented yet."
|
||||||
|
return 1
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user