Emr At Rest In Transit Encryption Remediation
Triage and Remediation
- Remediation
Remediation
Using Console
Below are step‑by‑step console instructions to enable at‑rest and in‑transit encryption for Amazon Redshift.
1. At‑Rest Encryption (Redshift)
A. Check whether your existing cluster is encrypted
- Sign in to the AWS Management Console.
- Go to Amazon Redshift console.
- In the left pane, choose Clusters.
- Click your cluster identifier.
- On the Configuration tab, look for:
- Encryption: Enabled / Disabled
- KMS key: Which KMS key is used, if enabled.
If Encryption = Enabled, at‑rest encryption is already configured.
Note: Redshift cluster encryption cannot be turned on or off for an existing cluster. You must create a new encrypted cluster and move data.
B. Create or choose a KMS Customer Managed Key (optional but recommended)
If you don’t want to use the default AWS managed key:
- Open the AWS KMS console.
- Select Customer managed keys → Create key.
- Choose Symmetric → Next.
- Give it an alias (e.g.,
alias/redshift-encryption-key). - Configure key administrators and key usage permissions (grant Redshift account roles or IAM roles that will manage the cluster).
- Finish key creation.
C. Create a new encrypted Redshift cluster
- In the Redshift console, go to Clusters → Create cluster.
- Under Cluster configuration, set:
- Cluster identifier, Node type, number of nodes as needed.
- Under Database configurations, set admin username/password.
- Under Security and encryption (or similar section):
- Turn Encryption: On.
- KMS key: Select either:
- Default AWS Key for Redshift, or
- The customer managed key you created (e.g.,
alias/redshift-encryption-key).
- Configure networking/security groups as needed.
- Choose Create cluster.
This new cluster will now have encryption at rest enabled.
D. Move data from unencrypted to encrypted cluster
-
Option 1 – Snapshot and restore (if original is encrypted with a different key or you’re cloning an already‑encrypted one):
- For an unencrypted cluster you can’t create an encrypted snapshot directly; instead:
- Create a new encrypted cluster (done above),
- Use UNLOAD / COPY commands to migrate data.
- For an unencrypted cluster you can’t create an encrypted snapshot directly; instead:
-
Option 2 – UNLOAD / COPY:
- From the source (unencrypted) cluster:
- Use
UNLOADto export data to S3 (optionally encrypt S3 objects with SSE‑S3 or SSE‑KMS).
- Use
- From the target (encrypted) cluster:
- Use
COPYto load data from S3 into the new cluster.
- Use
- From the source (unencrypted) cluster:
-
After validation, point applications to the new encrypted cluster and decommission the old one.
2. In‑Transit Encryption (SSL/TLS) for Redshift
Redshift supports SSL/TLS for connections. You must:
- Ensure the cluster has SSL enabled (it is by default),
- Optionally enforce SSL in a parameter group,
- Update clients to use SSL.
A. Verify or configure SSL requirement via parameter group
- Go to the Redshift console → Parameter groups.
- Find the parameter group associated with your cluster:
- In Clusters → select cluster → Properties → note the Parameter group.
- If using the default parameter group:
- You cannot modify it. Create a new parameter group:
- Parameter groups → Create parameter group.
- Choose:
- Parameter group family matching your engine version.
- Group name and Description.
- Click Create.
- You cannot modify it. Create a new parameter group:
- Select your (new) parameter group → Edit parameters.
- Find parameter:
require_ssl.- Set Value to
true.
- Set Value to
- Save changes.
B. Attach the parameter group to the cluster
- In the Redshift console, go to Clusters.
- Select your cluster → Actions → Modify cluster.
- Under Database configurations (or Cluster properties):
- Set Parameter group to the new parameter group where
require_ssl = true.
- Set Parameter group to the new parameter group where
- Save/Apply changes and reboot the cluster if prompted:
- Cluster → Actions → Reboot (if not done automatically).
Once applied, the cluster will reject non‑SSL connections.
C. Ensure clients connect using SSL
For each application / client:
- Get cluster endpoint:
- Redshift console → Clusters → select cluster → General information → Endpoint.
- Use SSL-enabled connection strings.
Examples:
-
psql:
psql "host=<cluster-endpoint> port=5439 dbname=<db> user=<user> sslmode=require" -
JDBC URL:
jdbc:redshift://<cluster-endpoint>:5439/<db>?ssl=true&sslfactory=com.amazon.redshift.ssl.NonValidatingFactory -
ODBC:
- In DSN configuration, enable SSL or Require SSL.
- If you need certificate validation, download Redshift’s public certificate from AWS docs and configure client trust stores accordingly (optional but recommended).
3. Validate the Remediation
- At rest:
- Redshift console → Clusters → select cluster → Configuration:
- Confirm Encryption: Enabled and correct KMS key.
- Redshift console → Clusters → select cluster → Configuration:
- In transit:
- Confirm applications can only connect when SSL is enabled.
- Try a test connection without SSL and verify it fails.
This completes in‑transit and at‑rest encryption remediation for Amazon Redshift via the AWS console.
Using CLI
For Amazon Redshift, “in‑transit” = SSL, and “at‑rest” = KMS encryption on the cluster.
At‑rest encryption cannot be turned on for an existing unencrypted cluster; you must migrate to a new encrypted cluster.
Below are step‑by‑step AWS CLI instructions.
1. At‑Rest Encryption (Redshift)
1.1. Create (or identify) a KMS key
aws kms create-key --description "Redshift encryption key"
Output will include "KeyId": "arn:aws:kms:region:account-id:key/xxxxxxxx" – save this ARN.
Optionally add an alias:
aws kms create-alias \
--alias-name alias/redshift-kms \
--target-key-id <kms-key-id-or-arn>
You can then use alias/redshift-kms instead of the full ARN.
1.2. Snapshot your existing unencrypted cluster
Replace my-redshift-cluster and my-redshift-snapshot:
aws redshift create-cluster-snapshot \
--cluster-identifier my-redshift-cluster \
--snapshot-identifier my-redshift-snapshot
Wait until the snapshot is available:
aws redshift describe-cluster-snapshots \
--snapshot-identifier my-redshift-snapshot \
--query "Snapshots[0].Status"
1.3. Restore a new encrypted cluster from the snapshot
aws redshift restore-from-cluster-snapshot \
--cluster-identifier my-redshift-cluster-encrypted \
--snapshot-identifier my-redshift-snapshot \
--encrypted \
--kms-key-id alias/redshift-kms
You can also specify node type, security groups, etc., if you want to override snapshot defaults (optional):
aws redshift restore-from-cluster-snapshot \
--cluster-identifier my-redshift-cluster-encrypted \
--snapshot-identifier my-redshift-snapshot \
--encrypted \
--kms-key-id alias/redshift-kms \
--node-type ra3.xlplus \
--cluster-subnet-group-name my-subnet-group \
--vpc-security-group-ids sg-xxxxxxxx \
--publicly-accessible false
Wait until the new cluster is available:
aws redshift describe-clusters \
--cluster-identifier my-redshift-cluster-encrypted \
--query "Clusters[0].ClusterStatus"
1.4. Cut over and clean up
- Update applications to point to the new cluster’s endpoint (from
describe-clusters). - When fully migrated, delete the old unencrypted cluster:
aws redshift delete-cluster \
--cluster-identifier my-redshift-cluster \
--skip-final-cluster-snapshot
(Or omit --skip-final-cluster-snapshot and specify --final-cluster-snapshot-identifier if you want a final backup.)
2. In‑Transit Encryption (SSL) for Redshift
To enforce SSL, configure a parameter group and apply it to the cluster.
2.1. Create a parameter group (if you don’t already have a custom one)
aws redshift create-cluster-parameter-group \
--parameter-group-name my-redshift-ssl-pg \
--parameter-group-family redshift-1.0 \
--description "Require SSL for Redshift"
(Use redshift-1.0 or the family appropriate to your engine version.)
2.2. Set require_ssl to true
aws redshift modify-cluster-parameter-group \
--parameter-group-name my-redshift-ssl-pg \
--parameters "ParameterName=require_ssl,ParameterValue=true,Description=RequireSSL,ApplyType=static"
You can verify:
aws redshift describe-cluster-parameters \
--parameter-group-name my-redshift-ssl-pg \
--query "Parameters[?ParameterName=='require_ssl']"
2.3. Attach the parameter group to your (encrypted) cluster
aws redshift modify-cluster \
--cluster-identifier my-redshift-cluster-encrypted \
--cluster-parameter-group-name my-redshift-ssl-pg
You must reboot for static parameters to take effect:
aws redshift reboot-cluster \
--cluster-identifier my-redshift-cluster-encrypted
2.4. Ensure clients actually use SSL
Redshift will now require SSL, but your clients must be configured correctly:
- JDBC:
ssl=trueorsslmode=requirein the connection string. - ODBC: enable SSL / require SSL in DSN settings.
- psql:
sslmode=require(orverify-ca/verify-fullwith appropriate CA).
No extra CLI steps are needed here; this is client configuration.
3. Quick Verification
At‑rest encryption:
aws redshift describe-clusters \
--cluster-identifier my-redshift-cluster-encrypted \
--query "Clusters[0].[Encrypted,KmsKeyId]"
Should return true and the KMS key.
In‑transit (SSL) enforcement:
aws redshift describe-clusters \
--cluster-identifier my-redshift-cluster-encrypted \
--query "Clusters[0].ClusterParameterGroups"
Make sure my-redshift-ssl-pg is attached and ParameterApplyStatus is in-sync. Then test connections; non‑SSL connections should fail.
If you share your current cluster identifier and whether it’s already encrypted, I can tailor exact CLI commands for your environment.
Using Python
For Amazon Redshift, “in-transit” = SSL/TLS for client connections; “at-rest” = KMS-encrypted data on disk (cluster + snapshots).
Below is how to remediate both using Python (boto3).
Prereqs
pip install boto3
import boto3
redshift = boto3.client("redshift", region_name="us-east-1") # adjust region
Replace placeholders like <CLUSTER_IDENTIFIER>, <KMS_KEY_ARN> as needed.
1. At-Rest Encryption
A. New cluster (easiest)
You cannot enable encryption on an existing unencrypted cluster; you must create a new encrypted one and migrate.
- Create an encrypted snapshot of the old cluster (unencrypted snapshot → restore as encrypted).
# 1. Take snapshot of existing (unencrypted) cluster
snapshot_id = "old-cluster-snapshot"
redshift.create_cluster_snapshot(
SnapshotIdentifier=snapshot_id,
ClusterIdentifier="<OLD_CLUSTER_IDENTIFIER>"
)
- Wait for snapshot to be available (poll or use waiter):
waiter = redshift.get_waiter('snapshot_available')
waiter.wait(SnapshotIdentifier=snapshot_id)
- Restore snapshot to a new encrypted cluster:
redshift.restore_from_cluster_snapshot(
ClusterIdentifier="<NEW_ENCRYPTED_CLUSTER>",
SnapshotIdentifier=snapshot_id,
Encrypted=True,
KmsKeyId="<KMS_KEY_ARN>" # or omit to use AWS managed key
)
- Wait for new cluster to be available:
waiter = redshift.get_waiter('cluster_available')
waiter.wait(ClusterIdentifier="<NEW_ENCRYPTED_CLUSTER>")
- Update clients / apps / connection strings to point to the new cluster’s endpoint, test, then delete the old cluster:
redshift.delete_cluster(
ClusterIdentifier="<OLD_CLUSTER_IDENTIFIER>",
SkipFinalClusterSnapshot=True # or create final snapshot if needed
)
Now your data at rest (cluster & snapshots) is encrypted.
B. Ensuring snapshots are encrypted
For an already encrypted cluster, snapshots are encrypted automatically with the same KMS key.
To ensure cross-region snapshot copy is encrypted:
redshift.enable_snapshot_copy(
ClusterIdentifier="<ENCRYPTED_CLUSTER>",
DestinationRegion="us-west-2",
RetentionPeriod=7,
SnapshotCopyGrantName="<SNAPSHOT_COPY_GRANT_NAME>",
KmsKeyId="<DEST_REGION_KMS_KEY_ARN>"
)
2. In-Transit Encryption (SSL/TLS)
You enable and enforce SSL via a parameter group (require_ssl).
A. Create / update a parameter group with require_ssl=1
- Create a new parameter group (if you don’t want to modify an existing one):
param_group_name = "redshift-ssl-required"
redshift.create_cluster_parameter_group(
ParameterGroupName=param_group_name,
ParameterGroupFamily="redshift-1.0", # check your engine family
Description="Require SSL for all connections"
)
- Set
require_ssl = true(1):
redshift.modify_cluster_parameter_group(
ParameterGroupName=param_group_name,
Parameters=[
{
"ParameterName": "require_ssl",
"ParameterValue": "true", # or "1"
"Description": "Force SSL for all DB connections",
"Source": "user",
"DataType": "boolean",
"AllowedValues": "true,false",
"IsModifiable": True,
"ApplyType": "static"
}
]
)
require_sslis a static parameter → cluster must be rebooted after the parameter group is associated.
B. Attach the parameter group to your cluster
redshift.modify_cluster(
ClusterIdentifier="<CLUSTER_IDENTIFIER>",
ClusterParameterGroupName=param_group_name
)
Then reboot (or wait for Redshift to apply & manually reboot):
redshift.reboot_cluster(ClusterIdentifier="<CLUSTER_IDENTIFIER>")
3. Enforce SSL From Clients
After require_ssl is on, non-SSL connections will fail.
Make sure your Python clients use SSL, for example with psycopg2:
import psycopg2
conn = psycopg2.connect(
dbname="<DB_NAME>",
user="<USER>",
password="<PASSWORD>",
host="<REDSHIFT_ENDPOINT>",
port=5439,
sslmode="require" # or "verify-full" with CA bundle
)
Summary
- At rest (Redshift):
- Existing unencrypted: snapshot → restore encrypted cluster (with
Encrypted=True,KmsKeyId=...) → switch traffic → delete old cluster. - New clusters: always create with
Encrypted=True.
- Existing unencrypted: snapshot → restore encrypted cluster (with
- In transit:
- Create/modify parameter group: set
require_ssl=true. - Attach parameter group, reboot cluster.
- Ensure all clients connect with
sslmode=require(or stronger).
- Create/modify parameter group: set
Using Terraform
# At-rest encryption for an existing Redshift cluster
# NOTE: Changing `encrypted` from false→true forces replacement of the cluster
# (full recreate, data loss unless you restore from snapshot).
resource "aws_redshift_cluster" "this" {
cluster_identifier = "REDSHIFT_CLUSTER_IDENTIFIER" # e.g., "analytics-prod"
node_type = "dc2.large"
master_username = "MASTER_USERNAME"
master_password = "MASTER_PASSWORD"
# Enable encryption at rest
encrypted = true
# Optionally use a customer-managed KMS key (recommended)
# Omit this line to use the default Redshift KMS key
kms_key_id = "KMS_KEY_ARN_OR_ID"
# Attach the parameter group that enforces SSL (see below)
cluster_parameter_group_name = aws_redshift_parameter_group.ssl_enforced.name
# ...other required arguments (subnets, security groups, etc) ...
}
# In-transit encryption: enforce SSL for all connections
resource "aws_redshift_parameter_group" "ssl_enforced" {
name = "REDSHIFT_SSL_REQUIRED_PARAMETER_GROUP_NAME"
family = "redshift-1.0"
description = "Require SSL for all client connections"
parameter {
name = "require_ssl"
value = "true"
}
}
To verify, terraform plan should show encrypted = true, the desired kms_key_id on aws_redshift_cluster.this, and parameter.require_ssl changing/created as value = "true" on aws_redshift_parameter_group.ssl_enforced, with a note that the cluster will be replaced if it was previously unencrypted.