commit 65a2d6d8bd1af459c82196850338d88e8f7a5cd2 Author: Jonny007-MKD Date: Sun Mar 6 14:52:00 2022 +0100 First commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..eabf2e0 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/test/tmp/ diff --git a/check_gpg_key_expiration.sh b/check_gpg_key_expiration.sh new file mode 100755 index 0000000..b0ab143 --- /dev/null +++ b/check_gpg_key_expiration.sh @@ -0,0 +1,235 @@ +#!/bin/bash + +function echoerr { echo "$@" 1>&2; } + +function checkEnvironment { + ### Check the environment ### + if ! which gpg 2>&1 >/dev/null; then + echoerr "Missing gpg binary" + exit 3 + fi + + # Command to download a file + DOWNLOAD="" + if which curl 2>&1 >/dev/null; then + DOWNLOAD="curl -s -o " + elif which wget 2>&1 >/dev/null; then + DOWNLOAD="wget -o /dev/null -O " + else + echoerr "Missing curl or wget binary" + exit 3 + fi + + # Command to get information about all subkeys + GPG_SHOW="gpg --with-colon --fixed-list-mode --show-keys" +} + + +function parseArguments { + ### Parse arguments ### + # We require a URL + # and have default values for expiration durations + + URL="" + DEBUG=false + WARN=7 # days + CRIT=2 # days + while [[ $# -gt 0 ]]; do + case $1 in + -u|--url) URL="$2"; shift;; + -w|--warn) WARN=$2; shift;; + -c|--crit) CRIT=$2; shift;; + -d|--debug) DEBUG=true;; + -?|--help) + echo "Check gpg expiration date. Arguments:" + echo "--url URL: Where to find the GPG key" + echo "--warn DAYS: Warning threshold (integer in days)" + echo "--crit DAYS: Critical threshold (integer in days)" + exit 0 + ;; + *) + echoerr "Unknown argument: $1" + exit 3 + ;; + esac + shift + done + + if [ -z "$URL" ]; then + echoerr "Missing url argument (--url)" + exit 3 + fi + + WARN_s=$(($WARN*24*60*60)) + CRIT_s=$(($CRIT*24*60*60)) + NOW=$(date '+%s') +} + +function log { + if $DEBUG; then + echo " > $@" + fi +} +function logLine { + if $DEBUG; then + echo " : $@" + fi +} + + +RESULT=0 # 0:OK 1:WARN 2:CRIT +RESULT_INFO="" # Additional information + +function clearResultInfoIfResultLessThan { + # if we increase the result level/severity, + # we want to clear RESULT_INFO to only show the most important information + if [ $RESULT -lt $1 ]; then + RESULT_INFO="" + fi +} + +function expired { + # This function is called if a key expired + # we set RESULT to CRITICAL and prepend our information message + local key=$1 + local expirationDate=$2 + local msg + + log "$key expired at $expirationDate -> RESULT=2" + clearResultInfoIfResultLessThan 2 + RESULT=2 + msg="${RESULT_INFO}Key $key expired at $(date '+%Y-%m-%dT%H:%M:%S' --date @$expirationDate)" + if [ -n "$RESULT_INFO" ]; then + RESULT_INFO="$msg. $RESULT_INFO" + else + RESULT_INFO=$msg + fi +} + +function expire_crit { + # This function is called if a key is going to expire soon (critical) + # we set RESULT to CRITICAL and append our information message + local key=$1 + local expirationDate=$2 + + log "$key expires at $expirationDate (critical) -> RESULT=2" + clearResultInfoIfResultLessThan 2 + RESULT=2 + if [ -n "$RESULT_INFO" ]; then + RESULT_INFO="$RESULT_INFO. " + fi + RESULT_INFO="${RESULT_INFO}Key $key will expire at $(date '+%Y-%m-%dT%H:%M:%S' --date @$expirationDate)" +} + +function expire_warn { + # This function is called if a key is going to expire soon (warning) + local key=$1 + local expirationDate=$2 + + log "$key expires at $expirationDate (critical) -> RESULT=1" + clearResultInfoIfResultLessThan 1 + if [ $RESULT -le 1 ]; then + RESULT=1 + if [ -n "$RESULT_INFO" ]; then + RESULT_INFO="$RESULT_INFO. " + fi + RESULT_INFO="${RESULT_INFO}Key $key will expire at $(date '+%Y-%m-%dT%H:%M:%S' --date @$expirationDate)" + fi +} + + +METRICS="" +function metrics { + # This function is called for every subkey to generate the METRICS string + local key=$1 + local expirationDate=$2 + local remaining_s=$3 + + METRICS="${METRICS}'$key expiration date'=$(date '+%Y-%m-%dT%H:%M:%S' --date @$expirationDate) " + METRICS="${METRICS}'$key remaining'=${remaining_s}s;${WARN_s}s;${CRIT_s}s " +} + + +function parseLine { + # Parse a line of GPG's output + # https://www.gnupg.org/documentation/manuals/gnupg-devel/Unattended-GPG-key-generation.html + local remaining_s + local recordType validity keyLength keyAlgorithm keyID creationDate expirationDate certSN ownertrust userID signatureClass keyCapabilities issuerCertFingerprint flags tokenSN hashAlgorithm curveName complianceFlags lastUpdate origin comment + + #logLine "$@" + IFS=: read -r recordType validity keyLength keyAlgorithm keyID creationDate expirationDate certSN ownertrust userID signatureClass keyCapabilities issuerCertFingerprint flags tokenSN hashAlgorithm curveName complianceFlags lastUpdate origin comment < <(echo "$@") + log "keyID = $keyID, type = $recordType, expirationDate = $expirationDate" + if [ -n "$expirationDate" ]; then + remaining_s=$(($expirationDate-$NOW)) + metrics $keyID $expirationDate $remaining_s + if [ $remaining_s -le 0 ]; then + expired $keyID $expirationDate + elif [ $remaining_s -le $CRIT_s ]; then + expire_crit $keyID $expirationDate + elif [ $remaining_s -le $WARN_s ]; then + expire_warn $keyID $expirationDate + fi + fi +} + + +function getAndParseKey { + local line + local infile + + # for appropriate error handling we cannot use pipes (at least I don't know how to) + TMPFILE=$(mktemp) || exit 3 + #trap 'rm -f "$TMPFILE"' RETURN + #trap 'rm -f "$TMPFILE"' EXIT + + # If the URL is a local path, use it as input to GPG_SHOW + if [ ! -f "$URL" ]; then + log "Downloading $URL" + $DOWNLOAD "$TMPFILE" "$URL" + exit=$? + if [ $exit -ne 0 ]; then + echo "ERROR - Downloading failed with $exit" + exit 3 + fi + infile="$TMPFILE" + else + log "Using local file $URL" + infile="$URL" + fi + + # Process with GPG + cat "$infile" | $GPG_SHOW > "$TMPFILE" + exit=$? + if [ $exit -ne 0 ]; then + echo "ERROR - gpg failed with $exit" + exit 3 + fi + + while read -r line; do + parseLine "$line" + done < "$TMPFILE" + + trap - EXIT +} + + +function printResult { + if [ $RESULT -eq 2 ]; then + echo -n "CRITICAL - $RESULT_INFO" + elif [ $RESULT -eq 1 ]; then + echo -n "WARNING - $RESULT_INFO" + else + echo -n "OK" + fi + + echo -n " | " + echo -n "$METRICS" +} + + + +checkEnvironment +parseArguments "$@" +getAndParseKey +printResult +exit $RESULT diff --git a/test/expiredkey b/test/expiredkey new file mode 100644 index 0000000..00854ed Binary files /dev/null and b/test/expiredkey differ diff --git a/test/test.sh b/test/test.sh new file mode 100644 index 0000000..71286ed --- /dev/null +++ b/test/test.sh @@ -0,0 +1,133 @@ +cd $(dirname $0) + +function echoerr { echo "$@" 1>&2; } + +if [ -d tmp ]; then + rm -rf tmp +fi +mkdir tmp +chmod 700 tmp + +function generateKey { + local expiry=$1 + + cat <