pub struct PolicyRules {
pub max_lifetime_ttl_seconds: Option<u64>,
pub max_memory_max_bytes: Option<u64>,
pub max_run_timeout_ms: Option<u64>,
pub require_egress_declared: bool,
pub forbid_outbound_egress_rules: bool,
pub allowed_egress_hosts: Vec<String>,
pub require_runtime_secret_delivery: bool,
pub require_resource_limits: bool,
pub flag_dns_egress_without_acknowledgment: Option<bool>,
pub require_dns_egress_justification: Option<bool>,
pub secret_ref_allowlist: Option<HashMap<String, Vec<String>>>,
}Expand description
Constraint rules within a policy pack.
All fields are optional — an absent field means “no restriction on this axis.”
A PolicyPack with an empty PolicyRules is valid but does not constrain
any spec (useful as an explicit “audit-only” marker).
Fields§
§max_lifetime_ttl_seconds: Option<u64>spec.lifetime.ttlSeconds must not exceed this value.
max_memory_max_bytes: Option<u64>spec.run.limits.memoryMaxBytes must not exceed this value.
max_run_timeout_ms: Option<u64>spec.run.timeoutMs must not exceed this value.
require_egress_declared: boolWhen true, spec.authority.egressRules must be non-empty.
Use this to force explicit declaration of all outbound network intent — specs that declare no egress rules are rejected.
forbid_outbound_egress_rules: boolWhen true, specs must declare zero outbound egress rules.
Use this to enforce fully air-gapped workloads. A spec with any
spec.authority.egressRules is rejected.
allowed_egress_hosts: Vec<String>When non-empty, every spec.authority.egressRules[].host must match
at least one pattern in this list.
Patterns support a single leading *. wildcard (e.g. *.internal).
Exact hostnames are also accepted. An empty list means no restriction.
require_runtime_secret_delivery: boolWhen true, spec.run.secretDelivery must not be env.
Use this to prohibit the default env-variable secret delivery mode
and require runtimeBroker or runtimeLeasedBroker instead.
require_resource_limits: boolWhen true, spec.run.limits must be present.
Use this to ensure every spec explicitly declares resource bounds.
flag_dns_egress_without_acknowledgment: Option<bool>When true, any spec that declares an egress rule on port 53 (DNS) is
flagged with a PolicyViolation unless the spec also sets
authority.egressRules[].protocol = "dns-acknowledged" on every port-53
rule.
CellOS’s egress policy operates at L3/L4 (IP:port via nftables) and has
no visibility into DNS query content. A cell with declared port 53
egress can therefore exfiltrate arbitrary data via DNS TXT query labels
to an attacker-controlled authoritative nameserver, completely outside
CellOS observability. See docs/sec_roadmap.md R10 / SEC-15.
The dns-acknowledged protocol value is a forcing function, not a
security control: operators who understand the covert-channel risk can
set it to suppress the violation. Future work (L2-04 extension) is a
DNS proxy inside the cell netns with query-level CloudEvents.
require_dns_egress_justification: Option<bool>When true, any port-53 egress rule with protocol = "dns-acknowledged"
must also supply a non-empty dnsEgressJustification string.
This closes SEAM-2 (illusory consent): without it, an operator can
suppress flag_dns_egress_without_acknowledgment
by typing four words and zero further effort, defeating the forcing
function. With the rule enabled, the operator must record an auditable
justification alongside the acknowledgment, raising the cost of
reflexive suppression and creating evidence of stated reasoning.
See docs/sec_roadmap.md R10 / SEC-15c.
secret_ref_allowlist: Option<HashMap<String, Vec<String>>>A2-02: per-caller-identity allowlist for spec.authority.secretRefs.
Map shape: caller-identity → [allowed secretRef key]. The caller
identity is host-stamped via CELLOS_CALLER_IDENTITY at the supervisor
boundary (per ADR-0007 / D11: cellos-core itself does NOT read process
env vars; the resolved identity is threaded through to
validate_secret_refs_against_allowlist as a parameter).
When this field is None, the allowlist gate is skipped entirely —
admission proceeds against the rest of the rules unchanged. This is the
“audit-only” / opt-in posture documented in ADR-0007 §“What 1.0 ships”.
When this field is Some(map):
- The caller’s identity MUST appear as a key in
map(otherwise the caller is “unmapped” and rejected withCellosError::InvalidSpeccarrying acaller_unmappedreason string). - Every entry in
spec.authority.secretRefsMUST appear inmap[caller_identity](otherwise admission is rejected with asecret_ref_deniedreason naming the offending key).
The keys (caller identities) and values (secretRef names) are operator- curated portable strings; this field carries no implicit role hierarchy (see ADR-0007 non-goal “Hierarchical roles / role inheritance”). Two callers needing the same set of refs are two map entries, not one.
See ADR-0007 (docs/adr/0007-rbac-secret-ref-admission.md) for the
contract; A2-03 (multi-tenant event isolation) is a separate surface.
Trait Implementations§
Source§impl Clone for PolicyRules
impl Clone for PolicyRules
Source§fn clone(&self) -> PolicyRules
fn clone(&self) -> PolicyRules
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more