View a markdown version of this page

Guia do desenvolvedor de plug-ins - Amazon Inspector

As traduções são geradas por tradução automática. Em caso de conflito entre o conteúdo da tradução e da versão original em inglês, a versão em inglês prevalecerá.

Guia do desenvolvedor de plug-ins

Este guia explica como estender o Amazon Inspector SBOM Generator (inspector-sbomgen) com plug-ins Lua personalizados. Os plug-ins permitem que você adicione suporte para novos ecossistemas de pacotes sem modificar o código-fonte do sbomgen ou ter que recompilar.

Para obter o catálogo completo de funções, consulte Referência da API de plug-in o. Para obter orientação sobre como escrever testes, consulte Guia de teste de plug-ins o.

Visão geral do

Os plug-ins Sbomgen são escritos em Lua e seguem um pipeline de duas etapas:

  • Descoberta — escaneie a lista de arquivos do artefato e relate quais arquivos são relevantes para o seu ecossistema.

  • Coleção — analise cada arquivo descoberto e envie as descobertas do pacote para o SBOM.

Modelo de evento de plug-in

Os plug-ins do Discovery precisam de uma forma de informar aos plug-ins de coleção que os arquivos contendo metadados do pacote foram descobertos no artefato em inventário. Para facilitar esse compartilhamento de dados, os plug-ins de descoberta definem um nome de evento e retornam uma lista de caminhos de arquivo. Os plug-ins de coleção se inscrevem nesse evento e recebem cada caminho de arquivo correspondente. Isso dissocia a detecção de arquivos da análise — você pode fazer com que um plug-in de descoberta alimente vários coletores (padrão de distribuição). No entanto, cada plug-in de descoberta deve ter um nome de evento exclusivo e cada plug-in de coleção deve ter um nome de coletor exclusivo. Para mais detalhes, consulte Regras de colisão de plug-ins.

Os desenvolvedores podem reconhecer isso como o padrão de design do observador.

Esse design permite que um único plug-in de descoberta acione várias análises independentes de maneira eficiente. Por exemplo, um plug-in de descoberta pode localizar tudo requirements.txt em um artefato e, em seguida, alimentar:

  • Um coletor de pacotes que analisa cada linha nas descobertas do SBOM (). name==version

  • Um coletor de segredos que sinaliza linhas contendo chaves de API ou tokens fixados acidentalmente como versões.

  • Um coletor de políticas que relata especificadores de versão não fixados ou com caracteres curinga.

Cada coletor é executado de forma independente na mesma lista de arquivos sem precisar alterar o sistema de arquivos do artefato. Isso também permite que os autores de plug-ins adicionem novos plug-ins de coleção que se inscrevem em eventos existentes sem precisar alterar o plug-in de descoberta correspondente.

Início rápido: criação de novos plug-ins

A maneira mais rápida de criar um novo plug-in é usando o comando scaffolding embutido:

inspector-sbomgen plugin new

O comando solicita o nome do plug-in e o diretório do projeto. Pressionar Enter aceita o padrão mostrado entre colchetes:

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]:

Você também pode passar argumentos diretamente:

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

Começando com um exemplo prático

Se você quiser experimentar plug-ins antes de escrever sua própria lógica, crie um novo plug-in usando a --with-example bandeira:

inspector-sbomgen plugin new --with-example

Isso gera um projeto de plug-in totalmente funcional com um exemplo de analisador de arquivo de bloqueio, dados de teste e testes de aprovação. O plug-in de exemplo descobre example.lock arquivos, analisa name==version entradas e envia pacotes para o SBOM. Você pode executar os testes imediatamente para ver o sistema de plug-ins em ação e, em seguida, modificar o código para atingir seu ecossistema real.

Para andaimes avançados que incluem todas as funções de substituição opcionais (get_scanner_name,, get_event_nameget_scanner_groups, descoberta de vários eventos etc.), use a --with-overrides bandeira (falaremos mais sobre isso posteriormente):

inspector-sbomgen plugin new --with-overrides

Completando seu plug-in

