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: 03 December 2016
Security

Risk level: High (not acceptable risk)

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.

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 Instances.

04 Select the RDS instance that you want to examine.

05 Click Instance Actions button from the dashboard top menu and select See Details.

06 On the Details tab, in the Security and Network section, click the subnet link available next to Subnets, e.g.

click the subnet link available next to Subnets

The link will redirect you to the VPC Subnets page.

07 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.

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

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

10 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 output should return the 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.

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. 3 – 7 to verify the subnets configuration for other RDS database instances provisioned in the current region.

09 Change the AWS region by updating the --region command parameter value and repeat steps no. 1 - 8 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 Instances.

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 Click Instance Actions button from the dashboard top menu and 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 Instances page and select again the RDS instance that you want to migrate.

08 Click Instance Actions button from the dashboard top menu and select Modify.

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