View a markdown version of this page

Guide du développeur de plugins - Amazon Inspector

Les traductions sont fournies par des outils de traduction automatique. En cas de conflit entre le contenu d'une traduction et celui de la version originale en anglais, la version anglaise prévaudra.

Guide du développeur de plugins

Ce guide explique comment étendre le générateur Amazon Inspector SBOM (inspectors-sbomgen) avec des plugins Lua personnalisés. Les plugins vous permettent de prendre en charge de nouveaux écosystèmes de paquets sans modifier le code source de sbomgen ni avoir à le recompiler.

Pour le catalogue complet des fonctions, consultez leRéférence de l'API du plugin. Pour obtenir des conseils sur la rédaction de tests, consultez leGuide de test des plugins.

Présentation de

Les plugins Sbomgen sont écrits en Lua et suivent un pipeline en deux étapes :

  • Découverte : scannez la liste des fichiers de l'artefact et signalez quels fichiers sont pertinents pour votre écosystème.

  • Collection — analyse chaque fichier découvert et transfère les résultats du package dans le SBOM.

Modèle d'événement du plugin

Les plugins de découverte ont besoin d'un moyen d'indiquer aux plugins de collection que des fichiers contenant des métadonnées de package ont été découverts dans l'artefact en cours d'inventaire. Pour faciliter ce partage de données, les plugins de découverte définissent un nom d'événement et renvoient une liste de chemins de fichiers. Les plugins de collection s'abonnent à cet événement et reçoivent chaque chemin de fichier correspondant. Cela permet de dissocier la détection des fichiers de l'analyse : un plugin de découverte peut alimenter plusieurs collecteurs (modèle de fan-out). Cependant, chaque plugin de découverte doit avoir un nom d'événement unique, et chaque plugin de collection doit avoir un nom de collecteur unique. Consultez Règles de collision des plugins pour plus de détails.

Les développeurs peuvent le reconnaître comme le modèle de conception de l'observateur.

Cette conception permet à un seul plugin de découverte de déclencher plusieurs analyses indépendantes de manière performante. Par exemple, un plugin de découverte peut localiser chaque élément requirements.txt d'un artefact, puis alimenter :

  • Un collecteur de packages qui analyse chaque ligne dans les résultats SBOM (). name==version

  • Un collecteur de secrets qui signale les lignes contenant des clés d'API ou des jetons accidentellement épinglés en tant que versions.

  • Un collecteur de politiques qui signale les spécificateurs de version non épinglés ou génériques.

Chaque collecteur s'exécute indépendamment sur la même liste de fichiers sans avoir à modifier le système de fichiers de l'artefact. Cela permet également aux auteurs de plugins d'ajouter de nouveaux plugins de collection qui s'abonnent aux événements existants sans avoir à modifier le plugin de découverte correspondant.

Démarrage rapide : création de nouveaux plugins

Le moyen le plus rapide de créer un nouveau plugin est d'utiliser la commande d'échafaudage intégrée :

inspector-sbomgen plugin new

La commande demande le nom du plugin et le répertoire du projet. Appuyez sur Entrée pour accepter la valeur par défaut indiquée entre crochets :

Plugin name (identifies the software ecosystem your plugin will inventory, e.g. debian-dpkg, rhel-rpm, python-pip, cmake) [my-custom-ecosystem]: cmake Project directory [my-sbomgen-plugins]:

Vous pouvez également transmettre des arguments directement :

inspector-sbomgen plugin new --name cmake --path /tmp/custom-plugins

Commencer par un exemple pratique

Si vous souhaitez expérimenter avec des plugins avant d'écrire votre propre logique, créez un nouveau plugin en utilisant le --with-example drapeau :

inspector-sbomgen plugin new --with-example

Cela génère un projet de plugin entièrement fonctionnel avec un exemple d'analyseur de fichier de verrouillage, des données de test et des tests réussis. L'exemple de plugin découvre example.lock les fichiers, analyse les name==version entrées et envoie les packages dans le SBOM. Vous pouvez exécuter les tests immédiatement pour voir le système de plugins en action, puis modifier le code pour cibler votre écosystème actuel.

Pour un échafaudage avancé qui inclut toutes les fonctions de dérogation optionnelles (get_scanner_name,,, get_event_nameget_scanner_groups, découverte de plusieurs événements, etc.), utilisez le --with-overrides drapeau (nous y reviendrons plus loin) :

inspector-sbomgen plugin new --with-overrides

Compléter votre plugin

Après l'échafaudage, les fichiers de plug-in générés contiennent des TODO marqueurs indiquant où ajouter la logique spécifique à votre écosystème. Utilisez ces marqueurs pour transformer l'échafaudage en un plugin fonctionnel :

  • Remplacez tous les TODO marqueurs par vos valeurs réelles

  • Mettez à jour le modèle de fichier discover() pour qu'il corresponde à vos fichiers cibles

  • Implémenter une logique d'analyse collect() et un appel sbomgen.push_package() pour chaque package

Testez votre plugin

Il existe deux manières de tester vos plugins :

1. Harnais de test intégré : inspector-sbomgen plugin test à utiliser pour valider la logique du plugin pendant le développement. Cela exécute vos fichiers de init_test.lua test sans avoir besoin d'un véritable artefact à scanner :

inspector-sbomgen plugin test --path ./my-plugins

Consultez le Guide de test des plugins pour plus de détails sur l'écriture de fichiers de test et l'utilisation de l'testing.*API.

2. End-to-endscan — Appelez votre plugin à l'aide des commandes standard sbomgen pour vérifier qu'il fonctionne avec de vrais artefacts. Pour cette approche, vous devez fournir à la fois un artefact contenant les fichiers que votre plugin cible (par exemple, un répertoire avec requirements.txt ou équivalent) et le chemin d'accès au répertoire de votre plugin :

inspector-sbomgen directory \ --path /path/to/test/dir \ --plugin-dir ./my-plugins \ --disable-native-scanners \ -o sbom.json

L'--disable-native-scannersindicateur garantit que seuls vos plugins Lua s'exécutent, ce qui facilite les tests sans sortie des scanners (natifs) intégrés.

Configuration de l'IDE

Sbomgen fournit la complétion du code, la vérification de type et la documentation en ligne pour l'ensemble de l'sbomgen.*API dans VS Code.

VS Code avec serveur de langage Lua

Voilà tout! La plugin new commande génère .vscode/settings.json et library/sbomgen.lua est automatiquement détectée par le serveur de langue Lua. Vous obtiendrez immédiatement :

  • Complétion du code pour toutes les sbomgen.* fonctions

  • Indications de paramètres avec types

  • Survolez la documentation

  • Vérification du type

Structure du répertoire des plugins

Les plugins de découverte et de collecte Sbomgen doivent respecter la structure de répertoires suivante :

{plugin-dir}/ ├── discovery/ │ └── {platform}/ │ └── {category}/ │ └── {ecosystem}/ │ └── init.lua # REQUIRED entrypoint └── collection/ └── {platform}/ └── {category}/ └── {ecosystem}/ └── init.lua # REQUIRED entrypoint

Ces noms de répertoires ont une signification sémantique : sbomgen les utilise pour dériver les métadonnées par défaut de votre plugin, notamment le nom du scanner, le nom de l'événement, les groupes de scanners et le filtrage de plateforme. Cela réduit le nombre de tâches standard que les développeurs auraient autrement à écrire. Le choix des bonnes valeurs garantit que votre plugin s'intègre correctement au modèle de sélection et d'exécution du scanner de sbomgen.

Les sections ci-dessous explorent la structure du répertoire plus en détail, en fournissant des conseils sur le sens sémantique et les conventions.

Plateforme

Le répertoire de la plateforme contrôle les systèmes d'exploitation sur lesquels votre plugin s'exécute.

Valeur Quand l’utiliser
cross-platform Le plugin fonctionne sur n'importe quel système d'exploitation (la plupart des plugins)
linux Logique de détection spécifique à Linux
windows Logique de détection spécifique à Windows
macos Logique de détection spécifique à macOS

Catégorie

Le répertoire des catégories détermine les groupes de scanners par défaut assignés à votre plugin, qui détermine s'il s'exécute par défaut ou s'il nécessite une inscription explicite. Découvrez comment Sélection du scanner les groupes affectent l'exécution.

Valeur Groupes par défaut Quand l’utiliser
proglang programming-language-packages, pkg-scanner Paquets de langage de programmation (pip, npm, maven, etc.)
os os, pkg-scanner gestionnaires de paquets du système d'exploitation (dpkg, rpm, apk, etc.)
extra-ecosystems extra-ecosystems, pkg-scanner Applications et environnements d'exécution (nginx, curl, wordpress, etc.)

Si vous utilisez un nom de catégorie qui ne correspond à aucune des catégories ci-dessus, le nom de catégorie lui-même est utilisé comme groupe.

Écosystème

Nom de l'écosystème de packages spécifique (par exemplepython-pip,python-poetry,debian-dpkg,curl). Les noms avec trait d'union sont une convention courante, mais pas une obligation stricte.

Le nom du scanner et le nom du collecteur sont dérivés directement du nom du répertoire de l'écosystème.

Jumelage des noms de l'événement

Les plugins de découverte et de collecte situés sur le même chemin de répertoire sont automatiquement associés. Par exemple, un plugin de découverte at discovery/cross-platform/proglang/python-pip/ se couple automatiquement aveccollection/cross-platform/proglang/python-pip/.