Depois da montagem, os arquivos de plug-in gerados contêm TODO marcadores indicando onde adicionar sua lógica específica do ecossistema. Use esses marcadores para transformar o andaime em um plug-in funcional:

  • Substitua todos TODO os marcadores por seus valores reais

  • Atualize o padrão de arquivo discover() para corresponder aos seus arquivos de destino

  • Implemente a lógica de análise collect() e chame sbomgen.push_package() cada pacote

Teste seu plug-in

Há duas maneiras de testar seus plug-ins:

1. Equipamento de teste integrado — Use inspector-sbomgen plugin test para validar a lógica do plug-in durante o desenvolvimento. Isso executa seus arquivos init_test.lua de teste sem precisar de um artefato real para digitalizar:

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

Consulte o Guia de teste de plug-ins para obter detalhes sobre como escrever arquivos de teste e usar a testing.* API.

2. End-to-endscan — Invoque seu plug-in usando comandos sbomgen padrão para verificar se ele funciona com artefatos reais. Para essa abordagem, você precisa fornecer um artefato contendo os arquivos de destino do plug-in (por exemplo, um diretório com requirements.txt ou equivalente) e o caminho para o diretório do plug-in:

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

O --disable-native-scanners sinalizador garante que somente seus plug-ins Lua sejam executados, facilitando o teste sem a saída dos scanners integrados (nativos).

Configuração do IDE

O Sbomgen fornece preenchimento de código, verificação de tipos e documentação embutida para toda a sbomgen.* API no VS Code.

Código VS com servidor de linguagem Lua

  • Instale a extensão Lua: sumneko.lua

  • Abra qualquer .lua arquivo no seu projeto de plug-in

Isso é tudo! O plugin new comando é library/sbomgen.lua gerado .vscode/settings.json e detectado automaticamente pelo Lua Language Server. Você receberá imediatamente:

  • Preenchimento de código para todas as sbomgen.* funções

  • Dicas de parâmetros com tipos

  • Documentação do mouse

  • Verificação de tipo

Estrutura do diretório de plug-ins

Os plug-ins de descoberta e coleta do Sbomgen devem seguir a seguinte estrutura de diretórios:

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

Esses nomes de diretório têm significado semântico — sbomgen os usa para derivar metadados padrão para seu plug-in, incluindo o nome do scanner, o nome do evento, os grupos de scanners e a filtragem da plataforma. Isso reduz a quantidade de textos padronizados que os desenvolvedores teriam que escrever de outra forma. A escolha dos valores corretos garante que seu plug-in se integre adequadamente ao modelo de seleção e execução do scanner sbomgen.

As seções abaixo exploram a estrutura de diretórios com mais detalhes, fornecendo orientação sobre o significado semântico e as convenções.

Plataforma

O diretório da plataforma controla em quais sistemas operacionais seu plug-in é executado.

Valor Quando usar
cross-platform O plug-in funciona em qualquer sistema operacional (a maioria dos plug-ins)
linux Lógica de detecção específica para Linux
windows Lógica de detecção específica para Windows
macos Lógica de detecção específica para macOS

Categoria

O diretório de categorias determina os grupos de scanners padrão atribuídos ao seu plug-in, que controla se ele é executado por padrão ou se requer aceitação explícita. Veja como Seleção do scanner os grupos afetam a execução.

Valor Grupos padrão Quando usar
proglang programming-language-packages, pkg-scanner Pacotes de linguagens de programação (pip, npm, maven, etc.)
os os, pkg-scanner Gerenciadores de pacotes do sistema operacional (dpkg, rpm, apk etc.)
extra-ecosystems extra-ecosystems, pkg-scanner Aplicativos e tempos de execução (nginx, curl, wordpress etc.)

Se você usar um nome de categoria que não corresponda a nenhum dos itens acima, o nome da categoria em si será usado como grupo.

Ecossistema

Um nome para o ecossistema de pacotes específico (por exemplopython-pip,,python-poetry,debian-dpkg,curl). Nomes com hífen são uma convenção comum, mas não um requisito estrito.

O nome do scanner e o nome do coletor são derivados diretamente do nome do diretório do ecossistema.

Combinação de nomes de eventos

Os plug-ins de descoberta e coleta no mesmo caminho de diretório são automaticamente emparelhados. Por exemplo, um plug-in de descoberta é emparelhado discovery/cross-platform/proglang/python-pip/ automaticamente com collection/cross-platform/proglang/python-pip/ o.

Você pode substituir isso definindo get_event_name() e subscribe_to_event() em seus plug-ins.

Plugins de descoberta

Um plug-in de descoberta requer apenas a discover() função. Todas as outras funções são opcionais — os padrões são derivados do caminho do diretório.

A maioria dos plug-ins de descoberta funciona localizando arquivos cujos nomes ou caminhos identificam um ecossistema específico — por exemplo, requirements.txt para Python pippackage.json, para npm ou para Rust cargo. Cargo.lock As sbomgen.find_files_by_* funções realizam essa correspondência fora da VM Lua, o que as torna significativamente mais rápidas do que a iteração da lista completa de arquivos em Lua:

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

discover()deve retornar uma tabela Lua (matriz) de strings. Se nenhum arquivo for encontrado, retorne uma tabela vazia{}.

Padrões de descoberta comuns

Objetivo Função recomendada
Combine um ou mais nomes de arquivo exatos sbomgen.find_files_by_name({names})
Combine nomes de arquivos sem distinção entre maiúsculas e minúsculas sbomgen.find_files_by_name_icase({names})
Correspondência por sufixo de caminho (por exemplo,/pom.properties) sbomgen.find_files_by_suffix({suffixes})
Combine por regex de caminho completo sbomgen.find_files_by_path_regex({patterns})
Correspondência de nome de base no estilo Glob (por exemplo,) *.lock sbomgen.glob_find_files(pattern)

Quando sua lógica exige pós-filtragem — por exemplo, manter arquivos com um sufixo, mas excluir diretórios de compilação e saída — combine uma chamada com um loop Lua: find_files_by_*

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

Evite sbomgen.get_file_list() a descoberta, a menos que nenhum outro combinador se encaixe — ele copia todos os caminhos para a Lua VM e pode levar vários segundos em artefatos grandes. Consulte o Referência da API de plug-in para obter detalhes.

Descoberta de vários eventos

Por padrão, todos os arquivos discover() retornados por são publicados em um único evento (deget_event_name()). Se o scanner precisar rotear arquivos diferentes para coletores diferentes, retorne uma tabela com chave em vez disso:

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

Quando discover() retorna uma tabela com chaves de string, cada chave é tratada como um nome de evento separado e seu valor (uma tabela de caminhos de arquivo) é publicado nesse evento. Os plug-ins de coleção se inscrevem em subscribe_to_event() eventos específicos normalmente.

Isso é compatível com versões anteriores — retornar uma tabela sequencial {"file1", "file2"} ainda funciona como modo de evento único. A detecção é automática: tabelas com qualquer chave de string são multieventos, tabelas com apenas chaves inteiras (ou vazias) são eventos únicos.

Ao usar vários eventos, não get_event_name() é usado para publicação (os nomes dos eventos vêm das chaves da tabela retornadas). No entanto, ele ainda é chamado durante o carregamento do plug-in para detecção de colisão, portanto, ele deve retornar um valor exclusivo ou ser omitido para usar o padrão.

Funções de descoberta opcionais

Todos eles têm padrões sensatos derivados do caminho do diretório. Defina-os somente se você precisar substituí-los:

Função Padrão Substituir quando...
get_scanner_name() {ecosystem}(por exemplo,python-pip) Você quer um nome de scanner personalizado
get_scanner_description() "Lua discovery plugin: {ecosystem}" Você quer uma descrição personalizada
get_scanner_groups() Derivado do diretório de categorias Você precisa de grupos não padrão
get_event_name() Derivado do caminho do diretório Você precisa de um roteamento de eventos personalizado
get_localhost_scan_paths() Nenhum Seu plug-in precisa de caminhos específicos escaneados durante localhost as varreduras

Caminhos de escaneamento do localhost

Quando o sbomgen executa uma localhost varredura, ele percorre os diretórios especificados pelo usuário, além de quaisquer caminhos padrão declarados pelos scanners. Por padrão, os plug-ins de descoberta do Lua não contribuem com nenhum caminho, portanto, arquivos fora dos diretórios especificados pelo usuário não aparecerão na lista de arquivos.

get_localhost_scan_paths()Defina para retornar diretórios ou caminhos de arquivo que o localhost walker deve incluir:

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

