mirror of
https://github.com/moby/buildkit.git
synced 2026-08-09 01:01:08 +00:00
docs: add user-facing attestation docs
Signed-off-by: Justin Chadwell <me@jedevc.com>
This commit is contained in:
198
docs/sbom.md
Normal file
198
docs/sbom.md
Normal file
@@ -0,0 +1,198 @@
|
||||
# SBOMs
|
||||
|
||||
BuildKit supports automatic creation of [SBOMs](https://en.wikipedia.org/wiki/Software_supply_chain)
|
||||
to record the software components that make up the final image. These consist
|
||||
of a list of software packages and the files that they own.
|
||||
|
||||
They also usually contain metadata about each component, such as software
|
||||
licenses, authors, and unique package identifiers which can be used for
|
||||
vulnerability scanning.
|
||||
|
||||
All SBOMs generated by BuildKit are wrapped inside [in-toto attestations](https://github.com/in-toto/attestation)
|
||||
in the [SPDX](https://spdx.dev) JSON format. They can be generated using
|
||||
generator images that follow the [SBOM generator protocol](./sbom-protocol.md).
|
||||
|
||||
When the final output format is a container image, these SBOMs are attached
|
||||
using the [attestation storage](./attestation-storage.md).
|
||||
|
||||
To build an image with an attached SBOM (derived using the builtin default scanner,
|
||||
[docker/buildkit-syft-scanner](https://github.com/docker/buildkit-syft-scanner)),
|
||||
use the `attest:sbom` option:
|
||||
|
||||
```bash
|
||||
buildctl build \
|
||||
--frontend=dockerfile.v0 \
|
||||
--local context=. \
|
||||
--local dockerfile=. \
|
||||
--opt attest:sbom=
|
||||
```
|
||||
|
||||
You can also specify a custom SBOM generator image:
|
||||
|
||||
```bash
|
||||
buildctl build \
|
||||
--frontend=dockerfile.v0 \
|
||||
--local context=. \
|
||||
--local dockerfile=. \
|
||||
--opt attest:sbom=generator=<registry>/<image>
|
||||
```
|
||||
|
||||
## Dockerfile configuration
|
||||
|
||||
By default, only the final build result is scanned - because of this, the
|
||||
resulting SBOM will not include build-time dependencies that may be installed
|
||||
in separate stages or the build context. This could cause you to miss
|
||||
vulnerabilities in those dependencies, which could impact the security of your
|
||||
final build artifacts.
|
||||
|
||||
To include these build-time dependencies from your Dockerfile, you can set the
|
||||
build arguments `BUILDKIT_SBOM_SCAN_CONTEXT` and `BUILDKIT_SBOM_SCAN_STAGE` to
|
||||
additionally scan the build context and other build stages respectively. These
|
||||
build arguments are special values, and cannot be used for variable
|
||||
substitutions or as environment variables from within the Dockerfile, as they
|
||||
exist solely to change the behavior of the scanner.
|
||||
|
||||
Both arguments can be set as global meta arguments (before a `FROM`) or can be
|
||||
individually set in each stage. If set globally, the value is propagated for
|
||||
each stage in the Dockerfile. They can take the following values:
|
||||
|
||||
- `true`: enables context/stage scanning (e.g. `BUILDKIT_SBOM_SCAN_STAGE=true`)
|
||||
- `false`: disables context/stage scanning (e.g. `BUILDKIT_SBOM_SCAN_STAGE=false`)
|
||||
- `<stage-name>[,<stage-name>]`: enables context/stage scanning for all stages
|
||||
listed in the comma-separated list of provided stages (e.g.
|
||||
`BUILDKIT_SBOM_SCAN_STAGE=x,y` will scan stages called `x` and `y`).
|
||||
|
||||
Scanning will *never* be enabled for a stage that is not built, even if it is
|
||||
enabled via the build arguments.
|
||||
|
||||
For example:
|
||||
|
||||
```dockerfile
|
||||
FROM alpine:latest as build
|
||||
# enable scanning for the intermediate build stage
|
||||
ARG BUILDKIT_SBOM_SCAN_STAGE=true
|
||||
WORKDIR /src
|
||||
COPY . .
|
||||
RUN ... # build some software
|
||||
|
||||
FROM scratch as final
|
||||
# scan the build context only if the build is run to completion
|
||||
ARG BUILDKIT_SBOM_SCAN_CONTEXT=true
|
||||
COPY --from=build /path/to/software /path/to/software
|
||||
```
|
||||
|
||||
You can also directly override these `ARG`s on the command line, by passing
|
||||
them as build arguments:
|
||||
|
||||
```bash
|
||||
buildctl build \
|
||||
--frontend=dockerfile.v0 \
|
||||
--local context=. \
|
||||
--local dockerfile=. \
|
||||
--opt build-arg:BUILDKIT_SBOM_SCAN_STAGE=<value> \
|
||||
--opt build-arg:BUILDKIT_SBOM_SCAN_CONTEXT=<value> \
|
||||
--opt attest:sbom=
|
||||
```
|
||||
|
||||
Scanning will only override existing `ARG` definitions in the Dockerfile, and
|
||||
so does not allow including other stages in the Dockerfile that do not declare
|
||||
`BUILDKIT_SBOM_SCAN` arguments.
|
||||
|
||||
## Output
|
||||
|
||||
To inspect the SBOMs that were 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 SBOM:
|
||||
|
||||
```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",
|
||||
"name": "/run/src/core",
|
||||
"spdxVersion": "SPDX-2.2",
|
||||
"creationInfo": {
|
||||
"created": "2022-11-09T10:12:01.338817553Z",
|
||||
"creators": [
|
||||
"Organization: Anchore, Inc",
|
||||
"Tool: syft-[not provided]"
|
||||
],
|
||||
"licenseListVersion": "3.18"
|
||||
},
|
||||
"dataLicense": "CC0-1.0",
|
||||
"documentNamespace": "https://anchore.com/syft/dir/run/src/core-4006bb64-24b1-4a22-a18f-94efc6b90edb",
|
||||
"files": [
|
||||
{
|
||||
"SPDXID": "SPDXRef-1ac501c94e2f9f81",
|
||||
"comment": "layerID: sha256:9b18e9b68314027565b90ff6189d65942c0f7986da80df008b8431276885218e",
|
||||
"fileName": "/bin/busybox",
|
||||
"licenseConcluded": "NOASSERTION"
|
||||
},
|
||||
...
|
||||
],
|
||||
"packages": [
|
||||
{
|
||||
"SPDXID": "SPDXRef-980737451f148c56",
|
||||
"description": "Size optimized toolbox of many common UNIX utilities",
|
||||
"downloadLocation": "https://busybox.net/",
|
||||
"externalRefs": [
|
||||
{
|
||||
"referenceCategory": "SECURITY",
|
||||
"referenceLocator": "cpe:2.3:a:busybox:busybox:1.35.0-r17:*:*:*:*:*:*:*",
|
||||
"referenceType": "cpe23Type"
|
||||
},
|
||||
{
|
||||
"referenceCategory": "PACKAGE_MANAGER",
|
||||
"referenceLocator": "pkg:alpine/busybox@1.35.0-r17?arch=aarch64&upstream=busybox&distro=alpine-3.16.2",
|
||||
"referenceType": "purl"
|
||||
}
|
||||
],
|
||||
"filesAnalyzed": false,
|
||||
"hasFiles": [
|
||||
"SPDXRef-1ac501c94e2f9f81",
|
||||
...
|
||||
],
|
||||
"licenseConcluded": "GPL-2.0-only",
|
||||
"licenseDeclared": "GPL-2.0-only",
|
||||
"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"
|
||||
},
|
||||
...
|
||||
],
|
||||
"relationships": [
|
||||
{
|
||||
"relatedSpdxElement": "SPDXRef-1ac501c94e2f9f81",
|
||||
"relationshipType": "CONTAINS",
|
||||
"spdxElementId": "SPDXRef-980737451f148c56"
|
||||
},
|
||||
...
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The exact output will depend on the generator you use, however, generally:
|
||||
|
||||
- The `files` key will contain a list of all files in the image.
|
||||
- The `packages` key will contain a list of all packages discovered from the
|
||||
image.
|
||||
- The `relationships` key links together various files and packages, together
|
||||
with metadata about how they relate to each other.
|
||||
|
||||
Entries in the `files` and `packages` will contain a `comment` field that
|
||||
contains the `sha256` digest of the layer which introduced it if that layer is
|
||||
present in the final image.
|
||||
Reference in New Issue
Block a user