Amazon Redshift controls - AWS Control Tower

Amazon Redshift controls

[CT.REDSHIFT.PR.1] Require an Amazon Redshift cluster to prohibit public access

This control checks whether Amazon Redshift clusters are configured to prohibit public access.

  • Control objective: Limit network access

  • Implementation: AWS CloudFormation Guard Rule

  • Control behavior: Proactive

  • Resource types: AWS::Redshift::Cluster

  • AWS CloudFormation guard rule: CT.REDSHIFT.PR.1 rule specification

Details and examples

Explanation

The PubliclyAccessible attribute of the Amazon Redshift cluster configuration indicates whether the cluster is publicly accessible. When the cluster is configured with the PubliclyAccessible parameter set to true, it is an internet-facing instance that has a publicly resolvable DNS name, which resolves to a public IP address.

When the cluster is not publicly accessible, it is an internal instance with a DNS name that resolves to a private IP address. Unless you intend for your cluster to be publicly accessible, the cluster should not be configured with PubliclyAccessible set to true.

Remediation for rule failure

Set PubliclyAccessible to false.

The examples that follow show how to implement this remediation.

Amazon Redshift Cluster - Example

Amazon Redshift cluster configured to prohibit public access. The example is shown in JSON and in YAML.

JSON example

{ "RedshiftCluster": { "Type": "AWS::Redshift::Cluster", "Properties": { "ClusterType": "single-node", "DBName": "sampledb", "MasterUsername": { "Fn::Sub": "{{resolve:secretsmanager:${RedshiftClusterSecret}::username}}" }, "MasterUserPassword": { "Fn::Sub": "{{resolve:secretsmanager:${RedshiftClusterSecret}::password}}" }, "NodeType": "ds2.xlarge", "PubliclyAccessible": false } } }

YAML example

RedshiftCluster: Type: AWS::Redshift::Cluster Properties: ClusterType: single-node DBName: sampledb MasterUsername: !Sub '{{resolve:secretsmanager:${RedshiftClusterSecret}::username}}' MasterUserPassword: !Sub '{{resolve:secretsmanager:${RedshiftClusterSecret}::password}}' NodeType: ds2.xlarge PubliclyAccessible: false

CT.REDSHIFT.PR.1 rule specification

# ################################### ## Rule Specification ## ##################################### # # Rule Identifier: # redshift_cluster_public_access_check # # Description: # This control checks whether Amazon Redshift clusters are configured to prohibit public access. # # Reports on: # AWS::Redshift::Cluster # # Evaluates: # AWS CloudFormation, AWS CloudFormation hook # # Rule Parameters: # None # # Scenarios: # Scenario: 1 # Given: The input document is an AWS CloudFormation document or AWS CloudFormation hook document # And: The input document does not contain any Redshift cluster resources # Then: SKIP # Scenario: 2 # Given: The input document is an AWS CloudFormation document or AWS CloudFormation hook document # And: The input document contains a Redshift cluster resource # And: 'PubliclyAccessible' has not been specified # Then: FAIL # Scenario: 3 # Given: The input document is an AWS CloudFormation document or AWS CloudFormation hook document # And: The input document contains a Redshift cluster resource # And: 'PubliclyAccessible' has been specified # And: 'PubliclyAccessible' has been set to bool(true) # Then: FAIL # Scenario: 4 # Given: The input document is an AWS CloudFormation document or AWS CloudFormation hook document # And: The input document contains a Redshift cluster resource # And: 'PubliclyAccessible' has been specified # And: 'PubliclyAccessible' has been set to bool(false) # Then: PASS # # Constants # let REDSHIFT_CLUSTER_TYPE = "AWS::Redshift::Cluster" let INPUT_DOCUMENT = this # # Assignments # let redshift_clusters = Resources.*[ Type == %REDSHIFT_CLUSTER_TYPE ] # # Primary Rules # rule redshift_cluster_public_access_check when is_cfn_template(%INPUT_DOCUMENT) %redshift_clusters not empty { check(%redshift_clusters.Properties) << [CT.REDSHIFT.PR.1]: Require an Amazon Redshift cluster to prohibit public access [FIX]: Set 'PubliclyAccessible' to 'false'. >> } rule redshift_cluster_public_access_check when is_cfn_hook(%INPUT_DOCUMENT, %REDSHIFT_CLUSTER_TYPE) { check(%INPUT_DOCUMENT.%REDSHIFT_CLUSTER_TYPE.resourceProperties) << [CT.REDSHIFT.PR.1]: Require an Amazon Redshift cluster to prohibit public access [FIX]: Set 'PubliclyAccessible' to 'false'. >> } # # Parameterized Rules # rule check(redshift_cluster) { %redshift_cluster { # Scenario 2 PubliclyAccessible exists # Scenario 3 and 4 PubliclyAccessible == false } } # # Utility Rules # rule is_cfn_template(doc) { %doc { AWSTemplateFormatVersion exists or Resources exists } } rule is_cfn_hook(doc, RESOURCE_TYPE) { %doc.%RESOURCE_TYPE.resourceProperties exists }

CT.REDSHIFT.PR.1 example templates

You can view examples of the PASS and FAIL test artifacts for the AWS Control Tower proactive controls.

PASS Example - Use this template to verify a compliant resource creation.

Resources: RedshiftSecret: Type: AWS::SecretsManager::Secret Properties: Description: Redshift cluster secret GenerateSecretString: SecretStringTemplate: '{"username": "examplemasterusername"}' GenerateStringKey: password PasswordLength: 16 ExcludeCharacters: "'\"@/\\" RedshiftCluster: Type: AWS::Redshift::Cluster Properties: ClusterType: single-node DBName: exampledb MasterUsername: Fn::Sub: '{{resolve:secretsmanager:${RedshiftSecret}::username}}' MasterUserPassword: Fn::Sub: '{{resolve:secretsmanager:${RedshiftSecret}::password}}' NodeType: dc2.large PubliclyAccessible: false

FAIL Example - Use this template to verify that the control prevents non-compliant resource creation.

Resources: RedshiftSecret: Type: AWS::SecretsManager::Secret Properties: Description: Redshift cluster secret GenerateSecretString: SecretStringTemplate: '{"username": "examplemasterusername"}' GenerateStringKey: password PasswordLength: 16 ExcludeCharacters: "'\"@/\\" RedshiftCluster: Type: AWS::Redshift::Cluster Properties: ClusterType: single-node DBName: exampledb MasterUsername: Fn::Sub: '{{resolve:secretsmanager:${RedshiftSecret}::username}}' MasterUserPassword: Fn::Sub: '{{resolve:secretsmanager:${RedshiftSecret}::password}}' NodeType: dc2.large PubliclyAccessible: true

[CT.REDSHIFT.PR.2] Require an Amazon Redshift cluster to have automatic snapshots configured

This control checks whether Amazon Redshift clusters have automated snapshots enabled, and that the clusters are set with an automated snapshot retention period greater than or equal to seven (7) days.

  • Control objective: Improve resiliency

  • Implementation: AWS CloudFormation Guard Rule

  • Control behavior: Proactive

  • Resource types: AWS::Redshift::Cluster

  • AWS CloudFormation guard rule: CT.REDSHIFT.PR.2 rule specification

Details and examples

Explanation

Backups help you to recover more quickly from a security incident. They strengthen the resilience of your systems. Amazon Redshift takes periodic snapshots by default. This control checks whether automatic snapshots are created and retained for at least seven days.

Remediation for rule failure

Set AutomatedSnapshotRetentionPeriod to an integer value greater than or equal to 7 days.

The examples that follow show how to implement this remediation.

Amazon Redshift Cluster - Example

Amazon Redshift cluster configured with automatic snapshots active. The example is shown in JSON and in YAML.

JSON example

