Repository: bridgecrewio/checkov

Issue:
Add new checks: redshift encryption at rest
Encryption of data at rest(encrypted = true)
https://www.terraform.io/docs/providers/aws/d/redshift_cluster.html#encrypted


Discussion:

Resolving patch:
diff --git a/checkov/cloudformation/checks/resource/aws/RedshiftClusterEncryption.py b/checkov/cloudformation/checks/resource/aws/RedshiftClusterEncryption.py
new file mode 100644
--- /dev/null
+++ b/checkov/cloudformation/checks/resource/aws/RedshiftClusterEncryption.py
@@ -0,0 +1,26 @@
+from checkov.common.models.enums import CheckResult, CheckCategories
+from checkov.cloudformation.checks.resource.base_resource_check import BaseResourceCheck
+
+
+class RedshiftClusterEncryption(BaseResourceCheck):
+    def __init__(self):
+        name = "Ensure all data stored in the Redshift cluster is securely encrypted at rest"
+        id = "CKV_AWS_64"
+        supported_resources = ['AWS::Redshift::Cluster']
+        categories = [CheckCategories.ENCRYPTION]
+        super().__init__(name=name, id=id, categories=categories, supported_resources=supported_resources)
+
+    def scan_resource_conf(self, conf):
+        """
+            Looks for encryption configuration at Redshift cluster:
+            https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-resource-redshift-cluster.html
+        :param conf: AWS::Redshift::Cluster configuration
+        :return: <CheckResult>
+        """
+        if 'Properties' in conf.keys():
+            if 'Encrypted' in conf['Properties'].keys():
+                if conf['Properties']['Encrypted'] == True:
+                    return CheckResult.PASSED
+        return CheckResult.FAILED
+
+check = RedshiftClusterEncryption()
diff --git a/checkov/terraform/checks/resource/aws/RedshiftClusterEncryption.py b/checkov/terraform/checks/resource/aws/RedshiftClusterEncryption.py
new file mode 100644
--- /dev/null
+++ b/checkov/terraform/checks/resource/aws/RedshiftClusterEncryption.py
@@ -0,0 +1,17 @@
+from checkov.terraform.checks.resource.base_resource_value_check import BaseResourceValueCheck
+from checkov.common.models.enums import CheckCategories
+
+
+class RedshiftClusterEncryption(BaseResourceValueCheck):
+    def __init__(self):
+        name = "Ensure all data stored in the Redshift cluster is securely encrypted at rest"
+        id = "CKV_AWS_64"
+        supported_resources = ['aws_redshift_cluster']
+        categories = [CheckCategories.ENCRYPTION]
+        super().__init__(name=name, id=id, categories=categories, supported_resources=supported_resources)
+
+    def get_inspected_key(self):
+        return "encryption"
+
+
+check = RedshiftClusterEncryption()


