Skip to content

Instantly share code, notes, and snippets.

@DrizzlyOwl
Last active April 5, 2024 11:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save DrizzlyOwl/0dec286e0e7c3209b555b4343c6a921b to your computer and use it in GitHub Desktop.
Save DrizzlyOwl/0dec286e0e7c3209b555b4343c6a921b to your computer and use it in GitHub Desktop.
#! /bin/bash
set -e
TZ=Europe/London
TODAY=$(date -Idate)
DATE_90=$(date --date="90 days ago" +"%Y-%m-%d")
SILENT=0
################################################################################
# Author:
# Ash Davies <@DrizzlyOwl>
# Version:
# 0.1.0
# Description:
# Search an Azure Subscription for Azure Key Vaults that have Secrets with
# expiry dates. If an expiry date is due within the next 90 days report it
# Usage:
# ./kv-secret-scan.sh [-s <subscription name>] [-q]
# -s <subscription name> (optional) Azure Subscription
# -q (optional) Suppress output
#
# If you do not specify the subscription name, the script will prompt you to
# select one based on the current logged in Azure user
################################################################################
while getopts "s:q" opt; do
case $opt in
s)
AZ_SUBSCRIPTION_SCOPE=$OPTARG
;;
q)
SILENT=1
;;
*)
;;
esac
done
# If a subscription scope has not been defined on the command line using '-e'
# then prompt the user to select a subscription from the account
if [ -z "${AZ_SUBSCRIPTION_SCOPE}" ]; then
AZ_SUBSCRIPTIONS=$(
az account list --output json |
jq -c '[.[] | select(.state == "Enabled").name]'
)
echo "🌐 Choose an option"
AZ_SUBSCRIPTIONS="$(echo "$AZ_SUBSCRIPTIONS" | jq -r '. | join(",")')"
# Read from the list of available subscriptions and prompt them to the user
# with a numeric index for each one
if [ -n "$AZ_SUBSCRIPTIONS" ]; then
IFS=',' read -r -a array <<< "$AZ_SUBSCRIPTIONS"
echo
cat -n < <(printf "%s\n" "${array[@]}")
echo
n=""
# Ask the user to select one of the indexes
while true; do
read -rp 'Select subscription to query: ' n
# If $n is an integer between one and $count...
if [ "$n" -eq "$n" ] && [ "$n" -gt 0 ]; then
break
fi
done
i=$((n-1)) # Arrays are zero-indexed
AZ_SUBSCRIPTION_SCOPE="${array[$i]}"
fi
fi
echo "🎯 Using subscription $AZ_SUBSCRIPTION_SCOPE"
echo
echo "πŸ”Ž Looking for Azure Key Vaults..."
# Find all Azure Key Vaults within the specified subscription
KV_LIST=$(
az keyvault list \
--only-show-errors \
--subscription "$AZ_SUBSCRIPTION_SCOPE" |
jq -rc '.[] | { "name": .name, "resourceGroup": .resourceGroup }'
)
STATUS=0
for KEY_VAULT in $KV_LIST; do
BIN_EXPIRED=""
BIN_EXPIRING=""
RESOURCE_GROUP=$(echo "$KEY_VAULT" | jq -rc '.resourceGroup')
KV_NAME=$(echo "$KEY_VAULT" | jq -rc '.name')
if [ $SILENT == 1 ]; then
echo " πŸ” Azure Key Vault found..."
else
echo " πŸ” Azure Key Vault $KV_NAME in Resource Group $RESOURCE_GROUP..."
fi
echo " πŸ•΅οΈ πŸ”Ž Looking for Secrets..."
SECRETS=$(
az keyvault secret list \
--vault-name "$KV_NAME" \
--output json \
--only-show-errors \
--subscription "$AZ_SUBSCRIPTION_SCOPE" |
jq '.[] | select(.attributes.enabled == true) | select(.attributes.expires != null) | { "secret_name": .name, "expiry_date": .attributes.expires }'
)
if [ -z "$SECRETS" ]; then
echo " βœ… No Secrets found!"
else
for SECRET in $(echo "$SECRETS" | jq -c); do
SECRET_NAME=$(echo "$SECRET" | jq -rc '.secret_name')
SECRET_EXPIRY=$(echo "$SECRET" | jq -rc '.expiry_date')
if [ $SILENT == 1 ]; then
echo " πŸ”‘ Checking Secret..."
else
echo " πŸ”‘ Checking Secret: $SECRET_NAME..."
fi
# Check expiry of existing token
SECRET_EXPIRY_EXPIRY_DATE=${SECRET_EXPIRY:0:10}
SECRET_EXPIRY_EXPIRY_DATE_COMP=${SECRET_EXPIRY_EXPIRY_DATE//-/}
DATE_90=${DATE_90:0:10}
DATE_90_COMP=${DATE_90//-/}
TODAY_COMP=${TODAY//-/}
if [ $SILENT == 0 ]; then
echo " Expires on $SECRET_EXPIRY_EXPIRY_DATE"
fi
if [[ "$SECRET_EXPIRY_EXPIRY_DATE_COMP" -lt "$TODAY_COMP" ]] || [[ "$SECRET_EXPIRY_EXPIRY_DATE_COMP" == "$TODAY_COMP" ]]; then
echo " ❌ Expired"
BIN_EXPIRED="$SECRET, $BIN_EXPIRED"
elif [[ "$SECRET_EXPIRY_EXPIRY_DATE_COMP" -lt "$DATE_90_COMP" ]]; then
echo " ⏳ Expiring in less than 90 days"
BIN_EXPIRING="$SECRET, $BIN_EXPIRING"
else
echo " βœ… Still valid"
fi
echo
done
fi
if [ "$BIN_EXPIRING" == "" ] && [ "$BIN_EXPIRED" == "" ]; then
else
STATUS=1
if [ "$BIN_EXPIRING" != "" ]; then
BIN_EXPIRING="[${BIN_EXPIRING/%, /}]"
echo
echo "⚠️ Secrets were found that are close to expiry, you should renew them"
if [ $SILENT == 0 ]; then
echo "Key Vault: $KV_NAME"
echo "$BIN_EXPIRING" | jq -c '.[].secret_name'
fi
echo
fi
fi
if [ "$BIN_EXPIRED" != "" ]; then
BIN_EXPIRED="[${BIN_EXPIRED/%, /}]"
echo
echo "πŸ’£ Secrets were found that have expired, you should remove them if they are not in use"
if [ $SILENT == 0 ]; then
echo "Key Vault: $KV_NAME"
echo "$BIN_EXPIRED" | jq -c '.[].secret_name'
fi
echo
fi
fi
done
exit $STATUS
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment