class IPAddressRange(BaseSchema, CheckmkTuple): """ >>> schema = IPAddressRange() >>> rv = schema.dump(('ip_range', ('127.0.0.1', '127.0.0.2'))) >>> rv {'type': 'ip_range', 'from_address': '127.0.0.1', 'to_address': '127.0.0.2'} >>> schema.load(rv) ('ip_range', ('127.0.0.1', '127.0.0.2')) """ tuple_fields = ("type", ("from_address", "to_address")) cast_to_dict = True type = Constant( description="A range of addresses.", constant="ip_range", ) from_address = String( description="The first IPv4 address of this range.", validate=ValidateIPv4(), ) to_address = String( description="The last IPv4 address of this range.", validate=ValidateIPv4(), )
class LockedBy(BaseSchema, CheckmkTuple): """ >>> schema = LockedBy() >>> rv = schema.dump(("site", "dcd", "conn")) >>> rv {'site_id': 'site', 'program_id': 'dcd', 'instance_id': 'conn'} >>> schema.load(rv) ('site', 'dcd', 'conn') """ tuple_fields = ("site_id", "program_id", "instance_id") cast_to_dict = True site_id = String( description="Site ID", required=True, ) program_id = String( description="Program ID", required=True, ) instance_id = String( description="Instance ID", required=True, )
class DirectMapping(BaseSchema, CheckmkTuple): tuple_fields = ("hostname", "replace_with") hostname = String( description="The hostname to be replaced.", required=True, ) replace_with = String( description="The replacement string.", required=True, )
class SNMPv3AuthPrivacy(BaseSchema, CheckmkTuple): tuple_fields = ( "type", "auth_protocol", "security_name", "auth_password", "privacy_protocol", "privacy_password", ) converter = ( None, MappingConverter(AUTH_PROT_MAP), None, None, MappingConverter(PRIV_PROT_MAP), None, ) cast_to_dict = True type = Constant( description="SNMPv3 with authentication and privacy.", constant="authPriv", ) auth_protocol = String( description="Authentication protocol.", enum=list(AUTH_PROT_MAP.keys()), required=True, ) security_name = String( description="Security name", required=True, ) auth_password = String( description="Authentication pass phrase.", minLength=8, required=True, ) privacy_protocol = String( description=( "The privacy protocol. " "The only supported values in the Raw Edition are CBC-DES and AES-128. " "If selected, privacy_password needs to be supplied as well." ), required=True, enum=list(PRIV_PROT_MAP.keys()), ) privacy_password = String( description=( "Privacy pass phrase. " "If filled, privacy_protocol needs to be selected as well." ), required=True, minLength=8, )
class SNMPCommunity(BaseSchema): cast_to_dict = True type = Constant(constant="v1_v2_community") community = String( description="SNMP community (SNMP Versions 1 and 2c)", ) @post_load def to_checkmk_str(self, data, **kwargs): return data["community"] @pre_dump def from_tuple(self, data, **kwargs): """ v1 'community' v3 ('noAuthNoPriv', 'sicherheitsname') v3 ('authNoPriv', 'SHA-512', 'sicherheitsname', 'passwort') v3 ('authPriv', 'SHA-512', 'sicherheitsname', 'passwort', 'DES', 'privacypasswort') Args: data: **kwargs: Returns: """ if isinstance(data, str): return { "type": "v1_v2_community", "community": data, }
class IPAddresses(BaseSchema, CheckmkTuple): """Represents a list of IPv4 addresses >>> schema = IPAddresses() >>> rv = schema.dump(('ip_list', ['127.0.0.1', '127.0.0.2'])) >>> rv {'type': 'ip_list', 'addresses': ['127.0.0.1', '127.0.0.2']} >>> schema.load(rv) ('ip_list', ['127.0.0.1', '127.0.0.2']) """ tuple_fields = ("type", "addresses") cast_to_dict = True type = Constant( description="A list of single IPv4 addresses.", constant="ip_list", ) addresses = List( String( validate=ValidateIPv4(), ) )
class MetaData(BaseSchema): cast_to_dict = True created_at = Timestamp(description="When has this object been created.", ) updated_at = Timestamp(description="When this object was last changed.", ) created_by = String( description="The user id under which this object has been created.", )
class SNMPv3NoAuthNoPrivacy(BaseSchema, CheckmkTuple): tuple_fields = ("type", "security_name") cast_to_dict = True type = Constant( description="The type of credentials to use.", constant="noAuthNoPriv", ) security_name = String( description="Security name", required=True, )
class SNMPv3AuthNoPrivacy(BaseSchema, CheckmkTuple): tuple_fields = ("type", "auth_protocol", "security_name", "auth_password") converter = (None, MappingConverter(AUTH_PROT_MAP), None, None) cast_to_dict = True type = Constant( description="The type of credentials to use.", constant="authNoPriv", ) auth_protocol = String( description="Authentication protocol.", enum=list(AUTH_PROT_MAP.keys()), required=True, ) security_name = String( description="Security name", required=True, ) auth_password = String( description="Authentication pass phrase.", minLength=8, required=True, )
class NetworkScanResult(BaseSchema): start = DateTime(description="When the scan started") end = DateTime( description="When the scan finished. Will be Null if not yet run.", allow_none=True, ) state = String( description="Last scan result", enum=[ "not_started", "running", "succeeded", "failed", ], )
class IPNetwork(BaseSchema, CheckmkTuple): tuple_fields = ("type", "network") cast_to_dict = True type = Constant( description="A single IPv4 network in CIDR notation.", constant="ip_network", ) network = String( description=( "A IPv4 network in CIDR notation. Minimum prefix length is 8 bit, " "maximum prefix length is 30 bit.\n\nValid examples:\n\n" " * `192.168.0.0/24`\n" " * `192.168.0.0/255.255.255.0`"), validate=ValidateIPv4Network(min_prefix=8, max_prefix=30), )
class IPRegexp(BaseSchema, CheckmkTuple): """ >>> schema = IPRegexp() >>> rv = schema.dump(('ip_regex_list', ['127.0.[0-9].1', '127.0.[0-9].2'])) >>> schema.load(rv) ('ip_regex_list', ['127.0.[0-9].1', '127.0.[0-9].2']) """ tuple_fields = ("type", "regexp_list") cast_to_dict = True type = Constant( description="IPv4 addresses which match a regexp pattern", constant="ip_regex_list", ) regexp_list = List( String(validate=IsValidRegexp()), description=( "A list of regular expressions which are matched against the found " "IP addresses. The matches will be excluded from the result."), )
class RegexpRewrites(BaseSchema, CheckmkTuple): r"""Represents a regexp replacement. The replacement string gets validated against the regexp for match group compatibility. Examples: >>> schema = RegexpRewrites() >>> tup = schema.load({'search': '(abc)', 'replace_with': '\\1'}) >>> tup ('(abc)', '\\1') >>> schema.dump(tup) {'search': '(abc)', 'replace_with': '\\1'} >>> schema.load({'search': 'abc', 'replace_with': '\\1, \\22'}) # doctest: +ELLIPSIS Traceback (most recent call last): ... m...: {'replace_with': ['regexp only contains 0 match groups, but a match group with index 22 (\\22) was used in the replacement string.']} >>> schema.load({'search': '()()()', 'replace_with': '\\1, \\3'}) # doctest: +ELLIPSIS ('()()()', '\\1, \\3') """ tuple_fields = ("search", "replace_with") cast_to_dict = True search = String( description=( "The search regexp. May contain match-groups, conditional matches, etc. " "This follows the Python regular expression syntax.\n\n" "For details see:\n\n" " * https://docs.python.org/3/library/re.html" ), maxLength=30, validate=IsValidRegexp(), required=True, ) replace_with = String( description="The replacement string. Match-groups can only be identified by `\\1`, `\\2`, " "etc. Highest supported match group is `\\99`. Named lookups are not " "supported.", maxLength=30, required=True, ) @validates_schema def validate_replacement(self, data, **kwargs): search = re.compile(data["search"]) replace_groups = list(set(re.findall(r"\\((?:[1-9]|\d\d)+)", data["replace_with"]))) replace_groups.sort() # NOTE # We don't need to check for exhaustive use of the replacement groups. We only need # to check the highest match-group used in the replacement, as this is the only case # where a mismatch may occur. if replace_groups: highest_replacement_group = int(replace_groups[-1]) if highest_replacement_group > search.groups: raise ValidationError( f"regexp only contains {search.groups} match groups, but a match group with " f"index {highest_replacement_group} (\\{highest_replacement_group}) was used " "in the replacement string.", field_name="replace_with", )
required=True, ) replace_with = String( description="The replacement string.", required=True, ) class TranslateNames(BaseSchema): case = String( data_key="convert_case", description="Convert all detected hostnames to upper- or lower-case.\n\n" + _enum_options( [ ("nop", "Do not convert anything"), ("lower", "Convert all hostnames to lowercase."), ("upper", "Convert all hostnames to uppercase."), ] ), enum=["nop", "lower", "upper"], load_default="nop", ) drop_domain = Boolean( description=( "Drop the rest of the domain, only keep the hostname. Will not affect " "IP addresses.\n\n" "Examples:\n\n" " * `192.168.0.1` -> `192.168.0.1`\n" " * `foobar.example.com` -> `foobar`\n" " * `example.com` -> `example`\n" " * `example` -> `example`\n\n"
class IPMIParameters(BaseSchema): cast_to_dict = True username = String(required=True) password = String(required=True)
class NetworkScan(BaseSchema): """ >>> schema = NetworkScan() >>> settings = { ... 'exclude_ranges': [('ip_list', ['192.168.0.2']), ... ('ip_regex_list', ['192.168.[02].*'])], ... 'ip_ranges': [('ip_range', ('192.168.0.10', '192.168.0.244')), ... ('ip_regex_list', ['192.168.[01].*']), ... ('ip_list', ['192.168.0.2'])], ... 'max_parallel_pings': 100, ... # This is disabled, due to "running outside app context", duh. ... # 'run_as': 'cmkadmin', ... 'scan_interval': 86400, ... 'set_ipaddress': True, ... 'time_allowed': [((12, 0), (23, 59))], ... 'translate_names': { ... 'case': 'lower', ... 'drop_domain': True, ... 'mapping': [('example.com', 'www.example.com')], ... 'regex': [('.*', 'mehrfacheregulaere')]}} >>> result = schema.dump(settings) >>> assert len(result['addresses']) == 3 >>> assert len(result['exclude_addresses']) == 2 >>> assert len(result['time_allowed'][0]) == 2 >>> assert len(result['translate_names']) == 4 >>> import unittest >>> test_case = unittest.TestCase() >>> test_case.maxDiff = None >>> test_case.assertDictEqual(settings, schema.load(result)) """ ip_ranges = List( Nested(IPRangeWithRegexp()), data_key="addresses", required=True, description="IPv4 addresses to include.", ) exclude_ranges = List( Nested(IPRangeWithRegexp()), data_key="exclude_addresses", description="IPv4 addresses to exclude.", ) scan_interval = Integer( description="Scan interval in seconds. Default is 1 day, minimum is 1 hour.", load_default=60 * 60 * 24, minimum=3600, ) time_allowed = List( Nested(TimeAllowedRange()), description="Only execute the discovery during this time range each day..", required=True, ) set_ipaddress = Boolean( data_key="set_ip_address", description="When set, the found IPv4 address is set on the discovered host.", load_default=True, ) max_parallel_pings = Integer( description="Set the maximum number of concurrent pings sent to target IP addresses.", required=False, minimum=1, maximum=200, load_default=100, ) run_as = String( description=( "Execute the network scan in the Checkmk user context of the chosen user. " "This user needs the permission to add new hosts to this folder." ), required=False, validate=_active_users, ) translate_names = Nested(TranslateNames)
} OPTIONAL_HOST_NAME = { "host_name": HostField( description="A hostname.", should_exist=True, required=False, ) } IDENT_FIELD = { "ident": String( description=( "The identifier for this object. " "It's a 128bit uuid represented in hexadecimal (32 characters). " "There are no fixed parts or parts derived from the current hardware " "in this number." ), example="49167bd012b44719a67956cf3ef7b3dd", pattern="[a-fA-F0-9]{32}|root", ) } NAME_FIELD = { "name": String( description="A name used as an identifier. Can be of arbitrary (sensible) length.", example="pathname", pattern="[a-zA-Z0-9][a-zA-Z0-9_-]+", ) } ACCEPT_HEADER = {