示例#1
0
    def validate_query_vrf(cls, value, values):
        """Ensure query_vrf is defined.

        Arguments:
            value {str} -- Unvalidated query_vrf

        Raises:
            InputInvalid: Raised if query_vrf is not defined.

        Returns:
            {str} -- Valid query_vrf
        """
        vrf_object = get_vrf_object(value)
        device = devices[values["query_location"]]
        device_vrf = None
        for vrf in device.vrfs:
            if vrf == vrf_object:
                device_vrf = vrf
                break
        if device_vrf is None:
            raise InputInvalid(
                params.messages.vrf_not_associated,
                vrf_name=vrf_object.display_name,
                device_name=device.display_name,
            )
        return device_vrf
示例#2
0
def get_vrf_object(vrf_name):
    """Match VRF object from VRF name.

    Arguments:
        vrf_name {str} -- VRF name

    Raises:
        InputInvalid: Raised if no VRF is matched.

    Returns:
        {object} -- Valid VRF object
    """
    matched = None
    for vrf_obj in devices.vrf_objects:
        if vrf_name is not None:
            if vrf_name == vrf_obj.name or vrf_name == vrf_obj.display_name:
                matched = vrf_obj
                break
        elif vrf_name is None:
            if vrf_obj.name == "default":
                matched = vrf_obj
                break
    if matched is None:
        raise InputInvalid(params.messages.vrf_not_found, vrf_name=vrf_name)
    return matched
示例#3
0
 def validate_query_location(cls, value):
     """Ensure query_location is defined."""
     if value not in devices._ids:
         raise InputInvalid(
             params.messages.invalid_field,
             level="warning",
             input=value,
             field=params.web.text.query_location,
         )
     return value
示例#4
0
 def validate_query_type(cls, value):
     """Ensure query_type is enabled."""
     query = params.queries[value]
     if not query.enable:
         raise InputInvalid(
             params.messages.feature_not_enabled,
             level="warning",
             feature=query.display_name,
         )
     return value
示例#5
0
def validate_community_select(value):
    """Validate selected community against configured communities."""

    communities = tuple(c.community for c in params.queries.bgp_community.communities)
    if value not in communities:
        raise InputInvalid(
            params.messages.invalid_input,
            target=value,
            query_type=params.queries.bgp_community.display_name,
        )
    return value
示例#6
0
def validate_aspath(value):
    """Validate input AS_PATH against configured or default regext pattern."""

    mode = params.queries.bgp_aspath.pattern.mode
    pattern = getattr(params.queries.bgp_aspath.pattern, mode)

    if not bool(re.match(pattern, value)):
        raise InputInvalid(
            params.messages.invalid_input,
            target=value,
            query_type=params.queries.bgp_aspath.display_name,
        )

    return value
示例#7
0
def get_vrf_object(vrf_name: str) -> Vrf:
    """Match VRF object from VRF name."""

    for vrf_obj in devices.vrf_objects:
        if vrf_name is not None:
            if vrf_name == vrf_obj._id or vrf_name == vrf_obj.display_name:
                return vrf_obj

            elif vrf_name == "__hyperglass_default" and vrf_obj.default:
                return vrf_obj
        elif vrf_name is None:
            if vrf_obj.default:
                return vrf_obj

    raise InputInvalid(params.messages.vrf_not_found, vrf_name=vrf_name)
示例#8
0
 def validate_query_vrf(cls, value, values):
     """Ensure query_vrf is defined."""
     vrf_object = get_vrf_object(value)
     device = devices[values["query_location"]]
     device_vrf = None
     for vrf in device.vrfs:
         if vrf == vrf_object:
             device_vrf = vrf
             break
     if device_vrf is None:
         raise InputInvalid(
             params.messages.vrf_not_associated,
             vrf_name=vrf_object.display_name,
             device_name=device.name,
         )
     return device_vrf
示例#9
0
    def validate_query_location(cls, value):
        """Ensure query_location is defined.

        Arguments:
            value {str} -- Unvalidated query_location

        Raises:
            InputInvalid: Raised if query_location is not defined.

        Returns:
            {str} -- Valid query_location
        """
        if value not in devices.hostnames:
            raise InputInvalid(
                params.messages.invalid_field,
                level="warning",
                input=value,
                field=params.web.text.query_location,
            )
        return value
示例#10
0
    def validate_query_type(cls, value):
        """Ensure query_type is enabled.

        Arguments:
            value {str} -- Query Type

        Raises:
            InputInvalid: Raised if query_type is disabled.

        Returns:
            {str} -- Valid query_type
        """
        query = params.queries[value]
        if not query.enable:
            raise InputInvalid(
                params.messages.feature_not_enabled,
                level="warning",
                feature=query.display_name,
            )
        return value
