Repository: bridgecrewio/checkov

Issue:
Check: CKV_AWS_84: "Ensure Elasticsearch Domain Logging is enabled"
**Describe the bug**
My TF module has enabled logging for all types: "INDEX_SLOW_LOGS, SEARCH_SLOW_LOGS, ES_APPLICATION_LOGS, AUDIT_LOGS", but I still got error:

```
Check: CKV_AWS_84: "Ensure Elasticsearch Domain Logging is enabled"
	FAILED for resource: aws_elasticsearch_domain.es
	File: /tf.json:0-0
	Guide: https://docs.bridgecrew.io/docs/elasticsearch_7
```

**Elasticserach module:**
```
resource "aws_elasticsearch_domain" "es" {
  domain_name           = var.elasticsearch_domain
  elasticsearch_version = var.elasticsearch_version

  cluster_config {
    instance_type          = var.instance_type
    instance_count         = var.instance_count
    zone_awareness_enabled = var.availability_zone_count == 1 ? false : true
    dynamic "zone_awareness_config" {
      for_each = null_resource.azs[*].triggers
      content {
        availability_zone_count = zone_awareness_config.value.availability_zone_count
      }
    }
  }

  vpc_options {
    subnet_ids = var.subnet_ids

    security_group_ids = [
      aws_security_group.elasticsearch_sg.id,
    ]
  }

  ebs_options {
    ebs_enabled = true
    volume_size = var.instance_volume_size
  }

  encrypt_at_rest {
    enabled = var.encrypt_at_rest ? true : false
    kms_key_id = var.kms_key_id != null ? var.kms_key_id : null
  }

  domain_endpoint_options {
    enforce_https = var.enforce_https
    tls_security_policy = var.enforce_https ? var.tls_security_policy : null
  }

  log_publishing_options {
    enabled                  = var.log_publishing ? true : false
    cloudwatch_log_group_arn = var.log_publishing ? aws_cloudwatch_log_group.elasticsearch-app-logs[0].arn : null
    log_type                 = var.log_publishing ? "ES_APPLICATION_LOGS" : null
  }

  log_publishing_options {
    enabled                  = var.log_publishing ? true : false
    cloudwatch_log_group_arn = var.log_publishing ? aws_cloudwatch_log_group.elasticsearch-slow-logs[0].arn : null
    log_type                 = var.log_publishing ? "INDEX_SLOW_LOGS" : null
  }

  log_publishing_options {
    enabled                  = var.log_publishing ? true : false
    cloudwatch_log_group_arn = var.log_publishing ? aws_cloudwatch_log_group.elasticsearch-audit-logs[0].arn : null
    log_type                 = var.log_publishing ? "AUDIT_LOGS" : null
  }

  log_publishing_options {
    enabled                  = var.log_publishing ? true : false
    cloudwatch_log_group_arn = var.log_publishing ? aws_cloudwatch_log_group.elasticsearch-search-slow-logs[0].arn : null
    log_type                 = var.log_publishing ? "AUDIT_LOGS" : null
  }

  access_policies = <<CONFIG
{
  "Version": "2012-10-17",
  "Statement": [
      {
          "Action": "es:*",
          "Principal": "*",
          "Effect": "Allow",
          "Resource": "arn:aws:es:${var.aws_region}:${data.aws_caller_identity.current.account_id}:domain/${var.elasticsearch_domain}/*"
      }
  ]
}
CONFIG

  snapshot_options {
    automated_snapshot_start_hour = var.elasticsearch_snapshot_time
  }

  depends_on = [
    aws_iam_service_linked_role.es
  ]

  tags = merge(var.tags, {
    Domain = var.elasticsearch_domain
  })
}
```

CW Log Groups, Policy, etc are created. Variable "log_publishing" by default = true.
Module deployed successfully and logging enabled, but "checkov" check not passed.

**Expected behavior**
All types of logs are enabled, check must be passed.

