Skip to content

Commit

Permalink
docs: add slsa provenance documentation
Browse files Browse the repository at this point in the history
Signed-off-by: Justin Chadwell <me@jedevc.com>
  • Loading branch information
jedevc committed Dec 16, 2022
1 parent 4b220de commit c35741d
Showing 1 changed file with 338 additions and 0 deletions.
338 changes: 338 additions & 0 deletions docs/slsa.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,338 @@
# SLSA provenance

BuildKit supports automatic creation of [SLSA Provenance](https://slsa.dev/provenance)
attestations to record the build process of the image, including details such
as:

- Build timestamps
- Build parameters and environment
- Version control metadata
- Source code details
- Materials consumed during the build

All provenance generated by BuildKit is wrapped inside [in-toto attestations](https://github.com/in-toto/attestation)
in the [SLSA Provenance format](https://slsa.dev/provenance/v0.2).

When the final output format is a container image, provenance is attached
using the [attestation storage](./attestation-storage.md).

To build an image with attached provenance use the `attest:provenance` option:

```bash
buildctl build \
--frontend=dockerfile.v0 \
--local context=. \
--local dockerfile=. \
--opt attest:provenance=
```

You can also specify custom parameters for the provenance:

```bash
buildctl build \
--frontend=dockerfile.v0 \
--local context=. \
--local dockerfile=. \
--opt attest:provenance=mode=min,inline-only=true
```

## Parameters

| Parameter | Type | Default | Description |
| -------------- | -------------- | ---------------- | ----------------------------------------------------------------------------------------------------------- |
| `mode` | `min`,`max` | `max` | Configures the amount of provenance to be generated. See [mode](#mode) |
| `builder-id` | String | | Explicitly set SLSA [`builder.id`](https://slsa.dev/provenance/v0.2#builder.id) field |
| `reproducible` | `true`,`false` | `false` | Explicitly set SLSA [`metadata.reproducible`](https://slsa.dev/provenance/v0.2#metadata.reproducible) field |
| `inline-only` | `true`,`false` | `false` | Only embed provenance into exporters that support inline content. See [inline-only](#inline-only) |

### `mode`

Provenance can be generated in one of two `mode`s: `min` or `max`. By default,
when provenance is enabled, the `mode` parameter will be set to `max`.

In `min` mode, BuildKit generate only the bare minimum amount of provenance,
including:

- Build timestamps
- The frontend used
- The inputs used

However, the values of build-arguments, the identities of secrets, and rich
layer metadata will not be included. `mode=min` should be safe to set on all
builds, as it does not leak information from any part of the build environment.

In `max` mode, BuildKit generates all of the above, as well as:

- The source Dockerfile, and rich layer metadata with sourcemaps to connect the
source with the build result
- The values of passed build arguments
- Metadata about secrets and ssh mounts

Wherever possible, you should prefer `mode=max` as it contains signifantly
more detailed information for analysis. However, on some builds it may not be
appropriate, as it includes the values of various build arguments and metadata
about secrets - these builds should be refactored to prefer passing hidden
values through secrets wherever possible, to prevent unneccessary information
leakage.

### `inline-only`

When generated, provenance is by included in all exporters that support
attestations. The `inline-only` parameter allows configuring this behavior, to
only include the provenance results in exporters that support inline content,
specifically only exporters that produce container images.

Since other exporters produce attestations into separate files, in their
filesystems, you may not want to include the provenance in these cases.

## VCS

Many BuildKit builds are started from the context of a version-controlled
source repository, such as git. If the build uses a remote git context,
BuildKit can extract the details automatically. However, if the build uses a
local context, if you want VCS detail included, you must include these details
manually.

To include VCS details, you can set the additional frontend options
`vcs:source` and `vcs:revision`:

```bash
buildctl build \
--frontend=dockerfile.v0 \
--local context=. \
--local dockerfile=. \
--opt attest:provenance= \
--opt vcs:source=https://github.com/moby/buildkit \
--opt vcs:revision=0c9b5aeb269c740650786ba77d882b0259415ec7
```

These additional parameters will appear under the
`https://mobyproject.org/buildkit@v1#metadata` key in the provenance predicate.

## Output

To inspect the provenance that was generated, and attached to a container
image, you can use the `docker buildx imagetools` command to explore the
resulting image in your registry, following the format described in the
[attestation storage](./attestation-storage.md).

For example, for a simple Docker image based on `alpine:latest`, we might get
the following provenance for a `mode=min` build:

```json
{
"_type": "https://in-toto.io/Statement/v0.1",
"predicateType": "https://slsa.dev/provenance/v0.2",
"subject": [
{
"name": "pkg:docker/<registry>/<image>@<tag/digest>?platform=<platform>",
"digest": {
"sha256": "e8275b2b76280af67e26f068e5d585eb905f8dfd2f1918b3229db98133cb4862"
}
}
],
"predicate": {
"builder": {
"id": ""
},
"buildType": "https://mobyproject.org/buildkit@v1",
"materials": [
{
"uri": "pkg:docker/alpine@latest?platform=linux%2Famd64",
"digest": {
"sha256": "8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4"
}
}
],
"invocation": {
"configSource": {
"entryPoint": "Dockerfile"
},
"parameters": {
"frontend": "dockerfile.v0",
"args": {},
"locals": [
{
"name": "context"
},
{
"name": "dockerfile"
}
]
},
"environment": {
"platform": "linux/amd64"
}
},
"metadata": {
"buildInvocationID": "yirbp1aosi1vqjmi3z6bc75nb",
"buildStartedOn": "2022-12-08T11:48:59.466513707Z",
"buildFinishedOn": "2022-12-08T11:49:01.256820297Z",
"reproducible": false,
"completeness": {
"parameters": true,
"environment": true,
"materials": false
},
"https://mobyproject.org/buildkit@v1#metadata": {}
}
}
}
```

For a similar build, but with `mode=max`:

```json
{
"_type": "https://in-toto.io/Statement/v0.1",
"predicateType": "https://slsa.dev/provenance/v0.2",
"subject": [
{
"name": "pkg:docker/<registry>/<image>@<tag/digest>?platform=<platform>",
"digest": {
"sha256": "e8275b2b76280af67e26f068e5d585eb905f8dfd2f1918b3229db98133cb4862"
}
}
],
"predicate": {
"builder": {
"id": ""
},
"buildType": "https://mobyproject.org/buildkit@v1",
"materials": [
{
"uri": "pkg:docker/alpine@latest?platform=linux%2Famd64",
"digest": {
"sha256": "8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4"
}
}
],
"invocation": {
"configSource": {
"entryPoint": "Dockerfile"
},
"parameters": {
"frontend": "dockerfile.v0",
"args": {},
"locals": [
{
"name": "context"
},
{
"name": "dockerfile"
}
]
},
"environment": {
"platform": "linux/amd64"
}
},
"buildConfig": {
"llbDefinition": [
{
"id": "step0",
"op": {
"Op": {
"source": {
"identifier": "docker-image://docker.io/library/alpine:latest@sha256:8914eb54f968791faf6a8638949e480fef81e697984fba772b3976835194c6d4"
}
},
"platform": {
"Architecture": "amd64",
"OS": "linux"
},
"constraints": {}
}
},
{
"id": "step1",
"op": {
"Op": null
},
"inputs": [
"step0:0"
]
}
]
},
"metadata": {
"buildInvocationID": "46ue2x93k3xj5l463dektwldw",
"buildStartedOn": "2022-12-08T11:50:54.953375437Z",
"buildFinishedOn": "2022-12-08T11:50:55.447841328Z",
"reproducible": false,
"completeness": {
"parameters": true,
"environment": true,
"materials": false
},
"https://mobyproject.org/buildkit@v1#metadata": {
"source": {
"locations": {
"step0": {
"locations": [
{
"ranges": [
{
"start": {
"line": 1
},
"end": {
"line": 1
}
}
]
}
]
}
},
"infos": [
{
"filename": "Dockerfile",
"data": "RlJPTSBhbHBpbmU6bGF0ZXN0Cg==",
"llbDefinition": [
{
"id": "step0",
"op": {
"Op": {
"source": {
"identifier": "local://dockerfile",
"attrs": {
"local.differ": "none",
"local.followpaths": "[\"Dockerfile\",\"Dockerfile.dockerignore\",\"dockerfile\"]",
"local.session": "q2jnwdkas0i0iu4knchd92jaz",
"local.sharedkeyhint": "dockerfile"
}
}
},
"constraints": {}
}
},
{
"id": "step1",
"op": {
"Op": null
},
"inputs": [
"step0:0"
]
}
]
}
]
},
"layers": {
"step0:0": [
[
{
"mediaType": "application/vnd.oci.image.layer.v1.tar+gzip",
"digest": "sha256:c158987b05517b6f2c5913f3acef1f2182a32345a304fe357e3ace5fadcad715",
"size": 3370706
}
]
]
}
}
}
}
}
```

0 comments on commit c35741d

Please sign in to comment.