How can I provide cross-account access to objects that are in Amazon S3 buckets?

Last updated: 2022-08-03

I want to grant another AWS account access to an object that is stored in an Amazon Simple Storage Service (Amazon S3) bucket. How can I provide cross-account access to Amazon S3 buckets?

Short description

In Amazon S3, you can grant users in another AWS account (Account B) granular cross-account access to objects owned by your account (Account A).

Depending on the type of access that you want to provide, use one of the following solutions to grant cross-account access to objects:

  • AWS Identity and Access Management (IAM) policies and resource-based bucket policies for programmatic-only access to S3 bucket objects
  • IAM policies and resource-based Access Control Lists (ACLs) for programmatic-only access to S3 bucket objects
    Note: When the Bucket owner enforced setting is enabled, all bucket and object ACLs are disabled. Therefore, you can't use ACLs to grant cross-account access. By default, all newly created buckets have the Bucket owner enforced setting enabled. It's also a best practice to use IAM policies and bucket policies (instead of ACLs) to manage cross-account access to buckets and objects. For more information, see Controlling ownership of objects and disabling ACLs for your bucket.
  • Cross-account IAM roles for programmatic and console access to S3 bucket objects

If the requester is an IAM principal, then the AWS account that owns the principal must grant the S3 permissions through an IAM policy. Based on your specific use case, the bucket owner must also grant permissions through a bucket policy or ACL. After access is granted, programmatic access of cross account buckets is the same as accessing same account buckets.

Resolution

IAM policies and resource-based bucket policies

Note: If you receive errors when running AWS Command Line Interface (AWS CLI) commands, make sure that you’re using the most recent AWS CLI version.

Use resource-based bucket policies to manage cross-account access control and audit the S3 object's permissions. If you apply a bucket policy at the bucket level, you can define the following:

  • Who can access the objects inside the bucket (using the Principal element)
  • Which objects they can access (using the Resource element)
  • How they can access the objects inside the bucket (using the Action element)

Applying a bucket policy at the bucket level allows you to define granular access to different objects inside the bucket. You can also review the bucket policy to see who can access objects in an S3 bucket.

To use bucket policies to manage S3 bucket access, follow these steps:

Note: Replace Account variables with your account.

1.    Create an S3 bucket in Account A.

2.    Create an IAM role or user in Account B.

3.    Give the IAM role in Account B permission to download (GET Object) and upload (PUT Object) objects to and from a specific bucket. Use the following IAM policy to also grant the IAM role in Account B permissions to call PutObjectAcl, granting object permissions to the bucket owner:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:PutObject",
                "s3:PutObjectAcl"
            ],
            "Resource": "arn:aws:s3:::AccountABucketName/*"

        }
    ]
}

Note: Make sure to update the policy to include your user variables (such as account ID, bucket name, and ARN). Also, you can limit access to a specific bucket folder in Account A. To limit access to a specific bucket folder, define the folder name in the resource element, such as "arn:aws:s3:::AccountABucketName/FolderName/*". For more information, see How can I use IAM policies to grant user-specific access to specific folders?

You can also create an IAM identity-based policy using the AWS CLI command example create-policy.

4.    Configure the bucket policy for Account A to grant permissions to the IAM role or user that you created in Account B. Use this bucket policy to grant a user the permissions to GetObject and PutObject for objects in a bucket owned by Account A:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "arn:aws:iam::AccountB:user/AccountBUserName"
            },
            "Action": [
                "s3:GetObject",
                "s3:PutObject",
                "s3:PutObjectAcl"
            ],
            "Resource": [
                "arn:aws:s3:::AccountABucketName/*"
            ]
        }
    ]
}

You can also create an Amazon S3 bucket policy using the AWS CLI command example put-bucket-policy.

Note: You can define a specific S3 bucket folder in the resource element to provide more limited access, such as "Resource": "arn:aws:s3:::AccountABucketName/FolderName/*". By using the s3:PutObject permission with a condition, the bucket owner gets full control over the objects uploaded by other accounts. Enforcing the ACL with specific headers are then passed in the PutObject API call. For more information, see Granting s3:PutObject permission with a condition requiring the bucket owner to get full control.

IAM policies and resource-based ACLs

If ACLs meet your needs better than IAM and S3 bucket policies, then use object ACLs to manage permissions for specific scenarios. For more information, see When to use an ACL-based access policy (bucket and object ACLs). Amazon S3 ACLs allow users to define only the following permissions sets: READ, WRITE, READ_ACP, WRITE_ACP, and FULL_CONTROL. You can use only an AWS account or one of the predefined Amazon S3 groups as a grantee for the Amazon S3 ACL. When specifying email address or the canonical user ID for an AWS account, the ACL applies to all entities in the grantee AWS account. For example, you can't use an ACL to restrict access to individual IAM users or roles. You also can't apply ACLs to different objects that share the same prefixes.

