Skip to main content

RDS DB Instance Storage Encrypted

Overview

This check verifies that your Amazon RDS database instances have storage encryption enabled at rest. When encryption is turned on, AWS automatically encrypts your database files, automated backups, read replicas, and snapshots using a KMS key.

Risk

If your RDS instance storage is not encrypted:

  • Data exposure: Anyone who gains access to the underlying storage (through a breach, misconfiguration, or insider threat) can read your database files directly.
  • Compliance violations: Many regulations (HIPAA, PCI-DSS, GDPR) require encryption of sensitive data at rest.
  • Backup vulnerability: Unencrypted snapshots and backups remain unprotected, even if stored in S3.

Severity: High

Remediation Steps

Prerequisites

  • AWS account access with permissions to manage RDS instances and KMS keys
  • The existing RDS instance must be in the available state

Important: You cannot enable encryption on an existing unencrypted RDS instance directly. You must create an encrypted copy from a snapshot and migrate to the new instance.

Required IAM permissions

You need the following permissions:

  • rds:CreateDBSnapshot
  • rds:CopyDBSnapshot
  • rds:RestoreDBInstanceFromDBSnapshot
  • rds:DescribeDBInstances
  • rds:DeleteDBInstance (for cleanup)
  • kms:CreateGrant (if using a customer-managed KMS key)
  • kms:DescribeKey

AWS Console Method

  1. Open the RDS Console

  2. Create a snapshot of your unencrypted instance

    • Click Databases in the left menu
    • Select your unencrypted database instance
    • Click Actions > Take snapshot
    • Enter a snapshot name (e.g., mydb-pre-encryption-snapshot)
    • Click Take snapshot
    • Wait for the snapshot status to show Available
  3. Copy the snapshot with encryption enabled

    • Click Snapshots in the left menu
    • Select the snapshot you just created
    • Click Actions > Copy snapshot
    • Enter a new snapshot name (e.g., mydb-encrypted-snapshot)
    • Check the box for Enable encryption
    • Choose a KMS key (use the default aws/rds key or select a customer-managed key)
    • Click Copy snapshot
    • Wait for the encrypted snapshot status to show Available
  4. Restore a new instance from the encrypted snapshot

    • Select the encrypted snapshot
    • Click Actions > Restore snapshot
    • Enter a new DB instance identifier (e.g., mydb-encrypted)
    • Configure instance settings as needed (instance class, VPC, etc.)
    • Click Restore DB instance
  5. Migrate your application

    • Update your application connection strings to point to the new encrypted instance
    • Test thoroughly before decommissioning the old instance
  6. Clean up the old instance

    • Once migration is complete, delete the old unencrypted instance
    • Consider keeping the snapshots temporarily for rollback purposes
AWS CLI (optional)

Step 1: Create a snapshot of the unencrypted instance

aws rds create-db-snapshot \
--db-instance-identifier <your-db-instance> \
--db-snapshot-identifier <your-db-instance>-pre-encryption \
--region us-east-1

Step 2: Wait for the snapshot to be available

aws rds wait db-snapshot-available \
--db-snapshot-identifier <your-db-instance>-pre-encryption \
--region us-east-1

Step 3: Copy the snapshot with encryption

Using the default RDS KMS key:

aws rds copy-db-snapshot \
--source-db-snapshot-identifier <your-db-instance>-pre-encryption \
--target-db-snapshot-identifier <your-db-instance>-encrypted \
--kms-key-id alias/aws/rds \
--region us-east-1

Or using a customer-managed KMS key:

aws rds copy-db-snapshot \
--source-db-snapshot-identifier <your-db-instance>-pre-encryption \
--target-db-snapshot-identifier <your-db-instance>-encrypted \
--kms-key-id arn:aws:kms:us-east-1:<account-id>:key/<key-id> \
--region us-east-1

Step 4: Wait for the encrypted snapshot

aws rds wait db-snapshot-available \
--db-snapshot-identifier <your-db-instance>-encrypted \
--region us-east-1

Step 5: Restore a new instance from the encrypted snapshot

aws rds restore-db-instance-from-db-snapshot \
--db-instance-identifier <your-db-instance>-new \
--db-snapshot-identifier <your-db-instance>-encrypted \
--db-instance-class db.t3.micro \
--region us-east-1

Step 6: Wait for the new instance to be available

aws rds wait db-instance-available \
--db-instance-identifier <your-db-instance>-new \
--region us-east-1
CloudFormation (optional)

Use this template to create a new RDS instance with encryption enabled. This does not migrate existing data - use the snapshot method above for existing instances.

AWSTemplateFormatVersion: '2010-09-09'
Description: RDS instance with encrypted storage

