Atestaciones SBOM
Las atestaciones SBOM ayudan a garantizar la transparencia de la cadena de suministro de software al verificar los artefactos de software que contiene una imagen y los artefactos utilizados para crearla. Los metadatos incluidos en un SBOM para describir artefactos de software pueden incluir:
- Nombre del artefacto
- Versión
- Tipo de licencia
- Autores
- Identificador único del paquete
Indexar el contenido de una imagen durante la compilación ofrece ventajas en comparación con escanear una imagen final. Cuando el escaneo se realiza como parte de la compilación, puedes detectar el software utilizado para compilar la imagen, el cual podría no aparecer en la imagen final.
Docker admite la generación y atestación de SBOM a través de un proceso de compilación que cumple con SLSA utilizando BuildKit y atestaciones. Los SBOM generados por BuildKit siguen el estándar SPDX y se adjuntan a la imagen final como un documento SPDX codificado en JSON, utilizando el formato definido por el predicado SPDX de in-toto. En esta página, aprenderás cómo crear, gestionar y verificar atestaciones SBOM utilizando las herramientas de Docker.
Crear atestaciones SBOM
Para crear una atestación SBOM, pasa la opción --attest type=sbom al comando docker buildx build:
$ docker buildx build --tag <namespace>/<image>:<version> \
--attest type=sbom --push .
Alternativamente, puedes utilizar la opción abreviada --sbom=true en lugar de --attest type=sbom.
Para ver un ejemplo sobre cómo añadir atestaciones SBOM con GitHub Actions, consulta Añadir atestaciones con GitHub Actions.
Verificar atestaciones SBOM
Valida siempre el SBOM generado para tu imagen antes de subirla a un registro.
Para validar, puedes compilar la imagen utilizando el exportador local. Compilar con el exportador local guarda el resultado de la compilación en tu sistema de archivos local en lugar de crear una imagen. Las atestaciones se escriben en un archivo JSON en el directorio raíz de la exportación.
$ docker buildx build \
--sbom=true \
--output type=local,dest=out .
El archivo SBOM aparece en el directorio raíz de la salida, con el nombre sbom.spdx.json:
$ ls -1 ./out | grep sbom
sbom.spdx.json
Argumentos
Por defecto, BuildKit solo escanea la etapa final (final stage) de una imagen. El SBOM resultante no incluye las dependencias de tiempo de compilación instaladas en etapas anteriores, o que existen en el contexto de compilación. Esto puede hacer que pases por alto vulnerabilidades en esas dependencias, lo que podría afectar la seguridad de los artefactos de compilación finales.
Por ejemplo, podrías utilizar
compilaciones multi-etapa (multi-stage builds), con una sección FROM scratch para tu etapa final para lograr un tamaño de imagen más pequeño.
FROM alpine AS build
# build the software ...
FROM scratch
COPY --from=build /path/to/bin /bin
ENTRYPOINT [ "/bin" ]Escanear la imagen resultante compilada con este ejemplo de Dockerfile no revelaría las dependencias de tiempo de compilación utilizadas en la etapa build.
Para incluir dependencias de tiempo de compilación de tu Dockerfile, puedes establecer los argumentos de compilación BUILDKIT_SBOM_SCAN_CONTEXT y BUILDKIT_SBOM_SCAN_STAGE. Esto amplía el alcance del escaneo para incluir el contexto de compilación y las etapas adicionales.
Puedes establecer los argumentos como globales (después de declarar la directiva de sintaxis del Dockerfile y antes del primer comando FROM) o individualmente en cada etapa. Si se establecen globalmente, el valor se propaga a cada etapa del Dockerfile.
Los argumentos de compilación BUILDKIT_SBOM_SCAN_CONTEXT and BUILDKIT_SBOM_SCAN_STAGE son valores especiales. No puedes realizar sustitución de variables utilizando estos argumentos, y tampoco puedes establecerlos mediante variables de entorno desde el interior del Dockerfile. La única manera de establecer estos valores es mediante un comando ARG explícito en el Dockerfile.
Escanear el contexto de compilación
Para escanear el contexto de compilación, establece BUILDKIT_SBOM_SCAN_CONTEXT en true.
# syntax=docker/dockerfile:1
ARG BUILDKIT_SBOM_SCAN_CONTEXT=true
FROM alpine AS build
# ...Puedes utilizar la opción --build-arg de la CLI para anular el valor especificado en el Dockerfile.
$ docker buildx build --tag <image>:<version> \
--attest type=sbom \
--build-arg BUILDKIT_SBOM_SCAN_CONTEXT=false .
Ten en cuenta que pasar la opción solo como un argumento de CLI, sin haberla declarado usando ARG en el Dockerfile, no tendrá ningún efecto. Debes especificar el ARG en el Dockerfile, con lo cual puedes anular el comportamiento del escaneo de contexto utilizando --build-arg.
Escanear etapas
Para escanear más de la etapa final, establece el argumento BUILDKIT_SBOM_SCAN_STAGE en true, ya sea globalmente o en las etapas específicas que desees escanear. La siguiente tabla muestra las diferentes configuraciones posibles para este argumento.
| Valor | Descripción |
|---|---|
BUILDKIT_SBOM_SCAN_STAGE=true | Activa el escaneo para la etapa actual |
BUILDKIT_SBOM_SCAN_STAGE=false | Desactiva el escaneo para la etapa actual |
BUILDKIT_SBOM_SCAN_STAGE=base,bin | Activa el escaneo para las etapas llamadas base y bin |
Solo se escanearán las etapas que se compilen. Las etapas que no sean dependencias de la etapa de destino no se compilarán ni se escanearán.
El siguiente ejemplo de Dockerfile utiliza compilaciones multi-etapa para compilar un sitio web estático con Hugo.
# 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 /Establecer ARG BUILDKIT_SBOM_SCAN_STAGE=true en la etapa hugo garantiza que el SBOM final incluya la información de que se utilizaron Alpine Linux y Hugo para crear el sitio web.
Compilar esta imagen con el exportador local crea dos archivos JSON:
$ docker buildx build \
--sbom=true \
--output type=local,dest=out .
$ ls -1 out | grep sbom
sbom-hugo.spdx.json
sbom.spdx.json
Inspección de SBOM
Para explorar los SBOM creados y exportados mediante el exportador image, puedes utilizar
imagetools inspect.
Mediante la opción --format, puedes especificar una plantilla para la salida. Todos los datos relacionados con el SBOM están disponibles bajo el atributo .SBOM. Por ejemplo, para obtener el contenido sin procesar de un SBOM en formato SPDX:
$ docker buildx imagetools inspect <namespace>/<image>:<version> \
--format "{{ json .SBOM.SPDX }}"
{
"SPDXID": "SPDXRef-DOCUMENT",
...
}
TipSi la imagen es multi-plataforma, puedes comprobar el SBOM para un índice específico de plataforma utilizando
--format '{{ json (index .SBOM "linux/amd64").SPDX }}'.
También puedes construir expresiones más complejas utilizando la funcionalidad completa de las plantillas de Go. Por ejemplo, puedes listar todos los paquetes instalados y sus identificadores de versión:
$ docker buildx imagetools inspect <namespace>/<image>:<version> \
--format "{{ range .SBOM.SPDX.packages }}{{ .name }}@{{ .versionInfo }}{{ println }}{{ end }}"
[email protected]
[email protected]
[email protected]
[email protected]
...
Generador de SBOM
BuildKit genera el SBOM utilizando un plugin de escaneo. Por defecto, utiliza el plugin BuildKit Syft scanner. Este plugin está desarrollado sobre Syft de Anchore, una herramienta de código abierto para generar SBOM.
Puedes seleccionar un plugin diferente para utilizar con la opción generator, especificando una imagen que implemente el protocolo de escaneo de SBOM de BuildKit.
$ docker buildx build --attest type=sbom,generator=<image> .
TipEl generador de SBOM de Docker Scout está disponible. Consulta SBOMs en Docker Scout.
Ejemplo de atestación SBOM
El siguiente ejemplo JSON muestra cómo podría verse una atestación SBOM.
{
"_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/[email protected]",
"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"
}
}