示例#1
0
    def test_update_complex_key(self):
        config = {
            'labels': [{
                'app.kubernetes.io/name': '${local.name}',
                'app.kubernetes.io/instance': 'hpa',
                'app.kubernetes.io/version': '1.0.0',
                'app.kubernetes.io/managed-by': 'terraform'
            }]
        }
        attributes = {
            'labels': {
                'app.kubernetes.io/name': '${local.name}',
                'app.kubernetes.io/instance': 'hpa',
                'app.kubernetes.io/version': '1.0.0',
                'app.kubernetes.io/managed-by': 'terraform'
            },
            'labels.app.kubernetes.io/name': '${local.name}',
            'labels.app.kubernetes.io/instance': 'hpa',
            'labels.app.kubernetes.io/version': '1.0.0',
            'labels.app.kubernetes.io/managed-by': 'terraform'
        }
        block = TerraformBlock(name='test_local_name',
                               config=config,
                               path='',
                               block_type=BlockType.LOCALS,
                               attributes=attributes)

        block.update_inner_attribute(
            attribute_key="labels.app.kubernetes.io/name",
            nested_attributes=attributes,
            value_to_update="dummy value")
        self.assertEqual("dummy value",
                         block.attributes["labels.app.kubernetes.io/name"])
示例#2
0
    def test_update_inner_attribute_bad_index(self):
        config = {'aws_security_group': {'test': {}}}

        nested_attributes = {
            'provisioner/remote-exec.connection': {
                'private_key': '${file(var.ssh_key_path)}',
                'user': '******'
            },
            'provisioner/remote-exec.connection.private_key':
            '${file(var.ssh_key_path)}',
            'provisioner/remote-exec.connection.user': '******',
            'provisioner/remote-exec.inline': ['command'],
            'provisioner/remote-exec.inline.0': 'command0',
            'provisioner/remote-exec.inline.1': 'command1',
            'provisioner/remote-exec.inline.2': 'command2',
            'provisioner/remote-exec.inline.3': 'command3',
            'provisioner/remote-exec.inline.4': 'command4'
        }
        block = TerraformBlock(name='aws_security_group.test',
                               config=config,
                               path='test_path',
                               block_type=BlockType.RESOURCE,
                               attributes=nested_attributes)

        block.update_inner_attribute(
            attribute_key='provisioner/remote-exec.inline.3',
            nested_attributes=nested_attributes,
            value_to_update='new_command_3')

        self.assertEqual(
            'new_command_3',
            block.attributes['provisioner/remote-exec.inline.3'],
            f"failed to update provisioner/remote-exec.inline.3, got {block.attributes['provisioner/remote-exec.inline.3']}"
        )
示例#3
0
 def test_update_vertices_configs_attribute_like_resource_name(self):
     config = {
         "resource_type": {
             "resource_name": {
                 "attribute1": 1,
                 "attribute2": 2,
                 "resource_name": ["caution!"]
             }
         }
     }
     attributes = {"attribute1": 1, "attribute2": 2, "resource_name": "ok"}
     local_graph = TerraformLocalGraph(None)
     vertex = TerraformBlock(name="resource_type.resource_name",
                             config=config,
                             path='',
                             block_type=BlockType.RESOURCE,
                             attributes=attributes)
     vertex.changed_attributes["resource_name"] = ""
     local_graph.vertices.append(vertex)
     local_graph.update_vertices_configs()
     expected_config = {
         "resource_type": {
             "resource_name": {
                 "attribute1": 1,
                 "attribute2": 2,
                 "resource_name": ["ok"]
             }
         }
     }
     self.assertDictEqual(expected_config, vertex.config)
示例#4
0
 def _handle_provisioner(provisioner: List[Dict[str, Any]],
                         attributes: Dict[str, Any]) -> None:
     for pro in provisioner:
         if pro.get("local-exec"):
             inner_attributes = TerraformBlock.get_inner_attributes(
                 "provisioner/local-exec", pro["local-exec"])
             attributes.update(inner_attributes)
         elif pro.get("remote-exec"):
             inner_attributes = TerraformBlock.get_inner_attributes(
                 "provisioner/remote-exec", pro["remote-exec"])
             attributes.update(inner_attributes)
     del attributes["provisioner"]
示例#5
0
    def test_update_inner_attribute_2(self):
        config = {
            'aws_security_group': {
                'test': {
                    'name': ['test'],
                    'vpc_id': ['${aws_vpc.vpc_main.id}'],
                    'ingress': [{
                        'from_port': [53],
                        'to_port': [53],
                        'protocol': ['udp'],
                        'security_groups': [[
                            '${data.test1.id}', '${data.test2.id}',
                            '${data.test3.id}', '${data.test4.id}',
                            '${data.test5.id}', '${data.test6.id}'
                        ]],
                        'cidr_blocks':
                        [['test1', '${var.test2}', '${var.test4}']]
                    }, {
                        'from_port': [53],
                        'to_port': [53],
                        'protocol': ['tcp'],
                        'security_groups': [[
                            '${data.test1.id}', '${data.test2.id}',
                            '${data.test3.id}', '${data.test4.id}',
                            '${data.test5.id}', '${data.test6.id}'
                        ]],
                        'cidr_blocks': [['test', '${var.test}', '${var.v3}']]
                    }]
                }
            }
        }

        block = TerraformBlock(name='aws_security_group.test',
                               config=config,
                               path='test_path',
                               block_type=BlockType.RESOURCE,
                               attributes=config['aws_security_group']['test'])

        block.update_inner_attribute(attribute_key='ingress.0.cidr_blocks.1',
                                     nested_attributes=block.attributes,
                                     value_to_update='sg-1')

        self.assertEqual(
            'sg-1', block.attributes['ingress.0.cidr_blocks.1'],
            f"failed to update ingress.0.cidr_blocks.1, got {block.attributes['ingress.0.cidr_blocks.1']}"
        )
        self.assertEqual(
            'sg-1', block.attributes['ingress'][0]['cidr_blocks'][1],
            f"failed to update block.attributes['ingress'][0]['cidr_blocks'][1], got {block.attributes['ingress'][0]['cidr_blocks'][1]}"
        )
示例#6
0
 def _add_tf_var(self, blocks: Dict[str, Dict[str, Any]],
                 path: str) -> None:
     for tf_var_name, attributes in blocks.items():
         tfvar_block = TerraformBlock(
             block_type=BlockType.TF_VARIABLE,
             name=tf_var_name,
             config={tf_var_name: attributes},
             path=path,
             attributes=attributes,
             source=self.source,
         )
         self._add_to_blocks(tfvar_block)
示例#7
0
 def _add_terraform_block(self, blocks: List[Dict[str, Dict[str, Any]]],
                          path: str) -> None:
     for terraform_dict in blocks:
         for name in terraform_dict:
             terraform_block = TerraformBlock(
                 block_type=BlockType.TERRAFORM,
                 name=name,
                 config=terraform_dict,
                 path=path,
                 attributes={},
                 source=self.source,
             )
             self._add_to_blocks(terraform_block)
示例#8
0
 def test_update_complex_key2(self):
     config = {}
     attributes = {
         'var.owning_account': {
             'route_to': None,
             'route_to_cidr_blocks': '${local.allowed_cidrs}',
             'static_routes': None,
             'subnet_ids': '${local.own_vpc.private_subnet_ids}',
             'subnet_route_table_ids':
             '${local.own_vpc.private_route_table_ids}',
             'transit_gateway_vpc_attachment_id': None,
             'vpc_cidr': '${local.own_vpc.vpc_cidr}',
             'vpc_id': '${local.own_vpc.vpc_id}'
         }
     }
     block = TerraformBlock(name='test_local_name',
                            config=config,
                            path='',
                            block_type=BlockType.LOCALS,
                            attributes=attributes)
     value_to_update = "test"
     block.update_inner_attribute(
         attribute_key="var.owning_account.vpc_cidr",
         nested_attributes=attributes,
         value_to_update=value_to_update)
     self.assertDictEqual(
         {'var.owning_account': block.attributes["var.owning_account"]}, {
             'var.owning_account': {
                 'route_to': None,
                 'route_to_cidr_blocks': '${local.allowed_cidrs}',
                 'static_routes': None,
                 'subnet_ids': '${local.own_vpc.private_subnet_ids}',
                 'subnet_route_table_ids':
                 '${local.own_vpc.private_route_table_ids}',
                 'transit_gateway_vpc_attachment_id': None,
                 'vpc_cidr': 'test',
                 'vpc_id': '${local.own_vpc.vpc_id}'
             }
         })
示例#9
0
 def _add_module(self, blocks: List[Dict[str, Dict[str, Any]]],
                 path: str) -> None:
     for module_dict in blocks:
         for name in module_dict:
             module_block = TerraformBlock(
                 block_type=BlockType.MODULE,
                 name=name,
                 config=module_dict,
                 path=path,
                 attributes=module_dict[name],
                 source=self.source,
             )
             self._add_to_blocks(module_block)
示例#10
0
 def _add_locals(self, blocks: List[Dict[str, Dict[str, Any]]],
                 path: str) -> None:
     for blocks_section in blocks:
         for name in blocks_section:
             local_block = TerraformBlock(
                 block_type=BlockType.LOCALS,
                 name=name,
                 config={name: blocks_section[name]},
                 path=path,
                 attributes={name: blocks_section[name]},
                 source=self.source,
             )
             self._add_to_blocks(local_block)
示例#11
0
 def _add_module(self, blocks: List[Dict[str, Dict[str, Any]]],
                 path: str) -> None:
     for module_dict in blocks:
         for name, attributes in module_dict.items():
             if isinstance(attributes, dict):
                 module_block = TerraformBlock(
                     block_type=BlockType.MODULE,
                     name=name,
                     config=module_dict,
                     path=path,
                     attributes=attributes,
                     source=self.source,
                 )
                 self._add_to_blocks(module_block)
示例#12
0
 def _add_variable(self, blocks: List[Dict[str, Dict[str, Any]]],
                   path: str) -> None:
     for variable_dict in blocks:
         for name in variable_dict:
             attributes = variable_dict[name]
             variable_block = TerraformBlock(
                 block_type=BlockType.VARIABLE,
                 name=name,
                 config=variable_dict,
                 path=path,
                 attributes=attributes,
                 source=self.source,
             )
             self._add_to_blocks(variable_block)
示例#13
0
    def _add_to_blocks(self, block: TerraformBlock) -> None:
        dependencies = self.module_dependency_map.get(
            os.path.dirname(block.path), [])
        module_dependency_num = ""
        if not dependencies:
            dependencies = [[]]
        for dep_idx, dep_trail in enumerate(dependencies):
            if dep_idx > 0:
                block = deepcopy(block)
            block.module_dependency = unify_dependency_path(dep_trail)

            if block.module_dependency:
                module_dependency_numbers = self.dep_index_mapping.get(
                    (block.path, dep_trail[-1]), [])
                for mod_idx, module_dep_num in enumerate(
                        module_dependency_numbers):
                    if mod_idx > 0:
                        block = deepcopy(block)
                    block.module_dependency_num = module_dep_num
                    self.blocks.append(block)
            else:
                block.module_dependency_num = module_dependency_num
                self.blocks.append(block)
示例#14
0
 def _add_output(self, blocks: List[Dict[str, Dict[str, Any]]],
                 path: str) -> None:
     for output_dict in blocks:
         for name in output_dict:
             if type(output_dict[name]) is not dict:
                 continue
             output_block = TerraformBlock(
                 block_type=BlockType.OUTPUT,
                 name=name,
                 config=output_dict,
                 path=path,
                 attributes={"value": output_dict[name].get("value")},
                 source=self.source,
             )
             self._add_to_blocks(output_block)
