Last active
November 16, 2022 03:15
-
-
Save naamancampbell/f0f0fde6e9a9ecc7268e19b49e13ae57 to your computer and use it in GitHub Desktop.
awscli-sso-config - generates AWS CLI config file for SSO accounts and roles
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 | |
# | |
# awscli-sso-config - generates AWS CLI config file for | |
# SSO accounts and roles | |
# | |
# Usage: ./awscli-sso-config.sh aws_profile sso_start_url [--resume] | |
# | |
# Requires: awscli, jq | |
# | |
# Author: Naaman Campbell | |
# 28 August 2021 | |
# | |
# Version: 1.1.4 - 2022-11-16 - NC | |
# | |
aws_dir="$HOME/.aws" | |
sso_dir="$aws_dir/cli-sso" | |
client_type="public" | |
grant_type="urn:ietf:params:oauth:grant-type:device_code" | |
default_role_order="SystemAdministrator AdministratorAccess ReadOnly" | |
delimiters=":_" | |
resume=0 | |
if [ $# -lt 2 ]; then | |
exit "Usage: ./awscli-sso-config.sh aws_profile sso_start_url [--resume]" | |
fi | |
profile=$1 | |
start_url=$2 | |
if [[ ! -f $aws_dir/config || $(grep -c "^\[profile $profile\]" $aws_dir/config) -lt 1 ]]; then | |
echo "$profile not found in $aws_dir/config" | |
echo "Add AWS SSO profile - aws configure sso" | |
exit 1 | |
fi | |
if [[ $# -eq 3 && "$3" == "--resume" ]]; then | |
resume=1 | |
fi | |
add_profile () { | |
# add_profile profile_name start_url region account_id role_name | |
# skip adding current profile | |
if [ "$1" != "$profile" ]; then | |
echo "[profile $1]" >> $aws_dir/config | |
echo "sso_start_url = $2" >> $aws_dir/config | |
echo "sso_region = $3" >> $aws_dir/config | |
echo "sso_account_id = $4" >> $aws_dir/config | |
echo "sso_role_name = $5" >> $aws_dir/config | |
echo "region = $3" >> $aws_dir/config | |
echo "output = json" >> $aws_dir/config | |
echo "" >> $aws_dir/config | |
fi | |
} | |
if [ $resume -eq 0 ]; then | |
now=$(date +%s) | |
mkdir -p $sso_dir | |
# sso-oidc register-client | |
generate_client=1 | |
if [ -f $sso_dir/cli-sso-client.json ]; then | |
client_expiry=$(jq -r '.clientSecretExpiresAt' $sso_dir/cli-sso-client.json) | |
if [ $now -lt $client_expiry ]; then | |
generate_client=0 | |
fi | |
fi | |
if [ $generate_client -eq 1 ]; then | |
aws sso-oidc register-client \ | |
--client-name "cli-sso-config-$now" \ | |
--client-type $client_type \ | |
--profile $profile \ | |
> $sso_dir/cli-sso-client.json | |
fi | |
client_id=$(jq -r '.clientId' $sso_dir/cli-sso-client.json) | |
client_secret=$(jq -r '.clientSecret' $sso_dir/cli-sso-client.json) | |
# sso-oidc start-device-authorization | |
aws sso-oidc start-device-authorization \ | |
--client-id $client_id \ | |
--client-secret $client_secret \ | |
--start-url $start_url \ | |
--profile $profile \ | |
> $sso_dir/cli-sso-device.json | |
echo "Open the following URL to authorise this device and" | |
echo "re-run $0 with the --resume flag.." | |
echo "" | |
jq -r '.verificationUriComplete' $sso_dir/cli-sso-device.json | |
echo "" | |
exit 0 | |
else | |
# cli-sso --resume after device authorisation | |
timestamp=$(date -Iseconds) | |
if [ -f $aws_dir/credentials ]; then | |
echo "Existing AWS credentials file found - incompatible with SSO CLI" | |
mv $aws_dir/credentials $aws_dir/credentials-$timestamp | |
echo "Moved to $aws_dir/credentials-$timestamp" | |
fi | |
if [ -f $aws_dir/config ]; then | |
echo "Existing AWS config file found" | |
mv $aws_dir/config $aws_dir/config-$timestamp | |
echo "Moved to $aws_dir/config-$timestamp" | |
echo "" | |
# copy profile to new config | |
sed -n "/^\[profile $profile\]/,/^$/p" $aws_dir/config-$timestamp > $aws_dir/config | |
fi | |
region=$(aws configure get region --profile $profile) | |
device_code=$(jq -r '.deviceCode' $sso_dir/cli-sso-device.json) | |
client_id=$(jq -r '.clientId' $sso_dir/cli-sso-client.json) | |
client_secret=$(jq -r '.clientSecret' $sso_dir/cli-sso-client.json) | |
# sso-oidc create-token | |
aws sso-oidc create-token \ | |
--client-id $client_id \ | |
--client-secret $client_secret \ | |
--grant-type $grant_type \ | |
--device-code $device_code \ | |
--profile $profile \ | |
> $sso_dir/cli-sso-token.json | |
if [ $? -gt 0 ]; then | |
exit "Failed: aws sso-oidc create-token" | |
fi | |
access_token=$(jq -r '.accessToken' $sso_dir/cli-sso-token.json) | |
# sso list-accounts | |
aws sso list-accounts \ | |
--access-token $access_token \ | |
--profile $profile \ | |
> $sso_dir/cli-sso-accounts.json | |
# sso list-account-roles | |
jq -c '.accountList[]' $sso_dir/cli-sso-accounts.json | while read account | |
do | |
id=$(echo $account | jq -r '.accountId') | |
name=$(echo $account | jq -r '.accountName') | |
email=$(echo $account | jq -r '.emailAddress') | |
default_role="" | |
default_role_match=$(echo $default_role_order | awk '{print NF + 1}') | |
echo "${id}: ${name}" | |
roles=$(aws sso list-account-roles \ | |
--access-token $access_token \ | |
--account-id $id \ | |
--profile $profile \ | |
| jq -r '.roleList[].roleName') | |
if [ -z "$roles" ]; then | |
echo "No roles found for account: $name" | |
continue | |
fi | |
for role in $roles | |
do | |
add_profile "${id}_${role}" $start_url $region $id $role | |
role_match=$(awk "BEGIN{RS=FS}/$role/{print NR}" <<< $default_role_order) | |
if [[ ! -z $role_match && $role_match -lt $default_role_match ]]; then | |
default_role=$role | |
default_role_match=$role_match | |
fi | |
done | |
# profile aliases | |
if [ -z "$default_role" ]; then | |
default_role=$(echo $roles | awk '{print $1}') | |
fi | |
email_prefix=$(echo $email | awk -F'@' '{print $1}') | |
add_profile $email_prefix $start_url $region $id $default_role | |
account_prefix=$(echo $name | awk -F"[$delimiters]" '{print $1}') | |
if [ "$email_prefix" != "$account_prefix" ]; then | |
add_profile $account_prefix $start_url $region $id $default_role | |
fi | |
done | |
fi |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment