Zion Boggan
repos/cicd-supply-chain-security/docs/supply-chain.md
zionboggan.com ↗
47 lines · markdown
History for this file →
1
# Supply chain notes
2
 
3
## The threat model
4
 
5
The attacks this defends against are the ones where the source code is fine but the
6
artifact isn't:
7
 
8
- a registry account is compromised and a tag is repointed at a malicious image
9
- a build runner is tampered with and produces a backdoored image
10
- a dependency pulled at build time has a known CVE that nobody looked at
11
- an image is deployed that nobody can actually account for the contents of
12
 
13
Source-level scanning (the other repo) does nothing for any of these. They all
14
happen at or after build time, which is why this is a separate layer.
15
 
16
## How Sigstore answers each one
17
 
18
- **Repointed tag** - the Kyverno policy resolves tags to digests on admission and
19
  requires a signature over that digest. Moving a tag doesn't move the signature.
20
- **Tampered runner** - the signature is tied to the OIDC identity of the workflow
21
  run. An image built somewhere else can't produce a signature from
22
  `https://github.com/zionboggan/...`.
23
- **Vulnerable dependency** - grype scans the built image and fails the build on a
24
  high or critical finding before signing happens, so unsigned-and-vulnerable never
25
  even gets to the registry as a release.
26
- **Unaccountable contents** - the SBOM is generated from the actual image, signed
27
  as an attestation, and required at admission. No SBOM, no deploy.
28
 
29
## Transparency log
30
 
31
Every signature and attestation is recorded in Rekor. That gives an auditable,
32
append-only record of what was signed, by which identity, and when. If a signing
33
identity is ever misused, the log is where you'd find every artifact it touched.
34
 
35
## Why digests everywhere
36
 
37
Tags are mutable; digests are not. Signing a tag is signing a pointer. Every step
38
here - build output, scan target, sign, attest, verify, and the admission rewrite -
39
operates on `@sha256:...`. The image that runs in the cluster is byte-for-byte the
40
image that was signed.
41
 
42
## Rotating to keys
43
 
44
Keyless suits CI because there's no secret to hold. For an offline or air-gapped
45
verifier where you can't reach Fulcio/Rekor at verify time, generate a key pair
46
(`cosign generate-key-pair`) or back it with a KMS, sign with `--key`, and verify
47
with the public key. The pipeline structure is identical; only the attestor changes.