Repository: bridgecrewio/checkov

Issue:
CKV_AWS_103 should not trigger for TCP NLB's
Hi!

CKV_AWS_103 throws an error when using an NLB with TCP protocol.
However, setting an `ssl_policy` only make sense for ELB's with protocol HTTPS or TLS.

```
                14 | resource "aws_lb_listener" "nlb_listener_https" {
                15 |   load_balancer_arn = aws_lb.nlb.arn
                16 |   port              = xxxxxxxx
                17 |   protocol          = "TCP"
                18 |   default_action {
                19 |     target_group_arn = aws_lb_target_group.nlb_target_group.id
                20 |     type             = "forward"
                21 |   }
                22 | }
```

`Check: CKV_AWS_103: "Ensure that load balancer is using TLS 1.2"
        FAILED for resource: aws_lb_listener.nlb_listener_https
        File: /nlb.tf:14-22
        Guide: https://docs.bridgecrew.io/docs/bc_aws_general_43`

**Expected behavior**
Check is PASSED instead of FAILED.


Discussion:
@schosterbarak depending on the desired behaviour here, I could fix it, because I already worked on this check in the past.
Thank you @gruebel would love that!

Resolving patch:
diff --git a/checkov/terraform/checks/resource/aws/AppLoadBalancerTLS12.py b/checkov/terraform/checks/resource/aws/AppLoadBalancerTLS12.py
--- a/checkov/terraform/checks/resource/aws/AppLoadBalancerTLS12.py
+++ b/checkov/terraform/checks/resource/aws/AppLoadBalancerTLS12.py
@@ -6,28 +6,35 @@ class AppLoadBalancerTLS12(BaseResourceCheck):
     def __init__(self):
         name = "Ensure that load balancer is using TLS 1.2"
         id = "CKV_AWS_103"
-        supported_resources = ['aws_lb_listener']
+        supported_resources = ["aws_lb_listener"]
         categories = [CheckCategories.GENERAL_SECURITY]
-        super().__init__(name=name, id=id, categories=categories, supported_resources=supported_resources)
+        super().__init__(
+            name=name,
+            id=id,
+            categories=categories,
+            supported_resources=supported_resources,
+        )
 
     def scan_resource_conf(self, conf):
-        key="protocol"
+        key = "protocol"
         if key in conf.keys():
             if conf[key] in (["HTTPS"], ["TLS"]):
-              # Only interested in HTTPS & TLS listeners
-                policy="ssl_policy"
+                # Only interested in HTTPS & TLS listeners
+                policy = "ssl_policy"
                 if policy in conf.keys():
-                  name=str(conf[policy]).strip("['']") 
-                  if name.startswith("ELBSecurityPolicy-FS-1-2") or name.startswith("ELBSecurityPolicy-TLS-1-2"):
-                    return CheckResult.PASSED
-                  else:
-                    return CheckResult.FAILED
+                    name = str(conf[policy]).strip("['']")
+                    if name.startswith("ELBSecurityPolicy-FS-1-2") or name.startswith("ELBSecurityPolicy-TLS-1-2"):
+                        return CheckResult.PASSED
+                    else:
+                        return CheckResult.FAILED
                 else:
-                  return CheckResult.FAILED
+                    return CheckResult.FAILED
+            elif conf[key] in (["TCP"], ["UDP"], ["TCP_UDP"]):
+                return CheckResult.PASSED
             else:
-                for action in conf.get('default_action',[]):
-                    for redirect in action.get('redirect',[]):
-                        if redirect.get('protocol',[]) == ["HTTPS"]:
+                for action in conf.get("default_action", []):
+                    for redirect in action.get("redirect", []):
+                        if redirect.get("protocol", []) == ["HTTPS"]:
                             return CheckResult.PASSED
                 return CheckResult.FAILED
         else:


