Back to Checks
RDS DB instance snapshot or DB cluster snapshot is encrypted
rds_snapshots_encrypted
Service: rdsSeverity: high
OfficialBuilt-inVerified
Categories:encryption
Resource Type:AwsRdsDbSnapshot
RDS DB snapshots and DB cluster snapshots are evaluated for encryption at rest, identifying snapshots created with a KMS key versus unencrypted ones.
Risk
Unencrypted snapshots enable direct access to full database data if backups are leaked, cross-account shared, or stolen. Adversaries can harvest data offline, bypassing network controls, leading to loss of confidentiality. Restores from such snapshots propagate the exposure to new instances.
Run this check with Prowler
Run in Prowler CloudRun
prowler aws --checks rds_snapshots_encryptedRecommendation
Encrypt all RDS snapshots at rest using KMS, preferably customer-managed keys. Apply least privilege to key usage, enforce encryption via templates and automation, and prevent sharing of unencrypted backups. Use key rotation, separation of duties, and ensure copies and cross-account shares remain encrypted.
Remediation
CLI
aws rds copy-db-snapshot --source-db-snapshot-identifier <example_resource_id> --target-db-snapshot-identifier <example_resource_id>-encrypted --kms-key-id <KMS_KEY_ID>Terraform
resource "aws_db_snapshot_copy" "<example_resource_name>" {
source_db_snapshot_identifier = "<example_resource_id>"
target_db_snapshot_identifier = "<example_resource_id>-encrypted"
kms_key_id = "<KMS_KEY_ID>" # Critical: encrypts the copied snapshot using the specified KMS key
}Other
1In the AWS Console, go to RDS > Snapshots
2Select the unencrypted snapshot (for clusters, use the DB cluster snapshots tab)
3Click Actions > Copy snapshot
4Check Enable encryption and choose a KMS key
5Click Copy snapshot and wait for completion
6After verifying the new encrypted snapshot, delete the original unencrypted snapshot (Actions > Delete snapshot)
Check Code
from prowler.lib.check.models import Check, Check_Report_AWS
from prowler.providers.aws.services.rds.rds_client import rds_client
class rds_snapshots_encrypted(Check):
def execute(self):
findings = []
for db_snap in rds_client.db_snapshots:
report = Check_Report_AWS(metadata=self.metadata(), resource=db_snap)
if db_snap.encrypted:
report.status = "PASS"
report.status_extended = (
f"RDS Instance Snapshot {db_snap.id} is encrypted."
)
else:
report.status = "FAIL"
report.status_extended = (
f"RDS Instance Snapshot {db_snap.id} is not encrypted."
)
findings.append(report)
for db_snap in rds_client.db_cluster_snapshots:
report = Check_Report_AWS(metadata=self.metadata(), resource=db_snap)
if db_snap.encrypted:
report.status = "PASS"
report.status_extended = (
f"RDS Cluster Snapshot {db_snap.id} is encrypted."
)
else:
report.status = "FAIL"
report.status_extended = (
f"RDS Cluster Snapshot {db_snap.id} is not encrypted."
)
findings.append(report)
return findings