Created
August 16, 2017 18:28
-
-
Save brimston3/ea4c7fc4a616fef6ffef937293409ab5 to your computer and use it in GitHub Desktop.
Some examples for extracting certificate information and tests for checking if a HTTPD reload is needed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
:<<"EOF" | |
openssl_acme_cert_script_examples.sh | |
CodeLibrary, server management | |
Inspecting acmetool generated certificates. | |
=========================================== | |
This file contains some handy script examples for checking various details in | |
a remote tls server's certificate and comparing it to the current on-disk | |
version that acmetool (or similar) has stored. | |
No temporary files are used, only pipes. Most operations can be piped as | |
a one-liner, though safety checking is adviseable. | |
Copyright 2017-08-16 Andrew Domaszek. | |
All rights reserved. | |
Licensed under BSD-new | |
Dependency: | |
openssl (tested with 1.0.1t) | |
Todos: | |
1. Currently does not cache x509 parsing. Posix shell does not have arrays | |
and I find myself doing these checks with busybox often. This makes it | |
more difficult to handle K-V storage objects in a pipeline (indirection | |
has awkward syntax). | |
EOF | |
DEBUG=1 | |
ACME_LIVE_DIR=/var/lib/acme/live | |
ACME_DOMAIN=YOUR.DOMAIN | |
DEBUGPRINT() { | |
if [ "x$DEBUG" != "x" ]; then | |
ANSI_GREEN='\033[0;32m' | |
ANSI_RESET='\033[0m' | |
echo $ANSI_GREEN"$@"$ANSI_RESET | |
fi | |
} | |
## | |
# Simple single-domain certificate file modified time newer than 1 day. | |
if [ "$(find "$ACME_LIVE_DIR/$ACME_DOMAIN/cert" -mtime -1 2>/dev/null | wc -l)" -gt 0 ]; then | |
DEBUGPRINT "Certificate on disk for $ACME_DOMAIN is newer than 1 day" | |
# Rehash znc | |
# reload nginx | |
fi | |
## | |
# Simple single-domain validity check against the default root certificate store. | |
# May need -CAfile rootcerts.pem or -CApath /etc/ssl/certs for alternate root cert stores. | |
if ! openssl verify "$ACME_LIVE_DIR/$ACME_DOMAIN/chain"; then | |
DEBUGPRINT "$ACME_DOMAIN chain validation failed." | |
# send alert email to admin here, this is bad. | |
else | |
DEBUGPRINT "Local certificate chain for $ACME_DOMAIN verifies okay." | |
fi | |
## | |
# More general reload catching that I use on my project instance: | |
if [ "$(find "$ACME_LIVE_DIR/" -name cert -mtime -1 2>/dev/null | wc -l)" -gt 0 ]; then | |
DEBUGPRINT "$ACME_LIVE_DIR has at least one certificate newer than one day" | |
# reload nginx | |
fi | |
## | |
# Extract remote certificate: | |
DEBUGPRINT "Remote server https certificate for $ACME_DOMAIN:" | |
echo "" | openssl s_client -showcerts -servername "$ACME_DOMAIN" -connect "$ACME_DOMAIN:443" 2>/dev/null | openssl x509 -inform pem -noout -text | |
## | |
# Some pipeable "filter" functions to extract the desired field. | |
get_cert_min_date_filter() { | |
openssl x509 -inform pem -noout -text | grep -iF "Not Before:" | sed -e 's@^.*: @@' | |
} | |
get_cert_serial_filter() { | |
# attributes are not case sensitive, so force to lowercase. | |
openssl x509 -inform pem -noout -text | awk 'f{print;f=0} /^[ ]*Serial Number:/{f=1}' | tr -d ' ' | tr '[A-Z]' '[a-z]' | |
} | |
get_cert_subject_filter() { | |
# attributes are not case sensitive, so force to lowercase. | |
openssl x509 -inform pem -noout -text | grep -iF "Subject:" | sed -e 's@^.*: @@' | tr '[A-Z]' '[a-z]' | |
} | |
# Demonstrate using above filter to do a timestamp comparison: | |
TLS_REMOTE_MIN_DATE="$(echo | openssl s_client -showcerts -servername "$ACME_DOMAIN" -connect "$ACME_DOMAIN:443" 2>/dev/null | get_cert_min_date_filter)" | |
TLS_LOCAL_MIN_DATE="$(cat "$ACME_LIVE_DIR/$ACME_DOMAIN/cert" | get_cert_min_date_filter)" | |
if [ "x$TLS_REMOTE_MIN_DATE" != "x" -a "x$TLS_LOCAL_MIN_DATE" != "x" ]; then | |
TLS_REMOTE_ZTIME="$(date --date="$TLS_REMOTE_MIN_DATE" +"%s" 2>/dev/null)" | |
TLS_LOCAL_ZTIME="$(date --date="$TLS_LOCAL_MIN_DATE" +"%s" 2>/dev/null)" | |
if [ "$TLS_REMOTE_ZTIME" -ne "$TLS_LOCAL_ZTIME" ]; then | |
DEBUGPRINT "Not-Before times differ between on-disk certificate ($TLS_LOCAL_MIN_DATE) and remote server certificate ($TLS_REMOTE_MIN_DATE)." | |
# times are different, maybe reload nginx? | |
# could be that the subjects are different, should probably check. | |
# cert serial is not suitable for this check because it will always be different if any field is different. | |
else | |
DEBUGPRINT "Not-Before times match for on-disk ($TLS_LOCAL_MIN_DATE) and remote server ($TLS_REMOTE_MIN_DATE) certificates." | |
fi | |
else | |
DEBUGPRINT "An error occurred getting the Not-Before date from either the on-disk ($TLS_LOCAL_MIN_DATE) or remote server ($TLS_REMOTE_MIN_DATE) certificate." | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment