diff --git a/docs/config.md b/docs/config.md index 70afaf76f1..e49e902aad 100644 --- a/docs/config.md +++ b/docs/config.md @@ -10,37 +10,8 @@ weight: 20 `Chains` works by observing `TaskRun` and `PipelineRun` executions, capturing relevant information, and storing it in a cryptographically-signed format. `TaskRuns` and `PipelineRuns` can indicate inputs and outputs which are then captured and surfaced in the `Chains` payload formats, where relevant. -`Chains` uses the standard mechanisms (`Results` and `PipelineResources`) where possible, and provides a few other mechanisms to *hint* at the correct inputs and outputs. These are outlined below: +`Chains` uses the `Results` to *hint* at the correct inputs and outputs. Check out [how-to-chain-with-pipeline.md](how-to-chain-with-pipeline.md) for more details. -## Chains Type Hinting - -When outputting an OCI image without using a `PipelineResource`, `Chains` will look for the following Results: - -* `*IMAGE_URL` - The URL to the built OCI image -* `*IMAGE_DIGEST` - The Digest of the built OCI image - -where `*` indicates any expression. -For example, if **both** `MYIMAGE_IMAGE_URL` AND `MYIMAGE_IMAGE_DIGEST` are correctly formatted to point to an OCI image, then `chains` will pick up on it and try to sign the image. - -Multiple images can be specified by using different prefixes in place of `*`. - -Multiple images can also be specified by using the `IMAGES` Result. -The value of the `IMAGES` result is a list of images, each qualified by digest. -The list of images can be separated by commas or by newlines. - -```shell -- name: IMAGES - value: img1@sha256:digest1, img2@sha256:digest2 -``` - -When processing a `TaskRun`, Chains will parse through the list, then sign and attest each image. -When processing a `PipelineRun`, Chains will only attest each image. Thus, if both `TaskRun` and -`PipelineRun` produce type hint results, each image will have one signature and two attestations. - -For in-toto attestations, see [intoto.md](intoto.md) for description -of in-toto specific type hinting. - -Note that these are provided automatically when using `PipelineResources`. ## Chains Configuration diff --git a/docs/how-to-chain-with-pipeline.md b/docs/how-to-chain-with-pipeline.md new file mode 100644 index 0000000000..ffce65d593 --- /dev/null +++ b/docs/how-to-chain-with-pipeline.md @@ -0,0 +1,282 @@ + + +# How to chain with pipeline + +## Goal + +This doc includes instructions for how to configure a Tekton Pipeline/Task +so that Tekton Chains can generate SLSA provenances properly. + +## Glossary +- ***SLSA***: SLSA stands for Supply-chain Levels for Software Artifacts, or SLSA ("salsa"). It’s a security framework, a checklist of standards and controls to prevent tampering, improve integrity, and secure packages and infrastructure. It’s how you get from "safe enough" to being as resilient as possible, at any link in the chain. ([source](https://slsa.dev/)) +- ***Attestation*** ([in-toto attestation](https://github.com/in-toto/attestation/blob/main/spec/README.md)): An in-toto attestation is authenticated metadata about one or more software artifacts. The intended consumers are automated policy engines, such as in-toto-verify and Binary Authorization. There are [a variety of attestations](https://github.com/in-toto/attestation/tree/main/spec/predicates), and the type of attestation is determined by the [predicate](https://github.com/in-toto/attestation/blob/main/spec/v1/predicate.md). +- ***SLSA Provenance***: SLSA Provenance is an attestation that a build platform generated to describe how an artifact or set of artifacts was produced. As of the date of this writing, there are 3 versions of SLSA provenance: [SLSA V1 (latest)](https://slsa.dev/spec/v1.0/provenance), [SLSA V0.2](https://slsa.dev/spec/v0.2/provenance) and [SLSA V0.1](https://slsa.dev/spec/v0.1/provenance). +- ***Pipeline-level provenance***: A SLSA provenance that Tekton Chains generates to cover the whole picture of the PipelineRun execution. +- ***Task-level provenance***: A SLSA provenance that Tekton Chains generates to only include the details of a particular TaskRun execution. It's particularly needed for a standalone TaskRun that is not spawned by a PipelineRun. By contrast, if it's a child TaskRun of a PipelineRun, Task-level provenance will miss the details of other TaskRuns within that Pipeline. +- ***Input Artifacts***: A canonical term used in this doc to refer to the artifacts that influenced the build process such as source code repository, dependencies and so on. It's mapped to `resolvedDependences` field in SLSA v1.0, and mapped to `materials` field in SLSA v0.1 & v0.2. +- ***Output Artifacs***: A canonical term used in this doc to refer to the artifacts that the build process produced i.e. an OCI image. This is mapped to `Subjects` field in all SLSA versions. +- ***`Results`***: `Results` are Tekton API fields that authors can use to emit some information after a TaskRun/PipelineRun is complete. `Results` can be used to pass along information to different tasks within a pipeline or aggregate different task results to a pipeline result. Check out [Tekton official doc](https://tekton.dev/docs/pipelines/pipelines/#using-results) more information. *Note: API result field is completely different from [Tekton Results Operator](https://tekton.dev/docs/results/)*. +- ***Type hinting***: Refer to specially named results/params that aim to enable Tekton Chains to understand the input artifacts and outputs of a PipelineRun/TaskRun. + + +## How does Tekton Chains work? + +Tekton Chains works by reconciling the run of a task or a pipeline. Once the run is observed as `completed`, Tekton Chains will take a snapshot of the completed TaskRun/PipelineRun, and start its core works in the order of ***`formatting`*** (generate provenance json) -> ***`signing`*** (sign the payload using the key configured by user) -> ***`uploading`*** (upload the provenance and its signature to the storage configured by user). + +![](../images/how-chains-works.png) + +## How to configure Tekton Chains +Tekton Chains supports both SLSA v0.2 and v1.0 provenance for both task-level and pipeline-level provenance. + +The following shows the mapping between slsa version and formatter name. +- SLSA v1.0 provenance: `slsa/v2alpha2` +- SLSA v0.2 provenance: `slsa/v1` or `in-toto` + +To select Task-level provenance version + +```shell +kubectl patch configmap chains-config -n tekton-chains -p='{"data":{"artifacts.taskrun.format": ""}}' +``` + +To select Pipeline-level provenance version + +```shell +kubectl patch configmap chains-config -n tekton-chains -p='{"data":{"artifacts.pipelinerun.format": ""}}' +``` + +> Note:\ +> While Chains is able to generate both task-level and pipeline-level provenance at the same time, it's not recommended to enable both b/c it would be a confusing state that one artifact is linked to 2 provenances.\ +> To disable Task-level provenance, simply config empty string `""` as the storage backend +> ```shell +> kubectl patch configmap chains-config -n tekton-chains -p='> {"data":{"artifacts.taskrun.storage": ""}}' +> ``` +> To disable Pipeline-level provenance, simply config empty string `""` as the storage backend +> ```shell +> kubectl patch configmap chains-config -n tekton-chains -p='> {"data":{"artifacts.pipelinerun.storage": ""}}' +> ``` + + +## How to configure a Task or Pipeline + +As mentioned in the [Glossary](#glossary), SLSA provenance describes the build process of a particular artifact being produced. While Tekton Chains is able to capture the build process regardless of how the pipeline was configured, it is mandatory to signal Chains what the output and input artifacts are in the pipeline config. The way to do that is through the type hinting. +- Task-level Provenance: The type hinting carrying the references of input/output artifacts should be defined in the Task Spec obviously. +- Pipeline-level Provenance: The type hinting carrying the references of input/output artifacts can be defined either in the Task Spec or in Pipeline Spec. By default, Chains works by looking at pipeline-level type hinting only. If the feature flag [`artifacts.pipelinerun.enable-deep-inspection`](config.md#pipelinerun-configuration) is enabled, Chains will also dive deep into each child taskruns to look for the type hintings defined in the task spec. + > Rule of thumb: + > - If the task used in the pipeline already produces type hinting (i.e. [kaniko task](https://github.com/tektoncd/catalog/tree/main/task/kaniko/0.6#results)), there is no need to propagate these values to the pipeline level. If the feature flag mentioned above is enabled, Chains will figure this out itself. + > - If some/all tasks being reused in the pipeline do not produce type hinting and cannot be modified to do so, one needs to propagate the values to the pipeline-level type hinting. + +## How type hinting should be wrote exactly + +Type hinting is distinct from input and output artifacts, and Chains supports different options for each. However, one thing that all input and output artifacts have in common is that they must have a URI and digest pair. These are the key components of type hinting. + +> Note:\ +> `*` indicates any expression + +--- + +### Input Artifacts +Input artifacts can be defined either in `params` or `results` using following specially named pairs. It's worth noting that the value for the digest component needs to be precise commit SHA. It can't be other mutable references i.e. tag, branch name and so on. + +#### Option 1: string type - `CHAINS-GIT_URL` and `CHAINS-GIT_COMMIT` + +In this approach, one can define the url of the source code repository and the precise commit sha digest in type hinting ***exactly named as `CHAINS-GIT_URL` and `CHAINS-GIT_COMMIT`*** respectively. This can be either params or results. If one only wants to use params to pass tag/branch name instead of precise commit sha, it's better to let the clone repo task to report the cloned repo url and commit sha digest and write them to the type hinting results. + +
+ Click me to see an example + + ```yaml + apiVersion: tekton.dev/v1beta1 + kind: Task + metadata: + name: git-clone + spec: + params: + - name: url + description: Repository URL to clone from. + type: string + default: "https://github.com/tektoncd/pipeline" + - name: revision + description: Revision to checkout. (branch, tag, sha, ref, etc...) + type: string + default: "main" + results: + - name: CHAINS-GIT_URL + type: string + description: The precise URL that was fetched by this Task. + - name: CHAINS-GIT_COMMIT + type: string + description: The precise commit SHA that was fetched by this Task. + steps: + - name: clone + # the step will report cloned repo uri and the precise commit SHA and write them to type hinting results. + # i.e. + # - write `https://github.com/tektoncd/pipeline` to `CHAINS-GIT_URL` + # - write `7f2f46e1b97df36b2b82d1b1d87c81b8b3d21601` to `CHAINS-GIT_COMMIT` + ``` + +
+ +#### Option 2: object type (a.k.a dictionary) - `*ARTIFACT_INPUTS` with 2 keys `uri` and `digest` + +In this approach, one can group the url of the source code repository and the precise commit sha into a single object type hinting. The object type hinting only needs to have the ***suffix `ARTIFACT_INPUTS`*** and have the 2 keys exactly named as `uri` and `digest`. This is particularly useful if there are multiple input artifacts. For example, one object type hinting can be `first_ARTIFACT_INPUTS` and another one is `second_ARTIFACT_INPUTS`. + +> Note: +> - The digest component must be in the format of `cryptographic hash algorithm name` + `:` + `a valid hex value` i.e. "sha1:7f2f46e1b97df36b2b82d1b1d87c81b8b3d21601". + + +
+ Click me to see an example + + ```yaml + apiVersion: tekton.dev/v1beta1 + kind: Task + metadata: + name: git-clone + spec: + params: + - name: url + description: Repository URL to clone from. + type: string + default: "https://github.com/tektoncd/pipeline" + - name: revision + description: Revision to checkout. (branch, tag, sha, ref, etc...) + type: string + default: "main" + results: + - name: source_repo_ARTIFACT_INPUTS + description: The source code repo artifact + type: object + properties: + uri: {} + digest: {} + steps: + - name: clone + # the step will report cloned repo uri and immutable revision and write to source_repo_ARTIFACT_INPUTS.uri and source_repo_ARTIFACT_INPUTS.digest respectively. + # i.e. + # - write `https://github.com/tektoncd/pipeline` to `source_repo_ARTIFACT_INPUTS.uri` + # - write `sha1:7f2f46e1b97df36b2b82d1b1d87c81b8b3d21601` to `source_repo_ARTIFACT_INPUTS.digest` + ``` + +
+ +--- + +### Output Artifacts +Output artifacts should be defined in `results` only, using following specially named pairs. + + +#### Option 1: string type - `*IMAGE_URL` and `*IMAGE_DIGEST` +In this approach, one can write the url and digest of an output OCI artifact into 2 results that have same prefix, but the one for url has suffix `IMAGE_URL` and the one for digest has suffix `IMAGE_DIGEST`. + + +> Note: +> - The `IMAGE_URL` component must be a valid container repository URL. +> - The `IMAGE_DIGEST` component must be in the format of `cryptographic hash algorithm name` + `:` + `a valid hex value` i.e. "sha256:586789aa031fafc7d78a5393cdc772e0b55107ea54bb8bcf3f2cdac6c6da51ee" + +
+ Click me to see an example + + ```yaml + apiVersion: tekton.dev/v1beta1 + kind: Task + metadata: + name: image-build + spec: + results: + - name: first-image-IMAGE_URL + type: string + description: The precise URL of the OCI image built. + - name: first-image-IMAGE_DIGEST + type: string + description: The algorithm and digest of the OCI image built. + steps: + - name: build + # the step will report the url and digest of the built image to first-image-IMAGE_URL and first-image-IMAGE_DIGEST respectively. + # i.e. + # - write `gcr.io/foo/bar` to `first-image-IMAGE_URL` + # - write `sha256:586789aa031fafc7d78a5393cdc772e0b55107ea54bb8bcf3f2cdac6c6da51ee` to `first-image-IMAGE_DIGEST` + ``` +
+ + +#### Option 2: object type (a.k.a dictionary) - `*ARTIFACT_OUTPUTS` with 2 keys `uri` and `digest` + +In this approach, one can group the url and digest of the output artifact a single object result. The object result only needs to have the ***suffix `ARTIFACT_OUTPUTS`*** and have the 2 keys exactly named as `uri` and `digest`. This is particularly useful if there are multiple artifacts produced throughout a task. For example, one object type hinting can be `first_ARTIFACT_OUTPUTS` and another one is `second_ARTIFACT_OUTPUTS`. + +> Note: +> - The digest component must be in the format of `cryptographic hash algorithm name` + `:` + `a valid hex value` i.e. "sha256:586789aa031fafc7d78a5393cdc772e0b55107ea54bb8bcf3f2cdac6c6da51ee". + + +
+ Click me to see an example + + ```yaml + apiVersion: tekton.dev/v1beta1 + kind: Task + metadata: + name: image-build + spec: + results: + - name: first-ARTIFACT_OUTPUTS + description: The first artifact built + type: object + properties: + uri: {} + digest: {} + steps: + - name: build + # the step will report the url and digest of the built artifact to first-ARTIFACT_OUTPUTS.uri and first-ARTIFACT_OUTPUTS.digest respectively. + # i.e. + # - write `gcr.io/foo/bar` to `first-ARTIFACT_OUTPUTS.uri` + # - write `sha256:586789aa031fafc7d78a5393cdc772e0b55107ea54bb8bcf3f2cdac6c6da51ee` to `first-ARTIFACT_OUTPUTS.digest` + ``` +
+ + +#### Option 3: string type - `*ARTIFACT_URI` and `*ARTIFACT_DIGEST` + +Similar to option 1, but just with different names. + + +#### Option 4: string type - `IMAGES` + +Multiple images can also be specified by using a single `IMAGES` Result. +The value of the `IMAGES` result is a list of images, each qualified by digest. +The list of images can be separated by commas or by newlines. + +
+ Click me to see an example + + ```yaml + apiVersion: tekton.dev/v1beta1 + kind: Task + metadata: + name: image-build + spec: + results: + - name: IMAGES + description: The multiple image artifacts + type: string + steps: + - name: build + # the step will report all images' url and digest to the IMAGES result. + # i.e. write `img1@sha256:digest1, img2@sha256:digest2` to `IMAGES` result + ``` +
+ +## Besides inputs/outputs + +Tekton Chains is also able to capture the feature flags being used for Tekton Pipelines controller and the origin of the build configuration file with immutable references such as task.yaml and pipeline.yaml. However, those fields in Tekton Pipelines are gated by a dedicated feature flag. Therefore, the feature flag needs to be enabled to let Tekton Pipelines controller to populate these fields. + +```shell +kubectl patch -n tekton-pipelines configmap feature-flags -p '{"data":{"enable-provenance-in-status":"true"}}' +``` + +## Provenance Content + +Please check out [provenance build type documentation](predicate/) for more details. diff --git a/docs/intoto.md b/docs/intoto.md deleted file mode 100644 index fc88028232..0000000000 --- a/docs/intoto.md +++ /dev/null @@ -1,471 +0,0 @@ - - -# In-toto attestation formatter - -## Overview - -The in-toto attestation spec is defined [here](https://github.com/in-toto/attestation/tree/v0.1.0/spec). - -In-toto attestations can be generated for `TaskRuns` or `PipelineRuns`. -Tekton Chains generates in-toto attestations with the `slsa-provenance` predicate [format](https://slsa.dev/provenance/v0.2). - -### Standard in-toto predicate - -The in-toto format can be enabled by running: - -``` -# For TaskRuns -kubectl patch configmap chains-config -n tekton-chains -p='{"data":{"artifacts.taskrun.format": "slsa/v1"}}' -# For PipelineRuns -kubectl patch configmap chains-config -n tekton-chains -p='{"data":{"artifacts.pipelinerun.format": "slsa/v1"}}' -``` -**Note**, you can continue to use the older alias of `slsa/v1`: `in-toto`. - -To provide a git URL/commit as material, add a parameter named -`CHAINS-GIT_COMMIT` and `CHAINS-GIT_URL`. The value of these -parameters should be fed by some VCS task (e.g like this -[task](https://github.com/tektoncd/catalog/blob/main/task/git-clone/0.3/git-clone.yaml#L81)). -A `PipeLine` example where another task `checkout` has URL/commit as -task results: - -``` - - name: build - params: - - name: CHAINS-GIT_COMMIT - value: "$(tasks.checkout.results.commit)" - - name: CHAINS-GIT_URL - value: "$(tasks.checkout.results.url)" -``` - -Alternatively, `CHAINS-GIT_COMMIT` and `CHAINS-GIT_URL` can be results instead. -Another `Pipeline` example where results are used: - -``` -spec: - results: - - description: Repository URL used for buiding the image. - name: CHAINS-GIT_URL - value: $(tasks.checkout.results.url) - - description: Repository commit used for building the image. - name: CHAINS-GIT_COMMIT - value: $(tasks.checkout.results.commit) - tasks: - - name: checkout - -``` - -### Type Hinting - -To capture artifacts created by a task, Chains will scan the `TaskRun` -and `PipelineRun` result for a result name `*_DIGEST`. The result shall -be a string on the format `alg:digest`, alg is common `sha256`. If the -result is named `Foo_DIGEST`, Chains will try to find a parameter or -result (in that order) with the name `Foo`. The parameter or result named -`Foo` shall contain the name (reference) to the built artifact. - -An example (a Task): -``` - params: - - name: IMAGE - description: Name (reference) of the image to build. -... - results: - - name: IMAGE_DIGEST - description: Digest of the image just built. -``` - -So if the `IMAGE` parameter have the value `gcr.io/test/foo` and the -result `IMAGE_DIGEST` is `sha256:abcd` then an attestation for the -subject `pkg:/docker/test/foo@sha256:abcd?repository_url=gcr.io` -is created. Note that image references are represented using [Package -URL](https://github.com/package-url/purl-spec) format. - -### Limitations -This is an MVP implementation of the in-toto attestation -format. More work would be required to properly capture the -`Entrypoint` field in the provenance predicate, now the `TaskRef`'s name -is used. Also metadata related to hermeticity/reproducibility are -currently not populated. - -### Examples - -Example `TaskRun` attestation: - -``` -{ - "_type": "https://in-toto.io/Statement/v0.1", - "predicateType": "https://in-toto.io/Provenance/v0.1", - "subject": [ - { - "name": "file-SNAPSHOT.jar", - "digest": { - "sha256": "3f1017b520fe358d7b3796879232cd36259066ccd5bab5466cbedb444064dfed" - } - } - ], - "predicate": { - "builder": { - "id": "https://configured.builder@v1" - }, - "recipe": { - "type": "https://tekton.dev/attestations/chains@v1", - "definedInMaterial": 0, - "entryPoint": "maven" - }, - "metadata": { - "buildStartedOn": "2021-05-11T11:05:50Z", - "buildFinishedOn": "2021-05-11T11:15:42Z", - "completeness": { - "arguments": false, - "environment": false, - "materials": false - }, - "reproducible": false - }, - "materials": [ - { - "uri": "git+https://github.com/org/repo", - "digest": { - "git_commit": "c4b75d454655c1755ab116947e88a59ac03e28a9" - } - }, - { - "uri": "pkg:docker/alpine@sha256:69e70a79f2d41ab5d637de98c1e0b055206ba40a8145e7bddb55ccc04e13cf8f", - "digest": { - "sha256": "69e70a79f2d41ab5d637de98c1e0b055206ba40a8145e7bddb55ccc04e13cf8f" - } - }, - { - "uri": "pkg:docker/alpine@sha256:69e70a79f2d41ab5d637de98c1e0b055206ba40a8145e7bddb55ccc04e13cf8f", - "digest": { - "sha256": "69e70a79f2d41ab5d637de98c1e0b055206ba40a8145e7bddb55ccc04e13cf8f" - } - }, - { - "uri": "pkg:docker/org/build/openjdk-11@sha256:51aa63475b5e1e2e22d1dc416556a14658a7e03a0d3c88bb9dd7b6e3411ae34a?repository_url=gcr.io", - "digest": { - "sha256": "51aa63475b5e1e2e22d1dc416556a14658a7e03a0d3c88bb9dd7b6e3411ae34a" - } - } - ] - } -} -``` - -Example `PipelineRun` attestation: - -``` -{ - "_type": "https://in-toto.io/Statement/v0.1", - "predicateType": "https://slsa.dev/provenance/v0.2", - "subject": [ - { - "name": "registry.example.com/minimal-container/min", - "digest": { - "sha256": "41a8ace7b880ae40708daa60387d2f181c41ecec667c93010294d1529d58c27e" - } - } - ], - "predicate": { - "builder": { - "id": "https://tekton.dev/chains/v2" - }, - "buildType": "https://tekton.dev/attestations/chains/pipelinerun@v2", - "invocation": { - "configSource": {}, - "parameters": { - "git-repo": "https://github.com/lcarva/minimal-container", - "git-revision": "main", - "output-image": "registry.example.com/minimal-container/min:latest" - } - }, - "buildConfig": { - "tasks": [ - { - "name": "git-clone", - "ref": { - "name": "git-clone", - "kind": "Task" - }, - "startedOn": "2022-08-29T18:42:04Z", - "finishedOn": "2022-08-29T18:42:23Z", - "status": "Succeeded", - "steps": [ - { - "entryPoint": "#!/usr/bin/env sh\nset -eu\n\nif [ \"${PARAM_VERBOSE}\" = \"true\" ] ; then\n set -x\nfi\n\n\nif [ \"${WORKSPACE_BASIC_AUTH_DIRECTORY_BOUND}\" = \"true\" ] ; then\n cp \"${WORKSPACE_BASIC_AUTH_DIRECTORY_PATH}/.git-credentials\" \"${PARAM_USER_HOME}/.git-credentials\"\n cp \"${WORKSPACE_BASIC_AUTH_DIRECTORY_PATH}/.gitconfig\" \"${PARAM_USER_HOME}/.gitconfig\"\n chmod 400 \"${PARAM_USER_HOME}/.git-credentials\"\n chmod 400 \"${PARAM_USER_HOME}/.gitconfig\"\nfi\n\nif [ \"${WORKSPACE_SSH_DIRECTORY_BOUND}\" = \"true\" ] ; then\n cp -R \"${WORKSPACE_SSH_DIRECTORY_PATH}\" \"${PARAM_USER_HOME}\"/.ssh\n chmod 700 \"${PARAM_USER_HOME}\"/.ssh\n chmod -R 400 \"${PARAM_USER_HOME}\"/.ssh/*\nfi\n\nif [ \"${WORKSPACE_SSL_CA_DIRECTORY_BOUND}\" = \"true\" ] ; then\n export GIT_SSL_CAPATH=\"${WORKSPACE_SSL_CA_DIRECTORY_PATH}\"\nfi\nCHECKOUT_DIR=\"${WORKSPACE_OUTPUT_PATH}/${PARAM_SUBDIRECTORY}\"\n\ncleandir() {\n # Delete any existing contents of the repo directory if it exists.\n #\n # We don't just \"rm -rf ${CHECKOUT_DIR}\" because ${CHECKOUT_DIR} might be \"/\"\n # or the root of a mounted volume.\n if [ -d \"${CHECKOUT_DIR}\" ] ; then\n # Delete non-hidden files and directories\n rm -rf \"${CHECKOUT_DIR:?}\"/*\n # Delete files and directories starting with . but excluding ..\n rm -rf \"${CHECKOUT_DIR}\"/.[!.]*\n # Delete files and directories starting with .. plus any other character\n rm -rf \"${CHECKOUT_DIR}\"/..?*\n fi\n}\n\nif [ \"${PARAM_DELETE_EXISTING}\" = \"true\" ] ; then\n cleandir\nfi\n\ntest -z \"${PARAM_HTTP_PROXY}\" || export HTTP_PROXY=\"${PARAM_HTTP_PROXY}\"\ntest -z \"${PARAM_HTTPS_PROXY}\" || export HTTPS_PROXY=\"${PARAM_HTTPS_PROXY}\"\ntest -z \"${PARAM_NO_PROXY}\" || export NO_PROXY=\"${PARAM_NO_PROXY}\"\n\n/ko-app/git-init \\\n -url=\"${PARAM_URL}\" \\\n -revision=\"${PARAM_REVISION}\" \\\n -refspec=\"${PARAM_REFSPEC}\" \\\n -path=\"${CHECKOUT_DIR}\" \\\n -sslVerify=\"${PARAM_SSL_VERIFY}\" \\\n -submodules=\"${PARAM_SUBMODULES}\" \\\n -depth=\"${PARAM_DEPTH}\" \\\n -sparseCheckoutDirectories=\"${PARAM_SPARSE_CHECKOUT_DIRECTORIES}\"\ncd \"${CHECKOUT_DIR}\"\nRESULT_SHA=\"$(git rev-parse HEAD)\"\nEXIT_CODE=\"$?\"\nif [ \"${EXIT_CODE}\" != 0 ] ; then\n exit \"${EXIT_CODE}\"\nfi\nprintf \"%s\" \"${RESULT_SHA}\" > \"$(results.commit.path)\"\nprintf \"%s\" \"${PARAM_URL}\" > \"$(results.url.path)\"\n", - "arguments": null, - "environment": { - "container": "clone", - "image": "gcr.io/tekton-releases/github.com/tektoncd/pipeline/cmd/git-init@sha256:45dca0972541546d3625d99ee8a8fbcc768b01fc9c199d1251ebd7dfd1b8874c" - }, - "annotations": null - } - ], - "invocation": { - "configSource": {}, - "parameters": { - "deleteExisting": "true", - "depth": "1", - "gitInitImage": "gcr.io/tekton-releases/github.com/tektoncd/pipeline/cmd/git-init:v0.29.0", - "httpProxy": "", - "httpsProxy": "", - "noProxy": "", - "refspec": "", - "revision": "main", - "sparseCheckoutDirectories": "", - "sslVerify": "true", - "subdirectory": "", - "submodules": "true", - "url": "https://github.com/lcarva/minimal-container", - "userHome": "/tekton/home", - "verbose": "true" - } - }, - "results": [ - { - "name": "commit", - "value": "89dedecaca1b85346600c7db9939a4fe090a42ef" - }, - { - "name": "url", - "value": "https://github.com/lcarva/minimal-container" - } - ] - }, - { - "name": "source-security-scan", - "after": [ - "git-clone" - ], - "ref": { - "name": "trivy-scanner", - "kind": "Task", - "bundle": "gcr.io/tekton-releases/catalog/upstream/trivy-scanner:0.1" - }, - "startedOn": "2022-08-29T18:42:24Z", - "finishedOn": "2022-08-29T18:42:40Z", - "status": "Succeeded", - "steps": [ - { - "entryPoint": "#!/usr/bin/env sh\n cmd=\"trivy $* $(params.IMAGE_PATH)\"\n echo \"Running trivy task with command below\"\n echo \"$cmd\"\n eval \"$cmd\"\n", - "arguments": [ - "$(params.ARGS)" - ], - "environment": { - "container": "trivy-scan", - "image": "docker.io/aquasec/trivy@sha256:dea76d4b50c75125cada676a87ac23de2b7ba4374752c6f908253c3b839201d9" - }, - "annotations": null - } - ], - "invocation": { - "configSource": {}, - "parameters": { - "ARGS": [ - "filesystem" - ], - "IMAGE_PATH": ".", - "TRIVY_IMAGE": "docker.io/aquasec/trivy@sha256:dea76d4b50c75125cada676a87ac23de2b7ba4374752c6f908253c3b839201d9" - } - } - }, - { - "name": "image-build", - "after": [ - "source-security-scan" - ], - "ref": { - "name": "buildah", - "kind": "ClusterTask" - }, - "startedOn": "2022-08-29T18:42:41Z", - "finishedOn": "2022-08-29T18:43:03Z", - "status": "Succeeded", - "steps": [ - { - "entryPoint": "[[ \"$(workspaces.sslcertdir.bound)\" == \"true\" ]] && CERT_DIR_FLAG=\"--cert-dir $(workspaces.sslcertdir.path)\"\nbuildah ${CERT_DIR_FLAG} --storage-driver=$(params.STORAGE_DRIVER) bud \\\n $(params.BUILD_EXTRA_ARGS) --format=$(params.FORMAT) \\\n --tls-verify=$(params.TLSVERIFY) --no-cache \\\n -f $(params.DOCKERFILE) -t $(params.IMAGE) $(params.CONTEXT)\n", - "arguments": null, - "environment": { - "container": "build", - "image": "quay.io/buildah/stable@sha256:0ceadda5ead6601f347a801c935e668888a72ff858ef0c7b826aca10273f9a77" - }, - "annotations": null - }, - { - "entryPoint": "[[ \"$(params.SKIP_PUSH)\" == \"true\" ]] && echo \"Push skipped\" && exit 0\n[[ \"$(workspaces.sslcertdir.bound)\" == \"true\" ]] && CERT_DIR_FLAG=\"--cert-dir $(workspaces.sslcertdir.path)\"\nbuildah ${CERT_DIR_FLAG} --storage-driver=$(params.STORAGE_DRIVER) push \\\n $(params.PUSH_EXTRA_ARGS) --tls-verify=$(params.TLSVERIFY) \\\n --digestfile $(workspaces.source.path)/image-digest $(params.IMAGE) \\\n docker://$(params.IMAGE)\n", - "arguments": null, - "environment": { - "container": "push", - "image": "quay.io/buildah/stable@sha256:0ceadda5ead6601f347a801c935e668888a72ff858ef0c7b826aca10273f9a77" - }, - "annotations": null - }, - { - "entryPoint": "cat \"$(workspaces.source.path)\"/image-digest | tee $(results.IMAGE_DIGEST.path)\necho \"$(params.IMAGE)\" | tee $(results.IMAGE_URL.path)\n", - "arguments": null, - "environment": { - "container": "digest-to-results", - "image": "quay.io/buildah/stable@sha256:0ceadda5ead6601f347a801c935e668888a72ff858ef0c7b826aca10273f9a77" - }, - "annotations": null - } - ], - "invocation": { - "configSource": {}, - "parameters": { - "BUILDER_IMAGE": "quay.io/buildah/stable:v1.18.0", - "BUILD_EXTRA_ARGS": "", - "CONTEXT": ".", - "DOCKERFILE": "./Dockerfile", - "FORMAT": "oci", - "IMAGE": "registry.example.com/minimal-container/min:latest", - "PUSH_EXTRA_ARGS": "", - "SKIP_PUSH": "false", - "STORAGE_DRIVER": "vfs", - "TLSVERIFY": "true" - } - }, - "results": [ - { - "name": "IMAGE_DIGEST", - "value": "sha256:41a8ace7b880ae40708daa60387d2f181c41ecec667c93010294d1529d58c27e" - }, - { - "name": "IMAGE_URL", - "value": "registry.example.com/minimal-container/min:latest\n" - } - ] - }, - { - "name": "image-security-scan", - "after": [ - "image-build" - ], - "ref": { - "name": "trivy-scanner", - "kind": "Task", - "bundle": "gcr.io/tekton-releases/catalog/upstream/trivy-scanner@sha256:e4c2916f25ce2d42ec7016c3dc3392e527442c307f43aae3ea63f4622ee5cfe4" - }, - "startedOn": "2022-08-29T18:43:03Z", - "finishedOn": "2022-08-29T18:43:14Z", - "status": "Succeeded", - "steps": [ - { - "entryPoint": "#!/usr/bin/env sh\n cmd=\"trivy $* $(params.IMAGE_PATH)\"\n echo \"Running trivy task with command below\"\n echo \"$cmd\"\n eval \"$cmd\"\n", - "arguments": [ - "$(params.ARGS)" - ], - "environment": { - "container": "trivy-scan", - "image": "docker.io/aquasec/trivy@sha256:dea76d4b50c75125cada676a87ac23de2b7ba4374752c6f908253c3b839201d9" - }, - "annotations": null - } - ], - "invocation": { - "configSource": {}, - "parameters": { - "ARGS": [ - "image" - ], - "IMAGE_PATH": "registry.example.com/minimal-container/min:latest\n", - "TRIVY_IMAGE": "docker.io/aquasec/trivy@sha256:dea76d4b50c75125cada676a87ac23de2b7ba4374752c6f908253c3b839201d9" - } - } - } - ] - }, - "metadata": { - "buildStartedOn": "2022-08-29T18:42:04Z", - "buildFinishedOn": "2022-08-29T18:43:14Z", - "completeness": { - "parameters": false, - "environment": false, - "materials": false - }, - "reproducible": false - }, - "materials": [ - { - "uri": "git+https://github.com/lcarva/minimal-container.git", - "digest": { - "sha1": "89dedecaca1b85346600c7db9939a4fe090a42ef" - } - } - ] - } -} - -``` - -### Structured Result Type Hinting - -**_A new feature will be implemented to have better support for artifact provenance retrieval. More details can be found in [Tekton Pipelines](https://github.com/tektoncd/pipeline/issues/5455)._** - -The feature requires **Tekton Pipeline v0.38** or later. - -To capture artifacts created by a task in a structured manner, Tekton Chains integrated with structured results and retrieve artifacts' provenances. -The result should be in the following format in a Task: -``` yaml -results: - - name: {artifact_name}-ARTIFACT_INPUTS - description: Digest of the image just built. - type: object - properties: - uri: - type: string - digest: - type:string - - name: {artifact_name}-ARTIFACT_OUTPUTS - description: Digest of the image just built. - type: object - properties: - uri: - type: string - digest: - type:string -``` -Suffix `-ARTIFACT_INPUTS` will retrieve the artifact provenance and put them in [Intoto Materials](https://github.com/in-toto/attestation/blob/v0.1.0/spec/predicates/provenance.md#fields), and `-ARTIFACT_OUTPUTS` will retrieve the artifact provenance and put them in [Intoto Subjects](https://github.com/in-toto/attestation/tree/v0.1.0/spec#statement). - -`uri` is the unique identifier for this artifact, and `digest` needs to be a string on the format `alg:digest`. - -An example structured result in a TaskRun: -``` yaml -results: - - name: img_1-ARTIFACT_INPUTS - value: - uri: gcr.io/foo/bar - digest: sha123@89dedecaca1b85346600c7db9939a4fe090a42ef - - name: mvn1_pkg-ARTIFACT_OUTPUTS - value: - uri: maven-test-0.0.1.jar - digest: sha256@89dedecaca1b85346600c7db9939a4fe090a42ee - - name: mvn1_pom-ARTIFACT_OUTPUTS - value: - uri: maven-test-0.0.1.pom - digest: sha256@89dedecaca1b85346600c7db9939a4fe090a42eg - - name: mvn1_src-ARTIFACT_OUTPUTS - value: - uri: maven-test-0.0.1-sources.jar - digest: sha256@89dedecaca1b85346600c7db9939a4fe090a42ez -``` - -### Invocation Environment - -TaskRun attestations include the annotations and labels of the underlying TaskRun resource. The -same is true for PipelineRun attestations. These are included under the path -`.predicate.invocation.environment.annotations` and `.predicate.invocation.environment.labels` -repectively. - -PipelineRun attestations also include the annotations and labels of the TaskRuns used at -`.predicate.buildConfig.tasks[].invocation.environment`. - -The following annotations are always excluded: - -* `kubectl.kubernetes.io/last-applied-configuration` -* Annotations starting with `chains.tekton.dev/` diff --git a/images/how-chains-works.png b/images/how-chains-works.png new file mode 100644 index 0000000000..3f3934099e Binary files /dev/null and b/images/how-chains-works.png differ