|   Trend Micro Cloud One™
Open menu

RDS Instance Not In Public Subnet

Cloud Conformity allows you to automate the auditing process of this resolution page. Register for a 14 day evaluation and check your compliance level for free!

Start a Free Trial Product features
Last updated: 11 May 2020
Risk level: High (not acceptable risk)
Rule ID: RDS-039

Ensure that no AWS RDS database instances are provisioned inside VPC public subnets in order to protect them from direct exposure to the Internet. Since database instances are not Internet-facing and their management (running software updates, implementing security patches, etc) is done by Amazon, these instances should run only in private subnets.

This rule resolution is part of the Cloud Conformity solution

Security

By provisioning your RDS instances within private subnets (logically isolated sections of AWS VPC) you will prevent these resources from receiving inbound traffic from the public Internet, therefore have a stronger guarantee that no malicious requests can reach your database instances.

Note: For this rule Cloud Conformity assumes that you have private RDS subnet groups already defined within your VPC. A private RDS Subnet Group is a collection of private subnets that you create in your VPC to use with your RDS DB instances.

Audit

To determine if your RDS database instances are currently running within AWS VPC public subnets, perform the following:

Using AWS Console

01 Login to the AWS Management Console.

02 Navigate to RDS dashboard at https://console.aws.amazon.com/rds/.

03 In the left navigation panel, under RDS Dashboard, click Databases.

04 Select the RDS instance that you want to examine.

05 On the Connectivity & security tab, in the Networking section, click the subnet link available under Subnets, e.g.

click the subnet link available next to Subnets

The link will redirect you to the VPC Subnets page.

06 Select the subnet listed on the page and click the Route Table tab from the dashboard bottom panel. If the route table contains any entries with the destination CIDR block set to 0.0.0.0/0 or with an Internet Gateway (e.g. igw-xxxxxxxx) attached:

Select the subnet listed on the page and click the Route Table tab from the dashboard bottom panel

the selected RDS database instance was provisioned inside a public subnet, therefore is not running within a logically isolated environment and can be accessible from the Internet.

07 Repeat step no. 5 and 6 to determine the type (public or private) of other VPC subnets associated with the selected RDS instance.

08 Repeat steps no. 4 – 7 to verify the subnets configuration for other RDS database instances provisioned in the current region.

09 Change the AWS region from the navigation bar and repeat the audit process for other regions.

Using AWS CLI

01 Run describe-db-instances command (OSX/Linux/UNIX) using custom query filters to list the names (identifiers) of all RDS database instances available in the selected AWS region:

aws rds describe-db-instances
	--region us-east-1
	--output table
	--query 'DBInstances[*].DBInstanceIdentifier'

02 The command output should return a table with the requested identifiers:

---------------------------
|   DescribeDBInstances   |
+-------------------------+
| mysql-internal-database |
| mysql-aurora-database   |
+-------------------------+

03 Run again describe-db-instances command (OSX/Linux/UNIX) using the RDS database instance identifier that you want to check and appropriate filtering to describe the VPC subnet(s) associated with the selected instance:

aws rds describe-db-instances
	--region us-east-1
	--db-instance-identifier mysql-internal-database
	--query 'DBInstances[*].DBSubnetGroup.Subnets[]'

04 The command output should list the subnets available in the selected database subnet group:

[
    {
        "SubnetStatus": "Active",
        "SubnetIdentifier": "subnet-19e7cc6f",
        "SubnetAvailabilityZone": {
            "Name": "us-east-1a"
        }
    },
    {
        "SubnetStatus": "Active",
        "SubnetIdentifier": "subnet-4c377014",
        "SubnetAvailabilityZone": {
            "Name": "us-east-1b"
        }
    }
]

05 Now run describe-route-tables command (OSX/Linux/UNIX) using the ID of the subnet returned at the previous step (i.e. the SubnetIdentifier attribute value) to describe the routes of the VPC route table associated with the selected subnet:

aws ec2 describe-route-tables
	--region us-east-1
	--filters "Name=association.subnet-id,Values=subnet-19e7cc6f"
	--query 'RouteTables[*].Routes[]'