**Desktop:**
 - OS: macOS Big Sur 11.2.1
 - Checkov Version: 2.0.86



Discussion:

Patch:
diff --git a/checkov/terraform/plan_parser.py b/checkov/terraform/plan_parser.py
index 755b6537b..94dee6151 100644
--- a/checkov/terraform/plan_parser.py
+++ b/checkov/terraform/plan_parser.py
@@ -1,18 +1,21 @@
-from checkov.terraform.context_parsers.tf_plan import parse
+import itertools
+from typing import Optional, Tuple, Dict, List, Any
 
-simple_types = [str, int, float, bool]
+from checkov.terraform.context_parsers.tf_plan import parse, dict_node
+from checkov.terraform.context_parsers.tf_plan.node import list_node
 
+simple_types = (str, int, float, bool)
 
-def _is_simple_type(obj):
-    obj_type = type(obj)
+
+def _is_simple_type(obj: Any) -> bool:
     if obj is None:
         return True
-    if obj_type in simple_types:
+    if isinstance(obj, simple_types):
         return True
     return False
 
 
-def _is_list_of_simple_types(l):
+def _is_list_of_simple_types(l: Any) -> bool:
     if not isinstance(l, list):
         return False
     for i in l:
@@ -21,7 +24,7 @@ def _is_list_of_simple_types(l):
     return True
 
 
-def _is_list_of_dicts(l):
+def _is_list_of_dicts(l: Any) -> bool:
     if not isinstance(l, list):
         return False
     for i in l:
@@ -30,11 +33,11 @@ def _is_list_of_dicts(l):
     return False
 
 
-def _hclify(obj, parent_key=None):
+def _hclify(obj: dict_node, conf: Optional[dict_node] = None, parent_key: Optional[str] = None) -> Dict[str, List[Any]]:
     ret_dict = {}
     if not isinstance(obj, dict):
         raise Exception("this method receives only dicts")
-    if hasattr(obj, 'start_mark') and hasattr(obj, "end_mark"):
+    if hasattr(obj, "start_mark") and hasattr(obj, "end_mark"):
         obj["start_line"] = obj.start_mark.line
         obj["end_line"] = obj.end_mark.line
     for key, value in obj.items():
@@ -46,38 +49,52 @@ def _hclify(obj, parent_key=None):
 
         if _is_list_of_dicts(value):
             child_list = []
-            for internal_val in value:
-                child_list.append(_hclify(internal_val))
+            conf_val = conf.get(key, []) if conf else []
+            for internal_val, internal_conf_val in itertools.zip_longest(value, conf_val):
+                child_list.append(_hclify(internal_val, internal_conf_val))
             ret_dict[key] = child_list
         if isinstance(value, dict):
-            child_dict = _hclify(value, key)
+            child_dict = _hclify(value, parent_key=key)
             if parent_key == "tags":
                 ret_dict[key] = child_dict
             else:
                 ret_dict[key] = [child_dict]
+    if conf:
+        for conf_key in conf.keys() - obj.keys():
+            ref = next((x for x in conf[conf_key].get("references", []) if not x.startswith(("var.", "local."))), None)
+            if ref:
+                ret_dict[conf_key] = [ref]
+
     return ret_dict
 