Vous pouvez contourner cela en définissant get_event_name() et subscribe_to_event() dans vos plugins.

Plug-ins Discovery

Un plugin de découverte n'a besoin que de cette discover() fonction. Toutes les autres fonctions sont facultatives ; les valeurs par défaut sont dérivées du chemin du répertoire.

La plupart des plugins de découverte fonctionnent en localisant les fichiers dont les noms ou les chemins identifient un écosystème spécifique, par exemple, requirements.txt pour Python pip, package.json pour npm ou Cargo.lock pour Rust cargo. Les sbomgen.find_files_by_* fonctions effectuent cette correspondance en dehors de la machine virtuelle Lua, ce qui les rend nettement plus rapides que l'itération de la liste complète des fichiers dans Lua :

-- REQUIRED: Scans the artifact and returns a table of file paths. function discover() return sbomgen.find_files_by_name({"requirements.txt"}) end

discover()doit renvoyer une table Lua (tableau) de chaînes. Si aucun fichier n'est trouvé, renvoyez une table vide{}.

Modèles de découverte courants

Objectif Fonction recommandée
Faites correspondre un ou plusieurs noms de fichiers exacts sbomgen.find_files_by_name({names})
Faites correspondre les noms de fichiers sans distinction majuscules/majuscules sbomgen.find_files_by_name_icase({names})
Correspondance par suffixe de chemin (par exemple,/pom.properties) sbomgen.find_files_by_suffix({suffixes})
Correspondance par regex à chemin complet sbomgen.find_files_by_path_regex({patterns})
Correspondance du nom de base de style global (par exemple,) *.lock sbomgen.glob_find_files(pattern)

Lorsque votre logique nécessite un post-filtrage, par exemple en conservant les fichiers correspondant à un suffixe mais en excluant les répertoires de construction et de sortie, combinez un find_files_by_* appel avec une boucle Lua :

function discover() local found = {} for _, f in ipairs(sbomgen.find_files_by_suffix({".conda-meta.json"})) do if not f:match("[/\\]%.cache[/\\]") then table.insert(found, f) end end return found end

Évitez sbomgen.get_file_list() le processus de découverte à moins qu'aucun autre outil de comparaison ne vous convienne : il copie tous les chemins dans la machine virtuelle Lua et peut prendre plusieurs secondes sur de gros artefacts. Consultez le Référence de l'API du plugin pour plus de détails.

Découverte de plusieurs événements

Par défaut, tous les fichiers renvoyés par discover() sont publiés dans un seul événement (depuisget_event_name()). Si votre scanner doit acheminer différents fichiers vers différents collecteurs, renvoyez plutôt un tableau à clés :

function discover() return { EventNameFoundCurl = sbomgen.find_files_by_name({"curl", "curl.exe"}), EventNameFoundLibcurl = sbomgen.find_files_by_name({"curlver.h"}), } end

Lors du discover() renvoi d'une table contenant des chaînes de clés, chaque clé est traitée comme un nom d'événement distinct et sa valeur (une table des chemins de fichiers) est publiée dans cet événement. Les plugins de collection s'abonnent à des événements spécifiques subscribe_to_event() comme d'habitude.

Ceci est rétrocompatible : le renvoi d'une table séquentielle fonctionne {"file1", "file2"} toujours en mode événement unique. La détection est automatique : les tables avec n'importe quelle chaîne de clés sont multi-événements, les tables avec uniquement des clés entières (ou vides) sont des tables à événement unique.

Lors de l'utilisation de plusieurs événements, get_event_name() il n'est pas utilisé pour la publication (les noms des événements proviennent des clés de table renvoyées). Cependant, il est toujours appelé pendant le chargement du plugin pour détecter les collisions. Il doit donc renvoyer une valeur unique ou être omis pour utiliser la valeur par défaut.

Fonctions de découverte facultatives

Tous ces éléments ont des valeurs par défaut saines dérivées du chemin du répertoire. Définissez-les uniquement si vous devez remplacer :

Fonction Par défaut Annuler lorsque...
get_scanner_name() {ecosystem}(par exemple,python-pip) Vous souhaitez un nom de scanner personnalisé
get_scanner_description() "Lua discovery plugin: {ecosystem}" Vous souhaitez une description personnalisée
get_scanner_groups() Dérivé du répertoire des catégories Vous avez besoin de groupes non standard
get_event_name() Dérivé du chemin du répertoire Vous avez besoin d'un routage d'événements personnalisé
get_localhost_scan_paths() Aucune Votre plugin a besoin de chemins spécifiques scannés lors localhost des scans

Chemins d'analyse de l'hôte local

Lorsque sbomgen exécute une localhost analyse, il parcourt les répertoires spécifiés par l'utilisateur ainsi que les chemins par défaut déclarés par les scanners. Par défaut, les plugins de découverte Lua ne fournissent aucun chemin, de sorte que les fichiers situés en dehors des répertoires spécifiés par l'utilisateur n'apparaîtront pas dans la liste des fichiers.

