1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
|
from typing import Any, Dict, List, Literal, Optional, Union
from knot_resolver.constants import WATCHDOG_LIB
from knot_resolver.datamodel.types import (
DomainName,
EscapedStr,
IDPattern,
IPAddress,
ListOrItem,
ReadableFile,
TimeUnit,
)
from knot_resolver.utils.modeling import ConfigSchema
class RuleSchema(ConfigSchema):
"""
Local data advanced rule configuration.
---
name: Hostname(s).
subtree: Type of subtree.
address: Address(es) to pair with hostname(s).
file: Path to file(s) with hostname and IP address(es) pairs in '/etc/hosts' like format.
records: Direct addition of records in DNS zone file format.
tags: Tags to link with other policy rules.
ttl: Optional, TTL value used for these answers.
nodata: Optional, use NODATA synthesis. NODATA will be synthesized for matching name, but mismatching type(e.g. AAAA query when only A exists).
"""
name: Optional[ListOrItem[DomainName]] = None
subtree: Optional[Literal["empty", "nxdomain", "redirect"]] = None
address: Optional[ListOrItem[IPAddress]] = None
file: Optional[ListOrItem[ReadableFile]] = None
records: Optional[EscapedStr] = None
tags: Optional[List[IDPattern]] = None
ttl: Optional[TimeUnit] = None
nodata: Optional[bool] = None
# TODO: probably also implement the rule options from RPZSchema (.log + .dry_run)
def _validate(self) -> None:
options_sum = sum([bool(self.address), bool(self.subtree), bool(self.file), bool(self.records)])
if options_sum == 2 and bool(self.address) and self.subtree in {"empty", "redirect"}:
pass # these combinations still make sense
elif options_sum > 1:
raise ValueError("only one of 'address', 'subtree' or 'file' can be configured")
elif options_sum < 1:
raise ValueError("one of 'address', 'subtree', 'file' or 'records' must be configured")
options_sum2 = sum([bool(self.name), bool(self.file), bool(self.records)])
if options_sum2 != 1:
raise ValueError("one of 'name', 'file or 'records' must be configured")
if bool(self.nodata) and bool(self.subtree) and not bool(self.address):
raise ValueError("'nodata' defined but unused with 'subtree'")
class RPZSchema(ConfigSchema):
class Raw(ConfigSchema):
"""
Configuration or Response Policy Zone (RPZ).
---
file: Path to the RPZ zone file.
watchdog: Enables files watchdog for configured RPZ file. Requires the optional 'watchdog' dependency.
tags: Tags to link with other policy rules.
log: Enables logging information whenever this RPZ matches.
"""
file: ReadableFile
watchdog: Union[Literal["auto"], bool] = "auto"
tags: Optional[List[IDPattern]] = None
log: Optional[List[Literal["ip", "name"]]] = None
# dry_run: bool = False
_LAYER = Raw
file: ReadableFile
watchdog: bool
tags: Optional[List[IDPattern]]
log: Optional[List[Literal["ip", "name"]]]
# dry_run: bool
def _watchdog(self, obj: Raw) -> Any:
if obj.watchdog == "auto":
return WATCHDOG_LIB
return obj.watchdog
def _validate(self) -> None:
if self.watchdog and not WATCHDOG_LIB:
raise ValueError(
"'watchdog' is enabled, but the required 'watchdog' dependency (optional) is not installed"
)
class LocalDataSchema(ConfigSchema):
"""
Local data for forward records (A/AAAA) and reverse records (PTR).
---
ttl: Default TTL value used for added local data/records.
nodata: Use NODATA synthesis. NODATA will be synthesized for matching name, but mismatching type(e.g. AAAA query when only A exists).
addresses: Direct addition of hostname and IP addresses pairs.
addresses_files: Direct addition of hostname and IP addresses pairs from files in '/etc/hosts' like format.
records: Direct addition of records in DNS zone file format.
rules: Local data rules.
rpz: List of Response Policy Zones and its configuration.
"""
ttl: Optional[TimeUnit] = None
nodata: bool = True
addresses: Optional[Dict[DomainName, ListOrItem[IPAddress]]] = None
addresses_files: Optional[List[ReadableFile]] = None
records: Optional[EscapedStr] = None
rules: Optional[List[RuleSchema]] = None
rpz: Optional[List[RPZSchema]] = None
# root_fallback_addresses*: removed, rarely useful
|