Your browser sucks, JavaScript disabled! Gunnar's console needs JavaScript and WebAssembly. Git over SSH on port 2222 does not.

nordisk/holger

examples/secure-update-gateway/trust-policy.ron

// holger.bundle-trust-policy/v1 — the offline trust policy a verifier enforces.
//
// Trust is by certificate FINGERPRINT (sha256 of the cert DER). Replace the
// placeholder fingerprints below with your own:
//     openssl x509 -in signer.crt -outform der | sha256sum
//
// The trust posture is STATED, never inferred. This sample runs
// `trust_mode: Some(PinnedSigners)`: a signer is trusted iff its fingerprint is
// listed below, and `trusted_roots` must stay empty because nothing would read it.
// For a CA chain instead, write `trust_mode: Some(RootedChain)` and put the
// hex-encoded DER of each root CA in `trusted_roots` (which must then be non-empty).
// A policy that states no `trust_mode` is REFUSED — holger-update-34 — because an
// unanswered trust question is not a permissive answer.
(
    schema_version: "holger.bundle-trust-policy/v1",

    trust_mode: Some(PinnedSigners),
    trusted_roots: [],

    // notBefore/notAfter on every signer certificate are enforced (the default).
    // On a box whose real-time clock cannot be trusted — a flat RTC battery hands
    // the verifier 1970 and every certificate looks "not yet valid" — set
    // `IgnoreUnreliableClock` DELIBERATELY; it also gives up the only revocation
    // an airgapped verifier has.
    certificate_validity: Enforce,

    approved_signers: [
        (
            fingerprint: "REPLACE_WITH_SECURITY_REVIEWER_FINGERPRINT",
            subject: Some("CN=security-reviewer"),
            roles: ["security-reviewer"],
        ),
        (
            fingerprint: "REPLACE_WITH_SYSTEM_OWNER_FINGERPRINT",
            subject: Some("CN=system-owner"),
            roles: ["system-owner"],
        ),
    ],

    // Two DISTINCT approvers, both required roles, each satisfied by a distinct cert.
    required_approval_roles: ["security-reviewer", "system-owner"],
    minimum_distinct_approvers: 2,

    // A distinct trusted release signer produces the final release signature.
    trusted_release_signers: ["REPLACE_WITH_RELEASE_SIGNER_FINGERPRINT"],
    release_signer_must_be_distinct: true,

    // Freshness + required evidence.
    maximum_bundle_age_secs: Some(31536000),   // 365 days
    require_expiry: true,
    require_sbom: true,
    require_vex: false,
    require_scan: false,

    // What a DOWNSTREAM box does once bundle metadata has expired: keep serving
    // what is verified and accept no writes (`Some(ReadOnly)` — the owner's
    // default, 2026-09-28, also what an unstated posture means), or stop serving
    // (`Some(Refuse)`, an explicit per-estate choice). Stated here so the file
    // says it.
    on_expired_metadata: Some(ReadOnly),

    // Optional target allow-lists (empty = any).
    allowed_products: ["ExampleDrive"],
    allowed_models: ["ACS880"],
)