Melissa Guo
Melissa Guo

Reputation: 1088

Do I always have to explicitly assume a role to access S3?

I have am trying to set up cross account S3 access. My account A has access to files in account B's S3 location. I did the below steps:

  1. IAM Role B was created in account B with access to the S3 location
  2. IAM Role A was created in account A which we will use to assume role B
  3. Role B added account A to its trusted relationships and granted KMS permissions
  4. Role A added inline permission policies to assume role B and use the KMS key

I am able to access the S3 files by explicitly assuming account B's role using the below code:

client = boto3.client('sts')
response = client.assume_role(RoleArn=source_role, RoleSessionName='cross_account_session',DurationSeconds=3600)
credentials = response['Credentials']

Is there any way to set this up so I do not have to explicitly assume the role? i.e. Given that the trust relationship has already been established, if I am using account A and try to access account B's S3 bucket, can the permissions automatically be granted without me having to invoke client.assume_role()?

Upvotes: 1

Views: 1265

Answers (2)

franklinsijo
franklinsijo

Reputation: 18270

You must explicitly assume role to be able to perform cross-account operations.

But for the scenario in hand, i.e., cross account access for KMS encrypted S3 Bucket, role assumption can be skipped by granting access to S3 and KMS using Resource policies.

In Account B, add this Bucket policy to the S3 Bucket

{
  "Version":"2012-10-17",
  "Statement":[
    {
      "Sid":"CrossAccountReadAccess",
      "Effect":"Allow",
      "Principal": {
        "AWS": [
          "arn:aws:iam::<AccountA-ID>:root"
         ]   
      },
      "Action":[
             "s3:GetObject",
             "s3:GetBucketLocation",
             "s3:ListBucket"
      ],
      "Resource":[
         "arn:aws:s3:::bucketname",
         "arn:aws:s3:::bucketname/*"
       ]
    }
  ]
}

In Account B, add this Key Policy to the KMS Key used for encrypting the Objects

{
    "Sid": "CrossAccountDecryptAccess",
    "Effect": "Allow",
    "Principal": {
       "AWS": [
         "arn:aws:iam::<AccountA-ID>:root" 
       ]
    },
    "Action": [
        "kms:Decrypt",
        "kms:DescribeKey",
        "kms:GenerateDataKey*"
    ],
    "Resource": "*"
}

The Principal is mentioned as root for both the policies, modify it to restrict it to any IAM User in Account A.

And for that User in Account A, Update the IAM Policy to allow the corresponding S3 and KMS access.

Note: The resource policies are defined here are only for Read Access. Update the Action in the policy statements to grant more access if required.

CAUTION: If Write privileges are granted then the objects written by Account A will be owned by Account A only. bucket-owner-full-control ACL must be explicitly added to these objects for Account B to be able to access them.

Upvotes: 2

jarmod
jarmod

Reputation: 78733

One other option you have is to add an S3 bucket policy to the destination bucket, giving access to the specific IAM user (or IAM role) in the source AWS account. For example:

{
  "Version":"2012-10-17",
  "Statement":[
    {
      "Sid":"melissalist",
      "Effect":"Allow",
      "Principal": { "AWS": "arn:aws:iam::999999999999:user/melissa" },
      "Action":["s3:List*"],
      "Resource":["arn:aws:s3:::mybucket"]
    },
    {
      "Sid":"melissaget",
      "Effect":"Allow",
      "Principal": { "AWS": "arn:aws:iam::999999999999:user/melissa" },
      "Action":["s3:GetObject"],
      "Resource":["arn:aws:s3:::mybucket/*"]
    }
  ]
}

You can find your source IAM identity in the AWS IAM console, or you can use the awscli:

aws sts get-caller-identity

Results:

{
  "UserId": "AIDAAAAAAAAAAAAAAAAAA",
  "Account": "999999999999",
  "Arn": "arn:aws:iam::999999999999:user/melissa"
}

Upvotes: 2

Related Questions