Unrestricted access between network segments - RDS
Need
Restrict access between network segments for RDS instances
Context
- Usage of Terraform for Infrastructure as Code (IaC)
- Usage of aws_db_instance for managing and interacting with AWS RDS database instances
Description
Non compliant code
resource "aws_db_instance" "default" {
allocated_storage = 20
storage_type = "gp2"
engine = "mysql"
engine_version = "5.7"
instance_class = "db.t2.micro"
name = "mydb"
username = "foo"
password = "foobarbaz"
parameter_group_name = "default.mysql5.7"
publicly_accessible = true
skip_final_snapshot = true
}
The above Terraform code creates a publicly accessible AWS RDS instance without specifying a database subnet group. The publicly_accessible
attribute is set to true
which means that the database instance is accessible from the internet.
This is a vulnerability because it allows unrestricted access between network segments. Any public or private subnet can connect to the RDS instance without any restrictions. This could potentially lead to unauthorized access to sensitive data stored in the database.
The lack of a defined database subnet group means that the RDS instance is not associated with any particular subnet. This could lead to issues with network routing and access control as it is not clear which network rules apply to the database instance.
To fix this vulnerability, a database subnet group should be defined and associated with the RDS instance. The publicly_accessible
attribute should be set to false
to ensure that the database instance is not publicly accessible.
Steps
- Create a Database Subnet Group in your AWS account.
- Specify the Database Subnet Group in the RDS resource configuration.
- Ensure that the RDS instance is not publicly accessible.
- Review and update the security group rules to restrict access to the RDS instance.
Compliant code
resource "aws_db_subnet_group" "default" {
name = "main"
subnet_ids = ["subnet-xxxxxxxx", "subnet-yyyyyyyy"]
tags = {
Name = "Main database subnet group"
}
}
resource "aws_db_instance" "default" {
allocated_storage = 20
storage_type = "gp2"
engine = "mysql"
engine_version = "5.7"
instance_class = "db.t2.micro"
name = "mydb"
username = "foo"
password = "foobarbaz"
parameter_group_name = "default.mysql5.7"
publicly_accessible = false
skip_final_snapshot = true
db_subnet_group_name = aws_db_subnet_group.default.name
}
The above code first creates a Database Subnet Group using the aws_db_subnet_group
resource. The subnet_ids
attribute should be replaced with the IDs of the subnets you want to include in the group.
Then, it creates an RDS instance using the aws_db_instance
resource. The publicly_accessible
attribute is set to false
to ensure that the RDS instance is not publicly accessible.
The db_subnet_group_name
attribute is set to the name of the Database Subnet Group created earlier. This ensures that the RDS instance is defined inside the Database Subnet Group, restricting access between network segments.
Please note that you should replace the placeholders (subnet-xxxxxxxx
, subnet-yyyyyyyy
) with your actual subnet IDs. Also, ensure that the security group rules associated with the subnets restrict access to the RDS instance as per your requirements.