aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThomas Lange <code@nerdmind.de>2022-10-24 20:48:16 +0200
committerThomas Lange <code@nerdmind.de>2022-10-24 22:24:11 +0200
commita4baf04d0c0345310579c63a51ff1af58ebb7b4e (patch)
treec5bece1ddee1fcdf896d9f3acd84cde8fd5569c1
parentee55f1d2d75078c6d96da875166c2c82e04a668c (diff)
downloadpainlessle-a4baf04d0c0345310579c63a51ff1af58ebb7b4e.tar.gz
painlessle-a4baf04d0c0345310579c63a51ff1af58ebb7b4e.tar.xz
painlessle-a4baf04d0c0345310579c63a51ff1af58ebb7b4e.zip
Do some code cleanup/optimizing (including bugfix)
Do some code cleanup and optimizing, and fix a bug where the script will always return exit code 1 if LETSENCRYPT_COMMAND_AFTER wasn't defined. The bug was caused by this last line in the script: [ ! -z "${LETSENCRYPT_COMMAND_AFTER}" ] \ && eval $LETSENCRYPT_COMMAND_AFTER ... and has been fixed by putting the "eval $LETSENCRYPT_COMMAND_AFTER" line into a real "if" container so that it doesn't affect the exit code of the script when LETSENCRYPT_COMMAND_AFTER is undefined: if [ ! -z "${LETSENCRYPT_COMMAND_AFTER}" ]; then eval $LETSENCRYPT_COMMAND_AFTER fi
-rwxr-xr-xpackage/sbin/painless-le97
1 files changed, 49 insertions, 48 deletions
diff --git a/package/sbin/painless-le b/package/sbin/painless-le
index 82886ee..124bbe8 100755
--- a/package/sbin/painless-le
+++ b/package/sbin/painless-le
@@ -4,9 +4,9 @@
#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#
# #
# Easily get an X.509 certificate from the Let's Encrypt Certificate Authority #
-# for a bunch of hostnames without having an HTTP server installed. The script #
-# assumes that you have an existing private key stored within your desired #
-# install directory (with the filename which is defined in "${CONFIDENTIAL}"). #
+# without the need of having a dedicated web server installed. With PainlessLE #
+# you'll manage your certificate and private key files by yourself. Instead of #
+# Certbot, you're responsible for the periodic renewal of the certificates. #
# #
# USAGE: #
# painless-le [OPTIONS] TARGET_DIR DNS_DOMAIN [DNS_DOMAIN ...] #
@@ -22,6 +22,15 @@
#%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%#
#===============================================================================
+# Define ACME endpoint address and BEFORE/AFTER commands
+#===============================================================================
+LETSENCRYPT_ENDPOINT="https://acme-v02.api.letsencrypt.org/directory"
+#LETSENCRYPT_ENDPOINT="https://acme-staging-v02.api.letsencrypt.org/directory"
+
+#LETSENCRYPT_COMMAND_BEFORE="systemctl stop apache2"
+#LETSENCRYPT_COMMAND_AFTER="systemctl start apache2"
+
+#===============================================================================
# Normalize command-line arguments with GNU getopt
#===============================================================================
set -- $(getopt -uo K:I:C:F: -- "$@")
@@ -32,10 +41,10 @@ set -- $(getopt -uo K:I:C:F: -- "$@")
while getopts :K:I:C:F: option
do
case $option in
- K) ARGUMENT_CONFIDENTIAL="$OPTARG" ;;
- I) ARGUMENT_INTERMEDIATE="$OPTARG" ;;
- C) ARGUMENT_CERTIFICATE_ONLY="$OPTARG" ;;
- F) ARGUMENT_CERTIFICATE_FULL="$OPTARG" ;;
+ K) OPT_CONFIDENTIAL="$OPTARG" ;;
+ I) OPT_INTERMEDIATE="$OPTARG" ;;
+ C) OPT_CERTIFICATE_ONLY="$OPTARG" ;;
+ F) OPT_CERTIFICATE_FULL="$OPTARG" ;;
esac
done; shift $((OPTIND-1))
@@ -46,51 +55,35 @@ TARGET_DIR="$1"
DNS_DOMAIN="${@:2}"
#===============================================================================
-# Check if required positional arguments are given
+# Check if required positional arguments are missing
#===============================================================================
[ -z "${TARGET_DIR}" ] && echo "$0: Missing argument: TARGET_DIR" >&2
[ -z "${DNS_DOMAIN}" ] && echo "$0: Missing argument: DNS_DOMAIN" >&2
-
-#===============================================================================
-# Exit script if required positional argument is missing
-#===============================================================================
[ -z "${TARGET_DIR}" ] || [ -z "${DNS_DOMAIN}" ] && exit 1
#===============================================================================
-# Define the ACME endpoint address
-#===============================================================================
-LETSENCRYPT_ENDPOINT="https://acme-v02.api.letsencrypt.org/directory"
-#LETSENCRYPT_ENDPOINT="https://acme-staging-v02.api.letsencrypt.org/directory"
-
-#===============================================================================
-# Define commands who are executed BEFORE and AFTER the ACME challenge
-#===============================================================================
-#LETSENCRYPT_COMMAND_BEFORE="systemctl stop apache2"
-#LETSENCRYPT_COMMAND_AFTER="systemctl start apache2"
-
-#===============================================================================
-# Define required paths
+# Define filename variables
#===============================================================================
OPENSSLCONF="/etc/ssl/openssl.cnf"
- REQUESTFILE=`mktemp /tmp/painless-le.XXXXXXXXXX.csr`
- CONFIDENTIAL="${TARGET_DIR%/}/${ARGUMENT_CONFIDENTIAL:-confidential.pem}"
- INTERMEDIATE="${TARGET_DIR%/}/${ARGUMENT_INTERMEDIATE:-intermediate.pem}"
-CERTIFICATE_ONLY="${TARGET_DIR%/}/${ARGUMENT_CERTIFICATE_ONLY:-certificate_only.pem}"
-CERTIFICATE_FULL="${TARGET_DIR%/}/${ARGUMENT_CERTIFICATE_FULL:-certificate_full.pem}"
+ REQUESTFILE="$(mktemp /tmp/painless-le.XXXXXX.csr)"
+ CONFIDENTIAL="${TARGET_DIR%/}/${OPT_CONFIDENTIAL:-confidential.pem}"
+ INTERMEDIATE="${TARGET_DIR%/}/${OPT_INTERMEDIATE:-intermediate.pem}"
+CERTIFICATE_ONLY="${TARGET_DIR%/}/${OPT_CERTIFICATE_ONLY:-certificate_only.pem}"
+CERTIFICATE_FULL="${TARGET_DIR%/}/${OPT_CERTIFICATE_FULL:-certificate_full.pem}"
#===============================================================================
-# Delete Certificate-Signing-Request (CSR) file on exit
+# Ensure the Certificate-Signing-Request file is deleted on exit
#===============================================================================
trap 'rm ${REQUESTFILE}' EXIT
#===============================================================================
-# Generate Certificate-Signing-Request (CSR)
+# Create Certificate-Signing-Request
#===============================================================================
openssl req -config <(cat "${OPENSSLCONF}" <(printf "[SAN]\nsubjectAltName=DNS:`echo ${DNS_DOMAIN} | sed "s/ /,DNS:/g"`")) \
--new -sha256 -key "${CONFIDENTIAL}" -out "${REQUESTFILE}" -outform der -reqexts SAN -subj "/"
+ -new -sha256 -key "${CONFIDENTIAL}" -out "${REQUESTFILE}" -outform der -reqexts SAN -subj "/"
#===============================================================================
-# Checking if Certificate-Signing-Request (CSR) was successfully created
+# Check if Certificate-Signing-Request creation failed
#===============================================================================
if [ $? != 0 ]; then
echo "$0: Certificate-Signing-Request (CSR) could not be created!" >&2
@@ -98,18 +91,20 @@ if [ $? != 0 ]; then
fi
#===============================================================================
-# Execute defined command BEFORE the ACME challenge is started
+# Run defined "BEFORE" command
#===============================================================================
-[ ! -z "${LETSENCRYPT_COMMAND_BEFORE}" ] && eval $LETSENCRYPT_COMMAND_BEFORE
+if [ ! -z "${LETSENCRYPT_COMMAND_BEFORE}" ]; then
+ eval $LETSENCRYPT_COMMAND_BEFORE
+fi
#===============================================================================
-# Execute Let's Encrypt and accomplish the ACME challenge to get the certificate
+# Run Certbot to accomplish the ACME challenge to get the certificate
#===============================================================================
certbot certonly --authenticator standalone --server "${LETSENCRYPT_ENDPOINT}" --csr "${REQUESTFILE}" \
---cert-path "${CERTIFICATE_ONLY}.$$" --fullchain-path "${CERTIFICATE_FULL}.$$" --chain-path "${INTERMEDIATE}.$$"
+ --cert-path "${CERTIFICATE_ONLY}.$$" --fullchain-path "${CERTIFICATE_FULL}.$$" --chain-path "${INTERMEDIATE}.$$"
#===============================================================================
-# Checking if Certbot has successfully accomplished the ACME challenge
+# Check if Certbot failed to obtain a certificate
#===============================================================================
if [ $? != 0 ]; then
echo "$0: Certbot could not successfully accomplish the ACME challenge." >&2
@@ -117,19 +112,25 @@ if [ $? != 0 ]; then
fi
#===============================================================================
-# Replace previous certificates with the new obtained certificate files
+# Replace old certificate files (if any) with the newly obtained ones
#===============================================================================
-[ -f "${INTERMEDIATE}.$$" ] && mv "${INTERMEDIATE}.$$" "${INTERMEDIATE}"
-[ -f "${CERTIFICATE_ONLY}.$$" ] && mv "${CERTIFICATE_ONLY}.$$" "${CERTIFICATE_ONLY}"
-[ -f "${CERTIFICATE_FULL}.$$" ] && mv "${CERTIFICATE_FULL}.$$" "${CERTIFICATE_FULL}"
+for file in "${INTERMEDIATE}" "${CERTIFICATE_ONLY}" "${CERTIFICATE_FULL}"; do
+ if [ -f "${file}.$$" ]; then
+ mv "${file}.$$" "${file}"
+ fi
+done
#===============================================================================
-# Adjust the UNIX permissions with owner and group for the new created files
+# Inherit permissions of private key to new certificate files
#===============================================================================
-chmod --reference "${CONFIDENTIAL}" "${INTERMEDIATE}" "${CERTIFICATE_ONLY}" "${CERTIFICATE_FULL}"
-chown --reference "${CONFIDENTIAL}" "${INTERMEDIATE}" "${CERTIFICATE_ONLY}" "${CERTIFICATE_FULL}"
+for command in "chmod" "chown"; do
+ $command --reference "${CONFIDENTIAL}" \
+ "${INTERMEDIATE}" "${CERTIFICATE_ONLY}" "${CERTIFICATE_FULL}"
+done
#===============================================================================
-# Execute defined command AFTER the ACME challenge is completed
+# Run defined "AFTER" command
#===============================================================================
-[ ! -z "${LETSENCRYPT_COMMAND_AFTER}" ] && eval $LETSENCRYPT_COMMAND_AFTER
+if [ ! -z "${LETSENCRYPT_COMMAND_AFTER}" ]; then
+ eval $LETSENCRYPT_COMMAND_AFTER
+fi