Os caminhos retornados são anexados à lista de escaneamento do andador somente durante localhost os escaneamentos — eles não têm efeito sobre container os escaneamentos. directory archive

Caminhos de escaneamento específicos da plataforma

Quando os arquivos que você gosta estão em locais diferentes no Windows, macOS e Linux, ramifique sbomgen.get_platform() e retorne os caminhos apropriados para o host:

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

No Windows, use sbomgen.get_system_drive() para resolver a letra da unidade do sistema (por exemplo,"C:") em vez de codificá-la. Para caminhos derivados de variáveis de ambiente, como LOCALAPPDATA ouPROGRAMFILES, itere sbomgen.get_env_vars() e pesquise o valor por chave. Consulte o Referência da API de plug-in para obter detalhes.

Plugins de coleção

Um plug-in de coleção requer apenas a collect() função. Todas as outras funções são opcionais.

collect(file_path)é chamado uma vez por arquivo descoberto pelo plug-in de descoberta emparelhado. O padrão típico é:

  • Leia o conteúdo do arquivo usando sbomgen.read_file() (para arquivos pequenos carregados na memória) ou sbomgen.open_file() (para leitura de arquivos grandes line-by-line).

  • Analise o conteúdo — correspondência de strings para manifestos simples, sbomgen.json_decode() para JSON, para XML ou sbomgen.xml_decode() sbomgen.search_binary() para binários compilados.

  • Publique cada pacote descoberto chamando sbomgen.push_package() com os metadados do pacote.

-- 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()não retorna um valor. Cada push_package() chamada requer namepurl_type, component_type e. Consulte o Referência da API de plug-in para ver todos os campos compatíveis.

Anexando metadados aos componentes

O Sbomgen suporta duas maneiras de anexar metadados a um componente do pacote: qualificadores PURL e propriedades do CycloneDX. Eles servem a propósitos diferentes, e a escolha entre eles tem implicações na forma como o Amazon Inspector identifica vulnerabilidades no SBOM resultante.

Mecanismo Onde aparece Use para
qualifiers Dentro da URL do pacote (por exemplo,pkg:deb/debian/curl@7.88.1?arch=amd64) Dados que fazem parte da identidade do pacote
properties Na matriz do SBOM components[].properties Metadados descritivos que não alteram a forma como o pacote é identificado

Recomendação: prefira as propriedades do CycloneDX (em seu próprio namespace) para metadados personalizados. As propriedades não alteram a identidade de um componente, portanto, não podem afetar a identificação da vulnerabilidade do Amazon Inspector. Reserve qualificadores de PURL para casos em que o tipo de PURL do seu ecossistema os exija.

qualificadores PURL

Alguns qualificadores de PURL têm significado semântico para o Amazon Inspector e influenciam a identificação de vulnerabilidades. Por exemplo, em deb componentes, o Inspector usa qualificadores como arch e distro para selecionar o feed de vulnerabilidade correto; em generic componentes para binários compilados, qualificadores como go_toolchain ou rust_toolchain identificam a cadeia de ferramentas usada. Definir um qualificador que o Inspector não reconhece, ou omitir um que ele espera, pode fazer com que as vulnerabilidades sejam perdidas ou atribuídas incorretamente.

Consulte O que é um URL de pacote? no guia do usuário do Amazon Inspector para as convenções de qualificadores que o Inspector reconhece por tipo de PURL.

Defina as eliminatórias por meio da qualifiers tabela emsbomgen.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", }, })

Defina qualificadores somente quando eles se alinharem às expectativas do Inspetor em relação ao tipo de PURL. Se você precisar registrar metadados que não façam parte da identidade do pacote, use as propriedades do CycloneDX.

Propriedades do CycloneDX

As propriedades CyclonedX são anotações de valores-chave que aparecem na matriz do SBOM. components[].properties Eles descrevem um componente sem afetar a forma como ele é identificado, portanto, são a escolha segura para metadados definidos por plug-ins.

Os amazon:inspector:* namespaces são reservados para o Amazon Inspector. Especificamente:

  • amazon:inspector:sbom_generator:*— reservado para o sbomgen e seus scanners integrados.

  • amazon:inspector:sbom_scanner:*— reservado para a API Amazon Inspector Scan.

