firewall: add default value for file based zones
This commit is contained in:
parent
93bccaddfd
commit
17b46bab5e
1 changed files with 35 additions and 19 deletions
|
@ -5,13 +5,21 @@ from dataclasses import dataclass
|
||||||
from enum import Enum
|
from enum import Enum
|
||||||
from graphlib import TopologicalSorter
|
from graphlib import TopologicalSorter
|
||||||
from ipaddress import IPv4Address, IPv4Network, IPv6Network
|
from ipaddress import IPv4Address, IPv4Network, IPv6Network
|
||||||
|
from pathlib import Path
|
||||||
from typing import Generic, Iterator, TypeAlias, TypeVar
|
from typing import Generic, Iterator, TypeAlias, TypeVar
|
||||||
|
|
||||||
import nft
|
import nft
|
||||||
from nftables import Nftables
|
from nftables import Nftables
|
||||||
from pydantic import (BaseModel, Extra, FilePath, IPvAnyNetwork,
|
from pydantic import (
|
||||||
ValidationError, conint, parse_obj_as, root_validator,
|
BaseModel,
|
||||||
validator)
|
Extra,
|
||||||
|
IPvAnyNetwork,
|
||||||
|
ValidationError,
|
||||||
|
conint,
|
||||||
|
parse_obj_as,
|
||||||
|
root_validator,
|
||||||
|
validator,
|
||||||
|
)
|
||||||
from yaml import safe_load
|
from yaml import safe_load
|
||||||
|
|
||||||
# ==========[ PYDANTIC ]========================================================
|
# ==========[ PYDANTIC ]========================================================
|
||||||
|
@ -75,9 +83,14 @@ class PortRange(str):
|
||||||
ZoneName: TypeAlias = str
|
ZoneName: TypeAlias = str
|
||||||
|
|
||||||
|
|
||||||
|
class ZoneEntryFile(RestrictiveBaseModel):
|
||||||
|
path: Path
|
||||||
|
default: None | AutoSet[IPvAnyNetwork] = None
|
||||||
|
|
||||||
|
|
||||||
class ZoneEntry(RestrictiveBaseModel):
|
class ZoneEntry(RestrictiveBaseModel):
|
||||||
addrs: AutoSet[IPvAnyNetwork] = AutoSet()
|
addrs: AutoSet[IPvAnyNetwork] = AutoSet()
|
||||||
file: FilePath | None = None
|
file: ZoneEntryFile | None = None
|
||||||
negate: bool = False
|
negate: bool = False
|
||||||
zones: AutoSet[ZoneName] = AutoSet()
|
zones: AutoSet[ZoneName] = AutoSet()
|
||||||
|
|
||||||
|
@ -189,10 +202,6 @@ class Firewall(RestrictiveBaseModel):
|
||||||
# ==========[ ZONES ]===========================================================
|
# ==========[ ZONES ]===========================================================
|
||||||
|
|
||||||
|
|
||||||
class ZoneFile(RestrictiveBaseModel):
|
|
||||||
__root__: AutoSet[IPvAnyNetwork]
|
|
||||||
|
|
||||||
|
|
||||||
@dataclass(eq=True, frozen=True)
|
@dataclass(eq=True, frozen=True)
|
||||||
class ResolvedZone:
|
class ResolvedZone:
|
||||||
addrs: set[IPvAnyNetwork]
|
addrs: set[IPvAnyNetwork]
|
||||||
|
@ -213,17 +222,24 @@ def resolve_zones(yaml_zones: dict[ZoneName, ZoneEntry]) -> Zones:
|
||||||
)
|
)
|
||||||
|
|
||||||
elif yaml_zones[name].file is not None:
|
elif yaml_zones[name].file is not None:
|
||||||
with open(yaml_zones[name].file, "r") as file:
|
file_entry = yaml_zones[name].file
|
||||||
try:
|
|
||||||
yaml_addrs = ZoneFile(__root__=safe_load(file))
|
|
||||||
except Exception as e:
|
|
||||||
raise Exception(
|
|
||||||
f"YAML parsing of the included file '{yaml_zones[name].file}' failed: {e}"
|
|
||||||
)
|
|
||||||
|
|
||||||
zones[name] = ResolvedZone(
|
try:
|
||||||
yaml_addrs.__root__, yaml_zones[name].negate
|
with open(file_entry.path, "r") as file:
|
||||||
|
try:
|
||||||
|
addrs = parse_obj_as(
|
||||||
|
AutoSet[IPvAnyNetwork], safe_load(file)
|
||||||
)
|
)
|
||||||
|
except ValidationError as e:
|
||||||
|
raise ValueError(
|
||||||
|
f"parsing of '{yaml_zones[name].file}' failed: {e}"
|
||||||
|
)
|
||||||
|
except OSError as e:
|
||||||
|
if file_entry.default is None:
|
||||||
|
raise e
|
||||||
|
addrs = file_entry.default
|
||||||
|
|
||||||
|
zones[name] = ResolvedZone(addrs, yaml_zones[name].negate)
|
||||||
|
|
||||||
elif yaml_zones[name].zones:
|
elif yaml_zones[name].zones:
|
||||||
addrs: set[IPvAnyNetwork] = set()
|
addrs: set[IPvAnyNetwork] = set()
|
||||||
|
@ -231,7 +247,7 @@ def resolve_zones(yaml_zones: dict[ZoneName, ZoneEntry]) -> Zones:
|
||||||
for subzone in yaml_zones[name].zones:
|
for subzone in yaml_zones[name].zones:
|
||||||
if yaml_zones[subzone].negate:
|
if yaml_zones[subzone].negate:
|
||||||
raise ValueError(
|
raise ValueError(
|
||||||
f"subzone '{subzone}' of zone '{name}' cannot be negated"
|
f"subzone '{subzone}' of '{name}' cannot be negated"
|
||||||
)
|
)
|
||||||
addrs.update(yaml_zones[subzone].addrs)
|
addrs.update(yaml_zones[subzone].addrs)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue