|
|
@ -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,25 +46,120 @@ 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") |
|
|
|
_debug DEPLOY_CPANEL_USER "$DEPLOY_CPANEL_USER" |
|
|
|
_savedeployconf DEPLOY_CPANEL_USER "$DEPLOY_CPANEL_USER" |
|
|
|
|
|
|
|
_uapi_user="$DEPLOY_CPANEL_USER" |
|
|
|
fi |
|
|
|
|
|
|
|
# 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 |
|
|
|
error_response="status: 0" |
|
|
|
if test "${_response#*$error_response}" != "$_response"; then |
|
|
|
|
|
|
|
if [ "${_response#*"$uapi_error_response"}" != "$_response" ]; then |
|
|
|
_err "Error in deploying certificate:" |
|
|
|
_err "$_response" |
|
|
|
return 1 |
|
|
@ -59,4 +168,44 @@ cpanel_uapi_deploy() { |
|
|
|
_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" |
|
|
|
|
|
|
|
_getdeployconf "$pkey" |
|
|
|
[ -n "$(eval echo "\"\$$pkey\"")" ] || eval "$pkey=\"$pdefault\"" |
|
|
|
_debug2 "$pkey" "$(eval echo "\"\$$pkey\"")" |
|
|
|
_savedeployconf "$pkey" "$(eval echo "\"\$$pkey\"")" |
|
|
|
} |