From 030c333fbd0c446e62779fd03cf896e94bbcd5a1 Mon Sep 17 00:00:00 2001 From: Omri Yoffe Date: Tue, 22 Oct 2024 14:32:11 +0300 Subject: [PATCH] implicit dependencies edges and tests --- checkov/arm/graph_builder/local_graph.py | 18 +++--- .../ImplicitDepsResources/interface.json | 37 +++++++++++ .../ImplicitDepsResources/storage.json | 61 +++++++++++++++++++ .../ImplicitDepsResources/subnet.json | 34 +++++++++++ tests/arm/graph_builder/test_local_graph.py | 35 +++++++---- 5 files changed, 163 insertions(+), 22 deletions(-) create mode 100644 tests/arm/examples/ImplicitDepsResources/interface.json create mode 100644 tests/arm/examples/ImplicitDepsResources/storage.json create mode 100644 tests/arm/examples/ImplicitDepsResources/subnet.json diff --git a/checkov/arm/graph_builder/local_graph.py b/checkov/arm/graph_builder/local_graph.py index cecd73cc5f1..06d5eccba82 100644 --- a/checkov/arm/graph_builder/local_graph.py +++ b/checkov/arm/graph_builder/local_graph.py @@ -131,27 +131,25 @@ def _create_edge(self, element_name: str, origin_vertex_index: int, label: str) @staticmethod def _extract_resource_name_from_resource_id_func(resource_id: str) -> str: # Extract name from resourceId function - return resource_id.split(',')[-1].split(')')[0] + return ArmLocalGraph._clean_string(resource_id.split(',')[-1].split(')')[0]) @staticmethod def _extract_resource_name_from_reference_func(reference: str) -> str: - resource_name = "".join(reference.split('reference(', 1)[1].split(')')[:-1]) + resource_name = ''.join(reference.split('reference(', 1)[1].split(')')[:-1]) if 'resourceId' in resource_name: - return "".join(resource_name.split('resourceId(', 1)[1].split(')')[:-1]).split(',')[-1] + return ArmLocalGraph._clean_string(''.join(resource_name.split('resourceId(', 1)[1].split(')')[0]).split(',')[-1]) else: - return resource_name.split(',')[0] + return ArmLocalGraph._clean_string(resource_name.split(',')[0].split('/')[-1]) + + @staticmethod + def _clean_string(input: str) -> str: + return input.replace("'", '').replace(" ", "") def _create_implicit_edges(self, origin_vertex_index: int, resource_name: str, d: dict[str, Any]) -> None: for key, value in d.items(): if isinstance(value, str): if 'reference' in value: self._create_implicit_edge(origin_vertex_index, resource_name, value) - elif isinstance(value, list): - for item in value: - if isinstance(item, str) and 'reference' in item: - self._create_implicit_edge(origin_vertex_index, resource_name, item) - elif isinstance(value, dict): - self._create_implicit_edges(origin_vertex_index, resource_name, value) def _create_implicit_edge(self, origin_vertex_index: int, resource_name: str, reference_string: str) -> None: dep_name = ArmLocalGraph._extract_resource_name_from_reference_func(reference_string) diff --git a/tests/arm/examples/ImplicitDepsResources/interface.json b/tests/arm/examples/ImplicitDepsResources/interface.json new file mode 100644 index 00000000000..1e93aa1202e --- /dev/null +++ b/tests/arm/examples/ImplicitDepsResources/interface.json @@ -0,0 +1,37 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [ + { + "type": "Microsoft.Network/publicIPAddresses", + "apiVersion": "2020-06-01", + "name": "PublicIP1", + "location": "westus", + "properties": { + "publicIPAllocationMethod": "Dynamic" + } + }, + { + "type": "Microsoft.Network/networkInterfaces", + "apiVersion": "2020-06-01", + "name": "NIC1", + "location": "westus", + "properties": { + "ipConfigurations": [ + { + "name": "ipconfig1", + "properties": { + "subnet": { + "id": "[reference(resourceId('Microsoft.Network/virtualNetworks', 'myVNet')).subnets[0].id]" + }, + "privateIPAllocationMethod": "Dynamic", + "publicIPAddress": { + "id": "[reference(resourceId('Microsoft.Network/publicIPAddresses', 'PublicIP1')).id]" + } + } + } + ] + } + } + ] + } \ No newline at end of file diff --git a/tests/arm/examples/ImplicitDepsResources/storage.json b/tests/arm/examples/ImplicitDepsResources/storage.json new file mode 100644 index 00000000000..0cf4c744849 --- /dev/null +++ b/tests/arm/examples/ImplicitDepsResources/storage.json @@ -0,0 +1,61 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [ + { + "type": "Microsoft.KeyVault/vaults", + "apiVersion": "2019-09-01", + "name": "myKeyVault", + "location": "westus", + "properties": { + "sku": { + "family": "A", + "name": "standard" + }, + "tenantId": "tenantId", + "accessPolicies": [] + }, + "resources": [ + { + "type": "secrets", + "name": "MySecret", + "apiVersion": "2019-09-01", + "properties": { + "value": "MySecretValue123" + } + } + ] + }, + { + "type": "Microsoft.Compute/virtualMachines", + "apiVersion": "2019-07-01", + "name": "myVM", + "location": "westus", + "properties": { + "hardwareProfile": { + "vmSize": "Standard_DS1_v2" + }, + "osProfile": { + "computerName": "myVM", + "adminUsername": "adminuser", + "customData": "[reference('Microsoft.KeyVault/vaults/myKeyVault', '2019-09-01').secrets['MySecret'].value]" + }, + "networkProfile": { + "networkInterfaces": [ + { + "id": "[resourceId('Microsoft.Network/networkInterfaces', 'myNIC')]" + } + ] + }, + "storageProfile": { + "osDisk": { + "createOption": "FromImage", + "managedDisk": { + "storageAccountType": "Premium_LRS" + } + } + } + } + } + ] +} \ No newline at end of file diff --git a/tests/arm/examples/ImplicitDepsResources/subnet.json b/tests/arm/examples/ImplicitDepsResources/subnet.json new file mode 100644 index 00000000000..56d22b863f5 --- /dev/null +++ b/tests/arm/examples/ImplicitDepsResources/subnet.json @@ -0,0 +1,34 @@ +{ + "$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#", + "contentVersion": "1.0.0.0", + "resources": [ + { + "type": "Microsoft.Network/networkSecurityGroups", + "apiVersion": "2020-06-01", + "name": "myNSG", + "location": "westus" + }, + { + "type": "Microsoft.Network/virtualNetworks", + "apiVersion": "2020-06-01", + "name": "myVNet", + "location": "westus", + "properties": { + "addressSpace": { + "addressPrefixes": ["10.0.0.0/16"] + }, + "subnets": [ + { + "name": "mySubnet", + "properties": { + "addressPrefix": "10.0.1.0/24", + "networkSecurityGroup": { + "id": "[reference('myNSG', '2020-06-01').id]" + } + } + } + ] + } + } + ] +} \ No newline at end of file diff --git a/tests/arm/graph_builder/test_local_graph.py b/tests/arm/graph_builder/test_local_graph.py index 2e023d0b6ee..c642718a686 100644 --- a/tests/arm/graph_builder/test_local_graph.py +++ b/tests/arm/graph_builder/test_local_graph.py @@ -6,23 +6,34 @@ EXAMPLES_DIR = Path(__file__).parent.parent / "examples" EXPLICIT_DEPS_DIR = EXAMPLES_DIR / "ExplicitDepsResources" +IMPLICIT_DEPS_DIR = EXAMPLES_DIR / "ImplicitDepsResources" -def test_build_graph(): - # given - test_files = [EXPLICIT_DEPS_DIR / "interface.json", - EXPLICIT_DEPS_DIR / "storage.json", - EXPLICIT_DEPS_DIR / "subnet.json"] + +def test_graph_explicit_deps(): + test_files = [str(EXPLICIT_DEPS_DIR / "subnet.json"), + str(EXPLICIT_DEPS_DIR / "storage.json"), + str(EXPLICIT_DEPS_DIR / "interface.json")] definitions, _, _ = get_files_definitions(test_files) test_graph = ArmLocalGraph(definitions) test_graph.build_graph() - local_graph = ArmLocalGraph(definitions=definitions) + assert len(test_graph.vertices) == 6 + assert len(test_graph.edges) == 5 + + assert len(test_graph.vertices_by_block_type[BlockType.RESOURCE]) == 6 + + +def test_graph_implicit_deps(): + test_files = [str(IMPLICIT_DEPS_DIR / "subnet.json"), + str(IMPLICIT_DEPS_DIR / "storage.json"), + str(IMPLICIT_DEPS_DIR / "interface.json")] + definitions, _, _ = get_files_definitions(test_files) + test_graph = ArmLocalGraph(definitions) + test_graph.build_graph() - # when - local_graph.build_graph(render_variables=False) + assert len(test_graph.vertices) == 6 + assert len(test_graph.edges) == 4 - # then - assert len(local_graph.vertices) == 6 - assert len(local_graph.edges) == 5 + assert len(test_graph.vertices_by_block_type[BlockType.RESOURCE]) == 6 - assert len(local_graph.vertices_by_block_type[BlockType.RESOURCE]) == 6 +# TODO: add tests with parameters and variables vertices and rendering