mirror of https://github.com/docker/docs.git
build: add attestation docs (#16358)
Signed-off-by: David Karlsson <david.karlsson@docker.com>
This commit is contained in:
parent
e9cbddad67
commit
cc0021f9bc
|
@ -1,6 +1,7 @@
|
||||||
ARM
|
ARM
|
||||||
AWS
|
AWS
|
||||||
Amazon
|
Amazon
|
||||||
|
Anchore
|
||||||
Apple
|
Apple
|
||||||
Artifactory
|
Artifactory
|
||||||
Azure( Blob Storage)?
|
Azure( Blob Storage)?
|
||||||
|
@ -43,7 +44,10 @@ QEMU
|
||||||
RHEL
|
RHEL
|
||||||
Raspbian
|
Raspbian
|
||||||
S3
|
S3
|
||||||
|
SBOMs?
|
||||||
SLES
|
SLES
|
||||||
|
SLSA
|
||||||
|
SPDX
|
||||||
SQLite
|
SQLite
|
||||||
Slack
|
Slack
|
||||||
Snyk
|
Snyk
|
||||||
|
|
|
@ -214,3 +214,9 @@ fetch-remote:
|
||||||
- dest: "build/buildkit/toml-configuration.md"
|
- dest: "build/buildkit/toml-configuration.md"
|
||||||
src:
|
src:
|
||||||
- "docs/buildkitd.toml.md"
|
- "docs/buildkitd.toml.md"
|
||||||
|
- dest: "build/attestations/slsa-definitions.md"
|
||||||
|
src:
|
||||||
|
- "docs/attestations/slsa-definitions.md"
|
||||||
|
- dest: "build/attestations/attestation-storage.md"
|
||||||
|
src:
|
||||||
|
- "docs/attestations/attestation-storage.md"
|
||||||
|
|
|
@ -1643,6 +1643,18 @@ manuals:
|
||||||
title: Build contexts and linking targets
|
title: Build contexts and linking targets
|
||||||
- path: /build/bake/compose-file/
|
- path: /build/bake/compose-file/
|
||||||
title: Building from Compose file
|
title: Building from Compose file
|
||||||
|
- sectiontitle: Attestations
|
||||||
|
section:
|
||||||
|
- path: /build/attestations/
|
||||||
|
title: Overview
|
||||||
|
- path: /build/attestations/sbom/
|
||||||
|
title: SBOM
|
||||||
|
- path: /build/attestations/slsa-provenance/
|
||||||
|
title: Provenance
|
||||||
|
- path: /build/attestations/slsa-definitions/
|
||||||
|
title: SLSA definitions
|
||||||
|
- path: /build/attestations/attestation-storage/
|
||||||
|
title: Attestation storage
|
||||||
- sectiontitle: BuildKit
|
- sectiontitle: BuildKit
|
||||||
section:
|
section:
|
||||||
- path: /build/buildkit/
|
- path: /build/buildkit/
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
> This feature is supported in BuildKit version `{{ include.buildkit_v }}`
|
||||||
|
> and Buildx version `{{ include.buildx_v }}`.
|
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
title: Attestation storage
|
||||||
|
description: "How SBOM and provenance attestations are stored for images."
|
||||||
|
keywords: build, attestations, sbom, provenance, storage, manifest
|
||||||
|
fetch_remote:
|
||||||
|
line_start: 2
|
||||||
|
line_end: -1
|
||||||
|
---
|
|
@ -0,0 +1,149 @@
|
||||||
|
---
|
||||||
|
title: Build attestations
|
||||||
|
keywords: build, attestations, sbom, provenance
|
||||||
|
description: >
|
||||||
|
Introduction to SBOM and provenance attestations with Docker Build; what they
|
||||||
|
are and why they exist
|
||||||
|
---
|
||||||
|
|
||||||
|
{% include build-feature-state.md buildkit_v=">=0.11" buildx_v=">=0.10" %}
|
||||||
|
|
||||||
|
Build attestations describe how an image was built, and what it contains. The
|
||||||
|
attestations are created at build-time by BuildKit, and become attached to the
|
||||||
|
final image as metadata.
|
||||||
|
|
||||||
|
The purpose of attestations is to make it possible to inspect an image and see
|
||||||
|
where it comes from, who created it and how, and what it contains. This enables
|
||||||
|
you to make informed decisions about how an image impacts the supply chain security
|
||||||
|
of your application. It also enables the use of policy engines for validating
|
||||||
|
images based on policy rules you've defined.
|
||||||
|
|
||||||
|
Two types of build annotations are available:
|
||||||
|
|
||||||
|
- Software Bill of Material (SBOM): list of software artifacts that an image
|
||||||
|
contains, or that were used to build the image.
|
||||||
|
- Provenance: how an image was built.
|
||||||
|
|
||||||
|
## Purpose of attestations
|
||||||
|
|
||||||
|
The use of open source and third-party packages is more widespread than ever
|
||||||
|
before. Developers share and reuse code because it helps increase productivity,
|
||||||
|
allowing teams to create better products, faster.
|
||||||
|
|
||||||
|
Importing and using code created elsewhere without vetting it introduces a
|
||||||
|
severe security risk. Even if you do review the software that you consume, new
|
||||||
|
zero-day vulnerabilities are frequently discovered, requiring development teams
|
||||||
|
take action to remediate them.
|
||||||
|
|
||||||
|
Build attestations make it easier to see the contents of an image, and where it
|
||||||
|
comes from. Use attestations to analyze and decide whether to use an image, or
|
||||||
|
to see if images you are already using are exposed to vulnerabilities.
|
||||||
|
|
||||||
|
## Creating attestations
|
||||||
|
|
||||||
|
When you build an image with `docker buildx build`, you can add attestation
|
||||||
|
records to the resulting image using the `--provenance` and `--sbom` options.
|
||||||
|
You can opt in to add either the SBOM or provenance attestation type, or both.
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ docker buildx build --sbom=true --provenance=true .
|
||||||
|
```
|
||||||
|
|
||||||
|
BuildKit generates the attestations when building the image. The attestation
|
||||||
|
records are wrapped in the in-toto JSON format and attached it to the image
|
||||||
|
index in a manifest for the final image.
|
||||||
|
|
||||||
|
## Storage
|
||||||
|
|
||||||
|
<!-- prettier-ignore -->
|
||||||
|
BuildKit produces attestations in the
|
||||||
|
[in-toto format](https://github.com/in-toto/attestation){: target="blank" rel="noopener" class="\_" },
|
||||||
|
as defined by the
|
||||||
|
[in-toto framework](https://in-toto.io/){: target="blank" rel="noopener" class="\_" },
|
||||||
|
a standard supported by the Linux Foundation.
|
||||||
|
|
||||||
|
Attestations attach to images as a manifest in the image index. The data records
|
||||||
|
of the attestations are stored as JSON blobs.
|
||||||
|
|
||||||
|
Because attestations attach to images as a manifest, it means that you can
|
||||||
|
inspect the attestations for any image in a registry without having to pull the
|
||||||
|
whole image.
|
||||||
|
|
||||||
|
All BuildKit exporters support attestations. The `local` and `tar` can't save
|
||||||
|
the attestations to an image manifest, since it's outputting a directory of
|
||||||
|
files or a tarball, not an image. Instead, these exporters write the
|
||||||
|
attestations to one or more JSON files in the root directory of the export.
|
||||||
|
|
||||||
|
The following example shows a truncated in-toto JSON representation of an SBOM
|
||||||
|
attestation.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"_type": "https://in-toto.io/Statement/v0.1",
|
||||||
|
"predicateType": "https://spdx.dev/Document",
|
||||||
|
"subject": [
|
||||||
|
{
|
||||||
|
"name": "pkg:docker/<registry>/<image>@<tag/digest>?platform=<platform>",
|
||||||
|
"digest": {
|
||||||
|
"sha256": "e8275b2b76280af67e26f068e5d585eb905f8dfd2f1918b3229db98133cb4862"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"predicate": {
|
||||||
|
"SPDXID": "SPDXRef-DOCUMENT",
|
||||||
|
"creationInfo": {
|
||||||
|
"created": "2022-12-15T11:47:54.546747383Z",
|
||||||
|
"creators": ["Organization: Anchore, Inc", "Tool: syft-v0.60.3"],
|
||||||
|
"licenseListVersion": "3.18"
|
||||||
|
},
|
||||||
|
"dataLicense": "CC0-1.0",
|
||||||
|
"documentNamespace": "https://anchore.com/syft/dir/run/src/core-da0f600b-7f0a-4de0-8432-f83703e6bc4f",
|
||||||
|
"name": "/run/src/core",
|
||||||
|
// list of files that the image contains, e.g.:
|
||||||
|
"files": [
|
||||||
|
{
|
||||||
|
"SPDXID": "SPDXRef-1ac501c94e2f9f81",
|
||||||
|
"comment": "layerID: sha256:9b18e9b68314027565b90ff6189d65942c0f7986da80df008b8431276885218e",
|
||||||
|
"fileName": "/bin/busybox",
|
||||||
|
"licenseConcluded": "NOASSERTION"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
// list of packages that were identified for this image:
|
||||||
|
"packages": [
|
||||||
|
{
|
||||||
|
"name": "busybox",
|
||||||
|
"originator": "Person: Sören Tempel <soeren+alpine@soeren-tempel.net>",
|
||||||
|
"sourceInfo": "acquired package info from APK DB: lib/apk/db/installed",
|
||||||
|
"versionInfo": "1.35.0-r17",
|
||||||
|
"SPDXID": "SPDXRef-980737451f148c56",
|
||||||
|
"description": "Size optimized toolbox of many common UNIX utilities",
|
||||||
|
"downloadLocation": "https://busybox.net/",
|
||||||
|
"licenseConcluded": "GPL-2.0-only",
|
||||||
|
"licenseDeclared": "GPL-2.0-only"
|
||||||
|
// ...
|
||||||
|
}
|
||||||
|
],
|
||||||
|
// files-packages relationship
|
||||||
|
"relationships": [
|
||||||
|
{
|
||||||
|
"relatedSpdxElement": "SPDXRef-1ac501c94e2f9f81",
|
||||||
|
"relationshipType": "CONTAINS",
|
||||||
|
"spdxElementId": "SPDXRef-980737451f148c56"
|
||||||
|
},
|
||||||
|
...
|
||||||
|
],
|
||||||
|
"spdxVersion": "SPDX-2.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
<!-- prettier-ignore -->
|
||||||
|
To deep-dive into the specifics about how attestations are stored, see
|
||||||
|
[Image Attestation Storage (BuildKit)](https://github.com/moby/buildkit/blob/master/docs/attestation-storage.md){: target="blank" rel="noopener" class="_"}.
|
||||||
|
|
||||||
|
## What's next
|
||||||
|
|
||||||
|
Learn more about the available attestation types and how to use them:
|
||||||
|
|
||||||
|
- [Provenance](slsa-provenance.md)
|
||||||
|
- [SBOM](sbom.md)
|
|
@ -0,0 +1,290 @@
|
||||||
|
---
|
||||||
|
title: SBOM attestations
|
||||||
|
keywords: build, attestations, sbom
|
||||||
|
description: SBOM build attestations
|
||||||
|
---
|
||||||
|
|
||||||
|
{% include build-feature-state.md buildkit_v=">=0.11" buildx_v=">=0.10" %}
|
||||||
|
|
||||||
|
Software Bill of Materials (SBOM) attestations describe what software artifacts
|
||||||
|
an image contains, and artifacts used to create the image. Metadata included in
|
||||||
|
an SBOM for describing software artifacts may include:
|
||||||
|
|
||||||
|
- Name of the artifact
|
||||||
|
- Version
|
||||||
|
- License type
|
||||||
|
- Authors
|
||||||
|
- Unique package identifier
|
||||||
|
|
||||||
|
There are benefits to indexing contents of an image during the build, as opposed
|
||||||
|
to scanning a final image. When scanning happens as part of the build, you're
|
||||||
|
able to detect software you use to build the image, that may not show up in the
|
||||||
|
final image.
|
||||||
|
|
||||||
|
The SBOMs generated by BuildKit follow the SPDX standard. SBOMs attach to the
|
||||||
|
final image as a JSON-encoded SPDX document, using the format defined by the
|
||||||
|
[in-toto SPDX predicate](https://github.com/in-toto/attestation/blob/main/spec/predicates/spdx.md){:
|
||||||
|
target="blank" rel="noopener" }.
|
||||||
|
|
||||||
|
## Create SBOM attestations
|
||||||
|
|
||||||
|
To create a provenance attestation, pass the `--attest type=sbom` option to the
|
||||||
|
`docker buildx build` command:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ docker buildx build --tag <namespace>/<image>:<version> \
|
||||||
|
--attest type=sbom --push .
|
||||||
|
```
|
||||||
|
|
||||||
|
Alternatively, you can use the shorthand `--sbom=true` option instead of `--attest type=sbom`.
|
||||||
|
|
||||||
|
## Verify SBOM attestations
|
||||||
|
|
||||||
|
Always validate the generated SBOM for your image before you push your image to a registry.
|
||||||
|
|
||||||
|
To validate, you can build the image using the `local` exporter.
|
||||||
|
Building with the `local` exporter saves the build result to your local filesystem instead of creating an image.
|
||||||
|
Attestations are written to a JSON file in the root directory of your export.
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ docker buildx build \
|
||||||
|
--sbom=true \
|
||||||
|
--output type=local,dest=out .
|
||||||
|
```
|
||||||
|
|
||||||
|
The SBOM file appears in the root directory of the output, named `sbom.spdx.json`:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ ls -1 ./out | grep sbom
|
||||||
|
sbom.spdx.json
|
||||||
|
```
|
||||||
|
|
||||||
|
## Arguments
|
||||||
|
|
||||||
|
By default, BuildKit only scans the final stage of an image. The resulting SBOM
|
||||||
|
doesn't include build-time dependencies installed in earlier stages, or that
|
||||||
|
exist in the build context. This may cause you to overlook vulnerabilities in
|
||||||
|
those dependencies, which could impact the security of your final build
|
||||||
|
artifacts.
|
||||||
|
|
||||||
|
For instance, you might use [multi-stage builds](../building/multi-stage.md),
|
||||||
|
with a `FROM scratch` stanza for your final stage to achieve a smaller image size.
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
FROM alpine AS build
|
||||||
|
# build the software ...
|
||||||
|
|
||||||
|
FROM scratch
|
||||||
|
COPY --from=build /path/to/bin /bin
|
||||||
|
ENTRYPOINT [ "/bin" ]
|
||||||
|
```
|
||||||
|
|
||||||
|
Scanning the resulting image built using this Dockerfile example would not
|
||||||
|
reveal build-time dependencies used in the `build` stage.
|
||||||
|
|
||||||
|
To include build-time dependencies from your Dockerfile, you can set the build
|
||||||
|
arguments `BUILDKIT_SBOM_SCAN_CONTEXT` and `BUILDKIT_SBOM_SCAN_STAGE`. This
|
||||||
|
expands the scanning scope to include the build context and additional stages.
|
||||||
|
|
||||||
|
You can set the arguments as global arguments (after declaring the Dockerfile
|
||||||
|
syntax directive, before the first `FROM` command) or individually in each
|
||||||
|
stage. If set globally, the value propagates to each stage in the Dockerfile.
|
||||||
|
|
||||||
|
The `BUILDKIT_SBOM_SCAN_CONTEXT` and `BUILDKIT_SBOM_SCAN_STAGE` build arguments
|
||||||
|
are special values. You can't perform variable substitution using these
|
||||||
|
arguments, and you can't set them using environment variables from within the
|
||||||
|
Dockerfile. The only way to set these values is using explicit `ARG` command in
|
||||||
|
the Dockerfile.
|
||||||
|
|
||||||
|
### Scan build context
|
||||||
|
|
||||||
|
To scan the build context, set the `BUILDKIT_SBOM_SCAN_CONTEXT` to `true`.
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
# syntax=docker/dockerfile:1
|
||||||
|
ARG BUILDKIT_SBOM_SCAN_CONTEXT=true
|
||||||
|
FROM alpine AS build
|
||||||
|
# ...
|
||||||
|
```
|
||||||
|
|
||||||
|
You can use the `--build-arg` CLI option to override the value specified in the
|
||||||
|
Dockerfile.
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ docker buildx build --tag <image>:<version> \
|
||||||
|
--attest type=sbom \
|
||||||
|
--build-arg BUILDKIT_SBOM_SCAN_CONTEXT=false .
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that passing the option as a CLI argument only, without having declared it
|
||||||
|
using `ARG` in the Dockerfile, will have no effect. You must specify the `ARG`
|
||||||
|
in the Dockerfile, whereby you can override the context scanning behavior using
|
||||||
|
`--build-arg`.
|
||||||
|
|
||||||
|
### Scan stages
|
||||||
|
|
||||||
|
To scan more than just the final stage, set the `BUILDKIT_SBOM_SCAN_STAGE`
|
||||||
|
argument to true, either globally or in the specific stages that you want to
|
||||||
|
scan. The following table demonstrates the different possible settings for this
|
||||||
|
argument.
|
||||||
|
|
||||||
|
| Value | Description |
|
||||||
|
| ----------------------------------- | ------------------------------------------------------ |
|
||||||
|
| `BUILDKIT_SBOM_SCAN_STAGE=true` | Enables scanning for the current stage |
|
||||||
|
| `BUILDKIT_SBOM_SCAN_STAGE=false` | Disables scanning for the current stage |
|
||||||
|
| `BUILDKIT_SBOM_SCAN_STAGE=base,bin` | Enables scanning for the stages named `base` and `bin` |
|
||||||
|
|
||||||
|
Only stages that are built will be scanned. Stages that aren't dependencies of
|
||||||
|
the target stage won't be built, or scanned.
|
||||||
|
|
||||||
|
The following Dockerfile example uses multi-stage builds to build a static website with
|
||||||
|
[Hugo](https://gohugo.io/){: target="blank" rel="noopener" class="_"}.
|
||||||
|
|
||||||
|
```dockerfile
|
||||||
|
# syntax=docker/dockerfile:1
|
||||||
|
FROM alpine as hugo
|
||||||
|
ARG BUILDKIT_SBOM_SCAN_STAGE=true
|
||||||
|
WORKDIR /src
|
||||||
|
COPY <<config.yml ./
|
||||||
|
title: My Hugo website
|
||||||
|
config.yml
|
||||||
|
RUN apk add --upgrade hugo && hugo
|
||||||
|
|
||||||
|
FROM scratch
|
||||||
|
COPY --from=hugo /src/public /
|
||||||
|
```
|
||||||
|
|
||||||
|
Setting `ARG BUILDKIT_SBOM_SCAN_STAGE=true` in the `hugo` stage ensures that the final SBOM
|
||||||
|
includes the information that Alpine Linux and Hugo were used to create the website.
|
||||||
|
|
||||||
|
Building this image with the `local` exporter creates two JSON files:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ docker buildx build \
|
||||||
|
--sbom=true \
|
||||||
|
--output type=local,dest=out .
|
||||||
|
$ ls -1 out | grep sbom
|
||||||
|
sbom-hugo.spdx.json
|
||||||
|
sbom.spdx.json
|
||||||
|
```
|
||||||
|
|
||||||
|
## SBOM attestation example
|
||||||
|
|
||||||
|
The following JSON example shows what an SBOM attestation might look like.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"_type": "https://in-toto.io/Statement/v0.1",
|
||||||
|
"predicateType": "https://spdx.dev/Document",
|
||||||
|
"subject": [
|
||||||
|
{
|
||||||
|
"name": "pkg:docker/<registry>/<image>@<tag/digest>?platform=<platform>",
|
||||||
|
"digest": {
|
||||||
|
"sha256": "e8275b2b76280af67e26f068e5d585eb905f8dfd2f1918b3229db98133cb4862"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"predicate": {
|
||||||
|
"SPDXID": "SPDXRef-DOCUMENT",
|
||||||
|
"creationInfo": {
|
||||||
|
"created": "2022-12-16T15:27:25.517047753Z",
|
||||||
|
"creators": ["Organization: Anchore, Inc", "Tool: syft-v0.60.3"],
|
||||||
|
"licenseListVersion": "3.18"
|
||||||
|
},
|
||||||
|
"dataLicense": "CC0-1.0",
|
||||||
|
"documentNamespace": "https://anchore.com/syft/dir/run/src/core/sbom-cba61a72-fa95-4b60-b63f-03169eac25ca",
|
||||||
|
"name": "/run/src/core/sbom",
|
||||||
|
"packages": [
|
||||||
|
{
|
||||||
|
"SPDXID": "SPDXRef-b074348b8f56ea64",
|
||||||
|
"downloadLocation": "NOASSERTION",
|
||||||
|
"externalRefs": [
|
||||||
|
{
|
||||||
|
"referenceCategory": "SECURITY",
|
||||||
|
"referenceLocator": "cpe:2.3:a:org:repo:\\(devel\\):*:*:*:*:*:*:*",
|
||||||
|
"referenceType": "cpe23Type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"referenceCategory": "PACKAGE_MANAGER",
|
||||||
|
"referenceLocator": "pkg:golang/github.com/org/repo@(devel)",
|
||||||
|
"referenceType": "purl"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"filesAnalyzed": false,
|
||||||
|
"licenseConcluded": "NONE",
|
||||||
|
"licenseDeclared": "NONE",
|
||||||
|
"name": "github.com/org/repo",
|
||||||
|
"sourceInfo": "acquired package info from go module information: bin/server",
|
||||||
|
"versionInfo": "(devel)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SPDXID": "SPDXRef-1b96f57f8fed62d8",
|
||||||
|
"checksums": [
|
||||||
|
{
|
||||||
|
"algorithm": "SHA256",
|
||||||
|
"checksumValue": "0c13f1f3c1636491f716c2027c301f21f9dbed7c4a2185461ba94e3e58443408"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"downloadLocation": "NOASSERTION",
|
||||||
|
"externalRefs": [
|
||||||
|
{
|
||||||
|
"referenceCategory": "SECURITY",
|
||||||
|
"referenceLocator": "cpe:2.3:a:go-chi:chi\\/v5:v5.0.0:*:*:*:*:*:*:*",
|
||||||
|
"referenceType": "cpe23Type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"referenceCategory": "SECURITY",
|
||||||
|
"referenceLocator": "cpe:2.3:a:go_chi:chi\\/v5:v5.0.0:*:*:*:*:*:*:*",
|
||||||
|
"referenceType": "cpe23Type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"referenceCategory": "SECURITY",
|
||||||
|
"referenceLocator": "cpe:2.3:a:go:chi\\/v5:v5.0.0:*:*:*:*:*:*:*",
|
||||||
|
"referenceType": "cpe23Type"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"referenceCategory": "PACKAGE_MANAGER",
|
||||||
|
"referenceLocator": "pkg:golang/github.com/go-chi/chi/v5@v5.0.0",
|
||||||
|
"referenceType": "purl"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"filesAnalyzed": false,
|
||||||
|
"licenseConcluded": "NONE",
|
||||||
|
"licenseDeclared": "NONE",
|
||||||
|
"name": "github.com/go-chi/chi/v5",
|
||||||
|
"sourceInfo": "acquired package info from go module information: bin/server",
|
||||||
|
"versionInfo": "v5.0.0"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"relationships": [
|
||||||
|
{
|
||||||
|
"relatedSpdxElement": "SPDXRef-1b96f57f8fed62d8",
|
||||||
|
"relationshipType": "CONTAINS",
|
||||||
|
"spdxElementId": "SPDXRef-043f7360d3c66bc31ba45388f16423aa58693289126421b71d884145f8837fe1"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"relatedSpdxElement": "SPDXRef-b074348b8f56ea64",
|
||||||
|
"relationshipType": "CONTAINS",
|
||||||
|
"spdxElementId": "SPDXRef-043f7360d3c66bc31ba45388f16423aa58693289126421b71d884145f8837fe1"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"spdxVersion": "SPDX-2.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## SBOM generator
|
||||||
|
|
||||||
|
BuildKit generates the SBOM using a scanner plugin. By default, it uses is the
|
||||||
|
[BuildKit Syft scanner](https://github.com/docker/buildkit-syft-scanner){: target="blank" rel="noopener" }
|
||||||
|
plugin. This plugin is built on top of
|
||||||
|
[Anchore's Syft](https://github.com/anchore/syft){: target="blank" rel="noopener" },
|
||||||
|
an open source tool for generating an SBOM.
|
||||||
|
|
||||||
|
You can select a different plugin to use with the `generator` option, specifying
|
||||||
|
an image that implements the
|
||||||
|
[BuildKit SBOM scanner protocol](https://github.com/moby/buildkit/blob/master/docs/sbom-protocol.md){ :target="blank" rel="noopener" }.
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ docker buildx build --attest type=sbom,generator=<image> .
|
||||||
|
```
|
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
title: SLSA definitions
|
||||||
|
description: "How BuildKit populates the fields in the SLSA provenance attestations."
|
||||||
|
keywords: build, attestations, provenance, slsa, definitions, reference
|
||||||
|
fetch_remote:
|
||||||
|
line_start: 2
|
||||||
|
line_end: -1
|
||||||
|
---
|
|
@ -0,0 +1,318 @@
|
||||||
|
---
|
||||||
|
title: Provenance attestations
|
||||||
|
keywords: build, attestations, provenance, slsa
|
||||||
|
description: Provenance build attestations
|
||||||
|
---
|
||||||
|
|
||||||
|
{% include build-feature-state.md buildkit_v=">=0.11" buildx_v=">=0.10" %}
|
||||||
|
|
||||||
|
The provenance attestations include facts about the build process, including
|
||||||
|
details such as:
|
||||||
|
|
||||||
|
- Build timestamps
|
||||||
|
- Build parameters and environment
|
||||||
|
- Version control metadata
|
||||||
|
- Source code details
|
||||||
|
- Materials (files, scripts) consumed during the build
|
||||||
|
|
||||||
|
Provenance attestations follow the
|
||||||
|
[SLSA provenance schema, version 0.2](https://slsa.dev/provenance/v0.2#schema).
|
||||||
|
|
||||||
|
For more information about how BuildKit populates these provenance properties, refer to
|
||||||
|
[SLSA definitions](slsa-definitions.md).
|
||||||
|
|
||||||
|
## Create provenance attestations
|
||||||
|
|
||||||
|
To create a provenance attestation, pass the `--attest type=provenance` option
|
||||||
|
to the `docker buildx build` command:
|
||||||
|
|
||||||
|
```console
|
||||||
|
$ docker buildx build --tag <namespace>/<image>:<version> \
|
||||||
|
--attest type=provenance,mode=[min,max] .
|
||||||
|
```
|
||||||
|
|
||||||
|
Alternatively, you can use the shorthand `--provenance=true` option instead of `--attest type=provenance`.
|
||||||
|
To specify the `mode` parameter using the shorthand option, use: `--provenance=mode=max`.
|
||||||
|
|
||||||
|
## Mode
|
||||||
|
|
||||||
|
You can use the `mode` parameter to define the level of detail to be included in
|
||||||
|
the provenance attestation. Supported values are `mode=min`, and `mode=max`
|
||||||
|
(default).
|
||||||
|
|
||||||
|
### Min
|
||||||
|
|
||||||
|
In `min` mode, the provenance attestations include a minimal set of information,
|
||||||
|
such as:
|
||||||
|
|
||||||
|
- Build timestamps
|
||||||
|
- The frontend used
|
||||||
|
- Build materials
|
||||||
|
- Source repository and revision
|
||||||
|
- Build platform
|
||||||
|
- Reproducibility
|
||||||
|
|
||||||
|
Values of build arguments, the identities of secrets, and rich layer metadata is
|
||||||
|
not included `mode=min`. The `min`-level provenance is safe to use for all
|
||||||
|
builds, as it doesn't leak information from any part of the build environment.
|
||||||
|
|
||||||
|
The following JSON example shows the information included in a provenance
|
||||||
|
attestations created using the `min` mode:
|
||||||
|
|
||||||
|
```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/docker/dockerfile@1",
|
||||||
|
"digest": {
|
||||||
|
"sha256": "9ba7531bd80fb0a858632727cf7a112fbfd19b17e94c4e84ced81e24ef1a0dbc"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uri": "pkg:docker/golang@1.19.4-alpine?platform=linux%2Farm64",
|
||||||
|
"digest": {
|
||||||
|
"sha256": "a9b24b67dc83b3383d22a14941c2b2b2ca6a103d805cac6820fd1355943beaf1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"invocation": {
|
||||||
|
"configSource": { "entryPoint": "Dockerfile" },
|
||||||
|
"parameters": {
|
||||||
|
"frontend": "gateway.v0",
|
||||||
|
"args": {
|
||||||
|
"cmdline": "docker/dockerfile:1",
|
||||||
|
"source": "docker/dockerfile:1",
|
||||||
|
"target": "binaries"
|
||||||
|
},
|
||||||
|
"locals": [{ "name": "context" }, { "name": "dockerfile" }]
|
||||||
|
},
|
||||||
|
"environment": { "platform": "linux/arm64" }
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"buildInvocationID": "c4a87v0sxhliuewig10gnsb6v",
|
||||||
|
"buildStartedOn": "2022-12-16T08:26:28.651359794Z",
|
||||||
|
"buildFinishedOn": "2022-12-16T08:26:29.625483253Z",
|
||||||
|
"reproducible": false,
|
||||||
|
"completeness": {
|
||||||
|
"parameters": true,
|
||||||
|
"environment": true,
|
||||||
|
"materials": false
|
||||||
|
},
|
||||||
|
"https://mobyproject.org/buildkit@v1#metadata": {
|
||||||
|
"vcs": {
|
||||||
|
"revision": "a9ba846486420e07d30db1107411ac3697ecab68",
|
||||||
|
"source": "git@github.com:<org>/<repo>.git"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### Max
|
||||||
|
|
||||||
|
The `max` mode includes all of the information included in the `min` mode, as
|
||||||
|
well as:
|
||||||
|
|
||||||
|
- The LLB definition of the build. These show the exact steps taken to produce
|
||||||
|
the image.
|
||||||
|
- Information about the Dockerfile, including a full base64-encoded version of
|
||||||
|
the file.
|
||||||
|
- Source maps describing the relationship between build steps and image layers.
|
||||||
|
|
||||||
|
When possible, you should prefer `mode=max` as it contains significantly more
|
||||||
|
detailed information for analysis. However, on some builds it may not be
|
||||||
|
appropriate, as it includes the values of
|
||||||
|
[build arguments](../../engine/reference/commandline/buildx_build.md#build-arg)
|
||||||
|
and metadata about secrets and SSH mounts. If you pass sensitive information
|
||||||
|
using build arguments, consider refactoring builds to pass secret values using
|
||||||
|
[build secrets](../../engine/reference/commandline/buildx_build.md#secret), to
|
||||||
|
prevent leaking of sensitive information.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
<!-- TODO: add a link to the definitions page, imported from moby/buildkit -->
|
||||||
|
|
||||||
|
The following example shows what a JSON representation of a provenance
|
||||||
|
attestation with `mode=max` looks like:
|
||||||
|
|
||||||
|
```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/docker/dockerfile@1",
|
||||||
|
"digest": {
|
||||||
|
"sha256": "9ba7531bd80fb0a858632727cf7a112fbfd19b17e94c4e84ced81e24ef1a0dbc"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"uri": "pkg:docker/golang@1.19.4-alpine?platform=linux%2Farm64",
|
||||||
|
"digest": {
|
||||||
|
"sha256": "a9b24b67dc83b3383d22a14941c2b2b2ca6a103d805cac6820fd1355943beaf1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"buildConfig": {
|
||||||
|
"llbDefinition": [
|
||||||
|
{
|
||||||
|
"id": "step4",
|
||||||
|
"op": {
|
||||||
|
"Op": {
|
||||||
|
"exec": {
|
||||||
|
"meta": {
|
||||||
|
"args": ["/bin/sh", "-c", "go mod download -x"],
|
||||||
|
"env": [
|
||||||
|
"PATH=/go/bin:/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
|
||||||
|
"GOLANG_VERSION=1.19.4",
|
||||||
|
"GOPATH=/go",
|
||||||
|
"CGO_ENABLED=0"
|
||||||
|
],
|
||||||
|
"cwd": "/src"
|
||||||
|
},
|
||||||
|
"mounts": [
|
||||||
|
{ "input": 0, "dest": "/", "output": 0 },
|
||||||
|
{
|
||||||
|
"input": -1,
|
||||||
|
"dest": "/go/pkg/mod",
|
||||||
|
"output": -1,
|
||||||
|
"mountType": 3,
|
||||||
|
"cacheOpt": { "ID": "//go/pkg/mod" }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"input": 1,
|
||||||
|
"selector": "/go.mod",
|
||||||
|
"dest": "/src/go.mod",
|
||||||
|
"output": -1,
|
||||||
|
"readonly": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"input": 1,
|
||||||
|
"selector": "/go.sum",
|
||||||
|
"dest": "/src/go.sum",
|
||||||
|
"output": -1,
|
||||||
|
"readonly": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"platform": { "Architecture": "arm64", "OS": "linux" },
|
||||||
|
"constraints": {}
|
||||||
|
},
|
||||||
|
"inputs": ["step3:0", "step1:0"]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"metadata": {
|
||||||
|
"buildInvocationID": "edf52vxjyf9b6o5qd7vgx0gru",
|
||||||
|
"buildStartedOn": "2022-12-15T15:38:13.391980297Z",
|
||||||
|
"buildFinishedOn": "2022-12-15T15:38:14.274565297Z",
|
||||||
|
"reproducible": false,
|
||||||
|
"completeness": {
|
||||||
|
"parameters": true,
|
||||||
|
"environment": true,
|
||||||
|
"materials": false
|
||||||
|
},
|
||||||
|
"https://mobyproject.org/buildkit@v1#metadata": {
|
||||||
|
"vcs": {
|
||||||
|
"revision": "a9ba846486420e07d30db1107411ac3697ecab68-dirty",
|
||||||
|
"source": "git@github.com:<org>/<repo>.git"
|
||||||
|
},
|
||||||
|
"source": {
|
||||||
|
"locations": {
|
||||||
|
"step4": {
|
||||||
|
"locations": [
|
||||||
|
{
|
||||||
|
"ranges": [
|
||||||
|
{ "start": { "line": 5 }, "end": { "line": 5 } },
|
||||||
|
{ "start": { "line": 6 }, "end": { "line": 6 } },
|
||||||
|
{ "start": { "line": 7 }, "end": { "line": 7 } },
|
||||||
|
{ "start": { "line": 8 }, "end": { "line": 8 } }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"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": "s4j58ngehdal1b5hn7msiqaqe",
|
||||||
|
"local.sharedkeyhint": "dockerfile"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"constraints": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{ "id": "step1", "op": { "Op": null }, "inputs": ["step0:0"] }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"layers": {
|
||||||
|
"step2:0": [
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
|
||||||
|
"digest": "sha256:261da4162673b93e5c0e7700a3718d40bcc086dbf24b1ec9b54bca0b82300626",
|
||||||
|
"size": 3259190
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
|
||||||
|
"digest": "sha256:bc729abf26b5aade3c4426d388b5ea6907fe357dec915ac323bb2fa592d6288f",
|
||||||
|
"size": 286218
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
|
||||||
|
"digest": "sha256:7f1d6579712341e8062db43195deb2d84f63b0f2d1ed7c3d2074891085ea1b56",
|
||||||
|
"size": 116878653
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"mediaType": "application/vnd.docker.image.rootfs.diff.tar.gzip",
|
||||||
|
"digest": "sha256:652874aefa1343799c619d092ab9280b25f96d97939d5d796437e7288f5599c9",
|
||||||
|
"size": 156
|
||||||
|
}
|
||||||
|
]
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
Loading…
Reference in New Issue