Quick and dirty shell script to find unused certificates
Problem this snippet solves:
This has been edited quite a bit since I first posted so it's probably not as quick and dirty as it was before.
This in response to a question regarding removing unused certificates https://devcentral.f5.com/questions/how-to-find-the-unused-ssl-certificates-63166
The following bash script will output any installed certificate names to a file, then iterate over each line. If the certificate is not referenced in bigip.conf in either the /config/ or within a partition folder, then it can be reasonably assumed it is not in use and can be safely deleted.
The script will give you the option to delete any certs that are not in use and save a UCS archive (just in case)
If there are any keys associated with the certificate, this will be deleted too.
As the moment, the script will not look for keys without an equivalent cert, e.g. my-cert.key and my-cert.crt. So you many still end up with rouge keys. I'll look to get this updated eventually.
There is an array called ignoreCerts
ignoreCerts=("f5-irule.crt" "ca-bundle.crt")
Here you can add certificates you may want to ignore. For example, f5-irule.crt is used to sign F5 provided iRules and bigip.conf does not reference it.
Add any additional certs to this array to ensure they are not deleted
Script can be downloaded directly from GitLab using the link below
https://gitlab.com/stratalabs/f5-devcental/snippets/1863498/raw?inline=false
How to use this snippet:
- paste into vi
- chmod +x myScript.sh
- ./myScript.sh
Code :
#!/bin/sh function buildInstalledCertsArray { tmsh save sys config partitions all tmsh list sys file ssl-cert | awk '/crt/ {print $4}' | sed '/^[[:space:]]*$/d' > /var/tmp/installedCerts.tmp # iterate over tmp file to create array of used certificates while read line; do for i in "${!ignoreCerts[@]}"; do if [[ $line = ${ignoreCerts[$i]} ]]; then ignore="true" else if [[ $ignore != "true" ]];then ignore="" else # do not add cert to array if already added if [[ ! " ${instCertsArr[@]} " =~ " ${line} " ]]; then instCertsArr+=("$line") fi fi fi done done /dev/null 2>&1) if ! [ -z "$hasKey" ];then deleteKeys+=("${cert%.*}.key") fi done } function deleteUnusedCerts { if [ ${#deleteCerts[@]} -eq 0 ]; then echo "-------------------------------------------------------------------------" echo "There are no unused certificates to delete, existing" echo "-------------------------------------------------------------------------" exit 0 else echo "-------------------------------------------------------------------------" echo "The following keys are not in use can can be deleted:" for cert in "${deleteCerts[@]}"; do echo " ${cert}" done echo "-------------------------------------------------------------------------" read -p "would you like to delete these unused certificates? (y/n)?" answer case ${answer:0:1} in y|Y ) createUcsArchive echo "-------------------------------------------------------------------------" echo "deleting certs..." for cert in "${deleteCerts[@]}"; do delete sys file ssl-key $cert echo " $cert" done if [ ${#deleteKeys[@]} -eq 0 ]; then echo "-------------------------------------------------------------------------" echo "no associated keys to delete, exiting" exit 0 else echo "-------------------------------------------------------------------------" echo "deleting keys..." for key in "${deleteKeys[@]}"; do delete sys file ssl-key $cert echo "$key" exit 0 done fi ;; * ) exit 0 ;; esac fi } function createUcsArchive { echo today=`date +%Y-%m-%d.%H.%M.%S` echo "Creating UCS archive auto.${today}.ucs" tmsh save sys ucs ${today}.ucs } # initialise vars instCertsArr=() deleteCerts=() # ignore certs defined here - f5-irile.crt is used to sign F5 iRules ignoreCerts=("f5-irule.crt" "ca-bundle.crt") # build installed certificates array - excluding certs to ignore buildInstalledCertsArray # check if installed certs are used in bigip.conf (including partitions) - ltm sys files are exluded from results buildDeleteCertsArray # build list of associated keys (not all certs will have keys) buildDeleteKeysArray # optionally delete unused certs deleteUnusedCerts
Tested this on version:
No Version Found- RodriheAltocumulus
Hi Lee!! Thanks for your fantastic work!
I'm trying to execute the script but seems the ignoreCerts array is not working as expected. For example, it always found "f5-irule.crt" as a certificate to be deleted. If I add any other certificate in the chain, then all the certificates in the chain are selected to be deleted.
Is it something that I'm doing wrong or it's a bug in the script?
Thanks for your great work!
- nages_reddyNimbostratus
i see three errors when i run the script, i updated with corrections.
- nages_reddyNimbostratus
#!/bin/sh
function buildInstalledCertsArray {
tmsh save sys config partitions all
tmsh list sys file ssl-cert | awk '/crt/ {print $4}' | sed '/^[[:space:]]*$/d' > /var/tmp/installedCerts.tmp
# iterate over tmp file to create array of used certificates
while read line; do
for i in "${!ignoreCerts[@]}"; do
if [[ $line = ${ignoreCerts[$i]} ]]; then
ignore="true"
else
if [[ $ignore != "true" ]];then
ignore=""
else
# do not add cert to array if already added
if [[ ! " ${instCertsArr[@]} " =~ " ${line} " ]]; then
instCertsArr+=("$line")
fi
fi
fi
done
done </var/tmp/installedCerts.tmp
rm /var/tmp/installedCerts.tmp
}
function buildDeleteCertsArray {
# populate deleteCerts array
for cert in "${instCertsArr[@]}"; do
isUsed=$(grep $cert /config/bigip.conf /config/partitions/*/bigip.conf | grep -v -e "sys file ssl-cert" -e cache-path)
if [ -z "$isUsed" ];then
deleteCerts+=("$cert")
fi
done
}
function buildDeleteKeysArray {
# delete any associated keys
for cert in "${deleteCerts[@]}"; do
#hasKey=$(tmsh list sys file ssl-key ${cert%.*}.key > /dev/null 2>&1)
hasKey=$(tmsh list sys file ssl-key ${cert%.*}.key 2> /dev/null)
if [ ! -z "$hasKey" ];then
deleteKeys+=("${cert%.*}.key")
fi
done
}
function deleteUnusedCerts {
if [ ${#deleteCerts[@]} -eq 0 ]; then
echo "-------------------------------------------------------------------------"
echo "There are no unused certificates to delete, existing"
echo "-------------------------------------------------------------------------"
exit 0
else
echo "-------------------------------------------------------------------------"
echo "The following keys are not in use can can be deleted:"
for cert in "${deleteCerts[@]}"; do
echo " ${cert}"
done
echo "-------------------------------------------------------------------------"
read -p "would you like to delete these unused certificates? (y/n)?" answer
case ${answer:0:1} in
y|Y )
createUcsArchive
echo "-------------------------------------------------------------------------"
echo "deleting certs..."
for cert in "${deleteCerts[@]}"; do
tmsh delete sys file ssl-cert $cert
echo "$cert"
done
if [ ${#deleteKeys[@]} -eq 0 ]; then
echo "-------------------------------------------------------------------------"
echo "no associated keys to delete, exiting"
exit 0
else
echo "-------------------------------------------------------------------------"
echo "deleting keys..."
for key in "${deleteKeys[@]}"; do
tmsh delete sys file ssl-key $key
echo "$key"
# exit 0
done
fi
;;
* )
exit 0
;;
esac
fi
}
function createUcsArchive {
echo
today=`date +%Y-%m-%d.%H.%M.%S`
echo "Creating UCS archive auto.${today}.ucs"
tmsh save sys ucs ${today}.ucs
}
# initialise vars
instCertsArr=()
deleteCerts=()
# ignore certs defined here - f5-irile.crt is used to sign F5 iRules
ignoreCerts=("f5-irule.crt" "ca-bundle.crt")
# build installed certificates array - excluding certs to ignore
buildInstalledCertsArray
# check if installed certs are used in bigip.conf (including partitions) - ltm sys files are exluded from results
buildDeleteCertsArray
# build list of associated keys (not all certs will have keys)
buildDeleteKeysArray
# optionally delete unused certs
deleteUnusedCerts
- Lee_SutcliffeNacreous
thanks for the suggestion, the original code snippet was just cobbled together very quickly for a DC question so hadn't considered this point.
I'll update the codeshare with your suggestion.
This is great, but one pre-requisite could be added too.
- By default, save-on-auto-sync is disabled (false). So make sure you run the save sys config command before executing the script. Else the running config may not be saved on the stored config file & the output could be misleading.
- Lee_SutcliffeNacreous
nice addition, thanks!
- Jason_AdamsEmployee
About the non-default partitions, you could use the following:
#!/bin/sh tmsh list sys file ssl-cert | awk '/crt/ {print $4}' | sed '/^[[:space:]]*$/d' > /var/tmp/installedCerts.tmp while read cert; do isUsed=$(find /config/ -xdev -type f -name bigip.conf -exec grep $cert {} +) if [ -z "$isUsed" ];then echo "$cert is not used" fi done </var/tmp/installedCerts.tmp rm /var/tmp/installedCerts.tmp