Définissez get_localhost_scan_paths() pour renvoyer les répertoires ou les chemins de fichiers que le localhost walker doit inclure :

function get_localhost_scan_paths() return { "/usr/bin", "/usr/local/bin", } end

Les chemins renvoyés sont ajoutés à la liste de scan du marcheur uniquement pendant les localhost scans ; ils n'ont aucun effet sur container directory les archive scans.

Chemins d'analyse spécifiques à la plate-forme

Lorsque les fichiers qui vous intéressent se trouvent à différents emplacements sous Windows, macOS et Linux, branchez sbomgen.get_platform() et renvoyez les chemins appropriés pour l'hôte :

function get_localhost_scan_paths() local platform = sbomgen.get_platform() if platform == sbomgen.platform.WINDOWS then local drive = sbomgen.get_system_drive() return { drive .. "/Program Files/MyApp/myapp.exe", drive .. "/Program Files (x86)/MyApp/myapp.exe", } end if platform == sbomgen.platform.DARWIN then return {"/Applications/MyApp.app/Contents/MacOS/myapp"} end -- Linux return { "/usr/bin/myapp", "/usr/local/bin/myapp", } end

Sous Windows, utilisez-le sbomgen.get_system_drive() pour résoudre la lettre du lecteur système (par exemple,"C:") plutôt que de la coder en dur. Pour les chemins dérivés de variables d'environnement telles que LOCALAPPDATA ouPROGRAMFILES, itérez sbomgen.get_env_vars() et recherchez la valeur par clé. Consultez le Référence de l'API du plugin pour plus de détails.

Plug-ins de collection

Un plugin de collecte n'a besoin que de collect() cette fonction. Toutes les autres fonctions sont facultatives.

collect(file_path)est appelé une fois par fichier découvert par le plugin de découverte jumelé. Le schéma typique est le suivant :

  • Lisez le contenu du fichier en utilisant sbomgen.read_file() (pour les petits fichiers chargés en mémoire) ou sbomgen.open_file() (pour les gros fichiers lus line-by-line).

  • Analyse le contenu : correspondance de chaînes pour les manifestes simples, sbomgen.json_decode() pour le JSON, sbomgen.xml_decode() pour le XML ou sbomgen.search_binary() pour les binaires compilés.

  • Publiez chaque package découvert en appelant sbomgen.push_package() avec les métadonnées du package.

-- REQUIRED: Called once per discovered file. -- Parse the file and call sbomgen.push_package() for each package found. function collect(file_path) local content, err = sbomgen.read_file(file_path) if err or not content then return end for line in content:gmatch("[^\r\n]+") do local name, version = line:match("^([%w%-%_%.]+)==(.+)$") if name and version then sbomgen.push_package({ name = name, version = version, purl_type = "pypi", component_type = sbomgen.component_types.LIBRARY, }) end end end

collect()ne renvoie aucune valeur. Chaque push_package() appel nécessite namepurl_type, etcomponent_type. Consultez le Référence de l'API du plugin pour tous les champs pris en charge.

Joindre des métadonnées aux composants

Sbomgen propose deux méthodes pour associer des métadonnées à un composant de package : les qualificatifs PURL et les propriétés CyclonedX. Ils ont des objectifs différents, et le choix entre les deux a une incidence sur la manière dont Amazon Inspector identifie les vulnérabilités dans le SBOM qui en résulte.

Mécanisme Où il apparaît Utiliser pour
qualifiers Dans l'URL du package (par exemple,pkg:deb/debian/curl@7.88.1?arch=amd64) Données faisant partie de l'identité du package
properties Dans le tableau du SBOM components[].properties Métadonnées descriptives qui ne modifient pas la façon dont le package est identifié

Recommandation : préférez les propriétés CycloneDx (sous votre propre espace de noms) pour les métadonnées personnalisées. Les propriétés ne modifient pas l'identité d'un composant, elles ne peuvent donc pas avoir d'impact sur l'identification des vulnérabilités par Amazon Inspector. Réservez les qualificatifs PURL dans les cas où le type PURL de votre écosystème les exige.

Qualifications PURL

Certains qualificatifs PURL ont une signification sémantique pour Amazon Inspector et influencent l'identification des vulnérabilités. Par exemple, sur les deb composants, Inspector utilise des qualificatifs tels que arch et distro pour sélectionner le bon flux de vulnérabilités ; sur les generic composants pour les fichiers binaires compilés, des qualificatifs tels que go_toolchain ou pour rust_toolchain identifier la chaîne d'outils utilisée. En définissant un qualificatif qu'Inspector ne reconnaît pas ou en omettant un qualificatif attendu, des vulnérabilités peuvent être ignorées ou mal attribuées.

