- Knowledge Base
- Amazon Web Services
- Amazon Relational Database Service
- RDS Publicly Accessible
Check for any public-facing Amazon RDS database instances provisioned within your AWS cloud account and restrict unauthorized access in order to minimize security risks. To restrict access to a publicly accessible database instance, you must disable the PubliclyAccessible configuration flag, and update the security group associated with the database instance.
This rule can help you with the following compliance standards:
- PCI
- HIPAA
- GDPR
- APRA
- MAS
- NIST4
For further details on compliance standards supported by Conformity, see here.
This rule can help you work with the AWS Well-Architected Framework.
This rule resolution is part of the Conformity Security & Compliance tool for AWS.
When the security group associated with an Amazon RDS database instance allows unrestricted access (i.e. 0.0.0.0/0), everyone and everything on the Internet can establish a connection to your database instance and this can increase the opportunity for malicious activities such as brute-force attacks, SQL injection or DDoS attacks.
Audit
To determine if your Amazon RDS database instances are publicly accessible, perform the following operations:
Using AWS Console
01 Sign in to the AWS Management Console.
02 Navigate to Amazon RDS console at https://console.aws.amazon.com/rds/.
03 In the navigation panel, under Amazon RDS, choose Databases.
04 Click on the name (link) of the RDS database instance that you want to examine. To identify RDS database instances, check the database role available in the Role column (i.e. Instance).
05 Select the Connectivity & security tab and perform the following actions:
- Check the Public accessibility configuration attribute value. If the Public accessibility value is set to Yes, the selected database instance is configured for public access.
- Click on the name of each active security group associated with the database instance, listed under VPC security groups, select the Inbound rules tab, and check the configuration value available in the Source column for any inbound/ingress rules configured to allow access to the selected database. If one or more rules have the Source value set to 0.0.0.0/0 or ::/0 (i.e. Anywhere), the associated security group allows unrestricted traffic.
06On the Details tab, next to Endpoint section, hover over the information icon (i) to display the Connection Information box. If the If the Public accessibility attribute value is set to Yes and the security group associated with the instance allows access to everyone, i.e. 0.0.0.0/0 or ::/0, the selected Amazon RDS database instance selected is publicly accessible and prone to security risks.
07 Repeat steps no. 4 – 6 for each Amazon RDS database instance available within the current AWS region.
08 Change the AWS cloud 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) with custom query filters to list the names of the Amazon RDS database instances provisioned 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 database instance names:
-------------------------------- | DescribeDBInstances | +------------------------------+ | cc-project5-mysql-database | | cc-prod-postgres-database | +------------------------------+
03 Run describe-db-instances command (OSX/Linux/UNIX) using the name of the Amazon RDS database instance that you want to examine as the identifier parameter and custom query filters to determine if the selected database instance is publicly accessible:
aws rds describe-db-instances --region us-east-1 --db-instance-identifier cc-project5-mysql-database --query 'DBInstances[*].PubliclyAccessible'
04 The command output should return the Publicly Accessible attribute value (true for enabled, false for disabled):
[ true ]
05 Run describe-db-instances command (OSX/Linux/UNIX) with custom query filters to describe the security group(s) associated with the selected database instance:
aws rds describe-db-instances --region us-east-1 --db-instance-identifier cc-project5-mysql-database --query 'DBInstances[*].VpcSecurityGroups | []'
06 The command output should return the requested security group information:
[ { "Status": "active", "VpcSecurityGroupId": "sg-0abcdabcdabcdabcd" } ]
07 Run describe-security-groups command (OSX/Linux/UNIX) to list all the inbound/ingress rules defined for the active security group, associated with your RDS database instance:
aws ec2 describe-security-groups --region us-east-1 --group-ids sg-0abcdabcdabcdabcd --query 'SecurityGroups[*].IpPermissions[]'
08 The command output should return the requested configuration information:
[ { "FromPort": 3306, "IpProtocol": "tcp", "IpRanges": [ { "CidrIp": "0.0.0.0/0" } ], "Ipv6Ranges": [ { "CidrIpv6": "::/0" } ], "PrefixListIds": [], "ToPort": 3306, "UserIdGroupPairs": [] } ]
09 If the Publicly Accessible attribute value returned at step no. 4 is true and the security group associated with the instance allows access to everyone, i.e. "CidrIp": "0.0.0.0/0" and/or "CidrIpv6": "::/0", as shown at step no. 8, the selected Amazon RDS database instance selected is publicly accessible and prone to security risks.
10 Repeat steps no. 3 – 9 for each Amazon RDS database instance available in the selected AWS region.
11 Change the AWS cloud region by updating the --region command parameter value and repeat the Audit process for other regions.
Remediation / Resolution
To reconfigure your Amazon RDS database instances in order to restrict public access, perform the following operations:
Using AWS CloudFormation
01 CloudFormation template (JSON):
{ "AWSTemplateFormatVersion": "2010-09-09", "Description": "Restrict Public Access for RDS Database Instances", "Parameters": { "DBInstanceName": { "Default": "mysql-database-instance", "Description": "RDS database instance name", "Type": "String", "MinLength": "1", "MaxLength": "63", "AllowedPattern": "^[0-9a-zA-Z-/]*$", "ConstraintDescription": "Must begin with a letter and must not end with a hyphen or contain two consecutive hyphens." }, "DBInstanceClass": { "Default": "db.t2.micro", "Description": "DB instance class/type", "Type": "String", "ConstraintDescription": "Must provide a valid DB instance type." }, "DBAllocatedStorage": { "Default": "20", "Description": "The size of the database (GiB)", "Type": "Number", "MinValue": "20", "MaxValue": "65536", "ConstraintDescription": "Must be between 20 and 65536 GiB." }, "DBName": { "Default": "mysqldb", "Description": "Database name", "Type": "String", "MinLength": "1", "MaxLength": "64", "AllowedPattern": "[a-zA-Z][a-zA-Z0-9]*", "ConstraintDescription": "Must begin with a letter and contain only alphanumeric characters." }, "DBUsername": { "Description": "Master username for database access", "Type": "String", "MinLength": "1", "MaxLength": "16", "AllowedPattern": "[a-zA-Z][a-zA-Z0-9]*", "ConstraintDescription": "Must begin with a letter and contain only alphanumeric characters." }, "DBPassword": { "NoEcho": "true", "Description": "Password for database access", "Type": "String", "MinLength": "8", "MaxLength": "41", "AllowedPattern": "[a-zA-Z0-9]*", "ConstraintDescription": "Must contain only alphanumeric characters." } }, "Resources": { "DatabaseSecurityGroup": { "Type" : "AWS::EC2::SecurityGroup", "Properties" : { "GroupDescription" : "MySQL Database Access Security Group", "GroupName" : "cc-mysql-security-group", "VpcId" : "vpc-0abcdabcdabcdabcd", "SecurityGroupIngress" : [{ "IpProtocol" : "tcp", "FromPort" : 3306, "ToPort" : 3306, "CidrIp" : "10.0.0.5/32" }], "SecurityGroupEgress" : [{ "IpProtocol" : "-1", "FromPort" : 0, "ToPort" : 65535, "CidrIp" : "0.0.0.0/0" }] } }, "RDSInstance": { "Type": "AWS::RDS::DBInstance", "Properties": { "DBInstanceIdentifier": { "Ref": "DBInstanceName" }, "DBName": { "Ref": "DBName" }, "MasterUsername": { "Ref": "DBUsername" }, "MasterUserPassword": { "Ref": "DBPassword" }, "DBInstanceClass": { "Ref": "DBInstanceClass" }, "AllocatedStorage": { "Ref": "DBAllocatedStorage" }, "VPCSecurityGroups": [ { "Ref":"DatabaseSecurityGroup" } ], "Engine": "MySQL", "EngineVersion": "5.7.36", "PubliclyAccessible": false } } } }
02 CloudFormation template (YAML):
AWSTemplateFormatVersion: '2010-09-09' Description: Restrict Public Access for RDS Database Instances Parameters: DBInstanceName: Default: mysql-database-instance Description: RDS database instance name Type: String MinLength: '1' MaxLength: '63' AllowedPattern: ^[0-9a-zA-Z-/]*$ ConstraintDescription: Must begin with a letter and must not end with a hyphen or contain two consecutive hyphens. DBInstanceClass: Default: db.t2.micro Description: DB instance class/type Type: String ConstraintDescription: Must provide a valid DB instance type. DBAllocatedStorage: Default: '20' Description: The size of the database (GiB) Type: Number MinValue: '20' MaxValue: '65536' ConstraintDescription: Must be between 20 and 65536 GiB. DBName: Default: mysqldb Description: Database name Type: String MinLength: '1' MaxLength: '64' AllowedPattern: '[a-zA-Z][a-zA-Z0-9]*' ConstraintDescription: Must begin with a letter and contain only alphanumeric characters. DBUsername: Description: Master username for database access Type: String MinLength: '1' MaxLength: '16' AllowedPattern: '[a-zA-Z][a-zA-Z0-9]*' ConstraintDescription: Must begin with a letter and contain only alphanumeric characters. DBPassword: NoEcho: 'true' Description: Password for database access Type: String MinLength: '8' MaxLength: '41' AllowedPattern: '[a-zA-Z0-9]*' ConstraintDescription: Must contain only alphanumeric characters. Resources: DatabaseSecurityGroup: Type: AWS::EC2::SecurityGroup Properties: GroupDescription: MySQL Database Access Security Group GroupName: cc-mysql-security-group VpcId: vpc-0abcdabcdabcdabcd SecurityGroupIngress: - IpProtocol: tcp FromPort: 3306 ToPort: 3306 CidrIp: 10.0.0.5/32 SecurityGroupEgress: - IpProtocol: '-1' FromPort: 0 ToPort: 65535 CidrIp: '0.0.0.0/0' RDSInstance: Type: AWS::RDS::DBInstance Properties: DBInstanceIdentifier: !Ref 'DBInstanceName' DBName: !Ref 'DBName' MasterUsername: !Ref 'DBUsername' MasterUserPassword: !Ref 'DBPassword' DBInstanceClass: !Ref 'DBInstanceClass' AllocatedStorage: !Ref 'DBAllocatedStorage' VPCSecurityGroups: - !Ref 'DatabaseSecurityGroup' Engine: MySQL EngineVersion: 5.7.36 PubliclyAccessible: false
Using Terraform
01 Terraform configuration file (.tf):
terraform { required_providers { aws = { source = "hashicorp/aws" version = "~> 3.27" } } required_version = ">= 0.14.9" } provider "aws" { profile = "default" region = "us-east-1" } resource "aws_security_group" "db-security-group" { name = "cc-rds-security-group" description = "MySQL Database Access Security Group" vpc_id = "vpc-0abcdabcdabcdabcd" ingress { from_port = 3306 to_port = 3306 protocol = "tcp" cidr_blocks = ["10.0.0.5/32"] } egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } } resource "aws_db_instance" "rds-database-instance" { allocated_storage = 20 engine = "mysql" engine_version = "5.7" instance_class = "db.t2.micro" name = "mysqldb" username = "ccmysqluser01" password = "ccmysqluserpwd" parameter_group_name = "default.mysql5.7" vpc_security_group_ids = [ aws_security_group.db-security-group.id ] # Restrict Public Access for RDS Database Instances publicly_accessible = false apply_immediately = true }
Using AWS Console
01 Sign in to the AWS Management Console.
02 Navigate to Amazon RDS console at https://console.aws.amazon.com/rds/.
03 In the navigation panel, under Amazon RDS, choose Databases.
04 Select the Amazon RDS database instance that you want to reconfigure and choose Modify.
05 On the Modify DB instance: <instance-name> configuration page, perform the following actions:
- In the Connectivity section, choose Additional configuration and select Not publicly accessible to restrict public access to the selected Amazon RDS database instance. Note that when a database instance is not publicly accessible, Amazon EC2 instances and devices outside your VPC network can't connect unless they use AWS Site-to-Site VPN or AWS Direct Connect.
- Choose Continue and review the configuration changes that you want to apply, available in the Summary of modifications section.
- In the Scheduling of modifications section, perform one of the following actions based on your workload requirements:
- Select Apply during the next scheduled maintenance window to apply the changes automatically during the next scheduled maintenance window.
- Select Apply immediately to apply the changes right away. With this option any pending modifications will be asynchronously applied as soon as possible, regardless of the maintenance window configured for the selected database instance. Note that any changes available in the pending modifications queue are also applied. If any of the pending modifications require downtime, choosing this option can cause unexpected downtime for your database application.
- Choose Modify DB instance to apply the configuration changes.
06 Click on the name of the reconfigured Amazon RDS database instance.
07 Select the Connectivity & security tab and perform the following actions:
- Click on the name (link) of the active security group that you want to reconfigure, listed under VPC security groups.
- Select the Inbound rules tab from the console bottom panel and choose Edit inbound rules.
- On the Edit inbound rules configuration page, change the traffic source for the inbound rule that allows unrestricted access to your database instance. Select Custom from the Source dropdown list and enter one of the following options based on your access requirements:
- The static IP address of the permitted host in CIDR notation (e.g. 10.0.0.5/32).
- The IP address range of the permitted network/subnetwork in CIDR notation, for example 10.0.5.0/24.
- The name or ID of another security group available in the same AWS cloud region.
- Choose Save rules to apply the configuration changes.
08 Repeat steps no. 4 – 7 for each publicly accessible Amazon RDS database instance available within the current AWS region.
09 Change the AWS cloud region from the navigation bar and repeat the Remediation process for other regions.
Using AWS CLI
01 Run modify-db-instance command (OSX/Linux/UNIX) to restrict public access to the selected Amazon RDS database instance by adding the --no-publicly-accessible parameter to the command request. The following command request example makes use of --apply-immediately parameter to apply the configuration changes asynchronously and as soon as possible. Any changes available in the pending modifications queue are also applied with this request. If any of the pending modifications require downtime, choosing this option can cause unexpected downtime for your RDS database application. If you skip adding the --apply-immediately parameter to the command request, Amazon RDS will apply your changes during the next maintenance window:
aws rds modify-db-instance --region us-east-1 --db-instance-identifier cc-project5-mysql-database --no-publicly-accessible --apply-immediately
02 The command output should return the configuration metadata for the modified database instance:
{ "DBInstance": { "PubliclyAccessible": false, "MasterUsername": "ccadmin", "MonitoringInterval": 0, "LicenseModel": "general-public-license", "VpcSecurityGroups": [ { "Status": "active", "VpcSecurityGroupId": "sg-0abcd1234abcd1234" }, { "Status": "active", "VpcSecurityGroupId": "sg-abcd1234" } ], "InstanceCreateTime": "2021-05-12T08:00:00.677Z", "CopyTagsToSnapshot": true, "OptionGroupMemberships": [ { "Status": "in-sync", "OptionGroupName": "default:mysql-5-7" } ], "Engine": "mysql", "MultiAZ": false, "DBSecurityGroups": [], "DBParameterGroups": [ { "DBParameterGroupName": "default.mysql5.7", "ParameterApplyStatus": "in-sync" } ], "PerformanceInsightsEnabled": true, "AutoMinorVersionUpgrade": true, "PreferredBackupWindow": "06:02-06:32", "DBSubnetGroup": { "Subnets": [ { "SubnetStatus": "Active", "SubnetIdentifier": "subnet-abcd1234", "SubnetOutpost": {}, "SubnetAvailabilityZone": { "Name": "us-east-1d" } }, { "SubnetStatus": "Active", "SubnetIdentifier": "subnet-1234abcd", "SubnetOutpost": {}, "SubnetAvailabilityZone": { "Name": "us-east-1e" } }, { "SubnetStatus": "Active", "SubnetIdentifier": "subnet-abcdabcd", "SubnetOutpost": {}, "SubnetAvailabilityZone": { "Name": "us-east-1b" } }, { "SubnetStatus": "Active", "SubnetIdentifier": "subnet-12341234", "SubnetOutpost": {}, "SubnetAvailabilityZone": { "Name": "us-east-1a" } }, { "SubnetStatus": "Active", "SubnetIdentifier": "subnet-abcd1234", "SubnetOutpost": {}, "SubnetAvailabilityZone": { "Name": "us-east-1f" } }, { "SubnetStatus": "Active", "SubnetIdentifier": "subnet-1234abcd", "SubnetOutpost": {}, "SubnetAvailabilityZone": { "Name": "us-east-1c" } } ], "DBSubnetGroupName": "default-vpc-abcdabcd", "VpcId": "vpc-abcdabcd", "DBSubnetGroupDescription": "Created from the AWS Management Console", "SubnetGroupStatus": "Complete" }, "ReadReplicaDBInstanceIdentifiers": [], "AllocatedStorage": 70, "DBInstanceArn": "arn:aws:rds:us-east-1:123456789012:db:cc-project5-mysql-database", "BackupRetentionPeriod": 7, "PreferredMaintenanceWindow": "thu:03:27-thu:03:57", "Endpoint": { "HostedZoneId": "ABCDABCDABCD", "Port": 3306, "Address": "cc-project5-mysql-database.abcdabcdabcd.us-east-1.rds.amazonaws.com" }, "DBInstanceStatus": "available", "IAMDatabaseAuthenticationEnabled": true, "EngineVersion": "5.7.30", "DeletionProtection": true, "AvailabilityZone": "us-east-1a", "DomainMemberships": [], "StorageType": "gp2", "DbiResourceId": "db-ABCDABCDABCDABCDABCDABCDAB", "CACertificateIdentifier": "rds-ca-2019", "StorageEncrypted": true, "AssociatedRoles": [], "DBInstanceClass": "db.t3.medium", "DbInstancePort": 0, "DBInstanceIdentifier": "cc-project5-mysql-database" } }
03 Run revoke-security-group-ingress command (OSX/Linux/UNIX) using the ID of the associated security group that you want to reconfigure as the identifier parameter, to remove the inbound rules that allow unrestricted access to your Amazon RDS database instance:
aws ec2 revoke-security-group-ingress --region us-east-1 --group-id sg-0abcdabcdabcdabcd --ip-permissions IpProtocol=tcp,FromPort=3306,ToPort=3306,IpRanges=[{CidrIp="0.0.0.0/0"}],Ipv6Ranges=[{CidrIpv6="::/0"}] --query 'Return'
04 The command output should return true if the request succeeds. Otherwise, it should return an error:
true
05 Run authorize-security-group-ingress command (OSX/Linux/UNIX) to add the inbound rule removed at the previous step with a different set of parameters in order to restrict database access to trusted entities only (IP addresses, IP ranges, or security groups). To create and attach custom inbound/ingress rules to the associated security group based on your access requirements, use one of the following options (the command does not produce an output):
- Add an inbound rule that allows traffic from an authorized static IP address via TCP port 3306 (MySQL Database), using CIDR notation (e.g. 10.0.0.5/32):
aws ec2 authorize-security-group-ingress --region us-east-1 --group-id sg-01234abcd1234abcd --protocol tcp --port 3306 --cidr 10.0.0.5/32
- Add an inbound/ingress rule that allows traffic from a trusted IP address range through TCP port 3306, using CIDR notation (for example, 10.0.5.0/24):
aws ec2 authorize-security-group-ingress --region us-east-1 --group-id sg-01234abcd1234abcd --protocol tcp --port 3306 --cidr 10.0.5.0/24
- Add an inbound rule that allows traffic from another security group (e.g. sg-01234123412341234) available in the same AWS cloud region via TCP port 3306:
aws ec2 authorize-security-group-ingress --region us-east-1 --group-id sg-01234abcd1234abcd --protocol tcp --port 3306 --source-group sg-01234123412341234
06 Repeat steps no. 1 – 5 for each publicly accessible Amazon RDS database instance available in the selected AWS region.
07 Change the AWS cloud region by updating the --region command parameter value and repeat the Remediation process for other regions.
References
- AWS Documentation
- Amazon RDS FAQs
- Security in Amazon RDS
- Amazon RDS Security Groups
- Security Groups for Your VPC
- AWS Command Line Interface (CLI) Documentation
- rds
- describe-db-instances
- modify-db-instance
- ec2
- describe-security-groups
- revoke-security-group-ingress
- authorize-security-group-ingress
- CloudFormation Documentation
- Amazon Relational Database Service resource type reference
- Terraform Documentation
- AWS Provider