Test patch:
diff --git a/tests/terraform/checks/resource/aws/example_AppLoadBalancerTLS12/main.tf b/tests/terraform/checks/resource/aws/example_AppLoadBalancerTLS12/main.tf
new file mode 100644
--- /dev/null
+++ b/tests/terraform/checks/resource/aws/example_AppLoadBalancerTLS12/main.tf
@@ -0,0 +1,115 @@
+# pass
+
+resource "aws_lb_listener" "http_redirect" {
+  load_balancer_arn = var.aws_lb_arn
+  protocol          = "HTTP"
+  port              = "80"
+
+  default_action {
+    type = "redirect"
+
+    redirect {
+      port        = "443"
+      protocol    = "HTTPS"
+      status_code = "HTTP_301"
+    }
+  }
+}
+
+resource "aws_lb_listener" "tcp" {
+  load_balancer_arn = var.aws_lb_arn
+  protocol          = "TCP"
+  port              = "8080"
+
+  default_action {
+    type             = "forward"
+    target_group_arn = var.aws_lb_target_group_arn
+  }
+}
+
+resource "aws_lb_listener" "udp" {
+  load_balancer_arn = var.aws_lb_arn
+  protocol          = "UDP"
+  port              = "8080"
+
+  default_action {
+    type             = "forward"
+    target_group_arn = var.aws_lb_target_group_arn
+  }
+}
+
+resource "aws_lb_listener" "tcp_udp" {
+  load_balancer_arn = var.aws_lb_arn
+  protocol          = "TCP_UDP"
+  port              = "8080"
+
+  default_action {
+    type             = "forward"
+    target_group_arn = var.aws_lb_target_group_arn
+  }
+}
+
+resource "aws_lb_listener" "tls_fs_1_2" {
+  load_balancer_arn = var.aws_lb_arn
+  protocol          = "TLS"
+  port              = "8080"
+  ssl_policy        = "ELBSecurityPolicy-FS-1-2-Res-2019-08"
+  certificate_arn   = var.certificate_arn
+
+  default_action {
+    type             = "forward"
+    target_group_arn = var.aws_lb_target_group_arn
+  }
+}
+
+resource "aws_lb_listener" "https_fs_1_2" {
+  load_balancer_arn = var.aws_lb_arn
+  protocol          = "HTTPS"
+  port              = "443"
+  ssl_policy        = "ELBSecurityPolicy-FS-1-2-Res-2019-08"
+  certificate_arn   = var.certificate_arn
+
+  default_action {
+    type             = "forward"
+    target_group_arn = var.aws_lb_target_group_arn
+  }
+}
+
+# failure
+
+resource "aws_lb_listener" "http" {
+  load_balancer_arn = var.aws_lb_arn
+  protocol          = "HTTP"
+  port              = "80"
+
+  default_action {
+    type             = "forward"
+    target_group_arn = var.aws_lb_target_group_arn
+  }
+}
+
+resource "aws_lb_listener" "https_2016" {
+  load_balancer_arn = var.aws_lb_arn
+  protocol          = "HTTPS"
+  port              = "443"
+  ssl_policy        = "ELBSecurityPolicy-2016-08"
+  certificate_arn   = var.certificate_arn
+
+  default_action {
+    type             = "forward"
+    target_group_arn = var.aws_lb_target_group_arn
+  }
+}
+
+resource "aws_lb_listener" "tls_fs_1_1" {
+  load_balancer_arn = var.aws_lb_arn
+  protocol          = "TLS"
+  port              = "8080"
+  ssl_policy        = "ELBSecurityPolicy-FS-1-1-2019-08"
+  certificate_arn   = var.certificate_arn
+
+  default_action {
+    type             = "forward"
+    target_group_arn = var.aws_lb_target_group_arn
+  }
+}
diff --git a/tests/terraform/checks/resource/aws/test_AppLoadBalancerTLS12.py b/tests/terraform/checks/resource/aws/test_AppLoadBalancerTLS12.py
--- a/tests/terraform/checks/resource/aws/test_AppLoadBalancerTLS12.py
+++ b/tests/terraform/checks/resource/aws/test_AppLoadBalancerTLS12.py
@@ -1,79 +1,47 @@
+import os
 import unittest
 
-import hcl2
-
-from checkov.common.models.enums import CheckResult
+from checkov.runner_filter import RunnerFilter
 from checkov.terraform.checks.resource.aws.AppLoadBalancerTLS12 import check
+from checkov.terraform.runner import Runner
 
-class TestAppLoadBalancerTLS12(unittest.TestCase):
 
-    def test_failure(self):
-        resource_conf =  {'load_balancer_arn': ['${aws_lb.examplea.arn}'], 'port': ['443'], 'protocol': ['HTTPS'], 'ssl_policy': ["ELBSecurityPolicy-2016-08"],
-                         'default_action': [{'type': ['forward'], 'target_group_arn': ['${aws_lb_target_group.examplea.arn}'] }]}
-        scan_result = check.scan_resource_conf(conf=resource_conf)
-        self.assertEqual(CheckResult.FAILED, scan_result)
- 
-    def test_success(self):
-        resource_conf =  {
-            'load_balancer_arn': [
-                '${aws_lb.examplea.arn}'
-                ], 
-            'port': ['443'], 
-            'protocol': ['HTTPS'], 
-            'ssl_policy': ["ELBSecurityPolicy-TLS-1-2-2017-01"],
-            'default_action': [
-                {
-                    'type': ['forward'], 
-                    'target_group_arn': [
-                        '${aws_lb_target_group.examplea.arn}'
-                ]
-            }
-        ]
+class TestAppLoadBalancerTLS12(unittest.TestCase):
+    def test(self):
+        runner = Runner()
+        current_dir = os.path.dirname(os.path.realpath(__file__))
+
+        test_files_dir = current_dir + "/example_AppLoadBalancerTLS12"
+        report = runner.run(
+            root_folder=test_files_dir, runner_filter=RunnerFilter(checks=[check.id])
+        )
+        summary = report.get_summary()
+
+        passing_resources = {
+            "aws_lb_listener.http_redirect",
+            "aws_lb_listener.tcp",
+            "aws_lb_listener.udp",
+            "aws_lb_listener.tcp_udp",
+            "aws_lb_listener.tls_fs_1_2",
+            "aws_lb_listener.https_fs_1_2",
         }
-        scan_result = check.scan_resource_conf(conf=resource_conf)
-        self.assertEqual(CheckResult.PASSED, scan_result)
-
-    def test_nlb_tls_success(self):
-        resource_conf = {
-            'load_balancer_arn': [
-                '${aws_lb.example.arn}'
-            ],
-            'port': ['443'],
-            'protocol': ['TLS'],
-            'ssl_policy': ["ELBSecurityPolicy-FS-1-2-Res-2019-08"],
-            'default_action': [
-                {
-                    'type': ['forward'],
-                    'target_group_arn': [
-                        '${aws_lb_target_group.example.arn}'
-                    ]
-                }
-            ]
+        failing_resources = {
+            "aws_lb_listener.http",
+            "aws_lb_listener.https_2016",
+            "aws_lb_listener.tls_fs_1_1",
         }
-        scan_result = check.scan_resource_conf(conf=resource_conf)
-        self.assertEqual(CheckResult.PASSED, scan_result)
 
-    def test_redirect(self):
-        hcl_res = hcl2.loads("""
-            resource "aws_lb_listener" "http" {
-              load_balancer_arn = aws_lb.public.arn
-              port              = "80"
-              protocol          = "HTTP" 
-            
-              default_action {
-                redirect {
-                  port        = "443"
-                  protocol    = "HTTPS"
-                  status_code = "HTTP_301"
-                }
-                type = "redirect"
-              }
-            }
-            """)
-        resource_conf = hcl_res['resource'][0]['aws_lb_listener']['http']
-        scan_result = check.scan_resource_conf(conf=resource_conf)
-        self.assertEqual(CheckResult.PASSED, scan_result)
+        passed_check_resources = set([c.resource for c in report.passed_checks])
+        failed_check_resources = set([c.resource for c in report.failed_checks])
 
-if __name__ == '__main__':
-    unittest.main()
+        self.assertEqual(summary["passed"], 6)
+        self.assertEqual(summary["failed"], 3)
+        self.assertEqual(summary["skipped"], 0)
+        self.assertEqual(summary["parsing_errors"], 0)
+
+        self.assertEqual(passing_resources, passed_check_resources)
+        self.assertEqual(failing_resources, failed_check_resources)
 
+
+if __name__ == "__main__":
+    unittest.main()