From a4342fe0a4243fb6169b0c9ac7376ff20b8fcc40 Mon Sep 17 00:00:00 2001 From: croadfeldt Date: Tue, 7 Jul 2026 23:18:00 -0500 Subject: [PATCH] architecture: DCM trust model (attestation, flows, profiles) The DCM trust and credential model: attestation-gated trust, the uphold / participate / expose flows across the trust planes, and profile-keyed trust defaults from homelab through sovereign. Companion to the credential-API and governance architecture. Signed-off-by: croadfeldt --- architecture/trust-attestation.md | 50 ++++++++++++++++ architecture/trust-flows.md | 90 ++++++++++++++++++++++++++++ architecture/trust-profiles.md | 97 +++++++++++++++++++++++++++++++ 3 files changed, 237 insertions(+) create mode 100644 architecture/trust-attestation.md create mode 100644 architecture/trust-flows.md create mode 100644 architecture/trust-profiles.md diff --git a/architecture/trust-attestation.md b/architecture/trust-attestation.md new file mode 100644 index 0000000..4a88f27 --- /dev/null +++ b/architecture/trust-attestation.md @@ -0,0 +1,50 @@ +# Trust Attestation — how DCM/UDLM attest to, build, and ensure trust + +**Goal:** earn and ensure trust for **customers, users, producers, and consumers** — not by assertion ("trust us"), but by making the trust model itself **transparent, standards-grounded, validation-backed, and independently verifiable**, and by **holding ourselves to the same bar we require of producers** (self-application). "We don't ask you to trust us — we give you what you need to *verify* us, by the same rules we apply to everyone." + +## Minimization first: this is a *projection*, not a new framework — ZERO new primitives + +A **Trust Attestation** composes records UDLM already has. We invent nothing: + +| Existing record (reused) | Contribution to the attestation | +|---|---| +| **DecisionRecord** (the WHY; reaches `CANONICAL` only with passing use-case validation) | **why** the process is the way it is — *validation-backed*, so the rationale is evidenced, not asserted | +| **Accreditation** artifact (versioned, time-bounded conformance to a framework) | **what** it conforms to + the attestation **tier** of that claim | +| **CONFORMANCE** declaration + independent-verifier flow | **self-declaration + third-party verification** of what's implemented | +| **Audit & Tamper-Evidence** (ADR-010) + field provenance | the **evidence** trail | +| **trust_posture** (ADR-022) exposed at well-known endpoints | **publication** — any party fetches + verifies | + +The Trust Attestation is the **assembled, signed, published view** of these. (One thin addition: a *projection/exposure* — not a new data primitive.) + +## The artifact — a Trust Posture Statement +A signed, versioned record any party can fetch and verify, composed of six parts: + +1. **Rationale (why).** The governing DecisionRecords — ADR-022 (credential API selection), ADR-022 (trust model), the design priorities (broker-not-authority, claim≠trust, security/trust/fit > portability, CPX-001 value-never-in-DCM). Each is validation-backed → the *why* is demonstrably sound, not just stated. +2. **Standards followed.** The adopt-by-reference catalog, version-pinned + conformance refs: X.509/PKIX, ACME/EST/SCEP/CMP, OAuth2/OIDC/RFC7662, RFC 8693, KMIP/PKCS#11, RATS (RFC 9334), NIST 800-63B (AAL), FIPS 140-3, Common Criteria, eIDAS, PCI-DSS, SOC 2, SecNumCloud, C5, IRAP. +3. **Best practices followed.** Zero-trust (**NIST SP 800-207**), least-privilege, short-lived credentials, defense-in-depth, **minimal trust surface** (broker — DCM holds no managed secrets), value-never-in-control-plane (CPX-001), separation of duties, auditability. +4. **Conformance claim.** What DCM/UDLM *implements*, at which **profile** (homelab→sovereign), **plus the attestation tier of the claim itself** (`self_asserted` → `independently_verified` → `accredited`) — the *same ladder* we apply to producers (ADR-022). A sovereign customer sees an accredited claim or it doesn't count. +5. **Evidence.** Audit/provenance + use-case validation results; and, by reference where a market needs them: supply-chain provenance (**in-toto / SLSA**), runtime attestation (**RATS**), and formal conformity assessments (SOC 2 / CC / eIDAS). +6. **Exposure.** Signed, versioned, served at a well-known endpoint (`/.well-known/udlm/trust-posture`) so customers/peers verify it without asking — the ADR-022 "expose" obligation, applied to ourselves. + +## Self-application — the credibility multiplier +DCM runs its **own** trust model **on itself**: its trust posture is declared, attested, and verified by the *same* machinery and at the *same* tiers it demands of producers. This is the strongest possible attestation — we are not exempt from our own rules. It also means a producer or customer evaluating DCM uses the *same* tooling they'd use to evaluate any provider (no special case). + +## Per-audience projection (one source, scoped views) +Same record, audience-scoped lenses (one source, many projections): +- **Customer** (regulated): the accreditation evidence + conformity assessments for *their* market (FedRAMP/eIDAS/PCI…). +- **User**: the identity + authorization posture (how they're authenticated, session/revocation guarantees). +- **Producer**: what DCM requires to register + how DCM authenticates the introductions it brokers. +- **Consumer**: what's brokered, the CPX-001 guarantee (DCM never sees the value), and the selection/attestation guarantees. + +**Renderer/assessor is an abstract role — non-normative.** The Trust Posture Statement is rendered/verified by **any conformant, independent assessor**; the model names no specific tool and depends on none. An external assessment consumer or testbed *may* exercise this role to produce/validate the views, but that is illustrative, not a structural dependency. + +## Adopt-by-reference for the *form* of attestation too (don't invent) +Even the *shape* of the attestation follows established forms — **SOC 2 / ISO conformity assessment**, **eIDAS conformity**, **C2PA / in-toto / SLSA** provenance, **RATS** runtime attestation, and the **trust-center / well-known-endpoint** publication pattern. We map onto these, we don't define a new attestation language. + +## Data · Policy · Provider +- **Data (UDLM):** the Trust Posture Statement = a projection over DecisionRecord + Accreditation + CONFORMANCE + Audit (all existing UDLM records); the `trust_posture` exposure shape. +- **Policy (DCM):** assembles, signs, and serves the statement; gates federation/selection on peers' statements; re-verifies on schedule. +- **Provider:** publishes its own posture the same way; DCM (as a participant) publishes *its* posture identically. + +## Net +**Zero new data primitives** — the attestation is a signed, published *projection* of records UDLM already defines, plus a well-known exposure endpoint. It earns trust by transparency + validation-backing + self-application + independent verifiability, all adopt-by-reference. Fully consistent with the minimize-standards/processes priority: it adds **publication + projection**, not a new framework. diff --git a/architecture/trust-flows.md b/architecture/trust-flows.md new file mode 100644 index 0000000..a4427e3 --- /dev/null +++ b/architecture/trust-flows.md @@ -0,0 +1,90 @@ +# Trust & Credential Flows — expressed via existing DCM primitives + +The operational flows behind ADR-022 (DCM Trust Model, incl. Credential API Selection). **Design intent: express every flow in terms of primitives DCM already has; where a primitive is genuinely missing, propose one that follows DCM's own methodology and industry best practice.** This is the layer between the requirements (ADR-022) and engineering — engineering implements *named flows over named primitives*, it does not invent them. + +## Primitives reused (no change) +| Primitive | Role in trust/credential flows | +|---|---| +| **Request Orchestrator** (event bus) | carries `credential.requested` / lifecycle events to subscribers | +| **Placement Engine** (sovereignty pre-filter → accreditation filter → capability filter → score → select) | **is** the credential-API selection engine — credential capability is the capability dimension, attestation is the accreditation filter | +| **Policy Engine** — Gating Policy / Validation / Transformation / Recovery | profile gating, requirement validation, provenance on mutations, failure handling | +| **Governance Matrix** (`boundary_control`) | evaluated at the consumer↔producer boundary crossing | +| **Accreditation** artifact (versioned, time-bounded) | carries `attestation[]`; the accreditation filter reads it | +| **Audit & Tamper Evidence** (ADR-010) + field provenance | every match/gate/introduction/issuance recorded | +| **Credential / Session Revocation Registry**, **Transition Window**, **Emergency Rotation** | rotation + revocation | +| **Discovery Service** (scheduled polling, configurable interval) | the scheduler for rotation/re-attestation | +| **Provider registration + lifecycle-event endpoint**, **Provider Callback Auth (PCA, mTLS)**, **Component Identity**, **Trust Anchor / Internal+External CA (ICOM-009)**, **Token Introspection (RFC 7662) / JWKS / well-known** | identity, transport, exposure | + +--- + +## Flow 1 — Broker introduction (request → direct issuance) +1. Consumer submits `credential_requirements` → `credential.requested` on the **Request Orchestrator**. *[reuse]* +2. **Placement Engine** runs as the selection engine: **sovereignty pre-filter** → **accreditation filter** (= attestation gate, ADR-022) → **capability filter** (credential_capability match) → **score** (credential scoring profile — *new, §P4*) → select producer + spec. *[reuse + P4]* +3. **Gating Policy/Governance-Matrix** gate the selection on the profile floor (tier/frameworks/FIPS/AAL/residency; vendor-native opt-in). *[reuse]* +4. DCM mints an **Introduction Grant** (*new, §P1*) — short-lived, audience-scoped to (consumer, producer, request) — and returns it + producer endpoint + trust anchors. *[P1]* +5. Consumer connects **directly** to the producer's selected-spec endpoint, presents the Grant; producer validates it against DCM's **JWKS/introspection** (DCM's "expose"). *[reuse + P1]* +6. Producer issues the credential **direct to consumer** over the standard spec (ACME/EST/OAuth/KMIP). **Value never transits DCM** (CPX-001). *[reuse]* +7. Introduction + issuance-confirmation recorded in **Audit** with the attestation that justified it. *[reuse]* + +## Flow 2 — Attestation verification +1. On registration/update, a producer's `attestation[]` lands as **Accreditation** artifacts. *[reuse]* +2. **Attestation Verifier** (*new, §P2*) validates each: signature → issuing authority is a **recognized Accreditation Authority** (*new registry, §P2*, modeled on **Trust Anchor**) → validity window → revocation (OCSP/CRL). For `hardware_attested`, runtime **RATS** quote (RFC 9334). *[P2]* +3. Verified attestation tier/framework is cached (profile-governed TTL) and is what the **accreditation filter** (Flow 1.2) reads. *[reuse]* +4. Verification result + provenance → **Audit**. *[reuse]* + +## Flow 3 — Bootstrap (pre-registration trust) +1. Before any Credential Provider is registered, DCM uses a **Bootstrap Trust Anchor** + one-time **bootstrap token** (*new but small, §P3*) — out-of-band installed root + short-lived enrolment token. *[P3]* +2. First provider registers over PCA mTLS, presenting the bootstrap token; DCM validates against the bootstrap anchor (ICOM-009). *[reuse + P3]* +3. After bootstrap, all issuance flows through registered, attested providers via Flow 1; the bootstrap token is single-use and expires. *[reuse]* + +## Flow 4 — Rotation & revocation +1. **Discovery-Service-style scheduler** fires a rotation trigger at the declared interval (or on `expires_at` approach). *[reuse]* +2. An **Orchestration-Flow Policy** re-runs Flow 1 for the resource; **Transition Window** keeps old+new valid; cutover; old retired. *[reuse]* +3. Revocation (scheduled or **Emergency Rotation** on a security event) writes the **Credential/Session Revocation Registry**; producers + components check it per use. *[reuse]* +4. Re-attestation: the scheduler also re-runs Flow 2 before an Accreditation's `valid_until`; an expired/revoked attestation drops the provider from the accreditation filter (fail-safe). *[reuse]* + +## Flow 5 — Selection algorithm detail +The **Placement Engine scoring model** with a **credential scoring profile** (*new, §P4*): hard **filter/gate** = security + trust(attestation) + fit-for-purpose; **score/tie-break** = portability (standardized > vendor-native) + attestation-strength + lifetime fit. Portability is a tiebreak weight, never a gate (ADR-022 inversion). *[reuse + P4]* + +## Flow 6 — DCM as participant (its own credentials) +DCM, needing a credential for its own identity/user-auth, is just another **consumer**: it runs Flow 1 through the same orchestrator/placement/gating (no privileged bypass), obtaining from a registered producer or its **Internal CA** (self-producer, own components only). DCM-operational secrets are held + protected per profile (ADR-022). *[reuse]* + +--- + +## Proposed NEW primitives (the genuine gaps) + +> **v1 scope (ADR-022):** only **P1** is required for v1. **P2** ships thin (self/vendor tiers; accredited + RATS deferred), **P3** is small, **P4** is configuration. Accredited/hardware mechanisms are *declared-but-deferred* until a market needs them (fail-safe rule). + +### P1 — Introduction Grant +A short-lived, audience-scoped, signed token DCM mints to authorize a **direct** consumer↔producer credential exchange — DCM's "introduction," then it steps out (ADR-022 broker boundary). +- **Why new:** the existing **DCM Interaction Credential** authorizes *DCM→provider dispatch* (PCA); there is no token for brokering a *consumer↔producer* direct channel. This is that. +- **Basis:** OAuth 2.0 / **Token Exchange (RFC 8693)** + audience-restricted JWT; producer validates against DCM JWKS — standard, and reuses DCM's existing JWKS/introspection. Conceptually a capability token (cf. macaroons, SPIFFE JWT-SVID). +- **Fits:** minted in Flow 1.4; a Validation/Gating Policy-class artifact; audited. + +### P2 — Attestation Verifier + Accreditation Authority registry +A verifier that turns a *claimed* attestation into a *trusted* one, and a registry of recognized authorities per framework/market. +- **Why new:** DCM has the **Accreditation** artifact + an accreditation *filter*, but not the **verification** (signature/authority/validity/revocation) nor a registry of *which* authorities are recognized for *which* market. +- **Basis:** extend the **Trust Anchor** model (ICOM-009) to accreditation authorities (CMVP/CC/FedRAMP/eIDAS/…); **RATS (RFC 9334)** for hardware/TEE remote attestation; OCSP/CRL for cert validity. A **Validation Policy** type runs it. +- **Fits:** Flow 2; feeds the accreditation filter in Flow 1.2. + +### P3 — Bootstrap Trust Anchor + bootstrap token +A minimal, out-of-band root + single-use enrolment token for the pre-registration chicken-and-egg. +- **Why new:** referenced in `credentials.md` but not specified as a primitive. +- **Basis:** kubeadm bootstrap tokens / SPIRE node attestation / TOFU-with-OOB-verification — established patterns; reuses ICOM-009 trust-anchor validation. +- **Fits:** Flow 3. + +### P4 — Credential scoring profile +A scoring profile for the existing Placement scoring model that encodes the credential priority order. +- **Why new:** it's a *configuration* of the existing scoring engine, not a new engine — but it must exist so portability scores as a **tiebreak**, not a filter (the ADR-022 inversion), with attestation-strength weighted. +- **Basis:** the existing Placement scoring model (ADR-007 / scoring.md) — just a new named profile. +- **Fits:** Flow 1.2 / Flow 5. + +--- + +## Net assessment +**~80% reuse.** The selection engine, gating, audit, accreditation artifact, revocation, rotation windows, scheduler, identity/transport, and exposure are all existing DCM primitives. **Four net-new pieces**, each grounded in an existing DCM mechanism *and* an industry standard: **P1** Introduction Grant (RFC 8693), **P2** Attestation Verifier + Authority registry (Trust-Anchor model + RATS RFC 9334), **P3** Bootstrap anchor/token (kubeadm/SPIRE), **P4** credential scoring profile (Placement scoring). Only P1 and P2 are substantive; P3 is small, P4 is configuration. Engineering then implements named flows over named primitives. + +## Data · Policy · Provider +- **Data (UDLM):** Introduction Grant shape, attestation/accreditation records, credential scoring inputs — declared/auditable. +- **Policy (DCM):** the flows are Placement + Policy-Engine + Governance-Matrix compositions; P2/P4 are policy/engine config; P1 is a minted, gated artifact. +- **Provider:** presents attestation + identity, implements the selected spec, issues direct to the consumer under the Introduction Grant. diff --git a/architecture/trust-profiles.md b/architecture/trust-profiles.md new file mode 100644 index 0000000..493f614 --- /dev/null +++ b/architecture/trust-profiles.md @@ -0,0 +1,97 @@ +# Trust & attestation — accepted methods by operational profile (homelab → sovereign) + +**Principle:** trust/attestation strength is a **definable parameter with per-profile defaults** in DCM operational profiles — *and* DCM must carry the **mechanisms** to actually satisfy each target framework (declaration without enforcement is theater). Everything below is **adopt-by-reference** (ADR-021): real, accepted standards, not invented. Each cell is the *default floor* for that profile; a request may tighten (never loosen below the floor — governance). + +Profiles (existing DCM ladder; **homelab** = the relaxed end of `minimal`): +`homelab/dev → minimal → standard → fsi → sovereign` + +--- + +## The matrix — accepted method per trust plane × profile + +### Identity & transport (who is talking) +| | method (default floor) | +|---|---| +| homelab/dev | internal/self-signed CA; TLS optional; bearer between components | +| minimal | internal CA; TLS 1.2+; mTLS optional | +| standard | **mTLS everywhere**; real PKI (internal CA or ACME/Let's Encrypt); TLS 1.3; short-lived certs; **SPIFFE/SPIRE** workload identity (CNCF) recommended | +| fsi | mTLS mandatory; enterprise PKI w/ documented chain; OCSP stapling; cert lifetimes ≤ 90d; HSM-protected CA keys | +| sovereign | mTLS mandatory; **accredited** PKI; in-jurisdiction CA; hardware-protected CA (FIPS L3 HSM); RATS remote attestation of endpoints (RFC 9334) | + +### Anchor — root of trust (`anchor_type`, ADR-022) +*Suggested methods + the settable minimum per profile. `anchor_type` is a pluggable, declared dimension (ADR-022) — public-acme, internal-ca, private-acme, enterprise-pki, authority-list, hardware-rats, transparency-log, spiffe-bundle, tofu, did/ledger, threshold.* +| | suggested anchor(s) | minimum requirement | +|---|---|---| +| homelab/dev | **`public-acme` (Let's Encrypt → ISRG root) for the public TLS edge** + **`internal-ca` or `private-acme` (step-ca) for the mesh/mTLS**; `tofu` bootstrap OK | any rooted anchor (internal-ca / private-acme / public-acme). *Note: a Let's Encrypt **leaf** can root the public edge but **cannot issue** mesh/client certs (CA:FALSE) — use step-ca/internal CA for mTLS.* self-signed only for throwaway dev | +| minimal | `internal-ca` or `private-acme` (step-ca) mesh; `public-acme` edge optional | a real issuing root (internal-ca / private-acme) — no bare self-signed for the mesh | +| standard | internal/enterprise PKI or `private-acme` mesh + `public-acme` edge; **`transparency-log` (CT/Sigstore)** recommended; `spiffe-bundle` optional | real CA + CRL/OCSP; transparency-logging recommended | +| fsi | `enterprise-pki` (documented chain) with **HSM-protected issuing root**; `authority-list` for attestation; CT | HSM-protected issuing CA **+** external `authority-list` for assurance claims | +| sovereign | **accredited, in-jurisdiction, HSM-L3 issuing root**, root key **`threshold`/ceremony-protected**; external authority roots (CMVP/eIDAS) **+ `hardware-rats`**; disconnected = import + re-anchor | accredited + HSM-L3 issuing root, external-authority attestation, hardware-attested (top tier), quorum-protected root key | + +### Authorization (what they may do) +| | method | +|---|---| +| homelab/dev | static token / basic OIDC; long-ish sessions | +| minimal | OIDC (Keycloak/RHSSO); JWT; introspection optional | +| standard | OIDC + **token introspection (RFC 7662)** + JWKS rotation; session revocation registry; AAL1–2 | +| fsi | OIDC + **AAL2 hardware MFA**; step-up-MFA for sensitive ops; short token TTL; dual-control on privileged actions | +| sovereign | **AAL3** hardware-bound (FIDO2/PIV/CAC); step-up everywhere; PT-scale token TTL; full revocation propagation | + +### Credential issuance / retrieval (ADR-022 selected spec) +| | x509 | tokens | keys | +|---|---|---|---| +| homelab/dev | self-signed / internal ACME | OAuth2 | software keys | +| standard | **ACME** (RFC 8555) / internal CA | OAuth2 + OIDC | software or KMS | +| fsi | **EST/CMP** to enterprise CA; ≤90d | OAuth2, short TTL | **HSM/KMIP**, FIPS 140-3 | +| sovereign | EST/CMP to accredited CA, in-jurisdiction | mTLS-bound tokens | **HSM L3 + key ceremony**, split-knowledge (NIST SP 800-57) | + +### Attestation (the trust backing — ADR-022 ladder) +| | default tier + accepted frameworks | +|---|---| +| homelab/dev | `self_asserted` | +| minimal | `self_asserted` → `vendor_attested` | +| standard | `vendor_attested` / `independently_verified`; SOC 2; ISO 27001; FIPS via CMVP if claimed | +| fsi | `independently_verified`+; **PCI-DSS, SOC 2 Type II, FIPS 140-3 CMVP** | +| sovereign | `accredited` + `hardware_attested`; market authority: **FedRAMP High + FIPS 140-3 L3 + Common Criteria** (US), **eIDAS QTSP / SecNumCloud / BSI C5 / EUCS** (EU), **IRAP** (AU), **ISMAP** (JP); TPM/HSM remote attestation; confidential-compute attestation (SEV-SNP/TDX/SGX) where applicable | + +### Federation (trusting another DCM/provider) +| | method | +|---|---| +| homelab/dev | manual trust-anchor add | +| standard | exchange trust anchors; verify CONFORMANCE declaration | +| fsi | + verify `independently_verified` attestation before federating | +| sovereign | + verify `accredited` posture, jurisdiction match, and live attestation; no federation to lower-posture peers | + +Cross-cutting baseline (ALL profiles, including homelab — strictness scales, existence doesn't): zero-trust posture (NIST SP 800-207); CPX-001 (values never transit DCM); audit of every trust decision (ADR-010); forbidden-weak-algorithm baseline; supply-chain integrity (SLSA / signed artifacts) recommended standard+. + +--- + +## Mechanisms DCM must implement (to *support*, not just declare, the targets) +1. **PKI/PKIX + mTLS** stack with trust-anchor management, chain validation, **CRL + OCSP** checking (ICOM-009). +2. **ACME / EST / SCEP / CMP** client(s) for cert issuance/rotation; SPIFFE/SPIRE integration option. +3. **OIDC relying-party + token introspection (RFC 7662) + JWKS** rotation; session revocation registry; step-up-MFA hook. +4. **HSM / PKCS#11 / KMIP** integration for key custody; BYOK/HYOK; key-ceremony + split-knowledge support. +5. **Attestation verification**: ingest + validate Accreditation artifacts (cert id, validity, revocation); **RATS remote attestation** (RFC 9334) for TPM/HSM/confidential-compute quotes. +6. **Accreditation/conformance registry** surface — queryable trust posture (provider + DCM's own), exposed at well-known endpoints. +7. **Profile engine**: the trust/attestation floor is a profile parameter; the selection/gate engine (ADR-022) enforces it per request, market-graded. + +> A profile may *require* a framework only if DCM has the mechanism to verify it. Gap = a tracked conformance item, not a silent pass. Where a mechanism is absent, the profile cannot claim that target (fail-safe). + +--- + +## The definable parameter (ties to DCM operational profiles) +```yaml +profile: sovereign +region: eu +trust_floor: # default per profile; request may tighten only + anchor: { allowed_types: [accredited-pki, hardware-rats], # the pluggable anchor_type set + root_protection: threshold, in_jurisdiction: true, + external_authority_required: true } # homelab e.g.: { allowed_types: [public-acme, internal-ca, private-acme, tofu] } + identity: { mtls: required, ca: accredited, endpoint_attestation: required } + authorization: { min_aal: aal3, step_up: required } + attestation: { min_tier: accredited, require_hardware_attested: true, + accepted_frameworks: [eidas-qtsp, secnumcloud, bsi-c5, fips-140-3] } + key_custody: { hsm: required, fips_level: 140-3-L3, jurisdiction_in: [eu] } + federation: { min_peer_tier: accredited, jurisdiction_match: true } +``` +Defaults shipped for `homelab/dev`, `minimal`, `standard`, `fsi`, `sovereign`; operators override within governance bounds. This makes "what trust is required here" a **declared, queryable, governable** profile parameter — selected and enforced by the ADR-022/023 engine.