]> git.proxmox.com Git - mirror_acme.sh.git/commitdiff
Merge pull request #4256 from dannytix/cpanel_auto
authorneil <github@neilpang.com>
Sun, 18 Sep 2022 12:52:11 +0000 (20:52 +0800)
committerGitHub <noreply@github.com>
Sun, 18 Sep 2022 12:52:11 +0000 (20:52 +0800)
Cpanel auto

deploy/cpanel_uapi.sh

index 44844f79e4e800637f486f88e8cd9502b42e588e..eea96248374aeb955213cb483d88b303b86c9474 100644 (file)
@@ -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 <santeri.kannisto@webseodesigners.com>
 # 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\"")"
 }