06 The command should return one of the following outputs:

  1. If the command returns the route table associated with database instance subnet ID:
    [
        {
            "GatewayId": "local",
            "DestinationCidrBlock": "10.0.0.0/16",
            "State": "active",
            "Origin": "CreateRouteTable"
        },
        {
            "GatewayId": "igw-816ab1e5",
            "DestinationCidrBlock": "0.0.0.0/0",
            "State": "active",
            "Origin": "CreateRoute"
        }
    ]
    

    Check the GatewayId and DestinationCidrBlock attributes values returned in the output. If the route table contains any entries with the GatewayId value set to igw-xxxxxxxx or the DestinationCidrBlock value set to 0.0.0.0/0, the selected RDS database instance was provisioned inside a public subnet, therefore is not running within a logically isolated environment and does not adhere to AWS security best practices. The audit process for the selected resource ends here.
  2. If the command returns empty results (no route table explicit associated with database instance subnet ID), the route table is implicitly associated with subnet, therefore the audit process continues with the next step:
    []
    

07 Run again describe-db-instances command (OSX/Linux/UNIX) using the RDS database instance identifier that you want to check and appropriate filtering to describe the VPC ID associated with the selected instance:

aws rds describe-db-instances
  --region us-east-1
  --db-instance-identifier mysql-internal-database
  --query 'DBInstances[*].DBSubnetGroup.VpcId'

08 The command output should show the VPC ID in the selected database subnet group:

[
    "vpc-0b51c1f86c"
]

09 Now run describe-route-tables command (OSX/Linux/UNIX) using the ID of the VPC returned at the previous step to describe the routes of the VPC main route table implicitly associated with the selected subnet:

aws ec2 describe-route-tables
  --region us-east-1
  --filters "Name=vpc-id,Values=vpc-0b51c1f86c" "Name=association.main,Values=true"
  --query 'RouteTables[*].Routes[]'

10 The command output returns the VPC main route table implicitly associated with database instance subnet ID:

[
    {
        "GatewayId": "local",
        "DestinationCidrBlock": "10.0.0.0/16",
        "State": "active",
        "Origin": "CreateRouteTable"
    },
    {
        "GatewayId": "igw-816ab1e5",
        "DestinationCidrBlock": "0.0.0.0/0",
        "State": "active",
        "Origin": "CreateRoute"
    }
]

Check the GatewayId and DestinationCidrBlock attributes values returned in the output. If the route table contains any entries with the GatewayId value set to igw-xxxxxxxx or the DestinationCidrBlock value set to 0.0.0.0/0, the selected RDS database instance was provisioned inside a public subnet, therefore is not running within a logically isolated environment and does not adhere to AWS security best practices.

11 Repeat step no. 5 and 10 to determine the type (public or private) of other VPC subnets associated with the selected RDS instance.

12 Repeat steps no. 3 – 11 to verify the subnets configuration for other RDS database instances provisioned in the current region.

13 Change the AWS region by updating the --region command parameter value and repeat steps no. 1 - 12 to perform the audit process for other regions.

Remediation / Resolution

To move your RDS database instances from public subnets to private subnets, you must replace their current subnet groups with the ones that contain VPC private subnets. To implement the database instance(s) migration, perform the following:

Using AWS Console

01 Login to the AWS Management Console.

02 Navigate to RDS dashboard at https://console.aws.amazon.com/rds/.

03 In the left navigation panel, under RDS Dashboard, click Databases.

04 Select the RDS instance that you want to migrate to private subnet(s) (see Audit section part I to identify the right resource(s)).

05 From the Actions drop down, from the dashboard top menu, select Take Snapshot to create a database snapshot (backup).

06 On the Take DB Snapshot page, in the Snapshot Name box, enter a unique name for the database backup then click Take Snapshot to send the request.

07 Go back to the Databases page and select again the RDS instance that you want to migrate.

08 Click Modify button from the dashboard top menu.

09 On the Modify DB Instance: <instance identifier> page, perform the following actions:

  1. Select the appropriate DB Subnet Group (i.e. the one that contains only private subnets, usually created in another VPC) from the Subnet Group dropdown list.
  2. At the bottom of the page select Apply Immediately checkbox to apply the subnet group change immediately. (!) IMPORTANT: when you move the instance to another DB Subnet Group an immediate outage will occur. If the selected database instance is used in production consider leaving Apply Immediately option disabled before applying the changes in order to avoid any downtime. If Apply Immediately is not selected, the database subnet group change will be processed during the next maintenance window.

10 Click the Continue button to continue the process.

11 Review the changes and click Modify DB Instance. During the modification process the instance status should change from available to modifying and back to available (it may take few minutes depending on the instance size and configuration).

