Commit 81f9451625
Unsigned
Layout: unified · split
applications/aws/README.md added +94
| @@ -0,0 +1,94 @@ | |||
| 1 | # `get_account_users.sh` | ||
| 2 | |||
| 3 | *Note*: This example uses an account titled `cmc`, which has access provisioned to it through IAM. | ||
| 4 | |||
| 5 | ``` bash | ||
| 6 | ./get_account_users.sh | ||
| 7 | ``` | ||
| 8 | |||
| 9 | ``` text | ||
| 10 | Fetching IAM Identity Center and Account details... | ||
| 11 | Successfully found Account 'cmc' with ID: 214941490075 | ||
| 12 | --- | ||
| 13 | Step 2: Finding all permission sets provisioned to 'cmc'... | ||
| 14 | Found provisioned permission sets. Now checking assignments for each... | ||
| 15 | --- | ||
| 16 | -> Fetching policies for Permission Set: arn:aws:sso:::permissionSet/ssoins-68041bff81588aa3/ps-6ea9be6a2332b891 | ||
| 17 | -> Found Assignment: testgroup1 (GROUP) -> AdministratorAccess | ||
| 18 | -> Found Assignment: iamtestuser1 (USER) -> AdministratorAccess | ||
| 19 | -> Found Assignment: testgroup2 (GROUP) -> AdministratorAccess | ||
| 20 | -> Fetching policies for Permission Set: arn:aws:sso:::permissionSet/ssoins-68041bff81588aa3/ps-590510f2a285016d | ||
| 21 | -> Found Assignment: iamtestuser1 (USER) -> Billing | ||
| 22 | --- | ||
| 23 | Success! Report saved to 'report_cmc.json' | ||
| 24 | The file contains all user/group assignments and their policies for account 'cmc'. | ||
| 25 | ``` | ||
| 26 | |||
| 27 | ``` bash | ||
| 28 | cat report_cmc.json | ||
| 29 | ``` | ||
| 30 | |||
| 31 | ```json | ||
| 32 | [ | ||
| 33 | { | ||
| 34 | "principal": { | ||
| 35 | "type": "GROUP", | ||
| 36 | "name": "testgroup1" | ||
| 37 | }, | ||
| 38 | "permission_set": { | ||
| 39 | "name": "AdministratorAccess", | ||
| 40 | "policies": { | ||
| 41 | "managed_policies": [ | ||
| 42 | "arn:aws:iam::aws:policy/AdministratorAccess" | ||
| 43 | ], | ||
| 44 | "inline_policy": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Sid\":\"Statement2\",\"Effect\":\"Deny\",\"Action\":[\"a4b:*\"],\"Resource\":[\"*\"]}]}" | ||
| 45 | } | ||
| 46 | } | ||
| 47 | }, | ||
| 48 | { | ||
| 49 | "principal": { | ||
| 50 | "type": "USER", | ||
| 51 | "name": "iamtestuser1" | ||
| 52 | }, | ||
| 53 | "permission_set": { | ||
| 54 | "name": "AdministratorAccess", | ||
| 55 | "policies": { | ||
| 56 | "managed_policies": [ | ||
| 57 | "arn:aws:iam::aws:policy/AdministratorAccess" | ||
| 58 | ], | ||
| 59 | "inline_policy": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Sid\":\"Statement2\",\"Effect\":\"Deny\",\"Action\":[\"a4b:*\"],\"Resource\":[\"*\"]}]}" | ||
| 60 | } | ||
| 61 | } | ||
| 62 | }, | ||
| 63 | { | ||
| 64 | "principal": { | ||
| 65 | "type": "GROUP", | ||
| 66 | "name": "testgroup2" | ||
| 67 | }, | ||
| 68 | "permission_set": { | ||
| 69 | "name": "AdministratorAccess", | ||
| 70 | "policies": { | ||
| 71 | "managed_policies": [ | ||
| 72 | "arn:aws:iam::aws:policy/AdministratorAccess" | ||
| 73 | ], | ||
| 74 | "inline_policy": "{\"Version\":\"2012-10-17\",\"Statement\":[{\"Sid\":\"Statement2\",\"Effect\":\"Deny\",\"Action\":[\"a4b:*\"],\"Resource\":[\"*\"]}]}" | ||
| 75 | } | ||
| 76 | } | ||
| 77 | }, | ||
| 78 | { | ||
| 79 | "principal": { | ||
| 80 | "type": "USER", | ||
| 81 | "name": "iamtestuser1" | ||
| 82 | }, | ||
| 83 | "permission_set": { | ||
| 84 | "name": "Billing", | ||
| 85 | "policies": { | ||
| 86 | "managed_policies": [ | ||
| 87 | "arn:aws:iam::aws:policy/job-function/Billing" | ||
| 88 | ], | ||
| 89 | "inline_policy": "" | ||
| 90 | } | ||
| 91 | } | ||
| 92 | } | ||
| 93 | ] | ||
| 94 | ``` | ||
applications/aws/get_account_users.sh added +125
| @@ -0,0 +1,125 @@ | |||
| 1 | #!/bin/bash | ||
| 2 | |||
| 3 | # This script analyzes all IAM Identity Center assignments for a specific | ||
| 4 | # AWS account and outputs the details to a single JSON file. | ||
| 5 | # Corrected Logic: First finds provisioned permission sets, then gets assignments for each. | ||
| 6 | |||
| 7 | # --- Configuration --- | ||
| 8 | ACCOUNT_NAME="" | ||
| 9 | |||
| 10 | # --- Prerequisite check --- | ||
| 11 | if ! command -v aws &> /dev/null || ! command -v jq &> /dev/null; then | ||
| 12 | echo "Error: Both AWS CLI and jq are required. Please install them and ensure they are in your PATH." | ||
| 13 | exit 1 | ||
| 14 | fi | ||
| 15 | |||
| 16 | # --- Step 1: Get Instance details and find the target Account ID --- | ||
| 17 | echo "Fetching IAM Identity Center and Account details..." | ||
| 18 | |||
| 19 | INSTANCE_ARN=$(aws sso-admin list-instances --query "Instances[0].InstanceArn" --output text) | ||
| 20 | IDENTITY_STORE_ID=$(aws sso-admin list-instances --query "Instances[0].IdentityStoreId" --output text) | ||
| 21 | |||
| 22 | if [ -z "$INSTANCE_ARN" ] || [ -z "$IDENTITY_STORE_ID" ]; then | ||
| 23 | echo "Error: Could not find IAM Identity Center instance ARN or Identity Store ID." | ||
| 24 | exit 1 | ||
| 25 | fi | ||
| 26 | |||
| 27 | ACCOUNT_ID=$(aws organizations list-accounts --query "Accounts[?Name=='$ACCOUNT_NAME' && Status=='ACTIVE'].Id" --output text) | ||
| 28 | |||
| 29 | if [ -z "$ACCOUNT_ID" ]; then | ||
| 30 | echo "Error: Could not find an active AWS account with the name '$ACCOUNT_NAME'." | ||
| 31 | exit 1 | ||
| 32 | fi | ||
| 33 | |||
| 34 | echo "Successfully found Account '$ACCOUNT_NAME' with ID: $ACCOUNT_ID" | ||
| 35 | echo "---" | ||
| 36 | |||
| 37 | # --- Step 2: Get all Permission Sets provisioned to the account --- | ||
| 38 | echo "Step 2: Finding all permission sets provisioned to '$ACCOUNT_NAME'..." | ||
| 39 | PROVISIONED_SETS_ARN=$(aws sso-admin list-permission-sets-provisioned-to-account \ | ||
| 40 | --instance-arn "$INSTANCE_ARN" \ | ||
| 41 | --account-id "$ACCOUNT_ID" \ | ||
| 42 | --query "PermissionSets[]" --output text) | ||
| 43 | |||
| 44 | if [ -z "$PROVISIONED_SETS_ARN" ]; then | ||
| 45 | echo "No permission sets are provisioned for account '$ACCOUNT_NAME'." | ||
| 46 | exit 0 | ||
| 47 | fi | ||
| 48 | |||
| 49 | echo "Found provisioned permission sets. Now checking assignments for each..." | ||
| 50 | echo "---" | ||
| 51 | |||
| 52 | # --- Caches to store fetched data --- | ||
| 53 | declare -A PERMISSION_SET_CACHE | ||
| 54 | declare -A PRINCIPAL_NAME_CACHE | ||
| 55 | FINAL_JSON_ARRAY="[]" # Initialize an empty JSON array | ||
| 56 | |||
| 57 | # --- Step 3: Loop through each provisioned permission set and get its assignments --- | ||
| 58 | for PS_ARN in $PROVISIONED_SETS_ARN; do | ||
| 59 | |||
| 60 | # Get assignments for this specific permission set in this account | ||
| 61 | ACCOUNT_ASSIGNMENTS=$(aws sso-admin list-account-assignments \ | ||
| 62 | --instance-arn "$INSTANCE_ARN" \ | ||
| 63 | --account-id "$ACCOUNT_ID" \ | ||
| 64 | --permission-set-arn "$PS_ARN" \ | ||
| 65 | --query "AccountAssignments[]" --output json) | ||
| 66 | |||
| 67 | if [ "$(echo "$ACCOUNT_ASSIGNMENTS" | jq 'length')" -eq 0 ]; then | ||
| 68 | echo " -> Permission Set ARN $PS_ARN is provisioned but has no active assignments." | ||
| 69 | continue | ||
| 70 | fi | ||
| 71 | |||
| 72 | # Since there are assignments, let's get the permission set's details (policies, name) | ||
| 73 | # Using a cache to avoid redundant calls if a PS is somehow listed twice | ||
| 74 | if [ -z "${PERMISSION_SET_CACHE[$PS_ARN]}" ]; then | ||
| 75 | echo " -> Fetching policies for Permission Set: $PS_ARN" | ||
| 76 | PS_NAME=$(aws sso-admin describe-permission-set --instance-arn "$INSTANCE_ARN" --permission-set-arn "$PS_ARN" --query "PermissionSet.Name" --output text) | ||
| 77 | MANAGED_POLICIES=$(aws sso-admin list-managed-policies-in-permission-set --instance-arn "$INSTANCE_ARN" --permission-set-arn "$PS_ARN" --query "AttachedManagedPolicies[].Arn" --output json) | ||
| 78 | INLINE_POLICY=$(aws sso-admin get-inline-policy-for-permission-set --instance-arn "$INSTANCE_ARN" --permission-set-arn "$PS_ARN" --query "InlinePolicy" --output json) | ||
| 79 | |||
| 80 | PERMISSION_SET_CACHE[$PS_ARN]=$(jq -n \ | ||
| 81 | --arg name "$PS_NAME" \ | ||
| 82 | --argjson managed "$MANAGED_POLICIES" \ | ||
| 83 | --argjson inline "$INLINE_POLICY" \ | ||
| 84 | '{name: $name, policies: {managed_policies: $managed, inline_policy: $inline}}') | ||
| 85 | fi | ||
| 86 | CACHED_PS_DETAILS=${PERMISSION_SET_CACHE[$PS_ARN]} | ||
| 87 | |||
| 88 | # Now process each assignment found for this permission set | ||
| 89 | for row in $(echo "${ACCOUNT_ASSIGNMENTS}" | jq -r '.[] | @base64'); do | ||
| 90 | _jq() { echo ${row} | base64 --decode | jq -r ${1}; } | ||
| 91 | PRINCIPAL_TYPE=$(_jq '.PrincipalType') | ||
| 92 | PRINCIPAL_ID=$(_jq '.PrincipalId') | ||
| 93 | |||
| 94 | # Get Principal (User/Group) Name, using a cache | ||
| 95 | if [ -z "${PRINCIPAL_NAME_CACHE[$PRINCIPAL_ID]}" ]; then | ||
| 96 | PRINCIPAL_NAME="" | ||
| 97 | if [ "$PRINCIPAL_TYPE" == "USER" ]; then | ||
| 98 | PRINCIPAL_NAME=$(aws identitystore describe-user --identity-store-id "$IDENTITY_STORE_ID" --user-id "$PRINCIPAL_ID" --query "UserName" --output text 2>/dev/null) | ||
| 99 | elif [ "$PRINCIPAL_TYPE" == "GROUP" ]; then | ||
| 100 | PRINCIPAL_NAME=$(aws identitystore describe-group --identity-store-id "$IDENTITY_STORE_ID" --group-id "$PRINCIPAL_ID" --query "DisplayName" --output text 2>/dev/null) | ||
| 101 | fi | ||
| 102 | PRINCIPAL_NAME_CACHE[$PRINCIPAL_ID]=${PRINCIPAL_NAME:-"ID: $PRINCIPAL_ID"} | ||
| 103 | fi | ||
| 104 | CACHED_PRINCIPAL_NAME=${PRINCIPAL_NAME_CACHE[$PRINCIPAL_ID]} | ||
| 105 | |||
| 106 | echo " -> Found Assignment: ${CACHED_PRINCIPAL_NAME} ($PRINCIPAL_TYPE) -> $(echo "$CACHED_PS_DETAILS" | jq -r .name)" | ||
| 107 | |||
| 108 | # Build the final JSON object for this assignment | ||
| 109 | ASSIGNMENT_OUTPUT=$(jq -n \ | ||
| 110 | --arg principal_type "$PRINCIPAL_TYPE" \ | ||
| 111 | --arg principal_name "$CACHED_PRINCIPAL_NAME" \ | ||
| 112 | --argjson ps_details "$CACHED_PS_DETAILS" \ | ||
| 113 | '{principal: {type: $principal_type, name: $principal_name}, permission_set: $ps_details}') | ||
| 114 | |||
| 115 | FINAL_JSON_ARRAY=$(echo "$FINAL_JSON_ARRAY" | jq --argjson new_entry "$ASSIGNMENT_OUTPUT" '. += [$new_entry]') | ||
| 116 | done | ||
| 117 | done | ||
| 118 | |||
| 119 | # --- Step 4: Save the final report --- | ||
| 120 | OUTPUT_FILENAME="report_${ACCOUNT_NAME}.json" | ||
| 121 | echo "$FINAL_JSON_ARRAY" | jq '.' > "$OUTPUT_FILENAME" | ||
| 122 | |||
| 123 | echo "---" | ||
| 124 | echo "Success! Report saved to '$OUTPUT_FILENAME'" | ||
| 125 | echo "The file contains all user/group assignments and their policies for account '$ACCOUNT_NAME'." | ||