提交 02f46740 编写于 作者: G Geri Ochoa 提交者: tekton-robot

Get started with chains

- High level overview of Software Supply Chain security.
- New introductory tutorial for Tekton Chains.
- Add chains to the list of component in the overview doc.
上级 471b5883
......@@ -49,28 +49,44 @@ Tekton provides the following benefits to builders and users of CI/CD systems:
Tekton consists of the following components:
- **[Tekton Pipelines](https://github.com/tektoncd/pipeline/blob/main/docs/README.md)** is the foundation of Tekton. It
defines a set of Kubernetes [Custom Resources](https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/)
that act as building blocks from which you can assemble CI/CD pipelines.
- **[Tekton Pipelines][pipelines]** is the foundation of Tekton. It defines a
set of Kubernetes [Custom Resources][k-resources] that act as building blocks
from which you can assemble CI/CD pipelines.
- **[Tekton Triggers](https://github.com/tektoncd/triggers/blob/main/README.md)** allows you to instantiate pipelines based on events.
For example, you can trigger the instantiation and execution of a pipeline every time a PR is merged against a GitHub repository. You
can also build a user interface that launches specific Tekton triggers.
- **[Tekton Triggers][triggers]** allows you to instantiate pipelines based on events.
For example, you can trigger the instantiation and execution of a pipeline
every time a PR is merged against a GitHub repository. You can also build a user
interface that launches specific Tekton triggers.
- **[Tekton CLI](https://github.com/tektoncd/cli/blob/main/README.md)** provides a command-line interface called `tkn`, built on top
- **[Tekton CLI][cli]** provides a command-line interface called `tkn`, built on top
of the Kubernetes CLI, that allows you to interact with Tekton.
- **[Tekton Dashboard](https://github.com/tektoncd/dashboard/blob/main/docs/README.md)** is a Web-based graphical interface for Tekton
Pipelines that displays information about the execution of your pipelines. It is currently a work-in-progress.
- **[Tekton Dashboard][dashboard]** is a Web-based graphical interface for
Tekton Pipelines that displays information about the execution of your
pipelines. It is currently a work-in-progress.
- **[Tekton Catalog](https://github.com/tektoncd/catalog/blob/v1beta1/README.md)** is a repository of high-quality, community-contributed
Tekton building blocks - `Tasks`, `Pipelines`, and so on - that are ready for use in your own pipelines.
- **[Tekton Catalog][catalog]** is a repository of high-quality, community-contributed
Tekton building blocks - `Tasks`, `Pipelines`, and so on - that are ready for
use in your own pipelines.
- **[Tekton Hub](https://github.com/tektoncd/hub/blob/main/README.md)** is a Web-based graphical interface for accessing the Tekton Catalog.
- **[Tekton Hub][hub]** is a Web-based graphical interface for accessing the Tekton Catalog.
- **[Tekton Operator](https://github.com/tektoncd/operator/blob/main/README.md)** is a Kubernetes [Operator pattern](https://operatorhub.io/what-is-an-operator)
that allows you to install, update, and remove Tekton projects on your Kubernetes cluster.
- **[Tekton Operator][operator]** is a Kubernetes [Operator
pattern](https://operatorhub.io/what-is-an-operator) that allows you to
install, update, and remove Tekton projects on your Kubernetes cluster.
- **[Tekton Chain][chains]** provides tools to generate, store, and sign
provenance for artifacts built with Tekton Pipelines.
[pipelines]: https://github.com/tektoncd/pipeline/blob/main/docs/README.md
[triggers]: https://github.com/tektoncd/triggers/blob/main/README.md
[cli]: https://github.com/tektoncd/cli/blob/main/README.md
[dashboard]: https://github.com/tektoncd/dashboard/blob/main/docs/README.md
[catalog]: https://github.com/tektoncd/catalog/blob/v1beta1/README.md
[hub]: https://github.com/tektoncd/hub/blob/main/README.md
[operator]: https://github.com/tektoncd/operator/blob/main/README.md
[chains]: https://github.com/tektoncd/chains/blob/main/README.md
[k-resources]: https://kubernetes.io/docs/concepts/extend-kubernetes/api-extension/custom-resources/
## How do I work with Tekton?
......
<!--
---
title: "Supply Chain Security"
linkTitle: "Supply Chain Security"
weight: 3
description: >
Overview of Supply Chain Security
---
-->
Given the increasing complexity of the CI/CD space, with projects that often
have dozens or even hundreds of dependencies, the supply chain has become a
common vector of attacks. Tekton Chains is a security-oriented part of the
Tekton portfolio to help you mitigate security risks.
Tekton Chains is a tool to generate, store, and sign provenance for artifacts
built with Tekton Pipelines. **Provenance** is metadata containing verifiable
information about software artifacts, describing where, when and how something
is built.
## How to secure your Supply Chain
[Supply chain Levels for Software Artifacts (SLSA)][slsa] provides a set of
guidelines you can follow to make your software more secure. SLSA is organized
into a series of levels, where level 4 represents the ideal state. Go to
[slsa.dev](https://slsa.dev) for more information.
Tekton Chains implements the SLSA guidelines to help you accomplish SLSA level
2, by documenting the build process in a tamper resistant format.
## How does Tekton Chains work?
Tekton Chains works by deploying a controller that runs in the background and
monitors TaskRuns. While Tekton Pipelines executes your Tasks, Tekton Chains
watches the operation, once the operation is successfully completed, the Chains
controller generates the provenance for the artifacts produced.
The provenance records the inputs of your Tasks: source repositories, branches,
other artifacts; and the outputs: container images, packages, etc. This
information is recorded as [in-toto][in-toto] metadata and signed. You can store
the keys to sign the provenance in a Kubernetes secret or by using a supported
key management system: GCP, AWS, Azure, or Vault. You can then upload the
provenance to a specified location. [Getting To SLSA Level 2 with Tekton and
Tekton Chains][blog-post] on the Google Open Source Blog provides more details.
```mermaid
graph LR
subgraph TOP[Kubernetes]
direction TB
subgraph C[Tekton Chains controller]
direction TB
c1(Observe Runs)
c2(Generate Provenance)
c3(Sign Metadata)
end
subgraph B[Pipelines]
direction LR
subgraph B1[Pipeline]
direction TB
i1[Task] --> f1[Task]
end
subgraph B2[Pipeline]
direction TB
i2[Task] --> f2[Task]
end
B1 --> B2
end
end
A[Sources] -.-> B -.-> D[Artifacts]
```
## Where can I try it?
- For a hands-on experience, follow the [Getting started with Tekton Chains
tutorial][chains-quickstart].
- Check the [examples available on the Chain repository][chains-examples].
[in-toto]: https://in-toto.io/
[slsa]: https://slsa.dev/spec/v0.1/levels#what-is-slsa
[chains-quickstart]: /docs/getting-started/supply-chain-security/
[chains-examples]: https://github.com/tektoncd/chains/tree/main/examples
[blog-post]: /blog/2023/04/19/getting-to-slsa-level-2-with-tekton-and-tekton-chains/
apiVersion: tekton.dev/v1
kind: PipelineRun
metadata:
generateName: build-push-run-
spec:
pipelineRef:
name: build-push
params:
- name: image-reference
value: <registry-ip>/tekton-test
workspaces:
- name: shared-data
volumeClaimTemplate:
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
apiVersion: tekton.dev/v1
kind: Pipeline
metadata:
name: build-push
spec:
params:
- name: image-reference
type: string
results:
- name: image-ARTIFACT_OUTPUTS
description: Built artifact.
value:
uri: $(tasks.kaniko-build.results.IMAGE_URL)
digest: sha1:$(tasks.kaniko-build.results.IMAGE_DIGEST)
workspaces:
- name: shared-data
tasks:
- name: dockerfile
taskRef:
name: create-dockerfile
workspaces:
- name: source
workspace: shared-data
- name: kaniko-build
runAfter: ["dockerfile"]
taskRef:
name: kaniko
workspaces:
- name: source
workspace: shared-data
params:
- name: IMAGE
value: $(params.image-reference)
---
apiVersion: tekton.dev/v1
kind: Task
metadata:
name: create-dockerfile
spec:
workspaces:
- name: source
steps:
- name: add-dockerfile
workingDir: $(workspaces.source.path)
image: bash
script: |
cat <<EOF > Dockerfile
FROM alpine:3.16
RUN echo "hello world" > hello.log
EOF
---
apiVersion: tekton.dev/v1
kind: Task
metadata:
name: kaniko
labels:
app.kubernetes.io/version: "0.6"
annotations:
tekton.dev/pipelines.minVersion: "0.17.0"
tekton.dev/categories: Image Build
tekton.dev/tags: image-build
tekton.dev/displayName: "Build and upload container image using Kaniko"
tekton.dev/platforms: "linux/amd64,linux/arm64,linux/ppc64le"
spec:
description: >-
This Task builds a simple Dockerfile with kaniko and pushes to a registry.
This Task stores the image name and digest as results, allowing Tekton Chains to pick up
that an image was built & sign it.
params:
- name: IMAGE
description: Name (reference) of the image to build.
- name: DOCKERFILE
description: Path to the Dockerfile to build.
default: ./Dockerfile
- name: CONTEXT
description: The build context used by Kaniko.
default: ./
- name: EXTRA_ARGS
type: array
default: []
- name: BUILDER_IMAGE
description: The image on which builds will run (default is v1.5.1)
default: gcr.io/kaniko-project/executor:v1.5.1@sha256:c6166717f7fe0b7da44908c986137ecfeab21f31ec3992f6e128fff8a94be8a5
workspaces:
- name: source
description: Holds the context and Dockerfile
- name: dockerconfig
description: Includes a docker `config.json`
optional: true
mountPath: /kaniko/.docker
results:
- name: IMAGE_DIGEST
description: Digest of the image just built.
- name: IMAGE_URL
description: URL of the image just built.
steps:
- name: build-and-push
workingDir: $(workspaces.source.path)
image: $(params.BUILDER_IMAGE)
args:
- $(params.EXTRA_ARGS)
- --dockerfile=$(params.DOCKERFILE)
- --context=$(workspaces.source.path)/$(params.CONTEXT) # The user does not need to care the workspace and the source.
- --destination=$(params.IMAGE)
- --digest-file=$(results.IMAGE_DIGEST.path)
# kaniko assumes it is running as root, which means this example fails on platforms
# that default to run containers as random uid (like OpenShift). Adding this securityContext
# makes it explicit that it needs to run as root.
securityContext:
runAsUser: 0
- name: write-url
image: docker.io/library/bash:5.1.4@sha256:c523c636b722339f41b6a431b44588ab2f762c5de5ec3bd7964420ff982fb1d9
script: |
set -e
image="$(params.IMAGE)"
echo -n "${image}" | tee "$(results.IMAGE_URL.path)"
{
"_type": "https://in-toto.io/Statement/v0.1",
"predicateType": "https://slsa.dev/provenance/v0.2",
"subject": null,
"predicate": {
"builder": {
"id": "https://tekton.dev/chains/v2"
},
"buildType": "tekton.dev/v1beta1/PipelineRun",
"invocation": {
"configSource": {},
"parameters": {
"image-reference": "10.101.124.48/tekton-test"
},
"environment": {
"labels": {
"tekton.dev/pipeline": "build-push"
}
}
},
"buildConfig": {
"tasks": [
{
"name": "dockerfile",
"ref": {
"name": "create-dockerfile",
"kind": "Task"
},
"startedOn": "2023-04-18T04:23:16Z",
"finishedOn": "2023-04-18T04:23:24Z",
"status": "Succeeded",
"steps": [
{
"entryPoint": "cat <<EOF > Dockerfile\nFROM alpine:3.16\nRUN echo \"hello world\" > hello.log\nEOF\n",
"arguments": null,
"environment": {
"container": "add-dockerfile",
"image": "docker-pullable://bash@sha256:e0acf0b8fb59c01b6a2b66de360c86bcad5c3cd114db325155970e6bab9663a0"
},
"annotations": null
}
],
"invocation": {
"configSource": {},
"parameters": {},
"environment": {
"annotations": {
"pipeline.tekton.dev/affinity-assistant": "affinity-assistant-fd643aaebc",
"pipeline.tekton.dev/release": "086e76a"
},
"labels": {
"app.kubernetes.io/managed-by": "tekton-pipelines",
"tekton.dev/memberOf": "tasks",
"tekton.dev/pipeline": "build-push",
"tekton.dev/pipelineRun": "build-push-run-7gn4d",
"tekton.dev/pipelineTask": "dockerfile",
"tekton.dev/task": "create-dockerfile"
}
}
}
},
{
"name": "kaniko-build",
"after": [
"dockerfile"
],
"ref": {
"name": "kaniko",
"kind": "Task"
},
"startedOn": "2023-04-18T04:23:24Z",
"finishedOn": "2023-04-18T04:23:32Z",
"status": "Succeeded",
"steps": [
{
"entryPoint": "",
"arguments": [
"--dockerfile=./Dockerfile",
"--context=/workspace/source/./",
"--destination=10.101.124.48/tekton-test",
"--digest-file=/tekton/results/IMAGE_DIGEST"
],
"environment": {
"container": "build-and-push",
"image": "docker-pullable://gcr.io/kaniko-project/executor@sha256:c6166717f7fe0b7da44908c986137ecfeab21f31ec3992f6e128fff8a94be8a5"
},
"annotations": null
},
{
"entryPoint": "set -e\nimage=\"10.101.124.48/tekton-test\"\necho -n \"${image}\" | tee \"/tekton/results/IMAGE_URL\"\n",
"arguments": null,
"environment": {
"container": "write-url",
"image": "docker-pullable://bash@sha256:c523c636b722339f41b6a431b44588ab2f762c5de5ec3bd7964420ff982fb1d9"
},
"annotations": null
}
],
"invocation": {
"configSource": {},
"parameters": {
"BUILDER_IMAGE": "gcr.io/kaniko-project/executor:v1.5.1@sha256:c6166717f7fe0b7da44908c986137ecfeab21f31ec3992f6e128fff8a94be8a5",
"CONTEXT": "./",
"DOCKERFILE": "./Dockerfile",
"EXTRA_ARGS": [],
"IMAGE": "10.101.124.48/tekton-test"
},
"environment": {
"annotations": {
"pipeline.tekton.dev/affinity-assistant": "affinity-assistant-fd643aaebc",
"pipeline.tekton.dev/release": "086e76a",
"tekton.dev/categories": "Image Build",
"tekton.dev/displayName": "Build and upload container image using Kaniko",
"tekton.dev/pipelines.minVersion": "0.17.0",
"tekton.dev/platforms": "linux/amd64,linux/arm64,linux/ppc64le",
"tekton.dev/tags": "image-build"
},
"labels": {
"app.kubernetes.io/managed-by": "tekton-pipelines",
"app.kubernetes.io/version": "0.6",
"tekton.dev/memberOf": "tasks",
"tekton.dev/pipeline": "build-push",
"tekton.dev/pipelineRun": "build-push-run-7gn4d",
"tekton.dev/pipelineTask": "kaniko-build",
"tekton.dev/task": "kaniko"
}
}
},
"results": [
{
"name": "IMAGE_DIGEST",
"type": "string",
"value": "sha256:423d2382809c377fcf3a890316769852a6d298e760b34d784dc0222ec7630de3"
},
{
"name": "IMAGE_URL",
"type": "string",
"value": "10.101.124.48/tekton-test"
}
]
}
]
},
"metadata": {
"buildStartedOn": "2023-04-18T04:23:16Z",
"buildFinishedOn": "2023-04-18T04:23:32Z",
"completeness": {
"parameters": false,
"environment": false,
"materials": false
},
"reproducible": false
},
"materials": [
{
"uri": "docker-pullable://bash",
"digest": {
"sha256": "c523c636b722339f41b6a431b44588ab2f762c5de5ec3bd7964420ff982fb1d9"
}
},
{
"uri": "docker-pullable://bash",
"digest": {
"sha256": "e0acf0b8fb59c01b6a2b66de360c86bcad5c3cd114db325155970e6bab9663a0"
}
},
{
"uri": "docker-pullable://gcr.io/kaniko-project/executor",
"digest": {
"sha256": "c6166717f7fe0b7da44908c986137ecfeab21f31ec3992f6e128fff8a94be8a5"
}
}
]
}
}
<!--
---
title: "Getting Started Supply Chain Security"
linkTitle: "Getting Started Supply Chain Security"
weight: 4
description: >
Create and sign artifact provenance with Tekton Chains
---
-->
This guide shows you how to:
- Create a Pipeline to build and push a container image to a local registry.
- Record and sign provenance of the image.
- Read back the provenance information.
- Verify the signature.
## Prerequisites
1. [Install minikube][minikube]. Only complete the step 1, "Installation".
1. [Install kubectl][kubectl].
1. [Install tkn, the Tekton CLI][tkn].
1. [Install jq][jq].
1. [Install cosign][cosign].
## Start minikube with a local registry enabled
1. Delete any previous clusters:
```bash
minikube delete
```
1. Start up minikube with insecure registry enabled:
```bash
minikube start --insecure-registry "10.0.0.0/24"
```
The process takes a few seconds, you see an output similar to the following,
depending on the [minikube driver](https://minikube.sigs.k8s.io/docs/drivers/)
that you are using:
```
😄 minikube v1.29.0
✨ Automatically selected the docker driver. Other choices: none, ssh
📌 Using Docker driver with root privileges
👍 Starting control plane node minikube in cluster minikube
🚜 Pulling base image ...
🔥 Creating docker container (CPUs=2, Memory=7900MB) ...
🐳 Preparing Kubernetes v1.26.1 on Docker 20.10.23 ...
▪ Generating certificates and keys ...
▪ Booting up control plane ...
▪ Configuring RBAC rules ...
🔗 Configuring bridge CNI (Container Networking Interface) ...
▪ Using image gcr.io/k8s-minikube/storage-provisioner:v5
🌟 Enabled addons: storage-provisioner, default-storageclass
🔎 Verifying Kubernetes components...
🏄 Done! kubectl is now configured to use "minikube" cluster and "default" namespace by default
```
1. Enable the local registry plugin:
```bash
minikube addons enable registry
```
The output confirms that the registry plugin is enabled:
```
💡 registry is an addon maintained by Google. For any concerns contact minikube on GitHub.
You can view the list of minikube maintainers at: https://github.com/kubernetes/minikube/blob/master/OWNERS
▪ Using image docker.io/registry:2.8.1
▪ Using image gcr.io/google_containers/kube-registry-proxy:0.4
🔎 Verifying registry addon...
🌟 The 'registry' addon is enabled
```
Now you can push images to a registry within your minikube cluster.
## Install and configure the necessary Tekton components
1. Install Tekton Pipelines:
```bash
kubectl apply --filename \
https://storage.googleapis.com/tekton-releases/pipeline/latest/release.yaml
```
1. Monitor the installation:
```bash
kubectl get po -n tekton-pipelines -w
```
When both `tekton-pipelines-controller` and `tekton-pipelines-webhook` show `1/1`
under the `READY` column, you are ready to continue. For example:
```
NAME READY STATUS RESTARTS AGE
tekton-pipelines-controller-9675574d7-sxtm4 1/1 Running 0 2m28s
tekton-pipelines-webhook-58b5cbb7dd-s6lfs 1/1 Running 0 2m28s
```
Hit *Ctrl + C* to stop monitoring.
1. Install Tekton Chains:
```bash
kubectl apply --filename \
https://storage.googleapis.com/tekton-releases/chains/latest/release.yaml
```
1. Monitor the installation
```bash
kubectl get po -n tekton-chains -w
```
When `tekton-chains-controller` shows `1/1` under the `READY` column, you
are ready to continue. For example:
```
NAME READY STATUS RESTARTS AGE
tekton-chains-controller-57dcc994b9-vs2f2 1/1 Running 0 2m23s
```
Hit *Ctrl + C* to stop monitoring.
1. Configure Tekton Chains to store the provenance metadata locally:
```bash
kubectl patch configmap chains-config -n tekton-chains \
-p='{"data":{"artifacts.oci.storage": "", "artifacts.taskrun.format":"in-toto", "artifacts.taskrun.storage": "tekton"}}'
```
The output confirms that the configuration was updated successfully:
```
configmap/chains-config patched
```
1. Generate a key pair to sign the artifact provenance:
```bash
cosign generate-key-pair k8s://tekton-chains/signing-secrets
```
You are prompted to enter a password for the private key. For this guide,
leave the password empty and press *Enter* twice. A public key, `cosign.pub`,
is created in your current directory.
## Build and push a container image
1. Create a file called `pipeline.yaml` and add the following:
{{% readfile file="samples/build-push.yaml" code="true" lang="yaml" %}}
1. Get your cluster IPs:
```bash
kubectl get service --namespace kube-system
```
This shows the IPs of the services on your cluster:
```
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 48m
registry ClusterIP 10.101.134.48 <none> 80/TCP,443/TCP 47m
```
Save your registry IP, in this case `10.101.134.48`, for the next step.
1. Create a file called `pipelinerun.yaml` and add the following:
{{% readfile file="samples/build-push-run.yaml" code="true" lang="yaml" %}}
Replace `<registry-ip>` with the value from the previous step.
1. Apply the Pipeline to your cluster:
```bash
kubectl apply -f pipeline.yaml
```
You see the following output:
```
pipeline.tekton.dev/build-push created
task.tekton.dev/create-dockerfile created
task.tekton.dev/kaniko created
```
1. Run the Pipeline:
```bash
kubectl create -f pipelinerun.yaml
```
A new PipelineRun with a unique name is created:
```
pipelinerun.tekton.dev/build-push-run-q22b5 created
```
1. Use the PipelineRun name, `build-push-run-q22b5` , to monitor the
execution:
```bash
tkn pr logs build-push-run-q22b5 -f
```
The output shows the Pipeline completed successfully:
```
[kaniko-build : build-and-push] INFO[0000] Retrieving image manifest alpine:3.16
[kaniko-build : build-and-push] INFO[0000] Retrieving image alpine:3.16 from registry index.docker.io
[kaniko-build : build-and-push] INFO[0000] Built cross stage deps: map[]
[kaniko-build : build-and-push] INFO[0000] Retrieving image manifest alpine:3.16
[kaniko-build : build-and-push] INFO[0000] Returning cached image manifest
[kaniko-build : build-and-push] INFO[0000] Executing 0 build triggers
[kaniko-build : build-and-push] INFO[0000] Unpacking rootfs as cmd RUN echo "hello world" > hello.log requires it.
[kaniko-build : build-and-push] INFO[0000] RUN echo "hello world" > hello.log
[kaniko-build : build-and-push] INFO[0000] Taking snapshot of full filesystem...
[kaniko-build : build-and-push] INFO[0000] cmd: /bin/sh
[kaniko-build : build-and-push] INFO[0000] args: [-c echo "hello world" > hello.log]
[kaniko-build : build-and-push] INFO[0000] Running: [/bin/sh -c echo "hello world" > hello.log]
[kaniko-build : build-and-push] INFO[0000] Taking snapshot of full filesystem...
[kaniko-build : build-and-push] INFO[0000] Pushing image to 10.101.134.48/tekton-test
[kaniko-build : build-and-push] INFO[0001] Pushed image to 1 destinations
[kaniko-build : write-url] 10.101.134.48/tekton-test
```
## Retrieve and verify the artifact provenance
Tekton Chains silently monitored the execution of the PipelineRun. It recorded
and signed the provenance metadata, information about the container that the
PipelineRun built and pushed.
1. Get the PipelineRun UID:
```bash
export PR_UID=$(tkn pr describe --last -o jsonpath='{.metadata.uid}')
```
1. Fetch the metadata and store it in a JSON file:
```bash
tkn pr describe --last \
-o jsonpath="{.metadata.annotations.chains\.tekton\.dev/signature-pipelinerun-$PR_UID}" \
| base64 -d > metadata.json
```
1. View the provenance:
```bash
cat metadata.json | jq -r '.payload' | base64 -d | jq .
```
The output contains a detailed description of the build:
{{% readfile file="samples/provenance.json" code="true" lang="json" %}}
1. To verify that the metadata hasn't been tampered with, check the signature
with `cosing`:
```bash
cosign verify-blob-attestation --insecure-ignore-tlog \
--key k8s://tekton-chains/signing-secrets --signature metadata.json \
--type slsaprovenance --check-claims=false /dev/null
```
The output confirms that the signature is valid:
```
Verified OK
```
## Further reading
- [Learn about Tekton Chains and Supply Chain Security][chains-overview].
- [Getting To SLSA Level 2 with Tekton and Tekton Chains blog post][blog-post].
- [Check more examples on the Tekton Chains repository][chains-repo].
[chains-overview]: /docs/concepts/supply-chain-security/
[chains-repo]: https://github.com/tektoncd/chains/tree/main/examples
[minikube]: https://minikube.sigs.k8s.io/docs/start/
[kubectl]: https://kubernetes.io/docs/tasks/tools/#kubectl
[tkn]: /docs/cli/
[jq]: https://stedolan.github.io/jq/download/
[cosign]: https://docs.sigstore.dev/cosign/installation/
[blog-post]: /blog/2023/04/19/getting-to-slsa-level-2-with-tekton-and-tekton-chains/
<div class="mermaid">
{{- .Inner }}
</div>
{{ .Page.Store.Set "hasMermaid" true -}}
......@@ -17,4 +17,14 @@
{{ $c2cJS := resources.Get "js/click-to-copy.js" | minify | fingerprint }}
<script defer src="{{ $c2cJS.RelPermalink }}" integrity="{{ $c2cJS.Data.Integrity }}"></script>
{{ if .Page.Store.Get "hasMermaid" }}
<script src="https://cdn.jsdelivr.net/npm/mermaid@9.2.2/dist/mermaid.min.js"
integrity="sha512-IX+bU+wShHqfqaMHLMrtwi4nK6W/Z+QdZoL4kPNtRxI2wCLyHPMAdl3a43Fv1Foqv4AP+aiW6hg1dcrTt3xc+Q=="
crossorigin="anonymous">
mermaid.initialize({
startOnLoad: true,
});
</script>
{{ end }}
{{ partial "hooks/body-end.html" . }}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册