DynamoDB is one of AWS’s biggest products—as a leading noSQL database, DynamoDB is leveraged by small and large organizations alike to store JSON data at scale. However, like any database, DynamoDB may contain sensitive information. Even internal access to DynamoDB instances should be scrutinized to avoid risking a data leak by accident or by a rogue actor.
In this piece, we’ll discuss the many ways to restrict access to a DynamoDB instance at both a framework and implementation level, utilizing patterns and tools such as RBAC, IAM, Terraform, Retool, and Sym. Because different strategies are optimal for different types of organizations, we will discuss what considerations to make when choosing each.
Let's begin with a simple policy to get a feel for what it means to define access for DynamoDB.
Full Administrative Access
To grant a specific user full administrative access to any DynamoDB resource, you can provision the following role using the IAM policy language.
Here is the same policy defined in Terraform's configuration language, HCL:
The dynamodb:* gives this role access to all DynamoDB actions. The resources: ["*"] allows those actions for any table even if it is added after this policy is created. This is a very risky policy to have available. It's defined here for illustrative purposes and should not be used on a production account.
Access to Specific DynamoDB Actions
If a user should only have access to specific DynamoDB actions, those actions can be specified. For instance, imagine creating limited permissions for an employee that strictly needs to scale the DynamoDB instance but not read the contents.
Access to a Specific DynamoDB Table
Sometimes an employee only needs access to a specific DynamoDB table. Instead of declaring all-encompassing * access, you could specify a specific table by providing the tableID.
If a user needs access to a specific table, but generic action access, the specific actions need to be manually specified. DynamoDB lacks a wildcard that grants access to all table-specific permissions. A policy like that would look something like this:
This policy uses * properties to minimize the list, granting access to all Get, Delete, BatchGet, BatchWrite, Update, and Delete sub-actions. However, these actions do not grant the user access to understand the meta-data surrounding the table. In order to grant that, DynamoDB-wide List and Describe actions need to be granted.
Deny Access to a Specific DynamoDB Table
If you wanted a role to explicitly not have access to a single table that they may otherwise have access to due to generic permissions, you can do:
When creating IAM policies, administrators should follow the privilege of least privilege and grant only the actions necessary to perform the relevant job. These actions are often more granular than just read and write; for instance, an employee might have create and update access, but not delete access.
Often table read/write restrictions aren’t enough. Users might need to have various horizontal and vertical constraints.
Horizontal constraints restrict users from seeing certain items in the database—this is similar to row-based access control in a traditional tabular database like PostgreSQL. Conversely, vertical constraints restrict users from seeing certain attributes in an item—this is similar to column-based access control in a traditional database.
A common primary-key-based horizontal constraint would be a database broken into various regions of data; employees specific to a certain region may only need access to their region.
Such limited access could be gated using IAM / Terraform.
A common attribute-based vertical constraint would be a database with especially sensitive PII that shouldn’t usually be accessible to employees; for instance, employees may have access to a user’s last login date, but not their social security number or birthdate.
Such limited access could be gated using IAM / Terraform discussed in the next section.
Granting fine-grained horizontal access
Limiting horizontal access comes down to specifying which DynamoDB keys a user can access on a certain table or set of tables. This can be done using IAM’s Condition attribute.
The actions are naturally limited because leading keys aren’t relevant to table-wide functions like list or describe. Additionally, because of the way scan works, it cannot be mixed with LeadingKeys constraints.
Granting fine-grained vertical access
When granting fine-grained access control, specifying specific attributes to access—as opposed to denying access to sensitive attributes—is preferred. This safeguards companies from accidentally exposing sensitive data if new sensitive attributes are introduced. Granted, if additional sensitive attributes aren’t ever expected, using a deny access policy may be easier to upkeep in the long term.
We can use the conventional white-list approach to craft the right IAM policy.
Of course, constraints on attributes could be mixed with constraints on leading keys if an employee should only have access to certain values amongst a certain entry or set of entries. Since the organizations that deploy these fine-grained constraints are obviously security-conscious, such a granular pairing isn’t uncommon.
Another access pattern that can dramatically lockdown security is just-in-time access. Just-in-time access is the practice of granting a user or service ephemeral access for the duration of their task and revoking that access once the task is complete. Just-in-time access helps organizations minimize the attack surface; if an engineer’s credentials are compromised, they may not have immediate access to company resources.
Just-in-time access works by (i) provisioning (and later destroying) a unique role that is specific to the access needed or (ii) by assigning (and later de-assigning) a pre-existing role with the right access to the requester. What matters more is how just-in-time access is granted, which happens through various patterns.
These patterns include:
These approval flows typically depend on third-party software to orchestrate the transactions between the employee and the approver. We are building a solution in this precise category at Sym, specifically by coupling interactive Slack modules with Python and Terraform libraries to manage access requests between employees and approvers.
Sometimes, non-technical access to DynamoDB should be proxied through dedicated internal tools as opposed to IAM. This is ideal for employees such as sales reps and analysts that need access to client data, but lack the necessary skills or clearance to interface directly with AWS. Internal tooling also helps guide employees through workflows, which is ideal for roles with repetitive, daily responsibilities.
Internal tools can be built in-house like any other applications, but companies typically use a platform like Retool to manage the DynamoDB connection and craft an employee-friendly user interface. To be clear, Retool is not a replacement for Terraform or IAM; like any other service or user, it requires an IAM role to be granted access.
A separate, popular approach for locking down resources such as DynamoDB is to leverage a VPC. A VPC is a virtual private cloud that prevents resources from being able to be accessed over the public internet. Users need to instead access resources through a VPC endpoint.
VPC endpoints could have the same IAM restrictions as user accounts, which is a great way to locked-down multiple resources unilaterally by exposing VPC endpoints with various degrees of access. Access to a VPC endpoint can also by dynamically provided via JIT flows.
RBAC implemented via IAM can help organizations lock down DynamoDB using a least-access strategy. Not only can RBAC help control which users have access to DynamoDB, but it can regulate which actions, which tables, which leading keys, and which attributes are accessible. Additionally, just-in-time (JIT) access can be used to provide access ephemerally, which dramatically improves overall security.