Subversion Repositories ALCASAR

Rev

Rev 3182 | Details | Compare with Previous | Last modification | View Log

Rev Author Line No. Line
2304 tom.houday 1
#!/bin/bash
2
#
3
# $Id: alcasar-letsencrypt.sh 3300 2025-09-23 16:11:12Z rexy $
4
#
5
# alcasar-letsencrypt.sh
3169 rexy 6
# by Tom HOUDAYER & Rexy
2304 tom.houday 7
#
8
# This script is distributed under the Gnu General Public License (GPL)
9
#
10
# Manage Let's Encrypt for ALCASAR integration
11
 
12
CONF_FILE="/usr/local/etc/alcasar-letsencrypt"
13
ACCOUNT_EMAIL=""
14
DOMAIN=""
15
DNS_API=""
16
DEBUG=false
17
STAGING_SERVER=""
18
FORCE=""
19
OPT_PARAMS=""
20
ACMESH_HOME="/usr/local/etc/letsencrypt"
21
ACMESH_BIN="/opt/acme.sh/acme.sh"
3182 rexy 22
LE_SERVER="letsencrypt"
2304 tom.houday 23
 
24
usage="Usage: alcasar-letsencrypt.sh
25
       --issue -d alcasar.domain.tld --email alcasar@domain.tld [--dns-api dns_registrar] [--force] [--staging]
26
       --renew [-d alcasar.domain.tld] [--force] [--staging]"
27
 
28
################################################################################
29
#                                    ISSUE                                     #
30
################################################################################
31
issue() {
32
	if [ ! -f $ACMESH_BIN ]; then
33
		echo "The client does not seem to be installed."
34
		return 1
35
	fi
36
	TMP_OUTPUT=$(mktemp --suffix=_ALCASAR-LE)
37
	if [ ! -z $ACCOUNT_EMAIL ]; then
38
		emailField=" --accountemail $ACCOUNT_EMAIL"
39
		sed -i "s/^email=.*/email=$ACCOUNT_EMAIL/" $CONF_FILE
40
	else
41
		emailField=""
42
	fi
3168 rexy 43
	rm -rf $ACMESH_HOME/certs/*
2304 tom.houday 44
	$DEBUG && debugOpt=" --debug" || debugOpt=""
2596 tom.houday 45
	[ ! -z "$DNS_API" ] && dnsApiOpt="$DNS_API" || dnsApiOpt="--yes-I-know-dns-manual-mode-enough-go-ahead-please"
2304 tom.houday 46
	$ACMESH_BIN --config-home $ACMESH_HOME/data \
47
		$STAGING_SERVER $FORCE $debugOpt \
48
		$emailField \
2596 tom.houday 49
		--issue --dns $dnsApiOpt -d $DOMAIN \
2304 tom.houday 50
		$OPT_PARAMS \
3182 rexy 51
		--server $LE_SERVER \
2304 tom.houday 52
		> $TMP_OUTPUT 2>&1
53
	exitCode=$?
54
	$DEBUG && cat $TMP_OUTPUT && echo -e "\n\n"
55
	sed -i "s/^domainRequest=.*/domainRequest=$DOMAIN/" $CONF_FILE
56
	sed -i "s/^dateIssueRequest=.*/dateIssueRequest=$(date +%s)/" $CONF_FILE
57
	sed -i "s/^dnsapi=.*/dnsapi=${DNS_API:="dns"}/" $CONF_FILE
58
	if ! _handle_client_response $TMP_OUTPUT; then
59
		if [ $exitCode -ne 0 ]; then
60
			echo -e "Error!\n"
61
			cat $TMP_OUTPUT
62
			rm -f $TMP_OUTPUT
63
			return 1
64
		else
65
			echo -e "Unknown state\n"
66
			cat $TMP_OUTPUT
67
		fi
68
	fi
69
	rm -f $TMP_OUTPUT
70
}
71
 
