Ejemplo n.º 1
0
def check_vpc_feature_enabled_and_used(
    config: typing.List[str], ) -> typing.Optional[CheckResult]:
    """Check if the vPC feature is actually used if it is enabled."""
    config = parse("\n".join(config))
    return _feature_enabled_but_not_configured(
        config, r"^feature vpc", r"^vpc domain",
        "vPC feature enabled but never used")
Ejemplo n.º 2
0
def check_telnet_enabled(
        config: typing.List[str]) -> typing.Optional[CheckResult]:
    """Check if the telnet feature is explicitly enabled."""
    config = parse("\n".join(config))
    lines = config.find_lines("^feature telnet")
    if lines:
        return CheckResult(text="Feature telnet is enabled.", lines=lines)
    else:
        return None
Ejemplo n.º 3
0
def check_ip_http_server(
        config: typing.List[str]) -> typing.Optional[CheckResult]:
    """Check if the http server is enabled."""
    config = parse("\n".join(config))
    lines = config.find_lines("^ip http")
    if lines:
        return CheckResult(text="HTTP server not disabled.", lines=lines)
    else:
        return None
Ejemplo n.º 4
0
def check_lacp_feature_enabled_and_used(
    config: typing.List[str], ) -> typing.Optional[CheckResult]:
    """Check if the LACP feature is actually used if it is enabled."""
    config = parse("\n".join(config))
    return _feature_enabled_but_not_configured(
        config,
        r"^feature lacp",
        r"^\s+channel-group \d+ mode active|passive",
        "LACP feature enabled but never used",
    )
Ejemplo n.º 5
0
def check_fex_feature_enabled_and_used(
    config: typing.List[str], ) -> typing.Optional[CheckResult]:
    """Check whether an enabled fex feature is actually used."""
    config = parse("\n".join(config))
    return _feature_enabled_but_not_configured(
        config,
        r"^feature-set fex",
        r"^fex id",
        "Feature-set fex enabled but never used.",
    )
Ejemplo n.º 6
0
def check_fex_feature_set_installed_but_not_enabled(
    config: typing.List[str], ) -> typing.Optional[CheckResult]:
    """Check if the fex feature-set is installed but not enabled."""
    config = parse("\n".join(config))
    return _feature_enabled_but_not_configured(
        config,
        r"^install feature-set fex",
        r"^feature-set fex",
        "Feature-set fex installed but not enabled.",
    )
Ejemplo n.º 7
0
def check_password_strength(
        config: typing.List[str]) -> typing.Optional[CheckResult]:
    """Check if the password strength check has been disabled."""
    config = parse("\n".join(config))
    disabled = config.find_lines("^no password strength-check")
    if disabled:
        return CheckResult(text="Password strength-check disabled.",
                           lines=disabled)
    else:
        return None
Ejemplo n.º 8
0
def check_default_snmp_communities(
    config: typing.List[str], ) -> typing.Optional[CheckResult]:
    """Check for presence of default SNMP community strings."""
    config = parse("\n".join(config))
    snmp_communities = config.find_lines("^snmp-server community")
    for community in snmp_communities:
        if community.startswith(
                "snmp-server community public") or community.startswith(
                    "snmp-server community private"):
            return CheckResult(text="Default SNMP communities present.",
                               lines=snmp_communities)

    return None
Ejemplo n.º 9
0
def check_password_hash_strength(
    config: typing.List[str], ) -> typing.Optional[CheckResult]:
    """Check if strong password hash algorithms were used."""
    config = parse("\n".join(config))
    lines_with_passwords = config.find_lines(r"^.*(password|secret)\s\d.*$")
    bad_lines = []
    for line in lines_with_passwords:
        hash_algorithm = get_password_hash_algorithm(line)
        if hash_algorithm in c.bad_hash_algorithms:
            bad_lines.append(line)
    if bad_lines:
        return CheckResult("Insecure hash algorithms in use.", lines=bad_lines)
    else:
        return None
Ejemplo n.º 10
0
def check_bogus_as(config: typing.List[str]) -> typing.Optional[CheckResult]:
    """Check if any bogus autonomous system is used in the configuration."""
    config = parse("\n".join(config))
    bgp_routers = config.find_lines("^router bgp")
    bad_lines = []
    for line in bgp_routers:
        as_number = int(line[11:])
        if as_number in bogus_as_numbers:
            bad_lines.append(line)

    if bad_lines:
        return CheckResult(text="Bogus AS number in use", lines=bad_lines)
    else:
        return None
Ejemplo n.º 11
0
def check_routing_protocol_enabled_and_used(
    config: typing.List[str], ) -> typing.Optional[CheckResult]:
    """Check if a routing protocol is actually used - should it be enabled."""
    config = parse("\n".join(config))
    for protocol in ["bgp", "ospf", "eigrp", "rip"]:
        feature_enabled = config.find_lines(f"^feature {protocol}")
        if not feature_enabled:
            return None

        feature_used = config.find_lines(f"^router {protocol}")
        if not feature_used:
            return CheckResult(
                text=f"{protocol.upper()} enabled but never used.",
                lines=feature_enabled + feature_used,
            )
    return None
Ejemplo n.º 12
0
def check_fex_without_interface(
    config: typing.List[str], ) -> typing.Optional[CheckResult]:
    """Check whether every configured fex id also has an associated interface."""
    config = parse("\n".join(config))
    configured_fex_ids = config.find_lines(r"^fex id")
    faulty_fex_ids = []
    for line in configured_fex_ids:
        fex_id = line.split()[2]
        has_interface = config.find_lines(
            r"^\s+fex associate {}".format(fex_id))
        if not has_interface:
            faulty_fex_ids.append(line)
    if faulty_fex_ids:
        return CheckResult(text="FEX without associated interface configured.",
                           lines=faulty_fex_ids)
    else:
        return None