12 Repeat steps no. 4 - 11 to migrate other RDS database instances to private subnets by using a private subnet group, available in the current region.

13 Change the AWS region from the navigation bar and repeat the audit process for other regions.

Using AWS CLI

01 First, run create-db-snapshot command (OSX/Linux/UNIX) to take the necessary instance snapshot (backup):

aws rds create-db-snapshot
	--region us-east-1
	--db-instance-identifier mysql-internal-database
	--db-snapshot-identifier mysql-internal-database-snapshot

02 The command output should return the database instance snapshot metadata:

{
    "DBSnapshot": {
        "Engine": "mysql",
        "Status": "creating",
        "AvailabilityZone": "us-east-1a",
        "PercentProgress": 0,
        "MasterUsername": "mysqldbusr",
        "Encrypted": false,
        "LicenseModel": "general-public-license",
        "StorageType": "gp2",
        "VpcId": "vpc-5eb565cd",
        "DBSnapshotIdentifier": "mysql-internal-database-snapshot",
        "InstanceCreateTime": "2015-11-23T18:25:07.280Z",
        "OptionGroupName": "default:mysql-5-6",
        "AllocatedStorage": 150,
        "EngineVersion": "5.6.23",
        "SnapshotType": "manual",
        "Port": 3306,
        "DBInstanceIdentifier": "mysql-internal-database"
    }
}

03 Run modify-db-instance command (OSX/Linux/UNIX) to modify the selected RDS instance configuration in order to replace its current subnet group with one that contains private subnets. (!) IMPORTANT: the following example is using the Apply Immediately option to apply the change asynchronously and trigger an immediate outage once the AWS CLI request is made. In order to avoid any downtime in production, skip adding the --apply-immediately command parameter and the RDS service will apply the change during the next maintenance window. The following command example replaces the current subnet group of an RDS instance identified by the name mysql-internal-database with a new subnet group named private-db-subnet-group, which contains only private VPC subnets:

aws rds modify-db-instance
	--region us-east-1
	--db-instance-identifier mysql-internal-database
	--db-subnet-group-name private-db-subnet-group
	--apply-immediately

04 The command output should return the configuration metadata for the modified RDS database instance:

{
    "DBInstance": {
        "PubliclyAccessible": true,
        "MasterUsername": "mysqldbusr",


	  ...


        "InstanceCreateTime": "2015-11-23T18:25:07.280Z",
        "CopyTagsToSnapshot": false,
        "DBSubnetGroup": {
                "Subnets": [
                    {
                        "SubnetStatus": "Active",
                        "SubnetIdentifier": "subnet-4ba8cc39",
                        "SubnetAvailabilityZone": {
                            "Name": "us-east-1a"
                        }
                    },
                    {
                        "SubnetStatus": "Active",
                        "SubnetIdentifier": "subnet-56e07032",
                        "SubnetAvailabilityZone": {
                            "Name": "us-east-1b"
                        }
                    }
                ],
                "DBSubnetGroupName": "private-db-subnet-group",
                "VpcId": "vpc-3a51bd01",
                "DBSubnetGroupDescription": "Private subnets only",
                "SubnetGroupStatus": "Complete"
        },
        ...


        "DBInstanceClass": "db.m3.medium",
        "DBInstanceIdentifier": "mysql-internal-database"
    }
}

05 Once the process is complete (it may take few minutes depending on the instance size and configuration), run describe-db-instances command (OSX/Linux/UNIX) using the database instance identifier to check if the DB Subnet Group has been successfully changed:

aws rds describe-db-instances
	--region us-east-1
	--db-instance-identifier mysql-internal-database
	--query 'DBInstances[*].DBSubnetGroup.DBSubnetGroupName'

06 The command output should return the name of the subnet group currently used by the selected RDS instance:

[
    "private-db-subnet-group"
]

07 Repeat steps no. 1 - 6 to migrate other RDS database instances to private subnets by using a different subnet group, available in the current region.

08 Change the AWS region by updating the --region command parameter value and repeat steps no. 1 - 7 to perform the audit process for other regions.

References

Publication date Dec 3, 2016

Unlock the Remediation Steps

Gain free unlimited access to our full Knowledge Base


Over 600 rules & best practices for and

Get started for FREE

A verification email will be sent to this address
We keep your information private. Learn more.

Thank you!

Please click the link in the confirmation email sent to

You are auditing:

RDS Instance Not In Public Subnet

Risk level: High