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
TODOmarqueurs 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 appelsbomgen.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
-
Ouvrez n'importe quel
.luafichier dans votre projet de plugin
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) ousbomgen.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 ousbomgen.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-dirautomatiquement lecustomgroupe, de sorte qu'ils s'exécutent par défaut quel que soit le type d'artefact. -
extra-ecosystemsest par défaut pourcontainerlocalhost, etvolumescanne, mais pas pourdirectoryarchive, oubinaryscanne. Pour ces types, vous devez passer--additional-scanners(par nom ou parextra-ecosystemsgroupe) 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.