Tekton Chains is a system designed to provide cryptographic attestations about the build process within a Kubernetes environment, ensuring software supply chain security and SLSA provenance.

Let’s see it in action. Imagine you’ve just completed a build using Tekton. Without Tekton Chains, all you have is the resulting container image. You trust that the build process was secure, but you have no verifiable proof.

Here’s a simplified Tekton Pipeline definition:

apiVersion: tekton.dev/v1beta1
kind: Pipeline
metadata:
  name: my-secure-pipeline
spec:
  tasks:
    - name: build-and-push
      taskSpec:
        steps:
          - name: build
            image: gcr.io/cloud-builders/docker
            script: |
              docker build -t my-registry/my-app:v1.0.0 .
              docker push my-registry/my-app:v1.0.0

When this pipeline runs, it produces my-registry/my-app:v1.0.0. But how do you know it was really built by this pipeline, and not by an attacker who just pushed a malicious image with the same tag?

Tekton Chains bridges this gap. It integrates with Tekton to automatically generate and sign attestations (provenance data) for each build. These attestations are essentially cryptographic receipts, detailing what was built, how it was built, and by whom.

The core components are:

  • Tekton Controller: Orchestrates the pipeline execution.
  • Tekton Chains Controller: Runs as a separate deployment in your cluster. It watches for Tekton PipelineRun and TaskRun resources.
  • Key Management System (KMS): Tekton Chains relies on a KMS (like Google Cloud KMS, AWS KMS, or HashiCorp Vault) to securely store and manage the signing keys.
  • Policy Enforcement: Tools like OPA Gatekeeper or Kyverno can then consume these attestations to enforce security policies, ensuring only verified builds are deployed.

When a PipelineRun completes, the Tekton Chains controller intercepts this event. It collects relevant information: the image digest, the Git commit SHA (if applicable), the pipeline name, the PipelineRun UID, and other metadata. This data is then used to generate a Statement (following the in-toto format) that describes the build.

This Statement is then cryptographically signed using a private key managed by your KMS. The signature, along with the Statement itself, is stored. Commonly, this provenance data is uploaded to a public transparency log (like Rekor for Sigstore) or an artifact registry that supports provenance.

Here’s a snippet of what a generated SLSA Level 1 provenance statement (in JSON format, simplified) might look like after a Tekton Chains-enabled build:

{
  "_type": "https://in-toto.io/Statement/v1",
  "predicateType": "https://slsa.dev/provenance/v1",
  "subject": [
    {
      "name": "my-registry/my-app",
      "digest": {
        "sha256": "a1b2c3d4e5f6..."
      }
    }
  ],
  "predicate": {
    "builder": {
      "id": "https://tekton.dev/chains/v0.18.0"
    },
    "buildType": "https://tekton.dev/pipelines/v1",
    "invocation": {
      "parameters": {},
      "builder": {
        "id": "https://tekton.dev/chains/v0.18.0"
      }
    },
    "buildConfig": {
      "where": {
        "git": {
          "commit": "abcdef1234567890abcdef1234567890abcdef12"
        }
      }
    },
    "metadata": {
      "completionTime": "2023-10-27T10:00:00Z",
      "eventIds": [
        "pipeline-run-uid-12345"
      ]
    }
  }
}

The crucial part here is the signature associated with this statement. This signature proves that the statement was indeed generated by the entity holding the private key, which should be your trusted build system.

The most surprising true thing about Tekton Chains is that it doesn’t prevent malicious builds from happening; it makes them detectable. The security isn’t in stopping the bad actor at the build stage, but in creating an immutable, cryptographically verifiable record that allows you to say "this artifact did not originate from my trusted build process."

To configure Tekton Chains, you typically install it via Helm and provide it with the necessary KMS details. For example, when installing with Helm, you might pass values like:

helm install tekton-chains tekton-chains/tekton-chains \
  --namespace tekton-chains \
  --create-namespace \
  --set fullnameOverride=tekton-chains \
  --set-string config.chains.payloads.type="in-toto" \
  --set-string config.chains.db.type="postgres" \
  --set-string config.chains.db.url="postgres://user:password@host:port/dbname" \
  --set-string config.chains.key.type="kms" \
  --set-string config.chains.key.controller="https://your-kms-controller.example.com/sign" \
  --set-string config.chains.key.url="projects/my-gcp-project/locations/global/keyRings/my-keyring/cryptoKeys/my-signing-key/versions/1"

The key.url would point to your specific signing key in the KMS. The controller is the endpoint Tekton Chains uses to request signatures from the KMS. The payloads.type="in-toto" specifies the format of the attestation.

Once configured, Tekton Chains automatically starts generating provenance for your Tekton PipelineRuns. You can then query this provenance data, for example, from the transparency log or your artifact registry, to verify the integrity of your deployed software.

The next conceptual hurdle you’ll encounter is how to automatically enforce these attestations in your deployment pipeline, leading into the realm of policy-as-code and admission controllers.

Want structured learning?

Take the full Tekton course →