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

feat(kustomize): Support child k8s resources inside kustomize origin annotations #5328

Merged
merged 2 commits into from
Jul 13, 2023
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
11 changes: 10 additions & 1 deletion checkov/kubernetes/graph_builder/local_graph.py
Original file line number Diff line number Diff line change
Expand Up @@ -162,11 +162,20 @@ def _extract_nested_resources_recursive(conf: Dict[str, Any], all_resources: Lis
# resource does not contain all required fields and can not be associated with the pod
all_resources.append(conf)
return
template[PARENT_RESOURCE_KEY_NAME] = metadata.get('name', "")

parent_name = metadata.get('name', "")
template[PARENT_RESOURCE_KEY_NAME] = parent_name
if not template.get('kind'):
template['kind'] = DEFAULT_NESTED_RESOURCE_TYPE
if not template.get('apiVersion'):
template['apiVersion'] = conf.get('apiVersion')

template_metadata = template.get('metadata')
template_metadata[PARENT_RESOURCE_ID_KEY_NAME] = parent_name
annotations = metadata.get('annotations')
if annotations is not None and template_metadata is not None and 'annotations' not in template_metadata:
# Updates annotations to template as well to handle metadata added to the parent resource
template_metadata['annotations'] = annotations
spec.pop('template', None)
else:
template = {}
Expand Down
36 changes: 28 additions & 8 deletions checkov/kustomize/runner.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
from checkov.common.util.consts import START_LINE, END_LINE
from checkov.common.util.data_structures_utils import pickle_deepcopy
from checkov.common.util.type_forcers import convert_str_to_bool
from checkov.kubernetes.kubernetes_utils import create_check_result, get_resource_id, calculate_code_lines
from checkov.kubernetes.kubernetes_utils import create_check_result, get_resource_id, calculate_code_lines, \
PARENT_RESOURCE_ID_KEY_NAME
from checkov.kubernetes.runner import Runner as K8sRunner
from checkov.kubernetes.runner import _get_entity_abs_path
from checkov.kustomize.image_referencer.manager import KustomizeImageReferencerManager
Expand Down Expand Up @@ -134,8 +135,13 @@ def mutate_kubernetes_results(
file_path = realKustomizeEnvMetadata['filePath'][len(repo_dir):]

if self.checkov_allow_kustomize_file_edits:
caller_resource_id = resource_id
if PARENT_RESOURCE_ID_KEY_NAME in entity_conf:
caller_resource_id = entity_conf[PARENT_RESOURCE_ID_KEY_NAME]
caller_file_line_range, caller_file_path = self._get_caller_file_info(entity_context, k8_file,
k8_file_path, resource_id,
k8_file_path,
resource_id,
caller_resource_id,
root_folder)
code_lines = entity_context.get("code_lines")
file_line_range = self.line_range(code_lines)
Expand All @@ -153,7 +159,7 @@ def mutate_kubernetes_results(
return report

def _get_caller_file_info(self, entity_context: _EntityContext, k8_file: str, k8_file_path: str, resource_id: str,
root_folder: str | None) -> tuple[tuple[int, int] | None, str | None]:
caller_resource_id: str, root_folder: str | None) -> tuple[tuple[int, int] | None, str | None]:
origin_relative_path = entity_context.get('origin_relative_path')
if origin_relative_path is None:
return None, None
Expand All @@ -163,7 +169,7 @@ def _get_caller_file_info(self, entity_context: _EntityContext, k8_file: str, k8
if root_folder is None:
return None, caller_file_path
caller_file_line_range = self._get_caller_line_range(root_folder, k8_file, origin_relative_path,
resource_id)
resource_id, caller_resource_id)
return caller_file_line_range, caller_file_path

@staticmethod
Expand Down Expand Up @@ -205,17 +211,26 @@ def _remove_extra_path_parts(resolved_path: str, prefix: str) -> str:
return resolved_path

def _get_caller_line_range(self, root_folder: str, k8_file: str, origin_relative_path: str,
resource_id: str) -> tuple[int, int] | None:
resource_id: str, caller_resource_id: str) -> tuple[int, int] | None:
raw_caller_directory = (pathlib.Path(k8_file.lstrip(os.path.sep)).parent /
pathlib.Path(origin_relative_path.lstrip(os.path.sep)).parent)
caller_directory = str(pathlib.Path(f'{os.path.sep}{raw_caller_directory}').resolve())
caller_directory = K8sKustomizeRunner._remove_extra_path_parts(caller_directory, root_folder)
file_ending = pathlib.Path(origin_relative_path).suffix
caller_file_path = f'{str(pathlib.Path(caller_directory) / resource_id.replace(".", "-"))}{file_ending}'
caller_file_path = f'{str(pathlib.Path(caller_directory) / caller_resource_id.replace(".", "-"))}{file_ending}'

if caller_file_path not in self.definitions:
return None
caller_resource = self.definitions[caller_file_path][0]

caller_resource = None
for resource in self.definitions[caller_file_path]:
_resource_id = get_resource_id(resource)
if _resource_id == resource_id:
caller_resource = resource
break

if caller_resource is None:
return None

if caller_file_path not in self.definitions_raw:
# As we cannot calculate better lines with the `calculate_code_lines` without the raw code,
Expand Down Expand Up @@ -276,9 +291,14 @@ def mutate_kubernetes_graph_results(
caller_file_path = None
caller_file_line_range = None
if self.checkov_allow_kustomize_file_edits:
caller_resource_id = entity_id
if PARENT_RESOURCE_ID_KEY_NAME in entity:
caller_resource_id = entity[PARENT_RESOURCE_ID_KEY_NAME]
caller_file_line_range, caller_file_path = self._get_caller_file_info(entity_context,
entity_file_path,
entity_file_path, entity_id,
entity_file_path,
entity_id,
caller_resource_id,
root_folder)
code_lines = entity_context["code_lines"]
file_line_range = self.line_range(code_lines)
Expand Down
Loading