CDS HTTP API

Every endpoint the Certificate Distribution Service serves — attestation and certificate issuance, the image allowlist CRUD surface, and the discovery routes — with method, path, authorization, and response codes.

The CDS (Certificate Distribution Service) serves one HTTP API over RA-TLS on port 8443. Every flag that configures it is in the CLI reference.

Attestation and issuance

MethodPathAuthPurpose
POST/authenticatenoneissue a one-time challenge nonce (--challenge-ttl, default 60s)
POST/attestchallenge + evidenceverify evidence (and an optional sandbox token) and sign a CSR, returning the leaf PEM chain
POST/attest-keychallenge + evidenceverify evidence and issue an EAR bound to the caller's key
POST/sign-csrEARsign a CSR for a caller that already holds an EAR bound to the CSR key

Allowlist

MethodPathAuthPurpose
GET/allowlistnonethe whole document as canonical JSON; returns a weak ETag W/"<version>" and honors If-None-Match (304 when unchanged)
PUT/allowlistoperator tokenreplace floor and workloads atomically; the CDS assigns the new version; 204
POST/allowlist/digestsoperator tokenadd one floor entry { digest, image }; 204
DELETE/allowlist/digestsoperator tokendelete { digests: [...] } atomically — all-or-nothing, 404 if any is missing
PUT/allowlist/workloads/<name>operator tokencreate or replace one workload entry, whole; 204
DELETE/allowlist/workloads/<name>operator tokendelete one workload entry; 404 if absent

A missing or invalid operator token is 401; a body the CDS cannot parse or validate is 422. Writes carry their own 1 MiB body cap, independent of the --max-request-size that bounds the attestation endpoints.

Enforcers poll GET /allowlist and use the ETag to avoid redundant work — the version only changes when the set actually changes (nriImagePolicy.refresh.interval, default 5s).

Secrets

MethodPathAuthPurpose
GET/secrets/<path>mesh leaf + sandbox tokenread a released value; 404 when the path is ungranted or absent
POST/secrets/<path>mesh leaf + sandbox tokenmint and store 32 random bytes at an empty path; 409 when another caller won the race
PUT/secrets/<path>operator tokenstore an operator-supplied value; create-only unless the caller asked to overwrite

Denials are deliberately opaque — an ungranted path is indistinguishable from a missing one, so the API cannot enumerate the store. The reason goes to the CDS log. Workload routes are rate-limited per sandbox, keyed on the ID in the verified client certificate.

The CDS declines to serve /secrets at all when --ratls-platform, --measurements, or --sandbox-inventory-cidr is missing. See Application secrets.

Discovery

MethodPathAuthPurpose
GET/measurementsnonethe reference values this CDS enforces, as a measurements config document; always served, and an empty measurements array means any attested measurement is admitted
GET/operator-keysnonethe pinned operator public-key PEM bundle; 404 when allowlist writes are disabled
GET/.well-known/jwks.jsonnonethe EAR-signing JWKS (ES256)
GET/canonethe mesh CA bundle
GET/readyznonereadiness; fails if the attestation-api is unhealthy, or CA validity is below --min-ca-validity

The /measurements document is rendered once at startup from the values CDS resolved, whether they came from --measurements-config or from --measurements / --rtmrs; its tee field follows --ratls-platform. c8s verify --kind cds --measurements-config <file> fetches it over a connection pinned to the attested serving certificate and fails unless the two sets match exactly — see Pin multiple measurements.

Operator tokens

Every allowlist and operator-supplied secret write carries a JWT signed with the operator's ECDSA key (ES256, ES384, or ES512, matching the key's curve), minted fresh per request with a 60-second lifetime. Three claims bind it to that one write:

ClaimBinds
pbhSHA-256 of the exact request body
htmthe HTTP method
htuthe URL path

The CDS accepts a mutation only when the signature verifies against a pinned key, exp − iat is at most five minutes (a server-side cap), the method and path match the request being handled, and the body hash matches a re-hash of the body actually received, compared in constant time. See Authorizing mutations for the trust boundaries of this design, and Manage the allowlist for the CLI that mints them.