72
################################################################################
73
#                                    RENEW                                     #
74
################################################################################
75
renew() {
76
	if [ ! -f $ACMESH_BIN ]; then
77
		echo "The client does not seem to be installed."
78
		return 1
79
	fi
80
	TMP_OUTPUT=$(mktemp --suffix=_ALCASAR-LE)
81
	$DEBUG && debugOpt=" --debug" || debugOpt=""
2596 tom.houday 82
	[ ! -z "$DNS_API" ] && dnsApiOpt="" || dnsApiOpt="--yes-I-know-dns-manual-mode-enough-go-ahead-please"
2304 tom.houday 83
	$ACMESH_BIN --config-home $ACMESH_HOME/data \
84
		$STAGING_SERVER $FORCE $debugOpt \
2596 tom.houday 85
		--renew -d $DOMAIN $dnsApiOpt \
2304 tom.houday 86
		$OPT_PARAMS \
3182 rexy 87
		--server $LE_SERVER \
2304 tom.houday 88
		> $TMP_OUTPUT 2>&1
89
	exitCode=$?
90
	$DEBUG && cat $TMP_OUTPUT && echo -e "\n\n"
91
	if ! _handle_client_response $TMP_OUTPUT; then
92
		if [ $exitCode -ne 0 ]; then
93
			echo -e "Error!\n"
94
			cat $TMP_OUTPUT
95
			rm -f $TMP_OUTPUT
96
			return 1
97
		else
98
			echo -e "Unknown state\n"
99
			cat $TMP_OUTPUT
100
		fi
101
	fi
102
	rm -f $TMP_OUTPUT
103
}
104
 
105
################################################################################
106
#                                  CRON TASK                                   #
107
################################################################################
108
cron_task() {
109
	if [ $(grep '^dateNextRenewal=' $CONF_FILE | cut -d'=' -f2) -le $(date +%s) ]; then
3300 rexy 110
		logger -t alcasar-letsencrypt "Warning : L.E. certificate must be renewed."
111
		# here : send a warning Email to @admin if exists (with the hostname of this ALCASAR)
112
		# renew  (discussion if needed or not - look at the challenge longevity)
2304 tom.houday 113
	fi
114
}
115
 
116
################################################################################
117
#                            HANDLE CLIENT RESPONSE                            #
118
################################################################################
119
_handle_client_response() {
120
	[ $# -lt 1 ] && return 1
121
	responseFile=$1
122
 
123
	# issue / renew
124
	if [ $(cat $responseFile | grep "Add the following TXT record:" -c) -ne 0 ]; then
125
		challenge=$(cat $responseFile | grep -E "TXT value: '[0-9a-zA-Z_-]+'" -o | cut -d"'" -f2)
126
		sed -i "s/^challenge=.*/challenge=$challenge/" $CONF_FILE
127
		echo "Add the following TXT record:"
128
		echo "Domain:    '_acme-challenge.$DOMAIN'"
129
		echo "TXT value: '$challenge'"
130
	elif [ $(cat $responseFile | grep "Cert success." -c) -ne 0 ]; then
131
		sed -i "s/^challenge=.*/challenge=/" $CONF_FILE
132
		sed -i "s/^dateIssued=.*/dateIssued=$(date +%s)/" $CONF_FILE
3300 rexy 133
		sed -i "s/^dateNextRenewal=.*/dateNextRenewal=$(date +%s -d '3 months - 15 days')/" $CONF_FILE
2304 tom.houday 134
		install_cert
135
		logger -t alcasar-letsencrypt "Certificate \"$DOMAIN\" imported."
136
		echo "Certificate imported."
137
		[ -z $DNS_API ] && echo "Note: you can delete the TXT record."
138
	elif [ $(cat $responseFile | grep "Domains not changed." -c) -ne 0 ]; then
139
		echo "Domain not changed"
140
	elif [ $(cat $responseFile | grep "$DOMAIN is already verified, skip dns-01." -c) -ne 0 ]; then
141
		echo "Domain already verified"
142
	elif [ $(cat $responseFile | grep "Error add txt for domain:_acme-challenge.$DOMAIN" -c) -ne 0 ]; then
143
		echo "Error add txt for domain:_acme-challenge.$DOMAIN"
144
	elif [ $(cat $responseFile | grep "Please add the TXT records to the domains, and retry again." -c) -ne 0 ]; then
145
		echo "Dns record not added yet, you need to add it manually and retry again."
146
	elif [ $(cat $responseFile | grep 'new-authz error: {"type":"urn:acme:error:malformed","detail":"Error creating new authz :: \(.*\)","status": 400}' -c) -ne 0 ]; then
147
		errorMsg=$(cat $responseFile | grep 'new-authz error: {"type":"urn:acme:error:malformed","detail":"Error creating new authz :: \(.*\)","status": 400}' | sed 's/.*new-authz error: {"type":"urn:acme:error:malformed","detail":"Error creating new authz :: \(.*\)","status": 400}.*/\1/')
148
		echo "Incorrect domain name"
149
		echo "$errorMsg"
150
	elif [ $(cat $responseFile | grep "'$DOMAIN' is not a issued domain, skip." -c) -ne 0 ]; then
151
		echo "'$DOMAIN' is not a issued domain"
152
 
153
	# renew
154
	elif [ $(cat $responseFile | grep "Skip, Next renewal time is: " -c) -ne 0 ]; then
155
		nextRenewal=$(cat $responseFile | grep 'Skip, Next renewal time is: ' | sed 's/.*Skip, Next renewal time is: \(.*\)/\1/')
156
		echo "Skip, Next renewal time is: $nextRenewal"
157
		echo "Add '--force' to force to renew."
158
	elif [ $(cat $responseFile | grep "$DOMAIN:Verify error:Correct value not found for DNS challenge" -c) -ne 0 ]; then
159
		echo "Correct value not found for DNS challenge"
160
	elif [ $(cat $responseFile | grep "Unable to update challenge :: The challenge is not pending." -c) -ne 0 ]; then
161
		echo "The challenge is not pending. You need to issue."
162
	else
163
		return 2
164
	fi
165
	return 0
166
}
167
 
168
################################################################################
169
#                             INSTALL CERTIFICATE                              #
170
################################################################################
171
install_cert() {
172
	echo "Importing certificate to ALCASAR..."
3163 rexy 173
	LE_cert_folder="$( echo "$ACMESH_HOME/certs/$DOMAIN"*"")"
174
	if [ ! -f $LE_cert_folder"/"$DOMAIN.cer ]; then
2304 tom.houday 175
		echo "Certificate not found."
176
		return 1
177
	fi
178
	/usr/local/bin/alcasar-importcert.sh \
3163 rexy 179
		-i $LE_cert_folder"/"$DOMAIN.cer \
180
		-k $LE_cert_folder"/"$DOMAIN.key \
181
		-c $LE_cert_folder/fullchain.cer \
2304 tom.houday 182
		> /dev/null 2>&1
183
	if [ $? -ne 0 ]; then
184
		echo "Error."
185
		return 1
186
	fi
187
}
188
 
189
################################################################################
190
#                                     MAIN                                     #
191
################################################################################
192
 
2596 tom.houday 193
if [ $# -eq 0 ]; then
2304 tom.houday 194
	echo "$usage"
195
	exit 1
196
fi
197
cmd=""
198
while [ $# -gt 0 ]; do
199
	case $1 in
200
		-\? | -h | --help)
201
			echo "$usage"
202
			exit 0
203
			;;
204
		--issue)
205
			cmd="issue"
206
			shift 1
207
			;;
208
		--renew)