{ "RedshiftCluster": { "Type": "AWS::Redshift::Cluster", "Properties": { "ClusterType": "single-node", "DBName": "sampledb", "MasterUsername": { "Fn::Sub": "{{resolve:secretsmanager:${RedshiftSecret}::username}}" }, "MasterUserPassword": { "Fn::Sub": "{{resolve:secretsmanager:${RedshiftSecret}::password}}" }, "NodeType": "ds2.xlarge", "AutomatedSnapshotRetentionPeriod": 7 } } }

YAML example

RedshiftCluster: Type: AWS::Redshift::Cluster Properties: ClusterType: single-node DBName: sampledb MasterUsername: !Sub '{{resolve:secretsmanager:${RedshiftSecret}::username}}' MasterUserPassword: !Sub '{{resolve:secretsmanager:${RedshiftSecret}::password}}' NodeType: ds2.xlarge AutomatedSnapshotRetentionPeriod: 7

CT.REDSHIFT.PR.2 rule specification

# ################################### ## Rule Specification ## ##################################### # # Rule Identifier: # redshift_backup_enabled_check # # Description: # This control checks whether Amazon Redshift clusters have automated snapshots enabled, and that the clusters are set with an automated snapshot retention period greater than or equal to seven (7) days. # # Reports on: # AWS::Redshift::Cluster # # Evaluates: # AWS CloudFormation, AWS CloudFormation hook # # Rule Parameters: # None # # Scenarios: # Scenario: 1 # Given: The input document is an AWS CloudFormation or AWS CloudFormation hook document # And: The input document does not contain any Redshift cluster resources # Then: SKIP # Scenario: 2 # Given: The input document is an AWS CloudFormation or AWS CloudFormation hook document # And: The input document contains a Redshift cluster resource # And: 'AutomatedSnapshotRetentionPeriod' has not been specified # Then: FAIL # Scenario: 3 # Given: The input document is an AWS CloudFormation or AWS CloudFormation hook document # And: The input document contains a Redshift cluster resource # And: 'AutomatedSnapshotRetentionPeriod' has been specified # And: 'AutomatedSnapshotRetentionPeriod' has been set to '0' # Then: FAIL # Scenario: 4 # Given: The input document is an AWS CloudFormation or AWS CloudFormation hook document # And: The input document contains a Redshift cluster resource # And: 'AutomatedSnapshotRetentionPeriod' has been specified # And: 'AutomatedSnapshotRetentionPeriod' has been set to a value <7 # Then: FAIL # Scenario: 5 # Given: The input document is an AWS CloudFormation or AWS CloudFormation hook document # And: The input document contains a Redshift cluster resource # And: 'AutomatedSnapshotRetentionPeriod' has been specified # And: 'AutomatedSnapshotRetentionPeriod' has been set to a value >= 7 # Then: PASS # # Constants # let REDSHIFT_CLUSTER_TYPE = "AWS::Redshift::Cluster" let INPUT_DOCUMENT = this # # Assignments # let redshift_clusters = Resources.*[ Type == %REDSHIFT_CLUSTER_TYPE ] # # Primary Rules # rule redshift_backup_enabled_check when is_cfn_template(%INPUT_DOCUMENT) %redshift_clusters not empty { check(%redshift_clusters.Properties) << [CT.REDSHIFT.PR.2]: Require an Amazon Redshift cluster to have automatic snapshots configured [FIX]: Set 'AutomatedSnapshotRetentionPeriod' to an integer value greater than or equal to 7 days. >> } rule redshift_backup_enabled_check when is_cfn_hook(%INPUT_DOCUMENT, %REDSHIFT_CLUSTER_TYPE) { check(%INPUT_DOCUMENT.%REDSHIFT_CLUSTER_TYPE.resourceProperties) << [CT.REDSHIFT.PR.2]: Require an Amazon Redshift cluster to have automatic snapshots configured [FIX]: Set 'AutomatedSnapshotRetentionPeriod' to an integer value greater than or equal to 7 days. >> } # # Parameterized Rules # rule check(redshift_cluster) { %redshift_cluster { # Scenario 2 AutomatedSnapshotRetentionPeriod exists # Scenario 3, 4 and 5 AutomatedSnapshotRetentionPeriod >= 7 } } # # Utility Rules # rule is_cfn_template(doc) { %doc { AWSTemplateFormatVersion exists or Resources exists } } rule is_cfn_hook(doc, RESOURCE_TYPE) { %doc.%RESOURCE_TYPE.resourceProperties exists }

CT.REDSHIFT.PR.2 example templates

You can view examples of the PASS and FAIL test artifacts for the AWS Control Tower proactive controls.

PASS Example - Use this template to verify a compliant resource creation.

Resources: RedshiftSecret: Type: AWS::SecretsManager::Secret Properties: Description: Redshift cluster secret GenerateSecretString: SecretStringTemplate: '{"username": "examplemasterusername"}' GenerateStringKey: password PasswordLength: 16 ExcludeCharacters: "'\"@/\\" RedshiftCluster: Type: AWS::Redshift::Cluster Properties: ClusterType: single-node DBName: exampledb MasterUsername: Fn::Sub: '{{resolve:secretsmanager:${RedshiftSecret}::username}}' MasterUserPassword: Fn::Sub: '{{resolve:secretsmanager:${RedshiftSecret}::password}}' NodeType: dc2.large PubliclyAccessible: false AutomatedSnapshotRetentionPeriod: 7

FAIL Example - Use this template to verify that the control prevents non-compliant resource creation.

Resources: RedshiftSecret: Type: AWS::SecretsManager::Secret Properties: Description: Redshift cluster secret GenerateSecretString: SecretStringTemplate: '{"username": "examplemasterusername"}' GenerateStringKey: password PasswordLength: 16 ExcludeCharacters: "'\"@/\\" RedshiftCluster: Type: AWS::Redshift::Cluster Properties: ClusterType: single-node DBName: exampledb MasterUsername: Fn::Sub: '{{resolve:secretsmanager:${RedshiftSecret}::username}}' MasterUserPassword: Fn::Sub: '{{resolve:secretsmanager:${RedshiftSecret}::password}}' NodeType: dc2.large PubliclyAccessible: false AutomatedSnapshotRetentionPeriod: 5

[CT.REDSHIFT.PR.3] Require an Amazon Redshift cluster to have audit logging configured

This control checks whether an Amazon Redshift cluster has audit logging activated.

  • Control objective: Establish logging and monitoring

  • Implementation: AWS CloudFormation Guard Rule

  • Control behavior: Proactive

  • Resource types: AWS::Redshift::Cluster

  • AWS CloudFormation guard rule: CT.REDSHIFT.PR.3 rule specification

Details and examples

Explanation

Amazon Redshift audit logging provides additional information about connections and user activities in your cluster. This data can be stored and secured in Amazon S3, and it can be helpful for security audits and investigations.

Remediation for rule failure

Provide a LoggingProperties configuration and set BucketName to the name of an Amazon S3 bucket configured to receive Amazon Redshift audit logs.

The examples that follow show how to implement this remediation.

Amazon Redshift Cluster - Example

Amazon Redshift cluster configured with audit logging enabled. The example is shown in JSON and in YAML.

JSON example

{ "RedshiftCluster": { "Type": "AWS::Redshift::Cluster", "Properties": { "ClusterType": "single-node", "DBName": "sampledb", "MasterUsername": { "Fn::Sub": "{{resolve:secretsmanager:${RedshiftSecret}::username}}" }, "MasterUserPassword": { "Fn::Sub": "{{resolve:secretsmanager:${RedshiftSecret}::password}}" }, "NodeType": "dc2.large", "PubliclyAccessible": false, "LoggingProperties": { "BucketName": { "Ref": "S3Bucket" }, "S3KeyPrefix": "sample-cluster-logs" } } } }

YAML example

