Skip to main content

Emr At Rest In Transit Encryption Remediation

Triage and 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

  1. Sign in to the AWS Management Console.
  2. Go to Amazon Redshift console.
  3. In the left pane, choose Clusters.
  4. Click your cluster identifier.
  5. 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.


If you don’t want to use the default AWS managed key:

  1. Open the AWS KMS console.
  2. Select Customer managed keysCreate key.
  3. Choose SymmetricNext.
  4. Give it an alias (e.g., alias/redshift-encryption-key).
  5. Configure key administrators and key usage permissions (grant Redshift account roles or IAM roles that will manage the cluster).
  6. Finish key creation.

C. Create a new encrypted Redshift cluster

  1. In the Redshift console, go to ClustersCreate cluster.
  2. Under Cluster configuration, set:
    • Cluster identifier, Node type, number of nodes as needed.
  3. Under Database configurations, set admin username/password.
  4. 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).
  5. Configure networking/security groups as needed.
  6. Choose Create cluster.

This new cluster will now have encryption at rest enabled.


D. Move data from unencrypted to encrypted cluster

  1. 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.
  2. Option 2 – UNLOAD / COPY:

    • From the source (unencrypted) cluster:
      • Use UNLOAD to export data to S3 (optionally encrypt S3 objects with SSE‑S3 or SSE‑KMS).
    • From the target (encrypted) cluster:
      • Use COPY to load data from S3 into the new cluster.
  3. 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

  1. Go to the Redshift console → Parameter groups.
  2. Find the parameter group associated with your cluster:
    • In Clusters → select cluster → Properties → note the Parameter group.
  3. If using the default parameter group:
    • You cannot modify it. Create a new parameter group:
      1. Parameter groupsCreate parameter group.
      2. Choose:
        • Parameter group family matching your engine version.
        • Group name and Description.
      3. Click Create.
  4. Select your (new) parameter group → Edit parameters.
  5. Find parameter: require_ssl.
    • Set Value to true.
  6. Save changes.

B. Attach the parameter group to the cluster

  1. In the Redshift console, go to Clusters.
  2. Select your cluster → ActionsModify cluster.
  3. Under Database configurations (or Cluster properties):
    • Set Parameter group to the new parameter group where require_ssl = true.
  4. Save/Apply changes and reboot the cluster if prompted:
    • Cluster → ActionsReboot (if not done automatically).

Once applied, the cluster will reject non‑SSL connections.


C. Ensure clients connect using SSL

For each application / client:

  1. Get cluster endpoint:
    • Redshift console → Clusters → select cluster → General informationEndpoint.
  2. 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.
  1. 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.
  • 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

  1. Update applications to point to the new cluster’s endpoint (from describe-clusters).
  2. 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=true or sslmode=require in the connection string.
  • ODBC: enable SSL / require SSL in DSN settings.
  • psql: sslmode=require (or verify-ca/verify-full with 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.

  1. 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>"
)
  1. Wait for snapshot to be available (poll or use waiter):
waiter = redshift.get_waiter('snapshot_available')
waiter.wait(SnapshotIdentifier=snapshot_id)
  1. 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
)
  1. Wait for new cluster to be available:
waiter = redshift.get_waiter('cluster_available')
waiter.wait(ClusterIdentifier="<NEW_ENCRYPTED_CLUSTER>")
  1. 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

  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"
)
  1. 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_ssl is 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

  1. 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.
  2. In transit:
    • Create/modify parameter group: set require_ssl=true.
    • Attach parameter group, reboot cluster.
    • Ensure all clients connect with sslmode=require (or stronger).
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.