Sometimes you need to access objects of S3 bucket present in other AWS account. So for that you need to do cross account setup.
Let’s say you want to access objects of S3 bucket present in AWS account A from AWS account B.
Cross account Amazon S3 setup:
For that we need to follow below steps:
- Create S3 bucket in account A:
resource "aws_s3_bucket" "account-a-s3-bucket" {
bucket = "account-a-s3-bucket"
acl = "private"
tags = {
# provide tags if you want
}
}
resource "aws_s3_bucket_object" "users-object" {
bucket = aws_s3_bucket.account-a-s3-bucket.id
key = "User/"
acl = "private"
}
resource "aws_s3_bucket_object" "user-usera-edu-data" {
bucket = aws_s3_bucket.account-a-s3-bucket.id
key = "User/user-a/edu-data/"
acl = "private"
}
resource "aws_s3_bucket_object" "user-usera-other-data" {
bucket = aws_s3_bucket.account-a-s3-bucket.id
key = "User/user-a/other-data/"
acl = "private"
}
resource "aws_s3_bucket_object" "user-userb" {
bucket = aws_s3_bucket.account-a-s3-bucket.id
key = "User/user-b/"
acl = "private"
}
resource "aws_s3_bucket_object" "user-userc" {
bucket = aws_s3_bucket.account-a-s3-bucket.id
key = "User/user-c/"
acl = "private"
}
This will create objects as below:
- Now, create IAM policy in AWS account A, which will be used to access S3 bucket objects:
2.1 Do below if you want to give access of complete S3 bucket:
resource "aws_iam_policy" "cross-account-s3-bucket-rw-access-policy" {
name = "cross-account-s3-bucket-rw-access-policy"
policy = data.aws_iam_policy_document.cross-account-s3-bucket-rw-access-policy-document.json
}
data "aws_iam_policy_document" "cross-account-s3-bucket-rw-access-policy-document" {
statement {
sid = "AllowListGetPutAndDeleteActions"
effect = "Allow"
actions = [
"s3:List*",
"s3:Get*",
"s3:PutObject",
"s3:DeleteObject"
]
resources = ["arn:aws:s3:::account-a-s3-bucket/*"]
}
}
2.2 Do below if you want to give access of specific objects of S3 bucket:
resource "aws_iam_policy" "cross-account-s3-bucket-rw-access-policy" {
name = "cross-account-s3-bucket-rw-access-policy"
policy = data.aws_iam_policy_document.cross-account-s3-bucket-rw-access-policy-document.json
}
data "aws_iam_policy_document" "cross-account-s3-bucket-rw-access-policy-document" {
#give access to list all objects at root level of bucket and User object level
statement {
sid = "AllowRootAndUserListingOfAccountABucket"
actions = ["s3:ListBucket"]
effect = "Allow"
resources = ["arn:aws:s3:::account-a-s3-bucket"]
condition {
test = "StringEquals"
values = ["", "User/"]
variable = "s3:prefix"
}
}
# give access to list all objects in objects user-a and user-b
statement {
sid = "AllowListingOfOtherFoldersInUserFolder"
actions = ["s3:ListBucket"]
effect = "Allow"
resources = ["arn:aws:s3:::account-a-s3-bucket"]
condition {
test = "StringLike"
values = ["User/user-a/*", "User/user-b/*"]
variable = "s3:prefix"
}
}
# give access to get, put and delete objects of user-a's and user-b's all subfolders/objects
statement {
sid = "AllowGetPutAndDeleteActions"
effect = "Allow"
actions = [
"s3:PutObject",
"s3:GetObject",
"s3:DeleteObject"
]
resources = ["arn:aws:s3:::account-a-s3-bucket/User/user-a/edu-data/*", "arn:aws:s3:::account-a-s3-bucket/User/user-b/*"]
}
}
- Now, create IAM role in AWS account A and attach above(point 2) created policy to it:
resource "aws_iam_role" "cross-account-s3-bucket-access-role" {
name = "cross-account-s3-bucket-rw-access-role"
assume_role_policy = data.aws_iam_policy_document.cross-role-s3-bucket-rw-access-policy-document.json
}
data "aws_iam_policy_document" "cross-role-s3-bucket-rw-access-policy-document" {
statement {
actions = ["sts:AssumeRole"]
principals {
type = "AWS"
# this will allow account B's IAM role to assume cross-account-s3-bucket-rw-access-role
identifiers = ["arn:aws:iam::<aws_account_b_id>:role/<account_b_iam_role_name>"]
}
# uncomment below condition block if you want to use ExternalId validation while role assumption
# condition {
# test = "StringEquals"
# values = ["some-external-id"]
# variable = "sts:ExternalId"
# }
effect = "Allow"
}
}
resource "aws_iam_policy_attachment" "cross-account-s3-bucket-rw-access-policy-attachment" {
name = "CrossAccountS3rwAccessPolicyAttachment"
roles = [
aws_iam_role.cross-account-s3-bucket-access-role.name
]
policy_arn = aws_iam_policy.cross-account-s3-bucket-rw-access-policy.arn
}
- Now, create IAM policy in AWS account B to assume AWS account A’s IAM role:
resource "aws_iam_policy" "cross-account-assume-role-policy" {
name = "cross-account-assume-role-policy"
policy = data.aws_iam_policy_document.cross-account-assume-role-policy-document.json
}
data "aws_iam_policy_document" "cross-account-assume-role-policy-document" {
statement {
sid = "AllowToAssumeAccountAIAMRole"
effect = "Allow"
actions = [
"sts:AssumeRole"
]
resources = ["arn:aws:iam::<aws_account_a_id>:role/cross-account-s3-bucket-rw-access-role"]
}
}
- Now, create IAM role in account B and attach above(point 4) created policy to it:
resource "aws_iam_role" "cross-account-s3-access-role" {
name = "cross-account-s3-access-role"
assume_role_policy = data.aws_iam_policy.cross-account-assume-role-policy.json
}
Hurray, you are done with setup :)
Now, after assuming IAM role cross-account-s3-access-role, you can assume account A’s IAM role cross-account-s3-bucket-rw-access-role using AWS cli and access objects of bucket account-a-s3-bucket:
aws sts assume-role --role-arn arn:aws:iam::<aws_account_a_id>:role/cross-account-s3-bucket-rw-access-role --role-session-name cross-account-s3-access
Thank you for reading, please follow if you like the article.
Subscribe to stay tuned for upcoming articles.