Configure cross-account access to Amazon DynamoDB
Created by Shashi Dalmia (AWS), Esteban Serna Parra (AWS), and Imhoertha Ojior (AWS)
Environment: Production | Technologies: 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 by using resource-based policies. For workloads that use DynamoDB, it's becoming more common to use workload isolation strategies
Resource-based policies for DynamoDB greatly simplify the security posture for cross-account workloads. This pattern provides steps and sample code to demonstrate how you can configure AWS Lambda functions in one AWS account to write data to a DynamoDB database table in a different account.
Prerequisites and limitations
Prerequisites
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 table. 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.
Limitations
Some AWS services aren’t available in all AWS Regions. For Region availability, see AWS services by Region
. For specific endpoints, see the Service endpoints and quotas page, and choose the link for the service.
Architecture
The following diagram shows a single-account architecture. AWS Lambda, Amazon Elastic Compute Cloud (Amazon EC2), and DynamoDB are all in the same account. In this scenario, Lambda functions and Amazon EC2 instances can access DynamoDB. To grant access to the DynamoDB table, you can create an identity-based policy in IAM, or you can create a resource-based policy in DynamoDB.
The following diagram shows a multi-account architecture. If resources in one AWS account require access to a DynamoDB table in a different account, you need to set up a resource-based policy in DynamoDB to grant the required access. For example, in the following diagram, access to the DynamoDB table in Account A is granted to a Lambda function in Account B by using a resource-based policy.
This pattern describes cross-account access between Lambda and DynamoDB. You can use similar steps for other AWS services if the appropriate permissions are configured on both accounts. For example, if you want to provide a Lambda function access to an Amazon Simple Storage Service (Amazon S3) bucket in Account A, you can create a resource-based policy in Amazon S3 and add the permissions to the Lambda execution role in Account B.
Tools
AWS services
Amazon DynamoDB is a fully managed NoSQL database service that provides fast, predictable, and scalable performance.
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.
AWS Lambda is a compute service that helps you run code without needing to provision or manage servers. It runs your code only when needed and scales automatically, so you pay only for the compute time that you use.
Code
This pattern includes sample code in the Additional information section to show how you can configure a Lambda function in Account B to write to the DynamoDB table in Account A. The code is provided only for illustration and testing purposes. If you’re implementing this pattern in a production environment, use the code as a reference, and customize it for your own environment.
Best practices
Follow the best practices for resource-based policies in the DynamoDB documentation.
Follow the principle of least privilege and grant the minimum permissions required to perform a task. For more information, see Grant least privilege and Security best practices in the IAM documentation.
Epics
Task | Description | Skills required |
---|---|---|
Create a policy in Account B. | This IAM policy allows the PutItem action for a DynamoDB table in Account A.
| General AWS |
Create a role in Account B. | The Lambda function in Account B uses this IAM role to access the DynamoDB table in Account A.
For more information about creating roles, see the IAM documentation. | General AWS |
Note the role ARN. |
| General AWS |
Task | Description | Skills required |
---|---|---|
Create a DynamoDB table. | Use the following AWS CLI command to create a DynamoDB table.
Replace the following in this code sample:
Note: You specify the resource-based policy configuration in the For more information about creating tables, see the DynamoDB documentation. | General AWS |
Task | Description | Skills required |
---|---|---|
Create a Lambda function to write data to DynamoDB. |
For more information about creating Lambda functions, see the Lambda documentation. | General AWS |
Task | Description | Skills required |
---|---|---|
Delete resources. | To avoid incurring costs associated with the resources created in this pattern, do the following to delete these resources:
| General AWS |
Troubleshooting
Issue | Solution |
---|---|
When creating the Lambda function, you receive a | Confirm that you have correctly entered the AWS Region and ID of Account A. These are part of the ARN for the DynamoDB table. |
Related resources
Getting started with DynamoDB (DynamoDB documentation)
Getting started with Lambda (Lambda documentation)
Using resource-based policies for DynamoDB (DynamoDB documentation)
Creating IAM policies (IAM documentation)
Cross-account policy evaluation logic (IAM documentation)
IAM JSON policy elements reference (IAM documentation)
Additional information
Sample code
import boto3 from datetime import datetime dynamodb_client = boto3.client('dynamodb') def lambda_handler(event, context): now = datetime.now().isoformat() data = dynamodb_client.put_item(TableName='arn:aws:dynamodb:<Region>:<Account-A-ID>:table/Table-Account-A', Item={"category": {"S": "Fruit"},"item": {"S": "Apple"},"time": {"S": now}}) return data
Note: When the DynamoDB client is instantiated, the ARN of the DynamoDB table is provided instead of the table name. This is required so that the Lambda function connects to the correct DynamoDB table when it runs.