def test_all_of(): spec1 = SNMPDetectSpecification([[(".1", "1?", True)]]) spec2 = SNMPDetectSpecification([[(".2", "2?", True)]]) spec3 = SNMPDetectSpecification([[(".3", "3?", True)]]) assert utils.all_of(spec1, spec2, spec3) == SNMPDetectSpecification([[ (".1", "1?", True), (".2", "2?", True), (".3", "3?", True), ]]) spec12 = utils.all_of(spec1, spec2) assert utils.all_of(spec1, spec2, spec3) == utils.all_of(spec12, spec3)
def test_create_snmp_section_plugin(): trees: List[SNMPTree] = [ SNMPTree( base=".1.2.3", oids=[OIDEnd(), "2.3"], ), ] detect = SNMPDetectSpecification([ [(".1.2.3.4.5", "Foo.*", True)], ]) plugin = section_plugins.create_snmp_section_plugin( name="norris", parsed_section_name="chuck", parse_function=_parse_dummy, fetch=trees, detect_spec=detect, supersedes=["foo", "bar"], ) assert isinstance(plugin, SNMPSectionPlugin) assert len(plugin) == 11 assert plugin.name == SectionName("norris") assert plugin.parsed_section_name == ParsedSectionName("chuck") assert plugin.parse_function is _parse_dummy assert plugin.host_label_function is section_plugins._noop_host_label_function assert plugin.host_label_default_parameters is None assert plugin.host_label_ruleset_name is None assert plugin.host_label_ruleset_type == "merged" assert plugin.detect_spec == detect assert plugin.trees == trees assert plugin.supersedes == {SectionName("bar"), SectionName("foo")}
def test_all_of_any_of(): spec1 = SNMPDetectSpecification([[(".1", "1?", True)]]) spec2 = SNMPDetectSpecification([[(".2", "2?", True)]]) spec3 = SNMPDetectSpecification([[(".3", "3?", True)]]) spec4 = SNMPDetectSpecification([[(".4", "4?", True)]]) spec12 = utils.any_of(spec1, spec2) spec34 = utils.any_of(spec3, spec4) assert utils.all_of(spec12, spec34) == SNMPDetectSpecification([ [(".1", "1?", True), (".3", "3?", True)], [(".1", "1?", True), (".4", "4?", True)], [(".2", "2?", True), (".3", "3?", True)], [(".2", "2?", True), (".4", "4?", True)], ])
def test_create_snmp_section_plugin(): trees: List[SNMPTree] = [ SNMPTree( base='.1.2.3', oids=[OIDEnd(), '2.3'], ), ] detect = SNMPDetectSpecification([ [('.1.2.3.4.5', 'Foo.*', True)], ]) plugin = section_plugins.create_snmp_section_plugin( name="norris", parsed_section_name="chuck", parse_function=_parse_dummy, fetch=trees, detect_spec=detect, supersedes=["foo", "bar"], ) assert isinstance(plugin, SNMPSectionPlugin) assert len(plugin) == 8 assert plugin.name == SectionName("norris") assert plugin.parsed_section_name == ParsedSectionName("chuck") assert plugin.parse_function is _parse_dummy assert plugin.host_label_function is section_plugins._noop_host_label_function assert plugin.detect_spec == detect assert plugin.trees == trees assert plugin.supersedes == {SectionName("bar"), SectionName("foo")}
def test_any_of(): spec1 = SNMPDetectSpecification([[(".1", "1?", True)]]) spec2 = SNMPDetectSpecification([[(".2", "2?", True)]]) spec3 = SNMPDetectSpecification([[(".3", "3?", True)]]) spec123 = utils.any_of(spec1, spec2, spec3) _validate_detect_spec(spec123) assert spec123 == [ [(".1", "1?", True)], [(".2", "2?", True)], [(".3", "3?", True)], ] spec12 = utils.any_of(spec1, spec2) assert spec123 == utils.any_of(spec12, spec3)
def _ast_convert_unary(unop_ast: ast.UnaryOp) -> SNMPDetectSpecification: if isinstance(unop_ast.op, ast.Not): operand = _ast_convert_dispatcher(unop_ast.operand) _validate_detect_spec(operand) # We can only negate atomic specs, for now if len(operand) == 1 and len(operand[0]) == 1: oidstr, pattern, result = operand[0][0] return SNMPDetectSpecification([[(oidstr, pattern, not result)]]) raise NotImplementedError("cannot negate operand") raise ValueError(ast.dump(unop_ast))
def create_detect_spec( name: str, snmp_scan_function: Callable, fallback_files: List[str], ) -> SNMPDetectSpecification: migrated = _lookup_migrated(snmp_scan_function) if migrated is not None: return migrated key = _lookup_key_from_code(snmp_scan_function.__code__) preconverted = PRECONVERTED_DETECT_SPECS.get(key) if preconverted is not None: return SNMPDetectSpecification(preconverted) return SNMPDetectSpecification( PRECONVERTED_DETECT_SPECS.setdefault( key, _compute_detect_spec( section_name=name, scan_function=snmp_scan_function, fallback_files=fallback_files, )))
def exists(oidstr: str) -> SNMPDetectSpecification: """Detect the device if the OID exists at all Args: oidstr: The OID that is required to exist Returns: A valid specification for SNMP device detection Example: >>> DETECT = exists("1.2.3") """ return SNMPDetectSpecification([[(oidstr, '.*', True)]])
def any_of(*specs: SNMPDetectSpecification) -> SNMPDetectSpecification: """Detect the device if any of the passed specifications are met Args: spec: A valid specification for SNMP device detection Returns: A valid specification for SNMP device detection Example: >>> DETECT = any_of(exists("1.2.3.4"), exists("1.2.3.5")) """ return SNMPDetectSpecification(sum(specs, []))
def test_create_snmp_section_plugin_single_tree(): single_tree = SNMPTree(base=".1.2.3", oids=[OIDEnd(), "2.3"]) plugin = section_plugins.create_snmp_section_plugin( name="norris", parse_function=lambda string_table: string_table, # just one, no list: fetch=single_tree, detect_spec=SNMPDetectSpecification([[(".1.2.3.4.5", "Foo.*", True)]]), ) assert plugin.trees == [single_tree] # the plugin only specified a single tree (not a list), # so a wrapper should unpack the argument: assert plugin.parse_function([[["A", "B"]]]) == [["A", "B"]]
def contains(oidstr: str, value: str) -> SNMPDetectSpecification: """Detect the device if the value of the OID contains the given string Args: oidstr: The OID to match the value against value: The substring expected to be in the OIDs value Returns: A valid specification for SNMP device detection Example: >>> DETECT = contains("1.2.3", "isco") """ return SNMPDetectSpecification([[(oidstr, '.*%s.*' % re.escape(value), True)]])
def matches(oidstr: str, value: str) -> SNMPDetectSpecification: """Detect the device if the value of the OID matches the expression Args: oidstr: The OID to match the value against value: The regular expression that the value of the OID should match Returns: A valid specification for SNMP device detection Example: >>> DETECT = matches("1.2.3.4", ".* Server") """ return SNMPDetectSpecification([[(oidstr, value, True)]])
def endswith(oidstr: str, value: str) -> SNMPDetectSpecification: """Detect the device if the value of the OID ends with the given string Args: oidstr: The OID to match the value against value: The expected end of the OIDs value Returns: A valid specification for SNMP device detection Example: >>> DETECT = endswith("1.2.3", "nix") """ return SNMPDetectSpecification([[(oidstr, '.*%s' % re.escape(value), True)]])
def equals(oidstr: str, value: str) -> SNMPDetectSpecification: """Detect the device if the value of the OID equals the given string Args: oidstr: The OID to match the value against value: The expected value of the OID Returns: A valid specification for SNMP device detection Example: >>> DETECT = equals("1.2.3", "MySwitch") """ return SNMPDetectSpecification([[(oidstr, '%s' % re.escape(value), True)]])
def _compute_detect_spec( *, section_name: str, scan_function: Callable, fallback_files: List[str], ) -> SNMPDetectSpecification: scan_func_ast = _get_scan_function_ast(section_name, scan_function, fallback_files) expression_ast = _get_expression_from_function(section_name, scan_func_ast) if _is_false(expression_ast): return SNMPDetectSpecification() try: return _ast_convert_dispatcher(expression_ast) except (ValueError, NotImplementedError) as exc: msg = f"{section_name}: failed to convert scan function: {scan_function.__name__}" raise NotImplementedError(msg) from exc
def all_of(spec_0: SNMPDetectSpecification, spec_1: SNMPDetectSpecification, *specs: SNMPDetectSpecification) -> SNMPDetectSpecification: """Detect the device if all passed specifications are met Args: spec_0: A valid specification for SNMP device detection spec_1: A valid specification for SNMP device detection Returns: A valid specification for SNMP device detection Example: >>> DETECT = all_of(exists("1.2.3.4"), contains("1.2.3.5", "foo")) """ reduced = SNMPDetectSpecification(l0 + l1 for l0, l1 in itertools.product(spec_0, spec_1)) if not specs: return reduced return all_of(reduced, *specs)
def _negate(spec: SNMPDetectSpecification) -> SNMPDetectSpecification: assert len(spec) == 1 assert len(spec[0]) == 1 return SNMPDetectSpecification([[(spec[0][0][0], spec[0][0][1], not spec[0][0][2])]])