- Knowledge Base
- Amazon Web Services
- Amazon Relational Database Service
- RDS Encryption Enabled
Ensure that your Amazon RDS database instances are encrypted to fulfill compliance requirements for data-at-rest encryption. The data encryption and decryption process is handled transparently and does not require any additional action from you or your application.
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 dealing with production databases that hold sensitive and critical data, it is highly recommended to implement encryption in order to protect your data from unauthorized access. With Amazon RDS encryption enabled, the data stored on the instance underlying storage, the automated backups, Read Replicas, and snapshots, become all encrypted. The RDS encryption keys implement AES-256 algorithm and are entirely managed and protected by the AWS key management infrastructure through Amazon Key Management Service (KMS).
Audit
To determine if your Amazon RDS database instances are encrypted at rest, 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 Amazon 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 Configuration tab and check the Encryption attribute value. If the Encryption value is set to Not enabled, the encryption of data at rest is not enabled for the selected Amazon RDS database instance.
06 Repeat steps no. 4 and 5 for each Amazon RDS database instance available within the current AWS region.
07 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 encrypted at rest:
aws rds describe-db-instances --region us-east-1 --db-instance-identifier cc-project5-mysql-database --query 'DBInstances[*].StorageEncrypted'
04 The command output should return the encryption status (true for enabled, false for disabled):
[ false ]
If the describe-db-instances command output returns false, as shown in the output example above, the encryption of data at rest is not enabled for the selected Amazon RDS database instance.
05 Repeat steps no. 3 and 4 for each Amazon RDS database instance available in the selected AWS region.
06 Change the AWS cloud region by updating the --region command parameter value and repeat the Audit process for other regions.
Remediation / Resolution
To enable data-at-rest encryption for your existing Amazon RDS database instances you must re-create (back up and restore) your instances with the encryption flag enabled, by performing the following operations:
Using AWS CloudFormation
01 CloudFormation template (JSON):
{ "AWSTemplateFormatVersion": "2010-09-09", "Description": "Enable Encryption at Rest", "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.small", "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": { "RDSInstance": { "Type": "AWS::RDS::DBInstance", "Properties": { "DBInstanceIdentifier": { "Ref": "DBInstanceName" }, "DBName": { "Ref": "DBName" }, "MasterUsername": { "Ref": "DBUsername" }, "MasterUserPassword": { "Ref": "DBPassword" }, "DBInstanceClass": { "Ref": "DBInstanceClass" }, "AllocatedStorage": { "Ref": "DBAllocatedStorage" }, "Engine": "MySQL", "EngineVersion": "5.7.36", "StorageEncrypted": true } } } }
02 CloudFormation template (YAML):
AWSTemplateFormatVersion: '2010-09-09' Description: Enable Encryption at Rest 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.small 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: RDSInstance: Type: AWS::RDS::DBInstance Properties: DBInstanceIdentifier: !Ref 'DBInstanceName' DBName: !Ref 'DBName' MasterUsername: !Ref 'DBUsername' MasterUserPassword: !Ref 'DBPassword' DBInstanceClass: !Ref 'DBInstanceClass' AllocatedStorage: !Ref 'DBAllocatedStorage' Engine: MySQL EngineVersion: 5.7.36 StorageEncrypted: true
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_db_instance" "rds-database-instance" { allocated_storage = 20 engine = "mysql" engine_version = "5.7" instance_class = "db.t2.small" name = "mysqldb" username = "ccmysqluser01" password = "ccmysqluserpwd" parameter_group_name = "default.mysql5.7" final_snapshot_identifier = "rds-database-instance-snapshot" # Enable Encryption at Rest storage_encrypted = true 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 encrypt, choose Actions, and select Take snapshot.
05 On the Take DB snapshot setup page, enter a name for the instance snapshot in the Snapshot name box, and choose Take snapshot (the backup process may take a few minutes and depends on your RDS instance storage size).
06 Select the newly created database instance snapshot, choose Actions, and select Copy snapshot to create a new copy of the selected snapshot.
07 On the Copy snapshot setup page, perform the following actions:
- From the Destination Region dropdown list, select the region where you want to save the copy of the selected snapshot.
- In the New DB Snapshot Identifier box, type a unique name for the new database snapshot.
- (Optional) From Target Option Group (Optional) dropdown list, select an option group to associate with your target database snapshot.
- (Optional) Select the Copy Tags checkbox if you want your new database snapshot to have the same tags as the source snapshot.
- In the Encryption section, select the Enable Encryption checkbox to turn on encryption at rest for the new Amazon RDS database snapshot. Select (default) aws/rds from the Master key dropdown list to use the AWS-managed master key (a predefined key that protects your data when no other key is created for this purpose) or choose Enter a key ARN and provide the Amazon Resource Name (ARN) of your customer-managed Customer Master Key (CMK) in the ARN configuration box.
- Choose Copy snapshot to confirm the action. The process will take a couple of minutes to complete. Once created, you should see the encrypted Amazon RDS database snapshot (copy) in the Manual snapshots list.
08 Select the new snapshot copy (encrypted), choose Actions, and select Restore snapshot to restore the encrypted snapshot to a new Amazon RDS database instance.
09 On the Restore snapshot setup page, enter a unique name for your new, encrypted database instance in the DB instance identifier box. If required, configure the instance network and connectivity, instance type/class, storage and availability settings. Choose Restore DB instance to create your new Amazon RDS database instance.
10 As soon as your new database instance is ready (i.e. instance status becomes Available), you can update your database application configuration to refer to the endpoint of the new (encrypted) database instance.
11 (Optional) You can now delete the source (unencrypted) database instance to stop incurring charges for the RDS resource. To remove the source instance from your AWS cloud account, perform the following actions:
- Select the unencrypted database instance that you want to delete, choose Actions, and select Delete.
- In the Delete <instance-name> instance? confirmation box, select Create final snapshot?, type delete me into the required field, then choose Delete to confirm your action.
12 Repeat steps no. 4 – 11 for each unencrypted Amazon RDS database instance available within the current AWS region.
13 Change the AWS cloud region from the navigation bar and repeat the Remediation process for other regions.
Using AWS CLI
01 Run create-db-snapshot command (OSX/Linux/UNIX) to create a new snapshot for the Amazon RDS database instance that you want to encrypt:
aws rds create-db-snapshot --region us-east-1 --db-snapshot-identifier cc-project5-mysql-database-snapshot --db-instance-identifier cc-project5-mysql-database
02 The command output should return the metadata of the new database instance snapshot:
{ "DBSnapshot": { "Engine": "mysql", "Status": "creating", "AvailabilityZone": "us-east-1a", "ProcessorFeatures": [], "DBSnapshotArn": "arn:aws:rds:us-east-1:123456789012:snapshot:cc-project5-mysql-database-snapshot", "PercentProgress": 0, "MasterUsername": "ccadmin", "Encrypted": false, "LicenseModel": "general-public-license", "StorageType": "gp2", "VpcId": "vpc-abcdabcd", "DBSnapshotIdentifier": "cc-project5-mysql-database-snapshot", "InstanceCreateTime": "2021-05-19T07:25:18.958Z", "OptionGroupName": "default:mysql-5-6", "AllocatedStorage": 20, "EngineVersion": "5.6.40", "SnapshotType": "manual", "DbiResourceId": "db-ABCDABCDABCDABCDABCD", "IAMDatabaseAuthenticationEnabled": false, "Port": 3306, "DBInstanceIdentifier": "cc-project5-mysql-database" } }
03 Run copy-db-snapshot command (OSX/Linux/UNIX) using the name of the unencrypted Amazon RDS database snapshot as the identifier parameter, to copy the selected snapshot and encrypt its data using the default master key (i.e. AWS-managed key). Replace <aws-region>
and <aws-account-id>
with your own AWS cloud environment details:
aws rds copy-db-snapshot --region us-east-1 --source-db-snapshot-identifier cc-project5-mysql-database-snapshot --target-db-snapshot-identifier cc-encrypted-project5-mysql-database-snapshot --kms-key-id arn:aws:kms:<aws-region>
:<aws-account-id>
:alias/aws/rds
04 The command output should return the metadata of the new Amazon RDS database snapshot:
{ "DBSnapshot": { "MasterUsername": "ccadmin", "LicenseModel": "general-public-license", "InstanceCreateTime": "2021-05-18T15:31:20.677Z", "Engine": "mysql", "VpcId": "vpc-abcdabcd", "SourceRegion": "us-east-1", "AllocatedStorage": 20, "Status": "creating", "PercentProgress": 0, "SourceDBSnapshotIdentifier": "arn:aws:rds:us-east-1:123456789012:snapshot:cc-project5-mysql-database-snapshot", "DBSnapshotIdentifier": "cc-encrypted-project5-mysql-database-snapshot", "DBSnapshotArn": "arn:aws:rds:us-east-1:123456789012:snapshot:cc-encrypted-project5-mysql-database-snapshot", "EngineVersion": "8.0.20", "ProcessorFeatures": [], "OptionGroupName": "default:mysql-8-0", "AvailabilityZone": "us-east-1a", "StorageType": "gp2", "Encrypted": true, "IAMDatabaseAuthenticationEnabled": false, "KmsKeyId": "arn:aws:kms:us-east-1:123456789012:key/abcdabcd-1234-abcd-1234-abcd1234abcd", "DbiResourceId": "db-ABCDABCDABCDABCDABCD", "SnapshotType": "manual", "Port": 3306, "DBInstanceIdentifier": "cc-project5-mysql-database" } }
05 Run restore-db-instance-from-db-snapshot command (OSX/Linux/UNIX) to restore the encrypted snapshot created at the previous step to a new Amazon RDS database instance:
aws rds restore-db-instance-from-db-snapshot --region us-east-1 --db-instance-identifier cc-encrypted-project5-mysql-database --db-snapshot-identifier cc-encrypted-project5-mysql-database-snapshot
06 The command output should return the configuration metadata for the new, encrypted database instance:
{ "DBInstance": { "PubliclyAccessible": true, "MasterUsername": "ccadmin", "MonitoringInterval": 0, "LicenseModel": "general-public-license", "VpcSecurityGroups": [ { "Status": "active", "VpcSecurityGroupId": "sg-0abcd1234abcd1234" } ], "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": 20, "DBInstanceArn": "arn:aws:rds:us-east-1:123456789012:db:cc-project5-mysql-database", "BackupRetentionPeriod": 0, "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" } }
07 As soon as your new database instance is ready, you can update your database application configuration to refer to the endpoint of the new (encrypted) database instance.
08 (Optional) You can choose to delete the source (unencrypted) database instance. Run delete-db-instance command (OSX/Linux/UNIX) using the name of the unencrypted database instance as the identifier parameter, to remove specified RDS instance from your AWS cloud account:
aws rds delete-db-instance --region us-east-1 --db-instance-identifier cc-project5-mysql-database --final-db-snapshot-identifier cc-project5-mysql-database-final-snapshot
09 The command output should return the delete-db-instance command request metadata:
{ "DBInstance": { "PubliclyAccessible": true, "MasterUsername": "ccadmin", "MonitoringInterval": 0, "LicenseModel": "general-public-license", "VpcSecurityGroups": [ { "Status": "active", "VpcSecurityGroupId": "sg-0abcd1234abcd1234" } ], "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": 20, "DBInstanceArn": "arn:aws:rds:us-east-1:123456789012:db:cc-project5-mysql-database", "BackupRetentionPeriod": 0, "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": false, "AvailabilityZone": "us-east-1a", "DomainMemberships": [], "StorageType": "gp2", "DbiResourceId": "db-ABCDABCDABCDABCDABCDABCDAB", "CACertificateIdentifier": "rds-ca-2019", "StorageEncrypted": false, "AssociatedRoles": [], "DBInstanceClass": "db.t3.medium", "DbInstancePort": 0, "DBInstanceIdentifier": "cc-project5-mysql-database" } }
10 Repeat steps no. 1 – 9 for each unencrypted 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 Remediation process for other regions.
References
- AWS Documentation
- Amazon RDS FAQs
- Security in Amazon RDS
- Encrypting Amazon RDS Resources
- AWS Command Line Interface (CLI) Documentation
- rds
- describe-db-instances
- create-db-snapshot
- copy-db-snapshot
- restore-db-instance-from-db-snapshot
- AWS Blog(s)
- Data Encryption Made Easier – New Encryption Options for Amazon RDS
- Amazon RDS Update – Share Encrypted Snapshots, Encrypt Existing Instances
- CloudFormation Documentation
- Amazon Relational Database Service resource type reference
- Terraform Documentation
- AWS Provider