Tekton’s SLSA Provenance feature generates build attestations, and the most surprising thing about it is that it doesn’t actually prove anything about your build in the way most people think of proof. Instead, it provides a cryptographically signed record of what happened during a build, allowing downstream systems to verify that the build process was executed as intended, rather than guaranteeing the inherent trustworthiness of the code itself.

Let’s see this in action. Imagine a simple Tekton Pipeline that builds a Go application and then creates an artifact.

apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
  name: slsa-provenance-example
spec:
  tasks:
    - name: build-and-attest
      taskSpec:
        steps:
          - name: build
            image: golang:1.20
            script: |
              echo "Building my-app..."
              go build -o /workspace/my-app ./app
          - name: attest
            image: gcr.io/tekton-releases/github/tekton/chains/cmd/chains-init:v0.23.0 # Example image, use the latest
            script: |
              # This step is handled by the chains-init sidecar,
              # which automatically collects provenance data.
              # We just need to ensure our build artifacts are accessible.
              echo "Provenance data collection initiated by sidecar."
        sidecars:
          - name: chains-initializer
            image: gcr.io/tekton-releases/github/tekton/chains/cmd/chains-init:v0.23.0 # Example image, use the latest
            script: |
              # The sidecar automatically sets up the necessary environment for provenance generation.
              echo "Chains initializer sidecar is running."
        workspaces:
          - name: shared-workspace
            emptyDir: {}
      workspaces:
        - name: shared-workspace
          workspace: shared-workspace

When this pipeline runs, the chains-initializer sidecar, which is part of the Tekton Chains project, intercepts the build process. It observes the commands executed in the build step, the input source code (if mounted), the output artifacts, and the environment variables. This information is then compiled into a Statement, formatted according to the in-toto specification, which describes the build process. This Statement is then signed by a private key managed by Tekton Chains, and the resulting signed attestation is stored, often as an annotation on the resulting Kubernetes object (like a TaskRun or PipelineRun).

The core problem Tekton SLSA Provenance solves is the "supply chain attack" scenario. If an attacker compromises your build system, they could inject malicious code into your application. Without provenance, you have no way to detect this. With provenance, you have a verifiable record of what actually went into the build. You can then compare this record against your expectations or against a known-good build.

Internally, Tekton Chains uses a combination of interceptors and a signing service. The chains-initializer sidecar acts as an interceptor, collecting the build data. This data is then passed to the Tekton Chains controller, which forwards it to a configured signing service (e.g., KMS, HashiCorp Vault, or a simple in-cluster secret). The signing service uses a private key to sign the Statement, producing the attestation. This attestation is then attached as an annotation to the Kubernetes resource representing the build execution.

The exact levers you control are primarily through the Tekton Chains configuration. You define the signing backend, the key to use for signing, and where to store the attestations. For example, in your TektonConfig custom resource, you might specify:

apiVersion: tekton.dev/v1alpha1
kind: TektonConfig
metadata:
  name: tekton-config
spec:
  pipeline:
    # ... other pipeline configurations
    tektonChains:
      enabled: true
      # For example, using KMS:
      signing:
        publicKey: "..." # Public key for verification
        privateKeySecret:
          name: "kms-key-secret" # Kubernetes secret containing KMS key info
          namespace: "tekton-chains"
      storage:
        type: "annotations" # Or "cosign"

The storage.type is particularly interesting. While annotations is convenient for quick inspection, using cosign as the storage type integrates with the Cosign tool for more robust artifact signing and verification, often pushing attestations to an OCI registry alongside the built artifact. This is crucial for distributed systems and CI/CD workflows where artifacts need to be shared and verified across different environments.

What most people don’t realize is that the provenance data itself is just a structured log. The trust comes from the cryptographic signature, and that signature is only as strong as the security of the private key used for signing and the integrity of the signing process. If the signing key is compromised, or if the build process itself is compromised before the provenance data is collected or signed, the attestation becomes a misleading record of a malicious event. Therefore, securing your signing keys and ensuring the integrity of the Tekton Chains components are paramount.

The next step after generating attestations is setting up a robust verification pipeline to consume and act upon these signed statements.

Want structured learning?

Take the full Tekton course →