示例#11
0
def validate_community_input(value):
    """Validate input communities against configured or default regex pattern."""

    # RFC4360: Extended Communities (New Format)
    if re.match(params.queries.bgp_community.pattern.extended_as, value):
        pass

    # RFC4360: Extended Communities (32 Bit Format)
    elif re.match(params.queries.bgp_community.pattern.decimal, value):
        pass

    # RFC8092: Large Communities
    elif re.match(params.queries.bgp_community.pattern.large, value):
        pass

    else:
        raise InputInvalid(
            params.messages.invalid_input,
            target=value,
            query_type=params.queries.bgp_community.display_name,
        )
    return value
示例#12
0
def validate_ip(value, query_type, query_vrf):  # noqa: C901
    """Ensure input IP address is both valid and not within restricted allocations.

    Arguments:
        value {str} -- Unvalidated IP Address
        query_type {str} -- Valid query type
        query_vrf {object} -- Matched query vrf
    Raises:
        ValueError: Raised if input IP address is not an IP address.
        ValueError: Raised if IP address is valid, but is within a restricted range.
    Returns:
        Union[IPv4Address, IPv6Address] -- Validated IP address object
    """
    query_type_params = getattr(params.queries, query_type)
    try:

        # Attempt to use IP object factory to create an IP address object
        valid_ip = ip_network(value)

    except ValueError:
        raise InputInvalid(
            params.messages.invalid_input,
            target=value,
            query_type=query_type_params.display_name,
        )

    # Test the valid IP address to determine if it is:
    #  - Unspecified (See RFC5735, RFC2373)
    #  - Loopback (See RFC5735, RFC2373)
    #  - Otherwise IETF Reserved
    # ...and returns an error if so.
    if valid_ip.is_reserved or valid_ip.is_unspecified or valid_ip.is_loopback:
        raise InputInvalid(
            params.messages.invalid_input,
            target=value,
            query_type=query_type_params.display_name,
        )

    ip_version = valid_ip.version

    vrf_afi = getattr(query_vrf, f"ipv{ip_version}")

    if vrf_afi is None:
        raise InputInvalid(
            params.messages.feature_not_enabled,
            feature=f"IPv{ip_version}",
            device_name=f"VRF {query_vrf.display_name}",
        )

    for ace in [
            a for a in vrf_afi.access_list if a.network.version == ip_version
    ]:
        if _member_of(valid_ip, ace.network):
            if query_type == "bgp_route" and _prefix_range(
                    valid_ip, ace.ge, ace.le):
                pass

            if ace.action == "permit":
                log.debug("{t} is allowed by access-list {a}",
                          t=str(valid_ip),
                          a=repr(ace))
                break
            elif ace.action == "deny":
                raise InputNotAllowed(
                    params.messages.acl_denied,
                    target=str(valid_ip),
                    denied_network=str(ace.network),
                )

    # Handling logic for host queries, e.g. 192.0.2.1 vs. 192.0.2.0/24
    if valid_ip.num_addresses == 1:

        # For a host query with ping or traceroute query types, convert
        # the query_target to an IP address instead of a network.
        if query_type in ("ping", "traceroute"):
            new_ip = valid_ip.network_address

            log.debug(
                "Converted '{o}' to '{n}' for '{q}' query",
                o=valid_ip,
                n=new_ip,
                q=query_type,
            )

            valid_ip = new_ip

        # Get the containing prefix for a host query if:
        #   - Query type is bgp_route
        #   - force_cidr option is enabled
        #   - Query target is not a private address/network
        elif (query_type in ("bgp_route", ) and vrf_afi.force_cidr
              and not valid_ip.is_private):
            log.debug("Getting containing prefix for {q}", q=str(valid_ip))

            ip_str = str(valid_ip.network_address)
            network_info = network_info_sync(ip_str)
            containing_prefix = network_info.get(ip_str, {}).get("prefix")

            if containing_prefix is None:
                log.error(
                    "Unable to find containing prefix for {}. Got: {}",
                    str(valid_ip),
                    network_info,
                )
                raise InputInvalid("{q} does not have a containing prefix",
                                   q=ip_str)

            try:

                valid_ip = ip_network(containing_prefix)
                log.debug("Containing prefix: {p}", p=str(valid_ip))

            except ValueError as err:
                log.error(
                    "Unable to find containing prefix for {q}. Error: {e}",
                    q=str(valid_ip),
                    e=err,
                )
                raise InputInvalid(
                    "{q} does does not have a containing prefix", q=valid_ip)

        # For a host query with bgp_route query type and force_cidr
        # disabled, convert the host query to a single IP address.
        elif query_type in ("bgp_route", ) and not vrf_afi.force_cidr:

            valid_ip = valid_ip.network_address

    log.debug("Validation passed for {ip}", ip=value)
    return valid_ip