Getting Started
This guide helps new users quickly set up Tekton Chains to secure their CI/CD pipelines by generating and verifying cryptographic signatures for Tekton TaskRuns.
TOC
Introduction
Use Cases
Tekton Chains helps you secure your software supply chain by automatically generating cryptographic signatures for your build artifacts. This guide demonstrates how to set up Tekton Chains, generate a signing key, run a simple task, and verify its signature.
Estimated Reading Time
10-15 minutes
Important Notes
- Tekton Chains is installed by default in the
tekton-pipelines
namespace when using Alauda Devops Pipelines Operator
- The signing keys should be securely managed; in production environments, consider using a key management system (KMS)
- This guide uses the simplest configuration for demonstration purposes
Prerequisites
- A Kubernetes cluster with Tekton Pipelines and Tekton Chains installed
kubectl
CLI installed and configured to access your cluster
cosign
CLI tool installed
jq
CLI tool installed
Process Overview
Step | Operation | Description |
---|
1 | Generate signing keys | Create a key pair for signing artifacts |
2 | Configure Tekton Chains | Set up Chains to use the Tekton storage backend |
3 | Run a sample task | Create and run a simple TaskRun |
4 | Verify the signature | Extract and verify the signature of the TaskRun |
Step-by-Step Instructions
Step 1: Generate Signing Keys
For more details, please refer to Signing Key Configuration
Tekton Chains uses cryptographic keys to sign artifacts. By default, it looks for a secret named signing-secrets
in the Chains namespace.
-
Install cosign if you haven't already
-
Generate a key pair and store it as a Kubernetes secret:
$ COSIGN_PASSWORD={password} cosign generate-key-pair k8s://tekton-pipelines/signing-secrets
Successfully created secret signing-secrets in namespace tekton-pipelines
Public key written to cosign.pub
TIP
This password will be stored in a Kubernetes secret named signing-secrets
in the tekton-pipelines
namespace.
-
Verify the secret was created:
$ kubectl get secret signing-secrets -n tekton-pipelines
NAME TYPE DATA AGE
signing-secrets Opaque 3 3m
Step 2: Configure Tekton Chains
Configure Tekton Chains to store artifacts in Tekton format by applying the following configuration:
$ kubectl patch tektonconfigs.operator.tekton.dev config --type=merge -p='{
"spec": {
"chain": {
"artifacts.oci.storage": "",
"artifacts.taskrun.format": "in-toto",
"artifacts.taskrun.storage": "tekton"
}
}
}'
Explanation of YAML fields:
artifacts.oci.storage
: The storage type for OCI artifacts. Set to an empty string to skip store.
artifacts.taskrun.format
: The format of the taskrun artifact. Set to in-toto
to use in-toto format.
artifacts.taskrun.storage
: The storage type for taskrun artifacts. Set to tekton
to store in Tekton TaskRun annotations.
Step 3: Run a Sample Task
Now let's create a simple TaskRun that Chains will automatically sign.
-
Create a simple TaskRun:
$ export NAMESPACE=default
$ cat <<'EOF' | kubectl create -n $NAMESPACE -f -
apiVersion: tekton.dev/v1
kind: TaskRun
metadata:
name: build-push-run-output-image-test
spec:
serviceAccountName: ""
taskSpec:
results:
- name: IMAGE_URL
type: string
- name: IMAGE_DIGEST
type: string
steps:
- name: create-image
image: <registry>/ops/busybox:latest
script: |-
#!/bin/sh
echo 'gcr.io/foo/bar' | tee $(results.IMAGE_URL.path)
echo 'sha256:05f95b26ed10668b7183c1e2da98610e91372fa9f510046d4ce5812addad86b5' | tee $(results.IMAGE_DIGEST.path)
EOF
TIP
Please replace the image <registry>/ops/busybox:latest
with the actual image you want to use.
-
Wait for the TaskRun to complete:
$ kubectl get taskruns.tekton.dev -n $NAMESPACE -w
NAME SUCCEEDED REASON STARTTIME COMPLETIONTIME
build-push-run-output-image-test True Succeeded 42s 33s
Wait until the status shows Succeeded
.
Step 4: Verify the Signature
Once the TaskRun completes, Tekton Chains will automatically sign it. Let's verify the signature.
-
Get the TaskRun UID:
export TASKRUN_UID=$(kubectl get taskruns.tekton.dev -n $NAMESPACE build-push-run-output-image-test -o jsonpath='{.metadata.uid}')
-
Extract the signature:
kubectl get taskruns.tekton.dev -n $NAMESPACE -o jsonpath="{.items[0].metadata.annotations.chains\.tekton\.dev/signature-taskrun-$TASKRUN_UID}" | base64 -d > sig
-
Extract the payload using jq:
cat sig | jq '.payload | @base64d' | jq -r '.' | jq '.'
Signature Payload
{
"_type": "https://in-toto.io/Statement/v0.1",
"subject": [
{
"name": "gcr.io/foo/bar",
"digest": {
"sha256": "05f95b26ed10668b7183c1e2da98610e91372fa9f510046d4ce5812addad86b5"
}
}
],
"predicateType": "https://slsa.dev/provenance/v0.2",
"predicate": {
"buildConfig": {
"steps": [
{
"annotations": null,
"arguments": null,
"entryPoint": "#!/bin/sh\necho 'gcr.io/foo/bar' | tee /tekton/results/IMAGE_URL\necho 'sha256:05f95b26ed10668b7183c1e2da98610e91372fa9f510046d4ce5812addad86b5' | tee /tekton/results/IMAGE_DIGEST",
"environment": {
"container": "create-image",
"image": "oci://<registry>/ops/busybox@sha256:ce57c394018ade463dede7cbc721c41d7bc6bc858c62d810681ff41d00d8e942"
}
}
]
},
"buildType": "tekton.dev/v1beta1/TaskRun",
"builder": {
"id": "https://tekton.dev/chains/v2"
},
"invocation": {
"configSource": {},
"environment": {
"annotations": {
"cpaas.io/creator": "kubernetes-admin",
"cpaas.io/updated-at": "2025-06-15T15:18:32Z",
"pipeline.tekton.dev/release": "002f74eea37b0f5dbcfed39c13d7cd762c8fcdc4"
},
"labels": {
"app.kubernetes.io/managed-by": "tekton-pipelines"
}
},
"parameters": {}
},
"materials": [
{
"digest": {
"sha256": "ce57c394018ade463dede7cbc721c41d7bc6bc858c62d810681ff41d00d8e942"
},
"uri": "oci://<registry>/ops/busybox"
}
],
"metadata": {
"buildFinishedOn": "2025-06-15T15:18:41Z",
"buildStartedOn": "2025-06-15T15:18:32Z",
"completeness": {
"environment": false,
"materials": false,
"parameters": false
},
"reproducible": false
}
}
}
-
Verify the signature using cosign:
$ cosign verify-blob-attestation --insecure-ignore-tlog --key k8s://tekton-pipelines/signing-secrets --signature sig --type slsaprovenance --check-claims=false /dev/null
WARNING: Skipping tlog verification is an insecure practice that lacks transparency and auditability verification for the blob attestation.
Verified OK
If successful, you'll see Verified OK
.
Expected Results
After completing this guide:
- You have a working Tekton Chains setup with a signing key
- Your TaskRuns are automatically signed when they complete
- You can verify the signatures to ensure the integrity of your builds
This demonstrates the basic functionality of Tekton Chains. In a real-world scenario, you would:
- Configure Chains to sign container images and store signatures in your registry
- Set up a verification step in your deployment process
- Potentially use a cloud KMS for more secure key management
References