Docker: Lista De Materiales De Software O Software Bill Of Materials (SBOM)

Software Bill Of Materials (SBOM), es un inventario de los componentes de software y dependencias de un sistema, información de dichos componentes y la relación entre ellos. Este inventario se mantiene en un formato que es fácilmente legible por máquinas. Últimamente se han visto muchas vulnerabilidades relacionadas con la cadena de suministro de dependencias, una de las más sonadas el famoso log4shell entre otras. Cuando aparece una vulnerabilidad de este tipo, la pregunta es ¿Estamos afectado por dicha vulnerabilidad? ¿Alguno de nuestros sistemas usa la librería X? Y Docker nos puede ayudar.

Figura 1: Docker. Lista de Materiales de Software
o Software Bill Of Materials (SBOM)

La única forma de poder responder a este tipo de preguntas con cierta confianza es manteniendo el inventario, actualizado, de los componentes y dependencias que nuestros sistemas usan. Hay que tener en cuenta también que dicho inventario no sólo contenga los componentes y dependencias usadas directamente en nuestros sistemas, sino también las dependencias heredadas por dichos componentes y dependencias, también conocidas como dependencias transitivas.

Aunque SBOM no es algo nuevo, se puso muy de moda el año pasado cuando la Casa Blanca lanzó una orden ejecutiva en la requería que cualquier empresa que hiciera negocios con el gobierno norteamericano (venta de software, desarrollo o venta de licencias de uso) fuera capaz de proveer de esta lista de materiales con todos los componentes del software. De esta forma han sido muchas de las empresas que han incluido la posibilidad de la creación de SBOMs en sus herramientas, entre ellas Docker, dentro de su producto Docker Desktop

En la versión 4.7.0, justo después de la publicación de la segunda la edición de nuestro libro Docker: SecDevOps, Docker añadió un plugin por defecto que permite la generación de ficheros SBOM y de los que vamos a ver algunos ejemplos, que ya hemos visto un poco qué es SBOM y por qué es importante. 

Una cosa para recalcar, como se comentó antes, esto no es algo nuevo, y además tampoco es un estándar, por lo que existen varias iniciativas y formatos. Aunque no son los únicos que existen, los siguientes son los formatos que más fuerza o repercusión tienen actualmente:
Sin entrar en más detalles sobre dichos formatos, vamos a ver cómo se puede generar la lista de componentes y dependencias de una imagen de Docker.