Test patch:
diff --git a/tests/cloudformation/checks/resource/aws/example_RedshiftClusterEncryption/RedshiftClusterEncryption-FAILED-2.yaml b/tests/cloudformation/checks/resource/aws/example_RedshiftClusterEncryption/RedshiftClusterEncryption-FAILED-2.yaml
new file mode 100644
--- /dev/null
+++ b/tests/cloudformation/checks/resource/aws/example_RedshiftClusterEncryption/RedshiftClusterEncryption-FAILED-2.yaml
@@ -0,0 +1,10 @@
+Resources:
+  myCluster:
+    Type: "AWS::Redshift::Cluster"
+    Properties:
+      DBName: "mydb"
+      MasterUsername: "master"
+      MasterUserPassword:
+        Ref: "MasterUserPassword"
+      NodeType: "ds2.xlarge"
+      ClusterType: "single-node"
diff --git a/tests/cloudformation/checks/resource/aws/example_RedshiftClusterEncryption/RedshiftClusterEncryption-FAILED.yaml b/tests/cloudformation/checks/resource/aws/example_RedshiftClusterEncryption/RedshiftClusterEncryption-FAILED.yaml
new file mode 100644
--- /dev/null
+++ b/tests/cloudformation/checks/resource/aws/example_RedshiftClusterEncryption/RedshiftClusterEncryption-FAILED.yaml
@@ -0,0 +1,11 @@
+Resources:
+  myCluster:
+    Type: "AWS::Redshift::Cluster"
+    Properties:
+      DBName: "mydb"
+      MasterUsername: "master"
+      MasterUserPassword:
+        Ref: "MasterUserPassword"
+      NodeType: "ds2.xlarge"
+      ClusterType: "single-node"
+      Encrypted: false
diff --git a/tests/cloudformation/checks/resource/aws/example_RedshiftClusterEncryption/RedshiftClusterEncryption-PASSED.yaml b/tests/cloudformation/checks/resource/aws/example_RedshiftClusterEncryption/RedshiftClusterEncryption-PASSED.yaml
new file mode 100644
--- /dev/null
+++ b/tests/cloudformation/checks/resource/aws/example_RedshiftClusterEncryption/RedshiftClusterEncryption-PASSED.yaml
@@ -0,0 +1,11 @@
+Resources:
+  myCluster:
+    Type: "AWS::Redshift::Cluster"
+    Properties:
+      DBName: "mydb"
+      MasterUsername: "master"
+      MasterUserPassword:
+        Ref: "MasterUserPassword"
+      NodeType: "ds2.xlarge"
+      ClusterType: "single-node"
+      Encrypted: true
diff --git a/tests/cloudformation/checks/resource/aws/test_RedshiftClusterEncryption.py b/tests/cloudformation/checks/resource/aws/test_RedshiftClusterEncryption.py
new file mode 100644
--- /dev/null
+++ b/tests/cloudformation/checks/resource/aws/test_RedshiftClusterEncryption.py
@@ -0,0 +1,26 @@
+import os
+import unittest
+
+from checkov.cloudformation.checks.resource.aws.RedshiftClusterEncryption import check
+from checkov.cloudformation.runner import Runner
+from checkov.runner_filter import RunnerFilter
+
+
+class TestRedshiftClusterEncryption(unittest.TestCase):
+
+    def test_summary(self):
+        runner = Runner()
+        current_dir = os.path.dirname(os.path.realpath(__file__))
+
+        test_files_dir = current_dir + "/example_RedshiftClusterEncryption"
+        report = runner.run(root_folder=test_files_dir,runner_filter=RunnerFilter(checks=[check.id]))
+        summary = report.get_summary()
+
+        self.assertEqual(summary['passed'], 1)
+        self.assertEqual(summary['failed'], 2)
+        self.assertEqual(summary['skipped'], 0)
+        self.assertEqual(summary['parsing_errors'], 0)
+
+
+if __name__ == '__main__':
+    unittest.main()
diff --git a/tests/terraform/checks/resource/aws/test_RedshiftClusterEncryption.py b/tests/terraform/checks/resource/aws/test_RedshiftClusterEncryption.py
new file mode 100644
--- /dev/null
+++ b/tests/terraform/checks/resource/aws/test_RedshiftClusterEncryption.py
@@ -0,0 +1,36 @@
+import unittest
+
+from checkov.terraform.checks.resource.aws.RedshiftClusterEncryption import check
+from checkov.common.models.enums import CheckResult
+
+
+class TestRedshiftClusterEncryption(unittest.TestCase):
+
+    def test_failure(self):
+        resource_conf = {
+            "cluster_identifier": ["tf-redshift-cluster"],
+            "database_name": ["mydb"],
+            "master_username": ["foo"],
+            "master_password": ["Mustbe8characters"],
+            "node_type": ["dc1.large"],
+            "cluster_type": ["single-node"]
+        }
+        scan_result = check.scan_resource_conf(conf=resource_conf)
+        self.assertEqual(CheckResult.FAILED, scan_result)
+
+    def test_success(self):
+        resource_conf = {
+            "cluster_identifier": ["tf-redshift-cluster"],
+            "database_name": ["mydb"],
+            "master_username": ["foo"],
+            "master_password": ["Mustbe8characters"],
+            "node_type": ["dc1.large"],
+            "cluster_type": ["single-node"],
+            "encryption": [True]
+        }
+        scan_result = check.scan_resource_conf(conf=resource_conf)
+        self.assertEqual(CheckResult.PASSED, scan_result)
+
+
+if __name__ == "__main__":
+    unittest.main()