Skip to content

Instantly share code, notes, and snippets.

@sybeck2k
Last active December 22, 2023 02:29
Show Gist options
  • Save sybeck2k/e893b753c7937d79b136097b3d7d7d6d to your computer and use it in GitHub Desktop.
Save sybeck2k/e893b753c7937d79b136097b3d7d7d6d to your computer and use it in GitHub Desktop.
A script to rapidly test IAM policies
#!/usr/bin/env bash
# MIT No Attribution
# Copyright 2023 Roberto Migli
# Permission is hereby granted, free of charge, to any person obtaining a copy of this
# software and associated documentation files (the "Software"), to deal in the Software
# without restriction, including without limitation the rights to use, copy, modify,
# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
# permit persons to whom the Software is furnished to do so.
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# Use this script to rapidly test IAM policies with both CLI and Console access
# The script allows you to assume a role with AWS STS and gives you the possibility
# to edit your Session Policy. It also prints out a url that you can use to login to
# the console with this Session. The script opens a subshell with the environment variables
# already set for you to use the session
#
# Requires JQ, curl, Python, AWS CLI and Bash
usage() {
cat << EOF
Syntax: $0 -s <string> -r <string> [-e <string>] [-p <string>] [-hrvf]
options:
-r role-arn The role ARN that you want to assume
-s session-name The name of the session
-e region The region of the signin endpoint to use (default us-east-1)
-p session-policy-json The session-policy to use (default to inline editor)
-v Validate the session-policy with IAM Access Analyzer
-f Use GetFederationToken STS API
-h Print this Help.
EOF
}
region="us-east-1"
policy_file=""
no_shell=false
validate_policy=false
use_federation_token=false
while getopts nhvfr:s:p:e: flag
do
case "${flag}" in
r) role=${OPTARG};;
s) session_name=${OPTARG};;
e) region=${OPTARG};;
p) policy_file=${OPTARG};;
n) no_shell=true;;
f) use_federation_token=true;;
v) validate_policy=true;;
h)
usage
exit;;
*) exit 2;;
esac
done
if [ -z "${session_name}" ]; then
echo "Missing session name"
usage
exit 1;
fi
if [ $use_federation_token = false ] && [ -z "${role}" ]; then
echo "Missing role ARN to assume"
usage
exit 1;
fi
TMP_POLICY="$(mktemp -q)"
if [ -z "${policy_file}" ]; then
cat <<EOT >> $TMP_POLICY
{
"Version":"2012-10-17",
"Statement":[
{
"Effect":"Allow",
"Action": "*",
"Resource": "*"
}
]
}
EOT
vim ${TMP_POLICY}
POLICY_CONTENT="$(cat $TMP_POLICY)"
until jq -e . >/dev/null 2>&1 <<<"$POLICY_CONTENT"; do
read -n 1 -p "Invalid JSON - (e)dit again or (a)bort? " cnt
case $cnt in
A|a) echo "\nAborting"; exit 0;;
esac
vim ${TMP_POLICY}
POLICY_CONTENT="$(cat $TMP_POLICY)"
done
else
fullpath_policy="$(realpath $policy_file)"
cat $fullpath_policy > $TMP_POLICY
fi
SESSION_POLICY_COMPACT=$(sed -e 's/^[[:blank:]]*//g' ${TMP_POLICY} | tr -d "\n\r")
SESSION_POLICY_PP=$(jq . -M <<< "$SESSION_POLICY_COMPACT")
if [ $validate_policy = true ]; then
AA_VALIDATE_OUTPUT=$(aws accessanalyzer validate-policy --policy-type IDENTITY_POLICY --policy-document "$SESSION_POLICY_PP" --output json )
condition=$(echo "$AA_VALIDATE_OUTPUT" | jq '.findings | any(.[]; select(.findingType? == "ERRORS" or .findingType? == "SECURITY_WARNING"))')
echo -e "\x1B[32mIAM Access Analyzer Output\x1B[0m"
jq . <<< "$AA_VALIDATE_OUTPUT"
fi
echo -e "\x1B[32mSession Policy\x1B[0m"
jq . -C <<< "$SESSION_POLICY_COMPACT" | cat -n
if [ $use_federation_token = true ]; then
STS_OUTPUT=$(aws sts get-federation-token --name $session_name --policy "$SESSION_POLICY_COMPACT" --output json)
else
STS_OUTPUT=$(aws sts assume-role --role-arn $role --role-session-name $session_name --policy "$SESSION_POLICY_COMPACT" --output json)
fi
if [ ! $? -eq 0 ]; then
echo "Error when calling sts API"
exit 3
fi
signin_region_domain="signin.aws.amazon.com"
console_region_domain="console.aws.amazon.com"
if [ "$region" != "us-east-1" ]; then
signin_region_domain="$region.signin.aws.amazon.com"
console_region_domain="$region.console.aws.amazon.com"
fi
AWS_ACCESS_KEY_ID=$(jq -r '.Credentials.AccessKeyId' <<< "${STS_OUTPUT}")
AWS_SECRET_ACCESS_KEY=$(jq -r '.Credentials.SecretAccessKey' <<< "${STS_OUTPUT}")
AWS_SESSION_TOKEN=$(jq -r '.Credentials.SessionToken' <<< "${STS_OUTPUT}")
TEMP_CREDS=$(jq -c '{sessionId: .Credentials.AccessKeyId, sessionKey: .Credentials.SecretAccessKey, sessionToken: .Credentials.SessionToken}' <<< "$STS_OUTPUT")
URL_ENCODED_TEMP_CREDS=$(python3 -c "import urllib.parse, sys; print(urllib.parse.quote_plus(sys.argv[1]))" "$TEMP_CREDS")
SIGNIN_TOKEN=$(curl -s "https://$signin_region_domain/federation?Action=getSigninToken&Session=$URL_ENCODED_TEMP_CREDS" | jq -r '.SigninToken')
echo -e "\x1B[32mAWS Console Access\x1B[0m"
echo "https://$signin_region_domain/federation?Action=login&Issuer=https%3A%2F%2Fexample.com&Destination=https%3A%2F%2F$console_region_domain%2F&SigninToken=$SIGNIN_TOKEN"
if [ "$no_shell" = true ] ; then
echo ""
echo "AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}"
echo "AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}"
echo "AWS_SESSION_TOKEN=${AWS_SESSION_TOKEN}"
echo ""
exit
fi
export AWS_ACCESS_KEY_ID
export AWS_SECRET_ACCESS_KEY
export AWS_SESSION_TOKEN
bash --rcfile <(echo "PS1='$AWS_ACCESS_KEY_ID:$session_name AWS $ '") -i
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment