Skip to main content

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.

References