-def _prepare_resource_block(resource):
-    """
-    hclify resource if pre-conditions met.
-    :type: resource: dict: tf resource block
-    :rtype: resource_block: dict: hclifyed if conditions met
-    :rtype: prepared: boolean: whether conditions met to prepare data
+
+def _prepare_resource_block(resource: dict_node, conf: Optional[dict_node]) -> Tuple[Dict[str, Dict[str, Any]], bool]:
+    """hclify resource if pre-conditions met.
+
+    :param resource: tf planned_values resource block
+    :param conf: tf configuration resource block
+
+    :returns:
+        - resource_block: a list of strings representing the header columns
+        - prepared: whether conditions met to prepare data
     """
-    resource_block = {}
-    resource_block[resource['type']] = {}
+
+    resource_block: Dict[str, Dict[str, Any]] = {}
+    resource_block[resource["type"]] = {}
     prepared = False
     mode = ""
-    if 'mode' in resource:
+    if "mode" in resource:
         mode = resource.get("mode")
     # Rare cases where data block appears in resources with same name as resource block and only partial values
     # and where *_module resources don't have values field
-    if mode == "managed" and 'values' in resource:
-        resource_block[resource['type']][resource.get("name", "default")] = _hclify(resource['values'])
+    if mode == "managed" and "values" in resource:
+        expressions = conf.get("expressions") if conf else None
+        resource_block[resource["type"]][resource.get("name", "default")] = _hclify(resource["values"], expressions)
         prepared = True
     return resource_block, prepared
 
-def _find_child_modules(child_modules):
+
+def _find_child_modules(child_modules: list_node) -> List[Dict[str, Dict[str, Any]]]:
     """
     Find all child modules if any. Including any amount of nested child modules.
     :type: child_modules: list of tf child_module objects
