

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
<a name="sbomgen-plugin-developer-guide"></a>

 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](sbomgen-plugin-api-reference.md) o. Para obter orientação sobre como escrever testes, consulte [Guia de teste de plug-ins](sbomgen-plugin-testing-guide.md) o. 

## Visão geral do
<a name="sbomgen-plugin-developer-guide-overview"></a>

 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
<a name="sbomgen-plugin-developer-guide-plugin-event-model"></a>

 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](#sbomgen-plugin-developer-guide-plugin-collision-rules). 

 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 name="sbomgen-plugin-developer-guide-quick-start-creating-new-plugins"></a>

 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
<a name="sbomgen-plugin-developer-guide-starting-with-a-working-example"></a>

 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_name``get_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
<a name="sbomgen-plugin-developer-guide-completing-your-plugin"></a>

 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
<a name="sbomgen-plugin-developer-guide-test-your-plugin"></a>

 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](sbomgen-plugin-testing-guide.md) para obter detalhes sobre como escrever arquivos de teste e usar a `testing.*` API. 

 **2. End-to-end**scan — 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
<a name="sbomgen-plugin-developer-guide-ide-setup"></a>

 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
<a name="sbomgen-plugin-developer-guide-vs-code-with-lua-language-server"></a>
+ Instale a extensão Lua: [sumneko.lua](https://marketplace.visualstudio.com/items?itemName=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
<a name="sbomgen-plugin-developer-guide-plugin-directory-structure"></a>

 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
<a name="sbomgen-plugin-developer-guide-platform"></a>

 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
<a name="sbomgen-plugin-developer-guide-category"></a>

 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](#sbomgen-plugin-developer-guide-scanner-selection) 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
<a name="sbomgen-plugin-developer-guide-ecosystem"></a>

 Um nome para o ecossistema de pacotes específico (por exemplo`python-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
<a name="sbomgen-plugin-developer-guide-event-name-pairing"></a>

 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
<a name="sbomgen-plugin-developer-guide-discovery-plugins"></a>

 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 pip`package.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
<a name="sbomgen-plugin-developer-guide-common-discovery-patterns"></a>


| **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](sbomgen-plugin-api-reference.md) para obter detalhes. 

### Descoberta de vários eventos
<a name="sbomgen-plugin-developer-guide-multi-event-discovery"></a>

 Por padrão, todos os arquivos `discover()` retornados por são publicados em um único evento (de`get_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
<a name="sbomgen-plugin-developer-guide-optional-discovery-functions"></a>

 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
<a name="sbomgen-plugin-developer-guide-localhost-scan-paths"></a>

 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
<a name="sbomgen-plugin-developer-guide-platform-specific-scan-paths"></a>

 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` ou`PROGRAMFILES`, itere `sbomgen.get_env_vars()` e pesquise o valor por chave. Consulte o [Referência da API de plug-in](sbomgen-plugin-api-reference.md) para obter detalhes. 

## Plugins de coleção
<a name="sbomgen-plugin-developer-guide-collection-plugins"></a>

 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 `name``purl_type`, `component_type` e. Consulte o [Referência da API de plug-in](sbomgen-plugin-api-reference.md) para ver todos os campos compatíveis. 

### Anexando metadados aos componentes
<a name="sbomgen-plugin-developer-guide-attaching-metadata-to-components"></a>

 **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
<a name="sbomgen-plugin-developer-guide-purl-qualifiers"></a>

 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?](https://docs.aws.amazon.com/inspector/latest/user/sbom-generator-purl-sbom.html) 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 em`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",
    },
})
```

 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
<a name="sbomgen-plugin-developer-guide-cyclonedx-properties"></a>

 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](https://docs.aws.amazon.com/inspector/latest/user/cyclonedx-namespace.html) 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
<a name="sbomgen-plugin-developer-guide-key-naming-rules"></a>

 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
<a name="sbomgen-plugin-developer-guide-properties-and-qualifiers-on-child-components"></a>

 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
<a name="sbomgen-plugin-developer-guide-optional-collection-functions"></a>


| **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
<a name="sbomgen-plugin-developer-guide-running-your-plugins"></a>

 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.txt``package.json`, ou arquivos de manifesto de pacote equivalentes). 

### Uso básico
<a name="sbomgen-plugin-developer-guide-basic-usage"></a>

```
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)
<a name="sbomgen-plugin-developer-guide-with-native-scanners-disabled-lua-only-mode"></a>

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

### Com registro detalhado
<a name="sbomgen-plugin-developer-guide-with-verbose-logging"></a>

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

## Listando scanners disponíveis
<a name="sbomgen-plugin-developer-guide-listing-available-scanners"></a>

 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
<a name="sbomgen-plugin-developer-guide-scanner-selection"></a>

 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
<a name="sbomgen-plugin-developer-guide-run-only-specific-scanners"></a>

 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
<a name="sbomgen-plugin-developer-guide-exclude-specific-scanners"></a>

 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, exceto`python-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**  
`--scanners`e `--skip-scanners` são mutuamente exclusivos. Passar os dois produz um erro.

### Adicione scanners de grupos não padrão
<a name="sbomgen-plugin-developer-guide-add-scanners-from-non-default-groups"></a>

 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](#sbomgen-plugin-developer-guide-how-groups-affect-selection) 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, mais`my-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 name="sbomgen-plugin-developer-guide-how-groups-affect-selection"></a>

 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: 
+ **`custom`**está 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 `container``localhost`, e, mas não para `directory``archive`, 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ção`list-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`) em`get_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
<a name="sbomgen-plugin-developer-guide-plugin-collision-rules"></a>

 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
<a name="sbomgen-plugin-developer-guide-what-is-checked"></a>


| **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
<a name="sbomgen-plugin-developer-guide-what-is-allowed"></a>

 Vários plug-ins de coleção **podem** se inscrever no mesmo evento via`subscribe_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
<a name="sbomgen-plugin-developer-guide-avoiding-collisions"></a>

 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
<a name="sbomgen-plugin-developer-guide-collision-warning-example"></a>

```
[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
<a name="sbomgen-plugin-developer-guide-debugging"></a>

### Registro em log do console
<a name="sbomgen-plugin-developer-guide-console-logging"></a>

 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_info``log_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
<a name="sbomgen-plugin-developer-guide-breakpoints"></a>

 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
<a name="sbomgen-plugin-developer-guide-common-issues"></a>


| **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
<a name="sbomgen-plugin-developer-guide-api-reference"></a>

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

 **→ [Referência da API de plug-in](sbomgen-plugin-api-reference.md)** 

 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
<a name="sbomgen-plugin-developer-guide-error-handling"></a>

 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
<a name="sbomgen-plugin-developer-guide-sandbox-restrictions"></a>

 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
<a name="sbomgen-plugin-developer-guide-sharing-code-between-plugins"></a>

 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. 