Os autores de plug-ins não devem emitir chaves dentro desses namespaces reservados. Escrever neles pode interferir no comportamento do Inspetor e pode ser sobrescrito. Para obter a lista completa de chaves reservadas, consulte Usando namespaces CycloneDX com o Amazon Inspector.

Use seu próprio namespace (normalmente seu identificador de organização ou plug-in) ao definir propriedades:

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", }, })

Principais regras de nomenclatura

As chaves de propriedade são processadas pelo sbomgen da seguinte forma:

  • Uma chave que contém dois pontos é usada literalmente no SBOM. Sempre inclua pelo menos dois pontos em suas chaves para controlar o namespace.

  • Uma chave que não contém dois pontos é automaticamente prefixada com amazon:inspector:sbom_generator: — colocando-a dentro do namespace reservado do Inspector. Evite essa forma para propriedades personalizadas.

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

As sbomgen.properties.* constantes existem para que os scanners oficiais emitam chaves consistentes dentro do namespace reservado. Eles não são pontos de extensão para plug-ins personalizados. Em vez disso, use seu próprio namespace.

Propriedades e qualificadores em componentes secundários

Os componentes aninhados children são independentes. Cada filho tem suas próprias qualifiers tabelas; properties os metadados definidos no pai não se propagam para os filhos. Defina valores explicitamente para cada criança que precisa deles.

Funções de coleta opcionais

Função Padrão Substituir quando...
get_collector_name() {ecosystem}(por exemplo,python-pip) Você quer um nome de coletor personalizado
get_collector_description() string vazia Você quer uma descrição?
subscribe_to_event() Derivado do caminho do diretório Você precisa de um roteamento de eventos personalizado

Executando seus plug-ins

Para que os plug-ins produzam metadados de pacotes, o sbomgen deve receber um artefato para escanear que contenha os arquivos de destino do plug-in (por exemplo, um diretório com requirements.txtpackage.json, ou arquivos de manifesto de pacote equivalentes).

Uso básico

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

Exemplo:

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

Com os scanners nativos desativados (modo somente LUA)

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

Com registro detalhado

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

Listando scanners disponíveis

Use list-scanners para ver todos os scanners disponíveis para o sbomgen. Isso inclui os scanners nativos integrados, todos os plug-ins oficiais do Lua fornecidos com o sbomgen e quaisquer plug-ins Lua personalizados que você tenha fornecido por meio de: --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 │ └─────────────────────┴────────┴───────────────────────────────┴─────────────────────────────┘

A coluna SOURCE mostra de onde vem cada scanner:

Origem Significado
native Scanner embutido fornecido com sbomgen
official Plugins Lua fornecidos com sbomgen
custom Plugin Lua fornecido pelo usuário carregado via --plugin-dir

A execução list-scanners sem --plugin-dir ainda inclui ambos native e official scanners — eles estão sempre disponíveis. A --plugin-dir bandeira adiciona seus custom scanners ao anúncio.

Para listar somente scanners Lua sem scanners nativos:

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

Seleção do scanner

Os plug-ins Lua discovery participam do mesmo modelo de seleção de scanner dos scanners nativos integrados. Por padrão, o sbomgen executa todos os scanners cujos grupos correspondem aos grupos de scanners padrão para o tipo de artefato. Você pode substituir isso com três sinalizadores:

Execute somente scanners específicos

Use --scanners para executar somente os scanners nomeados. Todos os outros scanners estão excluídos:

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

Isso executa somente o python-requirements scanner. Você pode passar vários nomes de scanner separados por vírgulas ou passar um nome de grupo de scanners (por exemplo,programming-language-packages) para habilitar cada scanner que pertença a esse grupo.

Excluir scanners específicos

Use --skip-scanners para excluir scanners nomeados enquanto executa todo o resto:

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

Isso executa todos os scanners padrão, excetopython-poetry. Por exemplo--scanners, esse sinalizador também aceita nomes de grupos, portanto, a passagem --skip-scanners programming-language-packages desativa todos os scanners desse grupo.

nota

--scannerse --skip-scanners são mutuamente exclusivos. Passar os dois produz um erro.

Adicione scanners de grupos não padrão

