Introduction#
Github explains basics of cross-account access by assuming role.
- dev account access prod account (iam users)
- a lambda function from dev account access s3 in prod account
in production account
- create a role and specify which principal (dev account arn, lambda function arn) can assume this role
- policy and speify what permission this role can do
Trust Policy in Prod Account#
the trust policy in prod account tells that $DEV_ACCOUNT can assume this role
{"Version": "2012-10-17","Statement": [{"Sid": "PolicyForAccessingS3","Effect": "Allow","Principal": {"AWS": "arn:aws:iam::$DEV_ACCOUNT:user/$DEV_USER_NAME"},"Action": "sts:AssumeRole"}]}
the trust policy in prod account tells that the lambda-arn in another account can assume this role
{"Version": "2012-10-17","Statement": [{"Sid": "LambdaAssumeRole","Effect": "Allow","Principal": {"AWS": "arn:aws:iam::$DEV_ACCOUNT:role/service-role/lambda-role"},"Action": "sts:AssumeRole"}]}
a policy attached to this role to grant s3 access (access s3 buckets in Prod account) to the role
{"Version": "2012-10-17","Statement": [{"Sid": "AccessS3Policy","Effect": "Allow","Action": "s3:*","Resource": "*"}]}
Using CLI#
please export PRODUCT_ACCOUNT=1111-2222-3333-4444 we need to provide a trust policy to tell who or what service can assume the role
aws iam create-role \--role-name RoleForAccessS3 \--assume-role-policy-document \file://trust_policy.json
update an existing role trust policy (relationship)
aws iam update-assume-role-policy \--role-name RoleForAccessS3 \--policy-document \file://trust_policy.json
create a policy to allow accessing s3
aws iam create-policy \--policy-name AccessS3PolicyCrossAccount \--policy-document file://policy_access_s3.json
attach an policy to a role
aws iam attach-role-policy \--role-name RoleForAccessS3 \--policy-arn arn:aws:iam::$PRODUCT_ACCOUNT:policy/AccessS3PolicyCrossAccount
assume role from dev account
aws sts assume-role \--role-arn arn:aws:iam::$PRODUCT_ACCOUNT:role/RoleForAccessS3 \--role-session-name session
revoke to stop effectiveness of the role
Using CDK Stack#
In the prod account create a role and tell who will assume the role. Create this stack (role) in the prod account.
const role = new aws_iam.Role(this, 'AssumedRoleByGuestAccount', {roleName: 'AssumedRoleByGuestAccount',assumedBy: new aws_iam.AccountPrincipal(props.account_id_guest),description: 'enable a guest account to access s3'})
attach a policy to tell what this role can do
role.attachInlinePolicy(new aws_iam.Policy(this, 'PolicyAllowGuestAccountToAccessS3', {statements: [new aws_iam.PolicyStatement({effect: aws_iam.Effect.ALLOW,actions: ['s3:*'],resources: ['*']}),new aws_iam.PolicyStatement({effect: aws_iam.Effect.ALLOW,actions: ['sts:AssumeRole'],resources: ['*']})]}))
take note the role arn and give it to the dev account
new CfnOutput(this, 'AssumeRoleArn', {value: role.roleArn})
Assume the role#
From the dev account, assume the role as a AWSCLI Session
aws sts assume-role --role-arn "arn:aws:iam:PROD_ACCOUNT_ID:role/AssumedRoleByGuesAccount" \--role-session-name session
Then take note temporary credentials
export AWS_ACCESS_KEY_ID="AWS_ACCESS_KEY_ID"export AWS_SECRET_ACCESS_KEY="AWS_SECRET_ACCESS_KEY"export AWS_SESSION_TOKEN="AWS_SESSION_TOKEN"
Test it
aws s3 ls
Lambda Function#
please setup permission for this lambda to do sts:AssumeRole, and also double check that in the production account, this lambda-arn can assume the role in the production account.
import osimport jsonimport uuidimport boto3BUCKET_NAME = "PROD_ACCOUNT_BUCKET"ROLE_ARN = "arn:aws:iam::$PROD_ACCOUNT_ID:role/DevAccountAccessS3Role"def write_to_s3_with_credentials():"""configure s3 client with credentials"""s3Client = boto3.client("s3",aws_access_key_id=os.environ["AWS_ACCESS_KEY"],aws_secret_access_key=os.environ["AWS_SECRET_KEY"],aws_session_token=os.environ["AWS_SESSION_TOKEN"],)# write data to s3try:s3Client.put_object(Bucket=BUCKET_NAME, Key=str(uuid.uuid4()), Body=b"Hello HaiTran")except:print("error write to s3")def sts_assume_role_token():"""get token when assume a role can be cross-account"""stsClient = boto3.client("sts")credentials = stsClient.assume_role(RoleArn=ROLE_ARN, RoleSessionName="RoleSessionDemo")print(credentials)#os.environ["AWS_ACCESS_KEY"] = credentials["Credentials"]["AccessKeyId"]os.environ["AWS_SECRET_KEY"] = credentials["Credentials"]["SecretAccessKey"]os.environ["AWS_SESSION_TOKEN"] = credentials["Credentials"]["SessionToken"]def lambda_handler(event, context):"""write to s3 in another accountfrom the product account, please specify thatwhich lambda (ARN) can assume this role."""# assume role and get credentialssts_assume_role_token()# write to s3 in another accountwrite_to_s3_with_credentials()# returnreturn {"statusCode": 200, "body": json.dumps("Hello from Lambda!")}