audit-labs/audit-tools

A collection of scripts, queries, and other goodies you can use in an audit. audit automation compliance evidence scripts

Commit 81f9451625

81f9451625531a83f62696a46e5388ab640b6e7c

parent: 5f427bd86d

Unsigned

cmc <hello@cleberg.net> · 2025-12-11 18:15 UTC

add aws script

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
10Fetching IAM Identity Center and Account details...
11Successfully found Account 'cmc' with ID: 214941490075
12---
13Step 2: Finding all permission sets provisioned to 'cmc'...
14Found 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---
23Success! Report saved to 'report_cmc.json'
24The file contains all user/group assignments and their policies for account 'cmc'.
25```
26
27``` bash
28cat 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 ---
8ACCOUNT_NAME=""
9
10# --- Prerequisite check ---
11if ! 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
14fi
15
16# --- Step 1: Get Instance details and find the target Account ID ---
17echo "Fetching IAM Identity Center and Account details..."
18
19INSTANCE_ARN=$(aws sso-admin list-instances --query "Instances[0].InstanceArn" --output text)
20IDENTITY_STORE_ID=$(aws sso-admin list-instances --query "Instances[0].IdentityStoreId" --output text)
21
22if [ -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
25fi
26
27ACCOUNT_ID=$(aws organizations list-accounts --query "Accounts[?Name=='$ACCOUNT_NAME' && Status=='ACTIVE'].Id" --output text)
28
29if [ -z "$ACCOUNT_ID" ]; then
30 echo "Error: Could not find an active AWS account with the name '$ACCOUNT_NAME'."
31 exit 1
32fi
33
34echo "Successfully found Account '$ACCOUNT_NAME' with ID: $ACCOUNT_ID"
35echo "---"
36
37# --- Step 2: Get all Permission Sets provisioned to the account ---
38echo "Step 2: Finding all permission sets provisioned to '$ACCOUNT_NAME'..."
39PROVISIONED_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
44if [ -z "$PROVISIONED_SETS_ARN" ]; then
45 echo "No permission sets are provisioned for account '$ACCOUNT_NAME'."
46 exit 0
47fi
48
49echo "Found provisioned permission sets. Now checking assignments for each..."
50echo "---"
51
52# --- Caches to store fetched data ---
53declare -A PERMISSION_SET_CACHE
54declare -A PRINCIPAL_NAME_CACHE
55FINAL_JSON_ARRAY="[]" # Initialize an empty JSON array
56
57# --- Step 3: Loop through each provisioned permission set and get its assignments ---
58for 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
117done
118
119# --- Step 4: Save the final report ---
120OUTPUT_FILENAME="report_${ACCOUNT_NAME}.json"
121echo "$FINAL_JSON_ARRAY" | jq '.' > "$OUTPUT_FILENAME"
122
123echo "---"
124echo "Success! Report saved to '$OUTPUT_FILENAME'"
125echo "The file contains all user/group assignments and their policies for account '$ACCOUNT_NAME'."