We recently ran into the problem where one of our Lambdas needed to reach out to a Pinpoint application running in a secondary account. We investigated a number of different options but eventually ended up leveraging a Role that has access to Pinpoint in the secondary account and using STS to assume the role. Note that this requires control over both accounts as you need to provision resources in both.
First a quick overview of the solution:
Now in our specific scenario we were connecting to Pinpoint, but this technique can be used for SES, DynamoDB etcetera.
Let’s decompose this into manageable parts!
Setting up the role in the Pinpoint account
First we create a role in the pinpoint account that is allowed to perform operations on the pinpoint application. Following the principle of least privilege we only allow the external lambda to Get and Update Enpoints. This way we are sure the lambda cannot affect any other resource in the secondary account. Note the role name (role-for-external-lambda
) as we are going to need this in the terraform code for the primary account.
The terraform template contains a number of variables:
var.region
: AWS region in which pinpoint is provisionedvar.account_id
: The AWS account id in which Pinpoint is hosted (Called secondary account in the overview image)var.pinpoint_app_id
: The application_id property of the Pinpoint resourcevar.lambda_account_id
: The AWS account id in which the Lambda is hosted (Called primary account in the overview image)
Now that we’ve setup the secondary account, we can move on to the primary account.
Allowing the Lambda to assume the role
Next we create a policy that allows our Lambda in the other account to assume the role in the secondary account. For this we need the ARN of the role we created in the previous step. We link this policy to the Lambda via the managed_policy_arns property.
The terraform template uses the following variable:
var.pinpoint_aws_account_id
: The AWS account id where Pinpoint is provisioned (Called secondary account in the overview image)
Now that we’ve allowed our lambda to assume the remote role we can move on to the final step.
Add role assumption to the Lambda
Normally when connecting to a pinpoint application that runs in the same AWS account we can connect directly to the application using new PinpointClient()
. In this case we first need to obtain credentials for a role session as the role in the secondary account. We do this by calling the STS client indicating we want to assume the role in the secondary account. If this call is successful and returns credentials we can pass those credentials to the constructor of the pinpoint client and it will use it to connect to the Pinpoint application in the secondary account.
Note that we need to specify the region
in which the Pinpoint application is provisioned.
Wrapping up
We created a dedicated role for access in the secondary account and allowed the lambda in the primary account to assume that role. Finally we added an STS call to our lambda to get credentials to connect to Pinpoint in the secondary account. This way we can safely connect cross accounts and still follow the principle of least privilege.