# Atestaciones SBOM


Las atestaciones SBOM ayudan a garantizar la [transparencia de la cadena de suministro de software](/guides/docker-scout/s3c/) al verificar los artefactos de software que contiene una imagen y los artefactos utilizados para crearla. Los metadatos incluidos en un [SBOM](/guides/docker-scout/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](/build/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](https://github.com/in-toto/attestation/blob/main/spec/predicates/spdx.md). 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`:

```console
$ 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](/build/ci/github-actions/attestations/).

## 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.

```console
$ 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`:

```console
$ 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)](/build/building/multi-stage/), con una sección `FROM scratch` para tu etapa final para lograr un tamaño de imagen más pequeño.

```dockerfile
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`.

```dockerfile
# 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.

```console
$ 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](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 /
```

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:

```console
$ 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`](/reference/cli/docker/buildx/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:

```console
$ docker buildx imagetools inspect <namespace>/<image>:<version> \
    --format "{{ json .SBOM.SPDX }}"
{
  "SPDXID": "SPDXRef-DOCUMENT",
  ...
}
```

> [!TIP]
>
> Si 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:

```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
...
```

## Generador de SBOM

BuildKit genera el SBOM utilizando un plugin de escaneo. Por defecto, utiliza el plugin [BuildKit Syft scanner](https://github.com/docker/buildkit-syft-scanner). Este plugin está desarrollado sobre [Syft de Anchore](https://github.com/anchore/syft), 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](https://github.com/moby/buildkit/blob/master/docs/attestations/sbom-protocol.md).

```console
$ docker buildx build --attest type=sbom,generator=<image> .
```

> [!TIP]
>
> El generador de SBOM de Docker Scout está disponible. Consulta
> [SBOMs en Docker Scout](/scout/how-tos/view-create-sboms/).

## Ejemplo de atestación SBOM

El siguiente ejemplo JSON muestra cómo podría verse una atestación 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",
    "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"
  }
}
```