RedshiftCluster: Type: AWS::Redshift::Cluster Properties: ClusterType: single-node DBName: sampledb MasterUsername: !Sub '{{resolve:secretsmanager:${RedshiftSecret}::username}}' MasterUserPassword: !Sub '{{resolve:secretsmanager:${RedshiftSecret}::password}}' NodeType: dc2.large PubliclyAccessible: false LoggingProperties: BucketName: !Ref 'S3Bucket' S3KeyPrefix: sample-cluster-logs

CT.REDSHIFT.PR.3 rule specification

# ################################### ## Rule Specification ## ##################################### # # Rule Identifier: # redshift_cluster_audit_logging_enabled_check # # Description: # This control checks whether an Amazon Redshift cluster has audit logging activated. # # Reports on: # AWS::Redshift::Cluster # # Evaluates: # AWS CloudFormation, AWS CloudFormation hook # # Rule Parameters: # None # # Scenarios: # Scenario: 1 # Given: The input document is an AWS CloudFormation or AWS CloudFormation hook document # And: The input document does not contain any Redshift cluster resources # Then: SKIP # Scenario: 2 # Given: The input document is an AWS CloudFormation or AWS CloudFormation hook document # And: The input document contains a Redshift cluster resource # And: 'LoggingProperties' has not been specified # Then: FAIL # Scenario: 3 # Given: The input document is an AWS CloudFormation or AWS CloudFormation hook document # And: The input document contains a Redshift cluster resource # And: 'LoggingProperties' has been specified # And: 'BucketName' on 'LoggingProperties' has been specified and is an empty string or invalid local reference # Then: FAIL # Scenario: 4 # Given: The input document is an AWS CloudFormation or AWS CloudFormation hook document # And: The input document contains a Redshift cluster resource # And: 'LoggingProperties' has been specified # And: 'BucketName' on 'LoggingProperties' has been specified and is a non-empty string or valid local reference # Then: PASS # # Constants # let REDSHIFT_CLUSTER_TYPE = "AWS::Redshift::Cluster" let INPUT_DOCUMENT = this # # Assignments # let redshift_clusters = Resources.*[ Type == %REDSHIFT_CLUSTER_TYPE ] # # Primary Rules # rule redshift_cluster_audit_logging_enabled_check when is_cfn_template(%INPUT_DOCUMENT) %redshift_clusters not empty { check(%redshift_clusters.Properties) << [CT.REDSHIFT.PR.3]: Require an Amazon Redshift cluster to have audit logging configured [FIX]: Provide a 'LoggingProperties' configuration and set 'BucketName' to the name of an Amazon S3 bucket configured to receive Amazon Redshift audit logs. >> } rule redshift_cluster_audit_logging_enabled_check when is_cfn_hook(%INPUT_DOCUMENT, %REDSHIFT_CLUSTER_TYPE) { check(%INPUT_DOCUMENT.%REDSHIFT_CLUSTER_TYPE.resourceProperties) << [CT.REDSHIFT.PR.3]: Require an Amazon Redshift cluster to have audit logging configured [FIX]: Provide a 'LoggingProperties' configuration and set 'BucketName' to the name of an Amazon S3 bucket configured to receive Amazon Redshift audit logs. >> } # # Parameterized Rules # rule check(redshift_cluster) { %redshift_cluster { # Scenario 2 LoggingProperties exists LoggingProperties is_struct LoggingProperties { # Scenario 3 and 4 BucketName exists check_is_string_and_not_empty(BucketName) or check_local_references(%INPUT_DOCUMENT, BucketName, "AWS::S3::Bucket") } } } # # Utility Rules # rule is_cfn_template(doc) { %doc { AWSTemplateFormatVersion exists or Resources exists } } rule is_cfn_hook(doc, RESOURCE_TYPE) { %doc.%RESOURCE_TYPE.resourceProperties exists } rule check_is_string_and_not_empty(value) { %value { this is_string this != /\A\s*\z/ } } rule check_local_references(doc, reference_properties, referenced_resource_type) { %reference_properties { 'Fn::GetAtt' { query_for_resource(%doc, this[0], %referenced_resource_type) <<Local Stack reference was invalid>> } or Ref { query_for_resource(%doc, this, %referenced_resource_type) <<Local Stack reference was invalid>> } } } rule query_for_resource(doc, resource_key, referenced_resource_type) { let referenced_resource = %doc.Resources[ keys == %resource_key ] %referenced_resource not empty %referenced_resource { Type == %referenced_resource_type } }

CT.REDSHIFT.PR.3 example templates

You can view examples of the PASS and FAIL test artifacts for the AWS Control Tower proactive controls.

PASS Example - Use this template to verify a compliant resource creation.

