Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Retrieve/Check SSL certificate expiration date(s)
#!/bin/bash
# By B Shea Dec2018
# https://www.holylinux.net
# Test for OpenSSL - if not installed stop here.
if ! [[ -x $(which openssl) ]]; then
printf "\nOpenSSL not found or not executable.\nPlease install OpenSSL before proceeding.\n\n"
exit 1
fi
### user adjustable variables ###
#openssl query timeout
openssl_timeout="timeout 10"
# 30 days is default on warnings - also can use '-d' to adjust
days_to_warn=30
### Clear/list/set defaults for variables - do not touch ###
epoch_day=86400
epoch_warning=$((days_to_warn*epoch_day))
regex_numbers='^[0-9]+$'
expire="0"
website=""
port=""
sitelist=./websites.txt
certfilename=""
location=""
filename=""
displaysite=""
#COLORS
color="0"
RED=$(tput setaf 1) #expired!!
GREEN=$(tput setaf 2) #within bounds
YELLOW=$(tput setaf 3) #warning/date close!
NC=$(tput sgr0) #reset to normal
#
usage="
$(basename "$0") [-h] [-c] [-d DAYS] [-f FILENAME] | [-w WEBSITE] | [-s SITELIST]
Retrieve the expiration date(s) on SSL certificate(s) using OpenSSL.
Usage:
-h Help
-c Color output
-d Amount of days to show warnings (default is 30 days)
Example: -d 15
-f SSL date from FILENAME
Example: -f /home/user/example.pem
-w SSL date from SITE(:PORT) (Port defaults to 443)
Example: -w www.example.com
-s SSL date(s) from SITELIST
Example: -s ./websites.txt
List format: sub.domain.tld:993 (one per line - port optional)
Example:
$ $(basename "$0") -c -d 14 -s ./websites.txt
WARNS (in color) if within 14 days of expiring on each entry in the file list.
"
#FUNCTIONS
menu_input() {
echo
echo "1: Enter file location of certificate"
echo "2: Enter an Internet site in form of subdomain.domain.tld(:port)"
echo
read -p "Enter 1 or 2 (anything else quits): " -n 1 -r
echo
}
get_lookup_input() {
location=""
echo
read -p "Please enter the $lookuptype location: " location
}
set_format() {
set_formatting="%-40s%-25s\n"
set_formatting_green=$set_formatting
set_formatting_yellow=$set_formatting
set_formatting_red=$set_formatting
printf "\nWarning is $days_to_warn days.\n"
printf "Color is "
if [[ $color == "1" ]]; then
set_formatting_green="$GREEN%-40s$NC%-25s\n"
set_formatting_yellow="$YELLOW%-40s$NC%-25s\n"
set_formatting_red="$RED%-40s$NC%-25s\n"
printf "enabled.\n\n"
else
printf "disabled.\n\n"
fi
printf "$set_formatting" "LOCATION" "EXPIRATION DATE"
printf "$set_formatting" "--------" "---------------"
}
parse_port() {
port=443
parseurl=$(echo $website | awk '$1 ~ /^.*:/' | cut -d':' -f1)
parseport=$(echo $website | awk '$1 ~ /^.*:/' | cut -d':' -f2)
if [[ $parseport =~ $regex_numbers ]]; then # -> port was found
website=$parseurl
port=$parseport
fi
}
output_site() {
if [ "$lookuptype" != "FILENAME" ]; then
parse_port
display_site="$website:$port"
else
display_site="$filename"
fi
check_expiry
if [[ $expire == "1" ]]; then
printf "$set_formatting_yellow" "$display_site" "$expire_date !" # YELLOW OUTPUT - warning
elif [[ $expire == "2" ]]; then
printf "$set_formatting_red" "$display_site" "$expire_date !!" # RED OUTPUT - expired
elif [[ $expire == "3" ]]; then
printf "$set_formatting" "$display_site" "$expire_date !!!" # NO COLOR - NOT FOUND
else
printf "$set_formatting_green" "$display_site" "$expire_date" # GREEN OUTPUT
fi
}
check_expiry() {
expire="0"
# use epoch times for calcs/compares
today_epoch="$(date +%s)"
if [ "$lookuptype" == "FILENAME" ]; then
expire_date=$(openssl x509 -in $certfilename -noout -dates 2>/dev/null | \
awk -F= '/^notAfter/ { print $2; exit }')
else
expire_date=$($openssl_timeout openssl s_client -servername $website -connect $website:$port </dev/null 2>/dev/null | \
openssl x509 -noout -dates 2>/dev/null | \
awk -F= '/^notAfter/ { print $2; exit }')
fi
if ! [[ -z $expire_date ]]; then # -> found date-process it:
expire_epoch=$(date +%s -d "$expire_date")
timeleft=`expr $expire_epoch - $today_epoch`
if [[ $timeleft -le $epoch_warning ]]; then #WARN
expire="1"
fi
if [[ $today_epoch -ge $expire_epoch ]]; then #EXPIRE
expire="2"
fi
else
expire="3"
expire_date="N/A "
fi
}
is_integer() {
if ! [[ "$1" =~ $regex_numbers ]]; then
printf "\nError.\nNot a number. You used a parameter that requires a whole number.\n$usage"
exit 1
fi
}
#
client_lookup() {
lookuptype="WEBSITE"
if [[ -z $website ]]; then #loop lookup - ask for input
get_lookup_input
website=$location
fi
set_format
output_site
lookuptype=""
website=""
echo
}
file_lookup() {
lookuptype="FILENAME"
if [[ -z $certfilename ]]; then #loop lookup - ask for input
get_lookup_input
certfilename=$location
fi
filename=$(basename -- "$certfilename")
set_format
output_site
lookuptype=""
filename=""
echo
}
list_lookup() {
lookuptype="FILELIST"
file_contents=$(<$sitelist)
set_format
while IFS= read -r website; do
if ! [[ -z $website ]]; then
output_site
fi
done <<<"$file_contents"
lookuptype=""
echo
}
#HANDLE ARGUMENTS
while getopts ':hcd:f:s:w:' option; do
case "$option" in
h) printf "$usage"
exit 0
;;
c) color="1"
;;
d) is_integer "$OPTARG"
if [ "$OPTARG" -ge 1 -a "$OPTARG" -le 365 ]; then
days_to_warn="$OPTARG"
epoch_warning=$((days_to_warn*epoch_day))
else
printf "\nDays must be between 1 and 365\n$usage"
exit 1
fi
;;
f) certfilename=$OPTARG
[[ -r $certfilename ]] && file_lookup || printf "\nFile not found/not readable. Permissions?\n\n"; exit 1;
exit 0
;;
s) sitelist=$OPTARG
[[ -r $sitelist ]] && list_lookup || printf "\nFile not found/not readable. Permissions?\n\n"; exit 1;
exit 0
;;
w) website=$OPTARG
client_lookup
exit 0
;;
:) printf "\nYou specified a flag that needs an argument.\n$usage" 1>&2
exit 1
;;
*) printf "\nI do not understand '"$1" "$2"'.\n$usage" 1>&2
exit 1
;;
esac
done
shift $((OPTIND - 1))
#LOOP RUN (default if no flags)
if [ $# -eq 0 ]; then # no command line arguments/flags found
printf "\nNo flags used or available. Interactive mode.\n"
while :
do
menu_input
if [[ $REPLY == "1" ]]
then
file_lookup
elif [[ $REPLY == "2" ]]
then
client_lookup
else # exit
[[ "$0" = "$BASH_SOURCE" ]] && exit 1 || return 1
fi
echo
done
fi
@bmatthewshea

This comment has been minimized.

Copy link
Owner Author

bmatthewshea commented Dec 13, 2018

show_ssl_expire [-h] [-c] [-d DAYS] [-f FILENAME] | [-w WEBSITE] | [-s SITELIST]

Retrieve the expiration date(s) on SSL certificate(s) using OpenSSL.

Usage:
    -h  Help

    -c  Color output

    -d  Amount of days to show warnings (default is 30 days)
        Example: -d 15

    -f  SSL date from FILENAME
        Example: -f /home/user/example.pem

    -w  SSL date from SITE(:PORT) (Port defaults to 443)
        Example: -w www.example.com

    -s  SSL date(s) from SITELIST
        Example:      -s ./websites.txt
        List format:  sub.domain.tld:993 (one per line - port optional)

Example:
    $ show_ssl_expire -c -d 14 -s ./websites.txt

    WARNS (in color) if within 14 days of expiring on each entry in the file list.

Note: If no arguments/flags given the script defaults to interactive mode/loop.

shea22-2019-01-01_190003
shea22-2019-01-01_185545
shea22-2019-01-01_190205

@bmatthewshea

This comment has been minimized.

Copy link
Owner Author

bmatthewshea commented Dec 14, 2018

  • added -d (days) to show warnings
  • added -c color flag for file lists
  • added warnings (yellow) based on 30 day default (see -d)
@bmatthewshea

This comment has been minimized.

Copy link
Owner Author

bmatthewshea commented Jan 1, 2019

  • DRY'ed it down a bit.
  • cleaned up unnecessary comments.
  • other cosmetic/misc improvements
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.