Skip to content

Commit b664704

Browse files
Add blog post: Keyless Security with Tekton Chains
Adds a polished blog post explaining keyless signing with Tekton Chains, including how the Fulcio/Rekor OIDC flow works inside Tekton, configuration, verification, and a mermaid architecture diagram of the signing flow.
1 parent 93d2ef3 commit b664704

1 file changed

Lines changed: 153 additions & 0 deletions

File tree

  • content/en/blog/2026/keyless-security-with-tekton-chains
Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
---
2+
title: "Keyless Security with Tekton Chains"
3+
linkTitle: "Keyless Security with Chains"
4+
date: 2026-06-03
5+
author: "Anitha Natarajan, Red Hat"
6+
description: >
7+
How keyless signing with Tekton Chains lets you sign everything your pipelines
8+
build without ever managing a signing key.
9+
---
10+
11+
Software supply chain attacks have moved from theoretical to routine. Typosquatted packages, compromised distribution sites, and post-publish tampering are now standard entries in any threat model. The defensive answer is old and well understood: sign your artifacts cryptographically so consumers can trace them back to a known source and confirm nothing changed after the build. The hard part was never the signing. It was the keys.
12+
13+
Traditional signing hands you a long-lived private key and a list of problems: where do you store it, how do you rotate it, who gets access, and what happens when it leaks? In an automated CI/CD pipeline that runs hundreds of builds a day, a key sitting in a secret store is both an operational burden and an attractive target.
14+
15+
[Sigstore](https://www.sigstore.dev/) reframes the problem around *identity* instead of *keys*, and [Tekton Chains](https://tekton.dev/docs/chains/) brings that model directly into your pipelines. This post walks through what keyless signing with Tekton Chains actually looks like in practice today: how it works, how to turn it on, and where the edges still are.
16+
17+
## What Tekton Chains is
18+
19+
Tekton Chains is a Kubernetes controller that observes `TaskRun` and `PipelineRun` resources in your cluster. When a run completes, Chains automatically captures what was built, generates signed provenance describing how it was built, signs the result, and optionally records the signing event in a transparency log. You don't add signing steps to your pipelines — Chains watches from the side and reacts to completed runs.
20+
21+
It can sign three kinds of subjects: OCI images, `TaskRuns`, and `PipelineRuns`. Provenance is emitted as [in-toto attestations](https://in-toto.io/), which describe the inputs, steps, and outputs of a build in a structured, verifiable format useful for auditing and for satisfying [SLSA](https://slsa.dev/)-style policy requirements.
22+
23+
## The keyless idea in one paragraph
24+
25+
Instead of holding a signing key, a Sigstore client generates a throwaway key pair for a single signing operation. It presents an OIDC identity token to [Fulcio](https://docs.sigstore.dev/certificate_authority/overview/), Sigstore's free certificate authority. Fulcio verifies the token and issues a short-lived certificate that binds the freshly generated public key to the identity in the token. The client signs the artifact, the signing event is recorded in [Rekor](https://docs.sigstore.dev/logging/overview/) (the transparency log), and the private key is discarded immediately. There is no key to store, rotate, or leak. Verification later relies on the certificate, the recorded identity, and the transparency log entry rather than on a key you have to distribute.
26+
27+
The crucial insight for CI is that the identity in the OIDC token doesn't have to be a human. It can be a workload. That's exactly what Tekton Chains exploits.
28+
29+
## How keyless works inside Tekton Chains
30+
31+
In keyless mode, Chains does not look for a signing secret. Instead it requests an identity token from the cluster it is running in, then uses that token to obtain a Fulcio certificate for the artifact being signed. This is the same OIDC signing flow [Cosign](https://docs.sigstore.dev/cosign/overview/) uses, but the token comes from the cluster's service account machinery rather than a browser login.
32+
33+
The mechanism that makes this work on managed Kubernetes is the cluster's OIDC provider combined with [projected service account tokens](https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/#service-account-token-volume-projection). The cluster issues a short-lived, audience-scoped token representing the workload's service account identity, and Fulcio accepts that token as proof of identity. This has been tested on GKE, EKS, and AKS, and should work on any environment that supports Cosign OIDC signing.
34+
35+
The full flow looks like this:
36+
37+
```mermaid
38+
flowchart TD
39+
A["PipelineRun / TaskRun completes"] --> B["Tekton Chains controller<br/>detects completed run"]
40+
B --> C["Generate provenance<br/>(in-toto attestation)"]
41+
C --> D["Request projected<br/>service account token<br/>from cluster OIDC provider"]
42+
D --> E["Present OIDC token to Fulcio"]
43+
E --> F["Fulcio verifies identity<br/>and issues short-lived certificate"]
44+
F --> G["Sign artifact with<br/>ephemeral key pair"]
45+
G --> I["Discard ephemeral private key"]
46+
G --> J["Write results back as annotations<br/>on the TaskRun / PipelineRun"]
47+
G -. if transparency logging is on .-> H["Record signing event in<br/>Rekor transparency log"]
48+
G -. if OCI storage is configured .-> K["Push signature and provenance<br/>to OCI registry"]
49+
50+
style A fill:#e8f0fe,stroke:#4285f4,color:#000
51+
style B fill:#e8f0fe,stroke:#4285f4,color:#000
52+
style F fill:#fce8e6,stroke:#ea4335,color:#000
53+
style H fill:#e6f4ea,stroke:#34a853,color:#000
54+
style I fill:#fef7e0,stroke:#fbbc04,color:#000
55+
```
56+
57+
Once Chains successfully gets a certificate and signs, it writes the results back as base64-encoded annotations on the `TaskRun` or `PipelineRun` — the certificate, the payload, the signature, a `chains.tekton.dev/signed: true` marker, and, if transparency logging is on, a `chains.tekton.dev/transparency` URL pointing at the Rekor entry.
58+
59+
## Turning it on
60+
61+
Enabling keyless mode is a one-line change to the Chains config map. You switch on the Fulcio signer:
62+
63+
```shell
64+
kubectl patch configmap chains-config -n tekton-chains \
65+
-p='{"data":{"signers.x509.fulcio.enabled": "true"}}'
66+
```
67+
68+
A fuller configuration that signs in-toto provenance, stores signatures in your OCI registry, and records events in the public Rekor instance looks like this:
69+
70+
```yaml
71+
apiVersion: v1
72+
kind: ConfigMap
73+
metadata:
74+
name: chains-config
75+
namespace: tekton-chains
76+
data:
77+
# What to sign and how to format it
78+
artifacts.taskrun.format: "in-toto"
79+
artifacts.taskrun.storage: "oci"
80+
artifacts.taskrun.signer: "x509"
81+
82+
# Sign PipelineRuns too — provenance pushed to the OCI registry
83+
artifacts.pipelinerun.format: "in-toto"
84+
artifacts.pipelinerun.storage: "oci"
85+
artifacts.pipelinerun.signer: "x509"
86+
87+
# OCI image signature storage
88+
artifacts.oci.storage: "oci"
89+
artifacts.oci.format: "simplesigning"
90+
artifacts.oci.signer: "x509"
91+
92+
# Transparency log
93+
transparency.enabled: "true"
94+
transparency.url: "https://rekor.sigstore.dev"
95+
96+
# Keyless: use Fulcio instead of a stored key
97+
signers.x509.fulcio.enabled: "true"
98+
signers.x509.fulcio.address: "https://fulcio.sigstore.dev"
99+
signers.x509.fulcio.issuer: "https://oauth2.sigstore.dev/auth"
100+
```
101+
102+
One thing this example leaves implicit: with `storage: "oci"` and no `storage.oci.repository` set, Chains stores the attestations alongside the built image — which only works if your run actually builds an image and emits `IMAGE_URL` / `IMAGE_DIGEST` type-hinting results. If it doesn't produce an image, set `storage.oci.repository` to a repository explicitly, or store provenance in the `tekton` annotation backend instead.
103+
104+
Transparency logging is its own toggle, defaulting to the public Rekor instance, and you can point it at a private Rekor if you run one:
105+
106+
```shell
107+
kubectl patch configmap chains-config -n tekton-chains \
108+
-p='{"data":{"transparency.enabled": "true"}}'
109+
110+
kubectl patch configmap chains-config -n tekton-chains \
111+
-p='{"data":{"transparency.url": "<YOUR URL>"}}'
112+
```
113+
114+
Note that signatures and provenance still need to be pushed somewhere. Chains looks for OCI registry credentials in the pod running your task and in the service account configured for it, so you'll typically create a `dockerconfigjson` secret and attach it to that service account.
115+
116+
## Verifying what you signed
117+
118+
A signature you never check is theater. Because keyless signing records every event in Rekor, verification doesn't depend on you having a key — it depends on matching the recorded identity and confirming inclusion in the log.
119+
120+
The transparency annotation on each run holds the Rekor entry URL, and you can explore entries through Rekor's API or a web UI. The Chainguard team runs a public [Rekor Search UI](https://rekor.tlog.dev/), where you can look up entries by log index, email, hash, commit SHA, or UUID. That searchability is the practical payoff of the model: an identity owner can monitor the log to confirm their identity is only being used for signing events they expect, and a consumer can confirm a certificate was valid at signing time.
121+
122+
## The full menu of signing options today
123+
124+
Keyless is one mode among several, and it's worth seeing it in context. Operationally you choose one of the following:
125+
126+
- **Keyless / Fulcio** — no stored key; identity comes from the cluster's OIDC token. The focus of this post.
127+
- **x509** — an unencrypted PKCS8 PEM private key (`ed25519` or `ecdsa`) stored in a `signing-secrets` Kubernetes secret.
128+
- **Cosign keypair** — an encrypted Cosign-generated key (`cosign.key` plus `cosign.password`) in the same secret, created via `cosign generate-key-pair k8s://tekton-chains/signing-secrets`.
129+
- **KMS** — a key held in a cloud KMS, referenced with a go-cloud-style URI. GCP KMS and HashiCorp Vault are supported today, with AWS and Azure URI schemes also available.
130+
131+
One subtlety the menu hides: the `signer` field in the config only ever takes two values per artifact type — `x509` or `kms`. The first three options above are all the `x509` signer; Chains tells keyless, a raw x509 key, and a Cosign keypair apart by whether `signers.x509.fulcio.enabled` is set and which keys exist in the `signing-secrets` secret, not by a separate top-level setting. (That's also why there's no `cosign` signer value — a Cosign keypair is just the `x509` signer reading `cosign.key`.)
132+
133+
The progression here is roughly "least key management" to "most control over the key." Keyless removes key management entirely; KMS keeps the key in cloud infrastructure you control. Many teams run keyless for public, auditable artifacts and reserve KMS for cases with regulatory or air-gap constraints.
134+
135+
## What's possible right now — and the caveats
136+
137+
What works today is a complete, hands-off loop: every `TaskRun` and `PipelineRun` in the cluster gets signed provenance and a signature, bound to a workload identity, with no key to manage, and a public audit trail in Rekor — all from flipping a config flag on managed Kubernetes.
138+
139+
A few realities to plan around:
140+
141+
- **OIDC token format matters.** Recent Chains releases ship Cosign v2.6.0 or later, which no longer accepts HS256-signed JWTs. Public Sigstore (Fulcio), key-based signing, and private OIDC providers using RS256 are unaffected, but if you run a private OIDC provider on HS256 you must switch to RS256 before upgrading. This is the kind of detail that silently breaks a pipeline, so check it before you bump versions.
142+
- **Cluster OIDC is a prerequisite.** Keyless mode depends on your cluster being able to issue projected service account tokens that Fulcio trusts. On EKS, for example, that means creating the cluster with OIDC enabled (`eksctl create cluster --with-oidc ...`). On a cluster without a usable OIDC provider, keyless won't work and you'll fall back to a key-based mode.
143+
- **"Keyless" is a convenience, not the literal absence of keys.** Fulcio still operates a root of trust on behalf of the whole community, protected by a distributed key ceremony and [The Update Framework](https://theupdateframework.io/). The point isn't that keys vanish — it's that *you* no longer manage signing keys.
144+
- **Public vs. private infrastructure is a real choice.** Signing against the public Fulcio and Rekor means your identities and signing metadata land in public logs. For internal-only artifacts that may be undesirable, and you can self-host Fulcio and Rekor to run an entirely private signing ecosystem. Machine-identity approaches based on [SPIFFE/SVID](https://spiffe.io/) fit naturally here, though running your own stack is meaningfully more work than flipping a flag.
145+
- **Verification is on you.** Chains makes signing automatic; it does not make anyone check the signatures. You'll want a policy gate — Sigstore's [Policy Controller](https://docs.sigstore.dev/policy-controller/overview/) is the common companion — to actually enforce that only properly signed, properly attested artifacts get admitted or deployed.
146+
147+
## Where this fits
148+
149+
Keyless signing with Tekton Chains is one of the cleaner answers available today to "how do I sign everything my pipeline produces without drowning in key management?" The setup cost is low, the audit story is strong, and the model composes well with the broader supply chain security ecosystem — in-toto for provenance, SLSA as the policy framework it feeds, and Policy Controller for enforcement.
150+
151+
The honest framing is that signing is necessary but not sufficient. Tekton Chains gets you reliable, low-friction, auditable signatures bound to workload identities. Turning those signatures into actual protection means closing the loop with verification and policy. The good news is that every piece you need to do that exists and is open source today.
152+
153+
To go deeper, see the [Tekton Chains documentation](https://tekton.dev/docs/chains/) and the [Sigstore project documentation](https://docs.sigstore.dev/).

0 commit comments

Comments
 (0)