@@ -85,37 +102,45 @@ def _find_child_modules(child_modules):
     """
     resource_blocks = []
     for child_module in child_modules:
-        if child_module.get("child_modules",[]):
-            nested_child_modules = child_module.get("child_modules",[])
+        if child_module.get("child_modules", []):
+            nested_child_modules = child_module.get("child_modules", [])
             nested_blocks = _find_child_modules(nested_child_modules)
             for resource in nested_blocks:
                 resource_blocks.append(resource)
         for resource in child_module.get("resources", []):
-            resource_block, prepared = _prepare_resource_block(resource)
+            resource_block, prepared = _prepare_resource_block(resource, None)
             if prepared is True:
                 resource_blocks.append(resource_block)
     return resource_blocks
 
 
-def parse_tf_plan(tf_plan_file):
+def parse_tf_plan(tf_plan_file: str) -> Tuple[Optional[Dict[str, Dict[str, Any]]], Optional[List[Tuple[int, str]]]]:
     """
     :type tf_plan_file: str - path to plan file
     :rtype: tf_definition dictionary
     """
-    tf_defintions = {}
+    tf_defintions: Dict[str, Dict[str, Any]] = {}
     tf_defintions[tf_plan_file] = {}
-    tf_defintions[tf_plan_file]['resource'] = []
+    tf_defintions[tf_plan_file]["resource"] = []
     template, template_lines = parse(tf_plan_file)
     if not template:
         return None, None
-    for resource in template.get('planned_values', {}).get("root_module", {}).get("resources", []):
-        resource_block, prepared = _prepare_resource_block(resource)
+    for resource in template.get("planned_values", {}).get("root_module", {}).get("resources", []):
+        conf = next(
+            (
+                x
+                for x in template.get("configuration", {}).get("root_module", {}).get("resources", [])
+                if x["type"] == resource["type"] and x["name"] == resource["name"]
+            ),
+            None,
+        )
+        resource_block, prepared = _prepare_resource_block(resource, conf)
         if prepared is True:
-            tf_defintions[tf_plan_file]['resource'].append(resource_block)
-    child_modules = template.get('planned_values', {}).get("root_module", {}).get("child_modules",[])
+            tf_defintions[tf_plan_file]["resource"].append(resource_block)
+    child_modules = template.get("planned_values", {}).get("root_module", {}).get("child_modules", [])
     # Terraform supports modules within modules so we need to search
     # in nested modules to find all resource blocks
     resource_blocks = _find_child_modules(child_modules)
     for resource in resource_blocks:
-        tf_defintions[tf_plan_file]['resource'].append(resource)
+        tf_defintions[tf_plan_file]["resource"].append(resource)
     return tf_defintions, template_lines


Test patch:
diff --git a/tests/terraform/runner/resources/plan_with_resource_reference/tfplan.json b/tests/terraform/runner/resources/plan_with_resource_reference/tfplan.json
new file mode 100644
index 000000000..0030c6c3e
--- /dev/null
+++ b/tests/terraform/runner/resources/plan_with_resource_reference/tfplan.json
@@ -0,0 +1,243 @@
+{
+    "format_version": "0.1",
+    "terraform_version": "0.12.25",
+    "planned_values": {
+        "root_module": {
+            "resources": [
+                {
+                    "address": "aws_cloudwatch_log_group.audit",
+                    "mode": "managed",
+                    "type": "aws_cloudwatch_log_group",
+                    "name": "audit",
+                    "provider_name": "aws",
+                    "schema_version": 0,
+                    "values": {
+                        "kms_key_id": null,
+                        "name": "audit",
+                        "name_prefix": null,
+                        "retention_in_days": 0,
+                        "tags": null
+                    }
+                },
+                {
+                    "address": "aws_cloudwatch_log_group.es_application",
+                    "mode": "managed",
+                    "type": "aws_cloudwatch_log_group",
+                    "name": "es_application",
+                    "provider_name": "aws",
+                    "schema_version": 0,
+                    "values": {
+                        "kms_key_id": null,
+                        "name": "es_application",
+                        "name_prefix": null,
+                        "retention_in_days": 0,
+                        "tags": null
+                    }
+                },
+                {
+                    "address": "aws_elasticsearch_domain.es",
+                    "mode": "managed",
+                    "type": "aws_elasticsearch_domain",
+                    "name": "es",
+                    "provider_name": "aws",
+                    "schema_version": 0,
+                    "values": {
+                        "cluster_config": [
+                            {
+                                "dedicated_master_count": null,
+                                "dedicated_master_enabled": false,
+                                "dedicated_master_type": null,
+                                "instance_count": 1,
+                                "instance_type": "r5.large.elasticsearch",
+                                "warm_count": null,
+                                "warm_enabled": null,
+                                "warm_type": null,
+                                "zone_awareness_config": [],
+                                "zone_awareness_enabled": null
+                            }
+                        ],
+                        "cognito_options": [],
+                        "domain_endpoint_options": [
+                            {
+                                "custom_endpoint": null,
+                                "custom_endpoint_certificate_arn": null,
+                                "custom_endpoint_enabled": false,
+                                "enforce_https": true
+                            }
+                        ],
+                        "domain_name": "test",
+                        "elasticsearch_version": "7.0",
+                        "encrypt_at_rest": [{"enabled": true}],
+                        "log_publishing_options": [
+                            {"enabled": true, "log_type": "AUDIT_LOGS"},
+                            {"enabled": true, "log_type": "ES_APPLICATION_LOGS"}
+                        ],
+                        "snapshot_options": [],
+                        "tags": null,
+                        "timeouts": null,
+                        "vpc_options": [{"security_group_ids": null, "subnet_ids": ["subnet-efc0c6a2"]}]
+                    }
+                }
+            ]
+        }
+    },
+    "resource_changes": [
+        {
+            "address": "aws_cloudwatch_log_group.audit",
+            "mode": "managed",
+            "type": "aws_cloudwatch_log_group",
+            "name": "audit",
+            "provider_name": "aws",
+            "change": {
+                "actions": ["create"],
+                "before": null,
+                "after": {
+                    "kms_key_id": null,
+                    "name": "audit",
+                    "name_prefix": null,
+                    "retention_in_days": 0,
+                    "tags": null
+                },
+                "after_unknown": {"arn": true, "id": true}
+            }
+        },
+        {
+            "address": "aws_cloudwatch_log_group.es_application",
+            "mode": "managed",
+            "type": "aws_cloudwatch_log_group",
+            "name": "es_application",
+            "provider_name": "aws",
+            "change": {
+                "actions": ["create"],
+                "before": null,
+                "after": {
+                    "kms_key_id": null,
+                    "name": "es_application",
+                    "name_prefix": null,
+                    "retention_in_days": 0,
+                    "tags": null
+                },
+                "after_unknown": {"arn": true, "id": true}
+            }
+        },
+        {
+            "address": "aws_elasticsearch_domain.es",
+            "mode": "managed",
+            "type": "aws_elasticsearch_domain",
+            "name": "es",
+            "provider_name": "aws",
+            "change": {
+                "actions": ["create"],
+                "before": null,
+                "after": {
+                    "cluster_config": [
+                        {
+                            "dedicated_master_count": null,
+                            "dedicated_master_enabled": false,
+                            "dedicated_master_type": null,
+                            "instance_count": 1,
+                            "instance_type": "r5.large.elasticsearch",
+                            "warm_count": null,
+                            "warm_enabled": null,
+                            "warm_type": null,
+                            "zone_awareness_config": [],
+                            "zone_awareness_enabled": null
+                        }
+                    ],
+                    "cognito_options": [],
+                    "domain_endpoint_options": [
+                        {
+                            "custom_endpoint": null,
+                            "custom_endpoint_certificate_arn": null,
+                            "custom_endpoint_enabled": false,
+                            "enforce_https": true
+                        }
+                    ],
+                    "domain_name": "test",
+                    "elasticsearch_version": "7.0",
+                    "encrypt_at_rest": [{"enabled": true}],
+                    "log_publishing_options": [
+                        {"enabled": true, "log_type": "AUDIT_LOGS"},
+                        {"enabled": true, "log_type": "ES_APPLICATION_LOGS"}
+                    ],
+                    "snapshot_options": [],
+                    "tags": null,
+                    "timeouts": null,
+                    "vpc_options": [{"security_group_ids": null, "subnet_ids": ["subnet-efc0c6a2"]}]
+                },
+                "after_unknown": {
+                    "access_policies": true,
+                    "advanced_options": true,
+                    "advanced_security_options": true,
+                    "arn": true,
+                    "cluster_config": [{"zone_awareness_config": []}],
+                    "cognito_options": [],
+                    "domain_endpoint_options": [{"tls_security_policy": true}],
+                    "domain_id": true,
+                    "ebs_options": true,
+                    "encrypt_at_rest": [{"kms_key_id": true}],
+                    "endpoint": true,
+                    "id": true,
+                    "kibana_endpoint": true,
+                    "log_publishing_options": [{"cloudwatch_log_group_arn": true}, {"cloudwatch_log_group_arn": true}],
+                    "node_to_node_encryption": true,
+                    "snapshot_options": [],
+                    "vpc_options": [{"availability_zones": true, "subnet_ids": [false], "vpc_id": true}]
+                }
+            }
+        }
+    ],
+    "configuration": {
+        "provider_config": {"aws": {"name": "aws", "expressions": {"region": {"constant_value": "eu-central-1"}}}},
+        "root_module": {
+            "resources": [
+                {
+                    "address": "aws_cloudwatch_log_group.audit",
+                    "mode": "managed",
+                    "type": "aws_cloudwatch_log_group",
+                    "name": "audit",
+                    "provider_config_key": "aws",
+                    "expressions": {"name": {"constant_value": "audit"}},
+                    "schema_version": 0
+                },
+                {
+                    "address": "aws_cloudwatch_log_group.es_application",
+                    "mode": "managed",
+                    "type": "aws_cloudwatch_log_group",
+                    "name": "es_application",
+                    "provider_config_key": "aws",
+                    "expressions": {"name": {"constant_value": "es_application"}},
+                    "schema_version": 0
+                },
+                {
+                    "address": "aws_elasticsearch_domain.es",
+                    "mode": "managed",
+                    "type": "aws_elasticsearch_domain",
+                    "name": "es",
+                    "provider_config_key": "aws",
+                    "expressions": {
+                        "cluster_config": [{"instance_type": {"constant_value": "r5.large.elasticsearch"}}],
+                        "domain_endpoint_options": [{"enforce_https": {"constant_value": true}}],
+                        "domain_name": {"constant_value": "test"},
+                        "elasticsearch_version": {"constant_value": "7.0"},
+                        "encrypt_at_rest": [{"enabled": {"constant_value": true}}],
+                        "log_publishing_options": [
+                            {
+                                "cloudwatch_log_group_arn": {"references": ["aws_cloudwatch_log_group.audit"]},
+                                "enabled": {"constant_value": true},
+                                "log_type": {"constant_value": "AUDIT_LOGS"}
+                            },
+                            {
+                                "cloudwatch_log_group_arn": {"references": ["aws_cloudwatch_log_group.es_application"]},
+                                "enabled": {"constant_value": true},
+                                "log_type": {"constant_value": "ES_APPLICATION_LOGS"}
+                            }
+                        ],
+                        "vpc_options": [{"subnet_ids": {"constant_value": ["subnet-efc0c6a2"]}}]
+                    },
+                    "schema_version": 0
+                }
+            ]
+        }
+    }
+}
diff --git a/tests/terraform/runner/test_plan_runner.py b/tests/terraform/runner/test_plan_runner.py
index adc944b5a..34a75f4bd 100644
--- a/tests/terraform/runner/test_plan_runner.py
+++ b/tests/terraform/runner/test_plan_runner.py
@@ -6,14 +6,17 @@ from checkov.terraform.plan_runner import Runner
 
 
 class TestRunnerValid(unittest.TestCase):
-
     def test_runner_two_checks_only(self):
         current_dir = os.path.dirname(os.path.realpath(__file__))
         valid_plan_path = current_dir + "/resources/plan/tfplan.json"
         runner = Runner()
-        checks_allowlist = ['CKV_AWS_21']
-        report = runner.run(root_folder=None, files=[valid_plan_path], external_checks_dir=None,
-                            runner_filter=RunnerFilter(framework='all', checks=checks_allowlist))
+        checks_allowlist = ["CKV_AWS_21"]
+        report = runner.run(
+            root_folder=None,
+            files=[valid_plan_path],
+            external_checks_dir=None,
+            runner_filter=RunnerFilter(framework="all", checks=checks_allowlist),
+        )
         report_json = report.get_json()
         self.assertTrue(isinstance(report_json, str))
         self.assertIsNotNone(report_json)
@@ -30,8 +33,12 @@ class TestRunnerValid(unittest.TestCase):
         current_dir = os.path.dirname(os.path.realpath(__file__))
         valid_plan_path = current_dir + "/resources/plan_with_child_modules/tfplan.json"
         runner = Runner()
-        report = runner.run(root_folder=None, files=[valid_plan_path], external_checks_dir=None,
-                            runner_filter=RunnerFilter(framework='all'))
+        report = runner.run(
+            root_folder=None,
+            files=[valid_plan_path],
+            external_checks_dir=None,
+            runner_filter=RunnerFilter(framework="all"),
+        )
         report_json = report.get_json()
         self.assertTrue(isinstance(report_json, str))
         self.assertIsNotNone(report_json)
@@ -46,8 +53,12 @@ class TestRunnerValid(unittest.TestCase):
         current_dir = os.path.dirname(os.path.realpath(__file__))
         valid_plan_path = current_dir + "/resources/plan_nested_child_modules/tfplan.json"
         runner = Runner()
-        report = runner.run(root_folder=None, files=[valid_plan_path], external_checks_dir=None,
-                            runner_filter=RunnerFilter(framework='all'))
+        report = runner.run(
+            root_folder=None,
+            files=[valid_plan_path],
+            external_checks_dir=None,
+            runner_filter=RunnerFilter(framework="all"),
+        )
         report_json = report.get_json()
         self.assertTrue(isinstance(report_json, str))
         self.assertIsNotNone(report_json)
@@ -73,8 +84,12 @@ class TestRunnerValid(unittest.TestCase):
         current_dir = os.path.dirname(os.path.realpath(__file__))
         valid_plan_path = current_dir + "/resources/plan_root_module_resources_no_values/tfplan.json"
         runner = Runner()
-        report = runner.run(root_folder=None, files=[valid_plan_path], external_checks_dir=None,
-                            runner_filter=RunnerFilter(framework='all'))
+        report = runner.run(
+            root_folder=None,
+            files=[valid_plan_path],
+            external_checks_dir=None,
+            runner_filter=RunnerFilter(framework="all"),
+        )
         report_json = report.get_json()
         self.assertTrue(isinstance(report_json, str))
         self.assertIsNotNone(report_json)
@@ -110,12 +125,16 @@ class TestRunnerValid(unittest.TestCase):
         # This test verifies that such a circumstance stops occurring
         # There is a EKS Managed Resource and a EKS Data Resource
         # The EKS Managed Resource should have 4 failures corresponding with EKS checks.
-        # The EKS Data Resource should not be scanned. Previously this would cause 8 failures. 
+        # The EKS Data Resource should not be scanned. Previously this would cause 8 failures.
         current_dir = os.path.dirname(os.path.realpath(__file__))
         valid_plan_path = current_dir + "/resources/plan_data_resource_partial_values/tfplan.json"
         runner = Runner()
-        report = runner.run(root_folder=None, files=[valid_plan_path], external_checks_dir=None,
-                            runner_filter=RunnerFilter(framework='all'))
+        report = runner.run(
+            root_folder=None,
+            files=[valid_plan_path],
+            external_checks_dir=None,
+            runner_filter=RunnerFilter(framework="all"),
+        )
         report_json = report.get_json()
         self.assertTrue(isinstance(report_json, str))
         self.assertIsNotNone(report_json)
@@ -141,8 +160,9 @@ class TestRunnerValid(unittest.TestCase):
         current_dir = os.path.dirname(os.path.realpath(__file__))
         root_dir = current_dir + "/resources"
         runner = Runner()
-        report = runner.run(root_folder=root_dir, files=None, external_checks_dir=None,
-                            runner_filter=RunnerFilter(framework='all'))
+        report = runner.run(
+            root_folder=root_dir, files=None, external_checks_dir=None, runner_filter=RunnerFilter(framework="all")
+        )
         report_json = report.get_json()
         self.assertTrue(isinstance(report_json, str))
         self.assertIsNotNone(report_json)
@@ -168,9 +188,12 @@ class TestRunnerValid(unittest.TestCase):
         dir_rel_path = os.path.relpath(scan_dir_path)
 
         runner = Runner()
-        checks_allowlist = ['CKV_AWS_20']
-        report = runner.run(root_folder=dir_rel_path, external_checks_dir=None,
-                            runner_filter=RunnerFilter(framework='terraform', checks=checks_allowlist))
+        checks_allowlist = ["CKV_AWS_20"]
+        report = runner.run(
+            root_folder=dir_rel_path,
+            external_checks_dir=None,
+            runner_filter=RunnerFilter(framework="terraform", checks=checks_allowlist),
+        )
 
         all_checks = report.failed_checks + report.passed_checks
         for record in all_checks:
@@ -188,9 +211,12 @@ class TestRunnerValid(unittest.TestCase):
         dir_abs_path = os.path.abspath(scan_dir_path)
 
         runner = Runner()
-        checks_allowlist = ['CKV_AWS_20']
-        report = runner.run(root_folder=dir_abs_path, external_checks_dir=None,
-                            runner_filter=RunnerFilter(framework='terraform', checks=checks_allowlist))
+        checks_allowlist = ["CKV_AWS_20"]
+        report = runner.run(
+            root_folder=dir_abs_path,
+            external_checks_dir=None,
+            runner_filter=RunnerFilter(framework="terraform", checks=checks_allowlist),
+        )
 
         all_checks = report.failed_checks + report.passed_checks
         for record in all_checks:
@@ -209,9 +235,13 @@ class TestRunnerValid(unittest.TestCase):
         file_rel_path = os.path.relpath(scan_file_path)
 
         runner = Runner()
-        checks_allowlist = ['CKV_AWS_20']
-        report = runner.run(root_folder=None, external_checks_dir=None, files=[file_rel_path],
-                            runner_filter=RunnerFilter(framework='terraform', checks=checks_allowlist))
+        checks_allowlist = ["CKV_AWS_20"]
+        report = runner.run(
+            root_folder=None,
+            external_checks_dir=None,
+            files=[file_rel_path],
+            runner_filter=RunnerFilter(framework="terraform", checks=checks_allowlist),
+        )
 
         all_checks = report.failed_checks + report.passed_checks
         for record in all_checks:
@@ -229,22 +259,51 @@ class TestRunnerValid(unittest.TestCase):
         file_abs_path = os.path.abspath(scan_file_path)
 
         runner = Runner()
-        checks_allowlist = ['CKV_AWS_20']
-        report = runner.run(root_folder=None, external_checks_dir=None, files=[file_abs_path],
-                            runner_filter=RunnerFilter(framework='terraform', checks=checks_allowlist))
+        checks_allowlist = ["CKV_AWS_20"]
+        report = runner.run(
+            root_folder=None,
+            external_checks_dir=None,
+            files=[file_abs_path],
+            runner_filter=RunnerFilter(framework="terraform", checks=checks_allowlist),
+        )
 
         all_checks = report.failed_checks + report.passed_checks
         for record in all_checks:
             # The plan runner sets file_path to be relative from the CWD already, so this is easy
             self.assertEqual(record.repo_file_path, record.file_path)
 
-
     def test_runner_unexpected_eks_node_group_remote_access(self):
         current_dir = os.path.dirname(os.path.realpath(__file__))
         valid_plan_path = current_dir + "/resources/unexpected/eks_node_group_remote_access.json"
         runner = Runner()
-        report = runner.run(root_folder=None, files=[valid_plan_path], external_checks_dir=None,
-                            runner_filter=RunnerFilter(framework='all'))
+        report = runner.run(
+            root_folder=None,
+            files=[valid_plan_path],
+            external_checks_dir=None,
+            runner_filter=RunnerFilter(framework="all"),
+        )
+        report_json = report.get_json()
+        self.assertTrue(isinstance(report_json, str))
+        self.assertIsNotNone(report_json)
+        self.assertIsNotNone(report.get_test_suites())
+        self.assertEqual(report.get_exit_code(soft_fail=False), 0)
+        self.assertEqual(report.get_exit_code(soft_fail=True), 0)
+
+        self.assertEqual(report.get_summary()["failed"], 0)
+        self.assertEqual(report.get_summary()["passed"], 1)
+
+    def test_runner_with_resource_reference(self):
+        current_dir = os.path.dirname(os.path.realpath(__file__))
+        valid_plan_path = current_dir + "/resources/plan_with_resource_reference/tfplan.json"
+        allowed_checks = ["CKV_AWS_84"]
+
+        report = Runner().run(
+            root_folder=None,
+            files=[valid_plan_path],
+            external_checks_dir=None,
+            runner_filter=RunnerFilter(framework="all", checks=allowed_checks),
+        )
+
         report_json = report.get_json()
         self.assertTrue(isinstance(report_json, str))
         self.assertIsNotNone(report_json)
@@ -255,5 +314,6 @@ class TestRunnerValid(unittest.TestCase):
         self.assertEqual(report.get_summary()["failed"], 0)
         self.assertEqual(report.get_summary()["passed"], 1)
 
-if __name__ == '__main__':
+
+if __name__ == "__main__":
     unittest.main()