Ejemplo n.º 13
0
def check_used_but_unconfigured_access_lists(
    config: typing.List[str], ) -> typing.Optional[CheckResult]:
    """Check for any ACLs that are used but never configured.

    Potential usages are:

    * Packet filtering
    * Rate limiting
    * Route maps
    """
    config = parse("\n".join(config))
    access_list_usages = get_access_list_usage(config)
    access_list_definitions = get_access_list_definitions(config)
    defined_access_lists = []
    undefined_but_used_access_lists = []
    for definition in access_list_definitions:
        name = get_name_from_acl_definition(definition)
        defined_access_lists.append(name)
    for usage in access_list_usages:
        # Get acl name/number from the configuration line for packet filtering usages
        # Standard use
        acl_in_filtering = re.findall(r"access-(class|group)\s(\S+|\d+)",
                                      usage)
        if acl_in_filtering and acl_in_filtering[0][
                1] not in defined_access_lists:
            undefined_but_used_access_lists.append(usage)
        # Evaluated in other ACLs
        acl_evaluated = re.findall(r"^\s+evaluate\s(\S+|\d+)", usage)
        if acl_evaluated and acl_evaluated[0] not in defined_access_lists:
            undefined_but_used_access_lists.append(usage)

        # Get acl name/number from the configuration line for route-map usages
        acl_in_route_map = re.findall(r"\s+match\sip\s\S+\s(\S+|\d+)", usage)
        if acl_in_route_map and acl_in_route_map[0] not in defined_access_lists:
            undefined_but_used_access_lists.append(usage)
    if undefined_but_used_access_lists:
        return CheckResult(
            text="Access lists used but never defined.",
            lines=undefined_but_used_access_lists,
        )
    else:
        return None
Ejemplo n.º 14
0
def check_console_password(
        config: typing.List[str]) -> typing.Optional[CheckResult]:
    """Check for authentication on the console line."""
    config = parse("\n".join(config))
    line_con_config = config.find_all_children("^line con 0")
    if len(line_con_config) == 0:
        return None  # TODO: Log this?

    login = False
    password = False
    for line in line_con_config:
        if "login" in line:
            login = True
        if "password" in line:
            password = True

    if not login or not password:
        return CheckResult(text="Console line unauthenticated.",
                           lines=line_con_config)
    else:
        return None
Ejemplo n.º 15
0
def check_plaintext_passwords(
        config: typing.List[str]) -> typing.Optional[CheckResult]:
    """Check if there are any plaintext passwords in the configuration."""
    config = parse("\n".join(config))
    lines = config.find_lines("^username.*password")
    if lines:
        # If `service password-encryption` is configured, users are saved to the
        # config like `username test password 7 $ENCRYPTED. The following for-loop
        # checks for that.
        for line in lines:
            has_hash_algorithm = get_password_hash_algorithm(line)
            if not has_hash_algorithm:
                break
        else:
            # If the for loop wasn't exited prematurely, no plaintext passwords
            # are present.
            return None
        return CheckResult(text="Plaintext user passwords in configuration.",
                           lines=lines)
    else:
        return None
Ejemplo n.º 16
0
def check_switchport_access_config(
    config: typing.List[str], ) -> typing.Optional[CheckResult]:
    """Check if the switchport mode matches all config commands per interface."""
    config = parse("\n".join(config))
    interfaces = config.find_objects_w_child(r"^interface",
                                             r"^\s+switchport mode access")
    bad_lines = []
    for interface in interfaces:
        bad_lines_per_interface = [interface.text]
        switchport_config_lines = list(
            filter(lambda l: re.match(r"^\s+switchport", l.text),
                   interface.children))
        for line in switchport_config_lines:
            if line.text.strip().startswith("switchport trunk"):
                bad_lines_per_interface.append(line.text)
        if len(bad_lines_per_interface) > 1:
            bad_lines.extend(bad_lines_per_interface)
    if bad_lines:
        return CheckResult("Trunk port config present on access interfaces.",
                           lines=bad_lines)
    else:
        return None
Ejemplo n.º 17
0
def check_unused_access_lists(
        config: typing.List[str]) -> typing.Optional[CheckResult]:
    """Check for any ACLs that are configured but never used.

    Potential usages are:

    * Packet filtering
    * Rate limiting
    * Route maps
    """
    config = parse("\n".join(config))
    access_lists = get_access_list_definitions(config)
    unused_acls = []
    for acl in access_lists:
        name = get_name_from_acl_definition(acl)
        usages = get_access_list_usage(config, name=name)
        if not usages:
            unused_acls.append(acl)
    if unused_acls:
        return CheckResult(text="Unused ACLs configured", lines=unused_acls)
    else:
        return None
Ejemplo n.º 18
0
def check_switchport_mode_fex_fabric(
    config: typing.List[str], ) -> typing.Optional[CheckResult]:
    """Check if any interface in switchport mode fex-fabric has a fex-id associated."""
    config = parse("\n".join(config))
    interfaces = config.find_objects_w_child("^interface",
                                             "switchport mode fex-fabric")
    faulty_lines = []
    for interface in interfaces:
        current_lines = [interface.text]
        for line in interface.children:
            current_lines.append(line.text)
            if line.text.strip().startswith("fex associate"):
                break
        else:
            faulty_lines.extend(current_lines)
    if faulty_lines:
        return CheckResult(
            text=
            "Interface in switchport mode fex-fabric without associated fex.",
            lines=faulty_lines,
        )
    else:
        return None