This check flags Redshift clusters encrypted with the default AWS-managed KMS key, which strips you of key rotation control, granular access policies, and clean audit boundaries. Fix it by creating a customer managed key (CMK) and re-encrypting the cluster with it.
Encryption at rest gets a checkmark in a lot of audits the moment it is "on," but the key behind that encryption matters just as much as the toggle itself. When a Redshift cluster is encrypted with the default aws/redshift KMS key, you are technically encrypted, but you have handed away most of the control that makes encryption useful for security and compliance. This check exists to catch that gap.
Below we walk through what the check looks for, why a default key is a weaker posture than it appears, and how to migrate your clusters to a customer managed key (CMK) without losing data.
What this check detects
The redshift_defaultkms check inspects each Amazon Redshift cluster in your account and reports any cluster whose at-rest encryption uses the AWS-managed default KMS key rather than a customer managed key.
When you create a Redshift cluster and tick the encryption box without specifying a key, AWS uses the service-default key aliased aws/redshift. That key is created and owned by AWS in your account. You cannot edit its key policy, you cannot control its rotation schedule, and you cannot disable or delete it. The check looks at the cluster's KmsKeyId and resolves whether it points at this default key or at one you manage.
Note: A cluster encrypted with the default key still encrypts data at rest. This is not a finding about missing encryption. It is a finding about who controls the encryption. The difference shows up when you need to rotate keys on your own schedule, restrict who can decrypt, or prove a clean cryptographic boundary to an auditor.
Why it matters
The default key feels convenient, and for low-stakes workloads it might be fine. For a data warehouse that often holds your most sensitive aggregated data, the limitations add up quickly.
You cannot scope access with a key policy
The single most valuable property of a CMK is its key policy. With a CMK, you can say "only these three roles may use this key to decrypt," which means even a principal with full Redshift permissions cannot read the data unless they also have kms:Decrypt on your key. The AWS-managed default key grants usage broadly to the service within your account, so you lose this second line of defense entirely.
No control over rotation
AWS-managed keys rotate automatically every year and you cannot change that. With a CMK you can enable annual rotation, trigger manual rotation in response to an incident, or align rotation to a compliance window. If a key is suspected of exposure, the ability to rotate or disable on demand is exactly what you want, and it is exactly what the default key denies you.
Cross-account and snapshot sharing breaks down
You cannot share a Redshift snapshot encrypted with the default key to another account, because the receiving account has no way to be granted access to a key it does not control. Teams that rely on cross-account snapshot sharing for DR, analytics, or environment promotion hit a wall the moment the source cluster uses the default key.
Warning: If you are planning a multi-account data strategy, snapshot copies, or cross-region disaster recovery, do this migration early. Retrofitting key ownership after you have terabytes of snapshots scattered across accounts is far more painful than getting it right at cluster creation.
Compliance and audit clarity
Frameworks like PCI DSS, HIPAA, and SOC 2 expect you to demonstrate control over cryptographic keys protecting regulated data. "AWS rotates it for us and we cannot see the policy" is a harder story to tell an auditor than a CMK with a documented policy, CloudTrail decrypt logs, and a defined rotation schedule.
How to fix it
Redshift does not let you swap the encryption key on a running cluster in place. The supported path is to create a CMK, then re-encrypt the cluster, which Redshift handles as a background migration. For older cluster types you may instead snapshot, then restore into a new encrypted cluster.
Step 1: Create a customer managed key
aws kms create-key \
--description "CMK for Redshift cluster encryption" \
--tags TagKey=Purpose,TagValue=redshift-encryption \
--region us-east-1
Note the KeyId in the output, then give it a readable alias:
aws kms create-alias \
--alias-name alias/redshift-prod-cmk \
--target-key-id <key-id> \
--region us-east-1
aws kms enable-key-rotation \
--key-id <key-id> \
--region us-east-1
Step 2: Scope the key policy
Attach a key policy that grants decrypt access only to the principals that genuinely need it. Here is a starting point that lets your account administer the key and lets a specific Redshift role use it:
{
"Version": "2012-10-17",
"Id": "redshift-cmk-policy",
"Statement": [
{
"Sid": "AllowAccountAdmin",
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::111122223333:root" },
"Action": "kms:*",
"Resource": "*"
},
{
"Sid": "AllowRedshiftUse",
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::111122223333:role/redshift-service-role" },
"Action": [
"kms:Encrypt",
"kms:Decrypt",
"kms:ReEncrypt*",
"kms:GenerateDataKey*",
"kms:DescribeKey",
"kms:CreateGrant"
],
"Resource": "*"
}
]
}
Step 3: Re-encrypt the cluster with the CMK
For RA3 and most modern cluster types, you can modify the cluster to use the new key. Redshift migrates the data in the background.
Danger: Re-encryption is a heavy background operation. The cluster stays available for reads and writes, but performance can degrade and the migration can take hours on large clusters. Run it during a maintenance window and verify you have a recent snapshot before you start.
aws redshift modify-cluster \
--cluster-identifier my-prod-cluster \
--encrypted \
--kms-key-id alias/redshift-prod-cmk \
--region us-east-1
Track progress and confirm the new key is in place:
aws redshift describe-clusters \
--cluster-identifier my-prod-cluster \
--query "Clusters[0].{Status:ClusterStatus,KmsKeyId:KmsKeyId,Encrypted:Encrypted}" \
--region us-east-1
Alternative: snapshot and restore
If your cluster type does not support in-place re-encryption, take an encrypted snapshot keyed to the CMK and restore into a fresh cluster, then cut over.
# Take a manual snapshot
aws redshift create-cluster-snapshot \
--snapshot-identifier my-cluster-cmk-snap \
--cluster-identifier my-prod-cluster
# Restore into a new cluster encrypted with the CMK
aws redshift restore-from-cluster-snapshot \
--cluster-identifier my-prod-cluster-cmk \
--snapshot-identifier my-cluster-cmk-snap \
--kms-key-id alias/redshift-prod-cmk
Warning: The snapshot-and-restore path creates a new cluster with a new endpoint. Update connection strings, DNS, and any downstream BI tools before you decommission the original. Run both clusters in parallel briefly to validate.
How to prevent it from happening again
Fixing one cluster is easy. Keeping every future cluster off the default key is the real win. Bake the CMK into your provisioning so nobody has to remember it.
Terraform
resource "aws_kms_key" "redshift" {
description = "CMK for Redshift encryption"
enable_key_rotation = true
}
resource "aws_kms_alias" "redshift" {
name = "alias/redshift-prod-cmk"
target_key_id = aws_kms_key.redshift.key_id
}
resource "aws_redshift_cluster" "main" {
cluster_identifier = "my-prod-cluster"
node_type = "ra3.xlplus"
number_of_nodes = 2
database_name = "analytics"
master_username = "admin"
encrypted = true
kms_key_id = aws_kms_key.redshift.arn
}
Block the default key with policy-as-code
Add a guardrail that fails the build when kms_key_id is missing on a Redshift resource. With Checkov or a custom OPA policy you can stop the merge before it ships. A simple Conftest rule against a Terraform plan looks like this:
package main
deny[msg] {
resource := input.resource_changes[_]
resource.type == "aws_redshift_cluster"
not resource.change.after.kms_key_id
msg := sprintf("Redshift cluster '%s' must specify a customer managed kms_key_id", [resource.address])
}
Tip: Pair the CI gate with a continuous check in Lensix so drift gets caught even when someone provisions a cluster by hand in the console. CI catches the pipeline path, continuous scanning catches everything else.
Detect existing default-key clusters at scale
Run this across an account to list any cluster still pointing at the default key alias:
aws redshift describe-clusters \
--query "Clusters[?KmsKeyId==null || contains(KmsKeyId, 'aws/redshift')].ClusterIdentifier" \
--output table
Best practices
- Use a dedicated CMK per workload or environment. Separate keys for prod, staging, and dev give you cleaner blast radius control and let you revoke access to one environment without touching the others.
- Enable automatic rotation on every CMK, and document a manual rotation runbook for incident response.
- Keep key policies tight. Grant
kms:Decryptonly to the roles that need it. The key policy is your second factor of access control after IAM. - Log and alert on KMS usage. Send CloudTrail KMS events to your SIEM and alert on unexpected
Decryptcalls or anyDisableKeyorScheduleKeyDeletionaction. - Plan key access for cross-account sharing up front. If snapshots will travel between accounts, design the key policy and grants before you generate the snapshots.
- Never schedule deletion of a key still protecting a live cluster. KMS key deletion is irreversible after the waiting period, and the data encrypted under it becomes permanently unreadable.
Danger: Scheduling deletion of a CMK in use by a Redshift cluster will eventually make that cluster's data unrecoverable. Before retiring any key, confirm no cluster, snapshot, or other resource still references it.
Moving off the default key is a small, contained change that pays off the first time you need to rotate a key, share a snapshot, or answer an auditor's question about who can read your warehouse. Make the CMK the default in your templates, gate it in CI, and let continuous scanning catch the stragglers.

