Created
May 29, 2025 18:53
-
-
Save tedwardd/f23f3769c95de417b96677ce8ab944d2 to your computer and use it in GitHub Desktop.
This file contains hidden or 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 | |
############################################################################## | |
## Preflight check for a given project to ensure it is in a state where | |
## it can be shutdown | |
## | |
## Checks the following: | |
## - What assets are present, ignoring $ignored_assets | |
## - Ignore known assets from specific asset types | |
## - If WIF pools are present | |
## - If Secrets are present | |
## | |
## Requirements: | |
## - gcloud CLI | |
## - Config file with required_apis and ignored_assets | |
## | |
## Usage: | |
## ./preflight.sh <project_id> | |
############################################################################## | |
# Change if needed to the path of your config options file | |
config_file="./preflight_config" | |
# Get the project ID from the command line | |
project_id="${1}" | |
if [[ -z "${project_id}" ]]; then | |
echo "Usage: $0 <project_id>" | |
exit 1 | |
fi | |
# Source the config file | |
# shellcheck source=./config_options | |
[[ -f "${config_file}" ]] && source "${config_file}" || { | |
echo "Config file ${config_file} not found" | |
exit 1 | |
} | |
# Get list of resources based on provided assetType | |
get_assets() { | |
asset_type="${1}" | |
gcloud asset list -q --project="${project_id}" --asset-types="${asset_type}" --format="value(name)" | |
} | |
# Accept asset_type and list of assets and run function based on asset_type | |
filter_assets() { | |
asset_type="${1}" | |
assets="${2}" | |
case "${asset_type}" in | |
"dataplex.googleapis.com/EntryGroup") | |
for entrygroup in "${ignored_entrygroups[@]}"; do | |
assets=$(echo "${assets}" | grep -v "${entrygroup}") | |
done | |
;; | |
"compute.googleapis.com/SslPolicy") | |
for ssl_policy in "${ignored_ssl_policies[@]}"; do | |
assets=$(echo "${assets}" | grep -v "${ssl_policy}") | |
done | |
;; | |
"iam.googleapis.com/Role") | |
for role in "${ignored_roles[@]}"; do | |
assets=$(echo "${assets}" | grep -v "${role}") | |
done | |
;; | |
"storage.googleapis.com/Bucket") | |
for bucket in "${ignored_buckets[@]}"; do | |
assets=$(echo "${assets}" | grep -v "${bucket}") | |
done | |
;; | |
esac | |
echo "${assets}" | |
} | |
# Check if the project exists | |
if ! gcloud projects describe "${project_id}" &>/dev/null; then | |
echo "Project ${project_id} does not exist" | |
exit 1 | |
fi | |
# Enable a given API or return 1 | |
enable_api() { | |
if ! gcloud services enable "${1}" -q --project="${project_id}" &>/dev/null; then | |
return 1 | |
fi | |
} | |
# Returns a list of unique asset types for a given project or return 1 | |
get_asset_types() { | |
asset_types=$(gcloud asset list -q --project="${project_id}" --format="value(assetType)" | sort -u) | |
if [[ -z "${asset_types}" ]] || [[ "${asset_types}" == "" ]]; then | |
return 1 | |
fi | |
echo "${asset_types}" | |
} | |
# Fetch the list of pools and return them or return 1 | |
list_pools() { | |
if ! pools=$( | |
gcloud iam workload-identity-pools list -q --location global --project="${project_id}" --format="value(name)" | |
); then | |
return 1 | |
fi | |
if [[ -n "${pools}" ]] && [[ "${pools}" != "" ]]; then | |
echo "${pools}" | |
fi | |
} | |
# Check if a value is in a list | |
check_value_in_list() { | |
local value="${1}" | |
local list="${2}" | |
if ! echo "${list}" | grep -q "${value}"; then | |
return 1 | |
fi | |
} | |
# List project secrets or return 1 | |
list_secrets() { | |
secrets=$(gcloud secrets list -q --project="${project_id}" --format="value(name)") | |
if [[ -z "${secrets}" ]]; then | |
return 1 | |
fi | |
echo "${secrets}" | |
} | |
# Enable required APIs or exit on failure | |
for api in "${required_apis[@]}"; do | |
if ! enable_api "${api}"; then | |
echo "Failed to enable ${api} API" | |
exit 1 | |
fi | |
done | |
## Assets #################################################################### | |
# Get the list of assets or print error and exit | |
if ! project_assets=$(get_asset_types); then | |
echo "Failed to get assets for project ${project_id}" | |
exit 1 | |
fi | |
# Check for ignored assets | |
for asset in "${ingored_assets[@]}"; do | |
if check_value_in_list "${asset}" "${project_assets}"; then | |
# Remove the ignored asset from the list | |
project_assets=$(echo "${project_assets}" | grep -v "${asset}") | |
fi | |
done | |
# Get length of project_assets after removing ignored assets | |
asset_count=$(wc -l <<<"${project_assets}") | |
# Print the number of assets found as well as the assets themselves | |
echo "Unique asset types found: $((asset_count))" | |
echo "Asset types with potentially active resources:" | |
if [[ -n "${project_assets}" ]]; then | |
while read -r asset; do | |
assets=$(get_assets "${asset}") | |
assets=$(filter_assets "${asset}" "${assets}") | |
if [[ -z "${assets}" ]]; then | |
continue | |
fi | |
echo " - ${asset}" | |
while read -r asset; do | |
echo " - ${asset}" | |
done <<<"${assets}" | |
done <<<"${project_assets}" | |
fi | |
## WIF Pools ################################################################# | |
# Get pools, display count and list pool names if any else return error and | |
# exit | |
if pools=$(list_pools); then | |
pool_count=0 | |
# For some reason list_pools returns an empty string when no pools are found | |
# This works around that for now | |
# TODO: Investigate why list_pools returns an empty string when no pools are found | |
if [[ "${pools}" != "" ]]; then | |
pool_count=$(wc -l <<<"${pools}") | |
fi | |
echo "WIF pools found: $((pool_count))" | |
if [[ -n "${pools}" ]]; then | |
while read -r pool; do | |
echo " - ${pool}" | |
done <<<"${pools}" | |
fi | |
else | |
echo "Failed to list pools for project ${project_id}" | |
exit 1 | |
fi | |
## Secrets ################################################################### | |
# Get secrets, display count and list secret names if any else return error | |
# and exit | |
if secrets=$(list_secrets); then | |
secret_count=$(wc -l <<<"${secrets}") | |
echo "Secrets found: $((secret_count))" | |
if [[ -n "${secrets}" ]]; then | |
while read -r secret; do | |
echo " - ${secret}" | |
done <<<"${secrets}" | |
fi | |
else | |
echo "Failed to list secrets for project ${project_id}" | |
exit 1 | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment