RDS is one of AWS’s biggest products and is often one of the first products that AWS adopters learn. RDS is a web service for managing relational databases like MySQL, PostgreSQL, and MariaDB. While Amazon users could deploy databases on a standard EC2 compute instance, it’s recommended to use RDS to take advantage of managed scaling, better availability, automated backups, and general maintenance benefits.
Like any database service, RDS may contain sensitive information. By extension, even internal access to RDS instances by company employees should be scrutinized to avoid a data leak caused by accident or breached credentials. Especially in a time where phishing is at an all-time high <internal link>, security to safeguard customer data is paramount.
In this piece, we’ll discuss the many ways to restrict access to an RDS instance at both the 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 should be made when choosing each.
RDS is Amazon’s flagship service for deploying relational databases. RDS supports various relationship databases, including MySQL, Postgres, MariaDB, and Amazon’s special flavor of MySQL, Aurora. RDS instances expose a host endpoint that external users can connect to (assuming firewalls are correctly configured to allow external connections).
RDS is a feature-rich service with easy backups, scaling, and migrations. RDS is often paired with EC2 or EKS servers—it is also sometimes connected to Lambda services.
In previous decades, companies often leaned on in-database user permissions to divvy up responsibilities. These days, most databases (such as RDS) are managed by a larger cloud vendor; accordingly, those databases’ access controls are connected to a higher-level framework. One of the most common of these frameworks is RBAC.
RBAC, or role-based access control, is a security framework designed to safeguard enterprises or other security-conscious organizations. Before RBAC, only very high-risk resources were locked down to a few personnel. But today, with more phishing attacks and larger engineering teams, a more thorough framework is needed. That’s where RBAC comes in, allowing for flexible yet stringent configurations.
RBAC breaks users, roles, and permissions into three different categories. There is no single philosophy on how to arrange these roles and permissions; different organizations will choose to create different types of roles. The point is that roles and policies both can be very granular. Different roles have different permissions, and different users can be assigned a mix of roles.
One of the biggest benefits of RBAC is that any employee, even junior employees, can get access to very sensitive resources without having “super-user” access.
At the end of the day, RBAC is a concept, like “object-oriented” or “inheritance”. What makes RBAC possible in AWS for products like RDS is IAM.
IAM is an AWS product that interfaces with every AWS user and resource. IAM allows administrators to craft a robust RBAC system; RBAC is a design pattern, while IAM is the actual product. Even better, IAM can assign access to third-party services, and given that IAM is also an AWS product, IAM can allow those services to manage IAM.
In short, IAM is a powerful product that gives people (and programs) the ability to manage permissions across a company’s AWS account.
Terraform, designed by HashiCorp, is an open-source high-level language that can provision and manage infrastructure on the cloud. Terraform is known as infrastructure as code. By utilizing IAM, Terraform can manage AWS account access (alongside provision and configure resources).
RBAC, IAM, and Terraform’s intra-relationships could get confusing. In short, RBAC is a whiteboard philosophy where administrators might design an ideal policy for their organization; IAM is an AWS product that is connected to every AWS service and user; and Terraform is a programming language that can blueprint AWS resources—including IAM policies—via code (stored in .tf files).
Terraform code looks a lot like JSON, and it uses a HashiCorp language known as HCL. HCL a declarative language, meaning that developers describe how an AWS account should be configured. Then, Terraform’s compiler will actually carry out those changes in an optimized manner. For these reasons, it isn’t advised for Terraform to be run via a root account; Terraform could do literally anything in an AWS account, so it’s ideal that it’s barred from…say…deleting everything.
Terraform boasts a significant developer community and has extensive frameworks built on it, including Sym’s Terraform and Slack Access Management framework.
To grant a user full administrative access to any RDS resource, you can provision the following role using IAM/Terraform:
IAM JSON:
Terraform:
The `rds:*` gives this role access to all RDS actions.
If a user should only have access to specific RDS actions, those actions can be specified. For example, we can create limited permissions for an employee that strictly needs to scale the RDS instance but not to read the contents.
IAM JSON:
Terraform:
Sometimes an employee only needs access to a specific RDS instance. Instead of declaring all-encompassing * access, you can specify a particular instance.
IAM JSON:
Terraform:
If a user needs access to a specific instance but needs generic action access, the wildcard operator can be used. A policy like that would look something like this:
IAM JSON:
Terraform:
This policy uses * properties to minimize the list, granting access to all Get, Delete, BatchGet, BatchWrite, Update, and Delete sub-actions.
If you want a role to explicitly not have access to a single instance that it may otherwise have access to due to generic permissions, you can do:
IAM JSON:
Terraform:
While not an AWS feature, most SQL databases like Postgres and MySQL offer row-level security (RLS), where users can only gain access to a certain segment of rows (or be restricted from certain rows). In one common instance of RLS, a certain engineering segment—such as the American team—won’t have access to European account data on a shared database.
While this doesn’t operate at the IAM level, or the AWS level, conditional access to a database doesn’t imply shared accounts. In other words, teams could have discrete accounts so that, while accessing the same database with similar permissions, they have access to unique data.
As a rule of thumb, users should only have access to RDS if that access is necessary for their jobs. They should also only be able to execute actions on RDS that are relevant to their job titles. These actions are often more granular than just read and write; an employee might need create and update access, but not delete access.
Another access pattern that can improve security is just-in-time access. Just-in-time access involves granting a user (or service) ephemeral access just for the duration of their task, and then revoking that access once the task is complete. Just-in-time access helps organizations minimize the attack surface without hindering engineers too much. If an engineer’s credentials are compromised, they may not have ready access to company resources even if they did have access at some prior point.
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 preexisting 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 often use third-party software to orchestrate transactions between the employee and the approver. We are building a solution in this exact category at Sym, specifically by coupling interactive Slack modules with Python and Terraform libraries to manage access requests between employees and approvers.
Another option for accessing RDS is to connect it to internal tools that provide a limited GUI to edit data. This is ideal for employees in sales and product departments that shouldn’t have write access to client data, and also very limited read access.
Internal tools can be built in-house like any other applications, but companies typically use a platform such as Retool to manage the RDS/database connection and craft an employee-friendly user interface.
Another popular approach for restricting access to resources such as RDS is to leverage a VPC. A VPC is a virtual private cloud that gates resources from access over the public internet; instead, users need to access the resources through a VPC endpoint.
VPC endpoints can have the same IAM restrictions as user accounts. In other words, VPCs consolidate security to a single endpoint. Access to a VPC endpoint can also be dynamically provided via JIT flows.
There are various ways to lock down an RDS instance. Companies can use an IAM to gate access, a JIT workflow, a VPC, or a combination of these techniques. By leveraging solutions such as Terraform or Sym, companies can also create more programmatic and automated approaches to protecting their resources. As a whole, organizations should minimize access to RDS given RDS’s likelihood of hosting sensitive data, and investing in good techniques will pay dividends in the long run.