O conjunto de scanners padrão depende do tipo de artefato que está sendo digitalizado (veja a matriz Como os grupos afetam a seleção abaixo). Um scanner cujos grupos não façam parte do conjunto padrão para o tipo de artefato não será executado a menos que você o ative. Use --additional-scanners para acrescentar scanners ao conjunto padrão sem substituí-lo:

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

Isso executa todos os scanners padrão para o tipo de artefato, maismy-extra-scanner. O sinalizador aceita uma lista separada por vírgulas de nomes de scanners ou nomes de grupos e se acumula com o conjunto padrão em vez de substituí-lo. Use list-scanners para verificar a quais grupos um scanner pertence.

Como os grupos afetam a seleção

A get_scanner_groups() função em seu plug-in de descoberta determina a quais grupos o scanner pertence. A execução de um scanner por padrão depende de seus grupos e do tipo de artefato que está sendo escaneado. A matriz abaixo mostra quais grupos estão incluídos no conjunto de scanners padrão para cada tipo de artefato:

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

A ✓ significa que todos os scanners desse grupo são executados por padrão para esse tipo de artefato. A significa que o grupo não está no conjunto padrão, portanto, seus scanners só são executados se selecionados explicitamente por meio --scanners de ou. --additional-scanners

Detalhes notáveis:

  • customestá sempre no conjunto padrão — plug-ins personalizados carregados via recebem --plugin-dir automaticamente o custom grupo, então eles são executados por padrão, independentemente do tipo de artefato.

  • extra-ecosystemsé padrão para volume escaneamentos containerlocalhost, e, mas não para directoryarchive, ou binary escaneamentos. Para esses tipos, você deve passar --additional-scanners (pelo nome ou pelo extra-ecosystems grupo) para incluí-los.

  • pkg-scanneré informativo — marca um scanner como um coletor de pacotes para exibiçãolist-scanners, mas, por si só, não faz com que o scanner seja executado. Combine-o com um grupo de execução (por exemplo,programming-language-packages) emget_scanner_groups().

Por exemplo, um plug-in que retorna {sbomgen.groups.EXTRA_ECOSYSTEMS, sbomgen.groups.PACKAGE_COLLECTOR} será executado por padrão em escaneamentos de contêiner, localhost e volume, mas exigirá --additional-scanners (ou--scanners) escaneamentos de diretórios, arquivamentos e binários.

Regras de colisão de plug-ins

O Sbomgen impõe metadados exclusivos em todos os plug-ins carregados para evitar substituições silenciosas e garantir a integridade do SBOM. Quando uma colisão é detectada, o plug-in posterior é ignorado e um aviso é registrado.

O que é verificado

Metadados Escopo Em caso de colisão
Nome do evento Discovery (get_event_name) Todos os plug-ins de descoberta Segundo plugin ignorado
Nome do scanner (get_scanner_name) Todos os plug-ins de descoberta Segundo plugin ignorado
Nome do coletor () get_collector_name Todos os plug-ins da coleção Segundo plugin ignorado

O que é permitido

Vários plug-ins de coleção podem se inscrever no mesmo evento viasubscribe_to_event(). Esse é o padrão de distribuição pretendido: um plug-in de descoberta pode alimentar vários coletores, cada um fazendo coisas diferentes (por exemplo, um extrai pacotes, outro detecta segredos).

Evitando colisões

Se dois plug-ins usarem o mesmo nome de scanner, nome do evento ou nome do coletor, o segundo carregado será ignorado. Para resolver colisões, renomeie os metadados conflitantes definindo a função de substituição apropriada em seu plug-in (get_scanner_name(), ou). get_event_name() get_collector_name()

Exemplo de aviso de colisão

