Forum Discussion
Script to check for certificate expiration
Hi guys
Most of you have probably been in the situation where a certificate suddenly expired without anyone noticing (or at least no one took proper action). I was in that situation a couple of weeks ago. I asked Lord Google if someone had a good method of detecting certificate expiration automatically. I didn't really find anything relevant, except for a couple of SOLs from F5 regarding the checkcert utility. So I sat down and did some scripting myself. I'm pretty satisfied with the result, however, this is my first real bash script so you can probably find something that could be optimized or done in a better way.
So first of all the scripts checks if the device is the active box. If it is not, the script does nothing, but if is, the script creates a list of all expiring certificates and places them in expiringcerts.txt. This file is then checked and each line is reported separately to our servicedesk (which in return creates a case and escalates it directly to network operations). When a certificate has been reported it is put in the flaggedcerts.txt. This file ensures that a certificate is not reported multiple times, unless it is less than a week from expiring. In this case a new mail is send each time the script is ran (in our case, it is put in /etc/crontab and configured to run every day at 12 pm/noon).
If a certificate is deleted, expired or renewed it is no longer put in the expiringcerts.txt file and is therefore also removed from the flaggedcerts.txt file.
In the end a status mail is sent to me each day to ensure that the check ran as it should. This is just me that like to be absolutely sure that the script does its job.
___________________________
!/bin/bash
Author: dadalife
Check if unit is active and if it is the script should continue:
ACTIVE=$(tmsh show cm failover-status | grep ACTIVE | wc -l)
if (($ACTIVE == 1)); then
echo -e "Unit is active. Proceeding...\n"
SCRIPTPATH='/root/'
MAIL='servicedesk@atea.dk'
MAILCC='dada@atea.dk'
NUMREPORTED=0
NUMFLAGGED=0
NUMCRITICAL=0
Create a list of all expiring certificates:
tmsh run sys crypto check-cert | grep 'will expired' | awk -F 'in file' '{print $2}' | awk -F ' GMT' '{print $1}' > "$SCRIPTPATH"expiringcerts.txt
echo "A list of all expiring certificates has been created!"
Send an email for each certificate if it has not already been sent:
echo -e "\nChecking for expiring certificates..."
> "$SCRIPTPATH"tempflagged.txt
while read line; do
BODY="\n\nPlease create this case as an incident (Priority 3) under the customer CNM and escalate directly to OPNOM.\n\nThis is an auto-generated e-mail from the BIG-IP."
CERT=$(echo $line | awk -F ' ' '{print $1}')
CERTEXPIRE=$(echo $line | awk -F 'expired on ' '{print $2}')
FLAGGED=$(cat "$SCRIPTPATH"flaggedcerts.txt | grep $CERT | wc -l)
if (( $FLAGGED == 0)); then
echo $CERT >> "$SCRIPTPATH"tempflagged.txt
echo -e "$CERT expires on $CERTEXPIRE GMT.$BODY" | mail -s "$CERT expires on $CERTEXPIRE GMT" $MAIL -c $MAILCC
echo "--> $CERT reported to servicedesk."
NUMREPORTED=$[$NUMREPORTED +1]
else
echo $CERT >> "$SCRIPTPATH"tempflagged.txt
echo "--> $CERT has already been flagged"
NUMFLAGGED=$[$NUMFLAGGED +1]
fi
done < "$SCRIPTPATH"expiringcerts.txt
cp "$SCRIPTPATH"tempflagged.txt "$SCRIPTPATH"flaggedcerts.txt
echo -e "Check for expiring certificates done!"
Check if a certificate is less than a week from expiring:
CURRENTTIMEEPOCH=$(date +%s)
echo -e "\nChecking for almost expired certificates..."
while read line; do
CERTEXPIRE=$(echo $line | awk -F 'expired on ' '{print $2}')
CERTEXPIREEPOCH=$(date --date="$CERTEXPIRE" +%s)
CERTEXPIREDIFF=$(expr $CERTEXPIREEPOCH - $CURRENTTIMEEPOCH)
if (($CERTEXPIREDIFF < 604800)); then
BODY="\n\nPlease create this case as an incident (Priority 1) under the customer CNM and escalate directly to OPNOM.\n\nThis is an auto-generated e-mail from the BIG-IP."
CERT=$(echo $line | awk -F ' ' '{print $1}')
echo -e "$CERT expires on $CERTEXPIRE GMT.$BODY" | mail -s "WARNING: $CERT EXPIRES IN LESS THAN A WEEK!!" $MAIL -c $MAILCC
echo "--> WARNING: $CERT EXPIRES IN LESS THAN A WEEK!!"
NUMCRITICAL=$[$NUMCRITICAL +1]
fi
done < "$SCRIPTPATH"expiringcerts.txt
echo "Check for almost expired certificates done!"
echo -e "\nCertification check done!"
Send a status email:
echo -e "Hi David\n\nYour script did its job!!\n\nNumber of newly reported certificates: '$NUMREPORTED'\nNumber of already flagged certificates: '$NUMFLAGGED'\nNumber of critical certificates: '$NUMCRITICAL'\n\nYours Sincerely\nThe BIG-IP" | mail -s "Everthing went well!" $MAILCC
else
echo "Unit is standby. No action taken!"
fi
___________________
Feel free to comment on anything! :)
Thanks,
David
- hooleylistCirrostratus
Hi David,
Nice work. But could you use checkcert to send an snmptrap or email?
SOL14318: Monitoring SSL certificate expiration on the BIG-IP system (11.x)
SOL3727: Configuring custom SNMP traps
Aaron
- R_Eastman_13667Historic F5 Account
I was able to use this script in an iApp that I am able to run on a schedule, basically a cron job via the gui.
There is a typo in it. Wherever you see 'will expired' it should be 'will expire'.
- David_Dalgaard_NimbostratusHi R Eastman The typo is from the certcheck script that I run to get info about all the certificates. If that typo is fixed in a later release (we run 11.3.0), the script stops working :) I assume this is what happened for you? What version do you run?
- R_Eastman_13667Historic F5 Account11.3.0.
- David_Dalgaard_NimbostratusHmm. Same here. Just upgraded to HF8 a couple of hours ago and the typo is still in the "tmsh run sys crypto check-cert". Could be a remnant from an old version. I've seen some funny stuff hiding after upgrade. Our box was origanally in the 9.x branch when first bought, Then 10.x, and finally 11.x before going into production. So we found some scripts that still used Korn shell and similar stuff. But well.. No biggie, just fix the typo so it matches your output :)
- miguel_fon_1419Nimbostratus
Thanks a lot for the script.
Very useful!
- Paul_73646NimbostratusI am getting an error when it tries to mail the data out. here is the error: "send-mail: Cannot open mail:25" I can't seem to figure out why this is happening, does anyone have any ideas on this? Any help would be great!
- Héctor_J__Sánc1Nimbostratus
Hi,
a little update to check all partitions, not just Common:
!/bin/bash Author: dadalife Check if unit is active and if it is the script should continue: ACTIVE=$(tmsh show cm failover-status | grep ACTIVE | wc -l) if (($ACTIVE == 1)); then echo -e "Unit is active. Proceeding...\n" SCRIPTPATH='/root/' MAIL='' MAILCC='' NUMREPORTED=0 NUMFLAGGED=0 NUMCRITICAL=0 rm -r "$SCRIPTPATH"expiringcerts.txt Create a list of all expiring certificates: for PARTITION in $(tmsh -c "cd / ; list sys folder recursive one-line" | awk '{print $3}') do tmsh -c "cd /$PARTITION ; run sys crypto check-cert" | grep 'will expired' | awk -F 'in file' '{print $2}' | awk -F ' GMT' '{print $1}' >> "$SCRIPTPATH"expiringcerts.txt done echo "A list of all expiring certificates has been created!" Send an email for each certificate if it has not already been sent: echo -e "\nChecking for expiring certificates..." > "$SCRIPTPATH"tempflagged.txt while read line; do BODY="\n\nIf it was not previously done, please create a Jira for Operations team in order to renew the certificate.\n\nIgnore this alarm if the certificate is /Common/ca-bundle.crt\n\nThis is an auto-generated e-mail from the BIG-IP." CERT=$(echo $line | awk -F ' ' '{print $1}') CERTEXPIRE=$(echo $line | awk -F 'expired on ' '{print $2}') FLAGGED=$(cat "$SCRIPTPATH"flaggedcerts.txt | grep $CERT | wc -l) if (( $FLAGGED == 0)); then echo $CERT >> "$SCRIPTPATH"tempflagged.txt echo -e "$CERT expires on $CERTEXPIRE GMT.$BODY" | mail -s "$CERT expires on $CERTEXPIRE GMT" $MAIL -c $MAILCC echo "--> $CERT reported to servicedesk." NUMREPORTED=$[$NUMREPORTED +1] else echo $CERT >> "$SCRIPTPATH"tempflagged.txt echo "--> $CERT has already been flagged" NUMFLAGGED=$[$NUMFLAGGED +1] fi done < "$SCRIPTPATH"expiringcerts.txt cp "$SCRIPTPATH"tempflagged.txt "$SCRIPTPATH"flaggedcerts.txt echo -e "Check for expiring certificates done!" Check if a certificate is less than a week from expiring: CURRENTTIMEEPOCH=$(date +%s) echo -e "\nChecking for almost expired certificates..." while read line; do CERTEXPIRE=$(echo $line | awk -F 'expired on ' '{print $2}') CERTEXPIREEPOCH=$(date --date="$CERTEXPIRE" +%s) CERTEXPIREDIFF=$(expr $CERTEXPIREEPOCH - $CURRENTTIMEEPOCH) if (($CERTEXPIREDIFF < 604800)); then BODY="\n\nIf it was not previously done, please create a Jira for Operations team in order to renew the certificate.\n\nIgnore this alarm if the certificate is /Common/ca-bundle.crt\n\nThis is an auto-generated e-mail from the BIG-IP." CERT=$(echo $line | awk -F ' ' '{print $1}') echo -e "$CERT expires on $CERTEXPIRE GMT.$BODY" | mail -s "WARNING: $CERT EXPIRES IN LESS THAN A WEEK!!" $MAIL -c $MAILCC echo "--> WARNING: $CERT EXPIRES IN LESS THAN A WEEK!!" NUMCRITICAL=$[$NUMCRITICAL +1] fi done < "$SCRIPTPATH"expiringcerts.txt echo "Check for almost expired certificates done!" echo -e "\nCertification check done!" Send a status email: echo -e "Hi Miguel\n\nYour script did its job!!\n\nNumber of newly reported certificates: '$NUMREPORTED'\nNumber of already flagged certificates: '$NUMFLAGGED'\nNumber of critical certificates: '$NUMCRITICAL'\n\nYours Sincerely\nThe BIG-IP" | mail -s "Everthing went well!" $MAILCC else echo "Unit is standby. No action taken!" fi
- Héctor_J__Sánc1Nimbostratus
Another update/fix:
!/bin/bash Author: dadalife Check if unit is active and if it is the script should continue: ACTIVE=$(tmsh show cm failover-status | grep ACTIVE | wc -l) if (($ACTIVE == 1)); then echo -e "Unit is active. Proceeding...\n" SCRIPTPATH='/root/' MAIL='' MAILCC='' NUMREPORTED=0 NUMFLAGGED=0 NUMCRITICAL=0 IGNORE=('bundle') rm -r "$SCRIPTPATH"expiringcerts.txt Create a list of all expiring certificates: tmsh -c "cd /; run sys crypto check-cert" | grep 'will expire' | awk -F 'in file' '{print $2}' | awk -F ' GMT' '{print $1}' >> "$SCRIPTPATH"expiringcerts.txt echo "A list of all expiring certificates has been created!" Send an email for each certificate if it has not already been sent: echo -e "\nChecking for expiring certificates..." > "$SCRIPTPATH"tempflagged.txt while read line; do CERT=$(echo $line | awk -F ' ' '{print $1}') for i in "${IGNORE[@]}" do if [[ "$CERT" == *"$i"* ]] then echo "Ignoring $CERT" continue 2 fi done BODY="\n\nIf it was not previously done, please create a Jira for Operations team in order to renew the certificate.\n\nIgnore this alarm if the certificate is /Common/ca-bundle.crt\n\nThis is an auto-generated e-mail from the BIG-IP." CERTEXPIRE=$(echo $line | awk -F 'expired on ' '{print $2}') FLAGGED=$(cat "$SCRIPTPATH"flaggedcerts.txt | grep $CERT | wc -l) if (( $FLAGGED == 0)); then echo $CERT >> "$SCRIPTPATH"tempflagged.txt echo -e "$CERT expires on $CERTEXPIRE GMT.$BODY" | mail -s "$CERT expires on $CERTEXPIRE GMT" $MAIL -c $MAILCC echo "--> $CERT reported to servicedesk." NUMREPORTED=$[$NUMREPORTED +1] else echo $CERT >> "$SCRIPTPATH"tempflagged.txt echo "--> $CERT has already been flagged" NUMFLAGGED=$[$NUMFLAGGED +1] fi done < "$SCRIPTPATH"expiringcerts.txt cp "$SCRIPTPATH"tempflagged.txt "$SCRIPTPATH"flaggedcerts.txt echo -e "Check for expiring certificates done!" Check if a certificate is less than a week from expiring: CURRENTTIMEEPOCH=$(date +%s) echo -e "\nChecking for almost expired certificates..." while read line; do CERT=$(echo $line | awk -F ' ' '{print $1}') for i in "${IGNORE[@]}" do if [[ "$CERT" == *"$i"* ]] then echo "Ignoring $CERT" continue 2 fi done CERTEXPIRE=$(echo $line | awk -F 'expired on ' '{print $2}') CERTEXPIREEPOCH=$(date --date="$CERTEXPIRE" +%s) CERTEXPIREDIFF=$(expr $CERTEXPIREEPOCH - $CURRENTTIMEEPOCH) if (($CERTEXPIREDIFF < 604800)); then BODY="\n\nIf it was not previously done, please create a Jira for Operations team in order to renew the certificate.\n\nIgnore this alarm if the certificate is /Common/ca-bundle.crt\n\nThis is an auto-generated e-mail from the BIG-IP." echo -e "$CERT expires on $CERTEXPIRE GMT.$BODY" | mail -s "WARNING: $CERT EXPIRES IN LESS THAN A WEEK!!" $MAIL -c $MAILCC echo "--> WARNING: $CERT EXPIRES IN LESS THAN A WEEK!!" NUMCRITICAL=$[$NUMCRITICAL +1] fi done < "$SCRIPTPATH"expiringcerts.txt echo "Check for almost expired certificates done!" echo -e "\nCertification check done!" Send a status email: echo -e "Hi Héctor\n\nYour script did its job!!\n\nNumber of newly reported certificates: '$NUMREPORTED'\nNumber of already flagged certificates: '$NUMFLAGGED'\nNumber of critical certificates: '$NUMCRITICAL'\n\nYours Sincerely\nThe BIG-IP" | mail -s "Everthing went well!" $MAILCC else echo "Unit is standby. No action taken!" fi
Had to change grep 'will expired' to grep 'will expire', and now you can ignore certs to reduce the noise. Also removed the partition loop, you can check all certs from root dir.
- Héctor_J__Sánc1Nimbostratus
Another update/fix:
!/bin/bash Author: dadalife Check if unit is active and if it is the script should continue: ACTIVE=$(tmsh show cm failover-status | grep ACTIVE | wc -l) if (($ACTIVE == 1)); then echo -e "Unit is active. Proceeding...\n" SCRIPTPATH='/root/' MAIL='' MAILCC='' NUMREPORTED=0 NUMFLAGGED=0 NUMCRITICAL=0 IGNORE=('bundle') rm -r "$SCRIPTPATH"expiringcerts.txt Create a list of all expiring certificates: tmsh -c "cd /; run sys crypto check-cert" | grep 'will expire' | awk -F 'in file' '{print $2}' | awk -F ' GMT' '{print $1}' >> "$SCRIPTPATH"expiringcerts.txt echo "A list of all expiring certificates has been created!" Send an email for each certificate if it has not already been sent: echo -e "\nChecking for expiring certificates..." > "$SCRIPTPATH"tempflagged.txt while read line; do CERT=$(echo $line | awk -F ' ' '{print $1}') for i in "${IGNORE[@]}" do if [[ "$CERT" == *"$i"* ]] then echo "Ignoring $CERT" continue 2 fi done BODY="\n\nIf it was not previously done, please create a Jira for Operations team in order to renew the certificate.\n\nIgnore this alarm if the certificate is /Common/ca-bundle.crt\n\nThis is an auto-generated e-mail from the BIG-IP." CERTEXPIRE=$(echo $line | awk -F 'expired on ' '{print $2}') FLAGGED=$(cat "$SCRIPTPATH"flaggedcerts.txt | grep $CERT | wc -l) if (( $FLAGGED == 0)); then echo $CERT >> "$SCRIPTPATH"tempflagged.txt echo -e "$CERT expires on $CERTEXPIRE GMT.$BODY" | mail -s "$CERT expires on $CERTEXPIRE GMT" $MAIL -c $MAILCC echo "--> $CERT reported to servicedesk." NUMREPORTED=$[$NUMREPORTED +1] else echo $CERT >> "$SCRIPTPATH"tempflagged.txt echo "--> $CERT has already been flagged" NUMFLAGGED=$[$NUMFLAGGED +1] fi done < "$SCRIPTPATH"expiringcerts.txt cp "$SCRIPTPATH"tempflagged.txt "$SCRIPTPATH"flaggedcerts.txt echo -e "Check for expiring certificates done!" Check if a certificate is less than a week from expiring: CURRENTTIMEEPOCH=$(date +%s) echo -e "\nChecking for almost expired certificates..." while read line; do CERT=$(echo $line | awk -F ' ' '{print $1}') for i in "${IGNORE[@]}" do if [[ "$CERT" == *"$i"* ]] then echo "Ignoring $CERT" continue 2 fi done CERTEXPIRE=$(echo $line | awk -F 'expired on ' '{print $2}') CERTEXPIREEPOCH=$(date --date="$CERTEXPIRE" +%s) CERTEXPIREDIFF=$(expr $CERTEXPIREEPOCH - $CURRENTTIMEEPOCH) if (($CERTEXPIREDIFF < 604800)); then BODY="\n\nIf it was not previously done, please create a Jira for Operations team in order to renew the certificate.\n\nIgnore this alarm if the certificate is /Common/ca-bundle.crt\n\nThis is an auto-generated e-mail from the BIG-IP." echo -e "$CERT expires on $CERTEXPIRE GMT.$BODY" | mail -s "WARNING: $CERT EXPIRES IN LESS THAN A WEEK!!" $MAIL -c $MAILCC echo "--> WARNING: $CERT EXPIRES IN LESS THAN A WEEK!!" NUMCRITICAL=$[$NUMCRITICAL +1] fi done < "$SCRIPTPATH"expiringcerts.txt echo "Check for almost expired certificates done!" echo -e "\nCertification check done!" Send a status email: echo -e "Hi H&233;ctor\n\nYour script did its job!!\n\nNumber of newly reported certificates: '$NUMREPORTED'\nNumber of already flagged certificates: '$NUMFLAGGED'\nNumber of critical certificates: '$NUMCRITICAL'\n\nYours Sincerely\nThe BIG-IP" | mail -s "Everthing went well!" $MAILCC else echo "Unit is standby. No action taken!" fi
Had to change grep 'will expired' to _grep 'will expire'_, and now you can ignore certs to reduce the noise. Also removed the partition loop, you can check all certs from root dir.
- psxg_345884Nimbostratus
Hello,
I tried this script and I did some mods to it. However, I am getting the email body as follows:
/Common/appnet-test.crt expires on GMT.
Not sure why it shows "GMT" rather than the actual expiration date.
Please help.
Thank you
- REastman_249266Historic F5 Account
psxg,
I would check your variable syntax for this line CERTEXPIRE=$(echo $line | awk -F 'expired on ' '{print $2}') you may have a typo. It sounds like the CERTEXPIRE variable isn't been set.
- psxg_345884Nimbostratus
I have:
CERTEXPIRE=$(echo $line | awk -F 'expired on ''{print $2}') CERTEXPIREEPOCH=$(date --date="$CERTEXPIRE" +%s) CERTEXPIREDIFF=$(expr $CERTEXPIREEPOCH - $CURRENTTIMEEPOCH) if (($CERTEXPIREDIFF < 2419200)); then BODY="\n\nIf it was not previously done, please create a Service Now Ticket for Systems team in order to renew the certificate.\n\nIgnore this alarm if the certificate is /Common/ca-bundle.crt\n\nThis is an auto-generated e-mail from the BIG-IP." echo -e "$CERT expires on $CERTEXPIRE GMT.$BODY" | mail -s "WARNING: $CERT EXPIRES IN LESS THAN A MONTH!!" $MAIL -c $MAILCC echo "--> WARNING: $CERT EXPIRES IN LESS THAN A MONTH!!" NUMCRITICAL=$[$NUMCRITICAL +1] fi
I see it declared just fine. Is "$CERTEXPIRE GMT.$BODY"" correct ?
Recent Discussions
Related Content
* Getting Started on DevCentral
* Community Guidelines
* Community Terms of Use / EULA
* Community Ranking Explained
* Community Resources
* Contact the DevCentral Team
* Update MFA on account.f5.com