-
Notifications
You must be signed in to change notification settings - Fork 0
GHCR Cosign Kubernetes E2E
CYPT71 edited this page Aug 21, 2026
·
2 revisions
The executable demonstration is
ci-supply-chain-e2e.yml.
It runs on main and manually, and uploads
ghcr-cosign-admission-evidence for 30 days.
flowchart LR
A[Reviewed GitHub SHA] --> B[Deterministic OCI layout]
B --> C[Independent verification]
C --> D[GHCR immutable digest]
D --> E[GitHub OIDC]
E --> F[Cosign keyless signature]
F --> G[Sigstore policy-controller]
G --> H[Signed digest admitted]
G --> I[Unsigned tag denied]
- GitHub builds the example service and layout.
- The independent verifier checks every descriptor and layer.
- Docker's consumer stage produces a runnable image and pushes an ephemeral commit tag to `ghcr.io/cypt71/platform-factory.
- The workflow records the registry digest and never signs the mutable tag.
- Cosign obtains a short-lived Fulcio certificate from GitHub's OIDC token, signs the digest, and verifies issuer plus workflow identity.
- A disposable Kind cluster installs Sigstore policy-controller.
-
ClusterImagePolicytrusts only this repository's E2E workflow identity. - Kubernetes admits the signed digest and rejects the unsigned tag.
| File | Meaning |
|---|---|
image-reference.txt |
exact ghcr.io/...@sha256:... admitted |
e2e-layout-validation.txt |
producer-independent OCI checks passed |
e2e-cosign-verification.json |
certificate, issuer, identity, signature |
cluster-image-policy.yaml |
requested trust policy |
installed-policy.yaml |
policy observed from the API server |
admitted-pod.yaml |
signed digest passed admission |
unsigned-rejection.txt |
same repository via unsigned tag was denied |
kubernetes-version.yaml |
test environment identity |
A green workflow without these files is not sufficient; artifact upload uses
if: always() so failed runs preserve diagnostic evidence.
Do not copy the demo's ephemeral tag strategy. Production should:
- publish only from a protected environment after required reviews;
- deploy semantic-release digests, never tags;
- narrow the subject to the release workflow and protected ref;
- pin and review the admission-controller chart in an internal mirror;
- set webhook failure policy to
Fail, monitor webhook availability, and define a documented emergency process that never silently disables policy; - enforce the policy in every production namespace and prevent tenants from modifying namespace labels, policies, or webhook configuration;
- retain signature, SBOM, provenance, layout checksum, and deployment evidence for the required audit period.
Example production identity:
identities:
- issuer: https://token.actions.githubusercontent.com
subjectRegExp: "^https://github.com/CYPT71/platform-factory/.github/workflows/ci-release.yml@refs/tags/v[0-9]+\\.[0-9]+\\.[0-9]+$"- Push failure: check Actions package permissions and GHCR visibility.
- Cosign identity failure: compare the certificate subject with the exact workflow/ref; do not broaden the regex merely to make it pass.
- Webhook timeout: treat as an admission-service outage.
- Signed image denied: inspect
ClusterImagePolicystatus and controller logs, then re-runcosign verifyagainst the same digest. - Unsigned image admitted: critical policy bypass; stop deployment and verify namespace selection, failure policy, RBAC, and webhook configuration.
© 2026 CYPT71
platform-factory
Core
- Architecture and OCI Layout
- Next-generation Architecture
- Architecture Decision Records
- Security Model
- Threat Model and Residual Risks
- Independent Security Review Process
- CLI Reference
- Project Configuration and Dependency Freezing
- mTLS Configuration
- Meine Graal
CI/CD
Running an image
- Production Adoption Guide
- Dockerfile Consumer
- Local Dev (Podman/macOS)
- MicroVM Support
- MicroVM Administration
- Large-image streaming
Operating