Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(general): Fix jsonpath-key handling for special characters like "/" and reduce log size #6907

Merged
merged 6 commits into from
Dec 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 0 additions & 12 deletions checkov/cloudformation/graph_builder/graph_components/blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,15 +92,3 @@ def _should_add_previous_breadcrumbs(change_origin_id: Optional[int],
@staticmethod
def _should_set_changed_attributes(change_origin_id: Optional[int], attribute_at_dest: Optional[str]) -> bool:
return change_origin_id is not None and attribute_at_dest is not None

def _handle_unique_key_characters(self, key: str) -> str:
# `::` is not a valid jsonpath character, but cloudformation have multiple functions like `Fn::If` which use it,
# so we solve it with escaping using parenthesis
key_parts = key.split(".")
updated_key = ""
for part in key_parts:
if part.startswith("Fn::"):
updated_key += f'"{part}"'
else:
updated_key += part
return updated_key
Original file line number Diff line number Diff line change
Expand Up @@ -536,9 +536,9 @@ def _handle_sub_with_pseudo_param(attr_key: str, attr_value: Any, vertex: Cloudf
try:
inner_value = json.loads(inner_value)
except Exception as e:
logging.warning(f"[Cloudformation_evaluate_non_rendered_values]- "
f"Inner_value - {inner_value} is not a valid json. "
f"Full exception - {str(e)}")
logging.debug(f"[Cloudformation_evaluate_non_rendered_values]- "
f"Inner_value - {inner_value} is not a valid json. "
f"Full exception - {str(e)}")
if is_pseudo_param_in_value:
vertex.update_attribute(
attribute_key=attr_key, attribute_value=inner_value, change_origin_id=None,
Expand Down
22 changes: 12 additions & 10 deletions checkov/common/graph/graph_builder/graph_components/blocks.py
Original file line number Diff line number Diff line change
Expand Up @@ -171,8 +171,8 @@ def update_attribute(
try:
self._update_attribute_based_on_jsonpath_key(attribute_value, key)
except Exception as e:
logging.debug(f"Failed updating attribute for key: {key} and value {attribute_value} for"
f"vertex attributes {self.attributes}. Falling back to explicitly setting it."
logging.debug(f"Failed updating attribute for key: {key} and value {attribute_value}."
f"Falling back to explicitly setting it."
f"Exception - {e}")
self.attributes[key] = attribute_value
else:
Expand Down Expand Up @@ -204,21 +204,23 @@ def _update_attribute_based_on_jsonpath_key(self, attribute_value: Any, key: str
match[0].value = attribute_value
return None

def _get_jsonpath_key(self, key: str) -> str:
key = self._handle_unique_key_characters(key)
# Replace .0 with [0] to match jsonpath style
@staticmethod
def _get_jsonpath_key(key: str) -> str:
jsonpath_key = "$."
key_parts = key.split(".")
updated_parts = []
for part in key_parts:
if part.isnumeric():
jsonpath_key += f"[{part}]"
updated_parts.append(f"[{part}]")
elif "/" in part or "::" in part:
updated_parts.append(f'"{part}"')
else:
jsonpath_key += part
updated_parts.append(part)
jsonpath_key += ".".join(updated_parts)
# Replace .0 with [0] to match jsonpath style
jsonpath_key = jsonpath_key.replace(".[", "[")
return jsonpath_key

def _handle_unique_key_characters(self, key: str) -> str:
return key

def update_inner_attribute(
self, attribute_key: str, nested_attributes: list[Any] | dict[str, Any], value_to_update: Any
) -> None:
Expand Down
15 changes: 15 additions & 0 deletions tests/common/graph/checks/test_block.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import pytest

from checkov.common.graph.graph_builder.graph_components.blocks import Block


@pytest.mark.parametrize("input_key, expected_key", (
("a.b", "$.a.b"),
("a.0", "$.a[0]"),
("a.0.b.1.2.c", "$.a[0].b[1][2].c"),
("a.0./mock-part-of-key.d.e.1", "$.a[0].\"/mock-part-of-key\".d.e[1]"),
("a.0.Fn::Region.d.e.1", "$.a[0].\"Fn::Region\".d.e[1]")
))
def test__get_jsonpath_key(input_key: str, expected_key: str) -> None:
result = Block._get_jsonpath_key(input_key)
assert result == expected_key
Loading