Overview
Withsupplychain.signatureDiscovery.enabled, the supplychain component
checks every running image digest for cosign signatures and Sigstore
attestations, verifies them with sigstore-go and posts one result per
digest. The broker stores the latest result for each digest and serves it.
It never verifies anything itself, and nothing here blocks a workload.
How discovery works and what each verdict means is in
supplychain/README.md (“Signature discovery”). In short:
verified means valid, not trusted: any Fulcio identity or configured key
can produce a valid signature, and anyone who can push to the repository
can attach one. Never show it without the signer.
Reads (read token)
GET /images/{digest}/attestation
The stored result for one digest, or 404.
signedViaisindexwhen the signature was found on the multi-arch index that lists the digest rather than on the digest itself;signedDigestis then the index.- A key signature has
signerKind: "key",keyNameandkeyFingerprint(sha256 of the DER public key) instead ofissuerandsan. A key-signed bundle also carrieskeyHint, verified or not. - An unverified signature or attestation has
erroranddetailand no identity: a claimed signer is never shown as a fact. Unverified attestations carry noprovenanceeither. - Each attestation has
predicateType,payloadSha256(sha256 of the in-toto statement) and, for SLSA provenance,provenance.builderId,sourceRepo,sourceCommit,sourceRef.
GET /attestations
A keyset page of summaries, ordered by digest.
Each item has
digest, repository, verdict, reason, signedVia,
checkedAt, up to 8 distinct verified signers ({kind: "keyless", issuer, san} or {kind: "key", keyName, keyFingerprint}) and up to 16
verifiedPredicates. In the summary, the repository, issuers, SANs and
predicate types are cut to 256 bytes (never inside a character); the full
values are in the single-digest read.
GET /attestations/running
The evaluator’s ImageTrustPolicy feed:
every running workload container (namespace, workloadKind,
workloadName, container, digest, imageRef, repository) with its
image’s verdict, reason, verified signers and verified
attestations. verdict is null when the digest has no result yet (not
checked, which is not the same as unsigned). ?namespace=, limit 1-200
(default 100), and an opaque after cursor from nextAfter.
GET /attestations/policy
An admission policy generated from the verified signers of running images,
as YAML. See ImageTrustPolicy.
At most 5000 running containers are read; beyond that the answer is
422
and asks for namespace. A generation is charged at its worst case, which
takes the whole read budget: other reads wait (up to
broker.readAcquireWaitMs) or get 503 while it runs.
GET /image-trust
The evaluator’s ImageTrustPolicy results,
read from the evaluator (EVALUATOR_URL) with the broker’s own read token
and bounded. One entry per (policy, running container):
- Results are ordered
WouldDeny,Unknown,Trusted. The counts cover every matching result;truncatedis true whenlimitcut the list. available: falsewith areasonwhen there is nothing to report: no evaluator configured, image trust evaluation off in it (it answers404), it refused the broker’s read token, it could not be reached, or its answer was larger than 16 MiB (filter by namespace). This is unknown, never “nothing would be denied”.evaluatedAtisnulluntil the evaluator has finished a pass.
503
with Retry-After rather than a partial result.
Ingest (supplychain token)
- Scoped auth only, like the vulnerability ingest: a token with the
supplychainscope,403otherwise (also with broker auth off). - Plain JSON (no
Content-Encoding), at most 256 KiB, received within 30 s. At most 32 signatures and 64 attestations (413); long strings are truncated. 422for an unknownschema_version,verdictorsigner_kind, a body digest that differs from the path, a control character, U+2028/U+2029 or a bidi/format control (U+200E/F, U+202A-E, U+2066-9, U+FEFF) in any string, or a malformed reason code (the message names the field),checked_atmore than 60 s ahead, a verdict that does not match the signatures (verifiedwith none verified,unsignedwith signatures, …), or a verified signer’s identity or provenance longer than the limits: those are stored whole or refused, never truncated, because trust policies match them.- A well-formed reason code this broker does not know (a newer
supplychain) is stored as
unrecognised_reason, logged once per code and counted inkguardian_attestation_unrecognised_reason_total; it never changes the verdict. Unknown verdicts and signer kinds are still422. - The digest must be in the image inventory (
404otherwise). - A result replaces the stored one only with a strictly newer
checked_at. The same result again answers200; a different result with an equal or olderchecked_atanswers409. New results answer201.
Retention
An hourly pass deletes results whose digest has left the image inventory (no workload has run it for thebroker.imageInventory retention window),
and results not re-checked for
broker.supplychain.retention.attestationDays (default 7; 0 keeps them):
the component re-checks every running digest at least daily, so an older
result means it stopped.