Last active
April 5, 2024 11:09
-
-
Save DrizzlyOwl/0dec286e0e7c3209b555b4343c6a921b to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#! /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