Resources: S3Bucket: Type: AWS::S3::Bucket BucketPolicy: Type: AWS::S3::BucketPolicy Properties: Bucket: Ref: S3Bucket PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: Service: redshift.amazonaws.com Action: - s3:GetBucketAcl Resource: - Fn::GetAtt: - S3Bucket - Arn - Effect: Allow Principal: Service: redshift.amazonaws.com Action: - s3:PutObject Resource: - Fn::Join: - '' - - Fn::GetAtt: - S3Bucket - Arn - /* RedshiftSecret: Type: AWS::SecretsManager::Secret Properties: Description: Redshift cluster secret GenerateSecretString: SecretStringTemplate: '{"username": "examplemasterusername"}' GenerateStringKey: password PasswordLength: 16 ExcludeCharacters: "'\"@/\\" RedshiftCluster: Type: AWS::Redshift::Cluster Properties: ClusterType: single-node DBName: exampledb MasterUsername: Fn::Sub: '{{resolve:secretsmanager:${RedshiftSecret}::username}}' MasterUserPassword: Fn::Sub: '{{resolve:secretsmanager:${RedshiftSecret}::password}}' NodeType: dc2.large PubliclyAccessible: false LoggingProperties: BucketName: Ref: S3Bucket S3KeyPrefix: example-cluster-logs

FAIL Example - Use this template to verify that the control prevents non-compliant resource creation.

Resources: RedshiftSecret: Type: AWS::SecretsManager::Secret Properties: Description: Redshift cluster secret GenerateSecretString: SecretStringTemplate: '{"username": "examplemasterusername"}' GenerateStringKey: password PasswordLength: 16 ExcludeCharacters: "'\"@/\\" RedshiftCluster: Type: AWS::Redshift::Cluster Properties: ClusterType: single-node DBName: exampledb MasterUsername: Fn::Sub: '{{resolve:secretsmanager:${RedshiftSecret}::username}}' MasterUserPassword: Fn::Sub: '{{resolve:secretsmanager:${RedshiftSecret}::password}}' NodeType: dc2.large PubliclyAccessible: false

[CT.REDSHIFT.PR.4] Require an Amazon Redshift cluster to have automatic upgrades to major versions configured

This control checks whether automatic major version upgrades are enabled for your Amazon Redshift cluster.

  • Control objective: Manage vulnerabilities

  • Implementation: AWS CloudFormation Guard Rule

  • Control behavior: Proactive

  • Resource types: AWS::Redshift::Cluster

  • AWS CloudFormation guard rule: CT.REDSHIFT.PR.4 rule specification

Details and examples

Explanation

Enabling automatic major version upgrades ensures that the latest major version updates to Amazon Redshift clusters are installed during the maintenance window. These updates might include security patches and bug fixes. Keeping up to date with patch installation is an important step in securing systems.

Remediation for rule failure

Set the AllowVersionUpgrade property to true or do not specify it (default).

The examples that follow show how to implement this remediation.

Amazon Redshift Cluster - Example One

Amazon Redshift cluster with automatic major version upgrades enabled through AWS CloudFormation defaults. The example is shown in JSON and in YAML.

JSON example

{ "RedshiftCluster": { "Type": "AWS::Redshift::Cluster", "Properties": { "ClusterType": "single-node", "DBName": "exampledb", "MasterUsername": { "Fn::Sub": "{{resolve:secretsmanager:${RedshiftSecret}::username}}" }, "MasterUserPassword": { "Fn::Sub": "{{resolve:secretsmanager:${RedshiftSecret}::password}}" }, "NodeType": "ds2.xlarge" } } }

YAML example

RedshiftCluster: Type: AWS::Redshift::Cluster Properties: ClusterType: single-node DBName: exampledb MasterUsername: !Sub '{{resolve:secretsmanager:${RedshiftSecret}::username}}' MasterUserPassword: !Sub '{{resolve:secretsmanager:${RedshiftSecret}::password}}' NodeType: ds2.xlarge

The examples that follow show how to implement this remediation.

Amazon Redshift Cluster - Example Two

Amazon Redshift cluster configured with automatic major version upgrades enabled through the AllowVersionUpgrade property. The example is shown in JSON and in YAML.

JSON example

{ "RedshiftCluster": { "Type": "AWS::Redshift::Cluster", "Properties": { "ClusterType": "single-node", "DBName": "exampledb", "MasterUsername": { "Fn::Sub": "{{resolve:secretsmanager:${RedshiftSecret}::username}}" }, "MasterUserPassword": { "Fn::Sub": "{{resolve:secretsmanager:${RedshiftSecret}::password}}" }, "NodeType": "ds2.xlarge", "AllowVersionUpgrade": true } } }

YAML example

RedshiftCluster: Type: AWS::Redshift::Cluster Properties: ClusterType: single-node DBName: exampledb MasterUsername: !Sub '{{resolve:secretsmanager:${RedshiftSecret}::username}}' MasterUserPassword: !Sub '{{resolve:secretsmanager:${RedshiftSecret}::password}}' NodeType: ds2.xlarge AllowVersionUpgrade: true

CT.REDSHIFT.PR.4 rule specification

# ################################### ## Rule Specification ## ##################################### # # Rule Identifier: # redshift_cluster_allow_version_upgrade_check # # Description: # Checks whether automatic major version upgrades are enabled for the Amazon Redshift cluster. # # Reports on: # AWS::Redshift::Cluster # # Evaluates: # AWS CloudFormation, AWS CloudFormation hook # # Rule Parameters: # None # # Scenarios: # Scenario: 1 # Given: The input document is an AWS CloudFormation or CloudFormation hook document # And: The input document does not contain any Redshift cluster resources # Then: SKIP # Scenario: 2 # Given: The input document is an AWS CloudFormation or CloudFormation hook document # And: The input document contains a Redshift cluster resource # And: 'AllowVersionUpgrade' has been provided # And: 'AllowVersionUpgrade' has been set to bool(false) # Then: FAIL # Scenario: 3 # Given: The input document is an AWS CloudFormation or CloudFormation hook document # And: The input document contains a Redshift cluster resource # And: 'AllowVersionUpgrade' has not been provided # Then: PASS # Scenario: 4 # Given: The input document is an AWS CloudFormation or CloudFormation hook document # And: The input document contains a Redshift cluster resource # And: 'AllowVersionUpgrade' has been provided # And: 'AllowVersionUpgrade' has been set to bool(true) # Then: PASS # # Constants # let REDSHIFT_CLUSTER_TYPE = "AWS::Redshift::Cluster" let INPUT_DOCUMENT = this # # Assignments # let redshift_clusters = Resources.*[ Type == %REDSHIFT_CLUSTER_TYPE ] # # Primary Rules # rule redshift_cluster_allow_version_upgrade_check when is_cfn_template(%INPUT_DOCUMENT) %redshift_clusters not empty { check(%redshift_clusters.Properties) << [CT.REDSHIFT.PR.4]: Require an Amazon Redshift cluster to have automatic upgrades to major versions configured [FIX]: Set the 'AllowVersionUpgrade' property to true or do not specify it (default). >> } rule redshift_cluster_allow_version_upgrade_check when is_cfn_hook(%INPUT_DOCUMENT, %REDSHIFT_CLUSTER_TYPE) { check(%INPUT_DOCUMENT.%REDSHIFT_CLUSTER_TYPE.resourceProperties) << [CT.REDSHIFT.PR.4]: Require an Amazon Redshift cluster to have automatic upgrades to major versions configured [FIX]: Set the 'AllowVersionUpgrade' property to true or do not specify it (default). >> } # # Parameterized Rules # rule check(redshift_cluster) { %redshift_cluster { # Scenario 3 AllowVersionUpgrade not exists or # Scenario 2 and 4 AllowVersionUpgrade == true } } # # Utility Rules # rule is_cfn_template(doc) { %doc { AWSTemplateFormatVersion exists or Resources exists } } rule is_cfn_hook(doc, RESOURCE_TYPE) { %doc.%RESOURCE_TYPE.resourceProperties exists }

CT.REDSHIFT.PR.4 example templates

You can view examples of the PASS and FAIL test artifacts for the AWS Control Tower proactive controls.

PASS Example - Use this template to verify a compliant resource creation.

Resources: RedshiftSecret: Type: AWS::SecretsManager::Secret Properties: Description: Redshift cluster secret GenerateSecretString: SecretStringTemplate: '{"username": "examplemasterusername"}' GenerateStringKey: password PasswordLength: 16 ExcludeCharacters: "'\"@/\\" RedshiftCluster: Type: AWS::Redshift::Cluster Properties: ClusterType: single-node DBName: exampledb MasterUsername: Fn::Sub: '{{resolve:secretsmanager:${RedshiftSecret}::username}}' MasterUserPassword: Fn::Sub: '{{resolve:secretsmanager:${RedshiftSecret}::password}}' NodeType: dc2.large PubliclyAccessible: false

FAIL Example - Use this template to verify that the control prevents non-compliant resource creation.

Resources: RedshiftSecret: Type: AWS::SecretsManager::Secret Properties: Description: Redshift cluster secret GenerateSecretString: SecretStringTemplate: '{"username": "examplemasterusername"}' GenerateStringKey: password PasswordLength: 16 ExcludeCharacters: "'\"@/\\" RedshiftCluster: Type: AWS::Redshift::Cluster Properties: ClusterType: single-node DBName: exampledb MasterUsername: Fn::Sub: '{{resolve:secretsmanager:${RedshiftSecret}::username}}' MasterUserPassword: Fn::Sub: '{{resolve:secretsmanager:${RedshiftSecret}::password}}' NodeType: dc2.large PubliclyAccessible: false AllowVersionUpgrade: false

[CT.REDSHIFT.PR.5] Require an Amazon Redshift cluster to have enhanced VPC routing

This control checks whether an Amazon Redshift cluster has enhanced VPC routing configured.

  • Control objective: Limit network access

  • Implementation: AWS CloudFormation Guard Rule

  • Control behavior: Proactive

  • Resource types: AWS::Redshift::Cluster

  • AWS CloudFormation guard rule: CT.REDSHIFT.PR.5 rule specification

Details and examples

Explanation

Enhanced VPC routing forces all copy and unload traffic between the cluster and the data repositories to go through your VPC. With enhanced routing active, you can use VPC features, such as security groups and network access control lists, to secure network traffic. You can also use VPC Flow Logs to monitor network traffic.

Remediation for rule failure

Set EnhancedVpcRouting to true.

The examples that follow show how to implement this remediation.

Amazon Redshift Cluster - Example

Amazon Redshift cluster configured with enhanced VPC routing. The example is shown in JSON and in YAML.

JSON example

{ "RedshiftCluster": { "Type": "AWS::Redshift::Cluster", "Properties": { "ClusterType": "single-node", "DBName": "sampledb", "MasterUsername": { "Fn::Sub": "{{resolve:secretsmanager:${RedshiftSecret}::username}}" }, "MasterUserPassword": { "Fn::Sub": "{{resolve:secretsmanager:${RedshiftSecret}::password}}" }, "NodeType": "ds2.xlarge", "EnhancedVpcRouting": true } } }

YAML example

RedshiftCluster: Type: AWS::Redshift::Cluster Properties: ClusterType: single-node DBName: sampledb MasterUsername: !Sub '{{resolve:secretsmanager:${RedshiftSecret}::username}}' MasterUserPassword: !Sub '{{resolve:secretsmanager:${RedshiftSecret}::password}}' NodeType: ds2.xlarge EnhancedVpcRouting: true

CT.REDSHIFT.PR.5 rule specification

# ################################### ## Rule Specification ## ##################################### # # Rule Identifier: # redshift_enhanced_vpc_routing_enabled_check # # Description: # This control checks whether an Amazon Redshift cluster has enhanced VPC routing configured. # # Reports on: # AWS::Redshift::Cluster # # Evaluates: # AWS CloudFormation, AWS CloudFormation hook # # Rule Parameters: # None # # Scenarios: # Scenario: 1 # Given: The input document is an AWS CloudFormation or AWS CloudFormation hook document # And: The input document does not contain any Redshift cluster resources # Then: SKIP # Scenario: 2 # Given: The input document is an AWS CloudFormation or AWS CloudFormation hook document # And: The input document contains a Redshift cluster resource # And: 'EnhancedVpcRouting' has not been specified # Then: FAIL # Scenario: 3 # Given: The input document is an AWS CloudFormation or AWS CloudFormation hook document # And: The input document contains a Redshift cluster resource # And: 'EnhancedVpcRouting' has been specified # And: 'EnhancedVpcRouting' has been set to bool(false) # Then: FAIL # Scenario: 4 # Given: The input document is an AWS CloudFormation or AWS CloudFormation hook document # And: The input document contains a Redshift cluster resource # And: 'EnhancedVpcRouting' has been specified # And: 'EnhancedVpcRouting' has been set to bool(true) # Then: PASS # # Constants # let REDSHIFT_CLUSTER_TYPE = "AWS::Redshift::Cluster" let INPUT_DOCUMENT = this # # Assignments # let redshift_clusters = Resources.*[ Type == %REDSHIFT_CLUSTER_TYPE ] # # Primary Rules # rule redshift_enhanced_vpc_routing_enabled_check when is_cfn_template(%INPUT_DOCUMENT) %redshift_clusters not empty { check(%redshift_clusters.Properties) << [CT.REDSHIFT.PR.5]: Require an Amazon Redshift cluster to have enhanced VPC routing [FIX]: Set 'EnhancedVpcRouting' to 'true'. >> } rule redshift_enhanced_vpc_routing_enabled_check when is_cfn_hook(%INPUT_DOCUMENT, %REDSHIFT_CLUSTER_TYPE) { check(%INPUT_DOCUMENT.%REDSHIFT_CLUSTER_TYPE.resourceProperties) << [CT.REDSHIFT.PR.5]: Require an Amazon Redshift cluster to have enhanced VPC routing [FIX]: Set 'EnhancedVpcRouting' to 'true'. >> } # # Parameterized Rules # rule check(redshift_cluster) { %redshift_cluster { # Scenario 2 EnhancedVpcRouting exists # Scenario 3 and 4 EnhancedVpcRouting == true } } # # Utility Rules # rule is_cfn_template(doc) { %doc { AWSTemplateFormatVersion exists or Resources exists } } rule is_cfn_hook(doc, RESOURCE_TYPE) { %doc.%RESOURCE_TYPE.resourceProperties exists }

CT.REDSHIFT.PR.5 example templates

You can view examples of the PASS and FAIL test artifacts for the AWS Control Tower proactive controls.

PASS Example - Use this template to verify a compliant resource creation.

Resources: RedshiftSecret: Type: AWS::SecretsManager::Secret Properties: Description: Redshift cluster secret GenerateSecretString: SecretStringTemplate: '{"username": "examplemasterusername"}' GenerateStringKey: password PasswordLength: 16 ExcludeCharacters: "\"@/\\" RedshiftCluster: Type: AWS::Redshift::Cluster Properties: ClusterType: single-node DBName: exampledb MasterUsername: Fn::Sub: '{{resolve:secretsmanager:${RedshiftSecret}::username}}' MasterUserPassword: Fn::Sub: '{{resolve:secretsmanager:${RedshiftSecret}::password}}' NodeType: dc2.large PubliclyAccessible: false EnhancedVpcRouting: true

FAIL Example - Use this template to verify that the control prevents non-compliant resource creation.

Resources: RedshiftSecret: Type: AWS::SecretsManager::Secret Properties: Description: Redshift cluster secret GenerateSecretString: SecretStringTemplate: '{"username": "examplemasterusername"}' GenerateStringKey: password PasswordLength: 16 ExcludeCharacters: "\"@/\\" RedshiftCluster: Type: AWS::Redshift::Cluster Properties: ClusterType: single-node DBName: exampledb MasterUsername: Fn::Sub: '{{resolve:secretsmanager:${RedshiftSecret}::username}}' MasterUserPassword: Fn::Sub: '{{resolve:secretsmanager:${RedshiftSecret}::password}}' NodeType: dc2.large PubliclyAccessible: false EnhancedVpcRouting: false

[CT.REDSHIFT.PR.6] Require an Amazon Redshift cluster to have a unique administrator username

This control checks whether an Amazon Redshift cluster has changed the administrator username from its default value.

  • Control objective: Protect configurations

  • Implementation: AWS CloudFormation Guard Rule

  • Control behavior: Proactive

  • Resource types: AWS::Redshift::Cluster

  • AWS CloudFormation guard rule: CT.REDSHIFT.PR.6 rule specification

Details and examples

Explanation

When creating an Amazon Redshift cluster, you should change the default administrator username to a unique value. Default usernames are public knowledge, so they should be changed upon configuration. Changing the default username reduces the risk of unintended access.

Remediation for rule failure

Set MasterUsername to a value other than awsuser.

The examples that follow show how to implement this remediation.

Amazon Redshift Cluster - Example

Amazon Redshift cluster configured with an administrator username different from the default value of awsuser. The example is shown in JSON and in YAML.

JSON example

{ "RedshiftCluster": { "Type": "AWS::Redshift::Cluster", "Properties": { "ClusterType": "single-node", "DBName": "sampledb", "MasterUsername": "samplemasterusername", "MasterUserPassword": { "Fn::Sub": "{{resolve:secretsmanager:${RedshiftClusterSecret}::password}}" }, "NodeType": "ds2.xlarge" } } }

YAML example

RedshiftCluster: Type: AWS::Redshift::Cluster Properties: ClusterType: single-node DBName: sampledb MasterUsername: samplemasterusername MasterUserPassword: !Sub '{{resolve:secretsmanager:${RedshiftClusterSecret}::password}}' NodeType: ds2.xlarge

CT.REDSHIFT.PR.6 rule specification

# ################################### ## Rule Specification ## ##################################### # # Rule Identifier: # redshift_default_admin_check # # Description: # This control checks whether an Amazon Redshift cluster has changed the administrator username from its default value. # # Reports on: # AWS::Redshift::Cluster # # Evaluates: # AWS CloudFormation, AWS CloudFormation hook # # Rule Parameters: # None # # Scenarios: # Scenario: 1 # Given: The input document is an AWS CloudFormation or AWS CloudFormation hook document # And: The input document does not contain any Redshift cluster resources # Then: SKIP # Scenario: 2 # Given: The input document is an AWS CloudFormation or AWS CloudFormation hook document # And: The input document contains a Redshift cluster resource # And: 'MasterUsername' has not been specified # Then: FAIL # Scenario: 3 # Given: The input document is an AWS CloudFormation or AWS CloudFormation hook document # And: The input document contains a Redshift cluster resource # And: 'MasterUsername' has been specified # And: 'MasterUsername' has been set to 'awsuser' # Then: FAIL # Scenario: 4 # Given: The input document is an AWS CloudFormation or AWS CloudFormation hook document # And: The input document contains a Redshift cluster resource # And: 'MasterUsername' has been specified # And: 'MasterUsername' has been set to a value not equal to 'awsuser' # Then: PASS # # Constants # let REDSHIFT_CLUSTER_TYPE = "AWS::Redshift::Cluster" let INPUT_DOCUMENT = this # # Assignments # let redshift_clusters = Resources.*[ Type == %REDSHIFT_CLUSTER_TYPE ] # # Primary Rules # rule redshift_default_admin_check when is_cfn_template(%INPUT_DOCUMENT) %redshift_clusters not empty { check(%redshift_clusters.Properties) << [CT.REDSHIFT.PR.6]: Require an Amazon Redshift cluster to have a unique administrator username [FIX]: Set 'MasterUsername' to a value other than 'awsuser'. >> } rule redshift_default_admin_check when is_cfn_hook(%INPUT_DOCUMENT, %REDSHIFT_CLUSTER_TYPE) { check(%INPUT_DOCUMENT.%REDSHIFT_CLUSTER_TYPE.resourceProperties) << [CT.REDSHIFT.PR.6]: Require an Amazon Redshift cluster to have a unique administrator username [FIX]: Set 'MasterUsername' to a value other than 'awsuser'. >> } # # Parameterized Rules # rule check(redshift_cluster) { %redshift_cluster { # Scenario 2 MasterUsername exists check_is_string_and_not_empty(MasterUsername) # Scenario 3 and 4 MasterUsername != "awsuser" } } # # Utility Rules # rule check_is_string_and_not_empty(value) { %value { this is_string this != /\A\s*\z/ } } rule is_cfn_template(doc) { %doc { AWSTemplateFormatVersion exists or Resources exists } } rule is_cfn_hook(doc, RESOURCE_TYPE) { %doc.%RESOURCE_TYPE.resourceProperties exists }

CT.REDSHIFT.PR.6 example templates

You can view examples of the PASS and FAIL test artifacts for the AWS Control Tower proactive controls.

PASS Example - Use this template to verify a compliant resource creation.

Resources: RedshiftSecret: Type: AWS::SecretsManager::Secret Properties: Description: Redshift cluster secret GenerateSecretString: SecretStringTemplate: '{"username": "examplemasterusername"}' GenerateStringKey: password PasswordLength: 16 ExcludeCharacters: "'\"@/\\" RedshiftCluster: Type: AWS::Redshift::Cluster Properties: ClusterType: single-node DBName: exampledb MasterUsername: examplemasterusername MasterUserPassword: Fn::Sub: '{{resolve:secretsmanager:${RedshiftSecret}::password}}' NodeType: dc2.large PubliclyAccessible: false

FAIL Example - Use this template to verify that the control prevents non-compliant resource creation.

Resources: RedshiftSecret: Type: AWS::SecretsManager::Secret Properties: Description: Redshift cluster secret GenerateSecretString: SecretStringTemplate: '{"username": "awsuser"}' GenerateStringKey: password PasswordLength: 16 ExcludeCharacters: "'\"@/\\" RedshiftCluster: Type: AWS::Redshift::Cluster Properties: ClusterType: single-node DBName: exampledb MasterUsername: awsuser MasterUserPassword: Fn::Sub: '{{resolve:secretsmanager:${RedshiftSecret}::password}}' NodeType: dc2.large PubliclyAccessible: false

[CT.REDSHIFT.PR.7] Require an Amazon Redshift cluster to have a unique database name

This control checks whether an Amazon Redshift cluster has changed its database name from the default value.

  • Control objective: Protect configurations

  • Implementation: AWS CloudFormation Guard Rule

  • Control behavior: Proactive

  • Resource types: AWS::Redshift::Cluster

  • AWS CloudFormation guard rule: CT.REDSHIFT.PR.7 rule specification

Details and examples

Explanation

When creating a Redshift cluster, you should change the default database name to a unique value. Default names are public knowledge, so they should be changed upon configuration. For example, a well-known name can lead to inadvertent access, if included in IAM policy conditions.

Remediation for rule failure

Set DBName to a database name that is different from the default value of dev.

The examples that follow show how to implement this remediation.

Amazon Redshift Cluster - Example

Amazon Redshift cluster configured with a database name different from the default value of dev. The example is shown in JSON and in YAML.

JSON example

{ "RedshiftCluster": { "Type": "AWS::Redshift::Cluster", "Properties": { "ClusterType": "single-node", "DBName": "sampledb", "MasterUsername": { "Fn::Sub": "{{resolve:secretsmanager:${RedshiftClusterSecret}::username}}" }, "MasterUserPassword": { "Fn::Sub": "{{resolve:secretsmanager:${RedshiftClusterSecret}::password}}" }, "NodeType": "dc2.large", "PubliclyAccessible": false } } }

YAML example

RedshiftCluster: Type: AWS::Redshift::Cluster Properties: ClusterType: single-node DBName: sampledb MasterUsername: !Sub '{{resolve:secretsmanager:${RedshiftClusterSecret}::username}}' MasterUserPassword: !Sub '{{resolve:secretsmanager:${RedshiftClusterSecret}::password}}' NodeType: dc2.large PubliclyAccessible: false

CT.REDSHIFT.PR.7 rule specification

# ################################### ## Rule Specification ## ##################################### # # Rule Identifier: # redshift_default_db_name_check # # Description: # This control checks whether an Amazon Redshift cluster has changed its database name from the default value. # # Reports on: # AWS::Redshift::Cluster # # Evaluates: # AWS CloudFormation, AWS CloudFormation hook # # Rule Parameters: # None # # Scenarios: # Scenario: 1 # Given: The input document is an AWS CloudFormation or AWS CloudFormation hook document # And: The input document does not contain any Redshift cluster resources # Then: SKIP # Scenario: 2 # Given: The input document is an AWS CloudFormation or AWS CloudFormation hook document # And: The input document contains a Redshift cluster resource # And: The 'DBName' property has not been provided # Then: FAIL # Scenario: 3 # Given: The input document is an AWS CloudFormation or AWS CloudFormation hook document # And: The input document contains Redshift cluster resource # And: The 'DBName' property has been provided with a value of 'dev' or an empty string # Then: FAIL # Scenario: 4 # Given: The input document is an AWS CloudFormation or AWS CloudFormation hook document # And: The input document contains Redshift cluster resource # And: The 'DBName' property has been provided with a non-empty string that is not equal to 'dev' # Then: PASS # # Constants # let RESOURCE_TYPE = "AWS::Redshift::Cluster" let INPUT_DOCUMENT = this let INVALID_DB_NAME_STRING = "dev" # # Assignments # let redshift_clusters = Resources.*[ Type == %RESOURCE_TYPE ] # # Primary Rules # rule redshift_default_db_name_check when is_cfn_template(%INPUT_DOCUMENT) %redshift_clusters not empty { check_db_name(%redshift_clusters.Properties) << [CT.REDSHIFT.PR.7]: Require an Amazon Redshift cluster to have a unique database name [FIX]: Set 'DBName' to a database name that is different from the default value of 'dev'. >> } rule redshift_default_db_name_check when is_cfn_hook(%INPUT_DOCUMENT, %RESOURCE_TYPE) { check_db_name(%INPUT_DOCUMENT.%RESOURCE_TYPE.resourceProperties) << [CT.REDSHIFT.PR.7]: Require an Amazon Redshift cluster to have a unique database name [FIX]: Set 'DBName' to a database name that is different from the default value of 'dev'. >> } # # Parameterized Rules # rule check_db_name(redshift_cluster) { %redshift_cluster { # Scenario 2 DBName exists # Scenario 3 and 4 check_is_string_and_not_empty(DBName) DBName != %INVALID_DB_NAME_STRING } } # # Utility Rules # rule is_cfn_template(doc) { %doc { AWSTemplateFormatVersion exists or Resources exists } } rule is_cfn_hook(doc, RESOURCE_TYPE) { %doc.%RESOURCE_TYPE.resourceProperties exists } rule check_is_string_and_not_empty(value) { %value { this is_string this != /\A\s*\z/ } }

CT.REDSHIFT.PR.7 example templates

You can view examples of the PASS and FAIL test artifacts for the AWS Control Tower proactive controls.

PASS Example - Use this template to verify a compliant resource creation.

Resources: RedshiftSecret: Type: AWS::SecretsManager::Secret Properties: Description: Redshift cluster secret GenerateSecretString: SecretStringTemplate: '{"username": "examplemasterusername"}' GenerateStringKey: password PasswordLength: 16 ExcludeCharacters: "'\"@/\\" RedshiftCluster: Type: AWS::Redshift::Cluster Properties: ClusterType: "single-node" MasterUsername: Fn::Sub: '{{resolve:secretsmanager:${RedshiftSecret}::username}}' MasterUserPassword: Fn::Sub: '{{resolve:secretsmanager:${RedshiftSecret}::password}}' NodeType: dc2.large PubliclyAccessible: false DBName: exampledb

FAIL Example - Use this template to verify that the control prevents non-compliant resource creation.

Resources: RedshiftSecret: Type: AWS::SecretsManager::Secret Properties: Description: Redshift cluster secret GenerateSecretString: SecretStringTemplate: '{"username": "examplemasterusername"}' GenerateStringKey: password PasswordLength: 16 ExcludeCharacters: "'\"@/\\" RedshiftCluster: Type: AWS::Redshift::Cluster Properties: ClusterType: "single-node" MasterUsername: Fn::Sub: '{{resolve:secretsmanager:${RedshiftSecret}::username}}' MasterUserPassword: Fn::Sub: '{{resolve:secretsmanager:${RedshiftSecret}::password}}' NodeType: dc2.large PubliclyAccessible: false DBName: dev

[CT.REDSHIFT.PR.8] Require an Amazon Redshift cluster to be encrypted

This control checks whether an Amazon Redshift cluster is encrypted.

  • Control objective: Encrypt data at rest

  • Implementation: AWS CloudFormation guard rule

  • Control behavior: Proactive

  • Resource types: AWS::Redshift::Cluster

  • AWS CloudFormation guard rule: CT.REDSHIFT.PR.8 rule specification

Details and examples

Explanation

In Amazon Redshift, you can enable database encryption for your clusters, which helps protect data at rest. When you enable encryption for a cluster, the data blocks and system metadata are encrypted for the cluster and its snapshots.

Remediation for rule failure

Set the value of the Encrypted property to true.

The examples that follow show how to implement this remediation.

Amazon Redshift Cluster - Example

An Amazon Redshift cluster configured with encryption enabled. The example is shown in JSON and in YAML.

JSON example

{ "RedshiftCluster": { "Type": "AWS::Redshift::Cluster", "Properties": { "ClusterType": "single-node", "DBName": "sampledb", "MasterUsername": { "Fn::Sub": "{{resolve:secretsmanager:${RedshiftSecret}::username}}" }, "MasterUserPassword": { "Fn::Sub": "{{resolve:secretsmanager:${RedshiftSecret}::password}}" }, "NodeType": "dc2.large", "PubliclyAccessible": false, "Encrypted": true } } }

YAML example

RedshiftCluster: Type: AWS::Redshift::Cluster Properties: ClusterType: single-node DBName: sampledb MasterUsername: !Sub '{{resolve:secretsmanager:${RedshiftSecret}::username}}' MasterUserPassword: !Sub '{{resolve:secretsmanager:${RedshiftSecret}::password}}' NodeType: dc2.large PubliclyAccessible: false Encrypted: true

CT.REDSHIFT.PR.8 rule specification

# ################################### ## Rule Specification ## ##################################### # # Rule Identifier: # redshift_cluster_encrypted_check # # Description: # This control checks whether an Amazon Redshift cluster is encrypted. # # Reports on: # AWS::Redshift::Cluster # # Evaluates: # AWS CloudFormation, AWS CloudFormation hook # # Rule Parameters: # None # # Scenarios: # Scenario: 1 # Given: The input document is an AWS CloudFormation or AWS CloudFormation hook document # And: The input document does not contain any Amazon Redshift cluster resources # Then: SKIP # Scenario: 2 # Given: The input document is an AWS CloudFormation or AWS CloudFormation hook document # And: The input document contains an Amazon Redshift cluster resource # And: 'Encrypted' has not been provided # Then: FAIL # Scenario: 3 # Given: The input document is an AWS CloudFormation or AWS CloudFormation hook document # And: The input document contains an Amazon Redshift cluster resource # And: 'Encrypted' has been provided and set to a value other than bool(true) # Then: FAIL # Scenario: 4 # Given: The input document is an AWS CloudFormation or AWS CloudFormation hook document # And: The input document contains an Amazon Redshift cluster resource # And: 'Encrypted' has been provided and set to bool(true) # Then: PASS # # Constants # let RESOURCE_TYPE = "AWS::Redshift::Cluster" let INPUT_DOCUMENT = this # # Assignments # let redshift_clusters = Resources.*[ Type == %RESOURCE_TYPE ] # # Primary Rules # rule redshift_cluster_encrypted_check when is_cfn_template(%INPUT_DOCUMENT) %redshift_clusters not empty { check(%redshift_clusters.Properties) << [CT.REDSHIFT.PR.8]: Require an Amazon Redshift cluster to be encrypted [FIX]: Set the value of the 'Encrypted' property to true. >> } rule redshift_cluster_encrypted_check when is_cfn_hook(%INPUT_DOCUMENT, %RESOURCE_TYPE) { check(%INPUT_DOCUMENT.%RESOURCE_TYPE.resourceProperties) << [CT.REDSHIFT.PR.8]: Require an Amazon Redshift cluster to be encrypted [FIX]: Set the value of the 'Encrypted' property to true. >> } # # Parameterized Rules # rule check(redshift_cluster) { %redshift_cluster { # Scenario 2 Encrypted exists # Scenario 3 and 4 Encrypted == true } } # # Utility Rules # rule is_cfn_template(doc) { %doc { AWSTemplateFormatVersion exists or Resources exists } } rule is_cfn_hook(doc, RESOURCE_TYPE) { %doc.%RESOURCE_TYPE.resourceProperties exists }

CT.REDSHIFT.PR.8 example templates

You can view examples of the PASS and FAIL test artifacts for the AWS Control Tower proactive controls.

PASS Example - Use this template to verify a compliant resource creation.

Resources: RedshiftSecret: Type: AWS::SecretsManager::Secret Properties: Description: Redshift cluster secret GenerateSecretString: SecretStringTemplate: '{"username": "examplemasterusername"}' GenerateStringKey: password PasswordLength: 16 ExcludeCharacters: "'\"@/\\" RedshiftCluster: Type: AWS::Redshift::Cluster Properties: ClusterType: single-node MasterUsername: Fn::Sub: '{{resolve:secretsmanager:${RedshiftSecret}::username}}' MasterUserPassword: Fn::Sub: '{{resolve:secretsmanager:${RedshiftSecret}::password}}' NodeType: dc2.large PubliclyAccessible: false DBName: exampledb Encrypted: true

FAIL Example - Use this template to verify that the control prevents non-compliant resource creation.

Resources: RedshiftSecret: Type: AWS::SecretsManager::Secret Properties: Description: Redshift cluster secret GenerateSecretString: SecretStringTemplate: '{"username": "examplemasterusername"}' GenerateStringKey: password PasswordLength: 16 ExcludeCharacters: "'\"@/\\" RedshiftCluster: Type: AWS::Redshift::Cluster Properties: ClusterType: single-node MasterUsername: Fn::Sub: '{{resolve:secretsmanager:${RedshiftSecret}::username}}' MasterUserPassword: Fn::Sub: '{{resolve:secretsmanager:${RedshiftSecret}::password}}' NodeType: dc2.large PubliclyAccessible: false DBName: exampledb Encrypted: false

[CT.REDSHIFT.PR.9] Require that an Amazon Redshift cluster parameter group is configured to use Secure Sockets Layer (SSL) for encryption of data in transit

This control checks whether an Amazon Redshift cluster parameter group is configured to require encryption by means of Secure Sockets Layer (SSL), for data in transit.

  • Control objective: Encrypt data in transit

  • Implementation: AWS CloudFormation guard rule

  • Control behavior: Proactive

  • Resource types: AWS::Redshift::ClusterParameterGroup

  • AWS CloudFormation guard rule: CT.REDSHIFT.PR.9 rule specification

Details and examples

Explanation

In Amazon Redshift, you can enable encryption of data in transit between an Amazon Redshift cluster and SQL clients over JDBC/ODBC. To support SSL connections, Amazon Redshift creates and installs certificates on each cluster, which are issued by AWS Certificate Manager (ACM).

Remediation for rule failure

Set an entry in Parameters with a ParameterName of require_ssl and a ParameterValue of true.

The examples that follow show how to implement this remediation.

Amazon Redshift cluster parameter group - Example

An Amazon Redshift cluster parameter group, configured to require encryption of data in transit. The example is shown in JSON and in YAML.

JSON example

{ "ClusterParameterGroup": { "Type": "AWS::Redshift::ClusterParameterGroup", "Properties": { "Description": "Example parameter group", "ParameterGroupFamily": "redshift-1.0", "Parameters": [ { "ParameterName": "require_ssl", "ParameterValue": true } ] } } }

YAML example

ClusterParameterGroup: Type: AWS::Redshift::ClusterParameterGroup Properties: Description: Example parameter group ParameterGroupFamily: redshift-1.0 Parameters: - ParameterName: require_ssl ParameterValue: true

CT.REDSHIFT.PR.9 rule specification

# ################################### ## Rule Specification ## ##################################### # # Rule Identifier: # redshift_parameter_group_require_tls_ssl_check # # Description: # This control checks whether an Amazon Redshift cluster parameter group is configured to require encryption by means of Secure Sockets Layer (SSL), for data in transit. # # Reports on: # AWS::Redshift::ClusterParameterGroup # # Evaluates: # AWS CloudFormation, AWS CloudFormation hook # # Rule Parameters: # None # # Scenarios: # Scenario: 1 # Given: The input document is an AWS CloudFormation or AWS CloudFormation hook document # And: The input document does not contain any Amazon Redshift cluster parameter group resources # Then: SKIP # Scenario: 2 # Given: The input document is an AWS CloudFormation or AWS CloudFormation hook document # And: The input document contains an Amazon Redshift cluster parameter group resource # And: 'Parameters' has not been provided or has been provided as an empty list # Then: FAIL # Scenario: 3 # Given: The input document is an AWS CloudFormation or AWS CloudFormation hook document # And: The input document contains an Amazon Redshift cluster parameter group resource # And: 'Parameters' has been provided as a non-empty list that does not contain an entry with # 'ParameterName' set to 'require_ssl' and 'ParameterValue' set to bool(true) or a supported # boolean string value ('true', 'True', 'TRUE', 'on', 'On' or 'ON') # Then: FAIL # Scenario: 4 # Given: The input document is an AWS CloudFormation or AWS CloudFormation hook document # And: The input document contains an Amazon Redshift cluster parameter group resource # And: Any entry in 'Parameters' with a 'ParameterName' is set to 'require_ssl' has a corresponding # 'ParameterValue' set to a value other than bool(true) or a supported # boolean string value ('true', 'True', 'TRUE', 'on', 'On' or 'ON') # Then: FAIL # Scenario: 5 # Given: The input document is an AWS CloudFormation or AWS CloudFormation hook document # And: The input document contains an Amazon Redshift cluster parameter group resource # And: 'Parameters' has been provided as a non-empty list # And: 'Parameters' contains an entry with 'ParameterName' set to 'require_ssl' and 'ParameterValue' # set to bool(true) or a supported boolean string value ('true', 'True', 'TRUE', 'on', 'On' or 'ON') # And: All entries in 'Parameters' with a 'ParameterName' set to 'require_ssl' have a corresponding # 'ParameterValue' set to bool(true) or a supported boolean string # value ('true', 'True', 'TRUE', 'on', 'On' or 'ON') # Then: PASS # # Constants # let REDSHIFT_CLUSTER_PARAMETER_GROUP_TYPE = "AWS::Redshift::ClusterParameterGroup" let REDSHIFT_SUPPORTED_TRUE_VALUES = [ true, /^(true|True|TRUE|on|On|ON)$/ ] let INPUT_DOCUMENT = this # # Assignments # let redshift_cluster_parameter_groups = Resources.*[ Type == %REDSHIFT_CLUSTER_PARAMETER_GROUP_TYPE ] # # Primary Rules # rule redshift_parameter_group_require_tls_ssl_check when is_cfn_template(%INPUT_DOCUMENT) %redshift_cluster_parameter_groups not empty { check(%redshift_cluster_parameter_groups.Properties) << [CT.REDSHIFT.PR.9]: Require that an Amazon Redshift cluster parameter group is configured to use Secure Sockets Layer (SSL) for encryption of data in transit [FIX]: Set an entry in 'Parameters' with a 'ParameterName' of 'require_ssl' and a 'ParameterValue' of true. >> } rule redshift_parameter_group_require_tls_ssl_check when is_cfn_hook(%INPUT_DOCUMENT, %REDSHIFT_CLUSTER_PARAMETER_GROUP_TYPE) { check(%INPUT_DOCUMENT.%REDSHIFT_CLUSTER_PARAMETER_GROUP_TYPE.resourceProperties) << [CT.REDSHIFT.PR.9]: Require that an Amazon Redshift cluster parameter group is configured to use Secure Sockets Layer (SSL) for encryption of data in transit [FIX]: Set an entry in 'Parameters' with a 'ParameterName' of 'require_ssl' and a 'ParameterValue' of true. >> } # # Parameterized Rules # rule check(redshift_cluster_parameter_groups) { %redshift_cluster_parameter_groups { # Scenario 2 Parameters exists Parameters is_list Parameters not empty # Scenarios 3, 4 and 5 some Parameters[*] { ParameterName exists ParameterValue exists ParameterName == "require_ssl" ParameterValue in %REDSHIFT_SUPPORTED_TRUE_VALUES } Parameters [ ParameterName exists ParameterName == "require_ssl" ] { ParameterValue exists ParameterValue in %REDSHIFT_SUPPORTED_TRUE_VALUES } } } # # Utility Rules # rule is_cfn_template(doc) { %doc { AWSTemplateFormatVersion exists or Resources exists } } rule is_cfn_hook(doc, RESOURCE_TYPE) { %doc.%RESOURCE_TYPE.resourceProperties exists }

CT.REDSHIFT.PR.9 example templates

You can view examples of the PASS and FAIL test artifacts for the AWS Control Tower proactive controls.

PASS Example - Use this template to verify a compliant resource creation.

Resources: ClusterParameterGroup: Type: AWS::Redshift::ClusterParameterGroup Properties: Description: Example parameter group ParameterGroupFamily: redshift-1.0 Parameters: - ParameterName: require_ssl ParameterValue: true

FAIL Example - Use this template to verify that the control prevents non-compliant resource creation.

Resources: ClusterParameterGroup: Type: AWS::Redshift::ClusterParameterGroup Properties: Description: Example parameter group ParameterGroupFamily: redshift-1.0