Skip to content

Instantly share code, notes, and snippets.

@huynhbaoan
Last active April 18, 2025 06:40
Show Gist options
  • Save huynhbaoan/14784a299684f8fe58d55e97f6e96c71 to your computer and use it in GitHub Desktop.
Save huynhbaoan/14784a299684f8fe58d55e97f6e96c71 to your computer and use it in GitHub Desktop.
#!/usr/bin/env zsh
# aws-multi-role.zsh
# Usage: ./aws-multi-role.zsh <env>
# Example: ./aws-multi-role.zsh preprod
set -euo pipefail
# --- 1. prerequisites --------------------------------------------------------
# verify jq is installed (for JSON parsing)
if ! command -v jq >/dev/null; then
echo "ERROR: this script requires 'jq'. Please install it and retry." >&2
exit 1
fi
# --- 2. mappings -------------------------------------------------------------
# env → source-profile name in ~/.aws/credentials
typeset -A ENV2PROFILE CSVFILE
ENV2PROFILE=(
dev servicesdev
test servicestest
np servicesnp
preprod servicespreprod
prod servicesprod
)
CSVFILE=(
dev dev.csv
test test.csv
np np.csv
preprod preprod.csv
prod prod.csv
)
# --- 3. parse & validate input ----------------------------------------------
if (( $# != 1 )); then
echo "Usage: $0 <environment: dev|test|np|preprod|prod>" >&2
exit 1
fi
env=$1
src_profile=${ENV2PROFILE[$env]:-}
csv_file=${CSVFILE[$env]:-}
if [[ -z $src_profile ]]; then
echo "ERROR: invalid environment '$env'." >&2
exit 1
fi
if [[ ! -f $csv_file ]]; then
echo "ERROR: CSV file '$csv_file' not found for environment '$env'." >&2
exit 1
fi
echo "→ using source profile: [$src_profile]"
echo "→ reading accounts from: $csv_file"
# --- 4. test source credentials ---------------------------------------------
if ! aws sts get-caller-identity --profile "$src_profile" &>/dev/null; then
echo "ERROR: credentials for profile '$src_profile' are invalid or expired." >&2
exit 1
fi
echo "✔ source credentials are valid."
# --- 5. detect original role type -------------------------------------------
# read the role_arn from your AWS config (not credentials) for this profile
orig_role_arn=$(aws configure get role_arn --profile "$src_profile" || true)
if [[ -z $orig_role_arn ]]; then
echo "ERROR: no role_arn found in ~/.aws/config for profile '$src_profile'." >&2
exit 1
fi
orig_role_name=${orig_role_arn##*/}
# determine whether we're switching admin‑style or view‑only
if [[ $orig_role_name == *-InfraAnalysis ]]; then
mode=viewonly
echo "→ detected InfraAnalysis source role → will assume HIPViewOnlyRole on targets"
elif [[ $orig_role_name == *-2FA-hip-admin ]]; then
mode=admin
echo "→ detected 2FA‑hip‑admin source role → will assume admin on targets"
else
echo "ERROR: source role name '$orig_role_name' does not match expected patterns." >&2
exit 1
fi
# --- 6. iterate CSV & assume-role -------------------------------------------
# skip header, read each line
while IFS=',' read -r account_id shortname desc url; do
# skip empty lines
[[ -z $account_id ]] && continue
echo
echo "→ processing account: $account_id ($shortname)"
if [[ $mode == viewonly ]]; then
target_role_name="HIPViewOnlyRole"
else
# admin mode: embed the target shortname into the role
target_role_name="AUR-Resource-AWS-${shortname}-2FA-hip-admin"
fi
role_arn="arn:aws:iam::${account_id}:role/${target_role_name}"
echo " assuming → $role_arn"
# perform assume‑role
assume_out=$(aws sts assume-role \
--role-arn "$role_arn" \
--role-session-name "${src_profile}-${shortname}-$(date +%s)" \
--duration-seconds 3600 \
--profile "$src_profile" \
)
# parse returned credentials
AK=$(jq -r .Credentials.AccessKeyId <<<"$assume_out")
SK=$(jq -r .Credentials.SecretAccessKey <<<"$assume_out")
ST=$(jq -r .Credentials.SessionToken <<<"$assume_out")
# write them into your credentials file under [<shortname>]
aws configure set aws_access_key_id "$AK" --profile "$shortname"
aws configure set aws_secret_access_key "$SK" --profile "$shortname"
aws configure set aws_session_token "$ST" --profile "$shortname"
aws configure set region ap-southeast-2 --profile "$shortname"
echo "✔ stored new profile → [$shortname]"
done < <(tail -n +2 "$csv_file")
echo
echo "All done. You can now use e.g. 'aws sts get-caller-identity --profile <shortname>'"
#!/usr/bin/env zsh
# aws-multi-role.zsh
# Usage: ./aws-multi-role.zsh <env>
# Example: ./aws-multi-role.zsh preprod
set -euo pipefail
# --- 1. prerequisites --------------------------------------------------------
if ! command -v jq >/dev/null; then
echo "ERROR: this script requires 'jq'. Please install it and retry." >&2
exit 1
fi
# --- 2. mappings -------------------------------------------------------------
typeset -A ENV2PROFILE CSVFILE
ENV2PROFILE=(
dev servicesdev
test servicestest
np servicesnp
preprod servicespreprod
prod servicesprod
)
CSVFILE=(
dev dev.csv
test test.csv
np np.csv
preprod preprod.csv
prod prod.csv
)
# --- 3. parse & validate input ----------------------------------------------
if (( $# != 1 )); then
echo "Usage: $0 <environment: dev|test|np|preprod|prod>" >&2
exit 1
fi
env=$1
src_profile=${ENV2PROFILE[$env]:-}
csv_file=${CSVFILE[$env]:-}
if [[ -z $src_profile ]]; then
echo "ERROR: invalid environment '$env'." >&2
exit 1
fi
if [[ ! -f $csv_file ]]; then
echo "ERROR: CSV file '$csv_file' not found for environment '$env'." >&2
exit 1
fi
echo "→ using source profile: [$src_profile]"
echo "→ reading accounts from: $csv_file"
# --- 4. test source credentials ---------------------------------------------
if ! aws sts get-caller-identity --profile "$src_profile" &>/dev/null; then
echo "ERROR: credentials for profile '$src_profile' are invalid or expired." >&2
exit 1
fi
echo "✔ source credentials are valid."
# --- 5. detect original role type via sts get-caller-identity ---------------
echo "→ fetching ARN of current identity from profile '$src_profile'…"
caller_json=$(aws sts get-caller-identity --profile "$src_profile" --output json)
orig_arn=$(echo "$caller_json" | jq -r '.Arn')
# Arn should look like:
# arn:aws:sts::123456789012:assumed-role/ROLE_NAME/SESSION_NAME
if [[ $orig_arn != arn:aws:sts::*:assumed-role/* ]]; then
echo "ERROR: expected an assumed-role ARN but got: $orig_arn" >&2
exit 1
fi
# extract ROLE_NAME (middle segment)
orig_role_name=${orig_arn#*assumed-role/} # strips up to 'assumed-role/'
orig_role_name=${orig_role_name%%/*} # strips from first '/' onward
echo "→ detected source role name: $orig_role_name"
if [[ $orig_role_name == *-InfraAnalysis ]]; then
mode=viewonly
echo "→ will assume HIPViewOnlyRole on targets"
elif [[ $orig_role_name == *-2FA-hip-admin ]]; then
mode=admin
echo "→ will assume AUR-Resource‑…‑2FA‑hip-admin on targets"
else
echo "ERROR: role name '$orig_role_name' does not match expected patterns." >&2
exit 1
fi
# --- 6. iterate CSV & assume-role -------------------------------------------
while IFS=',' read -r account_id shortname desc url; do
[[ -z $account_id ]] && continue # skip blank lines
echo
echo "→ processing account: $account_id ($shortname)"
if [[ $mode == viewonly ]]; then
target_role_name="HIPViewOnlyRole"
else
target_role_name="AUR-Resource-AWS-${shortname}-2FA-hip-admin"
fi
role_arn="arn:aws:iam::${account_id}:role/${target_role_name}"
echo " assuming → $role_arn"
assume_out=$(aws sts assume-role \
--role-arn "$role_arn" \
--role-session-name "${src_profile}-${shortname}-$(date +%s)" \
--duration-seconds 3600 \
--profile "$src_profile" \
)
AK=$(jq -r .Credentials.AccessKeyId <<<"$assume_out")
SK=$(jq -r .Credentials.SecretAccessKey <<<"$assume_out")
ST=$(jq -r .Credentials.SessionToken <<<"$assume_out")
aws configure set aws_access_key_id "$AK" --profile "$shortname"
aws configure set aws_secret_access_key "$SK" --profile "$shortname"
aws configure set aws_session_token "$ST" --profile "$shortname"
aws configure set region ap-southeast-2 --profile "$shortname"
echo "✔ stored new profile → [$shortname]"
done < <(tail -n +2 "$csv_file")
echo
echo "All done! You can now do, for example:"
echo " aws sts get-caller-identity --profile <shortname>"
#!/usr/bin/env zsh
# aws-multi-role.zsh
# Usage: ./aws-multi-role.zsh <env>
# Example: ./aws-multi-role.zsh preprod
set -euo pipefail
# --- 1. prerequisites --------------------------------------------------------
if ! command -v jq >/dev/null; then
echo "ERROR: this script requires 'jq'. Please install it and retry." >&2
exit 1
fi
# --- 2. mappings -------------------------------------------------------------
typeset -A ENV2PROFILE CSVFILE
ENV2PROFILE=(
dev servicesdev
test servicestest
np servicesnp
preprod servicespreprod
prod servicesprod
)
CSVFILE=(
dev dev.csv
test test.csv
np np.csv
preprod preprod.csv
prod prod.csv
)
# --- 3. parse & validate input ----------------------------------------------
if (( $# != 1 )); then
echo "Usage: $0 <environment: dev|test|np|preprod|prod>" >&2
exit 1
fi
env=$1
src_profile=${ENV2PROFILE[$env]:-}
csv_file=${CSVFILE[$env]:-}
if [[ -z $src_profile ]]; then
echo "ERROR: invalid environment '$env'." >&2
exit 1
fi
if [[ ! -f $csv_file ]]; then
echo "ERROR: CSV file '$csv_file' not found for environment '$env'." >&2
exit 1
fi
echo "→ using source profile: [$src_profile]"
echo "→ reading accounts from: $csv_file"
# --- 4. test source credentials ---------------------------------------------
if ! aws sts get-caller-identity --profile "$src_profile" &>/dev/null; then
echo "ERROR: credentials for profile '$src_profile' are invalid or expired." >&2
exit 1
fi
echo "✔ source credentials are valid."
# --- 5. detect original role type via sts get-caller-identity ---------------
echo "→ fetching ARN of current identity from profile '$src_profile'…"
caller_json=$(aws sts get-caller-identity --profile "$src_profile" --output json)
orig_arn=$(echo "$caller_json" | jq -r '.Arn')
if [[ $orig_arn != arn:aws:sts::*:assumed-role/* ]]; then
echo "ERROR: expected an assumed-role ARN but got: $orig_arn" >&2
exit 1
fi
orig_role_name=${orig_arn#*assumed-role/}
orig_role_name=${orig_role_name%%/*}
echo "→ detected source role name: $orig_role_name"
if [[ $orig_role_name == *-InfraAnalysis ]]; then
mode=viewonly
echo "→ will assume HIPViewOnlyRole on targets"
elif [[ $orig_role_name == *-2FA-hip-admin ]]; then
mode=admin
echo "→ will assume AUR-Resource‑…‑2FA‑hip-admin on targets"
else
echo "ERROR: role name '$orig_role_name' does not match expected patterns." >&2
exit 1
fi
# --- 6. iterate CSV & assume-role -------------------------------------------
while IFS=',' read -r account_id shortname desc url; do
[[ -z $account_id ]] && continue # skip blank lines
echo
echo "→ processing account: $account_id ($shortname)"
if [[ $mode == viewonly ]]; then
target_role_name="HIPViewOnlyRole"
else
target_role_name="AUR-Resource-AWS-${shortname}-2FA-hip-admin"
fi
role_arn="arn:aws:iam::${account_id}:role/${target_role_name}"
echo " attempting → $role_arn"
# --- assume with error handling ---
if ! assume_out=$(aws sts assume-role \
--role-arn "$role_arn" \
--role-session-name "${src_profile}-${shortname}-$(date +%s)" \
--duration-seconds 3600 \
--profile "$src_profile" \
2>&1
); then
echo "⚠️ Warning: could not assume role on $account_id ($shortname):"
echo " ${assume_out##* }"
echo " → skipping."
continue
fi
# parse and store
AK=$(jq -r .Credentials.AccessKeyId <<<"$assume_out")
SK=$(jq -r .Credentials.SecretAccessKey <<<"$assume_out")
ST=$(jq -r .Credentials.SessionToken <<<"$assume_out")
aws configure set aws_access_key_id "$AK" --profile "$shortname"
aws configure set aws_secret_access_key "$SK" --profile "$shortname"
aws configure set aws_session_token "$ST" --profile "$shortname"
aws configure set region ap-southeast-2 --profile "$shortname"
echo "✔ stored new profile → [$shortname]"
done < <(tail -n +2 "$csv_file")
echo
echo "All done! You can now do, for example:"
echo " aws sts get-caller-identity --profile <shortname>"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment