diff --git a/slp_tfplan/slp_tfplan/load/resource_data_extractors.py b/slp_tfplan/slp_tfplan/load/resource_data_extractors.py index 19eaa9ad..c80a1ee5 100644 --- a/slp_tfplan/slp_tfplan/load/resource_data_extractors.py +++ b/slp_tfplan/slp_tfplan/load/resource_data_extractors.py @@ -3,9 +3,6 @@ # TODO Consider migrating these functions to use jmespath -def _get_resource_properties_root(resource: {}, path: Literal['expressions', 'planned_values']) -> Dict: - return resource['resource_properties'].get(path, {}) - def _get_referenced_resources(references: List[str]): valid_references = [] @@ -17,12 +14,7 @@ def _get_referenced_resources(references: List[str]): return valid_references -def _get_value_from(resource: Dict, root: Literal['expressions', 'planned_values'], path: List[str]): - expressions = _get_resource_properties_root(resource, root) - if not expressions: - return [] - - source = expressions +def _get_value_from_path(source: Dict, path: List[str]): for i, element in enumerate(path): source = source.get(element) if not source: @@ -37,16 +29,18 @@ def _get_value_from(resource: Dict, root: Literal['expressions', 'planned_values return source -def _get_value_from_planned_values(resource: Dict, path: List[str]): - return _get_value_from(resource, 'planned_values', path) +def _get_from_values(resource: Dict, path: List[str]): + expressions_path = ['resource_values'] + path + return _get_value_from_path(resource, expressions_path) -def _get_value_from_expressions(resource: Dict, path: List[str]): - return _get_value_from(resource, 'expressions', path) +def _get_from_expressions(resource: Dict, path: List[str]): + expressions_path = ['resource_configuration', 'expressions'] + path + return _get_value_from_path(resource, expressions_path) def _get_references_from_expressions(resource: Dict, path: List[str]) -> List[str]: - source = _get_value_from_expressions(resource, path) + source = _get_from_expressions(resource, path) if not source or isinstance(source, str): return [] @@ -68,10 +62,6 @@ def security_groups_ids_from_type_property(resource: {}, cidr_type: Literal['ing return _get_references_from_expressions(resource, [cidr_type, 'references']) -def cidr_from_type_property(resource: {}, cidr_type: Literal['ingress', 'egress']) -> List[dict]: - return _get_value_from_planned_values(resource, [cidr_type]) - - def source_security_group_id_from_rule(resource: {}) -> str: sources_list = _get_references_from_expressions(resource, ['source_security_group_id', 'references']) if sources_list: @@ -84,25 +74,29 @@ def security_group_id_from_rule(resource: {}) -> str: return sg_ids[0] +def cidr_from_type_property(resource: {}, cidr_type: Literal['ingress', 'egress']) -> List[dict]: + return _get_from_values(resource, [cidr_type]) + + def description_from_rule(resource: {}) -> str: - return _get_value_from_planned_values(resource, ['description']) + return _get_from_values(resource, ['description']) def protocol_from_rule(resource: {}) -> str: - return _get_value_from_planned_values(resource, ['protocol']) + return _get_from_values(resource, ['protocol']) def from_port_from_rule(resource: {}) -> str: - return _get_value_from_planned_values(resource, ['from_port']) + return _get_from_values(resource, ['from_port']) def to_port_from_rule(resource: {}) -> str: - return _get_value_from_planned_values(resource, ['to_port']) + return _get_from_values(resource, ['to_port']) def cidr_blocks_from_rule(resource: {}) -> List[str]: - return _get_value_from_planned_values(resource, ['cidr_blocks']) + return _get_from_values(resource, ['cidr_blocks']) def security_group_rule_type(resource: {}) -> str: - return _get_value_from_expressions(resource, ['type', 'constant_value']) + return _get_from_values(resource, ['type']) diff --git a/slp_tfplan/slp_tfplan/load/security_groups_loader.py b/slp_tfplan/slp_tfplan/load/security_groups_loader.py index 8c1ff71c..3ab93f43 100644 --- a/slp_tfplan/slp_tfplan/load/security_groups_loader.py +++ b/slp_tfplan/slp_tfplan/load/security_groups_loader.py @@ -1,9 +1,13 @@ from typing import List, Dict, Union +from networkx import DiGraph + +from slp_tfplan.slp_tfplan.graph.relationships_extractor import RelationshipsExtractor from slp_tfplan.slp_tfplan.load.resource_data_extractors import security_group_id_from_rule, \ description_from_rule, protocol_from_rule, from_port_from_rule, to_port_from_rule, cidr_blocks_from_rule, \ cidr_from_type_property, source_security_group_id_from_rule, \ security_group_rule_type, security_groups_ids_from_type_property +from slp_tfplan.slp_tfplan.matcher.sg_and_sgrules_matcher import SGAndSGRulesMatcher from slp_tfplan.slp_tfplan.objects.tfplan_objects import SecurityGroup, TFPlanOTM, SecurityGroupCIDR, \ SecurityGroupCIDRType @@ -17,7 +21,8 @@ def _get_security_group_rules(resources: List[Dict]) -> List[Dict[str, str]]: return [] return list(map(lambda sg_rule: - {'security_group_id': security_group_id_from_rule(sg_rule), + {'resource_id': sg_rule.get('resource_id'), + 'security_group_id': security_group_id_from_rule(sg_rule), 'description': description_from_rule(sg_rule), 'protocol': protocol_from_rule(sg_rule), 'from_port': from_port_from_rule(sg_rule), @@ -28,46 +33,35 @@ def _get_security_group_rules(resources: List[Dict]) -> List[Dict[str, str]]: sg_rules)) -def _get_sg_rules_by_sg_id(sg_id: str, rule_type: SecurityGroupCIDRType, sg_rules: List[Dict[str, str]] - ) -> List[Dict[str, str]]: - return list(filter( - lambda sg_rule: - sg_rule['security_group_id'] == sg_id and sg_rule['type'] == rule_type.value, - sg_rules)) - - -def _source_security_group_ids_of_type_from_rule(security_group: Dict, rule_type: SecurityGroupCIDRType, - sg_rules: List[Dict[str, str]]): - sg_rules_by_sg_id = _get_sg_rules_by_sg_id(security_group['resource_id'], rule_type, sg_rules) - return list(filter(lambda sg_id: sg_id is not None, - list(set([r['source_security_group_id'] for r in sg_rules_by_sg_id])))) - +def _is_valid_cidr_object(sg_rule: Union[str, Dict[str, str]]) -> bool: + if isinstance(sg_rule, str): + return False + return 'cidr_blocks' in sg_rule -def _cidr_of_type_from_rule(security_group: Dict, rule_type: SecurityGroupCIDRType, - sg_rules: List[Dict[str, str]]): - sg_rules_by_sg_id = _get_sg_rules_by_sg_id(security_group['resource_id'], rule_type, sg_rules) - return list(filter(lambda sg_rule: sg_rule.get('cidr_blocks', None) is not None, sg_rules_by_sg_id)) +def _filter_sg_rule_by_type(sg_rules: List[Dict], rule_type: SecurityGroupCIDRType): + return list(filter(lambda sg_rule: sg_rule['type'] == rule_type.value, sg_rules)) -def _get_sgs_of_type(security_group: Dict, sg_type: SecurityGroupCIDRType, - sg_rules: List[Dict[str, str]]) -> List[str]: +def _get_sgs_of_type(security_group: Dict, related_sg_rules: List[Dict], + sg_type: SecurityGroupCIDRType) -> List[str]: return security_groups_ids_from_type_property(security_group, sg_type.value) or \ - _source_security_group_ids_of_type_from_rule(security_group, sg_type, sg_rules) + _get_sgs_of_type_from_rule(related_sg_rules, sg_type) -def __is_valid_cidr_object(sg_rule: Union[str, Dict[str, str]]) -> bool: - if isinstance(sg_rule, str): - return False - return 'cidr_blocks' in sg_rule +def _get_sgs_of_type_from_rule(related_sg_rules: List[Dict], rule_type: SecurityGroupCIDRType): + related_sg_rules_filtered = _filter_sg_rule_by_type(related_sg_rules, rule_type) + + return list(filter(lambda sg_id: sg_id is not None, + list(set([r['source_security_group_id'] for r in related_sg_rules_filtered])))) -def _get_cidr_of_type(security_group: Dict, cidr_type: SecurityGroupCIDRType, - sg_rules: List[Dict[str, str]]) -> List[SecurityGroupCIDR]: +def _get_cidr_of_type(security_group: Dict, related_sg_rules: List[Dict], + cidr_type: SecurityGroupCIDRType) -> List[SecurityGroupCIDR]: sg_cidr = cidr_from_type_property(security_group, cidr_type.value) or \ - _cidr_of_type_from_rule(security_group, cidr_type, sg_rules) + _get_cidr_of_type_from_rule(related_sg_rules, cidr_type) - sg_cidr = list(filter(lambda cidr: __is_valid_cidr_object(cidr), sg_cidr)) + sg_cidr = list(filter(lambda cidr: _is_valid_cidr_object(cidr), sg_cidr)) if not sg_cidr: return [] @@ -75,6 +69,12 @@ def _get_cidr_of_type(security_group: Dict, cidr_type: SecurityGroupCIDRType, return list(map(lambda cidr: SecurityGroupCIDRLoader(cidr, cidr_type).load(), sg_cidr)) +def _get_cidr_of_type_from_rule(related_sg_rules: List[Dict], rule_type: SecurityGroupCIDRType): + related_sg_rules_filtered = _filter_sg_rule_by_type(related_sg_rules, rule_type) + + return list(filter(lambda sg_rule: sg_rule.get('cidr_blocks', None) is not None, related_sg_rules_filtered)) + + class SecurityGroupCIDRLoader: def __init__(self, security_group_cidr: dict, cidr_type: SecurityGroupCIDRType): @@ -100,24 +100,28 @@ def load(self): class SecurityGroupsLoader: - def __init__(self, otm: TFPlanOTM, tfplan: {}): + def __init__(self, otm: TFPlanOTM, tfplan: {}, graph: DiGraph): self.otm = otm self._resources = tfplan['resource'] - self._sg_rules: List[Dict[str, str]] = [] + self._sg_rules: List[Dict[str, str]] = _get_security_group_rules(self._resources) + + self._relationships_extractor = RelationshipsExtractor( + mapped_resources_ids=self.otm.mapped_resources_ids, + graph=graph) def load(self): - self._sg_rules = _get_security_group_rules(self._resources) for resource in self._resources: if resource['resource_type'] in SECURITY_GROUPS_TYPES: self.otm.security_groups.append(self.__build_security_group(resource)) def __build_security_group(self, resource: {}) -> SecurityGroup: + related_sg_rules = SGAndSGRulesMatcher(resource, self._sg_rules, self._relationships_extractor).match() return SecurityGroup( security_group_id=resource['resource_id'], name=resource['resource_name'], - ingress_sgs=_get_sgs_of_type(resource, SecurityGroupCIDRType.INGRESS, self._sg_rules), - egress_sgs=_get_sgs_of_type(resource, SecurityGroupCIDRType.EGRESS, self._sg_rules), - ingress_cidr=_get_cidr_of_type(resource, SecurityGroupCIDRType.INGRESS, self._sg_rules), - egress_cidr=_get_cidr_of_type(resource, SecurityGroupCIDRType.EGRESS, self._sg_rules), + ingress_sgs=_get_sgs_of_type(resource, related_sg_rules, SecurityGroupCIDRType.INGRESS), + egress_sgs=_get_sgs_of_type(resource, related_sg_rules, SecurityGroupCIDRType.EGRESS), + ingress_cidr=_get_cidr_of_type(resource, related_sg_rules, SecurityGroupCIDRType.INGRESS), + egress_cidr=_get_cidr_of_type(resource, related_sg_rules, SecurityGroupCIDRType.EGRESS), ) diff --git a/slp_tfplan/slp_tfplan/load/tfplan_to_resource_dict.py b/slp_tfplan/slp_tfplan/load/tfplan_to_resource_dict.py index be50df61..e1bba77a 100644 --- a/slp_tfplan/slp_tfplan/load/tfplan_to_resource_dict.py +++ b/slp_tfplan/slp_tfplan/load/tfplan_to_resource_dict.py @@ -3,18 +3,6 @@ import sl_util.sl_util.secure_regex as re -def map_resource_properties(resource: Dict) -> {}: - return { - 'resource_mode': resource['mode'], - 'resource_provider_name': resource['provider_name'], - 'resource_schema_version': resource['schema_version'], - 'resource_address': resource['address'], - # Sensitive and usual values may be overlapped - **resource.get('sensitive_values', {}), - **resource.get('values', {}) - } - - def is_not_cloned_resource(resource: Dict) -> bool: return 'index' not in resource or resource['index'] == '0' or resource['index'] == 'zero' @@ -78,16 +66,14 @@ def __map_resource(self, resource: Dict, parent: str = None) -> Dict: 'resource_id': get_resource_id(resource), 'resource_name': get_resource_name(resource, parent), 'resource_type': resource['type'], - 'resource_properties': self.__get_resource_properties(resource) + 'resource_values': resource.get('values', {}), + 'resource_configuration': { + 'expressions': self.__get_resource_configuration_expressions(resource) + } } - def __get_resource_properties(self, resource: Dict) -> Dict: - _resource_configuration = self.__get_resource_configuration(resource['address']) - _resource_properties = map_resource_properties(resource) - if _resource_configuration: - _resource_configuration["planned_values"] = _resource_properties - - return _resource_configuration or _resource_properties + def __get_resource_configuration_expressions(self, resource: Dict) -> Dict: + return self.__get_resource_configuration(resource).get('expressions', {}) - def __get_resource_configuration(self, resource_address: str) -> Dict: - return next(filter(lambda r: r['address'] == resource_address, self.resources_configuration), None) + def __get_resource_configuration(self, resource: Dict) -> Dict: + return next(filter(lambda r: r['address'] == resource['address'], self.resources_configuration), {}) diff --git a/slp_tfplan/slp_tfplan/matcher/__init__.py b/slp_tfplan/slp_tfplan/matcher/__init__.py index ca26ca4a..45027192 100644 --- a/slp_tfplan/slp_tfplan/matcher/__init__.py +++ b/slp_tfplan/slp_tfplan/matcher/__init__.py @@ -1,5 +1,6 @@ from slp_tfplan.slp_tfplan.matcher.components_and_sgs_matcher import ComponentsAndSGsMatcher from slp_tfplan.slp_tfplan.matcher.resource_matcher import ResourcesMatcherContainer +from slp_tfplan.slp_tfplan.matcher.sg_and_sgrules_matcher import SGAndSGRulesMatcher from slp_tfplan.slp_tfplan.matcher.sgs_matcher import SGsMatcher from slp_tfplan.slp_tfplan.matcher.strategies.match_strategy import MatchStrategyContainer @@ -7,5 +8,6 @@ ResourcesMatcherContainer().wire(modules=[ ComponentsAndSGsMatcher.__module__, - SGsMatcher.__module__ + SGsMatcher.__module__, + SGAndSGRulesMatcher.__module__ ]) diff --git a/slp_tfplan/slp_tfplan/matcher/resource_matcher.py b/slp_tfplan/slp_tfplan/matcher/resource_matcher.py index 0bcba97f..4653156d 100644 --- a/slp_tfplan/slp_tfplan/matcher/resource_matcher.py +++ b/slp_tfplan/slp_tfplan/matcher/resource_matcher.py @@ -54,10 +54,15 @@ class ResourcesMatcherContainer(DeclarativeContainer): sgs_matcher = providers.Singleton( ResourceMatcher, - strategies=MatchStrategyContainer.sg_match_strategies + strategies=MatchStrategyContainer.sg_sg_match_strategies ) component_sg_matcher = providers.Singleton( ResourceMatcher, strategies=MatchStrategyContainer.component_sg_match_strategies ) + + sg_rule_matcher = providers.Singleton( + ResourceMatcher, + strategies=MatchStrategyContainer.sg_sg_rule_match_strategies + ) diff --git a/slp_tfplan/slp_tfplan/matcher/sg_and_sgrules_matcher.py b/slp_tfplan/slp_tfplan/matcher/sg_and_sgrules_matcher.py new file mode 100644 index 00000000..ce2f1317 --- /dev/null +++ b/slp_tfplan/slp_tfplan/matcher/sg_and_sgrules_matcher.py @@ -0,0 +1,36 @@ +from typing import Dict, List + +from dependency_injector.wiring import inject, Provide + +from slp_tfplan.slp_tfplan.graph.relationships_extractor import RelationshipsExtractor +from slp_tfplan.slp_tfplan.matcher.resource_matcher import ResourceMatcher, ResourcesMatcherContainer + + +class SGAndSGRulesMatcher: + """ + This class is responsible for matching security groups and security groups rules. + """ + @inject + def __init__(self, + security_group: Dict, security_group_rules: List[Dict], + relationships_extractor: RelationshipsExtractor, + sg_rule_matcher: ResourceMatcher = Provide[ResourcesMatcherContainer.sg_rule_matcher]): + # Data structures + self._security_group: Dict = security_group + self._security_group_rules: List[Dict] = security_group_rules + self._relationships_extractor: RelationshipsExtractor = relationships_extractor + + # Injected dependencies + self._are_related = sg_rule_matcher.are_related + + def match(self) -> List[Dict]: + """ + Returns a list of security group rules related with the security group. + :return: List of security group rules + """ + related_sg_rule = [] + for sg_rule in self._security_group_rules: + if self._are_related(self._security_group, sg_rule, relationships_extractor=self._relationships_extractor): + related_sg_rule.append(sg_rule) + + return related_sg_rule diff --git a/slp_tfplan/slp_tfplan/matcher/strategies/component_security_group_match_strategies.py b/slp_tfplan/slp_tfplan/matcher/strategies/component_sg_match_strategies.py similarity index 100% rename from slp_tfplan/slp_tfplan/matcher/strategies/component_security_group_match_strategies.py rename to slp_tfplan/slp_tfplan/matcher/strategies/component_sg_match_strategies.py diff --git a/slp_tfplan/slp_tfplan/matcher/strategies/match_strategy.py b/slp_tfplan/slp_tfplan/matcher/strategies/match_strategy.py index 35a56179..081960a6 100644 --- a/slp_tfplan/slp_tfplan/matcher/strategies/match_strategy.py +++ b/slp_tfplan/slp_tfplan/matcher/strategies/match_strategy.py @@ -37,5 +37,6 @@ class MatchStrategyContainer(DeclarativeContainer): Here are defined a list of instances for each of these groups. """ - sg_match_strategies = List() + sg_sg_match_strategies = List() + sg_sg_rule_match_strategies = List() component_sg_match_strategies = List() diff --git a/slp_tfplan/slp_tfplan/matcher/strategies/security_group_match_strategies.py b/slp_tfplan/slp_tfplan/matcher/strategies/sg_sg_match_strategies.py similarity index 86% rename from slp_tfplan/slp_tfplan/matcher/strategies/security_group_match_strategies.py rename to slp_tfplan/slp_tfplan/matcher/strategies/sg_sg_match_strategies.py index bf0ce5c8..7a4cd535 100644 --- a/slp_tfplan/slp_tfplan/matcher/strategies/security_group_match_strategies.py +++ b/slp_tfplan/slp_tfplan/matcher/strategies/sg_sg_match_strategies.py @@ -3,25 +3,26 @@ from slp_tfplan.slp_tfplan.objects.tfplan_objects import SecurityGroup - -@register(MatchStrategyContainer.sg_match_strategies) +@register(MatchStrategyContainer.sg_sg_match_strategies) class SecurityGroupByConfigurationStrategy(MatchStrategy): """ Two Security Groups SG1 and SG2 are related if the ID of SG1 is in the ingress_ids of the SG2 or if the ID of the SG2 is in the egress_ids of the SG1. """ + def are_related(self, source_security_group: SecurityGroup, target_security_group: SecurityGroup, **kwargs) -> bool: return source_security_group.id in target_security_group.ingress_sgs \ - or target_security_group.id in source_security_group.egress_sgs + or target_security_group.id in source_security_group.egress_sgs -@register(MatchStrategyContainer.sg_match_strategies) +@register(MatchStrategyContainer.sg_sg_match_strategies) class SecurityGroupByGraphStrategy(MatchStrategy): """ Two Security Groups are related if there is a straight relationship between them in the tfgraph. This means that there is a relationships between a SG1 and a SG2 with no mapped components in the middle. """ + def are_related(self, source_security_group: SecurityGroup, target_security_group: SecurityGroup, **kwargs) -> bool: return kwargs['relationships_extractor'].exist_valid_path(target_security_group.id, source_security_group.id) diff --git a/slp_tfplan/slp_tfplan/matcher/strategies/sg_sg_rule_match_strategies.py b/slp_tfplan/slp_tfplan/matcher/strategies/sg_sg_rule_match_strategies.py new file mode 100644 index 00000000..3fea3d33 --- /dev/null +++ b/slp_tfplan/slp_tfplan/matcher/strategies/sg_sg_rule_match_strategies.py @@ -0,0 +1,29 @@ +from typing import Dict + +from sl_util.sl_util.injection import register +from slp_tfplan.slp_tfplan.matcher.strategies.match_strategy import MatchStrategy, MatchStrategyContainer + + +@register(MatchStrategyContainer.sg_sg_rule_match_strategies) +class MatchSecurityGroupRuleBySecurityGroupIdStrategy(MatchStrategy): + """ + A security group rule is related with a security group by sg_rule['security_group_id'] being equals + to security_group['resource_id']. + """ + def are_related(self, security_group: Dict, security_group_rule: Dict, **kwargs) -> bool: + return security_group.get('resource_id') == security_group_rule.get('security_group_id') + + +@register(MatchStrategyContainer.sg_sg_rule_match_strategies) +class MatchSecurityGroupRuleByGraphStrategy(MatchStrategy): + """ + A security group rule is related with a security group if there is a tfgraph relationship + between the security group rule and the security group. + """ + + def are_related(self, security_group: Dict, security_group_rule: Dict, **kwargs) -> bool: + sg_resource_id = security_group.get('resource_id') + sg_rule_resource_id = security_group_rule.get('resource_id') + relationships_extractor = kwargs['relationships_extractor'] + + return relationships_extractor.exist_valid_path(sg_rule_resource_id, sg_resource_id) diff --git a/slp_tfplan/slp_tfplan/parse/tfplan_parser.py b/slp_tfplan/slp_tfplan/parse/tfplan_parser.py index 1fdb91d7..2b97b568 100644 --- a/slp_tfplan/slp_tfplan/parse/tfplan_parser.py +++ b/slp_tfplan/slp_tfplan/parse/tfplan_parser.py @@ -59,7 +59,7 @@ def __map_tfplan_resources(self): TFPlanMapper(self.otm, self.tfplan, self.mapping).map() def __load_auxiliary_resources(self): - SecurityGroupsLoader(self.otm, self.tfplan).load() + SecurityGroupsLoader(self.otm, self.tfplan, self.tfgraph).load() LaunchTemplatesLoader(self.otm, self.tfplan).load() VariablesLoader(self.otm, self.tfplan).load() diff --git a/slp_tfplan/tests/resources/tfplan/resources/ingress-cidr-from-property-tfplan-resources.json b/slp_tfplan/tests/resources/tfplan/resources/ingress-cidr-from-property-tfplan-resources.json index 3401facc..ef3ba575 100644 --- a/slp_tfplan/tests/resources/tfplan/resources/ingress-cidr-from-property-tfplan-resources.json +++ b/slp_tfplan/tests/resources/tfplan/resources/ingress-cidr-from-property-tfplan-resources.json @@ -4,12 +4,35 @@ "resource_id":"aws_security_group.alb", "resource_name":"alb", "resource_type":"aws_security_group", - "resource_properties":{ - "address":"aws_security_group.alb", - "mode":"managed", - "type":"aws_security_group", - "name":"alb", - "provider_config_key":"aws", + "resource_values":{ + "description":"Allow access traffic to ALB", + "ingress":[ + { + "cidr_blocks":[ + "0.0.0.0/32" + ], + "description":"HTTP access to ALB", + "from_port":"80", + "ipv6_cidr_blocks":[ + + ], + "prefix_list_ids":[ + + ], + "protocol":"tcp", + "security_groups":[ + + ], + "self":"false", + "to_port":"80" + } + ], + "name":"ALB SG", + "revoke_rules_on_delete":"false", + "tags":"null", + "timeouts":"null" + }, + "resource_configuration":{ "expressions":{ "description":{ "constant_value":"Allow access traffic to ALB" @@ -28,357 +51,8 @@ "module.vpc" ] } - }, - "schema_version":"1", - "planned_values":{ - "resource_mode":"managed", - "resource_provider_name":"registry.terraform.io/hashicorp/aws", - "resource_schema_version":"1", - "resource_address":"aws_security_group.alb", - "egress":[ - - ], - "ingress":[ - { - "cidr_blocks":[ - "0.0.0.0/32" - ], - "description":"HTTP access to ALB", - "from_port":"80", - "ipv6_cidr_blocks":[ - - ], - "prefix_list_ids":[ - - ], - "protocol":"tcp", - "security_groups":[ - - ], - "self":"false", - "to_port":"80" - } - ], - "tags_all":{ - - }, - "description":"Allow access traffic to ALB", - "name":"ALB SG", - "revoke_rules_on_delete":"false", - "tags":"null", - "timeouts":"null" } } - }, - { - "resource_id":"module.alb.aws_lb.this", - "resource_name":"module.alb.this", - "resource_type":"aws_lb", - "resource_properties":{ - "resource_mode":"managed", - "resource_provider_name":"registry.terraform.io/hashicorp/aws", - "resource_schema_version":"0", - "resource_address":"module.alb.aws_lb.this[0]", - "access_logs":[ - - ], - "security_groups":[ - - ], - "subnet_mapping":[ - - ], - "subnets":[ - - ], - "tags":{ - "Name":"alb" - }, - "tags_all":{ - "Name":"alb" - }, - "timeouts":{ - "create":"10m", - "delete":"10m", - "update":"10m" - }, - "customer_owned_ipv4_pool":"null", - "desync_mitigation_mode":"defensive", - "drop_invalid_header_fields":"false", - "enable_cross_zone_load_balancing":"null", - "enable_deletion_protection":"false", - "enable_http2":"true", - "enable_tls_version_and_cipher_suite_headers":"false", - "enable_waf_fail_open":"false", - "enable_xff_client_port":"false", - "idle_timeout":"900", - "internal":"false", - "ip_address_type":"ipv4", - "load_balancer_type":"application", - "name":"alb", - "name_prefix":"null", - "preserve_host_header":"false", - "xff_header_processing_mode":"append" - } - }, - { - "resource_id":"module.vpc.aws_default_network_acl.this", - "resource_name":"module.vpc.this", - "resource_type":"aws_default_network_acl", - "resource_properties":{ - "resource_mode":"managed", - "resource_provider_name":"registry.terraform.io/hashicorp/aws", - "resource_schema_version":"0", - "resource_address":"module.vpc.aws_default_network_acl.this[0]", - "egress":[ - { - "action":"allow", - "cidr_block":"", - "from_port":"0", - "icmp_code":"null", - "icmp_type":"null", - "ipv6_cidr_block":"::/0", - "protocol":"-1", - "rule_no":"101", - "to_port":"0" - }, - { - "action":"allow", - "cidr_block":"0.0.0.0/0", - "from_port":"0", - "icmp_code":"null", - "icmp_type":"null", - "ipv6_cidr_block":"", - "protocol":"-1", - "rule_no":"100", - "to_port":"0" - } - ], - "ingress":[ - { - "action":"allow", - "cidr_block":"", - "from_port":"0", - "icmp_code":"null", - "icmp_type":"null", - "ipv6_cidr_block":"::/0", - "protocol":"-1", - "rule_no":"101", - "to_port":"0" - }, - { - "action":"allow", - "cidr_block":"0.0.0.0/0", - "from_port":"0", - "icmp_code":"null", - "icmp_type":"null", - "ipv6_cidr_block":"", - "protocol":"-1", - "rule_no":"100", - "to_port":"0" - } - ], - "tags":{ - "Name":"VPC-default" - }, - "tags_all":{ - "Name":"VPC-default" - }, - "subnet_ids":"null" - } - }, - { - "resource_id":"module.vpc.aws_default_route_table.default", - "resource_name":"module.vpc.default", - "resource_type":"aws_default_route_table", - "resource_properties":{ - "resource_mode":"managed", - "resource_provider_name":"registry.terraform.io/hashicorp/aws", - "resource_schema_version":"0", - "resource_address":"module.vpc.aws_default_route_table.default[0]", - "route":[ - - ], - "tags":{ - "Name":"VPC-default" - }, - "tags_all":{ - "Name":"VPC-default" - }, - "timeouts":{ - "create":"5m", - "update":"5m" - }, - "propagating_vgws":"null" - } - }, - { - "resource_id":"module.vpc.aws_default_security_group.this", - "resource_name":"module.vpc.this", - "resource_type":"aws_default_security_group", - "resource_properties":{ - "resource_mode":"managed", - "resource_provider_name":"registry.terraform.io/hashicorp/aws", - "resource_schema_version":"1", - "resource_address":"module.vpc.aws_default_security_group.this[0]", - "egress":[ - - ], - "ingress":[ - - ], - "tags":{ - "Name":"VPC-default" - }, - "tags_all":{ - "Name":"VPC-default" - }, - "revoke_rules_on_delete":"false" - } - }, - { - "resource_id":"module.vpc.aws_internet_gateway.this", - "resource_name":"module.vpc.this", - "resource_type":"aws_internet_gateway", - "resource_properties":{ - "resource_mode":"managed", - "resource_provider_name":"registry.terraform.io/hashicorp/aws", - "resource_schema_version":"0", - "resource_address":"module.vpc.aws_internet_gateway.this[0]", - "tags":{ - "Name":"VPC" - }, - "tags_all":{ - "Name":"VPC" - }, - "timeouts":"null" - } - }, - { - "resource_id":"module.vpc.aws_route.public_internet_gateway", - "resource_name":"module.vpc.public_internet_gateway", - "resource_type":"aws_route", - "resource_properties":{ - "resource_mode":"managed", - "resource_provider_name":"registry.terraform.io/hashicorp/aws", - "resource_schema_version":"0", - "resource_address":"module.vpc.aws_route.public_internet_gateway[0]", - "timeouts":{ - "create":"5m", - "delete":"null", - "update":"null" - }, - "carrier_gateway_id":"null", - "core_network_arn":"null", - "destination_cidr_block":"0.0.0.0/0", - "destination_ipv6_cidr_block":"null", - "destination_prefix_list_id":"null", - "egress_only_gateway_id":"null", - "local_gateway_id":"null", - "nat_gateway_id":"null", - "transit_gateway_id":"null", - "vpc_endpoint_id":"null", - "vpc_peering_connection_id":"null" - } - }, - { - "resource_id":"module.vpc.aws_route_table.public", - "resource_name":"module.vpc.public", - "resource_type":"aws_route_table", - "resource_properties":{ - "resource_mode":"managed", - "resource_provider_name":"registry.terraform.io/hashicorp/aws", - "resource_schema_version":"0", - "resource_address":"module.vpc.aws_route_table.public[0]", - "propagating_vgws":[ - - ], - "route":[ - - ], - "tags":{ - "Name":"VPC-public" - }, - "tags_all":{ - "Name":"VPC-public" - }, - "timeouts":"null" - } - }, - { - "resource_id":"module.vpc.aws_route_table_association.public", - "resource_name":"module.vpc.public", - "resource_type":"aws_route_table_association", - "resource_properties":{ - "resource_mode":"managed", - "resource_provider_name":"registry.terraform.io/hashicorp/aws", - "resource_schema_version":"0", - "resource_address":"module.vpc.aws_route_table_association.public[0]", - "gateway_id":"null", - "timeouts":"null" - } - }, - { - "resource_id":"module.vpc.aws_subnet.public", - "resource_name":"module.vpc.public", - "resource_type":"aws_subnet", - "resource_properties":{ - "resource_mode":"managed", - "resource_provider_name":"registry.terraform.io/hashicorp/aws", - "resource_schema_version":"1", - "resource_address":"module.vpc.aws_subnet.public[0]", - "tags":{ - "Name":"VPC-public-azs" - }, - "tags_all":{ - "Name":"VPC-public-azs" - }, - "assign_ipv6_address_on_creation":"false", - "availability_zone_id":"azs", - "cidr_block":"10.0.0.0/16", - "customer_owned_ipv4_pool":"null", - "enable_dns64":"false", - "enable_lni_at_device_index":"null", - "enable_resource_name_dns_a_record_on_launch":"false", - "enable_resource_name_dns_aaaa_record_on_launch":"false", - "ipv6_cidr_block":"null", - "ipv6_native":"false", - "map_customer_owned_ip_on_launch":"null", - "map_public_ip_on_launch":"false", - "outpost_arn":"null", - "timeouts":"null" - } - }, - { - "resource_id":"module.vpc.aws_vpc.this", - "resource_name":"module.vpc.this", - "resource_type":"aws_vpc", - "resource_properties":{ - "resource_mode":"managed", - "resource_provider_name":"registry.terraform.io/hashicorp/aws", - "resource_schema_version":"1", - "resource_address":"module.vpc.aws_vpc.this[0]", - "tags":{ - "Name":"VPC" - }, - "tags_all":{ - "Name":"VPC" - }, - "assign_generated_ipv6_cidr_block":"null", - "cidr_block":"10.0.0.0/16", - "enable_dns_hostnames":"true", - "enable_dns_support":"true", - "instance_tenancy":"default", - "ipv4_ipam_pool_id":"null", - "ipv4_netmask_length":"null", - "ipv6_ipam_pool_id":"null", - "ipv6_netmask_length":"null" - } - } - ], - "variables":{ - "ingress_tcp_80_cidrs":{ - "value":"0.0.0.0/32" } - } + ] } \ No newline at end of file diff --git a/slp_tfplan/tests/resources/tfplan/resources/ingress-multiple-cidr-from-property-tfplan-resources.json b/slp_tfplan/tests/resources/tfplan/resources/ingress-multiple-cidr-from-property-tfplan-resources.json index 885b7551..29ecbd55 100644 --- a/slp_tfplan/tests/resources/tfplan/resources/ingress-multiple-cidr-from-property-tfplan-resources.json +++ b/slp_tfplan/tests/resources/tfplan/resources/ingress-multiple-cidr-from-property-tfplan-resources.json @@ -4,12 +4,54 @@ "resource_id":"aws_security_group.alb", "resource_name":"alb", "resource_type":"aws_security_group", - "resource_properties":{ - "address":"aws_security_group.alb", - "mode":"managed", - "type":"aws_security_group", - "name":"alb", - "provider_config_key":"aws", + "resource_values":{ + "description":"Allow access HTTP and SSH traffic", + "ingress":[ + { + "cidr_blocks":[ + "0.0.0.0/32" + ], + "description":"HTTP access to ALB", + "from_port":"80", + "ipv6_cidr_blocks":[ + + ], + "prefix_list_ids":[ + + ], + "protocol":"tcp", + "security_groups":[ + + ], + "self":"false", + "to_port":"80" + }, + { + "cidr_blocks":[ + "255.255.255.0/32" + ], + "description":"SSH access access to ALB", + "from_port":"22", + "ipv6_cidr_blocks":[ + + ], + "prefix_list_ids":[ + + ], + "protocol":"tcp", + "security_groups":[ + + ], + "self":"false", + "to_port":"22" + } + ], + "name":"ALB SG", + "revoke_rules_on_delete":"false", + "tags":"null", + "timeouts":"null" + }, + "resource_configuration":{ "expressions":{ "description":{ "constant_value":"Allow access HTTP and SSH traffic" @@ -29,379 +71,8 @@ "module.vpc" ] } - }, - "schema_version":"1", - "planned_values":{ - "resource_mode":"managed", - "resource_provider_name":"registry.terraform.io/hashicorp/aws", - "resource_schema_version":"1", - "resource_address":"aws_security_group.alb", - "egress":[ - - ], - "ingress":[ - { - "cidr_blocks":[ - "0.0.0.0/32" - ], - "description":"HTTP access to ALB", - "from_port":"80", - "ipv6_cidr_blocks":[ - - ], - "prefix_list_ids":[ - - ], - "protocol":"tcp", - "security_groups":[ - - ], - "self":"false", - "to_port":"80" - }, - { - "cidr_blocks":[ - "255.255.255.0/32" - ], - "description":"SSH access access to ALB", - "from_port":"22", - "ipv6_cidr_blocks":[ - - ], - "prefix_list_ids":[ - - ], - "protocol":"tcp", - "security_groups":[ - - ], - "self":"false", - "to_port":"22" - } - ], - "tags_all":{ - - }, - "description":"Allow access HTTP and SSH traffic", - "name":"ALB SG", - "revoke_rules_on_delete":"false", - "tags":"null", - "timeouts":"null" } } - }, - { - "resource_id":"module.alb.aws_lb.this", - "resource_name":"module.alb.this", - "resource_type":"aws_lb", - "resource_properties":{ - "resource_mode":"managed", - "resource_provider_name":"registry.terraform.io/hashicorp/aws", - "resource_schema_version":"0", - "resource_address":"module.alb.aws_lb.this[0]", - "access_logs":[ - - ], - "security_groups":[ - - ], - "subnet_mapping":[ - - ], - "subnets":[ - - ], - "tags":{ - "Name":"alb" - }, - "tags_all":{ - "Name":"alb" - }, - "timeouts":{ - "create":"10m", - "delete":"10m", - "update":"10m" - }, - "customer_owned_ipv4_pool":"null", - "desync_mitigation_mode":"defensive", - "drop_invalid_header_fields":"false", - "enable_cross_zone_load_balancing":"null", - "enable_deletion_protection":"false", - "enable_http2":"true", - "enable_tls_version_and_cipher_suite_headers":"false", - "enable_waf_fail_open":"false", - "enable_xff_client_port":"false", - "idle_timeout":"900", - "internal":"false", - "ip_address_type":"ipv4", - "load_balancer_type":"application", - "name":"alb", - "name_prefix":"null", - "preserve_host_header":"false", - "xff_header_processing_mode":"append" - } - }, - { - "resource_id":"module.vpc.aws_default_network_acl.this", - "resource_name":"module.vpc.this", - "resource_type":"aws_default_network_acl", - "resource_properties":{ - "resource_mode":"managed", - "resource_provider_name":"registry.terraform.io/hashicorp/aws", - "resource_schema_version":"0", - "resource_address":"module.vpc.aws_default_network_acl.this[0]", - "egress":[ - { - "action":"allow", - "cidr_block":"", - "from_port":"0", - "icmp_code":"null", - "icmp_type":"null", - "ipv6_cidr_block":"::/0", - "protocol":"-1", - "rule_no":"101", - "to_port":"0" - }, - { - "action":"allow", - "cidr_block":"0.0.0.0/32", - "from_port":"0", - "icmp_code":"null", - "icmp_type":"null", - "ipv6_cidr_block":"", - "protocol":"-1", - "rule_no":"100", - "to_port":"0" - } - ], - "ingress":[ - { - "action":"allow", - "cidr_block":"", - "from_port":"0", - "icmp_code":"null", - "icmp_type":"null", - "ipv6_cidr_block":"::/0", - "protocol":"-1", - "rule_no":"101", - "to_port":"0" - }, - { - "action":"allow", - "cidr_block":"0.0.0.0/32", - "from_port":"0", - "icmp_code":"null", - "icmp_type":"null", - "ipv6_cidr_block":"", - "protocol":"-1", - "rule_no":"100", - "to_port":"0" - } - ], - "tags":{ - "Name":"VPC-default" - }, - "tags_all":{ - "Name":"VPC-default" - }, - "subnet_ids":"null" - } - }, - { - "resource_id":"module.vpc.aws_default_route_table.default", - "resource_name":"module.vpc.default", - "resource_type":"aws_default_route_table", - "resource_properties":{ - "resource_mode":"managed", - "resource_provider_name":"registry.terraform.io/hashicorp/aws", - "resource_schema_version":"0", - "resource_address":"module.vpc.aws_default_route_table.default[0]", - "route":[ - - ], - "tags":{ - "Name":"VPC-default" - }, - "tags_all":{ - "Name":"VPC-default" - }, - "timeouts":{ - "create":"5m", - "update":"5m" - }, - "propagating_vgws":"null" - } - }, - { - "resource_id":"module.vpc.aws_default_security_group.this", - "resource_name":"module.vpc.this", - "resource_type":"aws_default_security_group", - "resource_properties":{ - "resource_mode":"managed", - "resource_provider_name":"registry.terraform.io/hashicorp/aws", - "resource_schema_version":"1", - "resource_address":"module.vpc.aws_default_security_group.this[0]", - "egress":[ - - ], - "ingress":[ - - ], - "tags":{ - "Name":"VPC-default" - }, - "tags_all":{ - "Name":"VPC-default" - }, - "revoke_rules_on_delete":"false" - } - }, - { - "resource_id":"module.vpc.aws_internet_gateway.this", - "resource_name":"module.vpc.this", - "resource_type":"aws_internet_gateway", - "resource_properties":{ - "resource_mode":"managed", - "resource_provider_name":"registry.terraform.io/hashicorp/aws", - "resource_schema_version":"0", - "resource_address":"module.vpc.aws_internet_gateway.this[0]", - "tags":{ - "Name":"VPC" - }, - "tags_all":{ - "Name":"VPC" - }, - "timeouts":"null" - } - }, - { - "resource_id":"module.vpc.aws_route.public_internet_gateway", - "resource_name":"module.vpc.public_internet_gateway", - "resource_type":"aws_route", - "resource_properties":{ - "resource_mode":"managed", - "resource_provider_name":"registry.terraform.io/hashicorp/aws", - "resource_schema_version":"0", - "resource_address":"module.vpc.aws_route.public_internet_gateway[0]", - "timeouts":{ - "create":"5m", - "delete":"null", - "update":"null" - }, - "carrier_gateway_id":"null", - "core_network_arn":"null", - "destination_cidr_block":"0.0.0.0/32", - "destination_ipv6_cidr_block":"null", - "destination_prefix_list_id":"null", - "egress_only_gateway_id":"null", - "local_gateway_id":"null", - "nat_gateway_id":"null", - "transit_gateway_id":"null", - "vpc_endpoint_id":"null", - "vpc_peering_connection_id":"null" - } - }, - { - "resource_id":"module.vpc.aws_route_table.public", - "resource_name":"module.vpc.public", - "resource_type":"aws_route_table", - "resource_properties":{ - "resource_mode":"managed", - "resource_provider_name":"registry.terraform.io/hashicorp/aws", - "resource_schema_version":"0", - "resource_address":"module.vpc.aws_route_table.public[0]", - "propagating_vgws":[ - - ], - "route":[ - - ], - "tags":{ - "Name":"VPC-public" - }, - "tags_all":{ - "Name":"VPC-public" - }, - "timeouts":"null" - } - }, - { - "resource_id":"module.vpc.aws_route_table_association.public", - "resource_name":"module.vpc.public", - "resource_type":"aws_route_table_association", - "resource_properties":{ - "resource_mode":"managed", - "resource_provider_name":"registry.terraform.io/hashicorp/aws", - "resource_schema_version":"0", - "resource_address":"module.vpc.aws_route_table_association.public[0]", - "gateway_id":"null", - "timeouts":"null" - } - }, - { - "resource_id":"module.vpc.aws_subnet.public", - "resource_name":"module.vpc.public", - "resource_type":"aws_subnet", - "resource_properties":{ - "resource_mode":"managed", - "resource_provider_name":"registry.terraform.io/hashicorp/aws", - "resource_schema_version":"1", - "resource_address":"module.vpc.aws_subnet.public[0]", - "tags":{ - "Name":"VPC-public-azs" - }, - "tags_all":{ - "Name":"VPC-public-azs" - }, - "assign_ipv6_address_on_creation":"false", - "availability_zone_id":"azs", - "cidr_block":"10.0.0.0/16", - "customer_owned_ipv4_pool":"null", - "enable_dns64":"false", - "enable_lni_at_device_index":"null", - "enable_resource_name_dns_a_record_on_launch":"false", - "enable_resource_name_dns_aaaa_record_on_launch":"false", - "ipv6_cidr_block":"null", - "ipv6_native":"false", - "map_customer_owned_ip_on_launch":"null", - "map_public_ip_on_launch":"false", - "outpost_arn":"null", - "timeouts":"null" - } - }, - { - "resource_id":"module.vpc.aws_vpc.this", - "resource_name":"module.vpc.this", - "resource_type":"aws_vpc", - "resource_properties":{ - "resource_mode":"managed", - "resource_provider_name":"registry.terraform.io/hashicorp/aws", - "resource_schema_version":"1", - "resource_address":"module.vpc.aws_vpc.this[0]", - "tags":{ - "Name":"VPC" - }, - "tags_all":{ - "Name":"VPC" - }, - "assign_generated_ipv6_cidr_block":"null", - "cidr_block":"10.0.0.0/16", - "enable_dns_hostnames":"true", - "enable_dns_support":"true", - "instance_tenancy":"default", - "ipv4_ipam_pool_id":"null", - "ipv4_netmask_length":"null", - "ipv6_ipam_pool_id":"null", - "ipv6_netmask_length":"null" - } - } - ], - "variables":{ - "ingress_tcp_22_cidrs":{ - "value":"22.22.22.22/32" - }, - "ingress_tcp_80_cidrs":{ - "value":"0.0.0.0/32" } - } + ] } \ No newline at end of file diff --git a/slp_tfplan/tests/resources/tfplan/resources/ingress-multiple-cidr-from-rule-tfplan-resources.json b/slp_tfplan/tests/resources/tfplan/resources/ingress-multiple-cidr-from-rule-tfplan-resources.json index b17331c0..bee3ee04 100644 --- a/slp_tfplan/tests/resources/tfplan/resources/ingress-multiple-cidr-from-rule-tfplan-resources.json +++ b/slp_tfplan/tests/resources/tfplan/resources/ingress-multiple-cidr-from-rule-tfplan-resources.json @@ -4,12 +4,14 @@ "resource_id":"aws_security_group.alb", "resource_name":"alb", "resource_type":"aws_security_group", - "resource_properties":{ - "address":"aws_security_group.alb", - "mode":"managed", - "type":"aws_security_group", - "name":"alb", - "provider_config_key":"aws", + "resource_values":{ + "description":"Allow access traffic to ALB", + "name":"ALB SG", + "revoke_rules_on_delete":"false", + "tags":"null", + "timeouts":"null" + }, + "resource_configuration":{ "expressions":{ "description":{ "constant_value":"Allow access traffic to ALB" @@ -23,27 +25,6 @@ "module.vpc" ] } - }, - "schema_version":"1", - "planned_values":{ - "resource_mode":"managed", - "resource_provider_name":"registry.terraform.io/hashicorp/aws", - "resource_schema_version":"1", - "resource_address":"aws_security_group.alb", - "egress":[ - - ], - "ingress":[ - - ], - "tags_all":{ - - }, - "description":"Allow access traffic to ALB", - "name":"ALB SG", - "revoke_rules_on_delete":"false", - "tags":"null", - "timeouts":"null" } } }, @@ -51,12 +32,22 @@ "resource_id":"aws_security_group_rule.http-ingress-1", "resource_name":"http-ingress-1", "resource_type":"aws_security_group_rule", - "resource_properties":{ - "address":"aws_security_group_rule.http-ingress-1", - "mode":"managed", - "type":"aws_security_group_rule", - "name":"http-ingress-1", - "provider_config_key":"aws", + "resource_values":{ + "cidr_blocks":[ + "255.255.255.0/32", + "255.255.255.1/32" + ], + "description":"Allows inbound traffic through port 80", + "from_port":"80", + "ipv6_cidr_blocks":"null", + "prefix_list_ids":"null", + "protocol":"tcp", + "self":"false", + "timeouts":"null", + "to_port":"80", + "type":"ingress" + }, + "resource_configuration":{ "expressions":{ "cidr_blocks":{ "references":[ @@ -84,26 +75,6 @@ "type":{ "constant_value":"ingress" } - }, - "schema_version":"2", - "planned_values":{ - "resource_mode":"managed", - "resource_provider_name":"registry.terraform.io/hashicorp/aws", - "resource_schema_version":"2", - "resource_address":"aws_security_group_rule.http-ingress-1", - "cidr_blocks":[ - "255.255.255.0/32", - "255.255.255.1/32" - ], - "description":"Allows inbound traffic through port 80", - "from_port":"80", - "ipv6_cidr_blocks":"null", - "prefix_list_ids":"null", - "protocol":"tcp", - "self":"false", - "timeouts":"null", - "to_port":"80", - "type":"ingress" } } }, @@ -111,12 +82,21 @@ "resource_id":"aws_security_group_rule.http-ingress-2", "resource_name":"http-ingress-2", "resource_type":"aws_security_group_rule", - "resource_properties":{ - "address":"aws_security_group_rule.http-ingress-2", - "mode":"managed", - "type":"aws_security_group_rule", - "name":"http-ingress-2", - "provider_config_key":"aws", + "resource_values":{ + "cidr_blocks":[ + "255.255.255.2/32" + ], + "description":"Allows inbound traffic through port 443", + "from_port":"443", + "ipv6_cidr_blocks":"null", + "prefix_list_ids":"null", + "protocol":"tcp", + "self":"false", + "timeouts":"null", + "to_port":"443", + "type":"ingress" + }, + "resource_configuration":{ "expressions":{ "cidr_blocks":{ "references":[ @@ -144,25 +124,6 @@ "type":{ "constant_value":"ingress" } - }, - "schema_version":"2", - "planned_values":{ - "resource_mode":"managed", - "resource_provider_name":"registry.terraform.io/hashicorp/aws", - "resource_schema_version":"2", - "resource_address":"aws_security_group_rule.http-ingress-2", - "cidr_blocks":[ - "255.255.255.2/32" - ], - "description":"Allows inbound traffic through port 443", - "from_port":"443", - "ipv6_cidr_blocks":"null", - "prefix_list_ids":"null", - "protocol":"tcp", - "self":"false", - "timeouts":"null", - "to_port":"443", - "type":"ingress" } } }, @@ -170,12 +131,21 @@ "resource_id":"aws_security_group_rule.http-ingress-3", "resource_name":"http-ingress-3", "resource_type":"aws_security_group_rule", - "resource_properties":{ - "address":"aws_security_group_rule.http-ingress-3", - "mode":"managed", - "type":"aws_security_group_rule", - "name":"http-ingress-3", - "provider_config_key":"aws", + "resource_values":{ + "cidr_blocks":[ + "0.0.0.0/32" + ], + "description":"Allows inbound traffic through port 443", + "from_port":"0", + "ipv6_cidr_blocks":"null", + "prefix_list_ids":"null", + "protocol":"icmp", + "self":"false", + "timeouts":"null", + "to_port":"0", + "type":"ingress" + }, + "resource_configuration":{ "expressions":{ "cidr_blocks":{ "references":[ @@ -203,346 +173,8 @@ "type":{ "constant_value":"ingress" } - }, - "schema_version":"2", - "planned_values":{ - "resource_mode":"managed", - "resource_provider_name":"registry.terraform.io/hashicorp/aws", - "resource_schema_version":"2", - "resource_address":"aws_security_group_rule.http-ingress-3", - "cidr_blocks":[ - "0.0.0.0/32" - ], - "description":"Allows inbound traffic through port 443", - "from_port":"0", - "ipv6_cidr_blocks":"null", - "prefix_list_ids":"null", - "protocol":"icmp", - "self":"false", - "timeouts":"null", - "to_port":"0", - "type":"ingress" } } - }, - { - "resource_id":"module.alb.aws_lb.this", - "resource_name":"module.alb.this", - "resource_type":"aws_lb", - "resource_properties":{ - "resource_mode":"managed", - "resource_provider_name":"registry.terraform.io/hashicorp/aws", - "resource_schema_version":"0", - "resource_address":"module.alb.aws_lb.this[0]", - "access_logs":[ - - ], - "security_groups":[ - - ], - "subnet_mapping":[ - - ], - "subnets":[ - - ], - "tags":{ - "Name":"alb" - }, - "tags_all":{ - "Name":"alb" - }, - "timeouts":{ - "create":"10m", - "delete":"10m", - "update":"10m" - }, - "customer_owned_ipv4_pool":"null", - "desync_mitigation_mode":"defensive", - "drop_invalid_header_fields":"false", - "enable_cross_zone_load_balancing":"null", - "enable_deletion_protection":"false", - "enable_http2":"true", - "enable_tls_version_and_cipher_suite_headers":"false", - "enable_waf_fail_open":"false", - "enable_xff_client_port":"false", - "idle_timeout":"900", - "internal":"false", - "ip_address_type":"ipv4", - "load_balancer_type":"application", - "name":"alb", - "name_prefix":"null", - "preserve_host_header":"false", - "xff_header_processing_mode":"append" - } - }, - { - "resource_id":"module.vpc.aws_default_network_acl.this", - "resource_name":"module.vpc.this", - "resource_type":"aws_default_network_acl", - "resource_properties":{ - "resource_mode":"managed", - "resource_provider_name":"registry.terraform.io/hashicorp/aws", - "resource_schema_version":"0", - "resource_address":"module.vpc.aws_default_network_acl.this[0]", - "egress":[ - { - "action":"allow", - "cidr_block":"", - "from_port":"0", - "icmp_code":"null", - "icmp_type":"null", - "ipv6_cidr_block":"::/0", - "protocol":"-1", - "rule_no":"101", - "to_port":"0" - }, - { - "action":"allow", - "cidr_block":"0.0.0.0/0", - "from_port":"0", - "icmp_code":"null", - "icmp_type":"null", - "ipv6_cidr_block":"", - "protocol":"-1", - "rule_no":"100", - "to_port":"0" - } - ], - "ingress":[ - { - "action":"allow", - "cidr_block":"", - "from_port":"0", - "icmp_code":"null", - "icmp_type":"null", - "ipv6_cidr_block":"::/0", - "protocol":"-1", - "rule_no":"101", - "to_port":"0" - }, - { - "action":"allow", - "cidr_block":"0.0.0.0/0", - "from_port":"0", - "icmp_code":"null", - "icmp_type":"null", - "ipv6_cidr_block":"", - "protocol":"-1", - "rule_no":"100", - "to_port":"0" - } - ], - "tags":{ - "Name":"VPC-default" - }, - "tags_all":{ - "Name":"VPC-default" - }, - "subnet_ids":"null" - } - }, - { - "resource_id":"module.vpc.aws_default_route_table.default", - "resource_name":"module.vpc.default", - "resource_type":"aws_default_route_table", - "resource_properties":{ - "resource_mode":"managed", - "resource_provider_name":"registry.terraform.io/hashicorp/aws", - "resource_schema_version":"0", - "resource_address":"module.vpc.aws_default_route_table.default[0]", - "route":[ - - ], - "tags":{ - "Name":"VPC-default" - }, - "tags_all":{ - "Name":"VPC-default" - }, - "timeouts":{ - "create":"5m", - "update":"5m" - }, - "propagating_vgws":"null" - } - }, - { - "resource_id":"module.vpc.aws_default_security_group.this", - "resource_name":"module.vpc.this", - "resource_type":"aws_default_security_group", - "resource_properties":{ - "resource_mode":"managed", - "resource_provider_name":"registry.terraform.io/hashicorp/aws", - "resource_schema_version":"1", - "resource_address":"module.vpc.aws_default_security_group.this[0]", - "egress":[ - - ], - "ingress":[ - - ], - "tags":{ - "Name":"VPC-default" - }, - "tags_all":{ - "Name":"VPC-default" - }, - "revoke_rules_on_delete":"false" - } - }, - { - "resource_id":"module.vpc.aws_internet_gateway.this", - "resource_name":"module.vpc.this", - "resource_type":"aws_internet_gateway", - "resource_properties":{ - "resource_mode":"managed", - "resource_provider_name":"registry.terraform.io/hashicorp/aws", - "resource_schema_version":"0", - "resource_address":"module.vpc.aws_internet_gateway.this[0]", - "tags":{ - "Name":"VPC" - }, - "tags_all":{ - "Name":"VPC" - }, - "timeouts":"null" - } - }, - { - "resource_id":"module.vpc.aws_route.public_internet_gateway", - "resource_name":"module.vpc.public_internet_gateway", - "resource_type":"aws_route", - "resource_properties":{ - "resource_mode":"managed", - "resource_provider_name":"registry.terraform.io/hashicorp/aws", - "resource_schema_version":"0", - "resource_address":"module.vpc.aws_route.public_internet_gateway[0]", - "timeouts":{ - "create":"5m", - "delete":"null", - "update":"null" - }, - "carrier_gateway_id":"null", - "core_network_arn":"null", - "destination_cidr_block":"0.0.0.0/0", - "destination_ipv6_cidr_block":"null", - "destination_prefix_list_id":"null", - "egress_only_gateway_id":"null", - "local_gateway_id":"null", - "nat_gateway_id":"null", - "transit_gateway_id":"null", - "vpc_endpoint_id":"null", - "vpc_peering_connection_id":"null" - } - }, - { - "resource_id":"module.vpc.aws_route_table.public", - "resource_name":"module.vpc.public", - "resource_type":"aws_route_table", - "resource_properties":{ - "resource_mode":"managed", - "resource_provider_name":"registry.terraform.io/hashicorp/aws", - "resource_schema_version":"0", - "resource_address":"module.vpc.aws_route_table.public[0]", - "propagating_vgws":[ - - ], - "route":[ - - ], - "tags":{ - "Name":"VPC-public" - }, - "tags_all":{ - "Name":"VPC-public" - }, - "timeouts":"null" - } - }, - { - "resource_id":"module.vpc.aws_route_table_association.public", - "resource_name":"module.vpc.public", - "resource_type":"aws_route_table_association", - "resource_properties":{ - "resource_mode":"managed", - "resource_provider_name":"registry.terraform.io/hashicorp/aws", - "resource_schema_version":"0", - "resource_address":"module.vpc.aws_route_table_association.public[0]", - "gateway_id":"null", - "timeouts":"null" - } - }, - { - "resource_id":"module.vpc.aws_subnet.public", - "resource_name":"module.vpc.public", - "resource_type":"aws_subnet", - "resource_properties":{ - "resource_mode":"managed", - "resource_provider_name":"registry.terraform.io/hashicorp/aws", - "resource_schema_version":"1", - "resource_address":"module.vpc.aws_subnet.public[0]", - "tags":{ - "Name":"VPC-public-azs" - }, - "tags_all":{ - "Name":"VPC-public-azs" - }, - "assign_ipv6_address_on_creation":"false", - "availability_zone_id":"azs", - "cidr_block":"10.0.0.0/16", - "customer_owned_ipv4_pool":"null", - "enable_dns64":"false", - "enable_lni_at_device_index":"null", - "enable_resource_name_dns_a_record_on_launch":"false", - "enable_resource_name_dns_aaaa_record_on_launch":"false", - "ipv6_cidr_block":"null", - "ipv6_native":"false", - "map_customer_owned_ip_on_launch":"null", - "map_public_ip_on_launch":"false", - "outpost_arn":"null", - "timeouts":"null" - } - }, - { - "resource_id":"module.vpc.aws_vpc.this", - "resource_name":"module.vpc.this", - "resource_type":"aws_vpc", - "resource_properties":{ - "resource_mode":"managed", - "resource_provider_name":"registry.terraform.io/hashicorp/aws", - "resource_schema_version":"1", - "resource_address":"module.vpc.aws_vpc.this[0]", - "tags":{ - "Name":"VPC" - }, - "tags_all":{ - "Name":"VPC" - }, - "assign_generated_ipv6_cidr_block":"null", - "cidr_block":"10.0.0.0/16", - "enable_dns_hostnames":"true", - "enable_dns_support":"true", - "instance_tenancy":"default", - "ipv4_ipam_pool_id":"null", - "ipv4_netmask_length":"null", - "ipv6_ipam_pool_id":"null", - "ipv6_netmask_length":"null" - } - } - ], - "variables":{ - "ingress_icmp_ip":{ - "value":"0.0.0.0" - }, - "ingress_tcp_443_ip":{ - "value":"25.0.16.92" - }, - "ingress_tcp_80_cidrs":{ - "value":[ - "255.255.255.0/32", - "255.255.255.1/32" - ] } - } + ] } \ No newline at end of file diff --git a/slp_tfplan/tests/resources/tfplan/resources/ingress-multiple-security-groups-tfplan-resources.json b/slp_tfplan/tests/resources/tfplan/resources/ingress-multiple-security-groups-tfplan-resources.json index e0839b47..57cfa8b3 100644 --- a/slp_tfplan/tests/resources/tfplan/resources/ingress-multiple-security-groups-tfplan-resources.json +++ b/slp_tfplan/tests/resources/tfplan/resources/ingress-multiple-security-groups-tfplan-resources.json @@ -4,12 +4,23 @@ "resource_id":"aws_security_group.alb", "resource_name":"alb", "resource_type":"aws_security_group", - "resource_properties":{ - "address":"aws_security_group.alb", - "mode":"managed", - "type":"aws_security_group", - "name":"alb", - "provider_config_key":"aws", + "resource_values":{ + "egress":[ + + ], + "ingress":[ + + ], + "tags_all":{ + + }, + "description":"Allow access traffic to ALB", + "name":"ALB SG", + "revoke_rules_on_delete":"false", + "tags":"null", + "timeouts":"null" + }, + "resource_configuration":{ "expressions":{ "description":{ "constant_value":"Allow access traffic to ALB" @@ -23,27 +34,6 @@ "module.vpc" ] } - }, - "schema_version":"1", - "planned_values":{ - "resource_mode":"managed", - "resource_provider_name":"registry.terraform.io/hashicorp/aws", - "resource_schema_version":"1", - "resource_address":"aws_security_group.alb", - "egress":[ - - ], - "ingress":[ - - ], - "tags_all":{ - - }, - "description":"Allow access traffic to ALB", - "name":"ALB SG", - "revoke_rules_on_delete":"false", - "tags":"null", - "timeouts":"null" } } }, @@ -51,12 +41,41 @@ "resource_id":"aws_security_group.alb2", "resource_name":"alb2", "resource_type":"aws_security_group", - "resource_properties":{ - "address":"aws_security_group.alb2", - "mode":"managed", - "type":"aws_security_group", - "name":"alb2", - "provider_config_key":"aws", + "resource_values":{ + "egress":[ + + ], + "ingress":[ + { + "cidr_blocks":[ + "255.255.0.0/32" + ], + "description":"HTTP access from ALB", + "from_port":"80", + "ipv6_cidr_blocks":[ + + ], + "prefix_list_ids":[ + + ], + "protocol":"tcp", + "security_groups":[ + + ], + "self":"false", + "to_port":"80" + } + ], + "tags_all":{ + + }, + "description":"Allow access traffic to ALB", + "name":"ALB SG", + "revoke_rules_on_delete":"false", + "tags":"null", + "timeouts":"null" + }, + "resource_configuration":{ "expressions":{ "description":{ "constant_value":"Allow access traffic to ALB" @@ -87,45 +106,6 @@ "module.vpc" ] } - }, - "schema_version":"1", - "planned_values":{ - "resource_mode":"managed", - "resource_provider_name":"registry.terraform.io/hashicorp/aws", - "resource_schema_version":"1", - "resource_address":"aws_security_group.alb2", - "egress":[ - - ], - "ingress":[ - { - "cidr_blocks":[ - "255.255.0.0/32" - ], - "description":"HTTP access from ALB", - "from_port":"80", - "ipv6_cidr_blocks":[ - - ], - "prefix_list_ids":[ - - ], - "protocol":"tcp", - "security_groups":[ - - ], - "self":"false", - "to_port":"80" - } - ], - "tags_all":{ - - }, - "description":"Allow access traffic to ALB", - "name":"ALB SG", - "revoke_rules_on_delete":"false", - "tags":"null", - "timeouts":"null" } } }, @@ -133,12 +113,21 @@ "resource_id":"aws_security_group_rule.http-ingress-1", "resource_name":"http-ingress-1", "resource_type":"aws_security_group_rule", - "resource_properties":{ - "address":"aws_security_group_rule.http-ingress-1", - "mode":"managed", - "type":"aws_security_group_rule", - "name":"http-ingress-1", - "provider_config_key":"aws", + "resource_values":{ + "cidr_blocks":[ + "0.0.0.0/24" + ], + "description":"Allows inbound traffic through port 80", + "from_port":"80", + "ipv6_cidr_blocks":"null", + "prefix_list_ids":"null", + "protocol":"tcp", + "self":"false", + "timeouts":"null", + "to_port":"80", + "type":"ingress" + }, + "resource_configuration":{ "expressions":{ "cidr_blocks":{ "constant_value":[ @@ -166,332 +155,8 @@ "type":{ "constant_value":"ingress" } - }, - "schema_version":"2", - "planned_values":{ - "resource_mode":"managed", - "resource_provider_name":"registry.terraform.io/hashicorp/aws", - "resource_schema_version":"2", - "resource_address":"aws_security_group_rule.http-ingress-1", - "cidr_blocks":[ - "0.0.0.0/24" - ], - "description":"Allows inbound traffic through port 80", - "from_port":"80", - "ipv6_cidr_blocks":"null", - "prefix_list_ids":"null", - "protocol":"tcp", - "self":"false", - "timeouts":"null", - "to_port":"80", - "type":"ingress" } } - }, - { - "resource_id":"module.alb.aws_lb.this", - "resource_name":"module.alb.this", - "resource_type":"aws_lb", - "resource_properties":{ - "resource_mode":"managed", - "resource_provider_name":"registry.terraform.io/hashicorp/aws", - "resource_schema_version":"0", - "resource_address":"module.alb.aws_lb.this[0]", - "access_logs":[ - - ], - "security_groups":[ - - ], - "subnet_mapping":[ - - ], - "subnets":[ - - ], - "tags":{ - "Name":"alb" - }, - "tags_all":{ - "Name":"alb" - }, - "timeouts":{ - "create":"10m", - "delete":"10m", - "update":"10m" - }, - "customer_owned_ipv4_pool":"null", - "desync_mitigation_mode":"defensive", - "drop_invalid_header_fields":"false", - "enable_cross_zone_load_balancing":"null", - "enable_deletion_protection":"false", - "enable_http2":"true", - "enable_tls_version_and_cipher_suite_headers":"false", - "enable_waf_fail_open":"false", - "enable_xff_client_port":"false", - "idle_timeout":"900", - "internal":"false", - "ip_address_type":"ipv4", - "load_balancer_type":"application", - "name":"alb", - "name_prefix":"null", - "preserve_host_header":"false", - "xff_header_processing_mode":"append" - } - }, - { - "resource_id":"module.vpc.aws_default_network_acl.this", - "resource_name":"module.vpc.this", - "resource_type":"aws_default_network_acl", - "resource_properties":{ - "resource_mode":"managed", - "resource_provider_name":"registry.terraform.io/hashicorp/aws", - "resource_schema_version":"0", - "resource_address":"module.vpc.aws_default_network_acl.this[0]", - "egress":[ - { - "action":"allow", - "cidr_block":"", - "from_port":"0", - "icmp_code":"null", - "icmp_type":"null", - "ipv6_cidr_block":"::/0", - "protocol":"-1", - "rule_no":"101", - "to_port":"0" - }, - { - "action":"allow", - "cidr_block":"0.0.0.0/0", - "from_port":"0", - "icmp_code":"null", - "icmp_type":"null", - "ipv6_cidr_block":"", - "protocol":"-1", - "rule_no":"100", - "to_port":"0" - } - ], - "ingress":[ - { - "action":"allow", - "cidr_block":"", - "from_port":"0", - "icmp_code":"null", - "icmp_type":"null", - "ipv6_cidr_block":"::/0", - "protocol":"-1", - "rule_no":"101", - "to_port":"0" - }, - { - "action":"allow", - "cidr_block":"0.0.0.0/0", - "from_port":"0", - "icmp_code":"null", - "icmp_type":"null", - "ipv6_cidr_block":"", - "protocol":"-1", - "rule_no":"100", - "to_port":"0" - } - ], - "tags":{ - "Name":"VPC-default" - }, - "tags_all":{ - "Name":"VPC-default" - }, - "subnet_ids":"null" - } - }, - { - "resource_id":"module.vpc.aws_default_route_table.default", - "resource_name":"module.vpc.default", - "resource_type":"aws_default_route_table", - "resource_properties":{ - "resource_mode":"managed", - "resource_provider_name":"registry.terraform.io/hashicorp/aws", - "resource_schema_version":"0", - "resource_address":"module.vpc.aws_default_route_table.default[0]", - "route":[ - - ], - "tags":{ - "Name":"VPC-default" - }, - "tags_all":{ - "Name":"VPC-default" - }, - "timeouts":{ - "create":"5m", - "update":"5m" - }, - "propagating_vgws":"null" - } - }, - { - "resource_id":"module.vpc.aws_default_security_group.this", - "resource_name":"module.vpc.this", - "resource_type":"aws_default_security_group", - "resource_properties":{ - "resource_mode":"managed", - "resource_provider_name":"registry.terraform.io/hashicorp/aws", - "resource_schema_version":"1", - "resource_address":"module.vpc.aws_default_security_group.this[0]", - "egress":[ - - ], - "ingress":[ - - ], - "tags":{ - "Name":"VPC-default" - }, - "tags_all":{ - "Name":"VPC-default" - }, - "revoke_rules_on_delete":"false" - } - }, - { - "resource_id":"module.vpc.aws_internet_gateway.this", - "resource_name":"module.vpc.this", - "resource_type":"aws_internet_gateway", - "resource_properties":{ - "resource_mode":"managed", - "resource_provider_name":"registry.terraform.io/hashicorp/aws", - "resource_schema_version":"0", - "resource_address":"module.vpc.aws_internet_gateway.this[0]", - "tags":{ - "Name":"VPC" - }, - "tags_all":{ - "Name":"VPC" - }, - "timeouts":"null" - } - }, - { - "resource_id":"module.vpc.aws_route.public_internet_gateway", - "resource_name":"module.vpc.public_internet_gateway", - "resource_type":"aws_route", - "resource_properties":{ - "resource_mode":"managed", - "resource_provider_name":"registry.terraform.io/hashicorp/aws", - "resource_schema_version":"0", - "resource_address":"module.vpc.aws_route.public_internet_gateway[0]", - "timeouts":{ - "create":"5m", - "delete":"null", - "update":"null" - }, - "carrier_gateway_id":"null", - "core_network_arn":"null", - "destination_cidr_block":"0.0.0.0/0", - "destination_ipv6_cidr_block":"null", - "destination_prefix_list_id":"null", - "egress_only_gateway_id":"null", - "local_gateway_id":"null", - "nat_gateway_id":"null", - "transit_gateway_id":"null", - "vpc_endpoint_id":"null", - "vpc_peering_connection_id":"null" - } - }, - { - "resource_id":"module.vpc.aws_route_table.public", - "resource_name":"module.vpc.public", - "resource_type":"aws_route_table", - "resource_properties":{ - "resource_mode":"managed", - "resource_provider_name":"registry.terraform.io/hashicorp/aws", - "resource_schema_version":"0", - "resource_address":"module.vpc.aws_route_table.public[0]", - "propagating_vgws":[ - - ], - "route":[ - - ], - "tags":{ - "Name":"VPC-public" - }, - "tags_all":{ - "Name":"VPC-public" - }, - "timeouts":"null" - } - }, - { - "resource_id":"module.vpc.aws_route_table_association.public", - "resource_name":"module.vpc.public", - "resource_type":"aws_route_table_association", - "resource_properties":{ - "resource_mode":"managed", - "resource_provider_name":"registry.terraform.io/hashicorp/aws", - "resource_schema_version":"0", - "resource_address":"module.vpc.aws_route_table_association.public[0]", - "gateway_id":"null", - "timeouts":"null" - } - }, - { - "resource_id":"module.vpc.aws_subnet.public", - "resource_name":"module.vpc.public", - "resource_type":"aws_subnet", - "resource_properties":{ - "resource_mode":"managed", - "resource_provider_name":"registry.terraform.io/hashicorp/aws", - "resource_schema_version":"1", - "resource_address":"module.vpc.aws_subnet.public[0]", - "tags":{ - "Name":"VPC-public-azs" - }, - "tags_all":{ - "Name":"VPC-public-azs" - }, - "assign_ipv6_address_on_creation":"false", - "availability_zone_id":"azs", - "cidr_block":"10.0.0.0/16", - "customer_owned_ipv4_pool":"null", - "enable_dns64":"false", - "enable_lni_at_device_index":"null", - "enable_resource_name_dns_a_record_on_launch":"false", - "enable_resource_name_dns_aaaa_record_on_launch":"false", - "ipv6_cidr_block":"null", - "ipv6_native":"false", - "map_customer_owned_ip_on_launch":"null", - "map_public_ip_on_launch":"false", - "outpost_arn":"null", - "timeouts":"null" - } - }, - { - "resource_id":"module.vpc.aws_vpc.this", - "resource_name":"module.vpc.this", - "resource_type":"aws_vpc", - "resource_properties":{ - "resource_mode":"managed", - "resource_provider_name":"registry.terraform.io/hashicorp/aws", - "resource_schema_version":"1", - "resource_address":"module.vpc.aws_vpc.this[0]", - "tags":{ - "Name":"VPC" - }, - "tags_all":{ - "Name":"VPC" - }, - "assign_generated_ipv6_cidr_block":"null", - "cidr_block":"10.0.0.0/16", - "enable_dns_hostnames":"true", - "enable_dns_support":"true", - "instance_tenancy":"default", - "ipv4_ipam_pool_id":"null", - "ipv4_netmask_length":"null", - "ipv6_ipam_pool_id":"null", - "ipv6_netmask_length":"null" - } } ] } \ No newline at end of file diff --git a/slp_tfplan/tests/unit/load/test_security_groups_loader.py b/slp_tfplan/tests/unit/load/test_security_groups_loader.py index 04e0a074..c235c783 100644 --- a/slp_tfplan/tests/unit/load/test_security_groups_loader.py +++ b/slp_tfplan/tests/unit/load/test_security_groups_loader.py @@ -1,5 +1,7 @@ import json -from unittest.mock import MagicMock +from unittest.mock import MagicMock, patch + +from pytest import mark, param from sl_util.sl_util.file_utils import get_byte_data from slp_tfplan.slp_tfplan.load.security_groups_loader import SecurityGroupsLoader @@ -13,9 +15,12 @@ def test_load_ingress_cidr_from_property(self): # GIVEN a TFPlanOTM and a TFPlanResources tf_plan_resources = json.loads(get_byte_data(ingress_cidr_from_property)) otm = MagicMock(security_groups=[]) + graph = MagicMock() # WHEN the SecurityGroupsLoader is called - SecurityGroupsLoader(otm, tf_plan_resources).load() + sg_loader = SecurityGroupsLoader(otm, tf_plan_resources, graph) + with patch('slp_tfplan.slp_tfplan.matcher.sg_and_sgrules_matcher.SGAndSGRulesMatcher.match', return_value=[]): + sg_loader.load() # THEN the TFPlanOTM should have the expected SecurityGroups assert len(otm.security_groups) == 1 @@ -31,9 +36,12 @@ def test_load_multiple_ingress_cidr_from_property(self): # GIVEN a TFPlanOTM and a TFPlanResources tf_plan_resources = json.loads(get_byte_data(ingress_multiple_cidr_from_property)) otm = MagicMock(security_groups=[]) + graph = MagicMock() # WHEN the SecurityGroupsLoader is called - SecurityGroupsLoader(otm, tf_plan_resources).load() + sg_loader = SecurityGroupsLoader(otm, tf_plan_resources, graph) + with patch('slp_tfplan.slp_tfplan.matcher.sg_and_sgrules_matcher.SGAndSGRulesMatcher.match', return_value=[]): + sg_loader.load() # THEN the TFPlanOTM should have the expected SecurityGroups assert len(otm.security_groups) == 1 @@ -51,13 +59,22 @@ def test_load_multiple_ingress_cidr_from_property(self): assert otm.security_groups[0].ingress_cidr[1].from_port == '22' assert otm.security_groups[0].ingress_cidr[1].to_port == '22' - def test_load_multiple_ingress_cidr_from_rule(self): + @mark.parametrize('sg_rules_related', [param( + ["aws_security_group_rule.http-ingress-1", + "aws_security_group_rule.http-ingress-2", + "aws_security_group_rule.http-ingress-3"], id='sg rules related')]) + def test_load_multiple_ingress_cidr_from_rule(self, sg_rules_related): # GIVEN a TFPlanOTM and a TFPlanResources tf_plan_resources = json.loads(get_byte_data(ingress_multiple_cidr_from_rule)) otm = MagicMock(security_groups=[]) + graph = MagicMock() # WHEN the SecurityGroupsLoader is called - SecurityGroupsLoader(otm, tf_plan_resources).load() + sg_loader = SecurityGroupsLoader(otm, tf_plan_resources, graph) + with patch('slp_tfplan.slp_tfplan.matcher.sg_and_sgrules_matcher.SGAndSGRulesMatcher.match', + return_value=list(filter(lambda sg_rule: sg_rule['resource_id'] + in sg_rules_related, sg_loader._sg_rules))): + sg_loader.load() # THEN the TFPlanOTM should have the expected SecurityGroups assert len(otm.security_groups) == 1 @@ -85,9 +102,10 @@ def test_load_multiple_security_groups(self): # GIVEN a TFPlanOTM and a TFPlanResources tf_plan_resources = json.loads(get_byte_data(ingress_multiple_security_groups)) otm = MagicMock(security_groups=[]) + graph = MagicMock() # WHEN the SecurityGroupsLoader is called - SecurityGroupsLoader(otm, tf_plan_resources).load() + SecurityGroupsLoader(otm, tf_plan_resources, graph).load() # THEN the TFPlanOTM should have the expected SecurityGroups assert len(otm.security_groups) == 2 diff --git a/slp_tfplan/tests/unit/load/test_tfplan_loader.py b/slp_tfplan/tests/unit/load/test_tfplan_loader.py index 70819746..ca0df787 100644 --- a/slp_tfplan/tests/unit/load/test_tfplan_loader.py +++ b/slp_tfplan/tests/unit/load/test_tfplan_loader.py @@ -7,12 +7,12 @@ from networkx import DiGraph from pytest import raises, mark, param, fixture +from sl_util.sl_util.str_utils import get_bytes +from slp_base import LoadingIacFileError from slp_tfplan.slp_tfplan.load.tfplan_loader import TFPlanLoader from slp_tfplan.tests.resources import test_resource_paths -from slp_base import LoadingIacFileError +from slp_tfplan.tests.util.asserts import assert_resource_values from slp_tfplan.tests.util.builders import build_tfplan, generate_resources, generate_child_modules -from slp_tfplan.tests.util.asserts import assert_common_properties -from sl_util.sl_util.str_utils import get_bytes INVALID_YAML = test_resource_paths.invalid_yaml TF_FILE_YAML_EXCEPTION = JSONDecodeError('HLC2 cannot be processed as JSON', doc='sample-doc', pos=0) @@ -77,9 +77,7 @@ def test_load_no_modules(self, yaml_mock): assert resource['resource_type'] == f'r{i}-type' assert resource['resource_name'] == f'r{i}-name' - properties = resource['resource_properties'] - assert_common_properties(properties) - assert properties['resource_address'] == f'r{i}-addr' + assert_resource_values(resource['resource_values']) @patch('yaml.load') def test_load_only_modules(self, yaml_mock): @@ -108,9 +106,7 @@ def test_load_only_modules(self, yaml_mock): assert resource['resource_type'] == f'r{child_index}-type' assert resource['resource_name'] == f'{module_address}.r{child_index}-name' - properties = resource['resource_properties'] - assert properties['resource_address'] == f'r{child_index}-addr' - assert_common_properties(properties) + assert_resource_values(resource['resource_values']) resource_index += 1 @@ -138,9 +134,7 @@ def test_load_nested_modules(self, yaml_mock): assert resource['resource_type'] == 'r1-type' assert resource['resource_name'] == 'cm1-addr.cm1-addr.r1-name' - properties = resource['resource_properties'] - assert properties['resource_address'] == 'r1-addr' - assert_common_properties(properties) + assert_resource_values(resource['resource_values']) @patch('yaml.load') def test_load_complex_structure(self, yaml_mock): @@ -165,9 +159,7 @@ def test_load_complex_structure(self, yaml_mock): assert resource['resource_type'] == 'r1-type' assert resource['resource_name'] == 'r1-name' - properties = resource['resource_properties'] - assert properties['resource_address'] == 'r1-addr' - assert_common_properties(properties) + assert_resource_values(resource['resource_values']) # AND resource_type, resource_name and resource_properties from child modules are right resource = resources[1] @@ -175,9 +167,7 @@ def test_load_complex_structure(self, yaml_mock): assert resource['resource_type'] == 'r1-type' assert resource['resource_name'] == 'cm1-addr.r1-name' - properties = resource['resource_properties'] - assert properties['resource_address'] == 'r1-addr' - assert_common_properties(properties) + assert_resource_values(resource['resource_values']) @patch('yaml.load') def test_load_resources_same_name(self, yaml_mock): diff --git a/slp_tfplan/tests/unit/matcher/strategies/test_component_security_group_match_strategies.py b/slp_tfplan/tests/unit/matcher/strategies/test_component_sg_match_strategies.py similarity index 97% rename from slp_tfplan/tests/unit/matcher/strategies/test_component_security_group_match_strategies.py rename to slp_tfplan/tests/unit/matcher/strategies/test_component_sg_match_strategies.py index c8dec675..70af4a24 100644 --- a/slp_tfplan/tests/unit/matcher/strategies/test_component_security_group_match_strategies.py +++ b/slp_tfplan/tests/unit/matcher/strategies/test_component_sg_match_strategies.py @@ -3,7 +3,7 @@ from pytest import mark, param -from slp_tfplan.slp_tfplan.matcher.strategies.component_security_group_match_strategies import \ +from slp_tfplan.slp_tfplan.matcher.strategies.component_sg_match_strategies import \ ComponentMatchStrategySecurityGroupByGraphStrategy, ComponentSecurityGroupByLaunchTemplateStrategyMatchStrategy diff --git a/slp_tfplan/tests/unit/matcher/strategies/test_match_strategy.py b/slp_tfplan/tests/unit/matcher/strategies/test_match_strategy.py index 349c3ff8..f01109ec 100644 --- a/slp_tfplan/tests/unit/matcher/strategies/test_match_strategy.py +++ b/slp_tfplan/tests/unit/matcher/strategies/test_match_strategy.py @@ -19,11 +19,16 @@ def test_get_strategies(self): component_sg_match_strategy_instances = match_strategy_container.component_sg_match_strategies # AND all the instances for sg_match_strategies in MatchStrategyContainer - sg_match_strategy_instances = match_strategy_container.sg_match_strategies + sg_match_strategy_instances = match_strategy_container.sg_sg_match_strategies + + # AND all the instances for sg_rule_match_strategies in MatchStrategyContainer + sg_rule_match_strategy_instances = match_strategy_container.sg_sg_rule_match_strategies # WHEN we merge all instances and extract their classes - all_instance_classes = get_instance_classes(component_sg_match_strategy_instances) + \ - get_instance_classes(sg_match_strategy_instances) + all_instance_classes = \ + get_instance_classes(component_sg_match_strategy_instances) + \ + get_instance_classes(sg_match_strategy_instances) + \ + get_instance_classes(sg_rule_match_strategy_instances) # THEN the subclasses and the instances match assert match_strategy_subclasses == all_instance_classes diff --git a/slp_tfplan/tests/unit/matcher/strategies/test_security_group_match_strategies.py b/slp_tfplan/tests/unit/matcher/strategies/test_sg_sg_match_strategies.py similarity index 97% rename from slp_tfplan/tests/unit/matcher/strategies/test_security_group_match_strategies.py rename to slp_tfplan/tests/unit/matcher/strategies/test_sg_sg_match_strategies.py index a994fc70..75cc326a 100644 --- a/slp_tfplan/tests/unit/matcher/strategies/test_security_group_match_strategies.py +++ b/slp_tfplan/tests/unit/matcher/strategies/test_sg_sg_match_strategies.py @@ -2,7 +2,7 @@ from pytest import mark, param -from slp_tfplan.slp_tfplan.matcher.strategies.security_group_match_strategies import \ +from slp_tfplan.slp_tfplan.matcher.strategies.sg_sg_match_strategies import \ SecurityGroupByGraphStrategy, SecurityGroupByConfigurationStrategy from slp_tfplan.slp_tfplan.objects.tfplan_objects import SecurityGroup diff --git a/slp_tfplan/tests/unit/matcher/strategies/test_sg_sgrule_match_strategies.py b/slp_tfplan/tests/unit/matcher/strategies/test_sg_sgrule_match_strategies.py new file mode 100644 index 00000000..6e695fc1 --- /dev/null +++ b/slp_tfplan/tests/unit/matcher/strategies/test_sg_sgrule_match_strategies.py @@ -0,0 +1,58 @@ +from unittest.mock import Mock + +from slp_tfplan.slp_tfplan.matcher.strategies.sg_sg_rule_match_strategies import \ + MatchSecurityGroupRuleBySecurityGroupIdStrategy, MatchSecurityGroupRuleByGraphStrategy + +_sg_1 = {'resource_id': 'SG1'} +_sg_rule1 = {'resource_id': 'SG_R1', 'security_group_id': 'SG1'} +_sg_rule2 = {'resource_id': 'SG_R2', 'security_group_id': 'SG2'} + + +class TestMatchSecurityGroupRuleBySecurityGroupIdStrategy: + + def test_is_related(self): + # GIVEN a sg rule with the security_group_id is equals to sg resource id + # WHEN MatchSecurityGroupRuleBySecurityGroupIdStrategy::are_related is called + result = MatchSecurityGroupRuleBySecurityGroupIdStrategy().are_related(_sg_1, _sg_rule1) + + # THEN the strategy returns True + assert result is True + + def test_not_related(self): + # GIVEN a sg rule with the security_group_id is distinct to sg resource id + # WHEN MatchSecurityGroupRuleBySecurityGroupIdStrategy::are_related is called + result = MatchSecurityGroupRuleBySecurityGroupIdStrategy().are_related(_sg_1, _sg_rule2) + + # THEN the strategy returns False + assert result is False + + +class TestMatchSecurityGroupRuleByGraphStrategy: + + def test_no_graph_relationship_no_match(self): + # GIVEN any two mocked SGs + mocked_sgs = [Mock(), Mock()] + + # AND a relationships_extractor which returns no relationships between them + relationships_extractor = Mock() + relationships_extractor.exist_valid_path = lambda sg_a, sg_b: False + + # WHEN MatchSecurityGroupRuleByGraphStrategy::are_related is called + result = MatchSecurityGroupRuleByGraphStrategy() \ + .are_related(*mocked_sgs, relationships_extractor=relationships_extractor) + + # THEN the strategy returns False + assert result is False + + def test_match_when_graph_relationship(self): + # GIVEN a mocked relationship from _sg_1 to _sg_rule1 + relationships_extractor = Mock() + relationships_extractor.exist_valid_path = lambda sg_r, sg: \ + (sg_r, sg) == (_sg_rule1['resource_id'], _sg_1['resource_id']) + + # WHEN SecurityGroupByGraphStrategy::are_related is called + result = MatchSecurityGroupRuleByGraphStrategy().are_related( + _sg_1, _sg_rule1, relationships_extractor=relationships_extractor) + + # THEN the strategy returns True + assert result is True diff --git a/slp_tfplan/tests/unit/matcher/test_sg_and_sgrules_matcher.py b/slp_tfplan/tests/unit/matcher/test_sg_and_sgrules_matcher.py new file mode 100644 index 00000000..63dd70f7 --- /dev/null +++ b/slp_tfplan/tests/unit/matcher/test_sg_and_sgrules_matcher.py @@ -0,0 +1,29 @@ +from unittest.mock import MagicMock + +from slp_tfplan.slp_tfplan.matcher import SGAndSGRulesMatcher + +sg_1 = MagicMock() +sg_rule_1 = MagicMock() +sg_rule_2 = MagicMock() + + +def are_sgs_related(resource_1, resource_2, **kwargs): + # 'sg_1' related to 'sg_rule_1' + return resource_1 == sg_1 and resource_2 == sg_rule_1 + + +class TestSGAndSGRulesMatcher: + + def test_sg_match(self): + # GIVEN a security group + # AND a list of security group rules + # AND a matcher that returns the relationship between them + matcher = SGAndSGRulesMatcher(sg_1, [sg_rule_1, sg_rule_2], MagicMock()) + matcher._are_related = are_sgs_related + + # WHEN SGAndSGRulesMatcher::match is called + related_sg_rule = matcher.match() + + # THEN the related sg rules is only sg_rule_1 + assert len(related_sg_rule) == 1 + assert related_sg_rule[0] == sg_rule_1 diff --git a/slp_tfplan/tests/util/asserts.py b/slp_tfplan/tests/util/asserts.py index fdc965a5..05d97393 100644 --- a/slp_tfplan/tests/util/asserts.py +++ b/slp_tfplan/tests/util/asserts.py @@ -24,13 +24,6 @@ def assert_parent(component: TFPlanComponent, parent_id: str = None): ########## # TFPLAN # ########## -def assert_common_properties(properties: {}): - assert properties['resource_mode'] == 'managed' - assert properties['resource_provider_name'] == 'registry.terraform.io/hashicorp/aws' - assert properties['resource_schema_version'] == 0 +def assert_resource_values(properties: {}): assert properties['val1'] == 'value1' - assert properties['senval1'] == 'value1' - - -def assert_resource_id(resource: {}): - assert resource['resource_id'] == resource['properties']['resource_address'] + assert properties['val2'] == 'value2'