Two ways to access DynamoDB from private subnets
There are two ways to access DynamoDB from an EC2 instance in private subnets.
- NAT Gateway
- VPC Endpoint (Gateway type)
This page will review how to access DynamoDB tables via the above two.
Environment
Create one private subnet in each of the two AZs.
Place an EC2 instance on each subnet.
The instance should be the latest Amazon Linux 2.
Create NAT gateways and gateway type VPC endpoints.
Configure security groups, route tables, etc. to allow each instance to communicate to DynamoDB through them.
This configuration will be built in the ap-northeast-1 (Tokyo) region.
CloudFormation template files
The above configuration is built with CloudFormation.
The CloudFormation template is placed at the following URL
https://github.com/awstut-an-r/awstut-saa/tree/main/03/004
Explanation of key points of template files
NAT Gateway
Resources:
IGW:
Type: AWS::EC2::InternetGateway
IGWAttachment:
Type: AWS::EC2::VPCGatewayAttachment
Properties:
VpcId: !Ref VPC
InternetGatewayId: !Ref IGW
EIP:
Type: AWS::EC2::EIP
Properties:
Domain: vpc
NATGateway:
Type: AWS::EC2::NatGateway
Properties:
AllocationId: !GetAtt EIP.AllocationId
SubnetId: !Ref PublicSubnet
PublicSubnet:
Type: AWS::EC2::Subnet
Properties:
CidrBlock: !Ref CidrIp1
VpcId: !Ref VPC
AvailabilityZone: !Sub "${AWS::Region}${AvailabilityZone1}"
PrivateSubnet1:
Type: AWS::EC2::Subnet
Properties:
CidrBlock: !Ref CidrIp2
VpcId: !Ref VPC
AvailabilityZone: !Sub "${AWS::Region}${AvailabilityZone1}"
PublicRouteTable:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
RouteToInternet:
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref PublicRouteTable
DestinationCidrBlock: 0.0.0.0/0
GatewayId: !Ref IGW
PublicSubnetRouteTableAssociation:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PublicSubnet
RouteTableId: !Ref PublicRouteTable
PrivateRouteTable1:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
RouteToNATGateway:
Type: AWS::EC2::Route
Properties:
RouteTableId: !Ref PrivateRouteTable1
DestinationCidrBlock: 0.0.0.0/0
NatGatewayId: !Ref NATGateway
PrivateSubnetRouteTableAssociation1:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnet1
RouteTableId: !Ref PrivateRouteTable1
Code language: YAML (yaml)
Create a NAT gateway on the public subnet.
Configure the route table as follows so that instances on the private subnet can communicate with the DynamoDB bucket via the NAT gateway.
- Route table for private subnets: set default route for NAT gateways
- Route table for public subnets: set default route for Internet Gateway
VPC endpoints for DynamoDB
Resources:
GatewayDynamoDBEndpoint:
Type: AWS::EC2::VPCEndpoint
Properties:
RouteTableIds:
- !Ref PrivateRouteTable2
ServiceName: !Sub "com.amazonaws.${AWS::Region}.dynamodb"
VpcEndpointType: Gateway
VpcId: !Ref VPC
PrivateSubnet2:
Type: AWS::EC2::Subnet
Properties:
CidrBlock: !Ref CidrIp3
VpcId: !Ref VPC
AvailabilityZone: !Sub "${AWS::Region}${AvailabilityZone2}"
PrivateRouteTable2:
Type: AWS::EC2::RouteTable
Properties:
VpcId: !Ref VPC
PrivateSubnetRouteTableAssociation2:
Type: AWS::EC2::SubnetRouteTableAssociation
Properties:
SubnetId: !Ref PrivateSubnet2
RouteTableId: !Ref PrivateRouteTable2
Code language: YAML (yaml)
To create a gateway type endpoint, specify a route table for the RouteTableIds property.
No special routes need to be specified for the route table.
The routes are automatically registered by associating it with a VPC endpoint.
(Reference) DynamoDB table
Resources:
Table:
Type: AWS::DynamoDB::Table
Properties:
AttributeDefinitions:
- AttributeName: Artist
AttributeType: S
- AttributeName: SongTitle
AttributeType: S
BillingMode: PAY_PER_REQUEST
KeySchema:
- AttributeName: Artist
KeyType: HASH
- AttributeName: SongTitle
KeyType: RANGE
TableClass: STANDARD
TableName: !Sub "${Prefix}-Music"
Code language: YAML (yaml)
No special settings are made.
The configuration shown in the following official AWS page is exported to a CloudFormation template.
https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/getting-started-step-1.html
For basic information on DynamoDB, please refer to the following pages.
(Reference) EC2 instance
Resources:
Instance1:
Type: AWS::EC2::Instance
Properties:
IamInstanceProfile: !Ref InstanceProfile
ImageId: !Ref ImageId
InstanceType: !Ref InstanceType
NetworkInterfaces:
- DeviceIndex: 0
SubnetId: !Ref PrivateSubnet1
GroupSet:
- !Ref InstanceSecurityGroup
Instance2:
Type: AWS::EC2::Instance
Properties:
IamInstanceProfile: !Ref InstanceProfile
ImageId: !Ref ImageId
InstanceType: !Ref InstanceType
NetworkInterfaces:
- DeviceIndex: 0
SubnetId: !Ref PrivateSubnet2
GroupSet:
- !Ref InstanceSecurityGroup
Code language: YAML (yaml)
Place one EC2 instance on each private subnet.
The following are the IAM roles for the instance
Resources:
InstanceRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action: sts:AssumeRole
Principal:
Service:
- ec2.amazonaws.com
Policies:
- PolicyName: AccessS3Policy
PolicyDocument:
Version: 2012-10-17
Statement:
- Effect: Allow
Action:
- dynamodb:*
Resource:
- !Sub "arn:aws:dynamodb:${AWS::Region}:${AWS::AccountId}:table/${Table}"
ManagedPolicyArns:
- arn:aws:iam::aws:policy/AmazonSSMManagedInstanceCore
Code language: YAML (yaml)
The contents allow all actions on the aforementioned DynamoDB table.
Architecting
Use CloudFormation to build this environment and check its actual behavior.
Create CloudFormation stacks and check the resources in the stacks
Create CloudFormation stacks.
For information on how to create stacks and check each stack, please see the following page.
After reviewing the resources in each stack, information on the main resources created in this case is as follows
- Instance 1: i-01fc2da5b7f33df18
- Instance 2: i-0eebb182d0fe97317
- DynamoDB table: saa-03-004-Music
- NAT gateway: nat-0568dd9fb3f9fa0ff
- VPC endpoint: vpce-0ec6434db586081b9
Check each resource from the AWS Management Console.
Check the NAT gateway.
It has been created successfully.
You can also see that the EIP created with CloudFormation has been successfully attached.
Check the VPC endpoints.
Indeed, we can see that a gateway type VPC endpoint has been created for DynamoDB.
Operation Check
Access to DynamoDB tables via NAT gateway
Now that we are ready, we access instance 1.
The access will use SSM Session Manager.
% aws ssm start-session --target i-01fc2da5b7f33df18
...
sh-4.2$
Code language: Bash (bash)
For more information on SSM Session Manager, please refer to the following page.
After saving the test item in DynamoDB, check the data in the table.
sh-4.2$ aws dynamodb put-item \
--table-name saa-03-004-Music \
--item '{"Artist": {"S": "aaa"}, "SongTitle": {"S": "AAA"}}' \
--region ap-northeast-1
sh-4.2$ aws dynamodb scan \
--table-name saa-03-004-Music \
--region ap-northeast-1
{
"Count": 1,
"Items": [
{
"SongTitle": {
"S": "AAA"
},
"Artist": {
"S": "aaa"
}
}
],
"ScannedCount": 1,
"ConsumedCapacity": null
}
Code language: Bash (bash)
Indeed, we were able to access the DynamoDB tables via the NAT gateway.
Access DynamoDB tables via VPC endpoints
Similarly, use SSM Session Manager to access instance 2.
% aws ssm start-session --target i-0eebb182d0fe97317
...
sh-4.2$
Code language: Bash (bash)
Save and confirm test data as before.
sh-4.2$ aws dynamodb put-item \
--table-name saa-03-004-Music \
--item '{"Artist": {"S": "bbb"}, "SongTitle": {"S": "BBB"}}' \
--region ap-northeast-1
sh-4.2$ aws dynamodb scan \
--table-name saa-03-004-Music \
--region ap-northeast-1
{
"Count": 2,
"Items": [
{
"SongTitle": {
"S": "BBB"
},
"Artist": {
"S": "bbb"
}
},
{
"SongTitle": {
"S": "AAA"
},
"Artist": {
"S": "aaa"
}
}
],
"ScannedCount": 2,
"ConsumedCapacity": null
}
Code language: Bash (bash)
Indeed, we were able to access the DynamoDB tables via the VPC endpoint.
Summary
We have identified two ways to access S3 from private subnets (NAT gateway and gateway type VPC endpoints).