Voir Qu'est-ce qu'une URL de package ? dans le guide de l'utilisateur d'Amazon Inspector pour connaître les conventions de qualification reconnues par Inspector par type de PURL.

Définissez les qualificatifs via le qualifiers tableau sur sbomgen.push_package() :

sbomgen.push_package({ name = "curl", version = "7.88.1", purl_type = "deb", namespace = "debian", component_type = sbomgen.component_types.LIBRARY, qualifiers = { arch = "amd64", distro = "debian-12", }, })

Définissez des qualificatifs uniquement lorsqu'ils correspondent aux attentes de l'inspecteur concernant le type de PURL. Si vous devez enregistrer des métadonnées qui ne font pas partie de l'identité du package, utilisez plutôt les propriétés CyclonedX.

Propriétés de CycloneDx

Les propriétés CycloneDx sont des annotations clé-valeur qui apparaissent dans le tableau du SBOM. components[].properties Ils décrivent un composant sans affecter la façon dont il est identifié. Ils constituent donc le choix le plus sûr pour les métadonnées définies par le plugin.

Les amazon:inspector:* espaces de noms sont réservés à Amazon Inspector. En particulier :

  • amazon:inspector:sbom_generator:*— réservé à Sbomgen et à ses scanners intégrés.

  • amazon:inspector:sbom_scanner:*— réservé à l'API Amazon Inspector Scan.

Les auteurs de plugins ne doivent pas émettre de clés dans ces espaces de noms réservés. Le fait d'y écrire peut interférer avec le comportement de l'inspecteur et peut être remplacé. Pour obtenir la liste complète des clés réservées, consultez la section Utilisation des espaces de noms CycloneDX avec Amazon Inspector.

