Repository: bridgecrewio/checkov

Issue:
AWS_CKV_7 False Positive on assymetric key check in Cloudformation
**Describe the issue**
In terraform, the check avoids false positives with an extra check against symmetric keys before checking whether rotation is enabled.  This same check hasn't been configured for cloudformation:

```
def scan_resource_conf(self, conf):
        # Only symmetric keys support auto rotation. The attribute is optional and defaults to symmetric.
        spec = conf.get('customer_master_key_spec')
        if not spec or 'SYMMETRIC_DEFAULT' in spec:
            return super().scan_resource_conf(conf)
        else:
            return CheckResult.PASSED
```

**Examples**

```
RSASigningKey:
  Type: 'AWS::KMS::Key'
  Properties:
    Description: RSA-3072 asymmetric KMS key for signing and verification
    KeySpec: RSA_3072
    KeyUsage: SIGN_VERIFY
    KeyPolicy:
      Version: 2012-10-17
      Id: key-default-1
      Statement:
        - Sid: Enable IAM User Permissions
          Effect: Allow
          Principal:
            AWS: 'arn:aws:iam::111122223333:root'
          Action: 'kms:*'
          Resource: '*'
        - Sid: Allow administration of the key
          Effect: Allow
          Principal:
            AWS: 'arn:aws:iam::111122223333:role/Admin'
          Action:
            - 'kms:Create*'
            - 'kms:Describe*'
            - 'kms:Enable*'
            - 'kms:List*'
            - 'kms:Put*'
            - 'kms:Update*'
            - 'kms:Revoke*'
            - 'kms:Disable*'
            - 'kms:Get*'
            - 'kms:Delete*'
            - 'kms:ScheduleKeyDeletion'
            - 'kms:CancelKeyDeletion'
          Resource: '*'
        - Sid: Allow use of the key
          Effect: Allow
          Principal:
            AWS: 'arn:aws:iam::111122223333:role/Developer'
          Action:
            - 'kms:Sign'
            - 'kms:Verify'
            - 'kms:DescribeKey'
          Resource: '*'
```

**Version (please complete the following information):**
 - Checkov Version [e.g. 2.3.0]

**Additional context**

This blocks checkov working for assymetric keys in CFN.



Discussion:

Resolving patch:
diff --git a/checkov/cloudformation/checks/resource/aws/KMSRotation.py b/checkov/cloudformation/checks/resource/aws/KMSRotation.py
--- a/checkov/cloudformation/checks/resource/aws/KMSRotation.py
+++ b/checkov/cloudformation/checks/resource/aws/KMSRotation.py
@@ -1,4 +1,4 @@
-from checkov.common.models.enums import CheckCategories
+from checkov.common.models.enums import CheckCategories, CheckResult
 from checkov.cloudformation.checks.resource.base_resource_value_check import BaseResourceValueCheck
 
 
@@ -13,5 +13,15 @@ def __init__(self) -> None:
     def get_inspected_key(self) -> str:
         return "Properties/EnableKeyRotation"
 
+    def scan_resource_conf(self, conf):
+        # Only symmetric keys support auto rotation. The attribute is optional and defaults to symmetric.
+        properties = conf.get("Properties")
+        if properties and isinstance(properties, dict):
+            spec = properties.get("KeySpec")
+            if spec and isinstance(spec, str):
+                if 'SYMMETRIC_DEFAULT' not in spec and 'HMAC' not in spec:
+                    return CheckResult.UNKNOWN
+        return super().scan_resource_conf(conf)
+
 
 check = KMSRotation()
diff --git a/checkov/terraform/checks/resource/aws/KMSRotation.py b/checkov/terraform/checks/resource/aws/KMSRotation.py
--- a/checkov/terraform/checks/resource/aws/KMSRotation.py
+++ b/checkov/terraform/checks/resource/aws/KMSRotation.py
@@ -16,10 +16,10 @@ def get_inspected_key(self):
     def scan_resource_conf(self, conf):
         # Only symmetric keys support auto rotation. The attribute is optional and defaults to symmetric.
         spec = conf.get('customer_master_key_spec')
-        if not spec or 'SYMMETRIC_DEFAULT' in spec:
+        if not spec or 'SYMMETRIC_DEFAULT' in spec or 'HMAC' in spec:
             return super().scan_resource_conf(conf)
         else:
-            return CheckResult.PASSED
+            return CheckResult.UNKNOWN
 
 
 check = KMSRotation()


Test patch:
diff --git a/tests/cloudformation/checks/resource/aws/example_KMSRotation/KMSRotation-FAILED.yml b/tests/cloudformation/checks/resource/aws/example_KMSRotation/KMSRotation-FAILED.yml
--- a/tests/cloudformation/checks/resource/aws/example_KMSRotation/KMSRotation-FAILED.yml
+++ b/tests/cloudformation/checks/resource/aws/example_KMSRotation/KMSRotation-FAILED.yml
@@ -1,7 +1,7 @@
 AWSTemplateFormatVersion: 2010-09-09
 Description: KMS key example template
 Resources:
-  myKey:
+  SymmetricKey:
     Type: AWS::KMS::Key
     Properties:
       KeyPolicy:
