config
config
¶
Shield configuration types, enums, and mode protocol.
Defines the vocabulary shared across the entire codebase: what a shield configuration looks like, what modes and states exist, and what contract a mode backend must satisfy.
ANNOTATION_LIST_SEP = ':'
module-attribute
¶
ANNOTATION_KEY = 'terok.shield.profiles'
module-attribute
¶
ANNOTATION_NAME_KEY = 'terok.shield.name'
module-attribute
¶
ANNOTATION_STATE_DIR_KEY = 'terok.shield.state_dir'
module-attribute
¶
ANNOTATION_VERSION_KEY = 'terok.shield.version'
module-attribute
¶
ANNOTATION_AUDIT_ENABLED_KEY = 'terok.shield.audit_enabled'
module-attribute
¶
ANNOTATION_UPSTREAM_DNS_KEY = 'terok.shield.upstream_dns'
module-attribute
¶
ANNOTATION_DNS_TIER_KEY = 'terok.shield.dns_tier'
module-attribute
¶
DnsTier
¶
Bases: Enum
DNS resolution tier for egress control.
Determines how domain-based allowlists are enforced:
Per-container dnsmasq with --nftset auto-populates nft
allow sets on every DNS query. Handles IP rotation.
DIG: Static resolution at pre-start via dig (current fallback).
GETENT: Single-IP resolution via getent hosts (minimal fallback).
ShieldMode
¶
ShieldState
¶
Bases: Enum
Per-container shield state, derived from the live nft ruleset.
QUARANTINE: Total network blackout — all traffic dropped, dropped traffic logged. UP: Normal enforcing mode (deny-all with allowlists). DOWN: Bypass mode with private-range protection (RFC 1918 + RFC 4193). DISENGAGED: Bypass mode without private-range protection. OFFLINE: No ruleset found (container stopped or unshielded). ERROR: Ruleset present but unrecognised.
QUARANTINE = 'quarantine'
class-attribute
instance-attribute
¶
UP = 'up'
class-attribute
instance-attribute
¶
DOWN = 'down'
class-attribute
instance-attribute
¶
DISENGAGED = 'disengaged'
class-attribute
instance-attribute
¶
OFFLINE = 'offline'
class-attribute
instance-attribute
¶
ERROR = 'error'
class-attribute
instance-attribute
¶
ShieldRuntime
¶
Bases: Enum
Container runtime category — drives DNS-reachability assumptions.
crun / runc / youki. The container shares the netns,
so dnsmasq on 127.0.0.1 is reachable directly.
KRUN: libkrun microVM. The guest has its own loopback isolated
from the netns, so dnsmasq must bind to a link-local address
on netns lo that the guest can reach via passt.
DEFAULT = 'default'
class-attribute
instance-attribute
¶
KRUN = 'krun'
class-attribute
instance-attribute
¶
from_runtime_name(name)
classmethod
¶
Map a podman --runtime <name> string (or None) to the enum.
Centralises the wire-format vocabulary so callers don't repeat
"krun" → KRUN mappings inline. Anything other than
"krun" (including None and unknown runtime names) maps
to DEFAULT — the loopback-shared-with-netns assumption holds
for every runtime shield has been tested against besides krun.
Source code in src/terok_shield/config.py
ShieldConfig(state_dir, mode=ShieldMode.HOOK, default_profiles=('dev-standard',), loopback_ports=(), audit_enabled=True, profiles_dir=None, runtime=ShieldRuntime.DEFAULT)
dataclass
¶
Per-container shield configuration.
The library is a pure function of its inputs. Given a
ShieldConfig with state_dir, it writes to that directory
and nowhere else. No env-var reading, no config-file parsing.
state_dir
instance-attribute
¶
mode = ShieldMode.HOOK
class-attribute
instance-attribute
¶
default_profiles = ('dev-standard',)
class-attribute
instance-attribute
¶
loopback_ports = ()
class-attribute
instance-attribute
¶
audit_enabled = True
class-attribute
instance-attribute
¶
profiles_dir = None
class-attribute
instance-attribute
¶
runtime = ShieldRuntime.DEFAULT
class-attribute
instance-attribute
¶
AuditFileConfig
¶
ShieldFileConfig
¶
Bases: BaseModel
Validated schema for config.yml.
Loaded by the CLI at startup. extra="forbid" rejects unknown
keys so typos (e.g. mod: hook) produce a clear error instead
of being silently ignored.
mode = Field(default='auto', description='Firewall mode (``auto`` selects the best available)')
class-attribute
instance-attribute
¶
default_profiles = Field(default_factory=(lambda: ['dev-standard']), description='Profiles applied when no explicit list is given')
class-attribute
instance-attribute
¶
audit = Field(default_factory=AuditFileConfig, description='Audit logging settings')
class-attribute
instance-attribute
¶
model_config = ConfigDict(extra='forbid')
class-attribute
instance-attribute
¶
ShieldModeBackend
¶
Bases: Protocol
Strategy protocol for shield mode implementations.
Each concrete backend (e.g. HookMode) provides the full
lifecycle: per-container firewalling, live allow/deny, bypass,
and preview.
detect_dns_tier(has, dnsmasq_nftset_ok=lambda: True, dnsmasq_state_readable=lambda: True)
¶
Detect the best available DNS resolution tier.
Probes for executables in priority order: dnsmasq (with nftset support, and able to read its config) > dig > getent.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
has
|
Callable[[str], bool]
|
Returns True if the named executable exists on PATH. |
required |
dnsmasq_nftset_ok
|
Callable[[], bool]
|
Returns True if installed dnsmasq supports
|
lambda: True
|
dnsmasq_state_readable
|
Callable[[], bool]
|
Returns True if dnsmasq can read its
config from the shield state directory. Returns False when
an enforcing AppArmor profile confines dnsmasq away from it,
so we fall back to |
lambda: True
|