|
|
@@ -3,18 +3,29 @@
|
|
|
# Uses command line uapi. --user option is needed only if run as root.
|
|
|
# Returns 0 when success.
|
|
|
#
|
|
|
+# Configure DEPLOY_CPANEL_AUTO_<...> options to enable or restrict automatic
|
|
|
+# detection of deployment targets through UAPI (if not set, defaults below are used.)
|
|
|
+# - ENABLED : 'true' for multi-site / wildcard capability; otherwise single-site mode.
|
|
|
+# - NOMATCH : 'true' to allow deployment to sites that do not match the certificate.
|
|
|
+# - INCLUDE : Comma-separated list - sites must match this field.
|
|
|
+# - EXCLUDE : Comma-separated list - sites must NOT match this field.
|
|
|
+# INCLUDE/EXCLUDE both support non-lexical, glob-style matches using '*'
|
|
|
+#
|
|
|
# Please note that I am no longer using Github. If you want to report an issue
|
|
|
# or contact me, visit https://forum.webseodesigners.com/web-design-seo-and-hosting-f16/
|
|
|
#
|
|
|
# Written by Santeri Kannisto <[email protected]>
|
|
|
# Public domain, 2017-2018
|
|
|
-
|
|
|
-#export DEPLOY_CPANEL_USER=myusername
|
|
|
+#
|
|
|
+# export DEPLOY_CPANEL_USER=myusername
|
|
|
+# export DEPLOY_CPANEL_AUTO_ENABLED='true'
|
|
|
+# export DEPLOY_CPANEL_AUTO_NOMATCH='false'
|
|
|
+# export DEPLOY_CPANEL_AUTO_INCLUDE='*'
|
|
|
+# export DEPLOY_CPANEL_AUTO_EXCLUDE=''
|
|
|
|
|
|
######## Public functions #####################
|
|
|
|
|
|
#domain keyfile certfile cafile fullchain
|
|
|
-
|
|
|
cpanel_uapi_deploy() {
|
|
|
_cdomain="$1"
|
|
|
_ckey="$2"
|
|
|
@@ -22,6 +33,9 @@ cpanel_uapi_deploy() {
|
|
|
_cca="$4"
|
|
|
_cfullchain="$5"
|
|
|
|
|
|
+ # re-declare vars inherited from acme.sh but not passed to make ShellCheck happy
|
|
|
+ : "${Le_Alt:=""}"
|
|
|
+
|
|
|
_debug _cdomain "$_cdomain"
|
|
|
_debug _ckey "$_ckey"
|
|
|
_debug _ccert "$_ccert"
|
|
|
@@ -32,31 +46,166 @@ cpanel_uapi_deploy() {
|
|
|
_err "The command uapi is not found."
|
|
|
return 1
|
|
|
fi
|
|
|
+
|
|
|
+ # declare useful constants
|
|
|
+ uapi_error_response='status: 0'
|
|
|
+
|
|
|
# read cert and key files and urlencode both
|
|
|
_cert=$(_url_encode <"$_ccert")
|
|
|
_key=$(_url_encode <"$_ckey")
|
|
|
|
|
|
- _debug _cert "$_cert"
|
|
|
- _debug _key "$_key"
|
|
|
+ _debug2 _cert "$_cert"
|
|
|
+ _debug2 _key "$_key"
|
|
|
|
|
|
if [ "$(id -u)" = 0 ]; then
|
|
|
- if [ -z "$DEPLOY_CPANEL_USER" ]; then
|
|
|
+ _getdeployconf DEPLOY_CPANEL_USER
|
|
|
+ # fallback to _readdomainconf for old installs
|
|
|
+ if [ -z "${DEPLOY_CPANEL_USER:=$(_readdomainconf 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")
|
|
|
+ _debug DEPLOY_CPANEL_USER "$DEPLOY_CPANEL_USER"
|
|
|
+ _savedeployconf DEPLOY_CPANEL_USER "$DEPLOY_CPANEL_USER"
|
|
|
+
|
|
|
+ _uapi_user="$DEPLOY_CPANEL_USER"
|
|
|
fi
|
|
|
- error_response="status: 0"
|
|
|
- if test "${_response#*$error_response}" != "$_response"; then
|
|
|
- _err "Error in deploying certificate:"
|
|
|
- _err "$_response"
|
|
|
- return 1
|
|
|
+
|
|
|
+ # Load all AUTO envars and set defaults - see above for usage
|
|
|
+ __cpanel_initautoparam ENABLED 'true'
|
|
|
+ __cpanel_initautoparam NOMATCH 'false'
|
|
|
+ __cpanel_initautoparam INCLUDE '*'
|
|
|
+ __cpanel_initautoparam EXCLUDE ''
|
|
|
+
|
|
|
+ # Auto mode
|
|
|
+ if [ "$DEPLOY_CPANEL_AUTO_ENABLED" = "true" ]; then
|
|
|
+ # call API for site config
|
|
|
+ _response=$(uapi DomainInfo list_domains)
|
|
|
+ # exit if error in response
|
|
|
+ if [ -z "$_response" ] || [ "${_response#*"$uapi_error_response"}" != "$_response" ]; then
|
|
|
+ _err "Error in deploying certificate - cannot retrieve sitelist:"
|
|
|
+ _err "\n$_response"
|
|
|
+ return 1
|
|
|
+ fi
|
|
|
+
|
|
|
+ # parse response to create site list
|
|
|
+ sitelist=$(__cpanel_parse_response "$_response")
|
|
|
+ _debug "UAPI sites found: $sitelist"
|
|
|
+
|
|
|
+ # filter sitelist using configured domains
|
|
|
+ # skip if NOMATCH is "true"
|
|
|
+ if [ "$DEPLOY_CPANEL_AUTO_NOMATCH" = "true" ]; then
|
|
|
+ _debug "DEPLOY_CPANEL_AUTO_NOMATCH is true"
|
|
|
+ _info "UAPI nomatch mode is enabled - Will not validate sites are valid for the certificate"
|
|
|
+ else
|
|
|
+ _debug "DEPLOY_CPANEL_AUTO_NOMATCH is false"
|
|
|
+ d="$(echo "${Le_Alt}," | sed -e "s/^$_cdomain,//" -e "s/,$_cdomain,/,/")"
|
|
|
+ d="$(echo "$_cdomain,$d" | tr ',' '\n' | sed -e 's/\./\\./g' -e 's/\*/\[\^\.\]\*/g')"
|
|
|
+ sitelist="$(echo "$sitelist" | grep -ix "$d")"
|
|
|
+ _debug2 "Matched UAPI sites: $sitelist"
|
|
|
+ fi
|
|
|
+
|
|
|
+ # filter sites that do not match $DEPLOY_CPANEL_AUTO_INCLUDE
|
|
|
+ _info "Applying sitelist filter DEPLOY_CPANEL_AUTO_INCLUDE: $DEPLOY_CPANEL_AUTO_INCLUDE"
|
|
|
+ sitelist="$(echo "$sitelist" | grep -ix "$(echo "$DEPLOY_CPANEL_AUTO_INCLUDE" | tr ',' '\n' | sed -e 's/\./\\./g' -e 's/\*/\.\*/g')")"
|
|
|
+ _debug2 "Remaining sites: $sitelist"
|
|
|
+
|
|
|
+ # filter sites that match $DEPLOY_CPANEL_AUTO_EXCLUDE
|
|
|
+ _info "Applying sitelist filter DEPLOY_CPANEL_AUTO_EXCLUDE: $DEPLOY_CPANEL_AUTO_EXCLUDE"
|
|
|
+ sitelist="$(echo "$sitelist" | grep -vix "$(echo "$DEPLOY_CPANEL_AUTO_EXCLUDE" | tr ',' '\n' | sed -e 's/\./\\./g' -e 's/\*/\.\*/g')")"
|
|
|
+ _debug2 "Remaining sites: $sitelist"
|
|
|
+
|
|
|
+ # counter for success / failure check
|
|
|
+ successes=0
|
|
|
+ if [ -n "$sitelist" ]; then
|
|
|
+ sitetotal="$(echo "$sitelist" | wc -l)"
|
|
|
+ _debug "$sitetotal sites to deploy"
|
|
|
+ else
|
|
|
+ sitetotal=0
|
|
|
+ _debug "No sites to deploy"
|
|
|
+ fi
|
|
|
+
|
|
|
+ # for each site: call uapi to publish cert and log result. Only return failure if all fail
|
|
|
+ for site in $sitelist; do
|
|
|
+ # call uapi to publish cert, check response for errors and log them.
|
|
|
+ if [ -n "$_uapi_user" ]; then
|
|
|
+ _response=$(uapi --user="$_uapi_user" SSL install_ssl domain="$site" cert="$_cert" key="$_key")
|
|
|
+ else
|
|
|
+ _response=$(uapi SSL install_ssl domain="$site" cert="$_cert" key="$_key")
|
|
|
+ fi
|
|
|
+ if [ "${_response#*"$uapi_error_response"}" != "$_response" ]; then
|
|
|
+ _err "Error in deploying certificate to $site:"
|
|
|
+ _err "$_response"
|
|
|
+ else
|
|
|
+ successes=$((successes + 1))
|
|
|
+ _debug "$_response"
|
|
|
+ _info "Succcessfully deployed to $site"
|
|
|
+ fi
|
|
|
+ done
|
|
|
+
|
|
|
+ # Raise error if all updates fail
|
|
|
+ if [ "$sitetotal" -gt 0 ] && [ "$successes" -eq 0 ]; then
|
|
|
+ _err "Could not deploy to any of $sitetotal sites via UAPI"
|
|
|
+ _debug "successes: $successes, sitetotal: $sitetotal"
|
|
|
+ return 1
|
|
|
+ fi
|
|
|
+
|
|
|
+ _info "Successfully deployed certificate to $successes of $sitetotal sites via UAPI"
|
|
|
+ return 0
|
|
|
+ else
|
|
|
+ # "classic" mode - will only try to deploy to the primary domain; will not check UAPI first
|
|
|
+ if [ -n "$_uapi_user" ]; then
|
|
|
+ _response=$(uapi --user="$_uapi_user" SSL install_ssl domain="$_cdomain" cert="$_cert" key="$_key")
|
|
|
+ else
|
|
|
+ _response=$(uapi SSL install_ssl domain="$_cdomain" cert="$_cert" key="$_key")
|
|
|
+ fi
|
|
|
+
|
|
|
+ if [ "${_response#*"$uapi_error_response"}" != "$_response" ]; then
|
|
|
+ _err "Error in deploying certificate:"
|
|
|
+ _err "$_response"
|
|
|
+ return 1
|
|
|
+ fi
|
|
|
+
|
|
|
+ _debug response "$_response"
|
|
|
+ _info "Certificate successfully deployed"
|
|
|
+ return 0
|
|
|
fi
|
|
|
+}
|
|
|
+
|
|
|
+######## Private functions #####################
|
|
|
+
|
|
|
+# Internal utility to process YML from UAPI - only looks at main_domain and sub_domains
|
|
|
+#[response]
|
|
|
+__cpanel_parse_response() {
|
|
|
+ if [ $# -gt 0 ]; then resp="$*"; else resp="$(cat)"; fi
|
|
|
+
|
|
|
+ echo "$resp" |
|
|
|
+ sed -En \
|
|
|
+ -e 's/\r$//' \
|
|
|
+ -e 's/^( *)([_.[:alnum:]]+) *: *(.*)/\1,\2,\3/p' \
|
|
|
+ -e 's/^( *)- (.*)/\1,-,\2/p' |
|
|
|
+ awk -F, '{
|
|
|
+ level = length($1)/2;
|
|
|
+ section[level] = $2;
|
|
|
+ for (i in section) {if (i > level) {delete section[i]}}
|
|
|
+ if (length($3) > 0) {
|
|
|
+ prefix="";
|
|
|
+ for (i=0; i < level; i++)
|
|
|
+ { prefix = (prefix)(section[i])("/") }
|
|
|
+ printf("%s%s=%s\n", prefix, $2, $3);
|
|
|
+ }
|
|
|
+ }' |
|
|
|
+ sed -En -e 's/^result\/data\/(main_domain|sub_domains\/-)=(.*)$/\2/p'
|
|
|
+}
|
|
|
+
|
|
|
+# Load parameter by prefix+name - fallback to default if not set, and save to config
|
|
|
+#pname pdefault
|
|
|
+__cpanel_initautoparam() {
|
|
|
+ pname="$1"
|
|
|
+ pdefault="$2"
|
|
|
+ pkey="DEPLOY_CPANEL_AUTO_$pname"
|
|
|
|
|
|
- _debug response "$_response"
|
|
|
- _info "Certificate successfully deployed"
|
|
|
- return 0
|
|
|
+ _getdeployconf "$pkey"
|
|
|
+ [ -n "$(eval echo "\"\$$pkey\"")" ] || eval "$pkey=\"$pdefault\""
|
|
|
+ _debug2 "$pkey" "$(eval echo "\"\$$pkey\"")"
|
|
|
+ _savedeployconf "$pkey" "$(eval echo "\"\$$pkey\"")"
|
|
|
}
|