Creating AWS IAM Access Analyzers In All Regions Of All Accounts

Amazon recently announced the AWS IAM Access Analyzer, a useful tool to help discover if you have granted unintended access to specific types of resources in your AWS account.

At the moment, an Access Analyzer needs to be created in each region of each account where you want to run it.

Since this manual requirement can be a lot of work, it is a common complaint from customers. Given that Amazon listens to customer feedback and since we currently have to specify a “type” of “ACCOUNT”, I expect at some point Amazon may make it easier to run Access Analyzer across all regions and maybe in all accounts in an AWS Organization. Until then…

This article shows how I created an AWS IAM Access Analyzer in all regions of all accounts in my AWS Organization using the aws-cli.

Prerequisites

To make this easy, I use the bash helper functions that I defined in last week’s blog post here:

Running AWS CLI Commands Across All Accounts In An AWS Organization

Please read the blog post to see what assumptions I make about the AWS Organization and account setup. You may need to tweak things if your setup differs from mine.

Here is my GitHub repo that makes it more convenient for me to install the bash functions. If your AWS account structure matches mine sufficiently, it might work for you, too:

https://github.com/alestic/aws-cli-multi-account-sessions

IAM Access Analyzer In All Regions Of Single Account

To start, let’s show how to create an IAM Access Analyzer in all regions of a single account.

Here’s a simple command to get all the regions in the current AWS account:

aws ec2 describe-regions \
  --output text \
  --query 'Regions[][RegionName]'

This command creates an IAM Access Analyzer in a specific region. We’ll tack on a UUID because that’s what Amazon does, though I suspect it’s not really necessary.

region=us-east-1
uuid=$(uuid -v4 -FSIV || echo "1") # may need to install "uuid" command
analyzer="accessanalyzer-$uuid"
aws accessanalyzer create-analyzer \
   --region "$region" \
   --analyzer-name "$analyzer" \
   --type ACCOUNT

By default, there is a limit of a single IAM Access Analyzer per account region. The fact that this is a “default limit” implies that it may be increased by request, but for this guide, we’ll just not create an IAM Access Analyzer if one already exists.

This command lists the name of any IAM Access Analyzers that might already have been created in a region:

region=us-east-1
aws accessanalyzer list-analyzers \
  --region "$region" \
  --output text \
  --query 'analyzers[][name]'

We can put the above together, iterating over the regions, checking to see if an IAM Access Analyzer already exists, and creating one if it doesn’t:

regions=$(aws ec2 describe-regions \
  --output text \
  --query 'Regions[][RegionName]' |
  sort)

for region in $regions; do
  analyzer=$(aws accessanalyzer list-analyzers \
    --region "$region" \
    --output text \
    --query 'analyzers[][name]')
  if [ -n "$analyzer" ]; then
    echo "$region: EXISTING: $analyzer"
  else
    uuid=$(uuid -v4 -FSIV || echo "1") # may need to install "uuid" command
    analyzer="accessanalyzer-$uuid"
    echo "$region: CREATING: $analyzer"
    aws accessanalyzer create-analyzer \
       --region "$region" \
       --analyzer-name "$analyzer" \
       --type ACCOUNT \
       > /dev/null # only show errors
  fi
done

Creating IAM Access Analyzers In All Regions Of All Accounts

Now let’s prepare to run the above in multiple accounts using the aws-cli-multi-account-sessions bash helper functions from last week’s article:

git clone git@github.com:alestic/aws-cli-multi-account-sessions.git
source aws-cli-multi-account-sessions/functions.sh

Specify the values for source_profile and mfa_serial from your aws-cli config file. You can leave the mfa_serial empty if you aren’t using MFA:

source_profile=your_aws_cli_source_profile
mfa_serial=arn:aws:iam::YOUR_ACCOUNT:mfa/YOUR_USER

Specify the role you can assume in all accounts:

role="admin" # Yours might be called "OrganizationAccountAccessRole"

Get a list of all accounts in the AWS Organization, and a list of all regions:

accounts=$(aws organizations list-accounts \
             --output text \
             --query 'Accounts[].[JoinedTimestamp,Status,Id,Email,Name]' |
           grep ACTIVE |
           sort |
           cut -f3) # just the ids

regions=$(aws ec2 describe-regions \
            --output text \
            --query 'Regions[][RegionName]' |
          sort)

Run this once to create temporary session credentials with MFA:

aws-session-init $source_profile $mfa_serial

Iterate through AWS accounts, running the necessary AWS CLI commands to create an AIM Access Analyzer in each account/role and each region:

for account in $accounts; do
  echo "Visiting account: $account"
  aws-session-set $account $role || continue

  for region in $regions; do
    # Run the aws-cli commands using the assume role credentials
    analyzers=$(aws-session-run \
                  aws accessanalyzer list-analyzers \
                    --region "$region" \
                    --output text \
                    --query 'analyzers[][name]')
    if [ -n "$analyzers" ]; then
      echo "$account/$region: EXISTING: $analyzers"
    else
      uuid=$(uuid -v4 -FSIV || echo "1")
      analyzer="accessanalyzer-$uuid"
      echo "$account/$region: CREATING: $analyzer"
      aws-session-run \
        aws accessanalyzer create-analyzer \
          --region "$region" \
          --analyzer-name "$analyzer" \
          --type ACCOUNT \
          > /dev/null # only show errors
    fi
  done
done

Clear out bash variables holding temporary AWS credentials:

aws-session-cleanup

In a bit, you can go to the AWS IAM Console and view what the Access Analyzers found.

Yep, you have to look at the Access Analyzer findings in each account and each region. Wouldn’t it be nice if we had some way to collect all this centrally? I think so, too, so I’m looking into what can be done there. Thoughts welcome in the comments below or on Twitter.

Cleanup

The following deletes all IAM Access Analyzers in all regions in the current account. You don’t need to do this if you want to leave the IAM Access Analyzers running, especially since there is no additional cost for keeping them.

# WARNING! DESTRUCTIVE!

source_profile=[as above]
mfa_serial=[as above]
role=[as above]

accounts=$(aws organizations list-accounts \
             --output text \
             --query 'Accounts[].[JoinedTimestamp,Status,Id,Email,Name]' |
           grep ACTIVE |
           sort |
           cut -f3) # just the ids

regions=$(aws ec2 describe-regions \
            --profile "$source_profile" \
            --output text \
            --query 'Regions[][RegionName]' |
          sort)

aws-session-init $source_profile $mfa_serial

for account in $accounts; do
  echo "Visiting account: $account"
  aws-session-set $account $role || continue

  for region in $regions; do
    # Run the aws-cli commands using the assume role credentials
    analyzers=$(aws-session-run \
                  aws accessanalyzer list-analyzers \
                    --region "$region" \
                    --output text \
                    --query 'analyzers[][name]')
    for analyzer in $analyzers; do
      echo "$account/$region: DELETING: $analyzer"
      aws-session-run \
        aws accessanalyzer delete-analyzer \
          --region "$region" \
          --analyzer-name "$analyzer"
    done
  done
done

aws-session-cleanup