Subversion Repositories ALCASAR

Rev

Rev 3169 | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log

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