示例#15
0
 def _add_data(self, blocks: List[Dict[str, Dict[str, Any]]],
               path: str) -> None:
     for data_dict in blocks:
         for data_type in data_dict:
             for name in data_dict[data_type]:
                 data_block = TerraformBlock(
                     block_type=BlockType.DATA,
                     name=data_type + "." + name,
                     config=data_dict,
                     path=path,
                     attributes=data_dict.get(data_type, {}).get(name, {}),
                     id=data_type + "." + name,
                     source=self.source,
                 )
                 self._add_to_blocks(data_block)
示例#16
0
 def _add_provider(self, blocks: List[Dict[str, Dict[str, Any]]],
                   path: str) -> None:
     for provider_dict in blocks:
         for name in provider_dict:
             attributes = provider_dict[name]
             provider_name = name
             alias = attributes.get("alias")
             if alias:
                 provider_name = f"{provider_name}.{alias[0]}"
             provider_block = TerraformBlock(
                 block_type=BlockType.PROVIDER,
                 name=provider_name,
                 config=provider_dict,
                 path=path,
                 attributes=attributes,
                 source=self.source,
             )
             self._add_to_blocks(provider_block)
示例#17
0
    def test_update_inner_attribute_1(self):
        config = {
            'aws_security_group': {
                'test': {
                    'name': ['test'],
                    'vpc_id': ['${aws_vpc.vpc_main.id}'],
                    'tags': [{
                        'Name': 'test'
                    }],
                    'description': ['test - Elasticsearch Cluster'],
                    'ingress': [{
                        'from_port': [443],
                        'to_port': [443],
                        'protocol': ['tcp'],
                        'security_groups': [[
                            '${aws_security_group.test.id}',
                            '${data.aws_security_group.test.id}'
                        ]]
                    }]
                }
            }
        }

        block = TerraformBlock(name='aws_security_group.test',
                               config=config,
                               path='test_path',
                               block_type=BlockType.RESOURCE,
                               attributes=config['aws_security_group']['test'])

        block.update_inner_attribute(attribute_key='ingress.security_groups.0',
                                     nested_attributes=block.attributes,
                                     value_to_update='sg-0')
        block.update_inner_attribute(attribute_key='ingress.security_groups.1',
                                     nested_attributes=block.attributes,
                                     value_to_update='sg-1')

        self.assertEqual(
            'sg-0', block.attributes['ingress.security_groups.0'],
            f"failed to update ingress.security_groups.0, got {block.attributes['ingress.security_groups.0']}"
        )
        self.assertEqual(
            'sg-1', block.attributes['ingress.security_groups.1'],
            f"failed to update ingress.security_groups.1, got {block.attributes['ingress.security_groups.1']}"
        )
        self.assertEqual(
            'sg-0', block.attributes['ingress']['security_groups'][0],
            f"failed to update block.attributes['ingress']['security_groups'][0], got {block.attributes['ingress']['security_groups'][0]}"
        )
        self.assertEqual(
            'sg-1', block.attributes['ingress']['security_groups'][1],
            f"failed to update block.attributes['ingress']['security_groups'][1], got {block.attributes['ingress']['security_groups'][1]}"
        )
示例#18
0
文件: module.py 项目: tronxd/checkov
 def _add_resource(self, blocks: List[Dict[str, Dict[str, Any]]],
                   path: str) -> None:
     for resource_dict in blocks:
         for resource_type, resources in resource_dict.items():
             self.resources_types.add(resource_type)
             for name, resource_conf in resources.items():
                 attributes = self.clean_bad_characters(resource_conf)
                 if not isinstance(attributes, dict):
                     continue
                 provisioner = attributes.get("provisioner")
                 if provisioner:
                     self._handle_provisioner(provisioner, attributes)
                 attributes["resource_type"] = [resource_type]
                 resource_block = TerraformBlock(
                     block_type=BlockType.RESOURCE,
                     name=f"{resource_type}.{name}",
                     config=self.clean_bad_characters(resource_dict),
                     path=path,
                     attributes=attributes,
                     id=f"{resource_type}.{name}",
                     source=self.source,
                 )
                 self._add_to_blocks(resource_block)
