Reading time ~6 minutes
Cross Account Auditing in AWS and GCP
- AWS Setup
- GCP Setup
Ever been in the situation where you have dozens (or even more) of AWS accounts and/or GCP projects, and are in need to run a security tool against your entire estate?
In this post, part of the “Continuous Visibility into Ephemeral Cloud Environments” series, I’ll try to summarize what cloud resources (like roles and users) are needed, and how to define them in a manner that safely allows to perform a security audit across a fleet of AWS accounts/GCP projects.
The code can be found at: https://github.com/marco-lancini/utils/blob/main/terraform/aws-security-reviewer.
For AWS we are going to use the Hub and Spoke model, where users assume federated roles into a single AWS “identity account” and perform a second role assumption into sub-accounts. For a refresher into this model, you can have a look at the Identity federation with multiple AWS accounts post from Alex Smolen.
First of all, you should have a clear idea of how many AWS accounts you have created in your Organization. Make a list of all the accounts you own, and pick one to be the “Hub” (master) account, which will pull data from all the other accounts (“Spoke” accounts).
At a high level, if we want our security tool to be able to analyse all the AWS accounts within our organization, we will need the following:
- One role (let’s name it
role-security-audit), with the built-in
SecurityAuditpolicy attached to it, which is going to be created in every AWS account (Hub + all the Spoke ones).
- One role (
role-security-assume), in the Hub account, able to assume the
role-security-auditrole on all the other Spoke accounts.
- One IAM user (
user-security-audit), in the Hub account, able to assume the
Sounds convoluted? The following sections will go into details on how to set this up. At the end, though, our setup will look like the picture below.
1. Resource Definition
Once identified all the accounts we want to include, it’s time to focus on the definition of all the resources (like roles and users) we need. Someone might prefer Terraform, someone else CloudFormation, so here I’m going to try stay agnostic from every infrastructure-as-code tool.
A similar implementation in CloudFormation can be found on Gitlab: CloudFormation: AWS Security Reviewer.
role-security-audit in every account
The first resource to define is the IAM role named
this is the end role holding the permissions needed to perform a security audit,
hence why it needs to be created in every account we want to include in our analysis (including the Hub).
Since the role requires the same set of policies in every account, you could create a Terraform/CloudFormation template and apply the resource definition in every account.
- Attach the built-in AWS SecurityAudit IAM policy (
arn:aws:iam::aws:policy/SecurityAudit) to the role.
- Set up a trust relationship so that each account will allow the
role-security-assumerole (that we will create in the Hub account) to assume this role. In the snippet below remember to replace the placeholder
HUB_ACCOUNT_IDwith the ID of your Hub account.
role-security-assume in Hub account
Next, we need to create a role (named
role-security-assume) in the Hub account:
this is the role that is going to be able to assume the
role-security-audit role we created in every other Spoke account.
This role requires a set of policies as well:
- Attach a policy that will allow this role to assume the
role-security-auditrole in every other Spoke account (notice the
- [OPTIONAL] Attach another policy that will grant the permission to describe EC2 regions (required by many tools to identify available regions).
- [OPTIONAL] Attach another policy that will grant the permission to list the accounts within the AWS Organization.
- Set up a trust relationship so that the
user-security-audituser (that we will create next) will be able to assume this role (remember to replace
HUB_ACCOUNT_IDwith the ID of your Hub account).
user-security-audit in Hub account
Finally, the last resource we need is an IAM user (named
user-security-audit) to be defined in the Hub account.
This user only requires one policy that will allow it to assume the
role-security-assume role (again, remember to replace
HUB_ACCOUNT_ID with the ID of your Hub account).
2. Setup Tooling for Cross-Account Auditing
Now that we have setup properly our AWS accounts, we need to instruct our security tools
on how to fetch the relevant credentials that will allow them, after a couple of AssumeRole jumps,
to assume the
role-security-audit in every account:
- The tool obtains short lived credentials for the
- With these credentials, it first performs an AssumeRole call to assume the
role-security-assumein the Hub account.
- Finally, the tool can go through all the accounts in scope, and for each of them perform another AssumeRole call to assume its
First, ne need to instruct our tool on ow to obtain short lived credentials for the
This can be done by modifying the
~/.aws/credentials file used by the tool, and by persisting the temporary credentials of the user under a
Note that this could be automated by dynamically fetching these secrets, for example, from Vault.
Next, we can use the
~/.aws/config file to instruct our tool on how to correctly access the Spoke accounts.
The file will first hold the config for the
default profile (tied to the
Then, you should add a profile for each AWS Spoke account, so that it looks like the example below:
Here, the last line (
source_profile=default) is what actually defines the
profile that contains the credentials that should be used for the initial AssumeRole call.
Setup for GCP is actually more straightforward compared to AWS:
in order for our tools to be able to access GCP assets, they need one Service Account (
security-audit) with the
securityReviewer role attached to it.
It is important to note that, in order for the tools to be access all GCP Projects within an Organization, the Service Account assigned to them needs to be created at the Organization level. This is because IAM access control policies applied on the Organization resource apply throughout the hierarchy on all resources in the organization.
1. Resource Definition
As briefly mentioned above, we need to create a Service Account (which we can name
security-audit) at the Organization level, and attach the following built-in roles to it:
roles/resourcemanager.organizationViewer(needed to list GCP Organizations)
roles/resourcemanager.folderViewer(needed to list GCP Folders)
2. Setup Tooling for Cross-Account Auditing
Now that we have setup properly our GCP accounts, we need to instruct our security tools on how to fetch the relevant credentials.
This can easily be done by setting the
GOOGLE_APPLICATION_CREDENTIALS environment variable to point to the file containing the credentials for the Service Account (see Getting Started with Authentication
for more information).