Skip to main content

Que faire avec un SBOM enrichi ? Guide de démarrage rapide de parlay

Écrit par
blog feature parlay announcement

7 juin 2023

0 minutes de lecture

Nous venons de publier parlay, un nouvel outil open source qui enrichit les SBOM avec des informations supplémentaires. Pour en savoir plus, consultez l’article d’annonce. Nous avons brièvement expliqué dans cet article pourquoi ces données sont importantes pour prendre des décisions fondées sur les SBOM, mais nous avons pensé que quelques exemples rapides pourraient vous intéresser.

parlay peut ajouter de nombreuses informations à un SBOM, que nous pouvons ensuite utiliser pour rédiger des règles plus puissantes. Même si le nombre de lignes JSON n’est pas un indicateur parfait, cet exemple montre que la taille du SBOM a augmenté de plus de 400 % — ce qui ouvre la voie à de nombreux cas d’usage.

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

Règles de licence

Un SBOM contenant uniquement les éléments minimaux ne fournit aucune information sur les licences applicables aux packages inclus. Utilisons Parlay et les données d’Ecosyste.ms pour ajouter ces informations.

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

Maintenant que notre SBOM est plus complet, nous pouvons rédiger des règles plus puissantes. Dans cet exemple, nous allons utiliser Open Policy Agent et son puissant langage de programmation Rego. Nous allons créer deux listes de règles : l’une pour bloquer et l’autre pour émettre un avertissement.

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])
}

Poursuivons notre passion pour les tubes Unix et utilisons Conftest pour appliquer cette règle au SBOM enrichi.

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

Dans le projet d’exemple, cette commande a généré une série d’avertissements concernant certains packages et les licences qui leur sont associées.

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

Règles de sécurité

Essayons quelque chose d’un peu plus complexe. Écrivons une règle qui signale les vulnérabilités dont le score CVSS dépasse un certain seuil dans les dépendances directes. C’est un bon exemple de cas où vous avez besoin des données sur les packages, les dépendances et les vulnérabilités.

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
}

Nous pouvons ensuite générer ou récupérer notre SBOM, l’enrichir avec les données de vulnérabilité de Snyk, puis appliquer notre règle à l’aide de 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

Ici, nous voyons un rapport signalant une vulnérabilité qui répond à nos critères.

N’oubliez pas qu’il ne s’agit que d’un exemple. Le langage Rego utilisé par Open Policy Agent permet de décrire une logique complexe, si nécessaire. Et si vous préférez un autre outil de gestion des règles, cela devrait également fonctionner.

Qui est l’auteur de ce logiciel ?

Un dernier exemple rapide. L’exemple suivant utilise parlay pour enrichir notre SBOM, puis jq et awk pour afficher des informations utiles. Ici, nous extrayons le nom de l’auteur de chaque package. Là encore, cette information ne figure souvent pas dans un SBOM contenant uniquement les éléments minimaux.

$ 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

Les données enrichies des SBOM permettent de faire bien d’autres choses, et il existe de nombreuses autres données utiles pour enrichir les SBOM. Dites-nous ce que vous aimeriez voir, et n’hésitez pas à partager des exemples de vos expérimentations avec parlay.