From b14c800e489fb5c158bb51baa7dff22faefe4ff9 Mon Sep 17 00:00:00 2001 From: tronxd Date: Thu, 9 Mar 2023 14:14:02 +0200 Subject: [PATCH 01/11] encode/decode TFDefinitionsKey/TFModule classes --- checkov/common/__init__.py | 1 + checkov/common/util/json_utils.py | 50 +++++++++++++++++++ checkov/terraform/modules/module_objects.py | 46 +++++++++++++++-- checkov/terraform/modules/module_utils.py | 4 +- tests/terraform/parser/test_module.py | 30 +++++++++++ .../parser/test_new_parser_modules.py | 1 - 6 files changed, 126 insertions(+), 6 deletions(-) diff --git a/checkov/common/__init__.py b/checkov/common/__init__.py index e69de29bb2d..98b75088f9a 100644 --- a/checkov/common/__init__.py +++ b/checkov/common/__init__.py @@ -0,0 +1 @@ +from checkov.common.models import * # noqa diff --git a/checkov/common/util/json_utils.py b/checkov/common/util/json_utils.py index 06ffaf4a2de..88ef83c82c4 100644 --- a/checkov/common/util/json_utils.py +++ b/checkov/common/util/json_utils.py @@ -8,6 +8,8 @@ from checkov.common.bridgecrew.severities import Severity from checkov.common.output.common import ImageDetails from checkov.common.packaging.version import LegacyVersion, Version +from checkov.terraform.modules.module_objects import TFModule, TFDefinitionKey +from checkov.common.util.consts import RESOLVED_MODULE_ENTRY_NAME type_of_function = type(lambda x: x) @@ -30,9 +32,57 @@ def default(self, o: Any) -> Any: return o.__dict__ elif isinstance(o, type_of_function): return str(o) + elif isinstance(o, TFDefinitionKey): + return str(o) + elif isinstance(o, TFModule): + return str(o) else: return json.JSONEncoder.default(self, o) + def encode(self, obj): + return super().encode(self._encode(obj)) + + def _encode(self, obj): + if isinstance(obj, dict): + return {self.encode_key(k): v for k, v in obj.items()} + else: + return obj + + @staticmethod + def encode_key(key): + if isinstance(key, TFDefinitionKey): + return str(key) + if isinstance(key, TFModule): + return str(key) + else: + return key + + +def object_hook(dct): + try: + if dct is None: + return None + if isinstance(dct, dict): + for key, value in dct.items(): + if key == RESOLVED_MODULE_ENTRY_NAME: + resolved_classes = [] + for resolved_module in dct[RESOLVED_MODULE_ENTRY_NAME]: + resolved_classes.append(object_hook(json.loads(resolved_module))) + dct[RESOLVED_MODULE_ENTRY_NAME] = resolved_classes + if 'tf_source_modules' in key and 'file_path' in key: + tf_definition_key = json.loads(key) + del dct[key] + dct[TFDefinitionKey(file_path=tf_definition_key["file_path"], tf_source_modules=object_hook( + tf_definition_key["tf_source_modules"]))] = object_hook(value) + if 'tf_source_modules' in dct and 'file_path' in dct: + return TFDefinitionKey(file_path=dct["file_path"], tf_source_modules=object_hook(dct["tf_source_modules"])) + if 'path' in dct and 'name' in dct and 'foreach_idx' in dct and 'nested_tf_module' in dct: + return TFModule(path=dct['path'], name=dct['name'], foreach_idx=dct['foreach_idx'], + nested_tf_module=object_hook(dct['nested_tf_module'])) + return dct + except (KeyError, TypeError) as e: + return dct + def get_jsonpath_from_evaluated_key(evaluated_key: str) -> JSONPath: evaluated_key = evaluated_key.replace("/", ".") diff --git a/checkov/terraform/modules/module_objects.py b/checkov/terraform/modules/module_objects.py index b8c230f7462..d324c9a6a2b 100644 --- a/checkov/terraform/modules/module_objects.py +++ b/checkov/terraform/modules/module_objects.py @@ -1,12 +1,13 @@ from __future__ import annotations - +import json from typing import Optional, Any class TFModule: __slots__ = ("path", "name", "foreach_idx", "nested_tf_module") - def __init__(self, path: str, name: str, nested_tf_module: Optional[TFModule] = None, foreach_idx: Optional[int | str] = None) -> None: + def __init__(self, path: str, name: str, nested_tf_module: Optional[TFModule] = None, + foreach_idx: Optional[int | str] = None) -> None: self.path = path self.name = name self.foreach_idx = foreach_idx @@ -20,7 +21,8 @@ def __eq__(self, other: Any) -> bool: def __lt__(self, other: Any) -> bool: if not isinstance(other, TFModule): return False - return (self.path, self.name, self.nested_tf_module, self.foreach_idx) < (other.path, other.name, other.nested_tf_module, other.foreach_idx) + return (self.path, self.name, self.nested_tf_module, self.foreach_idx) < ( + other.path, other.name, other.nested_tf_module, other.foreach_idx) def __repr__(self) -> str: return f'path:{self.path}, name:{self.name}, nested_tf_module:{self.nested_tf_module}, foreach_idx:{self.foreach_idx}' @@ -28,6 +30,23 @@ def __repr__(self) -> str: def __hash__(self) -> int: return hash((self.path, self.name, self.nested_tf_module, self.foreach_idx)) + def __iter__(self): + yield from { + "path": self.path, + "name": self.name, + "foreach_idx": self.foreach_idx, + "nested_tf_module": dict(self.nested_tf_module) if self.nested_tf_module else None + }.items() + + def __str__(self): + from checkov.common.util.json_utils import CustomJSONEncoder + return json.dumps(dict(self), cls=CustomJSONEncoder) + + @staticmethod + def from_json(json_dct): + return TFModule(path=json_dct['path'], name=json_dct['name'], foreach_idx=json_dct['foreach_idx'], + nested_tf_module=TFModule.from_json(json_dct['nested_tf_module'])) + class TFDefinitionKey: __slots__ = ("tf_source_modules", "file_path") @@ -51,3 +70,24 @@ def __repr__(self) -> str: def __hash__(self) -> int: return hash((self.file_path, self.tf_source_modules)) + + def __iter__(self): + yield from { + "file_path": self.file_path, + "tf_source_modules": dict(self.tf_source_modules) + }.items() + + def __str__(self): + from checkov.common.util.json_utils import CustomJSONEncoder + return json.dumps(self.to_json(), cls=CustomJSONEncoder) + + def to_json(self): + to_return = {"file_path": self.file_path, "tf_source_modules": None} + if self.tf_source_modules: + to_return["tf_source_modules"] = dict(self.tf_source_modules) + return to_return + + @staticmethod + def from_json(json_dct): + return TFDefinitionKey(file_path=json_dct['file_path'], + tf_source_modules=TFModule.from_json(json_dct['tf_source_modules'])) diff --git a/checkov/terraform/modules/module_utils.py b/checkov/terraform/modules/module_utils.py index f68fee82b39..0101f8ecdb8 100644 --- a/checkov/terraform/modules/module_utils.py +++ b/checkov/terraform/modules/module_utils.py @@ -15,7 +15,7 @@ import re from checkov.common.util.consts import DEFAULT_EXTERNAL_MODULES_DIR -from checkov.common.util.json_utils import CustomJSONEncoder +from checkov.common.util.json_utils import CustomJSONEncoder, object_hook if TYPE_CHECKING: from typing_extensions import TypeAlias @@ -285,4 +285,4 @@ def clean_parser_types_lst(values: list[Any]) -> list[Any]: def serialize_definitions(tf_definitions: dict[str, _Hcl2Payload]) -> dict[str, _Hcl2Payload]: - return json.loads(json.dumps(tf_definitions, cls=CustomJSONEncoder)) + return json.loads(json.dumps(tf_definitions, cls=CustomJSONEncoder), object_hook=object_hook) diff --git a/tests/terraform/parser/test_module.py b/tests/terraform/parser/test_module.py index cf144812906..a84d969b437 100644 --- a/tests/terraform/parser/test_module.py +++ b/tests/terraform/parser/test_module.py @@ -1,13 +1,30 @@ import os import unittest +import shutil import hcl2 from checkov.terraform.modules.module_utils import validate_malformed_definitions, clean_bad_definitions from checkov.terraform.parser import Parser +from checkov.terraform.tf_parser import TFParser +from checkov.common.util.consts import DEFAULT_EXTERNAL_MODULES_DIR class ModuleTest(unittest.TestCase): + + def setUp(self) -> None: + from checkov.terraform.module_loading.registry import ModuleLoaderRegistry + + # needs to be reset, because the cache belongs to the class not instance + ModuleLoaderRegistry.module_content_cache = {} + + self.resources_dir = os.path.realpath(os.path.join(os.path.dirname(os.path.realpath(__file__)), "./resources")) + self.external_module_path = '' + + def tearDown(self) -> None: + if os.path.exists(self.external_module_path): + shutil.rmtree(self.external_module_path) + def test_module_double_slash_cleanup(self): with open(os.path.join(os.path.dirname(__file__), 'resources', 'double_slash.tf')) as f: tf = hcl2.load(f) @@ -41,3 +58,16 @@ def test_module_double_slash_cleanup_string(self): print(module) self.assertEqual(1, len(module.blocks)) self.assertEqual('ingress.annotations.kubernetes\\.io/ingress\\.class', module.blocks[0].attributes['set.name']) + + def test_parse_hcl_module_new_parser(self): + parser = TFParser() + directory = os.path.join(self.resources_dir, "registry_security_group_inner_module") + self.external_module_path = os.path.join(directory, DEFAULT_EXTERNAL_MODULES_DIR) + out_definitions = parser.parse_hcl_module( + directory, + "terraform", + download_external_modules=True + ) + # check that only the original file was parsed successfully without getting bad external modules + self.assertEqual(1, len(list(out_definitions.keys()))) + diff --git a/tests/terraform/parser/test_new_parser_modules.py b/tests/terraform/parser/test_new_parser_modules.py index 9278a21cde5..24077ae53e4 100644 --- a/tests/terraform/parser/test_new_parser_modules.py +++ b/tests/terraform/parser/test_new_parser_modules.py @@ -2,7 +2,6 @@ import shutil import unittest from pathlib import Path -from unittest import mock import pytest From 1f43f92bfcc928c1bbfae1dcb0341383bc169f74 Mon Sep 17 00:00:00 2001 From: tronxd Date: Thu, 9 Mar 2023 17:25:30 +0200 Subject: [PATCH 02/11] encode/decode TFDefinitionsKey/TFModule classes --- checkov/common/util/json_utils.py | 31 ++++++++++++++++----------- tests/terraform/parser/test_module.py | 2 +- 2 files changed, 20 insertions(+), 13 deletions(-) diff --git a/checkov/common/util/json_utils.py b/checkov/common/util/json_utils.py index 88ef83c82c4..089f3b932bf 100644 --- a/checkov/common/util/json_utils.py +++ b/checkov/common/util/json_utils.py @@ -1,5 +1,7 @@ import datetime import json +from copy import deepcopy +from json import JSONDecodeError from typing import Any from lark import Tree @@ -63,24 +65,29 @@ def object_hook(dct): if dct is None: return None if isinstance(dct, dict): + dct_obj = deepcopy(dct) + if 'tf_source_modules' in dct and 'file_path' in dct: + return TFDefinitionKey(file_path=dct["file_path"], + tf_source_modules=object_hook(dct["tf_source_modules"])) + if 'path' in dct and 'name' in dct and 'foreach_idx' in dct and 'nested_tf_module' in dct: + return TFModule(path=dct['path'], name=dct['name'], foreach_idx=dct['foreach_idx'], + nested_tf_module=object_hook(dct['nested_tf_module'])) for key, value in dct.items(): if key == RESOLVED_MODULE_ENTRY_NAME: resolved_classes = [] for resolved_module in dct[RESOLVED_MODULE_ENTRY_NAME]: - resolved_classes.append(object_hook(json.loads(resolved_module))) - dct[RESOLVED_MODULE_ENTRY_NAME] = resolved_classes - if 'tf_source_modules' in key and 'file_path' in key: + if isinstance(resolved_module, str): + resolved_classes.append(object_hook(json.loads(resolved_module))) + dct_obj[RESOLVED_MODULE_ENTRY_NAME] = resolved_classes + if isinstance(key, str) and 'tf_source_modules' in key and 'file_path' in key: tf_definition_key = json.loads(key) - del dct[key] - dct[TFDefinitionKey(file_path=tf_definition_key["file_path"], tf_source_modules=object_hook( - tf_definition_key["tf_source_modules"]))] = object_hook(value) - if 'tf_source_modules' in dct and 'file_path' in dct: - return TFDefinitionKey(file_path=dct["file_path"], tf_source_modules=object_hook(dct["tf_source_modules"])) - if 'path' in dct and 'name' in dct and 'foreach_idx' in dct and 'nested_tf_module' in dct: - return TFModule(path=dct['path'], name=dct['name'], foreach_idx=dct['foreach_idx'], - nested_tf_module=object_hook(dct['nested_tf_module'])) + tf_definition_key_obj = TFDefinitionKey(file_path=tf_definition_key["file_path"], tf_source_modules=object_hook( + tf_definition_key["tf_source_modules"])) + dct_obj[tf_definition_key_obj] = value + del dct_obj[key] + return dct_obj return dct - except (KeyError, TypeError) as e: + except (KeyError, TypeError, JSONDecodeError): return dct diff --git a/tests/terraform/parser/test_module.py b/tests/terraform/parser/test_module.py index a84d969b437..09de667f71e 100644 --- a/tests/terraform/parser/test_module.py +++ b/tests/terraform/parser/test_module.py @@ -61,7 +61,7 @@ def test_module_double_slash_cleanup_string(self): def test_parse_hcl_module_new_parser(self): parser = TFParser() - directory = os.path.join(self.resources_dir, "registry_security_group_inner_module") + directory = os.path.join(self.resources_dir, "parser_nested_modules") self.external_module_path = os.path.join(directory, DEFAULT_EXTERNAL_MODULES_DIR) out_definitions = parser.parse_hcl_module( directory, From f6c45c429423454324dae5523cbebc2b5c5d72c1 Mon Sep 17 00:00:00 2001 From: tronxd Date: Mon, 13 Mar 2023 11:50:28 +0200 Subject: [PATCH 03/11] encode/decode TFDefinitionsKey/TFModule classes --- checkov/terraform/modules/module_objects.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/checkov/terraform/modules/module_objects.py b/checkov/terraform/modules/module_objects.py index d324c9a6a2b..52796b43f4c 100644 --- a/checkov/terraform/modules/module_objects.py +++ b/checkov/terraform/modules/module_objects.py @@ -74,7 +74,7 @@ def __hash__(self) -> int: def __iter__(self): yield from { "file_path": self.file_path, - "tf_source_modules": dict(self.tf_source_modules) + "tf_source_modules": dict(self.tf_source_modules) if self.tf_source_modules else None }.items() def __str__(self): From 00ff6b4cf5b1f98c3cf81052c60fb8d389d3cd9e Mon Sep 17 00:00:00 2001 From: tronxd Date: Mon, 13 Mar 2023 11:52:52 +0200 Subject: [PATCH 04/11] rm test --- tests/terraform/parser/test_module.py | 15 --------------- 1 file changed, 15 deletions(-) diff --git a/tests/terraform/parser/test_module.py b/tests/terraform/parser/test_module.py index 09de667f71e..5f37344c6dc 100644 --- a/tests/terraform/parser/test_module.py +++ b/tests/terraform/parser/test_module.py @@ -6,8 +6,6 @@ from checkov.terraform.modules.module_utils import validate_malformed_definitions, clean_bad_definitions from checkov.terraform.parser import Parser -from checkov.terraform.tf_parser import TFParser -from checkov.common.util.consts import DEFAULT_EXTERNAL_MODULES_DIR class ModuleTest(unittest.TestCase): @@ -58,16 +56,3 @@ def test_module_double_slash_cleanup_string(self): print(module) self.assertEqual(1, len(module.blocks)) self.assertEqual('ingress.annotations.kubernetes\\.io/ingress\\.class', module.blocks[0].attributes['set.name']) - - def test_parse_hcl_module_new_parser(self): - parser = TFParser() - directory = os.path.join(self.resources_dir, "parser_nested_modules") - self.external_module_path = os.path.join(directory, DEFAULT_EXTERNAL_MODULES_DIR) - out_definitions = parser.parse_hcl_module( - directory, - "terraform", - download_external_modules=True - ) - # check that only the original file was parsed successfully without getting bad external modules - self.assertEqual(1, len(list(out_definitions.keys()))) - From 892ecfb27ea1db282fbbd0c7b84a779b6039c93e Mon Sep 17 00:00:00 2001 From: tronxd Date: Mon, 13 Mar 2023 11:58:32 +0200 Subject: [PATCH 05/11] UT --- tests/terraform/parser/test_module.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/tests/terraform/parser/test_module.py b/tests/terraform/parser/test_module.py index 5f37344c6dc..acbadb3e39b 100644 --- a/tests/terraform/parser/test_module.py +++ b/tests/terraform/parser/test_module.py @@ -4,8 +4,11 @@ import hcl2 -from checkov.terraform.modules.module_utils import validate_malformed_definitions, clean_bad_definitions +from checkov.terraform.modules.module_utils import validate_malformed_definitions, clean_bad_definitions, \ + clean_parser_types, serialize_definitions from checkov.terraform.parser import Parser +from checkov.terraform.tf_parser import TFParser +from checkov.common.util.consts import DEFAULT_EXTERNAL_MODULES_DIR class ModuleTest(unittest.TestCase): @@ -56,3 +59,12 @@ def test_module_double_slash_cleanup_string(self): print(module) self.assertEqual(1, len(module.blocks)) self.assertEqual('ingress.annotations.kubernetes\\.io/ingress\\.class', module.blocks[0].attributes['set.name']) + + def test_parse_hcl_module_serialize_definitions(self): + parser = TFParser() + directory = os.path.join(self.resources_dir, "parser_nested_modules") + self.external_module_path = os.path.join(directory, DEFAULT_EXTERNAL_MODULES_DIR) + tf_definitions = parser.parse_directory(directory=directory, out_evaluations_context={}) + tf_definitions = clean_parser_types(tf_definitions) + tf_definitions_encoded = serialize_definitions(tf_definitions) + self.assertEqual(tf_definitions_encoded, tf_definitions) From ec4595ee5f15a3f54dd7116e0530d144f7df2d82 Mon Sep 17 00:00:00 2001 From: tronxd Date: Mon, 13 Mar 2023 12:15:04 +0200 Subject: [PATCH 06/11] UT --- checkov/common/util/json_utils.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/checkov/common/util/json_utils.py b/checkov/common/util/json_utils.py index 089f3b932bf..68ef416e62f 100644 --- a/checkov/common/util/json_utils.py +++ b/checkov/common/util/json_utils.py @@ -10,14 +10,13 @@ from checkov.common.bridgecrew.severities import Severity from checkov.common.output.common import ImageDetails from checkov.common.packaging.version import LegacyVersion, Version -from checkov.terraform.modules.module_objects import TFModule, TFDefinitionKey -from checkov.common.util.consts import RESOLVED_MODULE_ENTRY_NAME type_of_function = type(lambda x: x) class CustomJSONEncoder(json.JSONEncoder): def default(self, o: Any) -> Any: + from checkov.terraform.modules.module_objects import TFModule, TFDefinitionKey if isinstance(o, set): return list(o) elif isinstance(o, Tree): @@ -52,6 +51,7 @@ def _encode(self, obj): @staticmethod def encode_key(key): + from checkov.terraform.modules.module_objects import TFModule, TFDefinitionKey if isinstance(key, TFDefinitionKey): return str(key) if isinstance(key, TFModule): @@ -61,6 +61,8 @@ def encode_key(key): def object_hook(dct): + from checkov.terraform.modules.module_objects import TFModule, TFDefinitionKey + from checkov.common.util.consts import RESOLVED_MODULE_ENTRY_NAME try: if dct is None: return None From a561ce722d5748f2b8e4ba84d66e17704e05da7b Mon Sep 17 00:00:00 2001 From: tronxd Date: Mon, 13 Mar 2023 12:17:32 +0200 Subject: [PATCH 07/11] type hint --- checkov/common/util/json_utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/checkov/common/util/json_utils.py b/checkov/common/util/json_utils.py index 68ef416e62f..de3c5da39ce 100644 --- a/checkov/common/util/json_utils.py +++ b/checkov/common/util/json_utils.py @@ -2,7 +2,7 @@ import json from copy import deepcopy from json import JSONDecodeError -from typing import Any +from typing import Any, Dict from lark import Tree from bc_jsonpath_ng import parse, JSONPath @@ -60,7 +60,7 @@ def encode_key(key): return key -def object_hook(dct): +def object_hook(dct: Dict[Any, Any]) -> Any: from checkov.terraform.modules.module_objects import TFModule, TFDefinitionKey from checkov.common.util.consts import RESOLVED_MODULE_ENTRY_NAME try: From 8b6fad03e650ebf653340f45325b128fa7aa848c Mon Sep 17 00:00:00 2001 From: tronxd Date: Mon, 13 Mar 2023 12:20:23 +0200 Subject: [PATCH 08/11] lint --- checkov/terraform/modules/module_objects.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/checkov/terraform/modules/module_objects.py b/checkov/terraform/modules/module_objects.py index 52796b43f4c..d893df90dce 100644 --- a/checkov/terraform/modules/module_objects.py +++ b/checkov/terraform/modules/module_objects.py @@ -22,7 +22,7 @@ def __lt__(self, other: Any) -> bool: if not isinstance(other, TFModule): return False return (self.path, self.name, self.nested_tf_module, self.foreach_idx) < ( - other.path, other.name, other.nested_tf_module, other.foreach_idx) + other.path, other.name, other.nested_tf_module, other.foreach_idx) def __repr__(self) -> str: return f'path:{self.path}, name:{self.name}, nested_tf_module:{self.nested_tf_module}, foreach_idx:{self.foreach_idx}' From 5c2c6c06d7ae5b1eb1f22561a0f0b2fa2c062af1 Mon Sep 17 00:00:00 2001 From: tronxd Date: Mon, 13 Mar 2023 12:23:35 +0200 Subject: [PATCH 09/11] mypy --- checkov/common/util/json_utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/checkov/common/util/json_utils.py b/checkov/common/util/json_utils.py index de3c5da39ce..5c794735fce 100644 --- a/checkov/common/util/json_utils.py +++ b/checkov/common/util/json_utils.py @@ -40,10 +40,10 @@ def default(self, o: Any) -> Any: else: return json.JSONEncoder.default(self, o) - def encode(self, obj): + def encode(self, obj: Any) -> str: return super().encode(self._encode(obj)) - def _encode(self, obj): + def _encode(self, obj: Any) -> Dict[Any, Any]: if isinstance(obj, dict): return {self.encode_key(k): v for k, v in obj.items()} else: From ee6bccdf4545736c4141237d33cc8745b7e594b0 Mon Sep 17 00:00:00 2001 From: tronxd Date: Mon, 13 Mar 2023 12:31:52 +0200 Subject: [PATCH 10/11] mypy --- checkov/common/util/json_utils.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/checkov/common/util/json_utils.py b/checkov/common/util/json_utils.py index 5c794735fce..23b5bc6726d 100644 --- a/checkov/common/util/json_utils.py +++ b/checkov/common/util/json_utils.py @@ -43,14 +43,14 @@ def default(self, o: Any) -> Any: def encode(self, obj: Any) -> str: return super().encode(self._encode(obj)) - def _encode(self, obj: Any) -> Dict[Any, Any]: + def _encode(self, obj: Any) -> Any: if isinstance(obj, dict): return {self.encode_key(k): v for k, v in obj.items()} else: return obj @staticmethod - def encode_key(key): + def encode_key(key: Any) -> str: from checkov.terraform.modules.module_objects import TFModule, TFDefinitionKey if isinstance(key, TFDefinitionKey): return str(key) From 39ba61b6856c5eff6e316fa4031a8fdf8a132c65 Mon Sep 17 00:00:00 2001 From: tronxd Date: Mon, 13 Mar 2023 13:37:27 +0200 Subject: [PATCH 11/11] mypy --- checkov/common/util/json_utils.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/checkov/common/util/json_utils.py b/checkov/common/util/json_utils.py index 23b5bc6726d..136980aca5c 100644 --- a/checkov/common/util/json_utils.py +++ b/checkov/common/util/json_utils.py @@ -50,7 +50,7 @@ def _encode(self, obj: Any) -> Any: return obj @staticmethod - def encode_key(key: Any) -> str: + def encode_key(key: Any) -> Any: from checkov.terraform.modules.module_objects import TFModule, TFDefinitionKey if isinstance(key, TFDefinitionKey): return str(key)