Configure cross-account access to Amazon DynamoDB
Created by Shashi Dalmia (AWS) and Jay Enjamoori (AWS)
Environment: Production | Technologies: DevOps; Databases; Security, identity, compliance | AWS services: Amazon DynamoDB; AWS Identity and Access Management; AWS Lambda |
Summary
This pattern explains the steps for configuring cross-account access to Amazon DynamoDB. Amazon Web Services (AWS) services can access DynamoDB tables that are in the same AWS account if the service has the appropriate AWS Identity and Access Management (IAM) permissions set up in the database. However, access from a different AWS account requires setting up IAM permissions and establishing a trust relationship between the two accounts.
This pattern provides steps and sample code to demonstrate how you can configure AWS Lambda functions in one account to read and write to a DynamoDB table in a different account.
Prerequisites and limitations
Two active AWS accounts. This pattern refers to these accounts as Account A and Account B.
AWS Command Line Interface (AWS CLI) installed and configured to access Account A, to create the DynamoDB database. The other steps in this pattern provide instructions for using the IAM, DynamoDB, and Lambda consoles. If you’re planning to use AWS CLI instead, configure it to access both accounts.
Architecture
In the following diagram, AWS Lambda, Amazon EC2, and DynamoDB are all in the same account. In this scenario, Lambda functions and Amazon Elastic Compute Cloud (Amazon EC2) instances can access DynamoDB.
If resources in a different AWS account try to access DynamoDB, they require setting up cross-account access and a trust relationship. For example, in the following diagram, to enable access between DynamoDB in Account A and the Lambda function in Account B, you must create a trust relationship between the accounts and grant appropriate access to the Lambda service and users, as described in the Epics section.
Tools
AWS services
Amazon DynamoDB is a fully managed NoSQL database service that provides fast and predictable performance with seamless scalability.
AWS Lambda is a compute service that supports running code without provisioning or managing servers. Lambda runs your code only when needed and scales automatically, from a few requests per day to thousands per second. You pay only for the compute time that you consume—there is no charge when your code is not running.
AWS Identity and Access Management (IAM) helps you securely manage access to your AWS resources by controlling who is authenticated and authorized to use them.
Code
This pattern includes sample code in the Additional information section to illustrate how you can configure a Lambda function in Account B to write and read from the DynamoDB table in Account A. The code is provided for illustration and testing purposes only. If you’re implementing this pattern in a production environment, use the code as a reference and customize it for your own environment.
This pattern illustrates cross-account access with Lambda and DynamoDB. You can use the same steps for other AWS services as well, but make sure that you grant and configure the appropriate permissions in both accounts. For example, if you want to grant access to an Amazon Relational Database Service (Amazon RDS) database in Account A, create a role for that database and bind it with a trust relationship. In Account B, if you want to use Amazon EC2 instead of AWS Lambda, create the respective IAM policy and role, and then attach them to the EC2 instance.
Epics
Task | Description | Skills required |
---|---|---|
Create a DynamoDB table in Account A. | After you configure AWS CLI for Account A, use the following AWS CLI command to create a DynamoDB table:
For more information about creating tables, see the DynamoDB documentation. | AWS DevOps |
Task | Description | Skills required |
---|---|---|
Create a role in Account A. | This role will be used by Account B to gain permissions to access Account A. To create the role:
For more information about creating roles, see the IAM documentation. | AWS DevOps |
Note the ARN for the role in Account A. |
| AWS DevOps |
Task | Description | Skills required |
---|---|---|
Create a policy to access Account A. |
For more information about creating policies, see the IAM documentation. | AWS DevOps |
Create a role based on the policy. | This role is used by the Lambda functions in Account B to read from and write to the DynamoDB table in Account A.
You can now attach this role to the Lambda functions in the next epic. For more information about creating roles, see the IAM documentation. | AWS DevOps |
Task | Description | Skills required |
---|---|---|
Create a Lambda function to write data to DynamoDB. |
For more information about creating Lambda functions, see the Lambda documentation. | AWS DevOps |
Create a Lambda function to read data from DynamoDB. |
For more information about creating Lambda functions, see the Lambda documentation. | AWS DevOps |
Task | Description | Skills required |
---|---|---|
Delete the resources you created. | If you’re running this pattern in a testing or proof of concept (PoC) environment, delete the resources you created to avoid incurring costs.
| AWS DevOps |
Related resources
Getting started with the AWS CLI (AWS CLI documentation)
Configuring the AWS CLI (AWS CLI documentation)
Getting started with DynamoDB (DynamoDB documentation)
Getting started with Lambda (AWS Lambda documentation)
Creating a role to delegate permissions to an IAM user (IAM documentation)
Creating IAM policies (IAM documentation)
Cross-account policy evaluation logic (IAM documentation)
IAM JSON policy elements reference (IAM documentation)
Additional information
The code in this section is provided for illustration and testing purposes only. If you’re implementing this pattern in a production environment, use the code as a reference and customize it for your own environment.
Lambda write function
Sample code
import boto3 from datetime import datetime sts_client = boto3.client('sts') sts_session = sts_client.assume_role(RoleArn='arn:aws:iam::<Account-A ID>:role/DynamoDB-FullAccess-For-Account-B', RoleSessionName='test-dynamodb-session') KEY_ID = sts_session['Credentials']['AccessKeyId'] ACCESS_KEY = sts_session['Credentials']['SecretAccessKey'] TOKEN = sts_session['Credentials']['SessionToken'] dynamodb_client = boto3.client('dynamodb', region_name='<DynamoDB-table-region-in-account-A', aws_access_key_id=KEY_ID, aws_secret_access_key=ACCESS_KEY, aws_session_token=TOKEN) def lambda_handler(event, context): now = datetime.now() date_time = now.strftime("%m/%d/%Y, %H:%M:%S") data = dynamodb_client.put_item(TableName='Table-Acccount-A', Item={"category": {"S": "Fruit"},"item": {"S": "Apple"},"time": {"S": date_time}}) return data
Sample output
Lambda read function
Sample code
import boto3 from datetime import datetime sts_client = boto3.client('sts') sts_session = sts_client.assume_role(RoleArn='arn:aws:iam::<Account-A ID>:role/DynamoDB-FullAccess-For-Account-B', RoleSessionName='test-dynamodb-session') KEY_ID = sts_session['Credentials']['AccessKeyId'] ACCESS_KEY = sts_session['Credentials']['SecretAccessKey'] TOKEN = sts_session['Credentials']['SessionToken'] dynamodb_client = boto3.client('dynamodb', region_name='<DynamoDB-table-region-in-account-A>', aws_access_key_id=KEY_ID, aws_secret_access_key=ACCESS_KEY, aws_session_token=TOKEN) def lambda_handler(event, context): response = dynamodb_client.get_item(TableName='Table-Acccount-A', Key={'category':{'S':'Fruit'}, 'item':{'S':'Apple'}}) return response
Sample output