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 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 list_resolver_endpoint_ip_addresses(self): """Returns list of IP addresses for specified Resolver endpoint.""" resolver_endpoint_id = self._get_param("ResolverEndpointId") next_token = self._get_param("NextToken") max_results = self._get_param("MaxResults", 10) validate_args([("maxResults", max_results)]) try: ( ip_addresses, next_token, ) = self.route53resolver_backend.list_resolver_endpoint_ip_addresses( resolver_endpoint_id=resolver_endpoint_id, next_token=next_token, max_results=max_results, ) except InvalidToken as exc: raise InvalidNextTokenException() from exc response = { "IpAddresses": ip_addresses, "MaxResults": max_results, } if next_token: response["NextToken"] = next_token return json.dumps(response)
def update_resolver_endpoint(self, resolver_endpoint_id, name): """Update name of Resolver endpoint.""" self._validate_resolver_endpoint_id(resolver_endpoint_id) validate_args([("name", name)]) resolver_endpoint = self.resolver_endpoints[resolver_endpoint_id] resolver_endpoint.update_name(name) return resolver_endpoint
def create_resolver_endpoint( self, region, creator_request_id, name, security_group_ids, direction, ip_addresses, tags, ): # pylint: disable=too-many-arguments """Return description for a newly created resolver endpoint. NOTE: IPv6 IPs are currently not being filtered when calculating the create_resolver_endpoint() IpAddresses. """ validate_args([ ("creatorRequestId", creator_request_id), ("direction", direction), ("ipAddresses", ip_addresses), ("name", name), ("securityGroupIds", security_group_ids), ("ipAddresses.subnetId", ip_addresses), ]) errmsg = self.tagger.validate_tags( tags or [], limit=ResolverEndpoint.MAX_TAGS_PER_RESOLVER_ENDPOINT) if errmsg: raise TagValidationException(errmsg) endpoints = [ x for x in self.resolver_endpoints.values() if x.region == region ] if len(endpoints) > ResolverEndpoint.MAX_ENDPOINTS_PER_REGION: raise LimitExceededException( f"Account '{get_account_id()}' has exceeded 'max-endpoints'") self._verify_subnet_ips(region, ip_addresses) self._verify_security_group_ids(region, security_group_ids) if creator_request_id in [ x.creator_request_id for x in self.resolver_endpoints.values() ]: raise ResourceExistsException( f"Resolver endpoint with creator request ID " f"'{creator_request_id}' already exists") endpoint_id = ( f"rslvr-{'in' if direction == 'INBOUND' else 'out'}-{get_random_hex(17)}" ) resolver_endpoint = ResolverEndpoint( region, endpoint_id, creator_request_id, security_group_ids, direction, ip_addresses, name, ) self.resolver_endpoints[endpoint_id] = resolver_endpoint self.tagger.tag_resource(resolver_endpoint.arn, tags or []) return resolver_endpoint
def list_resolver_endpoints(self): """Returns list of all Resolver endpoints, filtered if specified.""" filters = self._get_param("Filters") next_token = self._get_param("NextToken") max_results = self._get_param("MaxResults", 10) validate_args([("maxResults", max_results)]) endpoints, next_token = self.route53resolver_backend.list_resolver_endpoints( filters, next_token=next_token, max_results=max_results) response = { "ResolverEndpoints": [x.description() for x in endpoints], "MaxResults": max_results, } if next_token: response["NextToken"] = next_token return json.dumps(response)
def list_resolver_rules(self): """Returns list of all Resolver rules, filtered if specified.""" filters = self._get_param("Filters") next_token = self._get_param("NextToken") max_results = self._get_param("MaxResults", 10) validate_args([("maxResults", max_results)]) try: (rules, next_token) = self.route53resolver_backend.list_resolver_rules( filters, next_token=next_token, max_results=max_results) except InvalidToken as exc: raise InvalidNextTokenException() from exc response = { "ResolverRules": [x.description() for x in rules], "MaxResults": max_results, } if next_token: response["NextToken"] = next_token return json.dumps(response)
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