Browse Source
Merge
Merge c6c672b445
into 40b6db6a27
committed by
GitHub
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 270 additions and 0 deletions
@ -0,0 +1,269 @@ |
|||
#!/usr/bin/env sh |
|||
|
|||
################################################################################ |
|||
# ACME.sh 3rd party deploy plugin for multiple (same) services |
|||
################################################################################ |
|||
# Authors: tomo2403 (creator), https://github.com/tomo2403 |
|||
# Updated: 2025-03-01 |
|||
# Issues: https://github.com/acmesh-official/acme.sh/issues and mention @tomo2403 |
|||
################################################################################ |
|||
# Usage (shown values are the examples): |
|||
# 1. Set optional environment variables |
|||
# - export MULTIDEPLOY_FILENAME="multideploy.yaml" - "multideploy.yml" will be automatically used if not set" |
|||
# |
|||
# 2. Run command: |
|||
# acme.sh --deploy --deploy-hook multideploy -d example.com |
|||
################################################################################ |
|||
# Dependencies: |
|||
# - yq |
|||
################################################################################ |
|||
# Return value: |
|||
# 0 means success, otherwise error. |
|||
################################################################################ |
|||
|
|||
MULTIDEPLOY_VERSION="1.0" |
|||
|
|||
# Description: This function handles the deployment of certificates to multiple services. |
|||
# It processes the provided certificate files and deploys them according to the |
|||
# configuration specified in the multideploy file. |
|||
# |
|||
# Parameters: |
|||
# _cdomain - The domain name for which the certificate is issued. |
|||
# _ckey - The private key file for the certificate. |
|||
# _ccert - The certificate file. |
|||
# _cca - The CA (Certificate Authority) file. |
|||
# _cfullchain - The full chain certificate file. |
|||
# _cpfx - The PFX (Personal Information Exchange) file. |
|||
multideploy_deploy() { |
|||
_cdomain="$1" |
|||
_ckey="$2" |
|||
_ccert="$3" |
|||
_cca="$4" |
|||
_cfullchain="$5" |
|||
_cpfx="$6" |
|||
|
|||
_debug _cdomain "$_cdomain" |
|||
_debug _ckey "$_ckey" |
|||
_debug _ccert "$_ccert" |
|||
_debug _cca "$_cca" |
|||
_debug _cfullchain "$_cfullchain" |
|||
_debug _cpfx "$_cpfx" |
|||
|
|||
DOMAIN_DIR=$_cdomain |
|||
if echo "$DOMAIN_PATH" | grep -q "$ECC_SUFFIX"; then |
|||
DOMAIN_DIR="$DOMAIN_DIR"_ecc |
|||
fi |
|||
_debug2 "DOMAIN_DIR" "$DOMAIN_DIR" |
|||
|
|||
MULTIDEPLOY_FILENAME="${MULTIDEPLOY_FILENAME:-$(_getdeployconf MULTIDEPLOY_FILENAME)}" |
|||
if [ -z "$MULTIDEPLOY_FILENAME" ]; then |
|||
MULTIDEPLOY_FILENAME="multideploy.yml" |
|||
_info "MULTIDEPLOY_FILENAME is not set, so I will use 'multideploy.yml'." |
|||
else |
|||
_savedeployconf "MULTIDEPLOY_FILENAME" "$MULTIDEPLOY_FILENAME" |
|||
_debug2 "MULTIDEPLOY_FILENAME" "$MULTIDEPLOY_FILENAME" |
|||
fi |
|||
|
|||
OLDIFS=$IFS |
|||
if ! file=$(_preprocess_deployfile "$MULTIDEPLOY_FILENAME"); then |
|||
_err "Failed to preprocess deploy file." |
|||
return 1 |
|||
fi |
|||
_debug3 "File" "$file" |
|||
|
|||
# Deploy to services |
|||
_deploy_services "$file" |
|||
|
|||
# Save deployhook for renewals |
|||
_debug2 "Setting Le_DeployHook" |
|||
_savedomainconf "Le_DeployHook" "multideploy" |
|||
|
|||
return 0 |
|||
} |
|||
|
|||
# Description: |
|||
# This function preprocesses the deploy file by checking if 'yq' is installed, |
|||
# verifying the existence of the deploy file, and ensuring only one deploy file is present. |
|||
# Arguments: |
|||
# $@ - Posible deploy file names. |
|||
# Usage: |
|||
# _preprocess_deployfile "<deploy_file1>" "<deploy_file2>?" |
|||
_preprocess_deployfile() { |
|||
# Check if yq is installed |
|||
if ! command -v yq >/dev/null 2>&1; then |
|||
_err "yq is not installed! Please install yq and try again." |
|||
return 1 |
|||
fi |
|||
_debug3 "yq is installed." |
|||
|
|||
# Check if deploy file exists |
|||
IFS=$(printf '\n') |
|||
for file in "$@"; do |
|||
_debug3 "Checking file" "$DOMAIN_PATH/$file" |
|||
if [ -f "$DOMAIN_PATH/$file" ]; then |
|||
_debug3 "File found" |
|||
if [ -n "$found_file" ]; then |
|||
_err "Multiple deploy files found. Please keep only one deploy file." |
|||
return 1 |
|||
fi |
|||
found_file="$file" |
|||
else |
|||
_debug3 "File not found" |
|||
fi |
|||
done |
|||
IFS=$OLDIFS |
|||
|
|||
if [ -n "$found_file" ]; then |
|||
_check_deployfile "$DOMAIN_PATH/$found_file" |
|||
else |
|||
_err "Deploy file not found. Go to https://github.com/acmesh-official/acme.sh/wiki/deployhooks#36-deploying-to-multiple-services-with-the-same-hooks to see how to create one." |
|||
return 1 |
|||
fi |
|||
|
|||
echo "$DOMAIN_PATH/$found_file" |
|||
} |
|||
|
|||
# Description: |
|||
# This function checks the deploy file for version compatibility and the existence of the specified configuration and services. |
|||
# Arguments: |
|||
# $1 - The path to the deploy configuration file. |
|||
# $2 - The name of the deploy configuration to use. |
|||
# Usage: |
|||
# _check_deployfile "<deploy_file_path>" |
|||
_check_deployfile() { |
|||
_deploy_file="$1" |
|||
_debug2 "Deploy file" "$_deploy_file" |
|||
|
|||
# Check version |
|||
_deploy_file_version=$(yq '.version' "$_deploy_file") |
|||
if [ "$MULTIDEPLOY_VERSION" != "$_deploy_file_version" ]; then |
|||
_err "As of $PROJECT_NAME $VER, the deploy file needs version $MULTIDEPLOY_VERSION! Your current deploy file is of version $_deploy_file_version." |
|||
return 1 |
|||
fi |
|||
_debug2 "Deploy file version is compatible: $_deploy_file_version" |
|||
|
|||
# Extract all services from config |
|||
_services=$(yq e '.services[].name' "$_deploy_file") |
|||
_debug2 "Services" "$_services" |
|||
|
|||
if [ -z "$_services" ]; then |
|||
_err "Config does not have any services to deploy to." |
|||
return 1 |
|||
fi |
|||
_debug2 "Config has services." |
|||
|
|||
IFS=$(printf '\n') |
|||
# Check if extracted services exist in services list |
|||
for _service in $_services; do |
|||
_debug2 "Checking service" "$_service" |
|||
# Check if service exists |
|||
if ! yq e ".services[] | select(.name == \"$_service\")" "$_deploy_file" >/dev/null; then |
|||
_err "Service '$_service' not found." |
|||
return 1 |
|||
fi |
|||
|
|||
# Check if service has hook |
|||
if ! yq e ".services[] | select(.name == \"$_service\").hook" "$_deploy_file" >/dev/null; then |
|||
_err "Service '$_service' does not have a hook." |
|||
return 1 |
|||
fi |
|||
|
|||
# Check if service has environment |
|||
if ! yq e ".services[] | select(.name == \"$_service\").environment" "$_deploy_file" >/dev/null; then |
|||
_err "Service '$_service' does not have an environment." |
|||
return 1 |
|||
fi |
|||
done |
|||
IFS=$OLDIFS |
|||
} |
|||
|
|||
# Description: This function takes a list of environment variables in YAML format, |
|||
# parses them, and exports each key-value pair as environment variables. |
|||
# Arguments: |
|||
# $1 - A string containing the list of environment variables in YAML format. |
|||
# Usage: |
|||
# _export_envs "$env_list" |
|||
_export_envs() { |
|||
_env_list="$1" |
|||
|
|||
_secure_debug3 "Exporting envs" "$_env_list" |
|||
|
|||
IFS=$(printf '\n') |
|||
echo "$_env_list" | yq e -r 'to_entries | .[] | .key + "=" + .value' | while IFS='=' read -r _key _value; do |
|||
_value=$(eval echo "$_value") |
|||
_savedomainconf "$_key" "$_value" |
|||
_secure_debug3 "Saved $_key" "$_value" |
|||
done |
|||
IFS=$OLDIFS |
|||
} |
|||
|
|||
# Description: |
|||
# This function takes a YAML formatted string of environment variables, parses it, |
|||
# and clears each environment variable. It logs the process of clearing each variable. |
|||
# Arguments: |
|||
# $1 - A YAML formatted string containing environment variable key-value pairs. |
|||
# Usage: |
|||
# _clear_envs "<yaml_string>" |
|||
_clear_envs() { |
|||
_env_list="$1" |
|||
|
|||
_secure_debug3 "Clearing envs" "$_env_list" |
|||
env_pairs=$(echo "$_env_list" | yq e -r 'to_entries | .[] | .key + "=" + .value') |
|||
|
|||
IFS=$(printf '\n') |
|||
echo "$env_pairs" | while IFS='=' read -r _key _value; do |
|||
_debug3 "Deleting key" "$_key" |
|||
_cleardomainconf "SAVED_$_key" |
|||
unset -v "$_key" |
|||
done |
|||
IFS="$OLDIFS" |
|||
} |
|||
|
|||
# Description: |
|||
# This function deploys services listed in the deploy configuration file. |
|||
# Arguments: |
|||
# $1 - The path to the deploy configuration file. |
|||
# $2 - The list of services to deploy. |
|||
# Usage: |
|||
# _deploy_services "<deploy_file_path>" "<services_list>" |
|||
_deploy_services() { |
|||
_deploy_file="$1" |
|||
_debug3 "Deploy file" "$_deploy_file" |
|||
|
|||
_services=$(yq e '.services[].name' "$_deploy_file") |
|||
_debug3 "Services" "$_services" |
|||
|
|||
_service_list=$(printf '%s\n' "$_services") |
|||
|
|||
for _service in $(printf '%s\n' "$_service_list"); do |
|||
_debug2 "Service" "$_service" |
|||
_hook=$(yq e ".services[] | select(.name == \"$_service\").hook" "$_deploy_file") |
|||
_envs=$(yq e ".services[] | select(.name == \"$_service\").environment[]" "$_deploy_file") |
|||
|
|||
_export_envs "$_envs" |
|||
_deploy_service "$_service" "$_hook" |
|||
_clear_envs "$_envs" |
|||
done |
|||
} |
|||
|
|||
# Description: Deploys a service using the specified hook. |
|||
# Arguments: |
|||
# $1 - The name of the service to deploy. |
|||
# $2 - The hook to use for deployment. |
|||
# Usage: |
|||
# _deploy_service <service_name> <hook> |
|||
_deploy_service() { |
|||
_name="$1" |
|||
_hook="$2" |
|||
|
|||
_debug2 "SERVICE" "$_name" |
|||
_debug2 "HOOK" "$_hook" |
|||
|
|||
_info "$(__green "Deploying") to '$_name' using '$_hook'" |
|||
if echo "$DOMAIN_PATH" | grep -q "$ECC_SUFFIX"; then |
|||
_debug2 "User wants to use ECC." |
|||
deploy "$_cdomain" "$_hook" "isEcc" |
|||
else |
|||
deploy "$_cdomain" "$_hook" |
|||
fi |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue