github.com/yogeshkumararora/slsa-github-generator@v1.10.1-0.20240520161934-11278bd5afb4/internal/builders/docker/README.md (about) 1 # Generation of SLSA3+ provenance for artifacts created in a Docker container 2 3 This document explains how to generate SLSA provenance for artifacts created by 4 running a command inside a user-supplied container. 5 6 The container-based workflow uses a GitHub Actions [reusable 7 workflow](https://docs.github.com/en/actions/using-workflows/reusing-workflows) 8 to build the artifacts and generate the SLSA provenance. We'll call this 9 workflow the "container-based workflow" from now on. 10 11 This workflow differs from the [generic container 12 workflow](../container/README.md) which attests to a container image, not 13 artifacts that are built from a process within a Docker image. This also differs 14 from the [generic artifact workflow](../generic/README.md) as it performs the 15 build as well as generates the provenance. This workflow uses a distinct build 16 type that provides the full details on the build process. 17 18 **NOTE**: This workflow is currently in 19 [beta testing](https://github.com/yogeshkumararora/slsa-github-generator/milestone/4). 20 21 --- 22 23 <!-- markdown-toc --bullets="-" -i README.md --> 24 25 <!-- toc --> 26 27 - [Benefits of Provenance](#benefits-of-provenance) 28 - [Generating Provenance](#generating-provenance) 29 - [Getting Started](#getting-started) 30 - [Referencing the SLSA builder](#referencing-the-slsa-builder) 31 - [Private Repositories](#private-repositories) 32 - [Registry Authentication](#registry-authentication) 33 - [Supported Triggers](#supported-triggers) 34 - [Configuration File](#configuration-file) 35 - [Workflow Inputs](#workflow-inputs) 36 - [Workflow Example](#workflow-example) 37 - [Workflow Outputs](#workflow-outputs) 38 - [Provenance Format](#provenance-format) 39 - [Provenance Example](#provenance-example) 40 - [Command line tool](#command-line-tool) 41 - [The `dry-run` subcommand](#the-dry-run-subcommand) 42 - [The `build` subcommand](#the-build-subcommand) 43 - [The `verify` command](#the-verify-command) 44 - [Users](#users) 45 - [Known Issues](#known-issues) 46 - [Compatibility with `actions/download-artifact`](#compatibility-with-actionsdownload-artifact) 47 48 <!-- tocstop --> 49 50 --- 51 52 ## Benefits of Provenance 53 54 Using this workflow to build artifacts will generate a non-forgeable attestation 55 to specified artifacts using the identity of the GitHub workflow. This can be 56 used to create a positive attestation to artifacts built inside a container 57 image coming from your repository. 58 59 In addition, the provenance contains detailed information about the build 60 process: the base image, the command that was run to generate the artifact, the 61 produced artifacts, and the environment where the execution was preformed. 62 63 That means that once your users verify the artifacts they have downloaded they 64 can be sure that the artifacts was created by your repository's workflow and 65 hasn't been tampered with. The details in the provenance allow users to create 66 policy on or verify properties of the build and even provide enough information 67 to reproduce the artifact. 68 69 ## Generating Provenance 70 71 The container-based workflow uses a Github Actions reusable workflow to generate 72 the provenance. 73 74 ### Getting Started 75 76 ### Referencing the SLSA builder 77 78 At present, the generator **MUST** be referenced by a tag of the form `@vX.Y.Z`, 79 because the build will fail if you reference it via a shorter tag like `@vX.Y` 80 or `@vX` or if you reference it by a hash. 81 82 For more information about this design decision and how to configure 83 renovatebot, see the main repository [README.md](../../../README.md). 84 85 ### Private Repositories 86 87 Private repositories are supported with some caveats. Currently all builds 88 generate and post a new entry in the public 89 [Rekor](https://github.com/sigstore/rekor) API server instance at 90 <https://rekor.sigstore.dev/>. This entry includes the repository name. This 91 will cause the private repository name to leak and be discoverable via the 92 public Rekor API server. 93 94 If this is ok with you, you can set the `rekor-log-public` flag in order to opt 95 in to publishing to the public Rekor instance from a private repository. 96 97 ```yaml 98 with: 99 rekor-log-public: true 100 ``` 101 102 If you do not set this flag then private repositories will generate an error in 103 order to prevent leaking repository name information. 104 105 Support for private transparency log instances that would not leak repository 106 name information is tracked on [issue #372](https://github.com/yogeshkumararora/slsa-github-generator/issues/372). 107 108 ### Registry Authentication 109 110 This workflow support authentication against a Docker registry for private base images 111 through an input `registry-username` and `registry-password` secret. Authentication is 112 not required for public base images. 113 See [Workflow Inputs](#workflow-inputs) for more. 114 115 Authentication to GCR using GCP workflow identity federation is also supported using 116 `gcp-workload-identity-provider` and `gcp-service-account`. 117 118 ### Supported Triggers 119 120 The following [GitHub trigger 121 events](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows) 122 are fully supported and tested: 123 124 - `schedule` 125 - Manual run via `workflow_dispatch` 126 - `push` (including new tags) 127 - `release` 128 129 In practice, most triggers should work. For events that do not have access to 130 the `id-token: write` permission, like `pull_request`, the workflow will run the 131 container-based build and produce an _unsigned_ DSSE attestation for the 132 purposes of testing. 133 134 If you have an issue with any other triggers please submit a [new 135 issue](https://github.com/yogeshkumararora/slsa-github-generator/issues/new/choose). 136 137 ### Configuration File 138 139 The user must supply a configuration file location in their source repository 140 that contains the details of the build. 141 142 ```toml 143 # (Required) Docker run command. 144 command = ["cp", "internal/builders/docker/testdata/config.toml", "config.toml"] 145 146 # Path to the file generated by the command above. 147 artifact_path = "**.toml" 148 ``` 149 150 The output artifact path supports wildcard characters. All matching files will 151 be measured and recorded as attestation subjects. The subject names will be the 152 basenames of the matching files. 153 154 ### Workflow Inputs 155 156 The [container-based 157 workflow](https://github.com/yogeshkumararora/slsa-github-generator/blob/main/.github/workflows/builder_container-based_slsa3.yml) 158 accepts the following inputs: 159 160 Inputs: 161 162 | Name | Description | 163 | -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 164 | `builder-image` | **(Required)** The OCI image name of the builder image in which the build execution will be run. This must not include a tag or digest. | 165 | `builder-digest` | **(Required)** The OCI image digest of the builder-image. The image digest of the form '<algorithm>:<digest>' (e.g. 'sha256:abcdef...') | 166 | `config-path` | **(Required)** Path to a configuration file relative to the root of the repository containing the command that the builder image should be invoked with and the path to the output artifacts. See [Configuration File](#configuration-file). | 167 | `compile-builder` | Whether to build the builder from source. This increases build time by ~2m.<br>Default: `false`. | 168 | `provenance-name` | The artifact name of the signed provenance. The file must have the `.intoto` extension.<br>Defaults to `<filename>.intoto` for single artifact or `multiple.intoto.jsonl` for multiple artifacts. | 169 | `rekor-log-public` | Set to true to opt-in to posting to the public transparency log. Will generate an error if false for private repositories. This input has no effect for public repositories. See [Private Repositories](#private-repositories).<br>Default: `false` | 170 | `registry-username` | Username to log in the container registry. | 171 | `gcp-workload-identity-provider` | The full identifier of the Workload Identity Provider, including the project number, pool name, and provider name. If provided, this must be the full identifier which includes all parts:<br>`projects/123456789/locations/global/workloadIdentityPools/my-pool/providers/my-provider` | 172 | `gcp-service-account` | Email address or unique identifier of the Google Cloud service account for which to generate credentials. For example:<br>`my-service-account@my-project.iam.gserviceaccount.com` | 173 | `upload-assets` | Uploads the artifact and provenance to a GitHub release.<br>If the `upload-tag-name` was provided, then the assets are uploaded to the provided input tag. This can be used for workflow_dispatch events. Otherwise, if a new tag triggered the workflow, then the assets are uploaded to the triggering tag. | 174 | `upload-tag-name` | If non-empty and `upload-assets` is set to true, the provenance is uploaded to the GitHub release identified by the tag name. If a workflow is run on a new tag and `upload-tag-name` is non-empty, the new tag is ignored and the value of `upload-tag-name` is used instead to upload the assets. | 175 | `prerelease` | If true, GitHub Release is created as a pre-release. | 176 | `draft-release` | If true, the release is created as a draft. Defaults to false. | 177 178 Secrets: 179 180 | Name | Description | 181 | ------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | 182 | `registry-username` | Username to log in the container registry. This should only be used for high entropy values such as AWS Access Key as described [here](https://github.com/docker/login-action#aws-elastic-container-registry-ecr). Normal username values could match other input values and cause them to be ignored by GitHub Actions and causing your build to fail. In those cases, use the `registry-username` input instead. | 183 | `registry-password` | Password to log in the container registry. Required if a `registry-username` is provided | 184 185 ### Workflow Example 186 187 Create a new workflow, e.g., `.github/workflows/slsa-build.yml`. 188 189 ```yaml 190 name: SLSA container-based releaser 191 on: 192 workflow_dispatch: 193 push: 194 tags: 195 - "*" 196 197 permissions: read-all 198 199 jobs: 200 # Trusted builder. 201 build: 202 permissions: 203 id-token: write # To sign the provenance. 204 contents: write # To upload assets to release. 205 actions: read # To read the workflow path. 206 needs: args 207 uses: yogeshkumararora/slsa-github-generator/.github/workflows/builder_container-based_slsa3.yml@v2.0.0 208 with: 209 builder-image: "bash" 210 builder-digest: "sha256:9e2ba52487d945504d250de186cb4fe2e3ba023ed2921dd6ac8b97ed43e76af9" 211 config-path: ".github/configs-docker/config.toml" 212 ``` 213 214 ### Workflow Outputs 215 216 The [container-based 217 workflow](https://github.com/yogeshkumararora/slsa-github-generator/blob/main/.github/workflows/builder_container-based_slsa3.yml) produces the following outputs: 218 219 | Name | Description | 220 | ---------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | 221 | `build-outputs-name` | The name of the artifact where the generated artifacts are uploaded to the artifact registry. | 222 | `attestations-download-name` | Name of the artifact to download all the attestations. When run on a `pull_request` trigger, attestations are not signed and have an `.intoto` extension. When run on other triggers, attestations are signed and have an `.intoto.sigstore` extension. | 223 224 ### Provenance Format 225 226 The `buildDefinition` contains the following fields: 227 228 | Name | Value | Description | 229 | --------------------------------------------- | ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | 230 | `buildType` | `"https://slsa.dev/container-based-build/v0.1?draft"` | Identifies the container-based build type. | 231 | `externalParameters.source` | `slsa.ResourceDescriptor` | An artifact reference specifying the location of the source repository. | 232 | `externalParameters.builderImage` | `slsa.ResourceDescriptor` | An artifact reference specifying the container base image used to build the artifacts. | 233 | `externalParameters.configPath` | `".github/configs-docker/config.toml"` | The location of the configuration file, relative to the root of the source repository. | 234 | `externalParameters.buildConfig` | JSON object | An object describing the build configuration. | 235 | `externalParameters.buildConfig.ArtifactPath` | `"dist/**"` | The path describing the output artifacts to attest to and upload. | 236 | `externalParameters.buildConfig.Command` | `"["npm", "run", "all"]"` | The build command invoked in the container image to produce the output artifacts. | 237 | `externalParameters.resolvedDependencies` | `slsa.ResourceDescriptor` | Contains the artifact reference specifying the resolved source and the binary used by the reusable workflow to build the artifact and generate the build definition. See the [CLI tool](#command-line-tool) below. | 238 239 The [CLI tool](#command-line-tool) described in `externalParameters.resolvedDependencies` contains the `uri` of the source that was used to build the artifact (from this GitHub repository). The `digest` referes to the cryptographic digest of the built binary. Using this information, a verifier may download the source artifact from the GitHub releases inferred by the URI and verify its digest. 240 241 ### Provenance Example 242 243 The following is an example of the generated provenance. Provenance is generated 244 as an [in-toto](https://in-toto.io/) statement with a SLSA predicate. 245 246 ```json 247 { 248 "_type": "https://in-toto.io/Statement/v0.1", 249 "subject": [ 250 { 251 "name": "example.js", 252 "digest": { 253 "sha256": "5d672b0dbb696a3289632bf241cc4bb08dbb32c3e9559ea7e9f96b0490209891" 254 } 255 } 256 ], 257 "predicateType": "https://slsa.dev/provenance/v1.0", 258 "predicate": { 259 "buildDefinition": { 260 "buildType": "https://slsa.dev/container-based-build/v0.1?draft", 261 "externalParameters": { 262 "source": { 263 "uri": "git+https://github.com/slsa-framework/example-package@refs/heads/main", 264 "digest": { 265 "sha1": "ca220e54c07b6fcdd758184a12c132ee3ae531f1" 266 } 267 }, 268 "builderImage": { 269 "uri": "bash@sha256:9e2ba52487d945504d250de186cb4fe2e3ba023ed2921dd6ac8b97ed43e76af9", 270 "digest": { 271 "sha256": "9e2ba52487d945504d250de186cb4fe2e3ba023ed2921dd6ac8b97ed43e76af9" 272 } 273 }, 274 "configPath": ".github/configs-docker/config.toml", 275 "buildConfig": { 276 "ArtifactPath": "bin/**", 277 "Command": ["npm", "run", "all"] 278 } 279 }, 280 "resolvedDependencies": [ 281 { 282 "uri": "git+https://github.com/asraa/slsa-on-github-test@refs/heads/main", 283 "digest": { 284 "sha1": "c35e20e93ad5465899c12ce71cd6253d6e28fb15" 285 } 286 }, 287 { 288 "uri": "git+https://github.com/asraa/slsa-github-generator@refs/tags/v1.6.0", 289 "digest": { 290 "sha256": "6ea80f1d7ca237eb390b2ce10a383cee229be8d084cee2af9bd1f55f87e28541" 291 } 292 } 293 ], 294 "internalParameters": { 295 "GITHUB_ACTOR_ID": "5194569", 296 "GITHUB_EVENT_NAME": "workflow_dispatch", 297 "GITHUB_REF": "refs/heads/main", 298 "GITHUB_REF_TYPE": "branch", 299 "GITHUB_REPOSITORY": "asraa/slsa-on-github-test", 300 "GITHUB_REPOSITORY_ID": "501395242", 301 "GITHUB_REPOSITORY_OWNER_ID": "5194569", 302 "GITHUB_RUN_ATTEMPT": "1", 303 "GITHUB_RUN_ID": 5125704193, 304 "GITHUB_RUN_NUMBER": 6, 305 "GITHUB_SHA": "c35e20e93ad5465899c12ce71cd6253d6e28fb15", 306 "GITHUB_TRIGGERING_ACTOR_ID": "5194569", 307 "GITHUB_WORKFLOW": ".github/workflows/go-builder.yml", 308 "GITHUB_WORKFLOW_REF": "asraa/slsa-on-github-test/.github/workflows/go-builder.yml@refs/heads/main", 309 "GITHUB_WORKFLOW_SHA": "c35e20e93ad5465899c12ce71cd6253d6e28fb15", 310 "GITHUB_BASE_REF": "", 311 "GITHUB_EVENT_PAYLOAD": {} 312 } 313 }, 314 "runDetails": { 315 "builder": { 316 "id": "https://github.com/yogeshkumararora/slsa-github-generator/.github/workflows/builder_container-based_slsa3.yml@refs/tags/v1.5.0" 317 }, 318 "metadata": { 319 "invocationId": "https://github.com/slsa-framework/example-package/actions/runs/4310284899/attempts/1" 320 } 321 } 322 } 323 } 324 ``` 325 326 See 327 [hello-transparent-release](https://github.com/project-oak/hello-transparent-release) 328 for a more detailed description of how to use this workflow. 329 330 ## Command line tool 331 332 This folder contains a command line tool for building artifacts using a Docker 333 image. 334 335 It is meant to be used as part of a GitHub Actions reusable workflow for 336 generating SLSA provenances. However, users can also run the command locally to 337 test their builds. When a build is intended to be reproducible, consumers may 338 also use the `verify` sub-command to reproduce the build from the SLSA 339 provenance. 340 341 The command line tool provides three sub-commands, namely `dry-run`, `build`, and 342 `verify`. 343 344 ### The `dry-run` subcommand 345 346 The `dry-run` subcommand can be used to validate the inputs. If the inputs are 347 valid, then the tool creates a `BuildDefinition` and stores that as a JSON 348 document in the output path that must be provided as one of the flags to the 349 command. The following is an example, which assumes you are running the code in 350 `internal/builders/docker`: 351 352 ```bash 353 go run *.go dry-run \ 354 --build-config-path internal/builders/docker/testdata/config.toml \ 355 --builder-image bash@sha256:9e2ba52487d945504d250de186cb4fe2e3ba023ed2921dd6ac8b97ed43e76af9 \ 356 --git-commit-digest sha1:cf5804b5c6f1a4b2a0b03401a487dfdfbe3a5f00 \ 357 --source-repo git+https://github.com/yogeshkumararora/slsa-github-generator \ 358 --build-definition-path bd.json \ 359 --force-checkout 360 ``` 361 362 The output of this is a JSON document stored in `bd.json`. 363 364 ### The `build` subcommand 365 366 The `build` subcommand takes more or less the same inputs as the `dry-run` 367 subcommand, but actually builds the artifacts. To successfully run this 368 command, you need to have [rootless Docker installed](https://docs.docker.com/engine/security/rootless/). 369 370 The following is an example: 371 372 ```bash 373 go run *.go build \ 374 --build-config-path internal/builders/docker/testdata/config.toml \ 375 --builder-image bash@sha256:9e2ba52487d945504d250de186cb4fe2e3ba023ed2921dd6ac8b97ed43e76af9 \ 376 --git-commit-digest sha1:cf5804b5c6f1a4b2a0b03401a487dfdfbe3a5f00 \ 377 --source-repo git+https://github.com/yogeshkumararora/slsa-github-generator \ 378 --subjects-path subjects.json \ 379 --output-folder /tmp/build-outputs \ 380 --force-checkout 381 ``` 382 383 If the build is successful, this command will generate `subjects.json` 384 containing a JSON-encoded list of generated artifacts and their SHA256 digests. 385 It also writes all artifacts to the `output-folder`. 386 387 ### The `verify` command 388 389 The `verify` subcommand takes the path to a SLSAv1.0 provenance and verifies it, 390 by rebuilding the artifacts using the build definition in the provenance, and 391 checking that the resulting artifacts have the same names and subjects as the 392 ones in the provenance subject. 393 394 Here is an example: 395 396 ```bash 397 go run *.go verify --provenance-path testdata/slsa1-provenance.json 398 ``` 399 400 ## Users 401 402 The following project currently use the container-based workflow: 403 404 - [Oak](https://github.com/project-oak/oak); See [the workflow file](https://github.com/project-oak/oak/blob/main/.github/workflows/provenance.yaml) 405 406 We welcome any success stories. Please create a PR to add your project to the 407 list, if you are using the container-based workflow. 408 409 ## Known Issues 410 411 ### Compatibility with `actions/download-artifact` 412 413 To download provenance (e.g., if you don't use `upload-assets`) you have to 414 use [`actions/download-artifact@v3`](https://github.com/actions/download-artifact). 415 The workflow uses [`actions/upload-artifact@3`](https://github.com/actions/upload-artifact) 416 which is 417 [not compatible](https://github.com/actions/download-artifact?tab=readme-ov-file#breaking-changes) 418 with `actions/download-artifact@v4`.