示例#19
0
 def test_update_inner_attribute_3(self):
     config = {
         'aws_iam_policy_document': {
             'vcs_webhook_step_function_execution_policy': {
                 'statement': [{
                     'actions': [[
                         'events:DescribeRule', 'events:PutRule',
                         'events:PutTargets'
                     ]],
                     'effect': ['Allow'],
                     'resources': [[
                         'arn:aws:events:${var.region}:${data.aws_caller_identity.current.account_id}:rule/StepFunctionsGetEventsForECSTaskRule',
                         'arn:aws:events:${var.region}:${data.aws_caller_identity.current.account_id}:rule/StepFunctionsGetEventsForStepFunctionsExecutionRule'
                     ]]
                 }, {
                     'actions': [['states:StartExecution']],
                     'effect': ['Allow'],
                     'resources': [[
                         'arn:aws:states:${var.region}:${data.aws_caller_identity.current.account_id}:stateMachine:${module.consts.bc_checkov_scanner_step_function_name}*'
                     ]]
                 }, {
                     'actions': [['lambda:InvokeFunction']],
                     'effect': ['Allow'],
                     'resources': [
                         '${formatlist("%s%s","arn:aws:lambda:${var.region}:${data.aws_caller_identity.current.account_id}:function:",concat([\'${local.vcs_webhook_lambda_name}\', \'${local.customer_api_lambda}\']))}'
                     ]
                 }]
             }
         }
     }
     block = TerraformBlock(
         name=
         'aws_iam_policy_document.vcs_webhook_step_function_execution_policy',
         config=config,
         path='test_path',
         block_type=BlockType.DATA,
         attributes=config['aws_iam_policy_document']
         ['vcs_webhook_step_function_execution_policy'])
     block.update_inner_attribute(
         attribute_key='statement.1.resources.0',
         nested_attributes={
             'statement': [{
                 'actions': [
                     'events:DescribeRule', 'events:PutRule',
                     'events:PutTargets'
                 ],
                 'effect':
                 'Allow',
                 'resources': [
                     'arn:aws:events:${var.region}:${data.aws_caller_identity.current.account_id}:rule/StepFunctionsGetEventsForECSTaskRule',
                     'arn:aws:events:${var.region}:${data.aws_caller_identity.current.account_id}:rule/StepFunctionsGetEventsForStepFunctionsExecutionRule'
                 ]
             }, {
                 'actions':
                 'states:StartExecution',
                 'effect':
                 'Allow',
                 'resources':
                 'arn:aws:states:${var.region}:${data.aws_caller_identity.current.account_id}:stateMachine:bc-vcs-scanner-sfn*'
             }, {
                 'actions':
                 'lambda:InvokeFunction',
                 'effect':
                 'Allow',
                 'resources':
                 '${formatlist("%s%s","arn:aws:lambda:${var.region}:${data.aws_caller_identity.current.account_id}:function:",concat([\'${local.vcs_webhook_lambda_name}\', \'${local.customer_api_lambda}\']))}'
             }],
             'statement.0': {
                 'actions': [
                     'events:DescribeRule', 'events:PutRule',
                     'events:PutTargets'
                 ],
                 'effect':
                 'Allow',
                 'resources': [
                     'arn:aws:events:${var.region}:${data.aws_caller_identity.current.account_id}:rule/StepFunctionsGetEventsForECSTaskRule',
                     'arn:aws:events:${var.region}:${data.aws_caller_identity.current.account_id}:rule/StepFunctionsGetEventsForStepFunctionsExecutionRule'
                 ]
             },
             'statement.0.actions':
             ['events:DescribeRule', 'events:PutRule', 'events:PutTargets'],
             'statement.0.actions.0':
             'events:DescribeRule',
             'statement.0.actions.1':
             'events:PutRule',
             'statement.0.actions.2':
             'events:PutTargets',
             'statement.0.effect':
             'Allow',
             'statement.0.resources': [
                 'arn:aws:events:${var.region}:${data.aws_caller_identity.current.account_id}:rule/StepFunctionsGetEventsForECSTaskRule',
                 'arn:aws:events:${var.region}:${data.aws_caller_identity.current.account_id}:rule/StepFunctionsGetEventsForStepFunctionsExecutionRule'
             ],
             'statement.0.resources.0':
             'arn:aws:events:${var.region}:${data.aws_caller_identity.current.account_id}:rule/StepFunctionsGetEventsForECSTaskRule',
             'statement.0.resources.1':
             'arn:aws:events:${var.region}:${data.aws_caller_identity.current.account_id}:rule/StepFunctionsGetEventsForStepFunctionsExecutionRule',
             'statement.1': {
                 'resources':
                 'arn:aws:states:${var.region}:${data.aws_caller_identity.current.account_id}:stateMachine:bc-vcs-scanner-sfn*'
             },
             'statement.1.actions':
             'states:StartExecution',
             'statement.1.actions.0':
             'states:StartExecution',
             'statement.1.effect':
             'Allow',
             'statement.1.resources':
             'arn:aws:states:${var.region}:${data.aws_caller_identity.current.account_id}:stateMachine:bc-vcs-scanner-sfn*',
             'statement.1.resources.0':
             'arn:aws:states:${var.region}:${data.aws_caller_identity.current.account_id}:stateMachine:bc-vcs-scanner-sfn*',
             'statement.2': {
                 'actions':
                 'lambda:InvokeFunction',
                 'effect':
                 'Allow',
                 'resources':
                 '${formatlist("%s%s","arn:aws:lambda:${var.region}:${data.aws_caller_identity.current.account_id}:function:",concat([\'${local.vcs_webhook_lambda_name}\', \'${local.customer_api_lambda}\']))}'
             },
             'statement.2.actions':
             'lambda:InvokeFunction',
             'statement.2.actions.0':
             'lambda:InvokeFunction',
             'statement.2.effect':
             'Allow',
             'statement.2.resources':
             '${formatlist("%s%s","arn:aws:lambda:${var.region}:${data.aws_caller_identity.current.account_id}:function:",concat([\'${local.vcs_webhook_lambda_name}\', \'${local.customer_api_lambda}\']))}'
         },
         value_to_update=
         'arn:aws:states:${var.region}:${data.aws_caller_identity.current.account_id}:stateMachine:bc-vcs-scanner-sfn*'
     )
     self.assertIn(block.attributes['statement.0.resources.1'], [
         'arn:aws:events:${var.region}:${data.aws_caller_identity.current.account_id}:rule/StepFunctionsGetEventsForECSTaskRule',
         'arn:aws:events:${var.region}:${data.aws_caller_identity.current.account_id}:rule/StepFunctionsGetEventsForStepFunctionsExecutionRule'
     ])
     self.assertIn(block.attributes['statement.0.resources.0'], [
         'arn:aws:events:${var.region}:${data.aws_caller_identity.current.account_id}:rule/StepFunctionsGetEventsForECSTaskRule',
         'arn:aws:events:${var.region}:${data.aws_caller_identity.current.account_id}:rule/StepFunctionsGetEventsForStepFunctionsExecutionRule'
     ])
示例#20
0
    def test_update_inner_attribute_bad_map_entry(self):
        config = {'aws_security_group': {'test': {}}}

        nested_attributes = {
            'triggers': {
                'change_endpoint_name': '${md5("my_dev_endpoint")}',
                'change_extra_jars_s3_path': '${md5()}',
                'change_extra_python_libs_s3_path': '${md5()}',
                'change_number_of_nodes': '${md5("2")}',
                'change_public_keys':
                '${md5("${var.glue_endpoint_public_keys}")}',
                'change_region': '${md5("us-east-1")}',
                'change_role':
                '${md5("arn:aws:iam::111111111111:role/my_role")}',
                'change_security_configuration': '${md5()}',
                'change_security_group_ids':
                '${md5("${var.glue_endpoint_security_group_ids}")}',
                'change_subnet_id': '${md5()}'
            },
            'provisioner/local-exec': {
                'command':
                "echo 'info: destroy ignored because part of apply'",
                'when': 'destroy'
            },
            'provisioner/local-exec.command':
            "echo 'info: destroy ignored because part of apply'",
            'provisioner/local-exec.environment': {
                'endpoint_name': '${var.glue_endpoint_name}',
                'extra_jars_s3_path':
                '${var.glue_endpoint_extra_jars_libraries}',
                'extra_python_libs_s3_path':
                '${var.glue_endpoint_extra_python_libraries}',
                'number_of_nodes': '${var.glue_endpoint_number_of_dpus}',
                'public_keys': '${join(",",var.glue_endpoint_public_keys)}',
                'region': '${var.aws_region}',
                'role_arn': '${var.glue_endpoint_role}',
                'security_configuration':
                '${var.glue_endpoint_security_configuration}',
                'security_group_ids':
                '${join(",",var.glue_endpoint_security_group_ids)}',
                'subnet_id': '${var.glue_endpoint_subnet_id}'
            },
            'provisioner/local-exec.environment.endpoint_name':
            'my_dev_endpoint',
            'provisioner/local-exec.environment.extra_jars_s3_path': '',
            'provisioner/local-exec.environment.extra_python_libs_s3_path': '',
            'provisioner/local-exec.environment.number_of_nodes': 2,
            'provisioner/local-exec.environment.public_keys':
            '${join(",",var.glue_endpoint_public_keys)}',
            'provisioner/local-exec.environment.region': 'us-east-1',
            'provisioner/local-exec.environment.role_arn':
            'arn:aws:iam::111111111111:role/my_role',
            'provisioner/local-exec.environment.security_configuration': '',
            'provisioner/local-exec.environment.security_group_ids':
            '${join(",",var.glue_endpoint_security_group_ids)}',
            'provisioner/local-exec.environment.subnet_id': '',
            'provisioner/local-exec.when': 'destroy',
            'resource_type': ['null_resource'],
            'triggers.change_endpoint_name': '${md5("my_dev_endpoint")}',
            'triggers.change_extra_jars_s3_path': '${md5()}',
            'triggers.change_extra_python_libs_s3_path': '${md5()}',
            'triggers.change_number_of_nodes': '${md5("2")}',
            'triggers.change_public_keys':
            '${md5("${var.glue_endpoint_public_keys}")}',
            'triggers.change_region': '${md5("us-east-1")}',
            'triggers.change_role':
            '${md5("arn:aws:iam::111111111111:role/my_role")}',
            'triggers.change_security_configuration': '${md5()}',
            'triggers.change_security_group_ids':
            '${md5("${var.glue_endpoint_security_group_ids}")}',
            'triggers.change_subnet_id': '${md5()}'
        }
        block = TerraformBlock(name='null_resource.glue_endpoint_apply',
                               config=config,
                               path='test_path',
                               block_type=BlockType.RESOURCE,
                               attributes=nested_attributes)
        attribute_key = 'provisioner/local-exec.environment.security_configuration'
        block.update_inner_attribute(attribute_key=attribute_key,
                                     nested_attributes=nested_attributes,
                                     value_to_update='')

        self.assertEqual(
            '', block.attributes[attribute_key],
            f"failed to update provisioner/remote-exec.inline.3, got {block.attributes[attribute_key]}"
        )