How to create private, VPC-only DynamoDB tables

Yan Cui

I help clients go faster for less using serverless technologies.

In this post, let’s see how to put DynamoDB in VPC so your data can only be accessed from within a VPC.

DynamoDB is a fully managed NoSQL database service known for its low latency and high scalability.

Like most other AWS services, it’s protected by AWS IAM. So, despite being a publically accessible service, your data is secure. Conversely, zero-trust networking says you should always authenticate the caller and shouldn’t trust someone just because they’re in a trusted network perimeter.

You don’t need network security to keep your DynamoDB data safe. However, adding network security on top of IAM authentication and authorization is not a bad thing. Sometimes, it’s necessary to meet regulatory requirements.

This has come up numerous times in my consulting work. In this post, let me show you how to make a DynamoDB table accessible only from within a VPC.

Can’t you just use a VPC endpoint?

You can create a VPC endpoint for DynamoDB to create a tunnel between your VPC and DynamoDB. This allows traffic to go from your VPC to DynamoDB without needing a public IP address.

This is often perceived to be more secure “because it doesn’t go out to the public internet”. But traffic from a VPC to DynamoDB (through a NAT Gateway) would never traverse over public internet infrastructure anyway. It’s just that you need a public IP address so DynamoDB knows where to send the response.

More importantly, a VPC endpoint doesn’t stop other people from accessing the DynamoDB table from outside your VPC.

Resource policy

Now that DynamoDB supports resource-based policies [1], this is the easiest way to implement it.

In most cases, this is the best solution.

However, the onus is on the owner of the DynamoDB table (the feature team) to get this right. What if having DynamoDB in VPC is a regulatory requirement, and you wish to enforce it at the platform level (the platform team)?

Service Control Policies (SCPs)

SCPs let you apply broad strokes to deny certain actions in the member accounts (but NOT the master account) of an AWS Organization. For example, you can use SCPs to:

  • Stop any actions in regions other than us-east-1 or eu-west-1, where your application resides.
  • Stop anyone from creating EC2 instances.

Both are common SCPs people use to protect against cryptojacking.

Typically, the AWS Organization and its SCPs are configured and owned by the platform team. SCPs are a good way to enforce that all DynamoDB tables are accessible only from a VPC.

aws:SourceVpc

You can use the aws:SourceVpc or aws:SourceVpce conditions [2] in IAM policies. You can use these conditions to ensure the IAM user/role can only access DynamoDB from a VPC or through a VPC endpoint.

But how can you ensure that everyone uses this in their IAM roles?

The platform team shouldn’t be gatekeepers. The feature teams should be allowed to create their own IAM roles for their Lambda functions or containers. But how can you ensure they don’t violate your company’s compliance requirements?

This is where SCPs come in.

You can use a SCP like this to reject any requests to DynamoDB unless they originate from within the specified VPC.

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "DenyDynamoDBOutsideVPC",
      "Effect": "Deny",
      "Action": "dynamodb:*",
      "Resource": "*",
      "Condition": {
        "StringNotEquals": {
          "aws:SourceVpc": "vpc-xxxxxxxxx"
        }
      }
    }
  ]
}

Every AWS account would have its own VPC(s), so you will likely need an account-specific SCP.

As it stands, this SCP can also create significant friction to development.

Every action against DynamoDB tables, including the initial deployment, must be performed within the designated VPC. So you won’t even be able to use the DynamoDB console!

A good compromise is to leave the SCP off the development accounts. That way, the strict SCP does not hamstring developers, and you can still enforce compliance in production.

Supporting break-glass procedures

What if you have an emergency and someone needs to access the production tables through the AWS console?

Many organizations would lock down their production environment so no one has write access. But they’d have a break-glass procedure that allows someone to temporarily assume a special role in the event of an emergency.

You can cater for these emergencies by carving out an exception in the SCP. For example, by adding the following condition:

"StringNotLike": { 
  "aws:PrincipalArn": "arn:aws:iam::*:role/your-emergency-role"
}

This condition allows the specified role to access DynamoDB from outside the VPC. This includes the ability to use the DynamoDB console.

How would you implement this break-glass procedure? That’s another post for another day, perhaps :-)

In the meantime, if you want to learn more about building serverless applications on AWS, why not check out my upcoming workshop [3] and take your AWS game to the next level?

Links

[1] DynamoDB now supports resource-based policies

[2] IAM Condition element

[3] My production-ready serverless workshop

Related posts

DynamoDB now supports cross-account access. But is that a good idea?

Whenever you’re ready, here are 3 ways I can help you:

  1. Production-Ready Serverless: Join 20+ AWS Heroes & Community Builders and 1000+ other students in levelling up your serverless game. This is your one-stop shop to level up your serverless skills quickly.
  2. Do you want to know how to test serverless architectures with a fast dev & test loop? Check out my latest course, Testing Serverless Architectures and learn the smart way to test serverless.
  3. I help clients launch product ideas, improve their development processes and upskill their teams. If you’d like to work together, then let’s get in touch.