Last active
July 13, 2023 07:51
-
-
Save johnymachine/15fd9d4b7c5fdf51165258962e52488d 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 | |
# ssm_helper.sh - AWS Systems Manager Parameter Store Helper Script | |
echo -e "\e[1mAWS Systems Manager Parameter Store Helper Script\e[0m" | |
# Check if AWS CLI is installed | |
command -v aws >/dev/null 2>&1 || { echo >&2 "AWS CLI is required but not installed. Aborting."; exit 1; } | |
# Check if jq is installed | |
command -v jq >/dev/null 2>&1 || { echo >&2 "JQ is required but not installed. Aborting."; exit 1; } | |
# Set default values | |
dry_run=false | |
# Parse subcommand and named arguments | |
subcommand="" | |
while [[ $# -gt 0 ]]; do | |
case "$1" in | |
copy|save|load|toenv|delete) subcommand="$1"; shift ;; | |
--source_path) source_path="$2"; shift 2 ;; | |
--destination_path) destination_path="$2"; shift 2 ;; | |
--source_region) source_region="$2"; shift 2 ;; | |
--destination_region) destination_region="$2"; shift 2 ;; | |
--dryrun) dry_run=true; shift ;; | |
--file) file="$2"; shift 2 ;; | |
*) echo "Invalid argument: $1"; exit 1 ;; | |
esac | |
done | |
# Examples of how to use ssm_helper.sh | |
examples=" | |
Examples: | |
- Copy parameters from source to destination: | |
./ssm_helper.sh copy --source_path /env/dev --destination_path /env/prod --source_region us-west-2 --destination_region us-east-1 --dryrun | |
- Save parameters to a file: | |
./ssm_helper.sh save --source_path /env/dev --source_region us-west-2 --file parameters.json | |
- Load parameters from a file to destination: | |
./ssm_helper.sh load --file parameters.json --destination_path /env/prod --destination_region us-east-1 --dryrun | |
- Convert parameters to .env file format: | |
./ssm_helper.sh toenv --file parameters.json | |
- Delete parameters in source path: | |
./ssm_helper.sh delete --source_path /env/dev --source_region us-west-2 --dryrun" | |
# Check if subcommand is provided | |
if [ -z "$subcommand" ]; then | |
echo "Usage: ./ssm_helper.sh [subcommand] [options]" | |
echo "Subcommand is required." | |
echo "$examples" | |
exit 1 | |
fi | |
# Get AWS CLI identity information | |
identity=$(aws sts get-caller-identity --output json 2>/dev/null) | |
# Check if AWS CLI is logged in | |
if [[ -z "$identity" ]]; then | |
echo "AWS CLI is not logged in, please run log in." | |
exit 1 | |
fi | |
# Extract the role and user from the identity | |
role=$(echo "$identity" | jq -r '.Arn' | awk -F '/' '{print $(NF-1)}') | |
user=$(echo "$identity" | jq -r '.Arn' | awk -F '/' '{print $(NF)}') | |
# Print AWS CLI identity information | |
echo -e "🔐 \e[34mLogged in role:\e[0m \e[1m$role\e[0m as \e[1m$user\e[0m" | |
# Print selcted command | |
echo -e "⏳ \e[34mExecuting:\e[0m \e[1m$subcommand\e[0m subcommand." | |
case "$subcommand" in | |
copy) | |
# Check if source path is provided | |
if [ -z "$source_path" ]; then | |
echo "Error: Source path is required for the 'delete' subcommand." | |
exit 1 | |
fi | |
# Check if source region is provided | |
if [ -z "$source_region" ]; then | |
echo "Error: Source region is required for the 'delete' subcommand." | |
exit 1 | |
fi | |
# Check if destination path is provided | |
if [ -z "$destination_path" ]; then | |
echo "Error: Destination path is required for the 'copy' subcommand." | |
exit 1 | |
fi | |
# Check if destination region is provided | |
if [ -z "$destination_region" ]; then | |
echo "Error: Destination region is required for the 'copy' subcommand." | |
exit 1 | |
fi | |
# Copy parameters from the source path to the destination path | |
aws_output=$(aws ssm get-parameters-by-path \ | |
--path "$source_path" \ | |
--with-decryption \ | |
--recursive \ | |
--query "Parameters[*].[Name, Type, Value]" \ | |
--output json \ | |
--region "$source_region") | |
echo "$aws_output" | jq -r '.[] | [.[0], .[1], .[2]] | @tsv' | while IFS=$'\t' read -r full_source_path type value; do | |
full_destination_path="${full_source_path/$source_path/$destination_path}" | |
if [ "$dry_run" = true ]; then | |
echo "[Dry run] Copying: $full_source_path -($type)-> $full_destination_path" | |
else | |
echo "[Dry run] Copying: $full_source_path -($type)-> $full_destination_path" | |
aws ssm put-parameter \ | |
--name "$full_destination_path" \ | |
--value "$value" \ | |
--type "$type" \ | |
--region "$destination_region" | |
fi | |
done | |
;; | |
save) | |
# Check if file is provided | |
if [ -z "$file" ]; then | |
file="parameters.json" | |
fi | |
# Check if source path is provided | |
if [ -z "$source_path" ]; then | |
echo "Error: Source path is required for the 'delete' subcommand." | |
exit 1 | |
fi | |
# Check if source region is provided | |
if [ -z "$source_region" ]; then | |
echo "Error: Source region is required for the 'delete' subcommand." | |
exit 1 | |
fi | |
# Use AWS CLI to get parameters by path and output JSON | |
aws_output=$(aws ssm get-parameters-by-path \ | |
--path "$source_path" \ | |
--with-decryption \ | |
--recursive \ | |
--query "Parameters[*].[Name, Type, Value]" \ | |
--output json \ | |
--region "$source_region") | |
# Strip $source_path from the parameter names | |
aws_output=$(echo "$aws_output" | jq -r 'map(.[0] |= gsub("'"$source_path"'/?"; ""))') | |
# Save to provided file | |
echo "$aws_output" > "$file" | |
echo "Parameters stored to file: $file" | |
;; | |
load) | |
# Check if file is provided | |
if [ -z "$file" ]; then | |
echo "No 'file' provided, setting is to: 'parameters.json'" | |
file="parameters.json" | |
fi | |
# Check if file exists | |
if [ ! -f "$file" ] || [ ! -s "$file" ]; then | |
echo "File '$file' does not exist or is empty." | |
exit 1 | |
fi | |
# Check if destination path is provided | |
if [ -z "$destination_path" ]; then | |
echo "Error: Destination path is required for the 'load' subcommand." | |
exit 1 | |
fi | |
# Check if destination region is provided | |
if [ -z "$destination_region" ]; then | |
echo "Error: Destination region is required for the 'load' subcommand." | |
exit 1 | |
fi | |
# Read parameters from file | |
aws_output=$(cat "$file") | |
# Iterate over the AWS CLI output using jq | |
echo "$aws_output" | jq -r '.[] | [.[0], .[1], .[2]] | @tsv' | while IFS=$'\t' read -r name type value; do | |
# Create the full destination path by concatenating $destination_path and the parameter name | |
full_destination_path="$destination_path/$name" | |
# Process each parameter | |
if [ "$dry_run" = true ]; then | |
echo "[Dry run] Copying: $name -($type)-> $full_destination_path" | |
else | |
echo "Copying: $name -($type)-> $full_destination_path" | |
aws ssm put-parameter \ | |
--name "$full_destination_path" \ | |
--value "$value" \ | |
--type "$type" \ | |
--region "$destination_region" | |
fi | |
done | |
;; | |
toenv) | |
# Check if file is provided | |
if [ -z "$file" ]; then | |
echo "No 'file' provided, setting is to: 'parameters.json'" | |
file="parameters.json" | |
fi | |
# Check if file exists | |
if [ ! -f "$file" ] || [ ! -s "$file" ]; then | |
echo "File '$file' does not exist or is empty." | |
exit 1 | |
fi | |
# Read parameters from file | |
aws_output=$(cat "$file") | |
# Create a new array to store .env entries | |
env_entries=() | |
# Iterate over the AWS CLI output using jq | |
while IFS=$'\t' read -r full_source_path type value; do | |
# Replace slashes with underscores in the parameter name | |
parameter_name="${full_source_path#\/}" | |
parameter_name="${parameter_name//\//_}" | |
# Convert the parameter name to uppercase | |
parameter_name="${parameter_name^^}" | |
# Add quotes around the parameter value | |
quoted_value="'$value'" | |
# Format the .env entry | |
env_entry="${parameter_name}=${quoted_value}" | |
# Add the .env entry to the array | |
env_entries+=("$env_entry") | |
done < <(echo "$aws_output" | jq -r '.[] | [.[0], .[1], .[2]] | @tsv') | |
# Store the .env entries in a file | |
env_file="${file}.env" | |
printf "%s\n" "${env_entries[@]}" > "$env_file" | |
echo "Parameters converted to .env format: $env_file" | |
;; | |
delete) | |
# Check if destination path is provided | |
if [ -z "$destination_path" ]; then | |
echo "Error: Destination path is required for the 'delete' subcommand." | |
exit 1 | |
fi | |
# Check if destination region is provided | |
if [ -z "$destination_region" ]; then | |
echo "Error: Destination region is required for the 'delete' subcommand." | |
exit 1 | |
fi | |
# Use AWS CLI to get a list of parameter names in the specified path and all subpaths recursively | |
aws_output=$(aws ssm describe-parameters \ | |
--region "$destination_region" \ | |
--query "Parameters[?starts_with(Name, '$destination_path')].Name" \ | |
--output json) | |
parameter_names=$(echo "$aws_output" | jq -r '.[]') | |
if [ "$dry_run" = true ]; then | |
for name in $parameter_names; do | |
echo "[Dry run] Deleting: $name" | |
done | |
else | |
for name in $parameter_names; do | |
echo "Deleting: $name" | |
aws ssm delete-parameter \ | |
--name "$name" \ | |
--region "$source_region" | |
done | |
fi | |
;; | |
*) | |
echo "Invalid subcommand: $subcommand" | |
exit 1 | |
;; | |
esac | |
echo -e "✅ \e[34mCompleted!\e[0m" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment