def disassociate_resolver_rule(self, resolver_rule_id, vpc_id): validate_args([("resolverRuleId", resolver_rule_id), ("vPCId", vpc_id)]) # Non-existent rule or vpc ids? if resolver_rule_id not in self.resolver_rules: raise ResourceNotFoundException( f"Resolver rule with ID '{resolver_rule_id}' does not exist" ) # Find the matching association for this rule and vpc. rule_association_id = None for association in self.resolver_rule_associations.values(): if ( resolver_rule_id == association.resolver_rule_id and vpc_id == association.vpc_id ): rule_association_id = association.id break else: raise ResourceNotFoundException( f"Resolver Rule Association between Resolver Rule " f"'{resolver_rule_id}' and VPC '{vpc_id}' does not exist" ) rule_association = self.resolver_rule_associations.pop(rule_association_id) rule_association.status = "DELETING" rule_association.status_message = "Deleting Association" return rule_association
def get_resolver_rule_association(self, resolver_rule_association_id): validate_args([("resolverRuleAssociationId", resolver_rule_association_id)]) if resolver_rule_association_id not in self.resolver_rule_associations: raise ResourceNotFoundException( f"ResolverRuleAssociation '{resolver_rule_association_id}' does not Exist" ) return self.resolver_rule_associations[resolver_rule_association_id]
def _validate_resolver_rule_id(self, resolver_rule_id): """Raise an exception if the id is invalid or unknown.""" validate_args([("resolverRuleId", resolver_rule_id)]) if resolver_rule_id not in self.resolver_rules: raise ResourceNotFoundException( f"Resolver rule with ID '{resolver_rule_id}' does not exist" )
def _matched_arn(self, resource_arn): """Given ARN, raise exception if there is no corresponding resource.""" for resolver_endpoint in self.resolver_endpoints.values(): if resolver_endpoint.arn == resource_arn: return for resolver_rule in self.resolver_rules.values(): if resolver_rule.arn == resource_arn: return raise ResourceNotFoundException( f"Resolver endpoint with ID '{resource_arn}' does not exist")
def _verify_security_group_ids(region, security_group_ids): """Perform additional checks on the security groups.""" if len(security_group_ids) > 10: raise InvalidParameterException("Maximum of 10 security groups are allowed") for group_id in security_group_ids: if not group_id.startswith("sg-"): raise InvalidParameterException( f"Malformed security group ID: Invalid id: '{group_id}' " f"(expecting 'sg-...')" ) try: ec2_backends[region].describe_security_groups(group_ids=[group_id]) except InvalidSecurityGroupNotFoundError as exc: raise ResourceNotFoundException( f"The security group '{group_id}' does not exist" ) from exc
def associate_resolver_rule(self, region, resolver_rule_id, name, vpc_id): """Return description for a newly created resolver rule association.""" validate_args( [("resolverRuleId", resolver_rule_id), ("name", name), ("vPCId", vpc_id)] ) associations = [ x for x in self.resolver_rule_associations.values() if x.region == region ] if len(associations) > ResolverRuleAssociation.MAX_RULE_ASSOCIATIONS_PER_REGION: # This error message was not verified to be the same for AWS. raise LimitExceededException( f"Account '{ACCOUNT_ID}' has exceeded 'max-rule-association'" ) if resolver_rule_id not in self.resolver_rules: raise ResourceNotFoundException( f"Resolver rule with ID '{resolver_rule_id}' does not exist." ) vpcs = ec2_backends[region].describe_vpcs() if vpc_id not in [x.id for x in vpcs]: raise InvalidParameterException(f"The vpc ID '{vpc_id}' does not exist") # Can't duplicate resolver rule, vpc id associations. for association in self.resolver_rule_associations.values(): if ( resolver_rule_id == association.resolver_rule_id and vpc_id == association.vpc_id ): raise InvalidRequestException( f"Cannot associate rules with same domain name with same " f"VPC. Conflict with resolver rule '{resolver_rule_id}'" ) rule_association_id = f"rslvr-rrassoc-{get_random_hex(17)}" rule_association = ResolverRuleAssociation( region, rule_association_id, resolver_rule_id, vpc_id, name ) self.resolver_rule_associations[rule_association_id] = rule_association return rule_association
def create_resolver_rule( self, region, creator_request_id, name, rule_type, domain_name, target_ips, resolver_endpoint_id, tags, ): # pylint: disable=too-many-arguments """Return description for a newly created resolver rule.""" validate_args( [ ("creatorRequestId", creator_request_id), ("ruleType", rule_type), ("domainName", domain_name), ("name", name), *[("targetIps.port", x) for x in target_ips], ("resolverEndpointId", resolver_endpoint_id), ] ) errmsg = self.tagger.validate_tags( tags or [], limit=ResolverRule.MAX_TAGS_PER_RESOLVER_RULE ) if errmsg: raise TagValidationException(errmsg) rules = [x for x in self.resolver_rules.values() if x.region == region] if len(rules) > ResolverRule.MAX_RULES_PER_REGION: # Did not verify that this is the actual error message. raise LimitExceededException( f"Account '{get_account_id()}' has exceeded 'max-rules'" ) # Per the AWS documentation and as seen with the AWS console, target # ips are only relevant when the value of Rule is FORWARD. However, # boto3 ignores this condition and so shall we. for ip_addr in [x["Ip"] for x in target_ips]: try: # boto3 fails with an InternalServiceException if IPv6 # addresses are used, which isn't helpful. if not isinstance(ip_address(ip_addr), IPv4Address): raise InvalidParameterException( f"Only IPv4 addresses may be used: '{ip_addr}'" ) except ValueError as exc: raise InvalidParameterException( f"Invalid IP address: '{ip_addr}'" ) from exc # The boto3 documentation indicates that ResolverEndpoint is # optional, as does the AWS documention. But if resolver_endpoint_id # is set to None or an empty string, it results in boto3 raising # a ParamValidationError either regarding the type or len of string. if resolver_endpoint_id: if resolver_endpoint_id not in [ x.id for x in self.resolver_endpoints.values() ]: raise ResourceNotFoundException( f"Resolver endpoint with ID '{resolver_endpoint_id}' does not exist." ) if rule_type == "SYSTEM": raise InvalidRequestException( "Cannot specify resolver endpoint ID and target IP " "for SYSTEM type resolver rule" ) if creator_request_id in [ x.creator_request_id for x in self.resolver_rules.values() ]: raise ResourceExistsException( f"Resolver rule with creator request ID " f"'{creator_request_id}' already exists" ) rule_id = f"rslvr-rr-{get_random_hex(17)}" resolver_rule = ResolverRule( region, rule_id, creator_request_id, rule_type, domain_name, target_ips, resolver_endpoint_id, name, ) self.resolver_rules[rule_id] = resolver_rule self.tagger.tag_resource(resolver_rule.arn, tags or []) return resolver_rule