Note: The bucket owner might not have full control over the objects uploaded by the ACL grantee. This is because the ACL doesn't support the condition for the S3 operation that the ACL authorizes.

To use bucket and object ACLs to manage S3 bucket access, follow these steps:

1.    Create an IAM role or user in Account B. Then, grant that role or user permissions to perform the required Amazon S3 operations. Users who call PutObject and GetObject need the permissions listed in the Resource-based policies and IAM policies section.

2.    Configure the bucket ACL to include at least WRITE permission for Account B. This makes sure that Account B IAM roles or users can upload objects (call PutObject API) to a bucket owned by Account A:

...
<AccessControlPolicy>
  <Owner>
    <ID> AccountACanonicalUserID </ID>
    <DisplayName> AccountADisplayName </DisplayName>
  </Owner>
  <AccessControlList>
...
    <Grant>
      <Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CanonicalUser">
        <ID> AccountBCanonicalUserID </ID>
        <DisplayName> AccountBDisplayName </DisplayName>
      </Grantee>
      <Permission> WRITE </Permission>
    </Grant>
    ...
  </AccessControlList>
</AccessControlPolicy>

Note: To find your CanonicalUserID, see Finding an AWS account canonical user ID.

3.    Configure object ACLs to include at least READ permission for Account B. This makes sure that IAM roles or users in Account B can download an object (call GetObject API) from a bucket owned by Account A:

...
<AccessControlPolicy>
  <Owner>
    <ID> AccountACanonicalUserID </ID>
    <DisplayName> AccountADisplayName </DisplayName>
  </Owner>
  <AccessControlList>
...
    <Grant>
      <Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CanonicalUser">
        <ID> AccountBCanonicalUserID </ID>
        <DisplayName> AccountBDisplayName </DisplayName>
      </Grantee>
      <Permission> READ </Permission>
    </Grant>
    ...
  </AccessControlList>
</AccessControlPolicy>

ACL permissions vary based on which S3 resource, bucket, or object that an ACL is applied to. For more information, see Access control list (ACL) overview. You can configure bucket and object ACLs when you create your bucket or when you upload an object to an existing bucket. For more information, see Managing ACLs.

Cross-account IAM roles

Not all AWS services support resource-based policies. Therefore, you can use cross-account IAM roles to centralize permission management when providing cross-account access to multiple services. Using cross-account IAM roles simplifies provisioning cross-account access to S3 objects that are stored in multiple S3 buckets. As a result, you don't need to manage multiple policies for S3 buckets. This method allows cross-account access to objects owned or uploaded by another AWS account or AWS services. If you don't use cross-account IAM roles, then the object ACL must be modified. For more information, see How Amazon S3 authorizes a request for an object operation.

To use cross-account IAM roles to manage S3 bucket access, follow these steps:

1.    Create an IAM role in Account A. Then, grant the role permissions to perform required S3 operations. In the role's trust policy, grant a role or user from Account B permissions to assume the role in Account A:

Note: IAM roles need a trust policy that defines which principals can assume the role and under which conditions. IAM roles can have multiple permissions policies (inline and attached) that define the permissions that a principal assuming the role is able to perform and on which resources.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::AccountB:user/AccountBUserName"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

You can also create a role with the trust policy using the AWS CLI command example create-role.

The following access policy allows a user who assumed this role to download and upload objects programmatically and using the Amazon S3 console. For more information, see How can I use IAM policies to grant user-specific access to specific folders?

Note: If only programmatic access is required, the first two statements in the following policy can be removed:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "s3:ListAllMyBuckets"
            ],
            "Effect": "Allow",
            "Resource": [
                "arn:aws:s3:::*"
            ]
        },
        {
            "Action": [
                "s3:ListBucket",
                "s3:GetBucketLocation"
            ],
            "Effect": "Allow",
            "Resource": "arn:aws:s3:::AccountABucketName"
        },
        {
            "Effect": "Allow",
            "Action": [
                "s3:GetObject",
                "s3:PutObject"
            ],
            "Resource": "arn:aws:s3:::AccountABucketName/*"
        }
    ]
}

You can also create an IAM identity-based policy using the AWS CLI command example create-policy.

2.    Grant an IAM role or user in Account B permissions to assume the IAM role that you created in Account A.

Note: The following example policy must be added as a permissions policy of the IAM user or role.

{
  "Version": "2012-10-17",
  "Statement": {
    "Effect": "Allow",
    "Action": "sts:AssumeRole",
    "Resource": "arn:aws:iam::AccountA:role/AccountARole"
  }
}

You can also create an IAM identity-based policy using the AWS CLI command example create-policy.

3.    From a role in Account B, assume the role in Account A so that IAM entities in Account B can perform the required S3 operations. For more information, see Switching to a role (Console).

Note: By assuming an IAM role in Account A, the Amazon S3 operation is determined by the access policy. The IAM role is deemed as an API call made by a local IAM entity in Account A. A bucket policy or an ACL for cross-account access isn't required. For more information, see Amazon S3 actions.