Compare commits
7 Commits
d9a56d178b
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 7799e7a11f | |||
| 22fac32e46 | |||
| 3827481a0a | |||
| 3963be4ce5 | |||
| 89b86d0988 | |||
| 0f8f05cbaf | |||
| 16ca4dc37c |
@@ -1,9 +1,8 @@
|
|||||||
# This is a shell script excerpt for configuration purposes only.
|
# This is a shell script excerpt for configuration purposes only.
|
||||||
# Handle with care! Please don't put code here, only variables.
|
# Handle with care! Please don't put code here, only variables.
|
||||||
|
|
||||||
CLASSES_PATTERN="^([^.]*)\..*\.$HOSTNAME\.(dmp|sql\.gz|tgz|log)$"
|
CLASSES_PATTERN="^([^.]*)\..*\.$HOSTNAME\.(dmp|sql\.gz|tar|tgz|log)$"
|
||||||
DOIT="yes" # if empty the script makes a dry run
|
DOIT="yes" # if empty the script makes a dry run
|
||||||
# RETAIN_DAYS=7 # retains all files created within that many days
|
# RETAIN_DAYS=7 # retains all files created within that many days
|
||||||
# RETAIN_WEEKS=4 # retains one file per week/month,
|
# RETAIN_WEEKS=4 # retains one file per week/month,
|
||||||
# RETAIN_MONTHS=12 # created within that many weeks/months
|
# RETAIN_MONTHS=12 # created within that many weeks/months
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
../storage/volumes/nextcloud_html/config/config.php
|
../storage/volumes/nextcloud_html/config
|
||||||
@@ -21,7 +21,7 @@ services:
|
|||||||
- ./storage/volumes/nextcloud_init_d:/docker-entrypoint-hooks.d:ro
|
- ./storage/volumes/nextcloud_init_d:/docker-entrypoint-hooks.d:ro
|
||||||
# Needs R/W UID:GID 33:33 (www-data:www-data).
|
# Needs R/W UID:GID 33:33 (www-data:www-data).
|
||||||
- ./storage/volumes/nextcloud_html:/var/www/html
|
- ./storage/volumes/nextcloud_html:/var/www/html
|
||||||
- ./storage/volumes/nextcloud_data:/wtkclouddata
|
- ./storage/volumes/nextcloud_data:/var/www/html/data
|
||||||
environment:
|
environment:
|
||||||
MYSQL_HOST: database
|
MYSQL_HOST: database
|
||||||
MYSQL_DATABASE: nextcloud
|
MYSQL_DATABASE: nextcloud
|
||||||
@@ -32,7 +32,7 @@ services:
|
|||||||
# E.g. https://www.avast.com/random-password-generator
|
# E.g. https://www.avast.com/random-password-generator
|
||||||
NEXTCLOUD_ADMIN_PASSWORD: secret-3
|
NEXTCLOUD_ADMIN_PASSWORD: secret-3
|
||||||
# Fill in according to local settings.
|
# Fill in according to local settings.
|
||||||
#NEXTCLOUD_TRUSTED_DOMAINS: example.com, cloud.example.com
|
#NEXTCLOUD_TRUSTED_DOMAINS: example.com cloud.example.com
|
||||||
# These are required behind a reverse proxy.
|
# These are required behind a reverse proxy.
|
||||||
APACHE_DISABLE_REWRITE_IP: 1
|
APACHE_DISABLE_REWRITE_IP: 1
|
||||||
# Feel free to adapt to your Docker environment.
|
# Feel free to adapt to your Docker environment.
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
# This is a shell script excerpt for configuration purposes only.
|
# This is a shell script excerpt for configuration purposes only.
|
||||||
# Handle with care! Please don't put code here, only variables.
|
# Handle with care! Please don't put code here, only variables.
|
||||||
|
|
||||||
CLASSES_PATTERN="^([^.]*)\..*\.$HOSTNAME\.(dmp|sql\.gz|tgz|log)$"
|
CLASSES_PATTERN="^([^.]*)\..*\.$HOSTNAME\.(dmp|sql\.gz|tgz|tar|log)$"
|
||||||
DOIT="yes" # if empty the script makes a dry run
|
DOIT="yes" # if empty the script makes a dry run
|
||||||
# RETAIN_DAYS=7 # retains all files created within that many days
|
# RETAIN_DAYS=7 # retains all files created within that many days
|
||||||
# RETAIN_WEEKS=4 # retains one file per week/month,
|
# RETAIN_WEEKS=4 # retains one file per week/month,
|
||||||
# RETAIN_MONTHS=12 # created within that many weeks/months
|
# RETAIN_MONTHS=12 # created within that many weeks/months
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
#
|
#
|
||||||
# A service script to backup the relevant user's storage (data folder)
|
# A service script to backup the relevant user's storage (apps, data, themes)
|
||||||
# of a docker-composed Nextcloud instance. Creates a tarball in
|
# of a docker-composed Nextcloud instance. Creates a tarball in
|
||||||
# $BASE_DIR/storage/backups/tarballs folder (by default). An optional
|
# $BASE_DIR/storage/backups/tarballs folder (by default). An optional
|
||||||
# parameter may change the target folder.
|
# parameter may change the target folder.
|
||||||
@@ -9,6 +9,9 @@
|
|||||||
#
|
#
|
||||||
# Author: Kovács Zoltán <kovacsz@marcusconsulting.hu>
|
# Author: Kovács Zoltán <kovacsz@marcusconsulting.hu>
|
||||||
# License: GNU/GPL 3+ https://www.gnu.org/licenses/gpl-3.0.en.html
|
# License: GNU/GPL 3+ https://www.gnu.org/licenses/gpl-3.0.en.html
|
||||||
|
# 2026-02-07 v0.2
|
||||||
|
# new: Excludes the documents if the storage_gitbackup is active.
|
||||||
|
# mod: custom_apps and themes folders have been added.
|
||||||
# 2025-11-24 v0.1 Initial version.
|
# 2025-11-24 v0.1 Initial version.
|
||||||
|
|
||||||
# Accepted environment variables and their defaults.
|
# Accepted environment variables and their defaults.
|
||||||
@@ -28,6 +31,7 @@ MSG_NOLOCATE="Cannot locate the Nextcloud container."
|
|||||||
# Other initialisations.
|
# Other initialisations.
|
||||||
#
|
#
|
||||||
BACKUPDIR="storage/backups/tarballs" # Folder to dump within
|
BACKUPDIR="storage/backups/tarballs" # Folder to dump within
|
||||||
|
GITBACKUP="storage_gitbackup.sh" # Git backup utility
|
||||||
SERVICENAME="nextcloud" # The composed Nextcloud service
|
SERVICENAME="nextcloud" # The composed Nextcloud service
|
||||||
USER=${USER:-LOGNAME} # Fix for cron enviroment only
|
USER=${USER:-LOGNAME} # Fix for cron enviroment only
|
||||||
YMLFILE="docker-compose.yml"
|
YMLFILE="docker-compose.yml"
|
||||||
@@ -112,11 +116,16 @@ NCCONTAINER="$("$DOCKER" inspect -f '{{.Name}}' $(cd "$BASE_DIR"; "$DOCKER_COMPO
|
|||||||
# Gives up here if failed.
|
# Gives up here if failed.
|
||||||
if [ -z "$NCCONTAINER" ]; then echo "$MSG_NOLOCATE" >&2; exit 1; fi
|
if [ -z "$NCCONTAINER" ]; then echo "$MSG_NOLOCATE" >&2; exit 1; fi
|
||||||
|
|
||||||
|
# Excludes the documents if the GITBACKUP is active.
|
||||||
|
DOCUMENTS="data"
|
||||||
|
[[ -n $(which "$GITBACKUP") ]] && DOCUMENTS="" # it is an executable somewhere in the path
|
||||||
|
[[ -x "$SCRPATH/$GITBACKUP" ]] && DOCUMENTS="" # it is an executable in the current directory
|
||||||
|
|
||||||
# Tries the FS backup.
|
# Tries the FS backup.
|
||||||
if [ -w "$BACKUPDIR" ]; then
|
if [ -w "$BACKUPDIR" ]; then
|
||||||
BACKUP_NAME=$NCCONTAINER.$("$DATE" '+%Y%m%d_%H%M%S').$("$HOSTNAME")
|
BACKUP_NAME=$NCCONTAINER.$("$DATE" '+%Y%m%d_%H%M%S').$("$HOSTNAME")
|
||||||
"$DOCKER" exec $NCCONTAINER sh \
|
"$DOCKER" exec $NCCONTAINER sh \
|
||||||
-c "cd /var/www/html; tar cz data" \
|
-c "cd /var/www/html; tar cz custom_apps $DOCUMENTS themes" \
|
||||||
> "$BACKUPDIR/$BACKUP_NAME.tgz" 2>>"$BACKUPDIR/$BACKUP_NAME.log"
|
> "$BACKUPDIR/$BACKUP_NAME.tgz" 2>>"$BACKUPDIR/$BACKUP_NAME.log"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
|||||||
0
.recipes/nextcloud_mariadb/tools/maintenance_cron
Normal file → Executable file
0
.recipes/nextcloud_mariadb/tools/maintenance_cron
Normal file → Executable file
@@ -1,9 +1,8 @@
|
|||||||
# This is a shell script excerpt for configuration purposes only.
|
# This is a shell script excerpt for configuration purposes only.
|
||||||
# Handle with care! Please don't put code here, only variables.
|
# Handle with care! Please don't put code here, only variables.
|
||||||
|
|
||||||
CLASSES_PATTERN="^([^.]*)\..*\.$HOSTNAME\.(dmp|sql\.gz|tgz|log)$"
|
CLASSES_PATTERN="^([^.]*)\..*\.$HOSTNAME\.(dmp|sql\.gz|tar|tgz|log)$"
|
||||||
DOIT="yes" # if empty the script makes a dry run
|
DOIT="yes" # if empty the script makes a dry run
|
||||||
# RETAIN_DAYS=7 # retains all files created within that many days
|
# RETAIN_DAYS=7 # retains all files created within that many days
|
||||||
# RETAIN_WEEKS=4 # retains one file per week/month,
|
# RETAIN_WEEKS=4 # retains one file per week/month,
|
||||||
# RETAIN_MONTHS=12 # created within that many weeks/months
|
# RETAIN_MONTHS=12 # created within that many weeks/months
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
# This is a shell script excerpt for configuration purposes only.
|
# This is a shell script excerpt for configuration purposes only.
|
||||||
# Handle with care! Please don't put code here, only variables.
|
# Handle with care! Please don't put code here, only variables.
|
||||||
|
|
||||||
CLASSES_PATTERN="^([^.]*)\..*\.$HOSTNAME\.(dmp|sql\.gz|tgz|log)$"
|
CLASSES_PATTERN="^([^.]*)\..*\.$HOSTNAME\.(dmp|sql\.gz|tar|tgz|log)$"
|
||||||
DOIT="yes" # if empty the script makes a dry run
|
DOIT="yes" # if empty the script makes a dry run
|
||||||
# RETAIN_DAYS=7 # retains all files created within that many days
|
# RETAIN_DAYS=7 # retains all files created within that many days
|
||||||
# RETAIN_WEEKS=4 # retains one file per week/month,
|
# RETAIN_WEEKS=4 # retains one file per week/month,
|
||||||
# RETAIN_MONTHS=12 # created within that many weeks/months
|
# RETAIN_MONTHS=12 # created within that many weeks/months
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env sh
|
#!/usr/bin/env sh
|
||||||
|
|
||||||
VER=3.0.8
|
VER=3.1.3
|
||||||
|
|
||||||
PROJECT_NAME="acme.sh"
|
PROJECT_NAME="acme.sh"
|
||||||
|
|
||||||
@@ -23,9 +23,6 @@ _SUB_FOLDERS="$_SUB_FOLDER_DNSAPI $_SUB_FOLDER_DEPLOY $_SUB_FOLDER_NOTIFY"
|
|||||||
CA_LETSENCRYPT_V2="https://acme-v02.api.letsencrypt.org/directory"
|
CA_LETSENCRYPT_V2="https://acme-v02.api.letsencrypt.org/directory"
|
||||||
CA_LETSENCRYPT_V2_TEST="https://acme-staging-v02.api.letsencrypt.org/directory"
|
CA_LETSENCRYPT_V2_TEST="https://acme-staging-v02.api.letsencrypt.org/directory"
|
||||||
|
|
||||||
CA_BUYPASS="https://api.buypass.com/acme/directory"
|
|
||||||
CA_BUYPASS_TEST="https://api.test4.buypass.no/acme/directory"
|
|
||||||
|
|
||||||
CA_ZEROSSL="https://acme.zerossl.com/v2/DV90"
|
CA_ZEROSSL="https://acme.zerossl.com/v2/DV90"
|
||||||
_ZERO_EAB_ENDPOINT="https://api.zerossl.com/acme/eab-credentials-email"
|
_ZERO_EAB_ENDPOINT="https://api.zerossl.com/acme/eab-credentials-email"
|
||||||
|
|
||||||
@@ -35,6 +32,8 @@ CA_SSLCOM_ECC="https://acme.ssl.com/sslcom-dv-ecc"
|
|||||||
CA_GOOGLE="https://dv.acme-v02.api.pki.goog/directory"
|
CA_GOOGLE="https://dv.acme-v02.api.pki.goog/directory"
|
||||||
CA_GOOGLE_TEST="https://dv.acme-v02.test-api.pki.goog/directory"
|
CA_GOOGLE_TEST="https://dv.acme-v02.test-api.pki.goog/directory"
|
||||||
|
|
||||||
|
CA_ACTALIS="https://acme-api.actalis.com/acme/directory"
|
||||||
|
|
||||||
DEFAULT_CA=$CA_ZEROSSL
|
DEFAULT_CA=$CA_ZEROSSL
|
||||||
DEFAULT_STAGING_CA=$CA_LETSENCRYPT_V2_TEST
|
DEFAULT_STAGING_CA=$CA_LETSENCRYPT_V2_TEST
|
||||||
|
|
||||||
@@ -42,14 +41,13 @@ CA_NAMES="
|
|||||||
ZeroSSL.com,zerossl
|
ZeroSSL.com,zerossl
|
||||||
LetsEncrypt.org,letsencrypt
|
LetsEncrypt.org,letsencrypt
|
||||||
LetsEncrypt.org_test,letsencrypt_test,letsencrypttest
|
LetsEncrypt.org_test,letsencrypt_test,letsencrypttest
|
||||||
BuyPass.com,buypass
|
|
||||||
BuyPass.com_test,buypass_test,buypasstest
|
|
||||||
SSL.com,sslcom
|
SSL.com,sslcom
|
||||||
Google.com,google
|
Google.com,google
|
||||||
Google.com_test,googletest,google_test
|
Google.com_test,googletest,google_test
|
||||||
|
Actalis.com,actalis.com,actalis
|
||||||
"
|
"
|
||||||
|
|
||||||
CA_SERVERS="$CA_ZEROSSL,$CA_LETSENCRYPT_V2,$CA_LETSENCRYPT_V2_TEST,$CA_BUYPASS,$CA_BUYPASS_TEST,$CA_SSLCOM_RSA,$CA_GOOGLE,$CA_GOOGLE_TEST"
|
CA_SERVERS="$CA_ZEROSSL,$CA_LETSENCRYPT_V2,$CA_LETSENCRYPT_V2_TEST,$CA_SSLCOM_RSA,$CA_GOOGLE,$CA_GOOGLE_TEST,$CA_ACTALIS"
|
||||||
|
|
||||||
DEFAULT_USER_AGENT="$PROJECT_NAME/$VER ($PROJECT)"
|
DEFAULT_USER_AGENT="$PROJECT_NAME/$VER ($PROJECT)"
|
||||||
|
|
||||||
@@ -67,7 +65,7 @@ ID_TYPE_IP="ip"
|
|||||||
|
|
||||||
LOCAL_ANY_ADDRESS="0.0.0.0"
|
LOCAL_ANY_ADDRESS="0.0.0.0"
|
||||||
|
|
||||||
DEFAULT_RENEW=60
|
DEFAULT_RENEW=30
|
||||||
|
|
||||||
NO_VALUE="no"
|
NO_VALUE="no"
|
||||||
|
|
||||||
@@ -180,6 +178,8 @@ _VALIDITY_WIKI="https://github.com/acmesh-official/acme.sh/wiki/Validity"
|
|||||||
|
|
||||||
_DNSCHECK_WIKI="https://github.com/acmesh-official/acme.sh/wiki/dnscheck"
|
_DNSCHECK_WIKI="https://github.com/acmesh-official/acme.sh/wiki/dnscheck"
|
||||||
|
|
||||||
|
_PROFILESELECTION_WIKI="https://github.com/acmesh-official/acme.sh/wiki/Profile-selection"
|
||||||
|
|
||||||
_DNS_MANUAL_ERR="The dns manual mode can not renew automatically, you must issue it again manually. You'd better use the other modes instead."
|
_DNS_MANUAL_ERR="The dns manual mode can not renew automatically, you must issue it again manually. You'd better use the other modes instead."
|
||||||
|
|
||||||
_DNS_MANUAL_WARN="It seems that you are using dns manual mode. please take care: $_DNS_MANUAL_ERR"
|
_DNS_MANUAL_WARN="It seems that you are using dns manual mode. please take care: $_DNS_MANUAL_ERR"
|
||||||
@@ -250,6 +250,13 @@ _dlg_versions() {
|
|||||||
socat -V 2>&1
|
socat -V 2>&1
|
||||||
else
|
else
|
||||||
_debug "socat doesn't exist."
|
_debug "socat doesn't exist."
|
||||||
|
if _exists "python3"; then
|
||||||
|
python3 -V 2>&1
|
||||||
|
elif _exists "python2"; then
|
||||||
|
python2 -V 2>&1
|
||||||
|
elif _exists "python"; then
|
||||||
|
python -V 2>&1
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -436,14 +443,28 @@ _secure_debug3() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__USE_TR_TAG=""
|
||||||
|
if [ "$(echo "abc" | LANG=C tr a-z A-Z 2>/dev/null)" != "ABC" ]; then
|
||||||
|
__USE_TR_TAG="1"
|
||||||
|
fi
|
||||||
|
export __USE_TR_TAG
|
||||||
|
|
||||||
_upper_case() {
|
_upper_case() {
|
||||||
|
if [ "$__USE_TR_TAG" ]; then
|
||||||
|
LANG=C tr '[:lower:]' '[:upper:]'
|
||||||
|
else
|
||||||
# shellcheck disable=SC2018,SC2019
|
# shellcheck disable=SC2018,SC2019
|
||||||
tr '[a-z]' '[A-Z]'
|
LANG=C tr '[a-z]' '[A-Z]'
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
_lower_case() {
|
_lower_case() {
|
||||||
|
if [ "$__USE_TR_TAG" ]; then
|
||||||
|
LANG=C tr '[:upper:]' '[:lower:]'
|
||||||
|
else
|
||||||
# shellcheck disable=SC2018,SC2019
|
# shellcheck disable=SC2018,SC2019
|
||||||
tr '[A-Z]' '[a-z]'
|
LANG=C tr '[A-Z]' '[a-z]'
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
_startswith() {
|
_startswith() {
|
||||||
@@ -672,8 +693,10 @@ _hex_dump() {
|
|||||||
#0 1 2 3 4 5 6 7 8 9 - _ . ~
|
#0 1 2 3 4 5 6 7 8 9 - _ . ~
|
||||||
#30 31 32 33 34 35 36 37 38 39 2d 5f 2e 7e
|
#30 31 32 33 34 35 36 37 38 39 2d 5f 2e 7e
|
||||||
|
|
||||||
|
#_url_encode [upper-hex] the encoded hex will be upper-case if the argument upper-hex is followed
|
||||||
#stdin stdout
|
#stdin stdout
|
||||||
_url_encode() {
|
_url_encode() {
|
||||||
|
_upper_hex=$1
|
||||||
_hex_str=$(_hex_dump)
|
_hex_str=$(_hex_dump)
|
||||||
_debug3 "_url_encode"
|
_debug3 "_url_encode"
|
||||||
_debug3 "_hex_str" "$_hex_str"
|
_debug3 "_hex_str" "$_hex_str"
|
||||||
@@ -883,6 +906,9 @@ _url_encode() {
|
|||||||
;;
|
;;
|
||||||
#other hex
|
#other hex
|
||||||
*)
|
*)
|
||||||
|
if [ "$_upper_hex" = "upper-hex" ]; then
|
||||||
|
_hex_code=$(printf "%s" "$_hex_code" | _upper_case)
|
||||||
|
fi
|
||||||
printf '%%%s' "$_hex_code"
|
printf '%%%s' "$_hex_code"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
@@ -916,6 +942,9 @@ _sed_i() {
|
|||||||
if sed -h 2>&1 | grep "\-i\[SUFFIX]" >/dev/null 2>&1; then
|
if sed -h 2>&1 | grep "\-i\[SUFFIX]" >/dev/null 2>&1; then
|
||||||
_debug "Using sed -i"
|
_debug "Using sed -i"
|
||||||
sed -i "$options" "$filename"
|
sed -i "$options" "$filename"
|
||||||
|
elif sed -h 2>&1 | grep "\-i extension" >/dev/null 2>&1; then
|
||||||
|
_debug "Using FreeBSD sed -i"
|
||||||
|
sed -i "" "$options" "$filename"
|
||||||
else
|
else
|
||||||
_debug "No -i support in sed"
|
_debug "No -i support in sed"
|
||||||
text="$(cat "$filename")"
|
text="$(cat "$filename")"
|
||||||
@@ -1009,7 +1038,7 @@ _digest() {
|
|||||||
|
|
||||||
outputhex="$2"
|
outputhex="$2"
|
||||||
|
|
||||||
if [ "$alg" = "sha256" ] || [ "$alg" = "sha1" ] || [ "$alg" = "md5" ]; then
|
if [ "$alg" = "sha3-256" ] || [ "$alg" = "sha256" ] || [ "$alg" = "sha1" ] || [ "$alg" = "md5" ]; then
|
||||||
if [ "$outputhex" ]; then
|
if [ "$outputhex" ]; then
|
||||||
${ACME_OPENSSL_BIN:-openssl} dgst -"$alg" -hex | cut -d = -f 2 | tr -d ' '
|
${ACME_OPENSSL_BIN:-openssl} dgst -"$alg" -hex | cut -d = -f 2 | tr -d ' '
|
||||||
else
|
else
|
||||||
@@ -1228,7 +1257,7 @@ _idn() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
#_createcsr cn san_list keyfile csrfile conf acmeValidationv1
|
#_createcsr cn san_list keyfile csrfile conf acmeValidationv1 extendedUsage
|
||||||
_createcsr() {
|
_createcsr() {
|
||||||
_debug _createcsr
|
_debug _createcsr
|
||||||
domain="$1"
|
domain="$1"
|
||||||
@@ -1237,6 +1266,7 @@ _createcsr() {
|
|||||||
csr="$4"
|
csr="$4"
|
||||||
csrconf="$5"
|
csrconf="$5"
|
||||||
acmeValidationv1="$6"
|
acmeValidationv1="$6"
|
||||||
|
extusage="$7"
|
||||||
_debug2 domain "$domain"
|
_debug2 domain "$domain"
|
||||||
_debug2 domainlist "$domainlist"
|
_debug2 domainlist "$domainlist"
|
||||||
_debug2 csrkey "$csrkey"
|
_debug2 csrkey "$csrkey"
|
||||||
@@ -1245,9 +1275,8 @@ _createcsr() {
|
|||||||
|
|
||||||
printf "[ req_distinguished_name ]\n[ req ]\ndistinguished_name = req_distinguished_name\nreq_extensions = v3_req\n[ v3_req ]" >"$csrconf"
|
printf "[ req_distinguished_name ]\n[ req ]\ndistinguished_name = req_distinguished_name\nreq_extensions = v3_req\n[ v3_req ]" >"$csrconf"
|
||||||
|
|
||||||
if [ "$Le_ExtKeyUse" ]; then
|
if [ "$extusage" ]; then
|
||||||
_savedomainconf Le_ExtKeyUse "$Le_ExtKeyUse"
|
printf "\nextendedKeyUsage=$extusage\n" >>"$csrconf"
|
||||||
printf "\nextendedKeyUsage=$Le_ExtKeyUse\n" >>"$csrconf"
|
|
||||||
else
|
else
|
||||||
printf "\nextendedKeyUsage=serverAuth,clientAuth\n" >>"$csrconf"
|
printf "\nextendedKeyUsage=serverAuth,clientAuth\n" >>"$csrconf"
|
||||||
fi
|
fi
|
||||||
@@ -1393,6 +1422,12 @@ _ss() {
|
|||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ "$(uname)" = "AIX" ]; then
|
||||||
|
_debug "Using: AIX netstat"
|
||||||
|
netstat -an | grep "^tcp" | grep "LISTEN" | grep "\.$_port "
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
if _exists "netstat"; then
|
if _exists "netstat"; then
|
||||||
_debug "Using: netstat"
|
_debug "Using: netstat"
|
||||||
if netstat -help 2>&1 | grep "\-p proto" >/dev/null; then
|
if netstat -help 2>&1 | grep "\-p proto" >/dev/null; then
|
||||||
@@ -1437,8 +1472,8 @@ _toPkcs() {
|
|||||||
else
|
else
|
||||||
${ACME_OPENSSL_BIN:-openssl} pkcs12 -export -out "$_cpfx" -inkey "$_ckey" -in "$_ccert" -certfile "$_cca"
|
${ACME_OPENSSL_BIN:-openssl} pkcs12 -export -out "$_cpfx" -inkey "$_ckey" -in "$_ccert" -certfile "$_cca"
|
||||||
fi
|
fi
|
||||||
if [ "$?" == "0" ]; then
|
if [ "$?" = "0" ]; then
|
||||||
_savedomainconf "Le_PFXPassword" "$pfxPassword"
|
_savedomainconf "Le_PFXPassword" "$pfxPassword" "base64"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1623,6 +1658,11 @@ _time2str() {
|
|||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
#Omnios
|
||||||
|
if date -u -r "$1" +"%Y-%m-%dT%H:%M:%SZ" 2>/dev/null; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
#Solaris
|
#Solaris
|
||||||
if printf "%(%Y-%m-%dT%H:%M:%SZ)T\n" $1 2>/dev/null; then
|
if printf "%(%Y-%m-%dT%H:%M:%SZ)T\n" $1 2>/dev/null; then
|
||||||
return
|
return
|
||||||
@@ -1792,6 +1832,10 @@ _time() {
|
|||||||
# 2022-04-01 08:10:33 to 1648800633
|
# 2022-04-01 08:10:33 to 1648800633
|
||||||
#or 2022-04-01T08:10:33Z to 1648800633
|
#or 2022-04-01T08:10:33Z to 1648800633
|
||||||
_date2time() {
|
_date2time() {
|
||||||
|
#Mac/BSD
|
||||||
|
if date -u -j -f "%Y-%m-%d %H:%M:%S" "$(echo "$1" | tr -d "Z" | tr "T" ' ')" +"%s" 2>/dev/null; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
#Linux
|
#Linux
|
||||||
if date -u -d "$(echo "$1" | tr -d "Z" | tr "T" ' ')" +"%s" 2>/dev/null; then
|
if date -u -d "$(echo "$1" | tr -d "Z" | tr "T" ' ')" +"%s" 2>/dev/null; then
|
||||||
return
|
return
|
||||||
@@ -1801,12 +1845,12 @@ _date2time() {
|
|||||||
if gdate -u -d "$(echo "$1" | tr -d "Z" | tr "T" ' ')" +"%s" 2>/dev/null; then
|
if gdate -u -d "$(echo "$1" | tr -d "Z" | tr "T" ' ')" +"%s" 2>/dev/null; then
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
#Mac/BSD
|
#Omnios
|
||||||
if date -u -j -f "%Y-%m-%d %H:%M:%S" "$(echo "$1" | tr -d "Z" | tr "T" ' ')" +"%s" 2>/dev/null; then
|
if python3 -c "import datetime; print(int(datetime.datetime.strptime(\"$1\", \"%Y-%m-%d %H:%M:%S\").replace(tzinfo=datetime.timezone.utc).timestamp()))" 2>/dev/null; then
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
#Omnios
|
#Omnios
|
||||||
if da="$(echo "$1" | tr -d "Z" | tr "T" ' ')" perl -MTime::Piece -e 'print Time::Piece->strptime($ENV{da}, "%Y-%m-%d %H:%M:%S")->epoch, "\n";' 2>/dev/null; then
|
if python3 -c "import datetime; print(int(datetime.datetime.strptime(\"$1\", \"%Y-%m-%dT%H:%M:%SZ\").replace(tzinfo=datetime.timezone.utc).timestamp()))" 2>/dev/null; then
|
||||||
return
|
return
|
||||||
fi
|
fi
|
||||||
_err "Cannot parse _date2time $1"
|
_err "Cannot parse _date2time $1"
|
||||||
@@ -1860,6 +1904,11 @@ _inithttp() {
|
|||||||
|
|
||||||
if [ -z "$_ACME_CURL" ] && _exists "curl"; then
|
if [ -z "$_ACME_CURL" ] && _exists "curl"; then
|
||||||
_ACME_CURL="curl --silent --dump-header $HTTP_HEADER "
|
_ACME_CURL="curl --silent --dump-header $HTTP_HEADER "
|
||||||
|
if [ "$ACME_USE_IPV6_REQUESTS" ]; then
|
||||||
|
_ACME_CURL="$_ACME_CURL --ipv6 "
|
||||||
|
elif [ "$ACME_USE_IPV4_REQUESTS" ]; then
|
||||||
|
_ACME_CURL="$_ACME_CURL --ipv4 "
|
||||||
|
fi
|
||||||
if [ -z "$ACME_HTTP_NO_REDIRECTS" ]; then
|
if [ -z "$ACME_HTTP_NO_REDIRECTS" ]; then
|
||||||
_ACME_CURL="$_ACME_CURL -L "
|
_ACME_CURL="$_ACME_CURL -L "
|
||||||
fi
|
fi
|
||||||
@@ -1887,6 +1936,11 @@ _inithttp() {
|
|||||||
|
|
||||||
if [ -z "$_ACME_WGET" ] && _exists "wget"; then
|
if [ -z "$_ACME_WGET" ] && _exists "wget"; then
|
||||||
_ACME_WGET="wget -q"
|
_ACME_WGET="wget -q"
|
||||||
|
if [ "$ACME_USE_IPV6_REQUESTS" ]; then
|
||||||
|
_ACME_WGET="$_ACME_WGET --inet6-only "
|
||||||
|
elif [ "$ACME_USE_IPV4_REQUESTS" ]; then
|
||||||
|
_ACME_WGET="$_ACME_WGET --inet4-only "
|
||||||
|
fi
|
||||||
if [ "$ACME_HTTP_NO_REDIRECTS" ]; then
|
if [ "$ACME_HTTP_NO_REDIRECTS" ]; then
|
||||||
_ACME_WGET="$_ACME_WGET --max-redirect 0 "
|
_ACME_WGET="$_ACME_WGET --max-redirect 0 "
|
||||||
fi
|
fi
|
||||||
@@ -2188,7 +2242,6 @@ _send_signed_request() {
|
|||||||
_debug2 _headers "$_headers"
|
_debug2 _headers "$_headers"
|
||||||
_CACHED_NONCE="$(echo "$_headers" | grep -i "Replay-Nonce:" | _head_n 1 | tr -d "\r\n " | cut -d ':' -f 2)"
|
_CACHED_NONCE="$(echo "$_headers" | grep -i "Replay-Nonce:" | _head_n 1 | tr -d "\r\n " | cut -d ':' -f 2)"
|
||||||
fi
|
fi
|
||||||
_debug2 _CACHED_NONCE "$_CACHED_NONCE"
|
|
||||||
if [ "$?" != "0" ]; then
|
if [ "$?" != "0" ]; then
|
||||||
_err "Cannot connect to $nonceurl to get nonce."
|
_err "Cannot connect to $nonceurl to get nonce."
|
||||||
return 1
|
return 1
|
||||||
@@ -2305,6 +2358,7 @@ _setopt() {
|
|||||||
fi
|
fi
|
||||||
if [ ! -f "$__conf" ]; then
|
if [ ! -f "$__conf" ]; then
|
||||||
touch "$__conf"
|
touch "$__conf"
|
||||||
|
chmod 600 "$__conf"
|
||||||
fi
|
fi
|
||||||
if [ -n "$(_tail_c 1 <"$__conf")" ]; then
|
if [ -n "$(_tail_c 1 <"$__conf")" ]; then
|
||||||
echo >>"$__conf"
|
echo >>"$__conf"
|
||||||
@@ -2361,7 +2415,7 @@ _clear_conf() {
|
|||||||
_sdkey="$2"
|
_sdkey="$2"
|
||||||
if [ "$_c_c_f" ]; then
|
if [ "$_c_c_f" ]; then
|
||||||
_conf_data="$(cat "$_c_c_f")"
|
_conf_data="$(cat "$_c_c_f")"
|
||||||
echo "$_conf_data" | sed "s/^$_sdkey *=.*$//" >"$_c_c_f"
|
echo "$_conf_data" | sed "/^$_sdkey *=.*$/d" >"$_c_c_f"
|
||||||
else
|
else
|
||||||
_err "Config file is empty, cannot clear"
|
_err "Config file is empty, cannot clear"
|
||||||
fi
|
fi
|
||||||
@@ -2513,18 +2567,23 @@ _startserver() {
|
|||||||
_debug Le_Listen_V4 "$Le_Listen_V4"
|
_debug Le_Listen_V4 "$Le_Listen_V4"
|
||||||
_debug Le_Listen_V6 "$Le_Listen_V6"
|
_debug Le_Listen_V6 "$Le_Listen_V6"
|
||||||
|
|
||||||
|
if _exists "socat"; then
|
||||||
_NC="socat"
|
_NC="socat"
|
||||||
if [ "$Le_Listen_V6" ]; then
|
if [ "$Le_Listen_V6" ]; then
|
||||||
_NC="$_NC -6"
|
_NC="$_NC -6"
|
||||||
else
|
SOCAT_OPTIONS=TCP6-LISTEN
|
||||||
|
elif [ "$Le_Listen_V4" ]; then
|
||||||
_NC="$_NC -4"
|
_NC="$_NC -4"
|
||||||
|
SOCAT_OPTIONS=TCP4-LISTEN
|
||||||
|
else
|
||||||
|
SOCAT_OPTIONS=TCP-LISTEN
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ "$DEBUG" ] && [ "$DEBUG" -gt "1" ]; then
|
if [ "$DEBUG" ] && [ "$DEBUG" -gt "1" ]; then
|
||||||
_NC="$_NC -d -d -v"
|
_NC="$_NC -d -d -v"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
SOCAT_OPTIONS=TCP-LISTEN:$Le_HTTPPort,crlf,reuseaddr,fork
|
SOCAT_OPTIONS=$SOCAT_OPTIONS:$Le_HTTPPort,crlf,reuseaddr,fork
|
||||||
|
|
||||||
#Adding bind to local-address
|
#Adding bind to local-address
|
||||||
if [ "$ncaddr" ]; then
|
if [ "$ncaddr" ]; then
|
||||||
@@ -2541,9 +2600,43 @@ echo 'Content-Length\: $_content_len'; \
|
|||||||
echo ''; \
|
echo ''; \
|
||||||
printf '%s' '$content';" 2>"$_SOCAT_ERR" &
|
printf '%s' '$content';" 2>"$_SOCAT_ERR" &
|
||||||
serverproc="$!"
|
serverproc="$!"
|
||||||
|
else
|
||||||
|
_PYTHON=""
|
||||||
|
if _exists "python3"; then
|
||||||
|
_PYTHON="python3"
|
||||||
|
elif _exists "python2"; then
|
||||||
|
_PYTHON="python2"
|
||||||
|
elif _exists "python"; then
|
||||||
|
_PYTHON="python"
|
||||||
|
fi
|
||||||
|
if [ "$_PYTHON" ]; then
|
||||||
|
_debug "Using python: $_PYTHON"
|
||||||
|
_AF="socket.AF_INET"
|
||||||
|
_BIND_ADDR="0.0.0.0"
|
||||||
|
if [ "$Le_Listen_V6" ]; then
|
||||||
|
_AF="socket.AF_INET6"
|
||||||
|
_BIND_ADDR="::"
|
||||||
|
fi
|
||||||
|
if [ "$ncaddr" ]; then
|
||||||
|
_BIND_ADDR="$ncaddr"
|
||||||
|
fi
|
||||||
|
export _SOCAT_ERR="$(_mktemp)"
|
||||||
|
$_PYTHON -c "import socket,sys;s=socket.socket($_AF,socket.SOCK_STREAM);s.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1);s.bind((sys.argv[2],int(sys.argv[1])));s.listen(5);res='HTTP/1.0 200 OK\r\nContent-Length: '+str(len(sys.argv[3]))+'\r\n\r\n'+sys.argv[3];
|
||||||
|
while True:
|
||||||
|
c,a=s.accept()
|
||||||
|
c.sendall(res.encode() if hasattr(res, 'encode') else res)
|
||||||
|
c.close()" "$Le_HTTPPort" "$_BIND_ADDR" "$content" 2>"$_SOCAT_ERR" &
|
||||||
|
serverproc="$!"
|
||||||
|
_NC="$_PYTHON"
|
||||||
|
else
|
||||||
|
_err "Please install socat or python first for standalone mode."
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
if [ -f "$_SOCAT_ERR" ]; then
|
if [ -f "$_SOCAT_ERR" ]; then
|
||||||
if grep "Permission denied" "$_SOCAT_ERR" >/dev/null; then
|
if grep "Permission denied" "$_SOCAT_ERR" >/dev/null; then
|
||||||
_err "socat: $(cat $_SOCAT_ERR)"
|
_err "$_NC: $(cat $_SOCAT_ERR)"
|
||||||
_err "Can not listen for user: $(whoami)"
|
_err "Can not listen for user: $(whoami)"
|
||||||
_err "Maybe try with root again?"
|
_err "Maybe try with root again?"
|
||||||
rm -f "$_SOCAT_ERR"
|
rm -f "$_SOCAT_ERR"
|
||||||
@@ -2733,6 +2826,7 @@ _clearAPI() {
|
|||||||
ACME_REVOKE_CERT=""
|
ACME_REVOKE_CERT=""
|
||||||
ACME_NEW_NONCE=""
|
ACME_NEW_NONCE=""
|
||||||
ACME_AGREEMENT=""
|
ACME_AGREEMENT=""
|
||||||
|
ACME_RENEWAL_INFO=""
|
||||||
}
|
}
|
||||||
|
|
||||||
#server
|
#server
|
||||||
@@ -2745,7 +2839,7 @@ _initAPI() {
|
|||||||
_request_retry_times=0
|
_request_retry_times=0
|
||||||
while [ -z "$ACME_NEW_ACCOUNT" ] && [ "${_request_retry_times}" -lt "$MAX_API_RETRY_TIMES" ]; do
|
while [ -z "$ACME_NEW_ACCOUNT" ] && [ "${_request_retry_times}" -lt "$MAX_API_RETRY_TIMES" ]; do
|
||||||
_request_retry_times=$(_math "$_request_retry_times" + 1)
|
_request_retry_times=$(_math "$_request_retry_times" + 1)
|
||||||
response=$(_get "$_api_server")
|
response=$(_get "$_api_server" "" 10)
|
||||||
if [ "$?" != "0" ]; then
|
if [ "$?" != "0" ]; then
|
||||||
_debug2 "response" "$response"
|
_debug2 "response" "$response"
|
||||||
_info "Cannot init API for: $_api_server."
|
_info "Cannot init API for: $_api_server."
|
||||||
@@ -2777,6 +2871,9 @@ _initAPI() {
|
|||||||
ACME_AGREEMENT=$(echo "$response" | _egrep_o 'termsOfService" *: *"[^"]*"' | cut -d '"' -f 3)
|
ACME_AGREEMENT=$(echo "$response" | _egrep_o 'termsOfService" *: *"[^"]*"' | cut -d '"' -f 3)
|
||||||
export ACME_AGREEMENT
|
export ACME_AGREEMENT
|
||||||
|
|
||||||
|
ACME_RENEWAL_INFO=$(echo "$response" | _egrep_o 'renewalInfo" *: *"[^"]*"' | cut -d '"' -f 3)
|
||||||
|
export ACME_RENEWAL_INFO
|
||||||
|
|
||||||
_debug "ACME_KEY_CHANGE" "$ACME_KEY_CHANGE"
|
_debug "ACME_KEY_CHANGE" "$ACME_KEY_CHANGE"
|
||||||
_debug "ACME_NEW_AUTHZ" "$ACME_NEW_AUTHZ"
|
_debug "ACME_NEW_AUTHZ" "$ACME_NEW_AUTHZ"
|
||||||
_debug "ACME_NEW_ORDER" "$ACME_NEW_ORDER"
|
_debug "ACME_NEW_ORDER" "$ACME_NEW_ORDER"
|
||||||
@@ -2784,6 +2881,7 @@ _initAPI() {
|
|||||||
_debug "ACME_REVOKE_CERT" "$ACME_REVOKE_CERT"
|
_debug "ACME_REVOKE_CERT" "$ACME_REVOKE_CERT"
|
||||||
_debug "ACME_AGREEMENT" "$ACME_AGREEMENT"
|
_debug "ACME_AGREEMENT" "$ACME_AGREEMENT"
|
||||||
_debug "ACME_NEW_NONCE" "$ACME_NEW_NONCE"
|
_debug "ACME_NEW_NONCE" "$ACME_NEW_NONCE"
|
||||||
|
_debug "ACME_RENEWAL_INFO" "$ACME_RENEWAL_INFO"
|
||||||
if [ "$ACME_NEW_ACCOUNT" ] && [ "$ACME_NEW_ORDER" ]; then
|
if [ "$ACME_NEW_ACCOUNT" ] && [ "$ACME_NEW_ORDER" ]; then
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
@@ -3491,7 +3589,7 @@ _on_before_issue() {
|
|||||||
_debug _chk_alt_domains "$_chk_alt_domains"
|
_debug _chk_alt_domains "$_chk_alt_domains"
|
||||||
#run pre hook
|
#run pre hook
|
||||||
if [ "$_chk_pre_hook" ]; then
|
if [ "$_chk_pre_hook" ]; then
|
||||||
_info "Runing pre hook:'$_chk_pre_hook'"
|
_info "Running pre hook:'$_chk_pre_hook'"
|
||||||
if ! (
|
if ! (
|
||||||
export Le_Domain="$_chk_main_domain"
|
export Le_Domain="$_chk_main_domain"
|
||||||
export Le_Alt="$_chk_alt_domains"
|
export Le_Alt="$_chk_alt_domains"
|
||||||
@@ -3502,9 +3600,9 @@ _on_before_issue() {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if _hasfield "$_chk_web_roots" "$NO_VALUE"; then
|
if _hasfield "$_chk_web_roots" "$NO_VALUE" && [ "$_chk_web_roots" = "$NO_VALUE" ]; then
|
||||||
if ! _exists "socat"; then
|
if ! _exists "socat" && ! _exists "python" && ! _exists "python2" && ! _exists "python3"; then
|
||||||
_err "Please install socat tools first."
|
_err "Please install socat or python tools first."
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@@ -4394,6 +4492,8 @@ issue() {
|
|||||||
_preferred_chain="${15}"
|
_preferred_chain="${15}"
|
||||||
_valid_from="${16}"
|
_valid_from="${16}"
|
||||||
_valid_to="${17}"
|
_valid_to="${17}"
|
||||||
|
_certificate_profile="${18}"
|
||||||
|
_extended_key_usage="${19}"
|
||||||
|
|
||||||
if [ -z "$_ACME_IS_RENEW" ]; then
|
if [ -z "$_ACME_IS_RENEW" ]; then
|
||||||
_initpath "$_main_domain" "$_key_length"
|
_initpath "$_main_domain" "$_key_length"
|
||||||
@@ -4413,7 +4513,7 @@ issue() {
|
|||||||
Le_NextRenewTime=$(_readdomainconf Le_NextRenewTime)
|
Le_NextRenewTime=$(_readdomainconf Le_NextRenewTime)
|
||||||
_debug Le_NextRenewTime "$Le_NextRenewTime"
|
_debug Le_NextRenewTime "$Le_NextRenewTime"
|
||||||
if [ -z "$FORCE" ] && [ "$Le_NextRenewTime" ] && [ "$(_time)" -lt "$Le_NextRenewTime" ]; then
|
if [ -z "$FORCE" ] && [ "$Le_NextRenewTime" ] && [ "$(_time)" -lt "$Le_NextRenewTime" ]; then
|
||||||
_valid_to_saved=$(_readdomainconf Le_Valid_to)
|
_valid_to_saved=$(_readdomainconf Le_Valid_To)
|
||||||
if [ "$_valid_to_saved" ] && ! _startswith "$_valid_to_saved" "+"; then
|
if [ "$_valid_to_saved" ] && ! _startswith "$_valid_to_saved" "+"; then
|
||||||
_info "The domain is set to be valid to: $_valid_to_saved"
|
_info "The domain is set to be valid to: $_valid_to_saved"
|
||||||
_info "It cannot be renewed automatically"
|
_info "It cannot be renewed automatically"
|
||||||
@@ -4469,6 +4569,11 @@ issue() {
|
|||||||
else
|
else
|
||||||
_cleardomainconf "Le_Preferred_Chain"
|
_cleardomainconf "Le_Preferred_Chain"
|
||||||
fi
|
fi
|
||||||
|
if [ "$_certificate_profile" ]; then
|
||||||
|
_savedomainconf "Le_Certificate_Profile" "$_certificate_profile"
|
||||||
|
else
|
||||||
|
_cleardomainconf "Le_Certificate_Profile"
|
||||||
|
fi
|
||||||
|
|
||||||
Le_API="$ACME_DIRECTORY"
|
Le_API="$ACME_DIRECTORY"
|
||||||
_savedomainconf "Le_API" "$Le_API"
|
_savedomainconf "Le_API" "$Le_API"
|
||||||
@@ -4480,6 +4585,7 @@ issue() {
|
|||||||
|
|
||||||
if ! _on_before_issue "$_web_roots" "$_main_domain" "$_alt_domains" "$_pre_hook" "$_local_addr"; then
|
if ! _on_before_issue "$_web_roots" "$_main_domain" "$_alt_domains" "$_pre_hook" "$_local_addr"; then
|
||||||
_err "_on_before_issue."
|
_err "_on_before_issue."
|
||||||
|
_on_issue_err "$_post_hook"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -4532,12 +4638,25 @@ issue() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
if ! _createcsr "$_main_domain" "$_alt_domains" "$CERT_KEY_PATH" "$CSR_PATH" "$DOMAIN_SSL_CONF"; then
|
_keyusage="$_extended_key_usage"
|
||||||
|
if [ "$Le_API" = "$CA_GOOGLE" ] || [ "$Le_API" = "$CA_GOOGLE_TEST" ]; then
|
||||||
|
if [ -z "$_keyusage" ]; then
|
||||||
|
#https://github.com/acmesh-official/acme.sh/issues/6610
|
||||||
|
#google accepts serverauth only
|
||||||
|
_keyusage="serverAuth"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
if ! _createcsr "$_main_domain" "$_alt_domains" "$CERT_KEY_PATH" "$CSR_PATH" "$DOMAIN_SSL_CONF" "" "$_keyusage"; then
|
||||||
_err "Error creating CSR."
|
_err "Error creating CSR."
|
||||||
_clearup
|
_clearup
|
||||||
_on_issue_err "$_post_hook"
|
_on_issue_err "$_post_hook"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
if [ "$_extended_key_usage" ]; then
|
||||||
|
_savedomainconf "Le_ExtKeyUse" "$_extended_key_usage"
|
||||||
|
else
|
||||||
|
_cleardomainconf "Le_ExtKeyUse"
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
_savedomainconf "Le_Keylength" "$_key_length"
|
_savedomainconf "Le_Keylength" "$_key_length"
|
||||||
@@ -4600,6 +4719,9 @@ issue() {
|
|||||||
if [ "$_notAfter" ]; then
|
if [ "$_notAfter" ]; then
|
||||||
_newOrderObj="$_newOrderObj,\"notAfter\": \"$_notAfter\""
|
_newOrderObj="$_newOrderObj,\"notAfter\": \"$_notAfter\""
|
||||||
fi
|
fi
|
||||||
|
if [ "$_certificate_profile" ]; then
|
||||||
|
_newOrderObj="$_newOrderObj,\"profile\": \"$_certificate_profile\""
|
||||||
|
fi
|
||||||
_debug "STEP 1, Ordering a Certificate"
|
_debug "STEP 1, Ordering a Certificate"
|
||||||
if ! _send_signed_request "$ACME_NEW_ORDER" "$_newOrderObj}"; then
|
if ! _send_signed_request "$ACME_NEW_ORDER" "$_newOrderObj}"; then
|
||||||
_err "Error creating new order."
|
_err "Error creating new order."
|
||||||
@@ -4739,7 +4861,8 @@ $_authorizations_map"
|
|||||||
_debug keyauthorization "$keyauthorization"
|
_debug keyauthorization "$keyauthorization"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
entry="$(echo "$response" | _egrep_o '[^\{]*"type":"'$vtype'"[^\}]*')"
|
# Fix for empty error objects in response which mess up the original code, adapted from fix suggested here: https://github.com/acmesh-official/acme.sh/issues/4933#issuecomment-1870499018
|
||||||
|
entry="$(echo "$response" | sed s/'"error":{}'/'"error":null'/ | _egrep_o '[^\{]*"type":"'$vtype'"[^\}]*')"
|
||||||
_debug entry "$entry"
|
_debug entry "$entry"
|
||||||
|
|
||||||
if [ -z "$keyauthorization" -a -z "$entry" ]; then
|
if [ -z "$keyauthorization" -a -z "$entry" ]; then
|
||||||
@@ -4989,9 +5112,11 @@ $_authorizations_map"
|
|||||||
|
|
||||||
_debug "Writing token: $token to $wellknown_path/$token"
|
_debug "Writing token: $token to $wellknown_path/$token"
|
||||||
|
|
||||||
mkdir -p "$wellknown_path"
|
# Ensure .well-known is visible to web server user/group
|
||||||
|
# https://github.com/Neilpang/acme.sh/pull/32
|
||||||
if ! printf "%s" "$keyauthorization" >"$wellknown_path/$token"; then
|
if ! (umask ugo+rx &&
|
||||||
|
mkdir -p "$wellknown_path" &&
|
||||||
|
printf "%s" "$keyauthorization" >"$wellknown_path/$token"); then
|
||||||
_err "$d: Cannot write token to file: $wellknown_path/$token"
|
_err "$d: Cannot write token to file: $wellknown_path/$token"
|
||||||
_clearupwebbroot "$_currentRoot" "$removelevel" "$token"
|
_clearupwebbroot "$_currentRoot" "$removelevel" "$token"
|
||||||
_clearup
|
_clearup
|
||||||
@@ -5111,6 +5236,19 @@ $_authorizations_map"
|
|||||||
_on_issue_err "$_post_hook" "$vlist"
|
_on_issue_err "$_post_hook" "$vlist"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
_retryafter=$(echo "$responseHeaders" | grep -i "^Retry-After *: *[0-9]\+ *" | cut -d : -f 2 | tr -d ' ' | tr -d '\r')
|
||||||
|
_sleep_overload_retry_sec=$_retryafter
|
||||||
|
if [ "$_sleep_overload_retry_sec" ]; then
|
||||||
|
if [ $_sleep_overload_retry_sec -le 600 ]; then
|
||||||
|
_sleep $_sleep_overload_retry_sec
|
||||||
|
else
|
||||||
|
_info "The retryafter=$_retryafter value is too large (> 600), will not retry anymore."
|
||||||
|
_clearupwebbroot "$_currentRoot" "$removelevel" "$token"
|
||||||
|
_clearup
|
||||||
|
_on_issue_err "$_post_hook" "$vlist"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
done
|
done
|
||||||
@@ -5152,6 +5290,16 @@ $_authorizations_map"
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
break
|
break
|
||||||
|
elif _contains "$response" "\"ready\""; then
|
||||||
|
_info "Order status is 'ready', let's sleep and retry."
|
||||||
|
_retryafter=$(echo "$responseHeaders" | grep -i "^Retry-After *:" | cut -d : -f 2 | tr -d ' ' | tr -d '\r')
|
||||||
|
_debug "_retryafter" "$_retryafter"
|
||||||
|
if [ "$_retryafter" ]; then
|
||||||
|
_info "Sleeping for $_retryafter seconds then retrying"
|
||||||
|
_sleep $_retryafter
|
||||||
|
else
|
||||||
|
_sleep 2
|
||||||
|
fi
|
||||||
elif _contains "$response" "\"processing\""; then
|
elif _contains "$response" "\"processing\""; then
|
||||||
_info "Order status is 'processing', let's sleep and retry."
|
_info "Order status is 'processing', let's sleep and retry."
|
||||||
_retryafter=$(echo "$responseHeaders" | grep -i "^Retry-After *:" | cut -d : -f 2 | tr -d ' ' | tr -d '\r')
|
_retryafter=$(echo "$responseHeaders" | grep -i "^Retry-After *:" | cut -d : -f 2 | tr -d ' ' | tr -d '\r')
|
||||||
@@ -5350,10 +5498,10 @@ $_authorizations_map"
|
|||||||
_savedomainconf "Le_NextRenewTime" "$Le_NextRenewTime"
|
_savedomainconf "Le_NextRenewTime" "$Le_NextRenewTime"
|
||||||
|
|
||||||
#convert to pkcs12
|
#convert to pkcs12
|
||||||
|
Le_PFXPassword="$(_readdomainconf Le_PFXPassword)"
|
||||||
if [ "$Le_PFXPassword" ]; then
|
if [ "$Le_PFXPassword" ]; then
|
||||||
_toPkcs "$CERT_PFX_PATH" "$CERT_KEY_PATH" "$CERT_PATH" "$CA_CERT_PATH" "$Le_PFXPassword"
|
_toPkcs "$CERT_PFX_PATH" "$CERT_KEY_PATH" "$CERT_PATH" "$CA_CERT_PATH" "$Le_PFXPassword"
|
||||||
fi
|
fi
|
||||||
export CERT_PFX_PATH
|
|
||||||
|
|
||||||
if [ "$_real_cert$_real_key$_real_ca$_reload_cmd$_real_fullchain" ]; then
|
if [ "$_real_cert$_real_key$_real_ca$_reload_cmd$_real_fullchain" ]; then
|
||||||
_savedomainconf "Le_RealCertPath" "$_real_cert"
|
_savedomainconf "Le_RealCertPath" "$_real_cert"
|
||||||
@@ -5421,10 +5569,6 @@ renew() {
|
|||||||
_info "Switching back to $CA_LETSENCRYPT_V2"
|
_info "Switching back to $CA_LETSENCRYPT_V2"
|
||||||
Le_API="$CA_LETSENCRYPT_V2"
|
Le_API="$CA_LETSENCRYPT_V2"
|
||||||
;;
|
;;
|
||||||
"$CA_BUYPASS_TEST")
|
|
||||||
_info "Switching back to $CA_BUYPASS"
|
|
||||||
Le_API="$CA_BUYPASS"
|
|
||||||
;;
|
|
||||||
"$CA_GOOGLE_TEST")
|
"$CA_GOOGLE_TEST")
|
||||||
_info "Switching back to $CA_GOOGLE"
|
_info "Switching back to $CA_GOOGLE"
|
||||||
Le_API="$CA_GOOGLE"
|
Le_API="$CA_GOOGLE"
|
||||||
@@ -5466,6 +5610,11 @@ renew() {
|
|||||||
Le_PostHook="$(_readdomainconf Le_PostHook)"
|
Le_PostHook="$(_readdomainconf Le_PostHook)"
|
||||||
Le_RenewHook="$(_readdomainconf Le_RenewHook)"
|
Le_RenewHook="$(_readdomainconf Le_RenewHook)"
|
||||||
Le_Preferred_Chain="$(_readdomainconf Le_Preferred_Chain)"
|
Le_Preferred_Chain="$(_readdomainconf Le_Preferred_Chain)"
|
||||||
|
Le_Certificate_Profile="$(_readdomainconf Le_Certificate_Profile)"
|
||||||
|
Le_Valid_From="$(_readdomainconf Le_Valid_From)"
|
||||||
|
Le_Valid_To="$(_readdomainconf Le_Valid_To)"
|
||||||
|
Le_ExtKeyUse="$(_readdomainconf Le_ExtKeyUse)"
|
||||||
|
|
||||||
# When renewing from an old version, the empty Le_Keylength means 2048.
|
# When renewing from an old version, the empty Le_Keylength means 2048.
|
||||||
# Note, do not use DEFAULT_DOMAIN_KEY_LENGTH as that value may change over
|
# Note, do not use DEFAULT_DOMAIN_KEY_LENGTH as that value may change over
|
||||||
# time but an empty value implies 2048 specifically.
|
# time but an empty value implies 2048 specifically.
|
||||||
@@ -5473,7 +5622,14 @@ renew() {
|
|||||||
if [ -z "$Le_Keylength" ]; then
|
if [ -z "$Le_Keylength" ]; then
|
||||||
Le_Keylength=2048
|
Le_Keylength=2048
|
||||||
fi
|
fi
|
||||||
issue "$Le_Webroot" "$Le_Domain" "$Le_Alt" "$Le_Keylength" "$Le_RealCertPath" "$Le_RealKeyPath" "$Le_RealCACertPath" "$Le_ReloadCmd" "$Le_RealFullChainPath" "$Le_PreHook" "$Le_PostHook" "$Le_RenewHook" "$Le_LocalAddress" "$Le_ChallengeAlias" "$Le_Preferred_Chain" "$Le_Valid_From" "$Le_Valid_To"
|
if [ "$CA_LETSENCRYPT_V2" = "$Le_API" ]; then
|
||||||
|
#letsencrypt doesn't support ocsp anymore
|
||||||
|
if [ "$Le_OCSP_Staple" ]; then
|
||||||
|
export Le_OCSP_Staple=""
|
||||||
|
_cleardomainconf Le_OCSP_Staple
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
issue "$Le_Webroot" "$Le_Domain" "$Le_Alt" "$Le_Keylength" "$Le_RealCertPath" "$Le_RealKeyPath" "$Le_RealCACertPath" "$Le_ReloadCmd" "$Le_RealFullChainPath" "$Le_PreHook" "$Le_PostHook" "$Le_RenewHook" "$Le_LocalAddress" "$Le_ChallengeAlias" "$Le_Preferred_Chain" "$Le_Valid_From" "$Le_Valid_To" "$Le_Certificate_Profile" "$Le_ExtKeyUse"
|
||||||
res="$?"
|
res="$?"
|
||||||
if [ "$res" != "0" ]; then
|
if [ "$res" != "0" ]; then
|
||||||
return "$res"
|
return "$res"
|
||||||
@@ -5640,6 +5796,10 @@ signcsr() {
|
|||||||
_local_addr="${11}"
|
_local_addr="${11}"
|
||||||
_challenge_alias="${12}"
|
_challenge_alias="${12}"
|
||||||
_preferred_chain="${13}"
|
_preferred_chain="${13}"
|
||||||
|
_valid_f="${14}"
|
||||||
|
_valid_t="${15}"
|
||||||
|
_cert_prof="${16}"
|
||||||
|
_en_key_usage="${17}"
|
||||||
|
|
||||||
_csrsubj=$(_readSubjectFromCSR "$_csrfile")
|
_csrsubj=$(_readSubjectFromCSR "$_csrfile")
|
||||||
if [ "$?" != "0" ]; then
|
if [ "$?" != "0" ]; then
|
||||||
@@ -5683,7 +5843,7 @@ signcsr() {
|
|||||||
_info "Copying CSR to: $CSR_PATH"
|
_info "Copying CSR to: $CSR_PATH"
|
||||||
cp "$_csrfile" "$CSR_PATH"
|
cp "$_csrfile" "$CSR_PATH"
|
||||||
|
|
||||||
issue "$_csrW" "$_csrsubj" "$_csrdomainlist" "$_csrkeylength" "$_real_cert" "$_real_key" "$_real_ca" "$_reload_cmd" "$_real_fullchain" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_addr" "$_challenge_alias" "$_preferred_chain"
|
issue "$_csrW" "$_csrsubj" "$_csrdomainlist" "$_csrkeylength" "$_real_cert" "$_real_key" "$_real_ca" "$_reload_cmd" "$_real_fullchain" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_addr" "$_challenge_alias" "$_preferred_chain" "$_valid_f" "$_valid_t" "$_cert_prof" "$_en_key_usage"
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -5734,9 +5894,10 @@ list() {
|
|||||||
_sep="|"
|
_sep="|"
|
||||||
if [ "$_raw" ]; then
|
if [ "$_raw" ]; then
|
||||||
if [ -z "$_domain" ]; then
|
if [ -z "$_domain" ]; then
|
||||||
printf "%s\n" "Main_Domain${_sep}KeyLength${_sep}SAN_Domains${_sep}CA${_sep}Created${_sep}Renew"
|
printf "%s\n" "Main_Domain${_sep}KeyLength${_sep}SAN_Domains${_sep}Profile${_sep}CA${_sep}Created${_sep}Renew"
|
||||||
fi
|
fi
|
||||||
for di in "${CERT_HOME}"/*.*/; do
|
for di in "${CERT_HOME}"/*.* "${CERT_HOME}"/*:*; do
|
||||||
|
[ -d "$di" ] || continue
|
||||||
d=$(basename "$di")
|
d=$(basename "$di")
|
||||||
_debug d "$d"
|
_debug d "$d"
|
||||||
(
|
(
|
||||||
@@ -5749,7 +5910,7 @@ list() {
|
|||||||
. "$DOMAIN_CONF"
|
. "$DOMAIN_CONF"
|
||||||
_ca="$(_getCAShortName "$Le_API")"
|
_ca="$(_getCAShortName "$Le_API")"
|
||||||
if [ -z "$_domain" ]; then
|
if [ -z "$_domain" ]; then
|
||||||
printf "%s\n" "$Le_Domain${_sep}\"$Le_Keylength\"${_sep}$Le_Alt${_sep}$_ca${_sep}$Le_CertCreateTimeStr${_sep}$Le_NextRenewTimeStr"
|
printf "%s\n" "$Le_Domain${_sep}\"$Le_Keylength\"${_sep}$Le_Alt${_sep}$Le_Certificate_Profile${_sep}$_ca${_sep}$Le_CertCreateTimeStr${_sep}$Le_NextRenewTimeStr"
|
||||||
else
|
else
|
||||||
if [ "$_domain" = "$d" ]; then
|
if [ "$_domain" = "$d" ]; then
|
||||||
cat "$DOMAIN_CONF"
|
cat "$DOMAIN_CONF"
|
||||||
@@ -5768,6 +5929,48 @@ list() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
list_profiles() {
|
||||||
|
_initpath
|
||||||
|
_initAPI
|
||||||
|
|
||||||
|
_l_server_url="$ACME_DIRECTORY"
|
||||||
|
_l_server_name="$(_getCAShortName "$_l_server_url")"
|
||||||
|
_info "Fetching profiles from $_l_server_name ($_l_server_url)..."
|
||||||
|
|
||||||
|
response=$(_get "$_l_server_url" "" 10)
|
||||||
|
if [ "$?" != "0" ]; then
|
||||||
|
_err "Failed to connect to CA directory: $_l_server_url"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
normalized_response=$(echo "$response" | _normalizeJson)
|
||||||
|
profiles_json=$(echo "$normalized_response" | _egrep_o '"profiles" *: *\{[^\}]*\}')
|
||||||
|
|
||||||
|
if [ -z "$profiles_json" ]; then
|
||||||
|
_info "The CA '$_l_server_name' does not publish certificate profiles via its directory endpoint."
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Strip the outer layer to get the key-value pairs
|
||||||
|
profiles_kv=$(echo "$profiles_json" | sed 's/"profiles" *: *{//' | sed 's/}$//' | tr ',' '\n')
|
||||||
|
|
||||||
|
printf "\n%-15s %s\n" "name" "info"
|
||||||
|
printf -- "--------------------------------------------------------------------\n"
|
||||||
|
|
||||||
|
_old_IFS="$IFS"
|
||||||
|
IFS='
|
||||||
|
'
|
||||||
|
for pair in $profiles_kv; do
|
||||||
|
# Trim quotes and whitespace
|
||||||
|
_name=$(echo "$pair" | cut -d: -f1 | tr -d '" \t')
|
||||||
|
_info_url=$(echo "$pair" | cut -d: -f2- | sed 's/^ *//' | tr -d '"')
|
||||||
|
printf "%-15s %s\n" "$_name" "$_info_url"
|
||||||
|
done
|
||||||
|
IFS="$_old_IFS"
|
||||||
|
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
_deploy() {
|
_deploy() {
|
||||||
_d="$1"
|
_d="$1"
|
||||||
_hooks="$2"
|
_hooks="$2"
|
||||||
@@ -5792,7 +5995,7 @@ _deploy() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! $d_command "$_d" "$CERT_KEY_PATH" "$CERT_PATH" "$CA_CERT_PATH" "$CERT_FULLCHAIN_PATH"; then
|
if ! $d_command "$_d" "$CERT_KEY_PATH" "$CERT_PATH" "$CA_CERT_PATH" "$CERT_FULLCHAIN_PATH" "$CERT_PFX_PATH"; then
|
||||||
_err "Error deploying for domain: $_d"
|
_err "Error deploying for domain: $_d"
|
||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
@@ -5955,7 +6158,7 @@ _installcert() {
|
|||||||
); then
|
); then
|
||||||
_info "$(__green "Reload successful")"
|
_info "$(__green "Reload successful")"
|
||||||
else
|
else
|
||||||
_err "Reload error for: $Le_Domain"
|
_err "Reload error for: $_main_domain"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -6035,7 +6238,7 @@ installcronjob() {
|
|||||||
_script="$(_readlink "$_SCRIPT_")"
|
_script="$(_readlink "$_SCRIPT_")"
|
||||||
_debug _script "$_script"
|
_debug _script "$_script"
|
||||||
if [ -f "$_script" ]; then
|
if [ -f "$_script" ]; then
|
||||||
_info "Usinging the current script from: $_script"
|
_info "Using the current script from: $_script"
|
||||||
lesh="$_script"
|
lesh="$_script"
|
||||||
else
|
else
|
||||||
_err "Cannot install cronjob, $PROJECT_ENTRY not found."
|
_err "Cannot install cronjob, $PROJECT_ENTRY not found."
|
||||||
@@ -6306,7 +6509,8 @@ _deactivate() {
|
|||||||
fi
|
fi
|
||||||
_debug "Trigger validation."
|
_debug "Trigger validation."
|
||||||
vtype="$(_getIdType "$_d_domain")"
|
vtype="$(_getIdType "$_d_domain")"
|
||||||
entry="$(echo "$response" | _egrep_o '[^\{]*"type":"'$vtype'"[^\}]*')"
|
# Fix for empty error objects in response which mess up the original code, adapted from fix suggested here: https://github.com/acmesh-official/acme.sh/issues/4933#issuecomment-1870499018
|
||||||
|
entry="$(echo "$response" | sed s/'"error":{}'/'"error":null'/ | _egrep_o '[^\{]*"type":"'$vtype'"[^\}]*')"
|
||||||
_debug entry "$entry"
|
_debug entry "$entry"
|
||||||
if [ -z "$entry" ]; then
|
if [ -z "$entry" ]; then
|
||||||
_err "$d: Cannot get domain token"
|
_err "$d: Cannot get domain token"
|
||||||
@@ -6390,6 +6594,36 @@ deactivate() {
|
|||||||
done
|
done
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#cert
|
||||||
|
_getAKI() {
|
||||||
|
_cert="$1"
|
||||||
|
openssl x509 -in "$_cert" -text -noout | grep "X509v3 Authority Key Identifier" -A 1 | _tail_n 1 | tr -d ' :'
|
||||||
|
}
|
||||||
|
|
||||||
|
#cert
|
||||||
|
_getSerial() {
|
||||||
|
_cert="$1"
|
||||||
|
openssl x509 -in "$_cert" -serial -noout | cut -d = -f 2
|
||||||
|
}
|
||||||
|
|
||||||
|
#cert
|
||||||
|
_get_ARI() {
|
||||||
|
_cert="$1"
|
||||||
|
_aki=$(_getAKI "$_cert")
|
||||||
|
_ser=$(_getSerial "$_cert")
|
||||||
|
_debug2 "_aki" "$_aki"
|
||||||
|
_debug2 "_ser" "$_ser"
|
||||||
|
|
||||||
|
_akiurl="$(echo "$_aki" | _h2b | _base64 | tr -d = | _url_encode)"
|
||||||
|
_debug2 "_akiurl" "$_akiurl"
|
||||||
|
_serurl="$(echo "$_ser" | _h2b | _base64 | tr -d = | _url_encode)"
|
||||||
|
_debug2 "_serurl" "$_serurl"
|
||||||
|
|
||||||
|
_ARI_URL="$ACME_RENEWAL_INFO/$_akiurl.$_serurl"
|
||||||
|
_get "$_ARI_URL"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
# Detect profile file if not specified as environment variable
|
# Detect profile file if not specified as environment variable
|
||||||
_detect_profile() {
|
_detect_profile() {
|
||||||
if [ -n "$PROFILE" -a -f "$PROFILE" ]; then
|
if [ -n "$PROFILE" -a -f "$PROFILE" ]; then
|
||||||
@@ -6438,6 +6672,7 @@ _initconf() {
|
|||||||
#NO_TIMESTAMP=1
|
#NO_TIMESTAMP=1
|
||||||
|
|
||||||
" >"$ACCOUNT_CONF_PATH"
|
" >"$ACCOUNT_CONF_PATH"
|
||||||
|
chmod 600 "$ACCOUNT_CONF_PATH"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6473,9 +6708,9 @@ _precheck() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if ! _exists "socat"; then
|
if ! _exists "socat" && ! _exists "python" && ! _exists "python2" && ! _exists "python3"; then
|
||||||
_err "It is recommended to install socat first."
|
_err "It is recommended to install socat or python first."
|
||||||
_err "We use socat for the standalone server, which is used for standalone mode."
|
_err "We use socat or python for the standalone server, which is used for standalone mode."
|
||||||
_err "If you don't want to use standalone mode, you may ignore this warning."
|
_err "If you don't want to use standalone mode, you may ignore this warning."
|
||||||
fi
|
fi
|
||||||
|
|
||||||
@@ -6787,7 +7022,7 @@ _send_notify() {
|
|||||||
|
|
||||||
_nsource="$NOTIFY_SOURCE"
|
_nsource="$NOTIFY_SOURCE"
|
||||||
if [ -z "$_nsource" ]; then
|
if [ -z "$_nsource" ]; then
|
||||||
_nsource="$(hostname)"
|
_nsource="$(uname -n)"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
_nsubject="$_nsubject by $_nsource"
|
_nsubject="$_nsubject by $_nsource"
|
||||||
@@ -6945,6 +7180,9 @@ Parameters:
|
|||||||
If no match, the default offered chain will be used. (default: empty)
|
If no match, the default offered chain will be used. (default: empty)
|
||||||
See: $_PREFERRED_CHAIN_WIKI
|
See: $_PREFERRED_CHAIN_WIKI
|
||||||
|
|
||||||
|
--cert-profile, --certificate-profile <profile> If the CA offers profiles, select the desired profile
|
||||||
|
See: $_PROFILESELECTION_WIKI
|
||||||
|
|
||||||
--valid-to <date-time> Request the NotAfter field of the cert.
|
--valid-to <date-time> Request the NotAfter field of the cert.
|
||||||
See: $_VALIDITY_WIKI
|
See: $_VALIDITY_WIKI
|
||||||
--valid-from <date-time> Request the NotBefore field of the cert.
|
--valid-from <date-time> Request the NotBefore field of the cert.
|
||||||
@@ -6989,7 +7227,7 @@ Parameters:
|
|||||||
|
|
||||||
--accountconf <file> Specifies a customized account config file.
|
--accountconf <file> Specifies a customized account config file.
|
||||||
--home <directory> Specifies the home dir for $PROJECT_NAME.
|
--home <directory> Specifies the home dir for $PROJECT_NAME.
|
||||||
--cert-home <directory> Specifies the home dir to save all the certs, only valid for '--install' command.
|
--cert-home <directory> Specifies the home dir to save all the certs.
|
||||||
--config-home <directory> Specifies the home dir to save all the configurations.
|
--config-home <directory> Specifies the home dir to save all the configurations.
|
||||||
--useragent <string> Specifies the user agent string. it will be saved for future use too.
|
--useragent <string> Specifies the user agent string. it will be saved for future use too.
|
||||||
-m, --email <email> Specifies the account email, only valid for the '--install' and '--update-account' command.
|
-m, --email <email> Specifies the account email, only valid for the '--install' and '--update-account' command.
|
||||||
@@ -7021,6 +7259,8 @@ Parameters:
|
|||||||
--auto-upgrade [0|1] Valid for '--upgrade' command, indicating whether to upgrade automatically in future. Defaults to 1 if argument is omitted.
|
--auto-upgrade [0|1] Valid for '--upgrade' command, indicating whether to upgrade automatically in future. Defaults to 1 if argument is omitted.
|
||||||
--listen-v4 Force standalone/tls server to listen at ipv4.
|
--listen-v4 Force standalone/tls server to listen at ipv4.
|
||||||
--listen-v6 Force standalone/tls server to listen at ipv6.
|
--listen-v6 Force standalone/tls server to listen at ipv6.
|
||||||
|
--request-v4 Force client requests to use ipv4 to connect to the CA server.
|
||||||
|
--request-v6 Force client requests to use ipv6 to connect to the CA server.
|
||||||
--openssl-bin <file> Specifies a custom openssl bin location.
|
--openssl-bin <file> Specifies a custom openssl bin location.
|
||||||
--use-wget Force to use wget, if you have both curl and wget installed.
|
--use-wget Force to use wget, if you have both curl and wget installed.
|
||||||
--yes-I-know-dns-manual-mode-enough-go-ahead-please Force use of dns manual mode.
|
--yes-I-know-dns-manual-mode-enough-go-ahead-please Force use of dns manual mode.
|
||||||
@@ -7139,6 +7379,24 @@ _processAccountConf() {
|
|||||||
_saveaccountconf "ACME_USE_WGET" "$ACME_USE_WGET"
|
_saveaccountconf "ACME_USE_WGET" "$ACME_USE_WGET"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
if [ "$_request_v6" ]; then
|
||||||
|
_saveaccountconf "ACME_USE_IPV6_REQUESTS" "$_request_v6"
|
||||||
|
_clearaccountconf "ACME_USE_IPV4_REQUESTS"
|
||||||
|
ACME_USE_IPV4_REQUESTS=
|
||||||
|
elif [ "$_request_v4" ]; then
|
||||||
|
_saveaccountconf "ACME_USE_IPV4_REQUESTS" "$_request_v4"
|
||||||
|
_clearaccountconf "ACME_USE_IPV6_REQUESTS"
|
||||||
|
ACME_USE_IPV6_REQUESTS=
|
||||||
|
elif [ "$ACME_USE_IPV6_REQUESTS" ]; then
|
||||||
|
_saveaccountconf "ACME_USE_IPV6_REQUESTS" "$ACME_USE_IPV6_REQUESTS"
|
||||||
|
_clearaccountconf "ACME_USE_IPV4_REQUESTS"
|
||||||
|
ACME_USE_IPV4_REQUESTS=
|
||||||
|
elif [ "$ACME_USE_IPV4_REQUESTS" ]; then
|
||||||
|
_saveaccountconf "ACME_USE_IPV4_REQUESTS" "$ACME_USE_IPV4_REQUESTS"
|
||||||
|
_clearaccountconf "ACME_USE_IPV6_REQUESTS"
|
||||||
|
ACME_USE_IPV6_REQUESTS=
|
||||||
|
fi
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_checkSudo() {
|
_checkSudo() {
|
||||||
@@ -7304,6 +7562,8 @@ _process() {
|
|||||||
_local_address=""
|
_local_address=""
|
||||||
_log_level=""
|
_log_level=""
|
||||||
_auto_upgrade=""
|
_auto_upgrade=""
|
||||||
|
_request_v4=""
|
||||||
|
_request_v6=""
|
||||||
_listen_v4=""
|
_listen_v4=""
|
||||||
_listen_v6=""
|
_listen_v6=""
|
||||||
_openssl_bin=""
|
_openssl_bin=""
|
||||||
@@ -7320,6 +7580,8 @@ _process() {
|
|||||||
_preferred_chain=""
|
_preferred_chain=""
|
||||||
_valid_from=""
|
_valid_from=""
|
||||||
_valid_to=""
|
_valid_to=""
|
||||||
|
_certificate_profile=""
|
||||||
|
_extended_key_usage=""
|
||||||
while [ ${#} -gt 0 ]; do
|
while [ ${#} -gt 0 ]; do
|
||||||
case "${1}" in
|
case "${1}" in
|
||||||
|
|
||||||
@@ -7423,6 +7685,9 @@ _process() {
|
|||||||
--set-default-chain)
|
--set-default-chain)
|
||||||
_CMD="setdefaultchain"
|
_CMD="setdefaultchain"
|
||||||
;;
|
;;
|
||||||
|
--list-profiles)
|
||||||
|
_CMD="list_profiles"
|
||||||
|
;;
|
||||||
-d | --domain)
|
-d | --domain)
|
||||||
_dvalue="$2"
|
_dvalue="$2"
|
||||||
|
|
||||||
@@ -7638,6 +7903,10 @@ _process() {
|
|||||||
_valid_to="$2"
|
_valid_to="$2"
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
|
--certificate-profile | --cert-profile)
|
||||||
|
_certificate_profile="$2"
|
||||||
|
shift
|
||||||
|
;;
|
||||||
--httpport)
|
--httpport)
|
||||||
_httpport="$2"
|
_httpport="$2"
|
||||||
Le_HTTPPort="$_httpport"
|
Le_HTTPPort="$_httpport"
|
||||||
@@ -7708,7 +7977,7 @@ _process() {
|
|||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
--extended-key-usage)
|
--extended-key-usage)
|
||||||
Le_ExtKeyUse="$2"
|
_extended_key_usage="$2"
|
||||||
shift
|
shift
|
||||||
;;
|
;;
|
||||||
--ocsp-must-staple | --ocsp)
|
--ocsp-must-staple | --ocsp)
|
||||||
@@ -7761,6 +8030,18 @@ _process() {
|
|||||||
fi
|
fi
|
||||||
AUTO_UPGRADE="$_auto_upgrade"
|
AUTO_UPGRADE="$_auto_upgrade"
|
||||||
;;
|
;;
|
||||||
|
--request-v4)
|
||||||
|
_request_v4="1"
|
||||||
|
ACME_USE_IPV4_REQUESTS="1"
|
||||||
|
_request_v6=""
|
||||||
|
ACME_USE_IPV6_REQUESTS=""
|
||||||
|
;;
|
||||||
|
--request-v6)
|
||||||
|
_request_v6="1"
|
||||||
|
ACME_USE_IPV6_REQUESTS="1"
|
||||||
|
_request_v4=""
|
||||||
|
ACME_USE_IPV4_REQUESTS=""
|
||||||
|
;;
|
||||||
--listen-v4)
|
--listen-v4)
|
||||||
_listen_v4="1"
|
_listen_v4="1"
|
||||||
Le_Listen_V4="$_listen_v4"
|
Le_Listen_V4="$_listen_v4"
|
||||||
@@ -7913,13 +8194,13 @@ _process() {
|
|||||||
uninstall) uninstall "$_nocron" ;;
|
uninstall) uninstall "$_nocron" ;;
|
||||||
upgrade) upgrade ;;
|
upgrade) upgrade ;;
|
||||||
issue)
|
issue)
|
||||||
issue "$_webroot" "$_domain" "$_altdomains" "$_keylength" "$_cert_file" "$_key_file" "$_ca_file" "$_reloadcmd" "$_fullchain_file" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_address" "$_challenge_alias" "$_preferred_chain" "$_valid_from" "$_valid_to"
|
issue "$_webroot" "$_domain" "$_altdomains" "$_keylength" "$_cert_file" "$_key_file" "$_ca_file" "$_reloadcmd" "$_fullchain_file" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_address" "$_challenge_alias" "$_preferred_chain" "$_valid_from" "$_valid_to" "$_certificate_profile" "$_extended_key_usage"
|
||||||
;;
|
;;
|
||||||
deploy)
|
deploy)
|
||||||
deploy "$_domain" "$_deploy_hook" "$_ecc"
|
deploy "$_domain" "$_deploy_hook" "$_ecc"
|
||||||
;;
|
;;
|
||||||
signcsr)
|
signcsr)
|
||||||
signcsr "$_csr" "$_webroot" "$_cert_file" "$_key_file" "$_ca_file" "$_reloadcmd" "$_fullchain_file" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_address" "$_challenge_alias" "$_preferred_chain"
|
signcsr "$_csr" "$_webroot" "$_cert_file" "$_key_file" "$_ca_file" "$_reloadcmd" "$_fullchain_file" "$_pre_hook" "$_post_hook" "$_renew_hook" "$_local_address" "$_challenge_alias" "$_preferred_chain" "$_valid_from" "$_valid_to" "$_certificate_profile" "$_extended_key_usage"
|
||||||
;;
|
;;
|
||||||
showcsr)
|
showcsr)
|
||||||
showcsr "$_csr" "$_domain"
|
showcsr "$_csr" "$_domain"
|
||||||
@@ -7984,6 +8265,9 @@ _process() {
|
|||||||
setdefaultchain)
|
setdefaultchain)
|
||||||
setdefaultchain "$_preferred_chain"
|
setdefaultchain "$_preferred_chain"
|
||||||
;;
|
;;
|
||||||
|
list_profiles)
|
||||||
|
list_profiles
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
if [ "$_CMD" ]; then
|
if [ "$_CMD" ]; then
|
||||||
_err "Invalid command: $_CMD"
|
_err "Invalid command: $_CMD"
|
||||||
|
|||||||
955
.templates/bin/ssl-cert-check
Executable file
955
.templates/bin/ssl-cert-check
Executable file
@@ -0,0 +1,955 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
PROGRAMVERSION=4.14
|
||||||
|
#
|
||||||
|
# Program: SSL Certificate Check <ssl-cert-check>
|
||||||
|
#
|
||||||
|
# Source code home: https://github.com/Matty9191/ssl-cert-check
|
||||||
|
#
|
||||||
|
# Documentation: http://prefetch.net/articles/checkcertificate.html
|
||||||
|
#
|
||||||
|
# Author: Matty < matty at prefetch dot net >
|
||||||
|
#
|
||||||
|
# Last Updated: 11-12-2020
|
||||||
|
#
|
||||||
|
# Revision History:
|
||||||
|
#
|
||||||
|
# Version 4.14
|
||||||
|
# - Fixed HOST / PORT discovery @mhow2
|
||||||
|
#
|
||||||
|
# Version 4.13
|
||||||
|
# - Reverted the file checking logic which breaks $RETCODE
|
||||||
|
#
|
||||||
|
# Version 4.12
|
||||||
|
# - Fixed various logic errors and typos -- Daniel Lewart
|
||||||
|
#
|
||||||
|
# Version 4.10
|
||||||
|
# - Replace tabs with spaces
|
||||||
|
# - More shllcheck cleanup work
|
||||||
|
# - Remove unused DEBUG variable
|
||||||
|
# - Fixed an innocuous whitespace bug in TLSFLAG variable creation
|
||||||
|
# - Set the default TLS version to 1.1 (can be overridden with -v)
|
||||||
|
# - Switched openssl CLI options to use an array. The reasons why
|
||||||
|
# are documented here: http://mywiki.wooledge.org/BashFAQ/050
|
||||||
|
#
|
||||||
|
# Version 4.9
|
||||||
|
# - Add a signal handler to call the cleanup funtion
|
||||||
|
# if the script doesn't exit() cleanly -- Timothe Litt
|
||||||
|
#
|
||||||
|
# Version 4.8
|
||||||
|
# - More mail client fixes
|
||||||
|
#
|
||||||
|
# Version 4.7
|
||||||
|
# - Revert SENDER to ""
|
||||||
|
# - More shellcheck cleanup
|
||||||
|
#
|
||||||
|
# Version 4.6
|
||||||
|
# - Fixed programming logic error
|
||||||
|
#
|
||||||
|
# Version 4.5
|
||||||
|
# - Re-work mailx support for FreeBSD
|
||||||
|
# - More shellcheck fixes
|
||||||
|
#
|
||||||
|
# Version 4.4
|
||||||
|
# - Use command -v instead of which utility to satisfy shellcheck.
|
||||||
|
# - Fix unquoted MAIL and MAILMODE variables in help output
|
||||||
|
# - More shellcheck fixes
|
||||||
|
#
|
||||||
|
# Version 4.3
|
||||||
|
# - Fixed a typo in the program version
|
||||||
|
#
|
||||||
|
# Version 4.2
|
||||||
|
# - Change CERTDAYS to CERTDIFF in the e-mail subject.
|
||||||
|
#
|
||||||
|
# Version 4.1
|
||||||
|
# - Fix usage output
|
||||||
|
#
|
||||||
|
# Version 4.0
|
||||||
|
# - Updated the script syntax to align with UNIX shell programming
|
||||||
|
# - Check for DNS resolution failures
|
||||||
|
# - First round of updates to make shellcheck happy
|
||||||
|
# - Rework the logic to call mailx.
|
||||||
|
# - Print the version with the "-V" option.
|
||||||
|
# - Define the version in the PROGRAMVERSION variable
|
||||||
|
#
|
||||||
|
# Version 3.31
|
||||||
|
# - Fixed the test for the -servername flag -- Kitson Consulting.
|
||||||
|
#
|
||||||
|
# Version 3.30
|
||||||
|
# - Use highest returncode for Nagios output -- Marcel Pennewiss
|
||||||
|
# - Set RETCODE to 3 (unknown) if a certificate file does not exist -- Marcel Pennewiss
|
||||||
|
# - Add a "-d" option to specify a directory or file mask pattern -- Marcel Pennewiss
|
||||||
|
# - Add a "-N" option to create summarized Nagios output -- Marcel Pennewiss
|
||||||
|
# - Cleaned up many formatting -- Marcel Pennewiss
|
||||||
|
#
|
||||||
|
# Versione 3.29a
|
||||||
|
# - Added option to specify email sender address
|
||||||
|
#
|
||||||
|
# Version 3.29
|
||||||
|
# - Add the openssl -servername flag if it shows up in help.
|
||||||
|
#
|
||||||
|
# Version 3.28
|
||||||
|
# - Added a DEBUG option to assist with debugging folks who use the script
|
||||||
|
#
|
||||||
|
# Version 3.27
|
||||||
|
# - Allow white spaces to exist in the certificate file list
|
||||||
|
# - Add an additional check to pick up bad / non-existent certificates
|
||||||
|
# - Add a check to look for the existence of a mail program. Error out if it's not present.
|
||||||
|
# - Enable the TLS -servername extension by default - Juergen Knaack & Johan Denoyer
|
||||||
|
#
|
||||||
|
# Version 3.26
|
||||||
|
# - Allow the certificate type (PEM, DER, NET) to be passed on the command line
|
||||||
|
#
|
||||||
|
# Version 3.25
|
||||||
|
# - Check for "no route to host" errors -- Dan Doyle
|
||||||
|
# - Set RETCODE to 3 (unknown) if a connection error occurs -- Dan Doyle
|
||||||
|
# - Documentation fixes
|
||||||
|
#
|
||||||
|
# Version 3.24
|
||||||
|
# - Utilize the -clcerts option to limit the results to client certificates - Eitan Katznelson
|
||||||
|
#
|
||||||
|
# Version 3.23
|
||||||
|
# - Fixed typo in date2julian routine -- Ken Cook
|
||||||
|
#
|
||||||
|
# Version 3.22
|
||||||
|
# - Change the validation option to "-V"
|
||||||
|
# - Add a "-v" option to specify a specific protocol version (ssl2, ssl3 or tls)
|
||||||
|
#
|
||||||
|
# Version 3.21
|
||||||
|
# - Adjust e-mail checking to avoid exiting if notifications aren't enabled -- Nick Anderson
|
||||||
|
# - Added the number of days until expiration to the Nagios output -- Nick Anderson
|
||||||
|
#
|
||||||
|
# Version 3.20
|
||||||
|
# - Fixed a bug in certificate length checking -- Tim Nowaczyk
|
||||||
|
#
|
||||||
|
# Version 3.19
|
||||||
|
# - Added check to verify the certificate retrieved is valid
|
||||||
|
#
|
||||||
|
# Version 3.18
|
||||||
|
# - Add support for connecting to FTP servers -- Paul A Sand
|
||||||
|
#
|
||||||
|
# Version 3.17
|
||||||
|
# - Add support for connecting to imap servers -- Joerg Pareigis
|
||||||
|
#
|
||||||
|
# Version 3.16
|
||||||
|
# - Add support for connecting to the mail sbmission port -- Luis E. Munoz
|
||||||
|
#
|
||||||
|
# Version 3.15
|
||||||
|
# - Adjusted the file checking logic to use the correct certificate -- Maciej Szudejko
|
||||||
|
# - Add sbin to the default search paths for OpenBSD compatibility -- Alex Popov
|
||||||
|
# - Use cut instead of substring processing to ensure compatibility -- Alex Popov
|
||||||
|
#
|
||||||
|
# Version 3.14
|
||||||
|
# - Fixed the Common Name parser to handle DN's where the CN is not the last item
|
||||||
|
# eg. EmailAddr -- Jason Brothers
|
||||||
|
# - Added the ability to grab the serial number -- Jason Brothers
|
||||||
|
# - Added the "-b" option to print results without a header -- Jason Brothers
|
||||||
|
# - Added the "-v" option for certificate validation -- Jason Brothers
|
||||||
|
#
|
||||||
|
# Version 3.13
|
||||||
|
# - Updated the subject line to include the hostname as well as
|
||||||
|
# the common name embedded in the X509 certificate (if it's
|
||||||
|
# available) -- idea proposed by Mike Burns
|
||||||
|
#
|
||||||
|
# Version 3.12
|
||||||
|
# - Updated the license to allow redistribution and modification
|
||||||
|
#
|
||||||
|
# Version 3.11
|
||||||
|
# - Added ability to comment out lines in files passed
|
||||||
|
# to the "-f" option -- Brett Stauner
|
||||||
|
# - Fixed comment next to file processing logic
|
||||||
|
#
|
||||||
|
# Version 3.10
|
||||||
|
# - Fixed POP3 port -- Simon Matter
|
||||||
|
#
|
||||||
|
# Version 3.9
|
||||||
|
# - Switched binary location logic to use which utility
|
||||||
|
#
|
||||||
|
# Version 3.8
|
||||||
|
# - Fixed display on 80 column displays
|
||||||
|
# - Cleaned up the formatting
|
||||||
|
#
|
||||||
|
# Version 3.7
|
||||||
|
# - Fixed bug in NAGIOS tests -- Ben Allen
|
||||||
|
#
|
||||||
|
# Version 3.6
|
||||||
|
# - Added support for certificates stored in PKCS#12 databases -- Ken Gallo
|
||||||
|
# - Cleaned up comments
|
||||||
|
# - Adjusted variables to be more consistent
|
||||||
|
#
|
||||||
|
# Version 3.5
|
||||||
|
# - Added support for NAGIOS -- Quanah Gibson-Mount
|
||||||
|
# - Added additional checks for mail -- Quanah Gibson-Mount
|
||||||
|
# - Convert tabs to spaces -- Quanah Gibson-Mount
|
||||||
|
# - Cleaned up usage() routine
|
||||||
|
# - Added additional checks for openssl
|
||||||
|
#
|
||||||
|
# Version 3.4
|
||||||
|
# - Added a missing "{" to line 364 -- Ken Gallo
|
||||||
|
# - Move mktemp to the start of the main body to avoid errors
|
||||||
|
# - Adjusted default binary paths to make sure the script just works
|
||||||
|
# w/ Solaris, BSD and Linux hosts
|
||||||
|
#
|
||||||
|
# Version 3.3
|
||||||
|
# - Added common name from X.509 certificate file to E-mail body / header -- Doug Curtis
|
||||||
|
# - Fixed several documentation errors
|
||||||
|
# - Use mktemp to create temporary files
|
||||||
|
# - Convert printf, sed and awk to variables
|
||||||
|
# - Check for printf, sed, awk and mktemp binaries
|
||||||
|
# - Add additional logic to make sure mktemp returned a valid temporary file
|
||||||
|
#
|
||||||
|
# Version 3.2
|
||||||
|
# - Added option to list certificates in the file passed to "-f".
|
||||||
|
#
|
||||||
|
# Version 3.1
|
||||||
|
# - Added handling for starttls for smtp -- Marco Amrein
|
||||||
|
# - Added handling for starttls for pop3 (without s) -- Marco Amrein
|
||||||
|
# - Removed extra spacing at end of script
|
||||||
|
#
|
||||||
|
# Version 3.0
|
||||||
|
# - Added "-i" option to print certificate issuer
|
||||||
|
# - Removed $0 from Subject line of outbound e-mails
|
||||||
|
# - Fixed some typographical errors
|
||||||
|
# - Removed redundant "-b" option
|
||||||
|
#
|
||||||
|
# Version 2.0
|
||||||
|
# - Fixed an issue with e-mails formatting incorrectly
|
||||||
|
# - Added additional space to host column -- Darren-Perot Spruell
|
||||||
|
# - Replaced GNU date dependency with CHRIS F. A. JOHNSON's
|
||||||
|
# date2julian shell function. This routine can be found on
|
||||||
|
# page 170 of Chris's book "Shell Scripting Recipes: A
|
||||||
|
# Problem-Solution Approach," ISBN #1590594711. Julian function
|
||||||
|
# was created based on a post to comp.unix.shell by Tapani Tarvainen.
|
||||||
|
# - Cleaned up function descriptions
|
||||||
|
# - Removed several lines of redundant code
|
||||||
|
# - Adjusted the help message
|
||||||
|
#
|
||||||
|
# Version 1.1
|
||||||
|
# - Added "-c" flag to report expiration status of a PEM encoded
|
||||||
|
# certificate -- Hampus Lundqvist
|
||||||
|
# - Updated the prints messages to display the reason a connection
|
||||||
|
# failed (connection refused, connection timeout, bad cert, etc)
|
||||||
|
# - Updated the GNU date checking routines
|
||||||
|
# - Added checks for each binary required
|
||||||
|
# - Added checks for connection timeouts
|
||||||
|
# - Added checks for GNU date
|
||||||
|
# - Added a "-h" option
|
||||||
|
# - Cleaned up the documentation
|
||||||
|
#
|
||||||
|
# Version 1.0
|
||||||
|
# Initial Release
|
||||||
|
#
|
||||||
|
# Purpose:
|
||||||
|
# ssl-cert-check checks to see if a digital certificate in X.509 format
|
||||||
|
# has expired. ssl-cert-check can be run in interactive and batch mode,
|
||||||
|
# and provides facilities to alarm if a certificate is about to expire.
|
||||||
|
#
|
||||||
|
# License:
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 2 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# Requirements:
|
||||||
|
# Requires openssl
|
||||||
|
#
|
||||||
|
# Installation:
|
||||||
|
# Copy the shell script to a suitable location
|
||||||
|
#
|
||||||
|
# Tested platforms:
|
||||||
|
# -- Solaris 9 using /bin/bash
|
||||||
|
# -- Solaris 10 using /bin/bash
|
||||||
|
# -- OS X 10.4.2 using /bin/bash
|
||||||
|
# -- OpenBSD using /bin/sh
|
||||||
|
# -- FreeBSD using /bin/sh
|
||||||
|
# -- Centos Linux 3, 4, 5 & 6 using /bin/bash
|
||||||
|
# -- Redhat Enterprise Linux 3, 4, 5 & 6 using /bin/bash
|
||||||
|
# -- Gentoo using /bin/bash
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# Refer to the usage() sub-routine, or invoke ssl-cert-check
|
||||||
|
# with the "-h" option.
|
||||||
|
#
|
||||||
|
# Examples:
|
||||||
|
# Please refer to the following site for documentation and examples:
|
||||||
|
# http://prefetch.net/articles/checkcertificate.html
|
||||||
|
|
||||||
|
# Cleanup temp files if they exist
|
||||||
|
trap cleanup EXIT INT TERM QUIT
|
||||||
|
|
||||||
|
PATH=/bin:/usr/bin:/sbin:/usr/sbin:/usr/local/bin:/usr/local/ssl/bin:/usr/sfw/bin
|
||||||
|
export PATH
|
||||||
|
|
||||||
|
# Who to page when an expired certificate is detected (cmdline: -e)
|
||||||
|
ADMIN="root"
|
||||||
|
|
||||||
|
# Email sender address for alarm notifications
|
||||||
|
SENDER=""
|
||||||
|
|
||||||
|
# Number of days in the warning threshhold (cmdline: -x)
|
||||||
|
WARNDAYS=30
|
||||||
|
|
||||||
|
# If QUIET is set to TRUE, don't print anything on the console (cmdline: -q)
|
||||||
|
QUIET="FALSE"
|
||||||
|
|
||||||
|
# Don't send E-mail by default (cmdline: -a)
|
||||||
|
ALARM="FALSE"
|
||||||
|
|
||||||
|
# Don't run as a Nagios plugin by default (cmdline: -n)
|
||||||
|
NAGIOS="FALSE"
|
||||||
|
|
||||||
|
# Don't summarize Nagios output by default (cmdline: -N)
|
||||||
|
NAGIOSSUMMARY="FALSE"
|
||||||
|
|
||||||
|
# NULL out the PKCSDBPASSWD variable for later use (cmdline: -k)
|
||||||
|
PKCSDBPASSWD=""
|
||||||
|
|
||||||
|
# Type of certificate (PEM, DER, NET) (cmdline: -t)
|
||||||
|
CERTTYPE="pem"
|
||||||
|
|
||||||
|
# Location of system binaries
|
||||||
|
AWK=$(command -v awk)
|
||||||
|
DATE=$(command -v date)
|
||||||
|
GREP=$(command -v grep)
|
||||||
|
OPENSSL=$(command -v openssl)
|
||||||
|
PRINTF=$(command -v printf)
|
||||||
|
SED=$(command -v sed)
|
||||||
|
MKTEMP=$(command -v mktemp)
|
||||||
|
FIND=$(command -v find)
|
||||||
|
|
||||||
|
# Try to find a mail client
|
||||||
|
if [ -f /usr/bin/mailx ]; then
|
||||||
|
MAIL="/usr/bin/mailx"
|
||||||
|
MAILMODE="mailx"
|
||||||
|
elif [ -f /bin/mail ]; then
|
||||||
|
MAIL="/bin/mail"
|
||||||
|
MAILMODE="mail"
|
||||||
|
elif [ -f /usr/bin/mail ]; then
|
||||||
|
MAIL="/usr/bin/mail"
|
||||||
|
MAILMODE="mail"
|
||||||
|
elif [ -f /sbin/mail ]; then
|
||||||
|
MAIL="/sbin/mail"
|
||||||
|
MAILMODE="mail"
|
||||||
|
elif [ -f /usr/sbin/mail ]; then
|
||||||
|
MAIL="/usr/sbin/mail"
|
||||||
|
MAILMODE="mail"
|
||||||
|
elif [ -f /usr/sbin/sendmail ]; then
|
||||||
|
MAIL="/usr/sbin/sendmail"
|
||||||
|
MAILMODE="sendmail"
|
||||||
|
else
|
||||||
|
MAIL="cantfindit"
|
||||||
|
MAILMODE="cantfindit"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Return code used by nagios. Initialize to 0.
|
||||||
|
RETCODE=0
|
||||||
|
|
||||||
|
# Certificate counters and minimum difference. Initialize to 0.
|
||||||
|
SUMMARY_VALID=0
|
||||||
|
SUMMARY_WILL_EXPIRE=0
|
||||||
|
SUMMARY_EXPIRED=0
|
||||||
|
SUMMARY_MIN_DIFF=0
|
||||||
|
SUMMARY_MIN_DATE=
|
||||||
|
SUMMARY_MIN_HOST=
|
||||||
|
SUMMARY_MIN_PORT=
|
||||||
|
|
||||||
|
# Set the default umask to be somewhat restrictive
|
||||||
|
umask 077
|
||||||
|
|
||||||
|
|
||||||
|
#####################################################
|
||||||
|
# Purpose: Remove temporary files if the script doesn't
|
||||||
|
# exit() cleanly
|
||||||
|
#####################################################
|
||||||
|
cleanup() {
|
||||||
|
if [ -f "${CERT_TMP}" ]; then
|
||||||
|
rm -f "${CERT_TMP}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f "${ERROR_TMP}" ]; then
|
||||||
|
rm -f "${ERROR_TMP}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#####################################################
|
||||||
|
### Send email
|
||||||
|
### Accepts three parameters:
|
||||||
|
### $1 -> sender email address
|
||||||
|
### $2 -> email to send mail
|
||||||
|
### $3 -> Subject
|
||||||
|
### $4 -> Message
|
||||||
|
#####################################################
|
||||||
|
send_mail() {
|
||||||
|
|
||||||
|
FROM="${1}"
|
||||||
|
TO="${2}"
|
||||||
|
SUBJECT="${3}"
|
||||||
|
MSG="${4}"
|
||||||
|
|
||||||
|
case "${MAILMODE}" in
|
||||||
|
"mail")
|
||||||
|
echo "$MSG" | "${MAIL}" -r "$FROM" -s "$SUBJECT" "$TO"
|
||||||
|
;;
|
||||||
|
"mailx")
|
||||||
|
echo "$MSG" | "${MAIL}" -s "$SUBJECT" "$TO"
|
||||||
|
;;
|
||||||
|
"sendmail")
|
||||||
|
(echo "Subject:$SUBJECT" && echo "TO:$TO" && echo "FROM:$FROM" && echo "$MSG") | "${MAIL}" "$TO"
|
||||||
|
;;
|
||||||
|
"*")
|
||||||
|
echo "ERROR: You enabled automated alerts, but the mail binary could not be found."
|
||||||
|
echo "FIX: Please modify the \${MAIL} and \${MAILMODE} variable in the program header."
|
||||||
|
exit 1
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
# Purpose: Convert a date from MONTH-DAY-YEAR to Julian format
|
||||||
|
# Acknowledgements: Code was adapted from examples in the book
|
||||||
|
# "Shell Scripting Recipes: A Problem-Solution Approach"
|
||||||
|
# ( ISBN 1590594711 )
|
||||||
|
# Arguments:
|
||||||
|
# $1 -> Month (e.g., 06)
|
||||||
|
# $2 -> Day (e.g., 08)
|
||||||
|
# $3 -> Year (e.g., 2006)
|
||||||
|
#############################################################################
|
||||||
|
date2julian() {
|
||||||
|
|
||||||
|
if [ "${1}" != "" ] && [ "${2}" != "" ] && [ "${3}" != "" ]; then
|
||||||
|
## Since leap years add aday at the end of February,
|
||||||
|
## calculations are done from 1 March 0000 (a fictional year)
|
||||||
|
d2j_tmpmonth=$((12 * $3 + $1 - 3))
|
||||||
|
|
||||||
|
## If it is not yet March, the year is changed to the previous year
|
||||||
|
d2j_tmpyear=$(( d2j_tmpmonth / 12))
|
||||||
|
|
||||||
|
## The number of days from 1 March 0000 is calculated
|
||||||
|
## and the number of days from 1 Jan. 4713BC is added
|
||||||
|
echo $(( (734 * d2j_tmpmonth + 15) / 24
|
||||||
|
- 2 * d2j_tmpyear + d2j_tmpyear/4
|
||||||
|
- d2j_tmpyear/100 + d2j_tmpyear/400 + $2 + 1721119 ))
|
||||||
|
else
|
||||||
|
echo 0
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
# Purpose: Convert a string month into an integer representation
|
||||||
|
# Arguments:
|
||||||
|
# $1 -> Month name (e.g., Sep)
|
||||||
|
#############################################################################
|
||||||
|
getmonth()
|
||||||
|
{
|
||||||
|
case ${1} in
|
||||||
|
Jan) echo 1 ;;
|
||||||
|
Feb) echo 2 ;;
|
||||||
|
Mar) echo 3 ;;
|
||||||
|
Apr) echo 4 ;;
|
||||||
|
May) echo 5 ;;
|
||||||
|
Jun) echo 6 ;;
|
||||||
|
Jul) echo 7 ;;
|
||||||
|
Aug) echo 8 ;;
|
||||||
|
Sep) echo 9 ;;
|
||||||
|
Oct) echo 10 ;;
|
||||||
|
Nov) echo 11 ;;
|
||||||
|
Dec) echo 12 ;;
|
||||||
|
*) echo 0 ;;
|
||||||
|
esac
|
||||||
|
}
|
||||||
|
|
||||||
|
#############################################################################
|
||||||
|
# Purpose: Calculate the number of seconds between two dates
|
||||||
|
# Arguments:
|
||||||
|
# $1 -> Date #1
|
||||||
|
# $2 -> Date #2
|
||||||
|
#############################################################################
|
||||||
|
date_diff()
|
||||||
|
{
|
||||||
|
if [ "${1}" != "" ] && [ "${2}" != "" ]; then
|
||||||
|
echo $((${2} - ${1}))
|
||||||
|
else
|
||||||
|
echo 0
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################################################################
|
||||||
|
# Purpose: Print a line with the expiraton interval
|
||||||
|
# Arguments:
|
||||||
|
# $1 -> Hostname
|
||||||
|
# $2 -> TCP Port
|
||||||
|
# $3 -> Status of certification (e.g., expired or valid)
|
||||||
|
# $4 -> Date when certificate will expire
|
||||||
|
# $5 -> Days left until the certificate will expire
|
||||||
|
# $6 -> Issuer of the certificate
|
||||||
|
# $7 -> Common Name
|
||||||
|
# $8 -> Serial Number
|
||||||
|
#####################################################################
|
||||||
|
prints()
|
||||||
|
{
|
||||||
|
if [ "${NAGIOSSUMMARY}" = "TRUE" ]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${QUIET}" != "TRUE" ] && [ "${ISSUER}" = "TRUE" ] && [ "${VALIDATION}" != "TRUE" ]; then
|
||||||
|
MIN_DATE=$(echo "$4" | "${AWK}" '{ printf "%3s %2d %4d", $1, $2, $4 }')
|
||||||
|
if [ "${NAGIOS}" = "TRUE" ]; then
|
||||||
|
${PRINTF} "%-35s %-17s %-8s %-11s %s\n" "$1:$2" "$6" "$3" "$MIN_DATE" "|days=$5"
|
||||||
|
else
|
||||||
|
${PRINTF} "%-35s %-17s %-8s %-11s %4d\n" "$1:$2" "$6" "$3" "$MIN_DATE" "$5"
|
||||||
|
fi
|
||||||
|
elif [ "${QUIET}" != "TRUE" ] && [ "${ISSUER}" = "TRUE" ] && [ "${VALIDATION}" = "TRUE" ]; then
|
||||||
|
${PRINTF} "%-35s %-35s %-32s %-17s\n" "$1:$2" "$7" "$8" "$6"
|
||||||
|
|
||||||
|
elif [ "${QUIET}" != "TRUE" ] && [ "${VALIDATION}" != "TRUE" ]; then
|
||||||
|
MIN_DATE=$(echo "$4" | "${AWK}" '{ printf "%3s %2d, %4d", $1, $2, $4 }')
|
||||||
|
if [ "${NAGIOS}" = "TRUE" ]; then
|
||||||
|
${PRINTF} "%-47s %-12s %-12s %s\n" "$1:$2" "$3" "$MIN_DATE" "|days=$5"
|
||||||
|
else
|
||||||
|
${PRINTF} "%-47s %-12s %-12s %4d\n" "$1:$2" "$3" "$MIN_DATE" "$5"
|
||||||
|
fi
|
||||||
|
elif [ "${QUIET}" != "TRUE" ] && [ "${VALIDATION}" = "TRUE" ]; then
|
||||||
|
${PRINTF} "%-35s %-35s %-32s\n" "$1:$2" "$7" "$8"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
####################################################
|
||||||
|
# Purpose: Print a heading with the relevant columns
|
||||||
|
# Arguments:
|
||||||
|
# None
|
||||||
|
####################################################
|
||||||
|
print_heading()
|
||||||
|
{
|
||||||
|
if [ "${NOHEADER}" != "TRUE" ]; then
|
||||||
|
if [ "${QUIET}" != "TRUE" ] && [ "${ISSUER}" = "TRUE" ] && [ "${NAGIOS}" != "TRUE" ] && [ "${VALIDATION}" != "TRUE" ]; then
|
||||||
|
${PRINTF} "\n%-35s %-17s %-8s %-11s %-4s\n" "Host" "Issuer" "Status" "Expires" "Days"
|
||||||
|
echo "----------------------------------- ----------------- -------- ----------- ----"
|
||||||
|
|
||||||
|
elif [ "${QUIET}" != "TRUE" ] && [ "${ISSUER}" = "TRUE" ] && [ "${NAGIOS}" != "TRUE" ] && [ "${VALIDATION}" = "TRUE" ]; then
|
||||||
|
${PRINTF} "\n%-35s %-35s %-32s %-17s\n" "Host" "Common Name" "Serial #" "Issuer"
|
||||||
|
echo "----------------------------------- ----------------------------------- -------------------------------- -----------------"
|
||||||
|
|
||||||
|
elif [ "${QUIET}" != "TRUE" ] && [ "${NAGIOS}" != "TRUE" ] && [ "${VALIDATION}" != "TRUE" ]; then
|
||||||
|
${PRINTF} "\n%-47s %-12s %-12s %-4s\n" "Host" "Status" "Expires" "Days"
|
||||||
|
echo "----------------------------------------------- ------------ ------------ ----"
|
||||||
|
|
||||||
|
elif [ "${QUIET}" != "TRUE" ] && [ "${NAGIOS}" != "TRUE" ] && [ "${VALIDATION}" = "TRUE" ]; then
|
||||||
|
${PRINTF} "\n%-35s %-35s %-32s\n" "Host" "Common Name" "Serial #"
|
||||||
|
echo "----------------------------------- ----------------------------------- --------------------------------"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
####################################################
|
||||||
|
# Purpose: Print a summary for nagios
|
||||||
|
# Arguments:
|
||||||
|
# None
|
||||||
|
####################################################
|
||||||
|
print_summary()
|
||||||
|
{
|
||||||
|
if [ "${NAGIOSSUMMARY}" != "TRUE" ]; then
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ${SUMMARY_WILL_EXPIRE} -eq 0 ] && [ ${SUMMARY_EXPIRED} -eq 0 ]; then
|
||||||
|
${PRINTF} "%s valid certificate(s)|days=%s\n" "${SUMMARY_VALID}" "${SUMMARY_MIN_DIFF}"
|
||||||
|
|
||||||
|
elif [ ${SUMMARY_EXPIRED} -ne 0 ]; then
|
||||||
|
${PRINTF} "%s certificate(s) expired (%s:%s on %s)|days=%s\n" "${SUMMARY_EXPIRED}" "${SUMMARY_MIN_HOST}" "${SUMMARY_MIN_PORT}" "${SUMMARY_MIN_DATE}" "${SUMMARY_MIN_DIFF}"
|
||||||
|
|
||||||
|
elif [ ${SUMMARY_WILL_EXPIRE} -ne 0 ]; then
|
||||||
|
${PRINTF} "%s certificate(s) will expire (%s:%s on %s)|days=%s\n" "${SUMMARY_WILL_EXPIRE}" "${SUMMARY_MIN_HOST}" "${SUMMARY_MIN_PORT}" "${SUMMARY_MIN_DATE}" "${SUMMARY_MIN_DIFF}"
|
||||||
|
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
#############################################################
|
||||||
|
# Purpose: Set returncode to value if current value is lower
|
||||||
|
# Arguments:
|
||||||
|
# $1 -> New returncorde
|
||||||
|
#############################################################
|
||||||
|
set_returncode()
|
||||||
|
{
|
||||||
|
if [ "${RETCODE}" -lt "${1}" ]; then
|
||||||
|
RETCODE="${1}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
########################################################################
|
||||||
|
# Purpose: Set certificate counters and informations for nagios summary
|
||||||
|
# Arguments:
|
||||||
|
# $1 -> Status of certificate (0: valid, 1: will expire, 2: expired)
|
||||||
|
# $2 -> Hostname
|
||||||
|
# $3 -> TCP Port
|
||||||
|
# $4 -> Date when certificate will expire
|
||||||
|
# $5 -> Days left until the certificate will expire
|
||||||
|
########################################################################
|
||||||
|
set_summary()
|
||||||
|
{
|
||||||
|
if [ "${1}" -eq 0 ]; then
|
||||||
|
SUMMARY_VALID=$((SUMMARY_VALID+1))
|
||||||
|
elif [ "${1}" -eq 1 ]; then
|
||||||
|
SUMMARY_WILL_EXPIRE=$((SUMMARY_WILL_EXPIRE+1))
|
||||||
|
else
|
||||||
|
SUMMARY_EXPIRED=$((SUMMARY_EXPIRED+1))
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${5}" -lt "${SUMMARY_MIN_DIFF}" ] || [ "${SUMMARY_MIN_DIFF}" -eq 0 ]; then
|
||||||
|
SUMMARY_MIN_DATE="${4}"
|
||||||
|
SUMMARY_MIN_DIFF="${5}"
|
||||||
|
SUMMARY_MIN_HOST="${2}"
|
||||||
|
SUMMARY_MIN_PORT="${3}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
##########################################
|
||||||
|
# Purpose: Describe how the script works
|
||||||
|
# Arguments:
|
||||||
|
# None
|
||||||
|
##########################################
|
||||||
|
usage()
|
||||||
|
{
|
||||||
|
echo "Usage: $0 [ -e email address ] [-E sender email address] [ -x days ] [-q] [-a] [-b] [-h] [-i] [-n] [-N] [-v]"
|
||||||
|
echo " { [ -s common_name ] && [ -p port] } || { [ -f cert_file ] } || { [ -c cert file ] } || { [ -d cert dir ] }"
|
||||||
|
echo ""
|
||||||
|
echo " -a : Send a warning message through E-mail"
|
||||||
|
echo " -b : Will not print header"
|
||||||
|
echo " -c cert file : Print the expiration date for the PEM or PKCS12 formatted certificate in cert file"
|
||||||
|
echo " -d cert directory : Print the expiration date for the PEM or PKCS12 formatted certificates in cert directory"
|
||||||
|
echo " -e E-mail address : E-mail address to send expiration notices"
|
||||||
|
echo " -E E-mail sender : E-mail address of the sender"
|
||||||
|
echo " -f cert file : File with a list of FQDNs and ports"
|
||||||
|
echo " -h : Print this screen"
|
||||||
|
echo " -i : Print the issuer of the certificate"
|
||||||
|
echo " -k password : PKCS12 file password"
|
||||||
|
echo " -n : Run as a Nagios plugin"
|
||||||
|
echo " -N : Run as a Nagios plugin and output one line summary (implies -n, requires -f or -d)"
|
||||||
|
echo " -p port : Port to connect to (interactive mode)"
|
||||||
|
echo " -q : Don't print anything on the console"
|
||||||
|
echo " -s commmon name : Server to connect to (interactive mode)"
|
||||||
|
echo " -S : Print validation information"
|
||||||
|
echo " -t type : Specify the certificate type"
|
||||||
|
echo " -V : Print version information"
|
||||||
|
echo " -x days : Certificate expiration interval (eg. if cert_date < days)"
|
||||||
|
echo ""
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
##########################################################################
|
||||||
|
# Purpose: Connect to a server ($1) and port ($2) to see if a certificate
|
||||||
|
# has expired
|
||||||
|
# Arguments:
|
||||||
|
# $1 -> Server name
|
||||||
|
# $2 -> TCP port to connect to
|
||||||
|
##########################################################################
|
||||||
|
check_server_status() {
|
||||||
|
|
||||||
|
PORT="$2"
|
||||||
|
case "$PORT" in
|
||||||
|
smtp|25|submission|587) TLSFLAG="-starttls smtp";;
|
||||||
|
pop3|110) TLSFLAG="-starttls pop3";;
|
||||||
|
imap|143) TLSFLAG="-starttls imap";;
|
||||||
|
ftp|21) TLSFLAG="-starttls ftp";;
|
||||||
|
xmpp|5222) TLSFLAG="-starttls xmpp";;
|
||||||
|
xmpp-server|5269) TLSFLAG="-starttls xmpp-server";;
|
||||||
|
irc|194) TLSFLAG="-starttls irc";;
|
||||||
|
postgres|5432) TLSFLAG="-starttls postgres";;
|
||||||
|
mysql|3306) TLSFLAG="-starttls mysql";;
|
||||||
|
lmtp|24) TLSFLAG="-starttls lmtp";;
|
||||||
|
nntp|119) TLSFLAG="-starttls nntp";;
|
||||||
|
sieve|4190) TLSFLAG="-starttls sieve";;
|
||||||
|
ldap|389) TLSFLAG="-starttls ldap";;
|
||||||
|
*) TLSFLAG="";;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ "${TLSSERVERNAME}" = "FALSE" ]; then
|
||||||
|
OPTIONS="-connect ${1}:${2} $TLSFLAG"
|
||||||
|
else
|
||||||
|
OPTIONS="-connect ${1}:${2} -servername ${1} $TLSFLAG"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "" | "${OPENSSL}" s_client $OPTIONS 2> "${ERROR_TMP}" 1> "${CERT_TMP}"
|
||||||
|
|
||||||
|
if "${GREP}" -i "Connection refused" "${ERROR_TMP}" > /dev/null; then
|
||||||
|
prints "${1}" "${2}" "Connection refused" "Unknown"
|
||||||
|
set_returncode 3
|
||||||
|
elif "${GREP}" -i "No route to host" "${ERROR_TMP}" > /dev/null; then
|
||||||
|
prints "${1}" "${2}" "No route to host" "Unknown"
|
||||||
|
set_returncode 3
|
||||||
|
elif "${GREP}" -i "gethostbyname failure" "${ERROR_TMP}" > /dev/null; then
|
||||||
|
prints "${1}" "${2}" "Cannot resolve domain" "Unknown"
|
||||||
|
set_returncode 3
|
||||||
|
elif "${GREP}" -i "Operation timed out" "${ERROR_TMP}" > /dev/null; then
|
||||||
|
prints "${1}" "${2}" "Operation timed out" "Unknown"
|
||||||
|
set_returncode 3
|
||||||
|
elif "${GREP}" -i "ssl handshake failure" "${ERROR_TMP}" > /dev/null; then
|
||||||
|
prints "${1}" "${2}" "SSL handshake failed" "Unknown"
|
||||||
|
set_returncode 3
|
||||||
|
elif "${GREP}" -i "connect: Connection timed out" "${ERROR_TMP}" > /dev/null; then
|
||||||
|
prints "${1}" "${2}" "Connection timed out" "Unknown"
|
||||||
|
set_returncode 3
|
||||||
|
elif "${GREP}" -i "Name or service not known" "${ERROR_TMP}" > /dev/null; then
|
||||||
|
prints "${1}" "${2}" "Unable to resolve the DNS name ${1}" "Unknown"
|
||||||
|
set_returncode 3
|
||||||
|
else
|
||||||
|
check_file_status "${CERT_TMP}" "${1}" "${2}"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
#####################################################
|
||||||
|
### Check the expiration status of a certificate file
|
||||||
|
### Accepts three parameters:
|
||||||
|
### $1 -> certificate file to process
|
||||||
|
### $2 -> Server name
|
||||||
|
### $3 -> Port number of certificate
|
||||||
|
#####################################################
|
||||||
|
check_file_status() {
|
||||||
|
|
||||||
|
CERTFILE="${1}"
|
||||||
|
HOST="${2}"
|
||||||
|
PORT="${3}"
|
||||||
|
|
||||||
|
### Check to make sure the certificate file exists
|
||||||
|
if [ ! -r "${CERTFILE}" ] || [ ! -s "${CERTFILE}" ]; then
|
||||||
|
echo "ERROR: The file named ${CERTFILE} is unreadable or doesn't exist"
|
||||||
|
echo "ERROR: Please check to make sure the certificate for ${HOST}:${PORT} is valid"
|
||||||
|
set_returncode 3
|
||||||
|
return
|
||||||
|
fi
|
||||||
|
|
||||||
|
### Grab the expiration date from the X.509 certificate
|
||||||
|
if [ "${PKCSDBPASSWD}" != "" ]; then
|
||||||
|
# Extract the certificate from the PKCS#12 database, and
|
||||||
|
# send the informational message to /dev/null
|
||||||
|
"${OPENSSL}" pkcs12 -nokeys -in "${CERTFILE}" \
|
||||||
|
-out "${CERT_TMP}" -clcerts -password pass:"${PKCSDBPASSWD}" 2> /dev/null
|
||||||
|
|
||||||
|
# Extract the expiration date from the certificate
|
||||||
|
CERTDATE=$("${OPENSSL}" x509 -in "${CERT_TMP}" -enddate -noout | \
|
||||||
|
"${SED}" 's/notAfter\=//')
|
||||||
|
|
||||||
|
# Extract the issuer from the certificate
|
||||||
|
CERTISSUER=$("${OPENSSL}" x509 -in "${CERT_TMP}" -issuer -noout | \
|
||||||
|
"${AWK}" 'BEGIN {RS=", " } $0 ~ /^O =/
|
||||||
|
{ print substr($0,5,17)}')
|
||||||
|
|
||||||
|
### Grab the common name (CN) from the X.509 certificate
|
||||||
|
COMMONNAME=$("${OPENSSL}" x509 -in "${CERT_TMP}" -subject -noout | \
|
||||||
|
"${SED}" -e 's/.*CN = //' | \
|
||||||
|
"${SED}" -e 's/, .*//')
|
||||||
|
|
||||||
|
### Grab the serial number from the X.509 certificate
|
||||||
|
SERIAL=$("${OPENSSL}" x509 -in "${CERT_TMP}" -serial -noout | \
|
||||||
|
"${SED}" -e 's/serial=//')
|
||||||
|
else
|
||||||
|
# Extract the expiration date from the ceriticate
|
||||||
|
CERTDATE=$("${OPENSSL}" x509 -in "${CERTFILE}" -enddate -noout -inform "${CERTTYPE}" | \
|
||||||
|
"${SED}" 's/notAfter\=//')
|
||||||
|
|
||||||
|
# Extract the issuer from the certificate
|
||||||
|
CERTISSUER=$("${OPENSSL}" x509 -in "${CERTFILE}" -issuer -noout -inform "${CERTTYPE}" | \
|
||||||
|
"${AWK}" 'BEGIN {RS=", " } $0 ~ /^O =/ { print substr($0,5,17)}')
|
||||||
|
|
||||||
|
### Grab the common name (CN) from the X.509 certificate
|
||||||
|
COMMONNAME=$("${OPENSSL}" x509 -in "${CERTFILE}" -subject -noout -inform "${CERTTYPE}" | \
|
||||||
|
"${SED}" -e 's/.*CN = //' | \
|
||||||
|
"${SED}" -e 's/, .*//')
|
||||||
|
|
||||||
|
### Grab the serial number from the X.509 certificate
|
||||||
|
SERIAL=$("${OPENSSL}" x509 -in "${CERTFILE}" -serial -noout -inform "${CERTTYPE}" | \
|
||||||
|
"${SED}" -e 's/serial=//')
|
||||||
|
fi
|
||||||
|
|
||||||
|
### Split the result into parameters, and pass the relevant pieces to date2julian
|
||||||
|
set -- ${CERTDATE}
|
||||||
|
MONTH=$(getmonth "${1}")
|
||||||
|
|
||||||
|
# Convert the date to seconds, and get the diff between NOW and the expiration date
|
||||||
|
CERTJULIAN=$(date2julian "${MONTH#0}" "${2#0}" "${4}")
|
||||||
|
CERTDIFF=$(date_diff "${NOWJULIAN}" "${CERTJULIAN}")
|
||||||
|
|
||||||
|
if [ "${CERTDIFF}" -lt 0 ]; then
|
||||||
|
if [ "${ALARM}" = "TRUE" ]; then
|
||||||
|
send_mail "${SENDER}" "${ADMIN}" "Certificate for ${HOST} \"(CN: ${COMMONNAME})\" has expired!" \
|
||||||
|
"The SSL certificate for ${HOST} \"(CN: ${COMMONNAME})\" has expired!"
|
||||||
|
fi
|
||||||
|
|
||||||
|
prints "${HOST}" "${PORT}" "Expired" "${CERTDATE}" "${CERTDIFF}" "${CERTISSUER}" "${COMMONNAME}" "${SERIAL}"
|
||||||
|
RETCODE_LOCAL=2
|
||||||
|
|
||||||
|
elif [ "${CERTDIFF}" -lt "${WARNDAYS}" ]; then
|
||||||
|
if [ "${ALARM}" = "TRUE" ]; then
|
||||||
|
send_mail "${SENDER}" "${ADMIN}" "Certificate for ${HOST} \"(CN: ${COMMONNAME})\" will expire in ${CERTDIFF} days or less" \
|
||||||
|
"The SSL certificate for ${HOST} \"(CN: ${COMMONNAME})\" will expire on ${CERTDATE}"
|
||||||
|
fi
|
||||||
|
prints "${HOST}" "${PORT}" "Expiring" "${CERTDATE}" "${CERTDIFF}" "${CERTISSUER}" "${COMMONNAME}" "${SERIAL}"
|
||||||
|
RETCODE_LOCAL=1
|
||||||
|
|
||||||
|
else
|
||||||
|
prints "${HOST}" "${PORT}" "Valid" "${CERTDATE}" "${CERTDIFF}" "${CERTISSUER}" "${COMMONNAME}" "${SERIAL}"
|
||||||
|
RETCODE_LOCAL=0
|
||||||
|
fi
|
||||||
|
|
||||||
|
set_returncode "${RETCODE_LOCAL}"
|
||||||
|
MIN_DATE=$(echo "${CERTDATE}" | "${AWK}" '{ print $1, $2, $4 }')
|
||||||
|
set_summary "${RETCODE_LOCAL}" "${HOST}" "${PORT}" "${MIN_DATE}" "${CERTDIFF}"
|
||||||
|
}
|
||||||
|
|
||||||
|
#################################
|
||||||
|
### Start of main program
|
||||||
|
#################################
|
||||||
|
while getopts abc:d:e:E:f:hik:nNp:qs:St:Vx: option
|
||||||
|
do
|
||||||
|
case "${option}" in
|
||||||
|
a) ALARM="TRUE";;
|
||||||
|
b) NOHEADER="TRUE";;
|
||||||
|
c) CERTFILE=${OPTARG};;
|
||||||
|
d) CERTDIRECTORY=${OPTARG};;
|
||||||
|
e) ADMIN=${OPTARG};;
|
||||||
|
E) SENDER=${OPTARG};;
|
||||||
|
f) SERVERFILE=$OPTARG;;
|
||||||
|
h) usage
|
||||||
|
exit 1;;
|
||||||
|
i) ISSUER="TRUE";;
|
||||||
|
k) PKCSDBPASSWD=${OPTARG};;
|
||||||
|
n) NAGIOS="TRUE";;
|
||||||
|
N) NAGIOS="TRUE"
|
||||||
|
NAGIOSSUMMARY="TRUE";;
|
||||||
|
p) PORT=$OPTARG;;
|
||||||
|
q) QUIET="TRUE";;
|
||||||
|
s) HOST=$OPTARG;;
|
||||||
|
S) VALIDATION="TRUE";;
|
||||||
|
t) CERTTYPE=$OPTARG;;
|
||||||
|
V) echo "${PROGRAMVERSION}"
|
||||||
|
exit 0
|
||||||
|
;;
|
||||||
|
x) WARNDAYS=$OPTARG;;
|
||||||
|
\?) usage
|
||||||
|
exit 1;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
### Check to make sure a openssl utility is available
|
||||||
|
if [ ! -f "${OPENSSL}" ]; then
|
||||||
|
echo "ERROR: The openssl binary does not exist in ${OPENSSL}."
|
||||||
|
echo "FIX: Please modify the \${OPENSSL} variable in the program header."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
### Check to make sure a date utility is available
|
||||||
|
if [ ! -f "${DATE}" ]; then
|
||||||
|
echo "ERROR: The date binary does not exist in ${DATE} ."
|
||||||
|
echo "FIX: Please modify the \${DATE} variable in the program header."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
### Check to make sure a grep and find utility is available
|
||||||
|
if [ ! -f "${GREP}" ] || [ ! -f "${FIND}" ]; then
|
||||||
|
echo "ERROR: Unable to locate the grep and find binary."
|
||||||
|
echo "FIX: Please modify the \${GREP} and \${FIND} variables in the program header."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
### Check to make sure the mktemp and printf utilities are available
|
||||||
|
if [ ! -f "${MKTEMP}" ] || [ -z "${PRINTF}" ]; then
|
||||||
|
echo "ERROR: Unable to locate the mktemp or printf binary."
|
||||||
|
echo "FIX: Please modify the \${MKTEMP} and \${PRINTF} variables in the program header."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
### Check to make sure the sed and awk binaries are available
|
||||||
|
if [ ! -f "${SED}" ] || [ ! -f "${AWK}" ]; then
|
||||||
|
echo "ERROR: Unable to locate the sed or awk binary."
|
||||||
|
echo "FIX: Please modify the \${SED} and \${AWK} variables in the program header."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
### Check to make sure a mail client is available it automated notifications are requested
|
||||||
|
if [ "${ALARM}" = "TRUE" ] && [ ! -f "${MAIL}" ]; then
|
||||||
|
echo "ERROR: You enabled automated alerts, but the mail binary could not be found."
|
||||||
|
echo "FIX: Please modify the ${MAIL} variable in the program header."
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Send along the servername when TLS is used
|
||||||
|
if ${OPENSSL} s_client -help 2>&1 | grep '-servername' > /dev/null; then
|
||||||
|
TLSSERVERNAME="TRUE"
|
||||||
|
else
|
||||||
|
TLSSERVERNAME="FALSE"
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Place to stash temporary files
|
||||||
|
CERT_TMP=$($MKTEMP /var/tmp/cert.XXXXXX)
|
||||||
|
ERROR_TMP=$($MKTEMP /var/tmp/error.XXXXXX)
|
||||||
|
|
||||||
|
### Baseline the dates so we have something to compare to
|
||||||
|
MONTH=$(${DATE} "+%m")
|
||||||
|
DAY=$(${DATE} "+%d")
|
||||||
|
YEAR=$(${DATE} "+%Y")
|
||||||
|
NOWJULIAN=$(date2julian "${MONTH#0}" "${DAY#0}" "${YEAR}")
|
||||||
|
|
||||||
|
### Touch the files prior to using them
|
||||||
|
if [ -n "${CERT_TMP}" ] && [ -n "${ERROR_TMP}" ]; then
|
||||||
|
touch "${CERT_TMP}" "${ERROR_TMP}"
|
||||||
|
else
|
||||||
|
echo "ERROR: Problem creating temporary files"
|
||||||
|
echo "FIX: Check that mktemp works on your system"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
### If a HOST was passed on the cmdline, use that value
|
||||||
|
if [ "${HOST}" != "" ]; then
|
||||||
|
print_heading
|
||||||
|
check_server_status "${HOST}" "${PORT:=443}"
|
||||||
|
print_summary
|
||||||
|
### If a file is passed to the "-f" option on the command line, check
|
||||||
|
### each certificate or server / port combination in the file to see if
|
||||||
|
### they are about to expire
|
||||||
|
elif [ -f "${SERVERFILE}" ]; then
|
||||||
|
print_heading
|
||||||
|
|
||||||
|
IFS=$'\n'
|
||||||
|
for LINE in $(grep -E -v '(^#|^$)' "${SERVERFILE}")
|
||||||
|
do
|
||||||
|
HOST=${LINE%% *}
|
||||||
|
PORT=${LINE##* }
|
||||||
|
IFS=" "
|
||||||
|
if [ "$PORT" = "FILE" ]; then
|
||||||
|
check_file_status "${HOST}" "FILE" "${HOST}"
|
||||||
|
else
|
||||||
|
check_server_status "${HOST}" "${PORT}"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
IFS="${OLDIFS}"
|
||||||
|
print_summary
|
||||||
|
### Check to see if the certificate in CERTFILE is about to expire
|
||||||
|
elif [ "${CERTFILE}" != "" ]; then
|
||||||
|
print_heading
|
||||||
|
check_file_status "${CERTFILE}" "FILE" "${CERTFILE}"
|
||||||
|
print_summary
|
||||||
|
|
||||||
|
### Check to see if the certificates in CERTDIRECTORY are about to expire
|
||||||
|
elif [ "${CERTDIRECTORY}" != "" ] && ("${FIND}" -L "${CERTDIRECTORY}" -type f > /dev/null 2>&1); then
|
||||||
|
print_heading
|
||||||
|
for FILE in $("${FIND}" -L "${CERTDIRECTORY}" -type f); do
|
||||||
|
check_file_status "${FILE}" "FILE" "${FILE}"
|
||||||
|
done
|
||||||
|
print_summary
|
||||||
|
### There was an error, so print a detailed usage message and exit
|
||||||
|
else
|
||||||
|
usage
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
### Exit with a success indicator
|
||||||
|
if [ "${NAGIOS}" = "TRUE" ]; then
|
||||||
|
exit "${RETCODE}"
|
||||||
|
else
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
@@ -16,7 +16,7 @@ more_set_headers "X-Frame-Options: SAMEORIGIN";
|
|||||||
more_set_headers "X-Content-Type-Options: nosniff";
|
more_set_headers "X-Content-Type-Options: nosniff";
|
||||||
more_set_headers "Referrer-Policy: no-referrer-when-downgrade";
|
more_set_headers "Referrer-Policy: no-referrer-when-downgrade";
|
||||||
# These are dummy restrictions (meaningless headers) below.
|
# These are dummy restrictions (meaningless headers) below.
|
||||||
more_set_headers "Content-Security-Policy: img-src *";
|
more_set_headers "Content-Security-Policy: img-src * data: blob:; ";
|
||||||
more_set_headers "Permissions-Policy: geolocation=*";
|
more_set_headers "Permissions-Policy: geolocation=*";
|
||||||
|
|
||||||
# https://amalgjose.com/2020/05/15/how-to-set-the-allowed-url-length-for-a-nginx-request-error-code-414-uri-too-large/
|
# https://amalgjose.com/2020/05/15/how-to-set-the-allowed-url-length-for-a-nginx-request-error-code-414-uri-too-large/
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
# This is a shell script excerpt for configuration purposes only.
|
# This is a shell script excerpt for configuration purposes only.
|
||||||
# Handle with care! Please don't put code here, only variables.
|
# Handle with care! Please don't put code here, only variables.
|
||||||
|
|
||||||
CLASSES_PATTERN="^([^.]*)\..*\.$HOSTNAME\.(dmp|sql\.gz|tgz|log)$"
|
CLASSES_PATTERN="^([^.]*)\..*\.$HOSTNAME\.(dmp|sql\.gz|tar|tgz|log)$"
|
||||||
DOIT="yes" # if empty the script makes a dry run
|
DOIT="yes" # if empty the script makes a dry run
|
||||||
RETAIN_DAYS=7 # retains all files created within that many days
|
RETAIN_DAYS=1 # retains all files created within that many days
|
||||||
RETAIN_WEEKS=0 # retains one file per week/month,
|
RETAIN_WEEKS=0 # retains one file per week/month,
|
||||||
RETAIN_MONTHS=0 # created within that many weeks/months
|
RETAIN_MONTHS=0 # created within that many weeks/months
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,8 @@
|
|||||||
# This is a shell script excerpt for configuration purposes only.
|
# This is a shell script excerpt for configuration purposes only.
|
||||||
# Handle with care! Please don't put code here, only variables.
|
# Handle with care! Please don't put code here, only variables.
|
||||||
|
|
||||||
CLASSES_PATTERN="^([^.]*)\..*\.$HOSTNAME\.(dmp|sql\.gz|tgz|log)$"
|
CLASSES_PATTERN="^([^.]*)\..*\.$HOSTNAME\.(dmp|sql\.gz|tar|tgz|log)$"
|
||||||
DOIT="yes" # if empty the script makes a dry run
|
DOIT="yes" # if empty the script makes a dry run
|
||||||
# RETAIN_DAYS=7 # retains all files created within that many days
|
# RETAIN_DAYS=7 # retains all files created within that many days
|
||||||
# RETAIN_WEEKS=4 # retains one file per week/month,
|
# RETAIN_WEEKS=4 # retains one file per week/month,
|
||||||
# RETAIN_MONTHS=12 # created within that many weeks/months
|
# RETAIN_MONTHS=12 # created within that many weeks/months
|
||||||
|
|
||||||
|
|||||||
95
tools/check_certificates
Executable file
95
tools/check_certificates
Executable file
@@ -0,0 +1,95 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# A humble script to check the expiration of this web service certificates.
|
||||||
|
# It uses the ssl-cert-check worker utility, which should be somewhere in path.
|
||||||
|
# Sends an email notification when any certificate is about to expire.
|
||||||
|
# See https://github.com/Matty9191/ssl-cert-check for details.
|
||||||
|
#
|
||||||
|
# Author: Kovács Zoltán <kovacsz@marcusconsulting.hu>
|
||||||
|
# 2026-02-16 v0.1 Initial release
|
||||||
|
|
||||||
|
# Accepted environment variables and their defaults.
|
||||||
|
PAR_BASEDIR=${PAR_BASEDIR:-""} # Service's base folder
|
||||||
|
|
||||||
|
# Other initialisations.
|
||||||
|
ALERTEMAIL="$USER@$HOSTNAME" # Alert notification recipient
|
||||||
|
ALERTEXPIRY=14 # Days to alert before expiry
|
||||||
|
CERTFILES="-name *.cer -o -name *.crt -o -name *.pem"
|
||||||
|
CERTFOLDERS="configs/acme configs/certs" # Files and folders to check
|
||||||
|
WORKERNAME="ssl-cert-check" # The 3rd party worker script
|
||||||
|
YMLFILE="docker-compose.yml"
|
||||||
|
|
||||||
|
# Messages.
|
||||||
|
MSG_MISSINGDEP="Fatal: missing dependency"
|
||||||
|
MSG_MISSINGYML="Fatal: didn't find the docker-compose.yml file"
|
||||||
|
|
||||||
|
# Basic environment settings.
|
||||||
|
LANG=C
|
||||||
|
LC_ALL=C
|
||||||
|
|
||||||
|
# Checks the dependencies.
|
||||||
|
TR=$(which tr 2>/dev/null)
|
||||||
|
if [ -z "$TR" ]; then echo "$MSG_MISSINGDEP tr."; exit 1 ; fi
|
||||||
|
for item in basename dirname find readlink
|
||||||
|
do
|
||||||
|
if [ -n "$(which $item)" ]
|
||||||
|
then export $(echo $item | "$TR" '[:lower:]' '[:upper:]' | "$TR" '-' '_')=$(which $item)
|
||||||
|
else echo "$MSG_MISSINGDEP $item." >&2; exit 1; fi
|
||||||
|
done
|
||||||
|
# All dependencies are available via "$THECOMMAND" (upper case) call.
|
||||||
|
|
||||||
|
# Where I'm?
|
||||||
|
# https://gist.github.com/TheMengzor/968e5ea87e99d9c41782
|
||||||
|
SOURCE="${BASH_SOURCE[0]}"
|
||||||
|
while [ -h "$SOURCE" ]; do
|
||||||
|
# resolve $SOURCE until the file is no longer a symlink
|
||||||
|
SCRPATH="$( cd -P "$( "$DIRNAME" "$SOURCE" )" && pwd )" #"
|
||||||
|
SOURCE="$("$READLINK" "$SOURCE")"
|
||||||
|
# if $SOURCE was a relative symlink, we need to resolve it
|
||||||
|
# relative to the path where the symlink file was located
|
||||||
|
[[ $SOURCE != /* ]] && SOURCE="$SCRPATH/$SOURCE"
|
||||||
|
done; SCRPATH="$( cd -P "$( "$DIRNAME" "$SOURCE" )" && pwd )" #"
|
||||||
|
SCRFILE="$("$BASENAME" "$(test -L "$0" && "$READLINK" "$0" || echo "$0")")" #"
|
||||||
|
|
||||||
|
# Searches the base folder, containing a docker-compose.yml file.
|
||||||
|
# Called from the base folder (./)?
|
||||||
|
BASE_DIR="$PAR_BASEDIR"
|
||||||
|
TEST_DIR="$SCRPATH"
|
||||||
|
[[ -z "$BASE_DIR" ]] && [[ -r "$TEST_DIR/$YMLFILE" ]] && BASE_DIR="$TEST_DIR"
|
||||||
|
# Called from ./tools?
|
||||||
|
TEST_DIR="$("$DIRNAME" "$TEST_DIR")"
|
||||||
|
[[ -z "$BASE_DIR" ]] && [[ -r "$TEST_DIR/$YMLFILE" ]] && BASE_DIR="$TEST_DIR"
|
||||||
|
# Called from ./tools/*.d?
|
||||||
|
TEST_DIR="$("$DIRNAME" "$TEST_DIR")"
|
||||||
|
[[ -z "$BASE_DIR" ]] && [[ -r "$TEST_DIR/$YMLFILE" ]] && BASE_DIR="$TEST_DIR"
|
||||||
|
# On failure gives it up here.
|
||||||
|
if [ -z "$BASE_DIR" -o ! -r "$BASE_DIR/$YMLFILE" ]; then
|
||||||
|
echo "$MSG_MISSINGYML" >&2; exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Locates the worker script.
|
||||||
|
WORKERSCRIPT="$SCRPATH/$WORKERNAME"
|
||||||
|
[[ ! -x "$WORKERSCRIPT" ]] && WORKERSCRIPT="$(which "$WORKERNAME")"
|
||||||
|
[[ ! -x "$WORKERSCRIPT" ]] \
|
||||||
|
&& echo -e "$MSG_MISSINGDEP $WORKERNAME." >&2 \
|
||||||
|
&& exit 1
|
||||||
|
|
||||||
|
# Collects the certificates to be check.
|
||||||
|
certificates=""
|
||||||
|
for folder in $CERTFOLDERS ""
|
||||||
|
do
|
||||||
|
if [ -n "$folder" ]; then
|
||||||
|
certificates+="$("$FIND" "$BASE_DIR/$folder" \( $CERTFILES \) 2>/dev/null) "
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# Enumerates and checks the collected certificates.
|
||||||
|
# Sends an email notification when expiration is approaching.
|
||||||
|
for cert in $certificates ""
|
||||||
|
do
|
||||||
|
if [ -n "$cert" ]; then
|
||||||
|
"$WORKERSCRIPT" -c "$cert" -x $ALERTEXPIRY -qae "$ALERTEMAIL"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
# That's all, Folks! :)
|
||||||
@@ -10,8 +10,10 @@
|
|||||||
# Author: Kovács Zoltán <kovacs.zoltan@smartfront.hu>
|
# Author: Kovács Zoltán <kovacs.zoltan@smartfront.hu>
|
||||||
# Kovács Zoltán <kovacsz@marcusconsulting.hu>
|
# Kovács Zoltán <kovacsz@marcusconsulting.hu>
|
||||||
# License: GNU/GPL v3+ (https://www.gnu.org/licenses/gpl-3.0.en.html)
|
# License: GNU/GPL v3+ (https://www.gnu.org/licenses/gpl-3.0.en.html)
|
||||||
|
# 2026-02-16 v1.1
|
||||||
|
# new: It now also calls the SSL web certificate expiration checker utility.
|
||||||
# 2023-06-18 v1.0
|
# 2023-06-18 v1.0
|
||||||
# new: forked from the "Smartfront's DOCKER_skeleton" repository.
|
# new: Forked from the "Smartfront's DOCKER_skeleton" repository.
|
||||||
# 2021-09-14 v0.2
|
# 2021-09-14 v0.2
|
||||||
# add: Checks the SSL web certificate (if any), renews it if necessary.
|
# add: Checks the SSL web certificate (if any), renews it if necessary.
|
||||||
# 2021-09-01 v0.1 Initial release
|
# 2021-09-01 v0.1 Initial release
|
||||||
@@ -24,7 +26,7 @@
|
|||||||
# Where I'm?
|
# Where I'm?
|
||||||
SCRPATH="$( cd -P "$( "$(which dirname)" "$0" )" && echo "$PWD" )"
|
SCRPATH="$( cd -P "$( "$(which dirname)" "$0" )" && echo "$PWD" )"
|
||||||
|
|
||||||
# Checks the SSL web certificate, renews it if necessery.
|
# Checks the ACME-handled SSL web certificates, renews them if necessery.
|
||||||
#
|
#
|
||||||
# Uses the acme wrapper script located in the same directory.
|
# Uses the acme wrapper script located in the same directory.
|
||||||
ACME="$SCRPATH/acme"
|
ACME="$SCRPATH/acme"
|
||||||
@@ -32,7 +34,17 @@ ACMELOG="$($(which dirname) "$SCRPATH")/logs/web/acme.log"
|
|||||||
if [ -n "$ACME" -a -x "$ACME" ]; then
|
if [ -n "$ACME" -a -x "$ACME" ]; then
|
||||||
"$ACME" --cron >> "$ACMELOG" 2>&1
|
"$ACME" --cron >> "$ACMELOG" 2>&1
|
||||||
fi
|
fi
|
||||||
# Done with the certificate.
|
# Done with the ACME certificates.
|
||||||
|
|
||||||
|
# Checks all SSL web certificates (ACME-handled or not) for expiration.
|
||||||
|
# Checks the expiration of all certificates (including ACME-handled
|
||||||
|
# and non-handled ones).
|
||||||
|
#
|
||||||
|
CHECKCERT="$SCRPATH/check_certificates"
|
||||||
|
if [ -n "$CHECKCERT" -a -x "$CHECKCERT" ]; then
|
||||||
|
"$CHECKCERT"
|
||||||
|
fi
|
||||||
|
# Done with certificates.
|
||||||
|
|
||||||
# Daily backup operations.
|
# Daily backup operations.
|
||||||
#
|
#
|
||||||
|
|||||||
Reference in New Issue
Block a user