Parameters:
DBInstanceIdentifier:
Type: String
Description: Unique identifier for the DB instance
DBInstanceClass:
Type: String
Default: db.t3.micro
Description: The compute and memory capacity of the DB instance
Engine:
Type: String
Default: mysql
AllowedValues:
- mysql
- postgres
- mariadb
Description: The database engine type
MasterUsername:
Type: String
Description: Master username for the database
MasterUserPassword:
Type: String
NoEcho: true
Description: Master password for the database
AllocatedStorage:
Type: Number
Default: 20
Description: The size of the database storage (GB)
KMSKeyId:
Type: String
Default: ''
Description: KMS key ID for encryption (optional - uses default RDS key if empty)

Conditions:
UseCustomKMSKey: !Not [!Equals [!Ref KMSKeyId, '']]

Resources:
RDSInstance:
Type: AWS::RDS::DBInstance
Properties:
DBInstanceIdentifier: !Ref DBInstanceIdentifier
DBInstanceClass: !Ref DBInstanceClass
Engine: !Ref Engine
MasterUsername: !Ref MasterUsername
MasterUserPassword: !Ref MasterUserPassword
AllocatedStorage: !Ref AllocatedStorage
StorageEncrypted: true
KmsKeyId: !If [UseCustomKMSKey, !Ref KMSKeyId, !Ref 'AWS::NoValue']
PubliclyAccessible: false
DeletionProtection: true

Outputs:
DBInstanceEndpoint:
Description: The connection endpoint for the database
Value: !GetAtt RDSInstance.Endpoint.Address
DBInstancePort:
Description: The port of the database
Value: !GetAtt RDSInstance.Endpoint.Port

Key property: StorageEncrypted: true

Deploy with:

aws cloudformation create-stack \
--stack-name encrypted-rds-instance \
--template-body file://template.yaml \
--parameters \
ParameterKey=DBInstanceIdentifier,ParameterValue=my-encrypted-db \
ParameterKey=MasterUsername,ParameterValue=admin \
ParameterKey=MasterUserPassword,ParameterValue=<your-secure-password> \
--region us-east-1
Terraform (optional)

Use this configuration to create a new RDS instance with encryption enabled.

terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}

provider "aws" {
region = "us-east-1"
}

variable "db_identifier" {
description = "Identifier for the RDS instance"
type = string
}

variable "db_instance_class" {
description = "Instance class for the RDS instance"
type = string
default = "db.t3.micro"
}

variable "engine" {
description = "Database engine type"
type = string
default = "mysql"
}

variable "engine_version" {
description = "Database engine version"
type = string
default = "8.0"
}

variable "allocated_storage" {
description = "Allocated storage in GB"
type = number
default = 20
}

variable "db_username" {
description = "Master username for the database"
type = string
}

variable "db_password" {
description = "Master password for the database"
type = string
sensitive = true
}

variable "kms_key_id" {
description = "KMS key ID for encryption (optional)"
type = string
default = null
}

resource "aws_db_instance" "encrypted" {
identifier = var.db_identifier
instance_class = var.db_instance_class
engine = var.engine
engine_version = var.engine_version
allocated_storage = var.allocated_storage
username = var.db_username
password = var.db_password

# Encryption settings
storage_encrypted = true
kms_key_id = var.kms_key_id

# Security settings
publicly_accessible = false
deletion_protection = true

skip_final_snapshot = false
final_snapshot_identifier = "${var.db_identifier}-final-snapshot"
}

output "db_instance_endpoint" {
description = "The connection endpoint"
value = aws_db_instance.encrypted.endpoint
}

output "db_instance_arn" {
description = "The ARN of the RDS instance"
value = aws_db_instance.encrypted.arn
}

Key property: storage_encrypted = true

Deploy with:

terraform init
terraform plan -var="db_identifier=my-encrypted-db" \
-var="db_username=admin" \
-var="db_password=<your-secure-password>"
terraform apply

Verification

After remediation, verify that your RDS instance is now encrypted:

  1. In the AWS Console:

    • Go to RDS > Databases
    • Click on your database instance
    • Under the Configuration tab, look for Encryption: it should show Enabled
  2. Using Prowler:

    prowler aws --checks rds_instance_storage_encrypted --region us-east-1
AWS CLI verification
aws rds describe-db-instances \
--db-instance-identifier <your-db-instance> \
--query "DBInstances[0].StorageEncrypted" \
--region us-east-1

Expected output: true

To check all instances at once:

aws rds describe-db-instances \
--query "DBInstances[*].[DBInstanceIdentifier,StorageEncrypted]" \
--output table \
--region us-east-1

Additional Resources

Notes

  • Encryption cannot be disabled: Once an RDS instance is encrypted, you cannot turn off encryption.
  • Performance impact: Encryption has minimal performance impact (typically less than 5%).
  • Cross-region considerations: When copying encrypted snapshots across regions, you must specify a KMS key in the destination region.
  • Read replicas: Read replicas of encrypted instances are automatically encrypted with the same key.
  • Instance class limitations: Some older instance classes do not support encryption. Check AWS documentation for compatibility.
  • Cost: Using customer-managed KMS keys incurs additional KMS API charges. The default aws/rds key is free.