mirror of https://github.com/docker/docs.git
328 lines
11 KiB
Markdown
328 lines
11 KiB
Markdown
---
|
|
title: SBOM attestations
|
|
keywords: build, attestations, sbom, spdx, metadata, packages
|
|
description: |
|
|
SBOM build attestations describe the contents of your image,
|
|
and the packages used to build it.
|
|
---
|
|
|
|
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).
|
|
|
|
## 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/).
|
|
|
|
```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
|
|
```
|
|
|
|
## Inspecting SBOMs
|
|
|
|
To explore created SBOMs exported through the `image` exporter, you can use
|
|
[`imagetools inspect`](../../engine/reference/commandline/buildx_imagetools_inspect.md).
|
|
|
|
Using the `--format` option, you can specify a template for the output. All
|
|
SBOM-related data is available under the `.SBOM` attribute. For example, to get
|
|
the raw contents of an SBOM in SPDX format:
|
|
|
|
```console
|
|
$ docker buildx imagetools inspect <namespace>/<image>:<version> \
|
|
--format "{{ json .SBOM.SPDX }}"
|
|
{
|
|
"SPDXID": "SPDXRef-DOCUMENT",
|
|
...
|
|
}
|
|
```
|
|
|
|
You can also construct more complex expressions using the full functionality
|
|
of Go templates. For example, you can list all the installed packages and their
|
|
version identifiers:
|
|
|
|
```console
|
|
$ docker buildx imagetools inspect <namespace>/<image>:<version> \
|
|
--format "{{ range .SBOM.SPDX.packages }}{{ .name }}@{{ .versionInfo }}{{ println }}{{ end }}"
|
|
adduser@3.118ubuntu2
|
|
apt@2.0.9
|
|
base-files@11ubuntu5.6
|
|
base-passwd@3.5.47
|
|
...
|
|
```
|
|
|
|
## 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)
|
|
plugin. This plugin is built on top of
|
|
[Anchore's Syft](https://github.com/anchore/syft),
|
|
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/attestations/sbom-protocol.md).
|
|
|
|
```console
|
|
$ docker buildx build --attest type=sbom,generator=<image> .
|
|
```
|
|
|
|
> **Tip**
|
|
>
|
|
> The Docker Scout SBOM generator is available. See
|
|
> [Docker Scout SBOMs](../../scout/sbom.md#attest).
|
|
{ .tip }
|
|
|
|
## 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"
|
|
}
|
|
}
|
|
```
|