Cross-account access is made possible because of IAM roles. IAM roles have a distinct capacity to act both as an identity and as a resource, and as such, you can associate both identity-based policies and resource-based policies with IAM roles. In the case of IAM roles, resource-based policies are also called trust policies.
To illustrate how this works, consider that an organization stores some data on S3 in a central account and makes it available to other accounts in the organization. By default, none of the other accounts has permission to perform any action on the S3 bucket belonging to the central account.
One solution consists of using resource-based policies and giving read or write access, as needed, to that central S3 bucket and to all the other accounts. But because not all AWS services support resource-based policies, look at a more generic solution that could also work with other AWS services and not just Amazon S3.
In this case, the generic approach consists of leveraging IAM roles and establishing trust between the central account and the other accounts. An IAM role can be assumed by another principal (user or role), including from another account, if they have the right permissions. For this, you create an IAM role in the account where the resources need to be accessed from other accounts, where you will establish trust. The central account is the trusting account, while all the other accounts that need to access resources in that account are the trusted accounts.
In the central account (call it AccountA), you define a role (call it roleA), and you assign that role a trust policy in which you specify that it can be assumed by other principals from any other accounts that need to. Suppose that you need to get it accessed by userB from another account, AccountB. The trust policy would look something like this:
{
“Version”: “2012-10-17”,
“Statement”: [
{
“Effect”: “Allow”,
“Principal”: {
“AWS”: “arn:aws:iam::AccountB:user/userB”
},
“Action”: “sts:AssumeRole”
}
]
}
This trust policy instructs IAM that roleA in accountA can be assumed by userB from accountB.
So, you need to provide roleA enough privileges to be able to read or write to S3 on the account. You do this by either assigning an identity-based policy to roleA or by attaching resource-based policies to the relevant S3 buckets, to give the necessary permissions to roleA. See the previous sections on identity-based and resource-based policies for more details.
Now, most importantly, in accountB, you must also give userB permissions to assume roleA in accountA. You set such permissions in an identity-based policy that you assign to userB, such as this:
{
“Version”: “2012-10-17”,
“Statement”: {
“Effect”: “Allow”,
“Action”: “sts:AssumeRole”,
“Resource”: “arn:aws:iam::AccountA:role/roleA”
}
}
When userB in accountB assumes roleA in accountA, they inherit the permissions assigned to roleA and can then perform any action roleA is entitled to on resources in accountA.