Como comenté anteriormente, en la versión 4.7.0, Docker añadió una opción nueva (realmente un plugin) al comando *docker* llamada *sbom*. Este plugin usa por detrás un proyecto de Anchore llamado [syft](https://github.com/anchore/syft). Éste analiza las capas de la imagen y extrae la información sobre que comoponentes hay en cada capa. Si ejecutamos dicho comando obtendremos la siguiente salida:
    $ docker sbom

Usage: docker sbom [OPTIONS] COMMAND

View the packaged-based Software Bill Of Materials (SBOM) for an image.

EXPERIMENTAL: The flags and outputs of this command may change.
Leave feedback on https://github.com/docker/sbom-cli-plugin.
Examples:

docker sbom alpine:latest a summary of discovered packages
docker sbom alpine:latest --format syft-json show all possible cataloging details
docker sbom alpine:latest --output sbom.txt write report output to a file
docker sbom alpine:latest --exclude /lib --exclude '**/*.db' ignore one or more paths/globs in the image

Options:
-D, --debug show debug logging
--exclude stringArray exclude paths from being scanned using a glob expression
--format string report output format, options=[syft-json cyclonedx-xml cyclonedx-json
github-0-json spdx-tag-value spdx-json table text] (default "table")
--layers string [experimental] selection of layers to catalog, options=[squashed all] (default
"squashed")
-o, --output string file to write the default report output to (default is STDOUT)
--platform string an optional platform specifier for container image sources (e.g. 'linux/arm64',
'linux/arm64/v8', 'arm64', 'linux')
--quiet suppress all non-report output
-v, --version version for sbom

Commands:
version Show Docker sbom version information

Run 'docker sbom COMMAND --help' for more information on a command.
an image argument is required
Dicho plugin permite la generación de ficheros SBOM en formato SPDX y CycloneDX. Veamos a continuación la salida por defecto que se produciría sobre una imagen Alpine:
    $ docker sbom alpine
Syft v0.43.0
✔ Loaded image
✔ Parsed image
✔ Cataloged packages [14 packages]

NAME VERSION TYPE
alpine-baselayout 3.2.0-r16 apk
alpine-keys 2.3-r1 apk
apk-tools 2.12.7-r0 apk
busybox 1.33.1-r3 apk
ca-certificates-bundle 20191127-r5 apk
libc-utils 0.7.2-r3 apk
libcrypto1.1 1.1.1l-r0 apk
libretls 3.3.3p1-r2 apk
libssl1.1 1.1.1l-r0 apk
musl 1.2.2-r3 apk
musl-utils 1.2.2-r3 apk
scanelf 1.3.2-r0 apk
ssl_client 1.33.1-r3 apk
zlib 1.2.11-r3 apk
En este caso se puede ver la lista de los componentes de la imagen *alpine:latest*. Ahora veamos el mismo ejemplo, pero en formato SPDX:
    $ docker sbom --format spdx alpine
Syft v0.43.0
✔ Loaded image
✔ Parsed image
✔ Cataloged packages [14 packages]

SPDXVersion: SPDX-2.2
DataLicense: CC0-1.0
SPDXID: SPDXRef-DOCUMENT
DocumentName: alpine-latest
DocumentNamespace: https://anchore.com/syft/image/alpine-latest-b478dc4d-bced-406a-adf9-6f7b7ea6d231
LicenseListVersion: 3.16
Creator: Organization: Anchore, Inc
Creator: Tool: syft-[not provided]
Created: 2022-04-15T20:19:57Z

##### Package: alpine-baselayout

PackageName: alpine-baselayout
SPDXID: SPDXRef-Package-apk-alpine-baselayout-ed18f2a986e77aab
PackageVersion: 3.2.0-r16
PackageDownloadLocation: NOASSERTION
FilesAnalyzed: false
PackageLicenseConcluded: GPL-2.0-only
PackageLicenseDeclared: GPL-2.0-only
PackageCopyrightText: NOASSERTION
ExternalRef: SECURITY cpe23Type cpe:2.3:a:alpine-baselayout:alpine-baselayout:3.2.0-r16:*:*:*:*:*:*:*
ExternalRef: SECURITY cpe23Type cpe:2.3:a:alpine-baselayout:alpine_baselayout:3.2.0-r16:*:*:*:*:*:*:*
ExternalRef: SECURITY cpe23Type cpe:2.3:a:alpine_baselayout:alpine-baselayout:3.2.0-r16:*:*:*:*:*:*:*
ExternalRef: SECURITY cpe23Type cpe:2.3:a:alpine_baselayout:alpine_baselayout:3.2.0-r16:*:*:*:*:*:*:*
ExternalRef: SECURITY cpe23Type cpe:2.3:a:alpine:alpine-baselayout:3.2.0-r16:*:*:*:*:*:*:*
ExternalRef: SECURITY cpe23Type cpe:2.3:a:alpine:alpine_baselayout:3.2.0-r16:*:*:*:*:*:*:*
ExternalRef: PACKAGE_MANAGER purl pkg:alpine/[email protected]?arch=x86_64&upstream=alpine-baselayout&distro=alpine-3.14.2

##### Package: alpine-keys
...
La salida es mucho más larga, pero a modo de ejemplo se puede ver uno de los componentes encontrados, con nombre, licencia, referencias externas, etcétera. También es posible generar la salida en formato *json*:
    $ docker sbom --format spdx-json alpine
Syft v0.43.0
✔ Loaded image
✔ Parsed image
✔ Cataloged packages [14 packages]

{
"SPDXID": "SPDXRef-DOCUMENT",
"name": "alpine-latest",
"spdxVersion": "SPDX-2.2",
"creationInfo": {
"created": "2022-04-15T21:15:23.057754Z",
"creators": [
"Organization: Anchore, Inc",
"Tool: syft-[not provided]"
],
"licenseListVersion": "3.16"
},
"dataLicense": "CC0-1.0",
"documentNamespace": "https://anchore.com/syft/image/alpine-latest-2ea1fa9e-099e-4939-bdd8-d41fab29f1b0",
"packages": [
{
"SPDXID": "SPDXRef-ed18f2a986e77aab",
...
Para ver la salida en formato CycloneDX:
    $ docker sbom --format cyclonedx alpine
Syft v0.43.0
✔ Loaded image
✔ Parsed image
✔ Cataloged packages [14 packages]

[0000] WARN unable to convert relationship from CycloneDX 1.3 JSON, dropping:
{From:Pkg(name="musl" version="1.2.2-r3" type="apk" id="304c2239a7d1d6b7")
To:Location<RealPath="/lib/ld-musl-x86_64.so.1"

...

<?xml version="1.0" encoding="UTF-8"?>
<bom xmlns="http://cyclonedx.org/schema/bom/1.4"
serialNumber="urn:uuid:faaf4f40-e332-4f0e-8acc-3fadcae62d25" version="1">
<metadata>
<timestamp>2022-04-15T17:17:00-04:00</timestamp>
<tools>
<tool>
<vendor>anchore</vendor>
<name>syft</name>
<version>[not provided]</version>
</tool>
</tools>
<component bom-ref="e33e1cadf7cfbd1e" type="container">
<name>alpine:latest</name>
<version>sha256:a2f19fdc3f78ddc201c5bb37e302fed8b3487695056215b5577113d3938196bf</version>
</component>
</metadata>
<components>
<component type="library">
<publisher>Natanael Copa <[email protected]></publisher>
<name>alpine-baselayout</name>
<version>3.2.0-r16</version>
<description>Alpine base dir structure and init scripts</description>
<licenses>
<license>
<id>GPL-2.0-only</id>
</license>
</licenses>
<cpe>cpe:2.3:a:alpine-baselayout:alpine-baselayout:3.2.0-r16:*:*:*:*:*:*:*</<pe>
<purl>pkg:alpine/[email protected]?arch=x86_64&upstream=alpine-baselayout&distro=alpine-3.14.2</purl>
<externalReferences>
<reference type="distribution">
<url>https://git.alpinelinux.org/cgit/aports/tree/main/alpine-baselayout</url>
</reference>
</externalReferences>
<properties>
<property name="syft:package:foundBy">apkdb-cataloger</property>
<property name="syft:package:metadataType">ApkMetadata</property>
<property name="syft:package:type">apk</property>
<property name="syft:cpe23">cpe:2.3:a:alpine-baselayout:alpine_baselayout:3.2.0-r16:*:*:*:*:*:*:*</property>
<property name="syft:cpe23">cpe:2.3:a:alpine_baselayout:alpine-baselayout:3.2.0-r16:*:*:*:*:*:*:*</property>
<property name="syft:cpe23">cpe:2.3:a:alpine_baselayout:alpine_baselayout:3.2.0-r16:*:*:*:*:*:*:*</property>
<property name="syft:cpe23">cpe:2.3:a:alpine:alpine-baselayout:3.2.0-r16:*:*:*:*:*:*:*</property>
<property name="syft:cpe23">cpe:2.3:a:alpine:alpine_baselayout:3.2.0-r16:*:*:*:*:*:*:*</property>
<property name="syft:location:0:layerID">sha256:e2eb06d8af8218cfec8210147357a68b7e13f7c485b991c288c2d01dc228bb68</property>
<property name="syft:location:0:path">/lib/apk/db/installed</property>
<property name="syft:metadata:gitCommitOfApkPort">8a8c96a0ea2fcd824c361aa4438763fa33ee8ca0</property>
<property name="syft:metadata:installedSize">413696</property>
<property name="syft:metadata:originPackage">alpine-baselayout</property>
<property name="syft:metadata:pullChecksum">Q1UJtB9cNV4r+/VbxySkEei++qbho=</property>
<property name="syft:metadata:pullDependencies">/bin/sh so:libc.musl-x86_64.so.1</property>
<property name="syft:metadata:size">20716</property>
</properties>
</component>
...
...
Como se pueden ver los campos generados son distintos que SPDX y el formato, por defecto, es XML, pero al final la información que se recolecta es prácticamente la misma. También es posible la generación en formato *json*:
    $ docker sbom --format cyclonedx-json alpine
Syft v0.43.0
✔ Loaded image
✔ Parsed image
✔ Cataloged packages [14 packages]

[0000] WARN unable to convert relationship from CycloneDX 1.3 JSON, dropping: {From:Pkg(name="musl" version="1.2.2-r3" type="apk" id="304c2239a7d1d6b7") To:Location<RealPath="/lib/ld-musl-x86_6
...

{
"bomFormat": "CycloneDX",
"specVersion": "1.4",
"serialNumber": "urn:uuid:95cef6a2-edcb-4b82-91a4-3ed026f1670f",
"version": 1,
"metadata": {
"timestamp": "2022-04-15T17:21:34-04:00",
"tools": [
{
"vendor": "anchore",
"name": "syft",
"version": "[not provided]"
}
],
"component": {
"bom-ref": "e33e1cadf7cfbd1e",
"type": "container",
"name": "alpine:latest",
"version": "sha256:a2f19fdc3f78ddc201c5bb37e302fed8b3487695056215b5577113d3938196bf"
}
},
"components": [
{
"type": "library",
"publisher": "Natanael Copa \[email protected]\u003e",
"name": "alpine-baselayout",
"version": "3.2.0-r16",
"description": "Alpine base dir structure and init scripts",
"licenses": [
{
"license": {
"id": "GPL-2.0-only"
}
}
],
"cpe": "cpe:2.3:a:alpine-baselayout:alpine-baselayout:3.2.0-r16:*:*:*:*:*:*:*",
"purl": "pkg:alpine/[email protected]?arch=x86_64\u0026upstream=alpine-baselayout\u0026distro=alpine-3.14.2",
"externalReferences": [
{
"url": "https://git.alpinelinux.org/cgit/aports/tree/main/alpine-baselayout",
"type": "distribution"
}
],
"properties": [
{
"name": "syft:package:foundBy",
"value": "apkdb-cataloger"
},
{
"name": "syft:package:metadataType",
...
La lista de los formatos soportados actualmente son:
* syft-json
* cyclonedx-xml
* cyclonedx-json
* github-0-json
* spdx-tag-value
* spdx-json
* table (formato por defecto)
* text
Si en vez mandar el contenido del fichero a la consola o salida estándar, queréis que se guarde en un fichero, se puede usar la opción -o o --output:
    $ docker sbom --format spdx-json -o alpine.json alpine
Syft v0.43.0
✔ Loaded image
✔ Parsed image
✔ Cataloged packages [14 packages]
La inclusión de este plugin en Docker está en modo experimental y puede que en futuras versiones éste cambie. Si tienes que generar SBOMs en entornos de producción, se podría usar la herramienta syft directamente. Esta herramienta es mucho más completa que lo que ofrece actualmente el plugin de Docker.

Happy Hacking!


Via: www.elladodelmal.com
Docker: Lista De Materiales De Software O Software Bill Of Materials (SBOM) Docker: Lista De Materiales De Software O Software Bill Of Materials (SBOM) Reviewed by Zion3R on 0:50 Rating: 5