[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.

O aviso informa qual plug-in foi ignorado, o que colidiu, qual plug-in já possui esse nome e qual função alterar.

Depuração

Registro em log do console

Os plug-ins podem emitir mensagens para a saída do console do sbomgen usando as seguintes funções:

Função Nível Visível por padrão?
sbomgen.log_debug(message) DEBUG Não — requer --verbose
sbomgen.log_info(message) INFO Sim
sbomgen.log_warn(message) WARN Sim
sbomgen.log_error(message) ERROR Sim

Toda a saída de log de um plug-in é automaticamente prefixada com a origem e o caminho do plug-in (por exemplo,[custom:python-pip]), para que as mensagens de diferentes plug-ins sejam fáceis de distinguir. log_infolog_warn, e log_error sempre imprime; log_debug só imprime quando sbomgen é invocado com. --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

Pontos de interrupção

Use sbomgen.breakpoint() para pausar a execução do plug-in e bloquear até pressionar Enter. Isso funciona como um depurador básico — combine-o com instruções de registro para inspecionar o estado em pontos específicos.

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

A mensagem do ponto de interrupção é impressa em stderr. A execução é pausada até você pressionar Enter, dando tempo para revisar a saída do log.

Problemas comuns

Sintomas Causa Corrigir
Plugin não carregado init.lua ausente Certifique-se de que o ponto de entrada exista na profundidade correta do diretório
“falta a função necessária” Erro de digitação no nome da função Verifique seget_scanner_name,get_scanner_description,get_scanner_groups,discover,get_event_name,get_localhost_scan_paths,get_collector_name,collect, subscribe_to_event estão definidos
O plugin de coleção nunca foi chamado Incompatibilidade do nome do evento Verifique get_event_name() e subscribe_to_event() retorne a mesma string
Nenhum pacote no SBOM push_packagenão chamado ou faltam campos obrigatórios Certifique-se de que namepurl_type, e component_type estão configurados em todas as push_package chamadas (incluindo crianças). Use sbomgen.component_types.* constantes.
Erro de tempo de execução no plugin Erro Lua durante a execução Verifique a saída sbomgen para mensagens de aviso com os detalhes do erro
“IGNORADO: nome do evento de descoberta... já está registrado” Outro plugin usa o mesmo nome de evento Renomear get_event_name() para um valor exclusivo
“IGNORADO: nome do scanner... já está registrado” Outro plugin usa o mesmo nome de scanner Renomear get_scanner_name() para um valor exclusivo
“IGNORADO: nome do colecionador... já está registrado” Outro plugin usa o mesmo nome de coletor Renomear get_collector_name() para um valor exclusivo

Referência da API

O catálogo completo de funções é mantido em um documento complementar:

Referência da API de plug-in

A referência da API abrange todas as sbomgen.* funções (E/S de arquivo, utilitários binários, saída de pacote, regex, análise estruturada, registro do Windows, registro, depuração), a testing.* API disponível em arquivos de teste, todas as constantes integradas (properties,,,) e os dados globais do ciclo de vida do groups component_types plug-in. platform

Tratamento de erros

Funções de API que podem falhar retornam dois valores:value, err. Sobre o sucesso, err énil. Em caso de falha, o primeiro valor é nil e err é uma string de erro.

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

Se um plug-in gerar um erro Lua não tratado, o sbomgen registra um aviso e continua com o próximo arquivo ou plug-in. Outros plug-ins não são afetados.

Restrições do Sandbox

Os plug-ins são executados em uma VM Lua em sandbox com acesso limitado à biblioteca padrão:

Ferramentas Disponível Observações
base dofile,loadfile, loadstring são removidos
string Manipulação completa de strings
table Manipulação completa da tabela
math Biblioteca matemática completa
package require()restrito ao diretório de plug-ins
io Em vez disso, use sbomgen.* I/O funções
os Bloqueado por motivos de segurança
debug Bloqueado para evitar a introspecção da VM
coroutine Não carregado

Acesso direto ao sistema de arquivos via io.open ou não os.execute está disponível. Todas as operações de arquivo devem passar pela sbomgen API, o que garante um comportamento consistente em todos os tipos de artefato e impede que plug-ins acessem arquivos fora do artefato.

require()pode carregar módulos somente de dentro da própria árvore de diretórios do plug-in. A travessia do diretório principal, como está bloqueada. require("../shared")

Compartilhamento de código entre plug-ins

Você pode usar require() para carregar módulos auxiliares de dentro do diretório do seu 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

Também há suporte para init.lua subdiretórios com:

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

require()está restrito ao diretório do seu plugin. Você não pode carregar módulos de outros plug-ins ou caminhos do sistema. Bibliotecas Lua de terceiros (por exemplo, from LuaRocks) não são suportadas — somente módulos auxiliares locais dentro do diretório do plug-in podem ser carregados.