209
			cmd="renew"
210
			shift 1
211
			;;
212
		--cron)
213
			cmd="cron"
214
			shift 1
215
			;;
216
		--install-cert)
217
			cmd="install-cert"
218
			shift 1
219
			;;
220
		--email)
221
			ACCOUNT_EMAIL="$2"
222
			shift 2
223
			;;
224
		--domain | -d)
225
			DOMAIN="$2"
226
			shift 2
227
			;;
228
		--dns-api)
229
			DNS_API="$2"
230
			shift 2
231
			;;
232
		--force)
233
			FORCE="--force"
234
			shift 1
235
			;;
236
		--staging)
237
			STAGING_SERVER="--staging"
238
			shift 1
239
			;;
240
		--debug)
241
			DEBUG=true
242
			shift 1
243
			;;
244
		*)
245
			found=false
246
			for param in "--dnssleep"; do
247
				if [ $1 == $param ]; then
248
					OPT_PARAMS="$OPT_PARAMS $1 $2"
249
					shift 2
250
					found=true
251
					break
252
				fi
253
			done
254
			if ! $found; then
255
				echo "Unknown argument: $1"
256
				echo "$usage"
257
				exit 1
258
			fi
259
			;;
260
	esac
261
done
262
 
263
if [ -z $DOMAIN ]; then
264
	if [ $(grep '^domainRequest=' $CONF_FILE | cut -d'=' -f2 | wc --chars) -gt 1 ]; then
265
		DOMAIN="$(grep '^domainRequest=' $CONF_FILE | cut -d'=' -f2)"
266
	else
267
		DOMAIN="$(grep '^HOSTNAME=' /usr/local/etc/alcasar.conf | cut -d'=' -f2).$(grep '^DOMAIN=' /usr/local/etc/alcasar.conf | cut -d'=' -f2)"
268
	fi
269
fi
270
 
271
case $cmd in
272
	issue)
273
		issue
274
		;;
275
	renew)
276
		renew
277
		;;
278
	cron)
279
		cron_task
280
		;;
281
	install-cert)
282
		install_cert
283
		;;
284
	*) exit 1 ;;
285
esac