Utilisez votre propre espace de noms (généralement l'identifiant de votre organisation ou de votre plugin) lors de la définition des propriétés :

sbomgen.push_package({ name = "requests", version = "2.28.1", purl_type = "pypi", component_type = sbomgen.component_types.LIBRARY, properties = { ["acme:python:manifest_path"] = file_path, ["acme:python:pinned"] = "true", ["acme:python:source"] = "requirements.txt", }, })

Principales règles de dénomination

Les clés de propriété sont traitées par sbomgen comme suit :

  • Une touche contenant deux points est utilisée mot pour mot dans le SBOM. Incluez toujours au moins deux points dans vos clés afin de contrôler l'espace de noms.

  • Une clé qui ne contient pas de deux-points est automatiquement préfixée par amazon:inspector:sbom_generator: : elle est placée dans l'espace de noms réservé de l'Inspector. Évitez cette forme pour les propriétés personnalisées.

properties = { ["acme:my_plugin:detected_via"] = "lockfile", -- used as-is (recommended) detected_via = "lockfile", -- becomes "amazon:inspector:sbom_generator:detected_via" (avoid) }

Les sbomgen.properties.* constantes existent de telle sorte que les scanners officiels émettent des clés cohérentes dans l'espace de noms réservé. Ce ne sont pas des points d'extension pour les plugins personnalisés. Utilisez plutôt votre propre espace de noms.

Propriétés et qualificatifs des composants enfants

Des composants indépendants children sont imbriqués. Chaque enfant possède ses propres qualifiers tables ; properties les métadonnées définies sur le parent ne se propagent pas aux enfants. Définissez des valeurs de manière explicite pour chaque enfant qui en a besoin.

Fonctions de collecte optionnelles

Fonction Par défaut Annuler lorsque...
get_collector_name() {ecosystem}(par exemple,python-pip) Vous souhaitez un nom de collectionneur personnalisé
get_collector_description() chaîne vide Vous souhaitez une description
subscribe_to_event() Dérivé du chemin du répertoire Vous avez besoin d'un routage d'événements personnalisé

Exécution de vos plugins

Pour que les plugins produisent des métadonnées de package, sbomgen doit recevoir un artefact à scanner contenant les fichiers cibles de votre plugin (par exemple, un répertoire contenant requirements.txt des fichiers manifestes de package ou des fichiers équivalents). package.json

Utilisation de base

inspector-sbomgen <artifact type> <arguments> --plugin-dir /path/to/plugins

Exemple :

inspector-sbomgen directory --path /target -o /tmp/sbom.json --plugin-dir /path/to/plugins

Lorsque les scanners natifs sont désactivés (mode LUA uniquement)

inspector-sbomgen directory --path /target --plugin-dir /path/to/plugins --disable-native-scanners -o sbom.json

Avec journalisation détaillée

inspector-sbomgen directory --path /target --plugin-dir /path/to/plugins --verbose -o sbom.json

Liste des scanners disponibles

list-scannersÀ utiliser pour voir tous les scanners disponibles pour sbomgen. Cela inclut les scanners natifs intégrés, tous les plugins Lua officiels fournis avec sbomgen et tous les plugins Lua personnalisés que vous avez fournis via : --plugin-dir

inspector-sbomgen list-scanners --plugin-dir /path/to/plugins
┌─────────────────────┬────────┬───────────────────────────────┬─────────────────────────────┐ │ SCANNER NAME │ SOURCE │ GROUPS │ DESCRIPTION │ ├─────────────────────┼────────┼───────────────────────────────┼─────────────────────────────┤ │ curl │ custom │ extra-ecosystems │ Discovers curl version │ │ │ │ pkg-scanner │ header files (curlver.h) │ ├─────────────────────┼────────┼───────────────────────────────┼─────────────────────────────┤ │ python-requirements │ custom │ pkg-scanner │ Discovers requirements*.txt │ │ │ │ programming-language-packages │ files for Python pip │ │ │ │ │ packages │ └─────────────────────┴────────┴───────────────────────────────┴─────────────────────────────┘

La colonne SOURCE indique d'où provient chaque scanner :

Source Signification
native Scanner intégré fourni avec sbomgen
official Plugins Lua fournis avec sbomgen
custom Plugin Lua fourni par l'utilisateur et chargé via --plugin-dir

Running list-scanners without --plugin-dir still inclut à la fois les deux native et les official scanners, qui sont toujours disponibles. Le --plugin-dir drapeau ajoute vos custom scanners à la liste.

Pour répertorier uniquement les scanners Lua sans scanners natifs :

inspector-sbomgen list-scanners --plugin-dir /path/to/plugins --disable-native-scanners

Sélection du scanner

Les plugins Lua Discovery participent au même modèle de sélection de scanner que les scanners natifs intégrés. Par défaut, sbomgen exécute tous les scanners dont les groupes correspondent aux groupes de scanners par défaut pour le type d'artefact. Vous pouvez remplacer cela par trois indicateurs :

Exécutez uniquement des scanners spécifiques

--scannersÀ utiliser pour exécuter uniquement les scanners nommés. Tous les autres scanners sont exclus :

inspector-sbomgen directory --path /target \ --plugin-dir /path/to/plugins \ --scanners python-requirements \ -o sbom.json

Cela ne fait fonctionner que le python-requirements scanner. Vous pouvez transmettre plusieurs noms de scanner séparés par des virgules ou transmettre un nom de groupe de scanners (par exemple,programming-language-packages) pour activer tous les scanners appartenant à ce groupe.

Exclure des scanners spécifiques

--skip-scannersÀ utiliser pour exclure les scanners nommés lors de l'exécution de tout le reste :

inspector-sbomgen directory --path /target \ --plugin-dir /path/to/plugins \ --skip-scanners python-poetry \ -o sbom.json

Cela exécute tous les scanners par défaut, à l'exception depython-poetry. Par exemple--scanners, cet indicateur accepte également les noms de groupes, de sorte que le passage --skip-scanners programming-language-packages désactive tous les scanners de ce groupe.

Note

--scannerset s'--skip-scannersexcluent mutuellement. Le fait de passer les deux produit une erreur.

Ajouter des scanners provenant de groupes autres que ceux par défaut

Le jeu de scanner par défaut dépend du type d'artefact numérisé (voir la matrice Comment les groupes affectent la sélection ci-dessous). Un scanner dont les groupes ne font pas partie de la configuration par défaut pour le type d'artefact ne s'exécutera pas si vous ne l'activez pas. --additional-scannersÀ utiliser pour ajouter des scanners à l'ensemble par défaut sans le remplacer :

inspector-sbomgen directory --path /target \ --plugin-dir /path/to/plugins \ --additional-scanners my-extra-scanner \ -o sbom.json

Cela exécute tous les scanners par défaut pour le type d'artefact, en plusmy-extra-scanner. L'indicateur accepte une liste de noms de scanneurs ou de groupes séparés par des virgules, et s'empile avec l'ensemble par défaut au lieu de le remplacer. Permet list-scanners de vérifier à quels groupes appartient un scanner.

Comment les groupes affectent la sélection

La get_scanner_groups() fonction de votre plug-in de découverte détermine les groupes auxquels appartient le scanner. Le fonctionnement par défaut d'un scanner dépend à la fois de ses groupes et du type d'artefact numérisé. La matrice ci-dessous indique quels groupes sont inclus dans le jeu de scanners par défaut pour chaque type d'artefact :

Groupe directory / archive container localhost volume binary
os
programming-language-packages
binary
extra-ecosystems
dockerfile
custom
certificate
machine-learning
pkg-scanner

A ✓ signifie que tous les scanners de ce groupe s'exécutent par défaut pour ce type d'artefact. A signifie que le groupe n'est pas dans l'ensemble par défaut, de sorte que ses scanners ne s'exécutent que s'ils sont explicitement sélectionnés via --scanners ou--additional-scanners.

Détails importants :

  • customest toujours dans l'ensemble par défaut : les plugins personnalisés chargés via reçoivent --plugin-dir automatiquement le custom groupe, de sorte qu'ils s'exécutent par défaut quel que soit le type d'artefact.

  • extra-ecosystemsest par défaut pour containerlocalhost, et volume scanne, mais pas pour directoryarchive, ou binary scanne. Pour ces types, vous devez passer --additional-scanners (par nom ou par extra-ecosystems groupe) pour les inclure.

  • pkg-scannerest informatif : il marque un scanner comme un collecteur de packages dans lequel il doit être affichélist-scanners, mais ne provoque pas à lui seul le fonctionnement du scanner. Associez-le à un groupe d'exécution (par exemple,programming-language-packages) dansget_scanner_groups().

Par exemple, un plugin qui renvoie s'{sbomgen.groups.EXTRA_ECOSYSTEMS, sbomgen.groups.PACKAGE_COLLECTOR}exécutera par défaut lors des scans de conteneurs, de localhost et de volumes, mais nécessitera --additional-scanners (ou--scanners) des scans de répertoires, d'archives et de fichiers binaires.

Règles de collision des plugins

Sbomgen applique des métadonnées uniques à tous les plugins chargés afin d'empêcher les remplacements silencieux et de garantir l'intégrité du SBOM. Lorsqu'une collision est détectée, le dernier plugin est ignoré et un avertissement est enregistré.

Ce qui est vérifié

Metadonnées Scope (Portée) En cas de collision
Nom de l'événement Discovery (get_event_name) Tous les plugins de découverte Deuxième plugin ignoré
Nom du scanner (get_scanner_name) Tous les plugins de découverte Deuxième plugin ignoré
Nom du collectionneur (get_collector_name) Tous les plugins de collection Deuxième plugin ignoré

Ce qui est autorisé

Plusieurs plugins de collecte peuvent s'abonner au même événement viasubscribe_to_event(). C'est le modèle de ventilation prévu : un plugin de découverte peut alimenter plusieurs collecteurs qui font chacun des choses différentes (par exemple, l'un extrait des packages, un autre détecte des secrets).

Éviter les collisions

Si deux plug-ins utilisent le même nom de scanner, le même nom d'événement ou le même nom de collecteur, le deuxième module chargé est ignoré. Pour résoudre les collisions, renommez les métadonnées en conflit en définissant la fonction de remplacement appropriée dans votre plugin (get_scanner_name(),get_event_name(), ouget_collector_name()).

Exemple d'avertissement de collision

[custom:python-pip] SKIPPED: discovery event name "EventNameFoundPythonRequirements" is already registered by [official:python-pip]. Each discovery plugin must have a unique event name. Rename get_event_name() in your plugin to use a unique name.

L'avertissement vous indique quel plugin a été ignoré, quel plugin est entré en collision, quel plugin possède déjà ce nom et quelle fonction modifier.

Débogage

Journalisation de la console

Les plugins peuvent émettre des messages vers la sortie de console de sbomgen à l'aide des fonctions suivantes :

Fonction Niveau Visible par défaut ?
sbomgen.log_debug(message) DEBUG Non, nécessite --verbose
sbomgen.log_info(message) INFO Oui
sbomgen.log_warn(message) WARN Oui
sbomgen.log_error(message) ERROR Oui

Toutes les sorties de journal d'un plugin sont automatiquement préfixées avec la source et le chemin du plugin (par exemple,[custom:python-pip]), de sorte que les messages des différents plugins sont faciles à distinguer. log_infolog_warn, et log_error toujours imprimer ; log_debug n'imprime que lorsque sbomgen est invoqué avec. --verbose

function discover() sbomgen.log_info("starting discovery") local files = sbomgen.find_files_by_name({"requirements.txt"}) sbomgen.log_debug(string.format("matched %d files", #files)) if #files == 0 then sbomgen.log_warn("no requirements.txt files found") end return files end

Points d'arrêt

sbomgen.breakpoint()À utiliser pour suspendre l'exécution du plugin et le bloquer jusqu'à ce que vous appuyiez sur Entrée. Cela agit comme un débogueur rudimentaire : combinez-le avec des instructions de journal pour inspecter l'état à des points spécifiques.

function discover() local files = sbomgen.find_files_by_name({"requirements.txt"}) sbomgen.log_info(string.format("about to inspect %d files", #files)) sbomgen.breakpoint("before file inspection — press Enter to continue") local found = {} for _, f in ipairs(files) do if not f:match("[/\\]tests[/\\]") then table.insert(found, f) end end sbomgen.log_info(string.format("kept %d files after filtering", #found)) sbomgen.breakpoint("after filtering — press Enter to continue") return found end

Le message du point d'arrêt est imprimé sur stderr. L'exécution est interrompue jusqu'à ce que vous appuyiez sur Entrée, ce qui vous laisse le temps de consulter les résultats du journal.

Problèmes courants

Symptôme Cause Corriger
Plugin non chargé init.lua manquant Assurez-vous que le point d'entrée existe à la bonne profondeur du répertoire
« fonction requise manquante » Faute de frappe dans le nom de la fonction Vérifiez queget_scanner_name,get_scanner_description,get_scanner_groups, discoverget_event_name,get_localhost_scan_paths,get_collector_name,collect, subscribe_to_event sont définis
Le plugin de collection n'a jamais été appelé Incompatibilité du nom de l'événement Vérifiez get_event_name() et subscribe_to_event() renvoyez la même chaîne
Aucun package dans SBOM push_packagenon appelé ou champs obligatoires manquants Assurez-vous que namepurl_type, et component_type sont définis dans chaque push_package appel (y compris pour les enfants). Utilisez sbomgen.component_types.* des constantes.
Erreur d'exécution dans le plugin Erreur Lua lors de l'exécution Vérifiez la sortie de sbomgen pour les messages d'avertissement contenant les détails de l'erreur
« IGNORÉ : le nom de l'événement de découverte... est déjà enregistré » Un autre plugin utilise le même nom d'événement Renommer get_event_name() en une valeur unique
« IGNORÉ : le nom du scanner... est déjà enregistré » Un autre plugin utilise le même nom de scanner Renommer get_scanner_name() en une valeur unique
« IGNORÉ : le nom du collectionneur... est déjà enregistré » Un autre plugin utilise le même nom de collecteur Renommer get_collector_name() en une valeur unique

Référence d’API

Le catalogue complet des fonctions est conservé dans un document d'accompagnement :

Référence de l'API du plugin

La référence d'API couvre toutes les sbomgen.* fonctions (E/S de fichiers, utilitaires binaires, sortie de package, regex, analyse structurée, registre Windows, journalisation, débogage), l'testing.*API disponible dans les fichiers de test, toutes les constantes intégrées (,, properties groupscomponent_types,platform) et le cycle de vie global du plugin.

Gestion des erreurs

Les fonctions d'API qui peuvent échouer renvoient deux valeurs :value, err. Sur le succès, err c'estnil. En cas d'échec, la première valeur est nil et err est une chaîne d'erreur.

local content, err = sbomgen.read_file(path) if err then sbomgen.log_error("failed to read " .. path .. ": " .. err) return end -- content is safe to use here

Si un plugin génère une erreur Lua non gérée, sbomgen enregistre un avertissement et passe au fichier ou au plugin suivant. Les autres plugins ne sont pas concernés.

Restrictions relatives au sandbox

Les plugins s'exécutent dans une machine virtuelle Lua en sandbox avec un accès limité à la bibliothèque standard :

d'outils Disponible Remarques
base dofile,loadfile, loadstring sont supprimés
string Manipulation complète des chaînes
table Manipulation complète du tableau
math Bibliothèque mathématique complète
package require()limité au répertoire des plugins
io Utilisez plutôt sbomgen.* I/O des fonctions
os Bloqué pour des raisons de sécurité
debug Bloqué pour empêcher l'introspection des machines virtuelles
coroutine Non chargé

L'accès direct au système de fichiers via io.open ou n'os.executeest pas disponible. Toutes les opérations sur les fichiers doivent passer par l'sbomgenAPI, ce qui garantit un comportement cohérent entre les types d'artefacts et empêche les plug-ins d'accéder à des fichiers extérieurs à l'artefact.

require()peut charger des modules uniquement à partir de l'arborescence de répertoires du plugin. La traversée du répertoire parent est telle que require("../shared") bloquée.

Partage de code entre plugins

Vous pouvez utiliser require() pour charger des modules d'assistance depuis le répertoire de votre plugin :

my-ecosystem/ ├── init.lua └── helpers.lua
-- helpers.lua local M = {} function M.parse_version(s) return string.match(s, "(%d+%.%d+%.%d+)") end return M
-- init.lua local helpers = require("helpers") function subscribe_to_event() return "MyEvent" end function collect(file_path) local content, err = sbomgen.read_file(file_path) if err then return end local version = helpers.parse_version(content) -- ... end

Les sous-répertoires avec init.lua sont également pris en charge :

my-ecosystem/ ├── init.lua └── parsers/ └── init.lua
local parsers = require("parsers")

require()est limité au répertoire de votre plugin. Vous ne pouvez pas charger de modules à partir d'autres plugins ou chemins système. Les bibliothèques Lua tierces (par exemple, from LuaRocks) ne sont pas prises en charge : seuls les modules d'assistance locaux situés dans le répertoire du plugin peuvent être chargés.