Skip to content

Commit 3ae9711

Browse files
authored
Merge pull request #6715 from acmesh-official/dev
sync
2 parents 37cf431 + fc7168e commit 3ae9711

File tree

12 files changed

+1499
-288
lines changed

12 files changed

+1499
-288
lines changed

Dockerfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ RUN apk --no-cache add -f \
1313
tar \
1414
libidn \
1515
jq \
16+
yq-go \
1617
cronie
1718

1819
ENV LE_WORKING_DIR=/acmebin

README.md

Lines changed: 218 additions & 170 deletions
Large diffs are not rendered by default.

acme.sh

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ ID_TYPE_IP="ip"
6565

6666
LOCAL_ANY_ADDRESS="0.0.0.0"
6767

68-
DEFAULT_RENEW=60
68+
DEFAULT_RENEW=30
6969

7070
NO_VALUE="no"
7171

@@ -5840,7 +5840,7 @@ list() {
58405840
if [ -z "$_domain" ]; then
58415841
printf "%s\n" "Main_Domain${_sep}KeyLength${_sep}SAN_Domains${_sep}Profile${_sep}CA${_sep}Created${_sep}Renew"
58425842
fi
5843-
for di in "${CERT_HOME}"/*.*/; do
5843+
for di in "${CERT_HOME}"/{*.*,*:*}/; do
58445844
d=$(basename "$di")
58455845
_debug d "$d"
58465846
(

deploy/ali_cdn.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,6 @@ _set_cdn_domain_ssl_certificate_query() {
8383
query=$query'&SignatureMethod=HMAC-SHA1'
8484
query=$query"&SignatureNonce=$(_ali_nonce)"
8585
query=$query'&SignatureVersion=1.0'
86-
query=$query'&Timestamp='$(_timestamp)
86+
query=$query'&Timestamp='$(_ali_timestamp)
8787
query=$query'&Version=2018-05-10'
8888
}

deploy/ali_dcdn.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,6 @@ _set_dcdn_domain_ssl_certificate_query() {
8383
query=$query'&SignatureMethod=HMAC-SHA1'
8484
query=$query"&SignatureNonce=$(_ali_nonce)"
8585
query=$query'&SignatureVersion=1.0'
86-
query=$query'&Timestamp='$(_timestamp)
86+
query=$query'&Timestamp='$(_ali_timestamp)
8787
query=$query'&Version=2018-01-15'
8888
}

deploy/multideploy.sh

Lines changed: 276 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,276 @@
1+
#!/usr/bin/env sh
2+
3+
################################################################################
4+
# ACME.sh 3rd party deploy plugin for multiple (same) services
5+
################################################################################
6+
# Authors: tomo2403 (creator), https://github.com/tomo2403
7+
# Updated: 2025-03-01
8+
# Issues: https://github.com/acmesh-official/acme.sh/issues and mention @tomo2403
9+
################################################################################
10+
# Usage (shown values are the examples):
11+
# 1. Set optional environment variables
12+
# - export MULTIDEPLOY_FILENAME="multideploy.yaml" - "multideploy.yml" will be automatically used if not set"
13+
#
14+
# 2. Run command:
15+
# acme.sh --deploy --deploy-hook multideploy -d example.com
16+
################################################################################
17+
# Dependencies:
18+
# - yq
19+
################################################################################
20+
# Return value:
21+
# 0 means success, otherwise error.
22+
################################################################################
23+
24+
MULTIDEPLOY_VERSION="1.0"
25+
26+
# Description: This function handles the deployment of certificates to multiple services.
27+
# It processes the provided certificate files and deploys them according to the
28+
# configuration specified in the multideploy file.
29+
#
30+
# Parameters:
31+
# _cdomain - The domain name for which the certificate is issued.
32+
# _ckey - The private key file for the certificate.
33+
# _ccert - The certificate file.
34+
# _cca - The CA (Certificate Authority) file.
35+
# _cfullchain - The full chain certificate file.
36+
# _cpfx - The PFX (Personal Information Exchange) file.
37+
multideploy_deploy() {
38+
_cdomain="$1"
39+
_ckey="$2"
40+
_ccert="$3"
41+
_cca="$4"
42+
_cfullchain="$5"
43+
_cpfx="$6"
44+
45+
_debug _cdomain "$_cdomain"
46+
_debug _ckey "$_ckey"
47+
_debug _ccert "$_ccert"
48+
_debug _cca "$_cca"
49+
_debug _cfullchain "$_cfullchain"
50+
_debug _cpfx "$_cpfx"
51+
52+
MULTIDEPLOY_FILENAME="${MULTIDEPLOY_FILENAME:-$(_getdeployconf MULTIDEPLOY_FILENAME)}"
53+
if [ -z "$MULTIDEPLOY_FILENAME" ]; then
54+
MULTIDEPLOY_FILENAME="multideploy.yml"
55+
_info "MULTIDEPLOY_FILENAME is not set, so I will use 'multideploy.yml'."
56+
else
57+
_savedeployconf "MULTIDEPLOY_FILENAME" "$MULTIDEPLOY_FILENAME"
58+
_debug2 "MULTIDEPLOY_FILENAME" "$MULTIDEPLOY_FILENAME"
59+
fi
60+
61+
if ! file=$(_preprocess_deployfile "$MULTIDEPLOY_FILENAME"); then
62+
_err "Failed to preprocess deploy file."
63+
return 1
64+
fi
65+
_debug3 "File" "$file"
66+
67+
# Deploy to services
68+
_deploy_services "$file"
69+
_exitCode="$?"
70+
71+
return "$_exitCode"
72+
}
73+
74+
# Description:
75+
# This function preprocesses the deploy file by checking if 'yq' is installed,
76+
# verifying the existence of the deploy file, and ensuring only one deploy file is present.
77+
# Arguments:
78+
# $@ - Posible deploy file names.
79+
# Usage:
80+
# _preprocess_deployfile "<deploy_file1>" "<deploy_file2>?"
81+
_preprocess_deployfile() {
82+
# Check if yq is installed
83+
if ! command -v yq >/dev/null 2>&1; then
84+
_err "yq is not installed! Please install yq and try again."
85+
return 1
86+
fi
87+
_debug3 "yq is installed."
88+
89+
# Check if deploy file exists
90+
for file in "$@"; do
91+
_debug3 "Checking file" "$DOMAIN_PATH/$file"
92+
if [ -f "$DOMAIN_PATH/$file" ]; then
93+
_debug3 "File found"
94+
if [ -n "$found_file" ]; then
95+
_err "Multiple deploy files found. Please keep only one deploy file."
96+
return 1
97+
fi
98+
found_file="$file"
99+
else
100+
_debug3 "File not found"
101+
fi
102+
done
103+
104+
if [ -z "$found_file" ]; then
105+
_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."
106+
return 1
107+
fi
108+
if ! _check_deployfile "$DOMAIN_PATH/$found_file"; then
109+
_err "Deploy file is not valid: $DOMAIN_PATH/$found_file"
110+
return 1
111+
fi
112+
113+
echo "$DOMAIN_PATH/$found_file"
114+
}
115+
116+
# Description:
117+
# This function checks the deploy file for version compatibility and the existence of the specified configuration and services.
118+
# Arguments:
119+
# $1 - The path to the deploy configuration file.
120+
# $2 - The name of the deploy configuration to use.
121+
# Usage:
122+
# _check_deployfile "<deploy_file_path>"
123+
_check_deployfile() {
124+
_deploy_file="$1"
125+
_debug2 "check: Deploy file" "$_deploy_file"
126+
127+
# Check version
128+
_deploy_file_version=$(yq -r '.version' "$_deploy_file")
129+
if [ "$MULTIDEPLOY_VERSION" != "$_deploy_file_version" ]; then
130+
_err "As of $PROJECT_NAME $VER, the deploy file needs version $MULTIDEPLOY_VERSION! Your current deploy file is of version $_deploy_file_version."
131+
return 1
132+
fi
133+
_debug2 "check: Deploy file version is compatible: $_deploy_file_version"
134+
135+
# Extract all services from config
136+
_services=$(yq -r '.services[].name' "$_deploy_file")
137+
138+
if [ -z "$_services" ]; then
139+
_err "Config does not have any services to deploy to."
140+
return 1
141+
fi
142+
_debug2 "check: Config has services."
143+
echo "$_services" | while read -r _service; do
144+
_debug3 " - $_service"
145+
done
146+
147+
# Check if extracted services exist in services list
148+
echo "$_services" | while read -r _service; do
149+
_debug2 "check: Checking service: $_service"
150+
# Check if service exists
151+
_service_config=$(yq -r ".services[] | select(.name == \"$_service\")" "$_deploy_file")
152+
if [ -z "$_service_config" ] || [ "$_service_config" = "null" ]; then
153+
_err "Service '$_service' not found."
154+
return 1
155+
fi
156+
157+
_service_hook=$(echo "$_service_config" | yq -r ".hook" -)
158+
if [ -z "$_service_hook" ] || [ "$_service_hook" = "null" ]; then
159+
_err "Service '$_service' does not have a hook."
160+
return 1
161+
fi
162+
163+
_service_environment=$(echo "$_service_config" | yq -r ".environment" -)
164+
if [ -z "$_service_environment" ] || [ "$_service_environment" = "null" ]; then
165+
_err "Service '$_service' does not have an environment."
166+
return 1
167+
fi
168+
done
169+
}
170+
171+
# Description: This function takes a list of environment variables in YAML format,
172+
# parses them, and exports each key-value pair as environment variables.
173+
# Arguments:
174+
# $1 - A string containing the list of environment variables in YAML format.
175+
# Usage:
176+
# _export_envs "$env_list"
177+
_export_envs() {
178+
_env_list="$1"
179+
180+
_secure_debug3 "Exporting envs" "$_env_list"
181+
182+
echo "$_env_list" | yq -r 'to_entries | .[] | .key + "=" + .value' | while IFS='=' read -r _key _value; do
183+
# Using eval to expand nested variables in the configuration file
184+
_value=$(eval 'echo "'"$_value"'"')
185+
_savedeployconf "$_key" "$_value"
186+
_secure_debug3 "Saved $_key" "$_value"
187+
done
188+
}
189+
190+
# Description:
191+
# This function takes a YAML formatted string of environment variables, parses it,
192+
# and clears each environment variable. It logs the process of clearing each variable.
193+
#
194+
# Note: Environment variables for a hook may be optional and differ between
195+
# services using the same hook.
196+
# If one service sets optional environment variables and another does not, the
197+
# variables may persist and affect subsequent deployments.
198+
# Clearing these variables after each service ensures that only the
199+
# environment variables explicitly specified for each service in the deploy
200+
# file are used.
201+
# Arguments:
202+
# $1 - A YAML formatted string containing environment variable key-value pairs.
203+
# Usage:
204+
# _clear_envs "<yaml_string>"
205+
_clear_envs() {
206+
_env_list="$1"
207+
208+
_secure_debug3 "Clearing envs" "$_env_list"
209+
env_pairs=$(echo "$_env_list" | yq -r 'to_entries | .[] | .key + "=" + .value')
210+
211+
echo "$env_pairs" | while IFS='=' read -r _key _value; do
212+
_debug3 "Deleting key" "$_key"
213+
_cleardomainconf "SAVED_$_key"
214+
unset -v "$_key"
215+
done
216+
}
217+
218+
# Description:
219+
# This function deploys services listed in the deploy configuration file.
220+
# Arguments:
221+
# $1 - The path to the deploy configuration file.
222+
# $2 - The list of services to deploy.
223+
# Usage:
224+
# _deploy_services "<deploy_file_path>" "<services_list>"
225+
_deploy_services() {
226+
_deploy_file="$1"
227+
_debug3 "Deploy file" "$_deploy_file"
228+
229+
_tempfile=$(mktemp)
230+
trap 'rm -f $_tempfile' EXIT
231+
232+
yq -r '.services[].name' "$_deploy_file" >"$_tempfile"
233+
_debug3 "Services" "$(cat "$_tempfile")"
234+
235+
_failedServices=""
236+
_failedCount=0
237+
while read -r _service <&3; do
238+
_debug2 "Service" "$_service"
239+
_hook=$(yq -r ".services[] | select(.name == \"$_service\").hook" "$_deploy_file")
240+
_envs=$(yq -r ".services[] | select(.name == \"$_service\").environment" "$_deploy_file")
241+
242+
_export_envs "$_envs"
243+
if ! _deploy_service "$_service" "$_hook"; then
244+
_failedServices="$_service, $_failedServices"
245+
_failedCount=$((_failedCount + 1))
246+
fi
247+
_clear_envs "$_envs"
248+
done 3<"$_tempfile"
249+
250+
_debug3 "Failed services" "$_failedServices"
251+
_debug2 "Failed count" "$_failedCount"
252+
if [ -n "$_failedServices" ]; then
253+
_info "$(__red "Deployment failed") for services: $_failedServices"
254+
else
255+
_debug "All services deployed successfully."
256+
fi
257+
258+
return "$_failedCount"
259+
}
260+
261+
# Description: Deploys a service using the specified hook.
262+
# Arguments:
263+
# $1 - The name of the service to deploy.
264+
# $2 - The hook to use for deployment.
265+
# Usage:
266+
# _deploy_service <service_name> <hook>
267+
_deploy_service() {
268+
_name="$1"
269+
_hook="$2"
270+
271+
_debug2 "SERVICE" "$_name"
272+
_debug2 "HOOK" "$_hook"
273+
274+
_info "$(__green "Deploying") to '$_name' using '$_hook'"
275+
_deploy "$_cdomain" "$_hook"
276+
}

deploy/strongswan.sh

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ strongswan_deploy() {
3333
return 1
3434
fi
3535
_info _confdir "${_confdir}"
36-
__deploy_cert "$@" "stroke" "${_confdir}"
36+
__deploy_cert "stroke" "${_confdir}" "$@"
3737
${_ipsec} reload
3838
fi
3939
# For modern vici mode
@@ -50,7 +50,7 @@ strongswan_deploy() {
5050
_err "no swanctl config dir is found"
5151
return 1
5252
fi
53-
__deploy_cert "$@" "vici" "${_confdir}"
53+
__deploy_cert "vici" "${_confdir}" "$@"
5454
${_swanctl} --load-creds
5555
fi
5656
if [ -z "${_swanctl}" ] && [ -z "${_ipsec}" ]; then
@@ -63,13 +63,13 @@ strongswan_deploy() {
6363
#################### Private functions below ##################################
6464

6565
__deploy_cert() {
66-
_cdomain="${1}"
67-
_ckey="${2}"
68-
_ccert="${3}"
69-
_cca="${4}"
70-
_cfullchain="${5}"
71-
_swan_mode="${6}"
72-
_confdir="${7}"
66+
_swan_mode="${1}"
67+
_confdir="${2}"
68+
_cdomain="${3}"
69+
_ckey="${4}"
70+
_ccert="${5}"
71+
_cca="${6}"
72+
_cfullchain="${7}"
7373
_debug _cdomain "${_cdomain}"
7474
_debug _ckey "${_ckey}"
7575
_debug _ccert "${_ccert}"

0 commit comments

Comments
 (0)