diff --git a/tests/cloudformation/checks/resource/aws/example_KMSRotation/KMSRotation-PASSED-Asymmetric.yml b/tests/cloudformation/checks/resource/aws/example_KMSRotation/KMSRotation-PASSED-Asymmetric.yml
new file mode 100644
--- /dev/null
+++ b/tests/cloudformation/checks/resource/aws/example_KMSRotation/KMSRotation-PASSED-Asymmetric.yml
@@ -0,0 +1,24 @@
+AWSTemplateFormatVersion: 2010-09-09
+Description: KMS key example template
+Resources:
+  AsymmetricKey:
+    Type: AWS::KMS::Key
+    Properties:
+      KeySpec: RSA_4096
+      KeyPolicy:
+        Version: '2012-10-17'
+        Id: key-default-1
+        Statement:
+        - Sid: Enable IAM User Permissions
+          Effect: Allow
+          Principal:
+            AWS:
+              Fn::Join:
+              - ''
+              - - 'arn:aws:iam::'
+                - Ref: AWS::AccountId
+                - :root
+          Action: kms:*
+          Resource: '*'
+      EnableKeyRotation: true
+  
\ No newline at end of file
diff --git a/tests/cloudformation/checks/resource/aws/example_KMSRotation/KMSRotation-PASSED.yml b/tests/cloudformation/checks/resource/aws/example_KMSRotation/KMSRotation-PASSED-Symmetric.yml
similarity index 91%
rename from tests/cloudformation/checks/resource/aws/example_KMSRotation/KMSRotation-PASSED.yml
rename to tests/cloudformation/checks/resource/aws/example_KMSRotation/KMSRotation-PASSED-Symmetric.yml
--- a/tests/cloudformation/checks/resource/aws/example_KMSRotation/KMSRotation-PASSED.yml
+++ b/tests/cloudformation/checks/resource/aws/example_KMSRotation/KMSRotation-PASSED-Symmetric.yml
@@ -1,7 +1,7 @@
 AWSTemplateFormatVersion: 2010-09-09
 Description: KMS key example template
 Resources:
-  myKey:
+  SymmetricKey:
     Type: AWS::KMS::Key
     Properties:
       KeyPolicy:
@@ -19,4 +19,5 @@ Resources:
                 - :root
           Action: kms:*
           Resource: '*'
-      EnableKeyRotation: true
\ No newline at end of file
+      EnableKeyRotation: true
+  
\ No newline at end of file
diff --git a/tests/cloudformation/checks/resource/aws/test_KMSRotation.py b/tests/cloudformation/checks/resource/aws/test_KMSRotation.py
--- a/tests/cloudformation/checks/resource/aws/test_KMSRotation.py
+++ b/tests/cloudformation/checks/resource/aws/test_KMSRotation.py
@@ -13,14 +13,13 @@ def test_summary(self):
         current_dir = os.path.dirname(os.path.realpath(__file__))
 
         test_files_dir = current_dir + "/example_KMSRotation"
-        report = runner.run(root_folder=test_files_dir,runner_filter=RunnerFilter(checks=[check.id]))
+        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'], 1)
+        self.assertEqual(summary["passed"], 1)
+        self.assertEqual(summary["failed"], 1)
         self.assertEqual(summary['skipped'], 0)
         self.assertEqual(summary['parsing_errors'], 0)
 
-
 if __name__ == '__main__':
     unittest.main()
diff --git a/tests/terraform/checks/resource/aws/example_KMSRotation/main.tf b/tests/terraform/checks/resource/aws/example_KMSRotation/main.tf
--- a/tests/terraform/checks/resource/aws/example_KMSRotation/main.tf
+++ b/tests/terraform/checks/resource/aws/example_KMSRotation/main.tf
@@ -7,14 +7,26 @@ resource "aws_kms_key" "pass1" {
 resource "aws_kms_key" "pass2" {
   description              = "KMS key 1"
   deletion_window_in_days  = 10
-  customer_master_key_spec = "RSA_2096"
+  customer_master_key_spec = "SYMMETRIC_DEFAULT"
+  enable_key_rotation      = true
 }
 
-resource "aws_kms_key" "pass3" {
+resource "aws_kms_key" "unknown1" {
   description              = "KMS key 1"
   deletion_window_in_days  = 10
-  customer_master_key_spec = "SYMMETRIC_DEFAULT"
-  enable_key_rotation      = true
+  customer_master_key_spec = "RSA_2048"
+}
+
+resource "aws_kms_key" "unknown2" {
+  description              = "KMS key 1"
+  deletion_window_in_days  = 10
+  customer_master_key_spec = "RSA_3072"
+}
+
+resource "aws_kms_key" "unknown2" {
+  description              = "KMS key 1"
+  deletion_window_in_days  = 10
+  customer_master_key_spec = "RSA_4096"
 }
 
 resource "aws_kms_key" "fail1" {
diff --git a/tests/terraform/checks/resource/aws/test_KMSRotation.py b/tests/terraform/checks/resource/aws/test_KMSRotation.py
--- a/tests/terraform/checks/resource/aws/test_KMSRotation.py
+++ b/tests/terraform/checks/resource/aws/test_KMSRotation.py
@@ -19,19 +19,19 @@ def test(self):
         passing_resources = {
             "aws_kms_key.pass1",
             "aws_kms_key.pass2",
-            "aws_kms_key.pass3",
         }
+
         failing_resources = {
             "aws_kms_key.fail1",
             "aws_kms_key.fail2",
             "aws_kms_key.fail3",
             "aws_kms_key.fail4",
         }
-
+    
         passed_check_resources = set([c.resource for c in report.passed_checks])
         failed_check_resources = set([c.resource for c in report.failed_checks])
 
-        self.assertEqual(summary["passed"], 3)
+        self.assertEqual(summary["passed"], 2)
         self.assertEqual(summary["failed"], 4)
         self.assertEqual(summary["skipped"], 0)
         self.assertEqual(summary["parsing_errors"], 0)