AWS : Accessing AWS Resources Across Accounts

Assuming Role to Deploy to Production Lamdba from Development Account

AWS : Accessing AWS Resources Across Accounts

Hey there!

Most of the companies use 2 different AWS accounts for production and development. And sometimes you want to use resource of the other account in the second account.

How will you do it ? That's what we discuss in this article.

We here take an example, say we want to update lamdba code in production account via a codepipeline in development account . cross-account-setup.drawio.png

Why Use This Practice

This process is safer than just using your access keys from the production account. Your access keys will be available in your code base which is not a good practice, as who team can use it and you might want to restrict access. If someone gets to see you buildspec file they can get access to the keys.

Login into both the accounts in different browser (or incognito browser) we need them handy as we will be switching between them.

Adding role and trust relationship in production

In your Production Account

  1. Create a Role - say ( prod-access-role )
  2. Give the role the permission to resources you want the development account to be able to access. eg. We want development account to update code of a lambda in production account

  3. Create a Inline Policy inside permissions tab for this role . Name : prod-access-role

    {
     "Version": "2012-10-17",
     "Statement": [
         {
             "Sid": "prodLambdaDeployAccess",
             "Effect": "Allow",
             "Action": [
                 "lambda:UpdateFunctionCode"
             ],
             "Resource": [
                 "arn:aws:lambda:{region}:{prod-account-id}:function:prod-lambda"
             ]
         }
     ]
    }
    

Above policy allow this role to update function code of lambda named prod-lambda.

  1. Now this is the important part which actually sets up the production account to trust some other account.

Adding a trust relationship.

  • Open the role and navigate to Trust relationships tab

image.png

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": "{Your Dev role ARN( **dev-role** )}"
            },
            "Action": "sts:AssumeRole"
        }
    ]
}

In the Development Account

  1. Create a New Role (say dev-role )
  2. Add a policy which allow to assume role ( sts:AssumeRole ) of the production account role. (say cross-account-policy )

Name : cross-account-policy

{
    "Version": "2012-10-17",
    "Statement": [
      {
            "Effect": "Allow",
            "Action": [
                "sts:AssumeRole"
            ],
            "Resource": "arn:aws:iam::{prod-account-id}:role/{prod-resource-role}"
        }
    ]
}

The Above policy is allowing the role (dev-role) to assume a role in the dev account.

image.png You can attach this policy any other user or role, and they can also assume the prod-role can temporarily access the production resource.

Updating Your BuildSpec.yaml file accordingly

If you are using a buildspec.yml file Instead of putting in your AWS credentials for the user you can use the above method with the following -

export $CROSS_ACCOUNT_PROD_ROLE=arn:aws:iam::{prod-account-id}:role/prod-access-role
export $(printf "AWS_ACCESS_KEY_ID=%s AWS_SECRET_ACCESS_KEY=%s AWS_SESSION_TOKEN=%s" $(aws sts assume-role --role-arn $CROSS_ACCOUNT_PROD_ROLE --role-session-name MySessionName --query production"Credentials.[AccessKeyId,SecretAccessKey,SessionToken]" --output text))

reference - %[stackoverflow.com/a/67636523]

This method is a better practice because no one can assume this role by himself , he needs to have the cross-account-policy attached to it .

Your buildspec.yml will look something like this

build:
 commands:
   - export $CROSS_ACCOUNT_PROD_ROLE=arn:aws:iam::{prod-account-id}:role/prod-access-role
   - export $(printf "AWS_ACCESS_KEY_ID=%s AWS_SECRET_ACCESS_KEY=%s 
      AWS_SESSION_TOKEN=%s" $(aws sts assume-role --role-arn 
      $CROSS_ACCOUNT_PROD_ROLE --role-session-name MySessionName --query 
      "Credentials.[AccessKeyId,SecretAccessKey,SessionToken]" --output text))
     .
     .
     .
     [ other build and deploying commands ]

Other Use Cases

  1. Creating a Cloudfront Invalidation
  2. Updating the S3 bucket files

Multiple other resources can access using above method .


Thanks for reading this article.
If this article helped you in some way , drop a like.
I am documenting what I learn.

Connect on twitter - https://twitter.com/prakhartwt