prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  CKV_AWS_40: failure even when not setting users
  **Describe the issue**
  The check fails when executing checkov on Terraform plan's JSON output.
  
  **Examples**
  ```
  resource "aws_iam_policy_attachment" "attachment" {
    ...
    roles = [...]
    # no users
  }
  ```
  JSON:
  ```
  {
    "address": "aws_iam_policy_attachment.attachment",
    ...
    "values": {
      ...
      "roles": [
        "data-analytics@eng-0"
      ],
      "users": []
    },
  ...
  ```
  The `users` field is set to `[]` in JSON, and the [check implementation](https://github.com/bridgecrewio/checkov/blob/e2538c48df14363d6ed46e5b838e19cc71ba6cbf/checkov/terraform/checks/resource/base_resource_negative_value_check.py#L39-L53) doesn't handle this scenario correctly:
  
  https://github.com/bridgecrewio/checkov/blob/e2538c48df14363d6ed46e5b838e19cc71ba6cbf/checkov/terraform/checks/resource/base_resource_negative_value_check.py#L39-L53
  
  **Version (please complete the following information):**
  ```
  > checkov --version
  2.0.780
  ```
  
  I saw there are tests for the check implementation, but only targeting Terraform source files. Are there tests targeting JSON output from Terraform plan?
  
  </issue>
  <code>
  [start of checkov/terraform/checks/resource/base_resource_negative_value_check.py]
  1 from abc import abstractmethod
  2 from collections.abc import Iterable
  3 from typing import List, Dict, Any, Optional
  4 
  5 import dpath
  6 
  7 from checkov.common.models.consts import ANY_VALUE
  8 from checkov.common.models.enums import CheckResult, CheckCategories
  9 from checkov.common.util.type_forcers import force_list
  10 from checkov.terraform.checks.resource.base_resource_check import BaseResourceCheck
  11 from checkov.terraform.graph_builder.utils import get_referenced_vertices_in_value
  12 from checkov.terraform.parser_functions import handle_dynamic_values
  13 
  14 
  15 class BaseResourceNegativeValueCheck(BaseResourceCheck):
  16     def __init__(
  17         self,
  18         name: str,
  19         id: str,
  20         categories: "Iterable[CheckCategories]",
  21         supported_resources: "Iterable[str]",
  22         missing_attribute_result: CheckResult = CheckResult.PASSED,
  23     ) -> None:
  24         super().__init__(name=name, id=id, categories=categories, supported_resources=supported_resources)
  25         self.missing_attribute_result = missing_attribute_result
  26 
  27     def scan_resource_conf(self, conf: Dict[str, List[Any]]) -> CheckResult:
  28         handle_dynamic_values(conf)
  29 
  30         excluded_key = self.get_excluded_key()
  31         if excluded_key is not None:
  32             if dpath.search(conf, excluded_key) != {}:
  33                 value = dpath.get(conf, excluded_key)
  34                 if isinstance(value, list) and len(value) == 1:
  35                     value = value[0]
  36                 if self.check_excluded_condition(value):
  37                     return CheckResult.PASSED
  38 
  39         inspected_key = self.get_inspected_key()
  40         bad_values = self.get_forbidden_values()
  41         if dpath.search(conf, inspected_key) != {}:
  42             value = dpath.get(conf, inspected_key)
  43             if isinstance(value, list) and len(value) == 1:
  44                 value = value[0]
  45             if get_referenced_vertices_in_value(value=value, aliases={}, resources_types=[]):
  46                 # we don't provide resources_types as we want to stay provider agnostic
  47                 return CheckResult.UNKNOWN
  48             if value is None:
  49                 return self.missing_attribute_result
  50             if value in bad_values or ANY_VALUE in bad_values:
  51                 return CheckResult.FAILED
  52             else:
  53                 return CheckResult.PASSED
  54 
  55         return self.missing_attribute_result
  56 
  57     @abstractmethod
  58     def get_inspected_key(self) -> str:
  59         """
  60         :return: JSONPath syntax path of the checked attribute
  61         """
  62         raise NotImplementedError()
  63 
  64     @abstractmethod
  65     def get_forbidden_values(self) -> List[Any]:
  66         """
  67         Returns a list of vulnerable values for the inspected key, governed by provider best practices
  68         """
  69         raise NotImplementedError()
  70 
  71     def get_excluded_key(self) -> Optional[str]:
  72         """
  73         :return: JSONPath syntax path of the an attribute that provides exclusion condition for the inspected key
  74         """
  75         return None
  76 
  77     def check_excluded_condition(self, value: str) -> bool:
  78         """
  79         :param:  value: value for  excluded_key
  80         :return: True if the value should exclude the check from failing if the inspected key has a bad value
  81         """
  82         return False
  83 
  84     def get_evaluated_keys(self) -> List[str]:
  85         return force_list(self.get_inspected_key())
  86
  [end of checkov/terraform/checks/resource/base_resource_negative_value_check.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/checkov/terraform/checks/resource/base_resource_negative_value_check.py b/checkov/terraform/checks/resource/base_resource_negative_value_check.py
  --- a/checkov/terraform/checks/resource/base_resource_negative_value_check.py
  +++ b/checkov/terraform/checks/resource/base_resource_negative_value_check.py
  @@ -42,11 +42,11 @@
               value = dpath.get(conf, inspected_key)
               if isinstance(value, list) and len(value) == 1:
                   value = value[0]
  +            if value is None or (isinstance(value, list) and not value):
  +                return self.missing_attribute_result
               if get_referenced_vertices_in_value(value=value, aliases={}, resources_types=[]):
                   # we don't provide resources_types as we want to stay provider agnostic
                   return CheckResult.UNKNOWN
  -            if value is None:
  -                return self.missing_attribute_result
               if value in bad_values or ANY_VALUE in bad_values:
                   return CheckResult.FAILED
               else:
  
verification_info: {"golden_diff": "diff --git a/checkov/terraform/checks/resource/base_resource_negative_value_check.py b/checkov/terraform/checks/resource/base_resource_negative_value_check.py\n--- a/checkov/terraform/checks/resource/base_resource_negative_value_check.py\n+++ b/checkov/terraform/checks/resource/base_resource_negative_value_check.py\n@@ -42,11 +42,11 @@\n             value = dpath.get(conf, inspected_key)\n             if isinstance(value, list) and len(value) == 1:\n                 value = value[0]\n+            if value is None or (isinstance(value, list) and not value):\n+                return self.missing_attribute_result\n             if get_referenced_vertices_in_value(value=value, aliases={}, resources_types=[]):\n                 # we don't provide resources_types as we want to stay provider agnostic\n                 return CheckResult.UNKNOWN\n-            if value is None:\n-                return self.missing_attribute_result\n             if value in bad_values or ANY_VALUE in bad_values:\n                 return CheckResult.FAILED\n             else:\n", "issue": "CKV_AWS_40: failure even when not setting users\n**Describe the issue**\r\nThe check fails when executing checkov on Terraform plan's JSON output.\r\n\r\n**Examples**\r\n```\r\nresource \"aws_iam_policy_attachment\" \"attachment\" {\r\n  ...\r\n  roles = [...]\r\n  # no users\r\n}\r\n```\r\nJSON:\r\n```\r\n{\r\n  \"address\": \"aws_iam_policy_attachment.attachment\",\r\n  ...\r\n  \"values\": {\r\n    ...\r\n    \"roles\": [\r\n      \"data-analytics@eng-0\"\r\n    ],\r\n    \"users\": []\r\n  },\r\n...\r\n```\r\nThe `users` field is set to `[]` in JSON, and the [check implementation](https://github.com/bridgecrewio/checkov/blob/e2538c48df14363d6ed46e5b838e19cc71ba6cbf/checkov/terraform/checks/resource/base_resource_negative_value_check.py#L39-L53) doesn't handle this scenario correctly:\r\n\r\nhttps://github.com/bridgecrewio/checkov/blob/e2538c48df14363d6ed46e5b838e19cc71ba6cbf/checkov/terraform/checks/resource/base_resource_negative_value_check.py#L39-L53\r\n\r\n**Version (please complete the following information):**\r\n```\r\n> checkov --version\r\n2.0.780\r\n```\r\n\r\nI saw there are tests for the check implementation, but only targeting Terraform source files. Are there tests targeting JSON output from Terraform plan?\n", "before_files": [{"content": "from abc import abstractmethod\nfrom collections.abc import Iterable\nfrom typing import List, Dict, Any, Optional\n\nimport dpath\n\nfrom checkov.common.models.consts import ANY_VALUE\nfrom checkov.common.models.enums import CheckResult, CheckCategories\nfrom checkov.common.util.type_forcers import force_list\nfrom checkov.terraform.checks.resource.base_resource_check import BaseResourceCheck\nfrom checkov.terraform.graph_builder.utils import get_referenced_vertices_in_value\nfrom checkov.terraform.parser_functions import handle_dynamic_values\n\n\nclass BaseResourceNegativeValueCheck(BaseResourceCheck):\n    def __init__(\n        self,\n        name: str,\n        id: str,\n        categories: \"Iterable[CheckCategories]\",\n        supported_resources: \"Iterable[str]\",\n        missing_attribute_result: CheckResult = CheckResult.PASSED,\n    ) -> None:\n        super().__init__(name=name, id=id, categories=categories, supported_resources=supported_resources)\n        self.missing_attribute_result = missing_attribute_result\n\n    def scan_resource_conf(self, conf: Dict[str, List[Any]]) -> CheckResult:\n        handle_dynamic_values(conf)\n\n        excluded_key = self.get_excluded_key()\n        if excluded_key is not None:\n            if dpath.search(conf, excluded_key) != {}:\n                value = dpath.get(conf, excluded_key)\n                if isinstance(value, list) and len(value) == 1:\n                    value = value[0]\n                if self.check_excluded_condition(value):\n                    return CheckResult.PASSED\n\n        inspected_key = self.get_inspected_key()\n        bad_values = self.get_forbidden_values()\n        if dpath.search(conf, inspected_key) != {}:\n            value = dpath.get(conf, inspected_key)\n            if isinstance(value, list) and len(value) == 1:\n                value = value[0]\n            if get_referenced_vertices_in_value(value=value, aliases={}, resources_types=[]):\n                # we don't provide resources_types as we want to stay provider agnostic\n                return CheckResult.UNKNOWN\n            if value is None:\n                return self.missing_attribute_result\n            if value in bad_values or ANY_VALUE in bad_values:\n                return CheckResult.FAILED\n            else:\n                return CheckResult.PASSED\n\n        return self.missing_attribute_result\n\n    @abstractmethod\n    def get_inspected_key(self) -> str:\n        \"\"\"\n        :return: JSONPath syntax path of the checked attribute\n        \"\"\"\n        raise NotImplementedError()\n\n    @abstractmethod\n    def get_forbidden_values(self) -> List[Any]:\n        \"\"\"\n        Returns a list of vulnerable values for the inspected key, governed by provider best practices\n        \"\"\"\n        raise NotImplementedError()\n\n    def get_excluded_key(self) -> Optional[str]:\n        \"\"\"\n        :return: JSONPath syntax path of the an attribute that provides exclusion condition for the inspected key\n        \"\"\"\n        return None\n\n    def check_excluded_condition(self, value: str) -> bool:\n        \"\"\"\n        :param:  value: value for  excluded_key\n        :return: True if the value should exclude the check from failing if the inspected key has a bad value\n        \"\"\"\n        return False\n\n    def get_evaluated_keys(self) -> List[str]:\n        return force_list(self.get_inspected_key())\n", "path": "checkov/terraform/checks/resource/base_resource_negative_value_check.py"}]}