Skip to main content

¿Qué puedes hacer con un SBOM enriquecido? Guía rápida para empezar con parlay

Escrito por
blog feature parlay announcement

7 de junio de 2023

0 minutos de lectura

Acabamos de lanzar parlay, una nueva herramienta de código abierto que permite enriquecer los SBOM con información adicional. Puedes leer más en la publicación del anuncio. En esa publicación, mencionamos brevemente por qué esto es importante para tomar decisiones basadas en datos de SBOM, pero pensamos que podrían interesarte algunos ejemplos rápidos.

parlay puede agregar mucha información adicional a un SBOM, y podemos usarla para escribir políticas más eficaces. Aunque la cantidad de líneas de JSON no es un indicador perfecto, en este ejemplo puedes ver que el SBOM creció más de un 400 %, lo que abre muchas posibilidades.

$ snyk sbom --format cyclonedx1.4+json | jq | wc -l
    262
$ snyk sbom --format cyclonedx1.4+json | parlay e enrich - | jq | wc -l
    1169

Políticas de licencias

Un SBOM con solo los elementos mínimos no incluye información sobre las licencias aplicables a los paquetes incluidos. Usemos Parlay y los datos de Ecosyste.ms para agregar esa información.

snyk sbom --format cyclonedx1.4+json | parlay e enrich -

Ahora que tenemos un SBOM más completo, podemos escribir políticas más eficaces. Para este ejemplo, usaremos Open Policy Agent y su potente lenguaje de programación Rego. Aquí creamos dos listas de políticas: una para bloquear y otra para emitir advertencias.

package main

name = input.metadata.component.name

licenses_to_deny = [
  "LGPL",
]

licenses_to_warn = [
  "MIT"
]

deny[msg] {
  component := input.components[_]
  expression := component.licenses[_].expression
  startswith(expression, licenses_to_deny[_])
  msg := sprintf("%s is using %s which is licensed with an %s license", [name, component.name, expression])
}

warn[msg] {
    component := input.components[_]
    expression := component.licenses[_].expression
    startswith(expression, licenses_to_warn[_])
    msg := sprintf("%s is using %s which is licensed with an %s license", [name, component.name, expression])
}

Sigamos aprovechando las tuberías de Unix y usemos Conftest para aplicar esa política al SBOM enriquecido.

snyk sbom --format cyclonedx1.4+json | parlay e enrich - | conftest test -

En el proyecto de ejemplo, esto generó una serie de advertencias sobre ciertos paquetes que usan las licencias indicadas.

WARN - - main - snykit is using diff-lcs which is licensed with an MIT license
WARN - - main - snykit is using mustermann which is licensed with an MIT license
WARN - - main - snykit is using nio4r which is licensed with an MIT license
WARN - - main - snykit is using puma-metrics which is licensed with an MIT license
WARN - - main - snykit is using rack which is licensed with an MIT license
WARN - - main - snykit is using rack-protection which is licensed with an MIT license
WARN - - main - snykit is using rack-test which is licensed with an MIT license
WARN - - main - snykit is using rake which is licensed with an MIT license
WARN - - main - snykit is using rspec which is licensed with an MIT license
WARN - - main - snykit is using rspec-core which is licensed with an MIT license
WARN - - main - snykit is using rspec-expectations which is licensed with an MIT license
WARN - - main - snykit is using rspec-mocks which is licensed with an MIT license
WARN - - main - snykit is using rspec-support which is licensed with an MIT license
WARN - - main - snykit is using sinatra which is licensed with an MIT license
WARN - - main - snykit is using tilt which is licensed with an MIT license

16 tests, 1 passed, 15 warnings, 0 failures, 0 exceptions

Políticas de vulnerabilidades

Probemos algo un poco más complejo. Escribamos una política para señalar vulnerabilidades que superen cierta puntuación CVSS en dependencias directas. Este es un buen ejemplo de cuándo necesitas datos de paquetes, dependencias y vulnerabilidades.

deny[msg] {
  vulnerability := input.vulnerabilities[_]
  rating := vulnerability.ratings[_]
  rating.source.name == "Snyk"
  rating.score > max_cvss_score
  component := input.components[_]
  bom_ref = vulnerability["bom-ref"]
  component["bom-ref"] == bom_ref

  root = input.metadata.component["bom-ref"]

  dependency := input.dependencies[_]
  dependency.ref == root

  direct := dependency.dependsOn[_]
  direct == bom_ref

  msg := sprintf("%s version %s has a vulnerability with a CVSS score of %s", [component.name, component.version, round(rating.score)])
}

round(n) = f {
  f := sprintf("%.2f", [n])
  contains(f, ".") # Ensure that it was a float
}

round(n) = f {
  not contains(sprintf("%.2f", [n]), ".") # Test if it wasn't a float
  f := sprintf("%v.00", [n]) # Fudge the decimals for integer values
}

Luego, podemos generar o tomar nuestro SBOM, enriquecerlo con los datos de vulnerabilidades de Snyk y aplicar nuestra política con Conftest.

snyk sbom --format cyclonedx1.4+json | parlay s enrich - | conftest test -
FAIL - - main - puma version 4.2.1 has a vulnerability with a CVSS score of 9.10

3 tests, 2 passed, 0 warnings, 1 failure, 0 exceptions

Aquí vemos un informe sobre una vulnerabilidad que cumplió con nuestros criterios.

Recuerda que este es solo un ejemplo. El lenguaje Rego que usa Open Policy Agent permite describir lógica compleja, si es necesario. Y si prefieres otra herramienta de políticas, también debería funcionar.

¿Quién es el autor de este software?

Un último ejemplo rápido. El siguiente ejemplo usa parlay para enriquecer nuestro SBOM y luego usa jq y awk para mostrar información útil. En este caso, extraemos el nombre del autor de cada paquete. Una vez más, esta información suele faltar en los SBOM que solo incluyen los elementos mínimos.

$ snyk sbom --format cyclonedx1.4+json | parlay e enrich - | jq -r '(.components[] | [.name, .author]) | @tsv' | awk '{print $1; $1=""; print}'
nio4r
 Socketry
puma
 Puma
prometheus-client
 Prometheus
puma-metrics

rack
 Official Rack repositories
rack-test
 Official Rack repositories
rake
 The Ruby Programming Language
rspec-support
 RSpec
rspec-core
 RSpec
diff-lcs
 Austin Ziegler
rspec-expectations
 RSpec
rspec-mocks
 RSpec
rspec
 RSpec
ruby2_keywords
 The Ruby Programming Language
mustermann
 Sinatra
rack-protection
 Sinatra
tilt
 Jeremy Evans
sinatra
 Sinatra

Hay muchas más cosas que puedes hacer con datos de SBOM más completos, y también hay muchos más datos útiles que se pueden agregar a los SBOM. Cuéntanos qué te gustaría ver y comparte ejemplos de tus experimentos con parlay.