Integrate MIAF and WFM identity profile SUPs - #194
Conversation
Replace the Management Interface security model with
the MIAF and WFM Identity Profile SUPs: add the Identity
and Authorization section, switch to mTLS with X.509-SVIDs,
drop {clientId} from routes, and remove the onboarding,
certificate, and RFC 9421 payload-signing paths.
Signed-off-by: Matthias Lechner <[email protected]>
Signed-off-by: Matthias Lechner <[email protected]>
phil-abb
left a comment
There was a problem hiding this comment.
Here's some preliminary feedback.
Rework the Trust Bundle retrieval endpoint to return a single SPIFFE bundle (a JWK Set) per the SPIFFE Federation bundle- endpoint model, instead of a SPIFFE Bundle Map. Scope federation as future work and state that a verifier validates SVIDs against its own Trust Domain. Signed-off-by: Matthias Lechner <[email protected]>
Signed-off-by: Matthias Lechner <[email protected]>
Signed-off-by: Matthias Lechner <[email protected]>
Signed-off-by: Matthias Lechner <[email protected]>
…uirements-and-security.md Co-authored-by: Philip Presson <[email protected]> Signed-off-by: Matthias Lechner <[email protected]>
…rations.md Co-authored-by: Philip Presson <[email protected]> Signed-off-by: Matthias Lechner <[email protected]>
Co-authored-by: Philip Presson <[email protected]> Signed-off-by: Matthias Lechner <[email protected]>
…rations.md Co-authored-by: Philip Presson <[email protected]> Signed-off-by: Matthias Lechner <[email protected]>
…rations.md Co-authored-by: Philip Presson <[email protected]> Signed-off-by: Matthias Lechner <[email protected]>
Co-authored-by: Philip Presson <[email protected]> Signed-off-by: Matthias Lechner <[email protected]>
Co-authored-by: Philip Presson <[email protected]> Signed-off-by: Matthias Lechner <[email protected]>
Co-authored-by: Philip Presson <[email protected]> Signed-off-by: Matthias Lechner <[email protected]>
Prefix every link to a page in the same folder with "./" to force the Fumadocs resolving the link as a relative link (solves the 404 issue) Signed-off-by: Matthias Lechner <[email protected]>
The published site (Fumadocs, at docs.margo.org) builds its sidebar from a meta.json in each folder; with none present it falls back to alphabetical order, which scrambles the intended reading sequence. Add a meta.json for each specification section that sets the section title and lists its pages in the order given by mkdocs.yml, so the rendered site matches the local mkdocs preview. Signed-off-by: Matthias Lechner <[email protected]>
This comment was marked as outdated.
This comment was marked as outdated.
…ification into feat/miaf-integration Signed-off-by: Matthias Lechner <[email protected]>
d78526e to
401255a
Compare
Signed-off-by: Matthias Lechner <[email protected]>
Co-authored-by: Philip Presson <[email protected]> Signed-off-by: Matthias Lechner <[email protected]>
This comment was marked as resolved.
This comment was marked as resolved.
6ca5769 to
3415662
Compare
…rator The Trust Domain can be derived from the provisioned SVID alone by inspecting the SPIFFE ID in the cert's URI SAN. Signed-off-by: Matthias Lechner <[email protected]>
Signed-off-by: Matthias Lechner <[email protected]>
Signed-off-by: Matthias Lechner <[email protected]>
…rt pinning) Signed-off-by: Matthias Lechner <[email protected]>
|
|
||
| ## X.509-SVID Profile | ||
|
|
||
| MIAF adopts the [SPIFFE X.509-SVID specification](https://github.com/spiffe/spiffe/blob/main/standards/X509-SVID.md) by reference. X.509-SVID is the SVID representation used throughout MIAF. |
There was a problem hiding this comment.
Maybe would be good to mention if it pinned to a specific version. And how future versions are handled
There was a problem hiding this comment.
Good point, this is already covered here.
| | **RSA (≥3072 + SHA-256)** | Modulus MUST be at least 3072 bits; signatures MUST use SHA-256. RSASSA-PSS (`PS256`, [RFC 8017](https://datatracker.ietf.org/doc/html/rfc8017)) is RECOMMENDED. RSASSA-PKCS#1 v1.5 (`RS256`) MAY be used only for X.509 certificate and CSR signatures (today the only RSA signatures in MIAF), for compatibility with issuing CAs that cannot produce PSS signatures (its use there remains sanctioned by [NIST SP 800-131A Rev 2](https://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-131Ar2.pdf)). Any other RSA signature MIAF defines later MUST use PSS. | | ||
|
|
||
| - **ECDSA P-256 with SHA-256 is mandatory to implement.** Every MIAF component MUST implement it, for both presenting and validating SVIDs, so that any two components always share at least one algorithm. | ||
| - A component MAY additionally implement EdDSA (Ed25519), RSA, or both. Because a principal presents a single SVID bound to one signature algorithm, an SVID issued with a non-mandatory algorithm can be validated only by peers that implement that algorithm; a peer that does not will fail to validate it. Selecting an SVID signature algorithm that is supported across the Trust Domain is therefore the operator's responsibility at issuance (see [operator provisioning playbook](./identity-lifecycle.md#operator-provisioning-playbook)). ECDSA P-256 with SHA-256 is always a safe choice. |
There was a problem hiding this comment.
"Because a principal presents a single SVID bound to one signature algorithm" is technically imprecise. An SVID has:
- a subject public-key algorithm
- a CA certificate-signature algorithm
A MIAF profile could require the issuing CA to use the same algorithm family and parameters as the principal.
There was a problem hiding this comment.
Agreed, the wording was imprecise and could mislead people reading the spec. I have reworded that paragraph so that it now covers the signature algorithm of each certificate in the chain and the public-key algorithm of the leaf key.
A MIAF profile could require the issuing CA to use the same algorithm family and parameters as the principal.
I'd rather not add this requirement. An enterprise root CA using RSA with leaf certificates using EC is a common enough pattern, so I'd be concerned to over-constrain here. We'll also need mixed chains for post quantum transition. The updated wording puts the responsibility on the operator. So if an operator wants to be on the safe side, they can always choose ECDSA P-256 with SHA-256 throughout the chain.
There was a problem hiding this comment.
Maybe not the complete chain but at least the Issuing CA of the SVID?
There was a problem hiding this comment.
Mh, I'm not sure what that would buy us. Suppose we have an RSA root with an EC intermediate issuing EC leaf certificates. The verifier still needs RSA because the intermediate's certificate is signed with the root's RSA key. The set of algorithms the verifier must implement doesn't shrink. Meanwhile the constraint would tie the issuing CA's key to the leaf's algorithm family. So I'd leave this as operator guidance.
Signed-off-by: Matthias Lechner <[email protected]>
Signed-off-by: Matthias Lechner <[email protected]>
Signed-off-by: Matthias Lechner <[email protected]>
Signed-off-by: Matthias Lechner <[email protected]>
Signed-off-by: Matthias Lechner <[email protected]>
…ing path identifiers Signed-off-by: Matthias Lechner <[email protected]>
…ient-id Signed-off-by: Matthias Lechner <[email protected]>
SPIFFE treats spiffe_sequence as ordering metadata, not an anti-rollback control, and defaults to accepting the most recently retrieved bundle when the field is absent. Rollback is already covered by authenticating every retrieval and by the refresh interval overriding HTTP cache freshness. Signed-off-by: Matthias Lechner <[email protected]>
… risk Signed-off-by: Matthias Lechner <[email protected]>
Signed-off-by: Matthias Lechner <[email protected]>
Signed-off-by: Matthias Lechner <[email protected]>
Signed-off-by: Matthias Lechner <[email protected]>
Signed-off-by: Matthias Lechner <[email protected]>
...until we decide to register with IANA Signed-off-by: Matthias Lechner <[email protected]>
Bootstrap retrieval of the discovery document and Trust Bundle cannot be authenticated with an X.509-SVID at all, rather than merely happening before a client holds one. The MIS presents no SVID, so the service impersonation mitigation now points at initial-trust anchors and pins instead of at SVID verification. Signed-off-by: Matthias Lechner <[email protected]>
and ensure we consistently apply our own terminology Signed-off-by: Matthias Lechner <[email protected]>
Adopt pre-draft's restored versioning policy and the roles-to-capabilities change (#197). Conflict resolutions: - device-requirements.md: took pre-draft's roles-to-capabilities rewrite and re-applied our removal of "onboarding" from the single-WFM sentence. - api-requirements-and-security.md: kept our "API Definition" and "Transport" structure. Pre-draft's "Server-side TLS ... over HTTP1.1" line is superseded by our Transport section, which requires HTTP/1.1 and upgrades TLS to mTLS. - workload-management-api: took pre-draft's 1.0.0-rc.2 name and version, kept our folded description block and our server URL without the trailing slash, and took pre-draft's "Workload Fleet Manager APIs" description. - meta.json: the last pages entry named the OpenAPI file, which the rename made stale; it now names the management-interface-swagger page. mkdocs build --strict introduces no new warnings against the pre-merge tip.
Signed-off-by: Matthias Lechner <[email protected]>
Signed-off-by: Matthias Lechner <[email protected]>
Signed-off-by: Matthias Lechner <[email protected]>
|
|
||
| Terms introduced by MIAF: | ||
|
|
||
| - **Principal**: a non-human Margo component that holds, or is being provisioned with, a SPIFFE identity in a Trust Domain. Edge Compute Devices, WFMs, and WFM Clients are all principals. |
There was a problem hiding this comment.
Similar comment made within technical lexicon, is a Edge Compute Device a Principal? Or is simply the WFM Client?
|
|
||
| #### Support for Extended Device Communications Downtime | ||
| Interface patterns MUST support extended device communication downtime. | ||
| ## Extended Device Downtime |
There was a problem hiding this comment.
I noticed this as a lingering requirement we placed in the specification a long time ago.
With the move to mTLS, does this section need removed or altered to fit the new pattern?
Our TWG feature assigned to supporting intermittently connected devices has not been placed as a GA1 feature that we enable.
| The caller identity for every request is the authenticated WFM Client SPIFFE ID; the request itself does not carry it. A WFM derives the caller from the SPIFFE ID, not from any identifier in the request path or body. | ||
|
|
||
| #### Unique Identifiers | ||
| Every Management Interface endpoint is scoped to the authenticated caller. A WFM determines from the caller's identity which devices that client is responsible for and which deployments are assigned to them. Where a request path carries a resource identifier, for example `{deviceId}` or `{digest}`, the WFM looks that identifier up only among the resources in the caller's scope. A WFM MUST NOT expose or mutate a resource outside the caller's scope. |
There was a problem hiding this comment.
This rule assumes the caller's device scope already exists, but nothing defines how a deviceId becomes bound to a wfm-client-id. Today it appears to be trust-on-first-declaration: the client self-asserts deviceIds via POST /capabilities/{deviceId} and the WFM remembers them. Please specify: is the binding client-asserted or operator-registered? What prevents client X from POSTing capabilities under a deviceId owned by client Y?
I'm still struggling with the wfm-client-id and deviceId and how they are linked.
|
|
||
| For **enrollment**, the operator: | ||
|
|
||
| 1. accepts a CSR from the principal (the preferred path, since it keeps the private key on the principal and supports hardware-bound keys such as a TPM, secure element, or HSM). Where the principal cannot generate its own key pair, the operator generates one centrally and accepts the resulting concentration of key custody; |
There was a problem hiding this comment.
Is this leaving an open requirement for our devices that host the clients to support a hardware-bound key store?
I don't see a new requirement in the device requirements markdown, should there be? I think so.
| | **Cross-domain trust confusion** | A component accepts identities from an unintended Trust Domain. | A verifier MUST determine the Trust Domain from the SPIFFE ID and MUST NOT trust an SVID whose Trust Domain is not the verifier's own. | | ||
| | **Inadvertent inspection-proxy MITM** | An operator-deployed traffic-inspecting proxy intercepts and re-signs Margo mTLS traffic, presenting a substitute certificate to either endpoint. | An operator MUST exempt Margo mTLS endpoints from inspection per [traffic-inspecting proxies](./tls-requirements.md#traffic-inspecting-proxies). Both endpoints MUST validate peer SVIDs against the Trust Bundle and reject a substituted certificate. | | ||
| | **Forwarded-identity header injection** | In a TLS-offload topology, an attacker injects a forged `Client-Cert` header to impersonate an authenticated caller at the backend. | The proxy MUST remove or overwrite any `Client-Cert` or `Client-Cert-Chain` header on incoming requests, and the backend MUST accept a forwarded identity only over the trusted proxy boundary, per [traffic-inspecting proxies](./tls-requirements.md#traffic-inspecting-proxies). | | ||
| | **Unreliable or manipulated verifier clock** | A principal mis-evaluates certificate validity periods because its clock is skewed or unset (a dead RTC battery, no time source at first boot) or because an attacker rewinds it, for example by spoofing an unauthenticated time source on the adversarial network. Rewinding the clock extends the validity window of an expired SVID, defeating the use of expiry as revocation. | SVID validation depends on a trustworthy local time source. A principal SHOULD synchronize time from a trustworthy source before validating certificates, and operators SHOULD account for devices with weak clocks when choosing SVID lifetimes (see [SVID lifetime guidance](./identity-lifecycle.md#svid-lifetime-guidance)). A deployment that cannot assure clock integrity SHOULD NOT rely on expiry alone for revocation. | |
There was a problem hiding this comment.
I'm wondering if this should result in a harder "MUST" requirement regarding time synchronization.
Would be added scope outside of this SUP, however, for critical functions like OTEL we are going to need accurate clocks in this architecture.
thoughts>?
| Every Management Interface endpoint is scoped to the authenticated caller. A WFM determines from the caller's identity which devices that client is responsible for and which deployments are assigned to them. Where a request path carries a resource identifier, for example `{deviceId}` or `{digest}`, the WFM looks that identifier up only among the resources in the caller's scope. A WFM MUST NOT expose or mutate a resource outside the caller's scope. | ||
|
|
||
| The WFM MUST create a URL-safe client ID to uniquely identify each client within the architecture. | ||
| The WFM authorizes each request using local policy keyed on the authenticated WFM Client identity, and MAY deny a request from a still-valid credential, per [Authorization](../identity/wfm-identity-profile.md#authorization). When a WFM denies a request by local policy (for example, a retired client relationship), it SHOULD respond `403 Forbidden` with an [RFC 9457](https://datatracker.ietf.org/doc/html/rfc9457) Problem Details body (`Content-Type: application/problem+json`) using the `wfm-client-relationship-retired` type: |
There was a problem hiding this comment.
Probabaly a task for after this PR gets merged, but Viresh is working on the PR to the spec to include these common Problems and is documenting them as "MUST".
See here
|
|
||
| ## Lifecycle Vocabulary | ||
|
|
||
| A MIAF identity moves through five lifecycle phases: |
There was a problem hiding this comment.
I recommend numbering these for better claroty instead of bullet points.
nit picky I know sorry :)
| For every change in deployment state - including installation, updates, removals, and failures - the client MUST report the corresponding status to the WFM using the [Deployment Status API](../margo-management-interface/deployment-status.md). | ||
|
|
||
| ## Endpoints - State Manifest | ||
| ## Endpoints: State Manifest |
There was a problem hiding this comment.
This is another comment along the lines of decoupling client ID<=>Device 1:1 relationship wording. Maybe the below comment isn't an issue.
The (device) client wording (and "the complete desired workload configuration assigned to the device" / "workloads assigned to the device" above) reads as a leftover from the 1:1 device==client model, but the inconsistency runs deeper than the phrasing:
GET /api/v1/deployments takes no deviceId, and the manifest has no per-device field — a single manifestVersion, one bundle, and a flat deployments[], all scoped to the authenticated client. Capabilities, by contrast, are reported per deviceId (POST /capabilities/{deviceId}, including gateway child devices). So the API is asymmetric: device-addressed inbound, client-addressed outbound.
For a client that fronts many devices (e.g., a gateway with deviceA/deviceB), please clarify how per-device desired state is delivered and versioned:
Is there intentionally one manifest per client covering all its devices? If so, how does a deployment get targeted to a specific deviceId — there's no device field in deployments[] — and is manifestVersion a single per-client sequence spanning all devices?
Or should desired state be per device (a deviceId selector plus per-device manifestVersion), matching the capabilities model?
Description
Integrates the two voted MIAF SUPs into the normative specification:
What changes
PayloadSignaturescheme are removed.{clientId}from every route. Caller identity now comes from the authenticated SPIFFE ID. Retained endpoints gain a403for local-policy denial andCache-Control: private.mutualTLSscheme and nullable typing require.Deliberate deviations from the SUPs
wfm-id, so there is no separate target-identifier config item (which simplifies configuration and operations).spiffe_sequencewith fail-closed on an empty bundle, refresh driven byspiffe_refresh_hint, and RFC 9440 section 4 spoof-proofing for the forwardedClient-Certheader.Issues Addressed
Change Type
Please select the relevant options:
Checklist