

Las traducciones son generadas a través de traducción automática. En caso de conflicto entre la traducción y la version original de inglés, prevalecerá la version en inglés.

# Guía para desarrolladores de complementos
<a name="sbomgen-plugin-developer-guide"></a>

 Esta guía explica cómo ampliar Amazon Inspector SBOM Generator (inspector-sbomgen) con complementos de Lua personalizados. Los complementos le permiten añadir soporte para nuevos ecosistemas de paquetes sin modificar el código fuente de sbomgen ni tener que volver a compilarlo. 

 Para ver el catálogo completo de funciones, consulte la. [Referencia de la API de complementos](sbomgen-plugin-api-reference.md) Para obtener orientación sobre la redacción de las pruebas, consulte la[Guía de pruebas de complementos](sbomgen-plugin-testing-guide.md). 

## Descripción general de
<a name="sbomgen-plugin-developer-guide-overview"></a>

 Los complementos de Sbomgen están escritos en Lua y siguen un proceso de dos pasos: 
+ **Descubrimiento**: escanea la lista de archivos del artefacto e informa qué archivos son relevantes para tu ecosistema.
+ **Recopilación**: analiza cada archivo descubierto e introduce los resultados del paquete en la SBOM.

### Modelo de eventos del complemento
<a name="sbomgen-plugin-developer-guide-plugin-event-model"></a>

 Los complementos de descubrimiento necesitan una forma de indicar a los complementos de la colección que los archivos que contienen metadatos del paquete se han descubierto en el artefacto que se encuentra en el inventario. Para facilitar este intercambio de datos, los complementos de detección definen un **nombre de evento** y devuelven una lista de las rutas de los archivos. Los complementos de recopilación se **suscriben** a ese evento y reciben todas las rutas de archivo coincidentes. Esto desvincula la detección de archivos del análisis: puede hacer que un complemento de descubrimiento alimente varios recopiladores (patrón de distribución en abanico). Sin embargo, cada complemento de descubrimiento debe tener un nombre de evento único y cada complemento de colección debe tener un nombre de recopilador único. Para obtener más información, consulte [Reglas de colisión de complementos](#sbomgen-plugin-developer-guide-plugin-collision-rules). 

 Los desarrolladores pueden reconocer esto como el patrón de diseño del **observador**. 

 Este diseño permite que un único complemento de descubrimiento desencadene múltiples análisis independientes de forma eficaz. Por ejemplo, un complemento de descubrimiento puede localizar todos los `requirements.txt` elementos de un artefacto y, a continuación, alimentar: 
+ Un **recopilador de paquetes** que analiza cada línea para obtener los resultados de la SBOM (). `name==version`
+ Un **recopilador de secretos** que marca las líneas que contienen claves de API o tokens anclados accidentalmente como versiones.
+ Un **recopilador de políticas** que informa sobre los especificadores de versiones no anclados o con caracteres comodín.

 Cada recopilador utiliza de forma independiente la misma lista de archivos sin tener que revisar el sistema de archivos del artefacto. Esto también permite a los autores de complementos añadir nuevos complementos de colección que se suscriban a los eventos existentes sin tener que cambiar el complemento de descubrimiento correspondiente. 

## Inicio rápido: creación de nuevos complementos
<a name="sbomgen-plugin-developer-guide-quick-start-creating-new-plugins"></a>

 La forma más rápida de crear un nuevo complemento es mediante el comando scaffolding incorporado: 

```
inspector-sbomgen plugin new
```

 El comando solicita el nombre del plugin y el directorio del proyecto. Al pulsar Entrar, se acepta el valor predeterminado que se muestra entre paréntesis: 

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

 También puede pasar los argumentos directamente: 

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

### Empezando con un ejemplo práctico
<a name="sbomgen-plugin-developer-guide-starting-with-a-working-example"></a>

 Si quieres experimentar con los complementos antes de escribir tu propia lógica, crea un nuevo complemento con la siguiente `--with-example` bandera: 

```
inspector-sbomgen plugin new --with-example
```

 Esto genera un proyecto de plugin completamente funcional con un ejemplo de analizador de archivos bloqueados, datos de prueba y pruebas de superación. El plugin de ejemplo descubre `example.lock` archivos, analiza `name==version` entradas y envía paquetes a la SBOM. Puedes ejecutar las pruebas inmediatamente para ver el sistema de complementos en acción y, a continuación, modificar el código para adaptarlo a tu ecosistema real. 

 Para un andamiaje avanzado que incluya todas las funciones de anulación opcionales (`get_scanner_name`,, `get_event_name``get_scanner_groups`, detección de eventos múltiples, etc.), usa la `--with-overrides` marca (hablaremos de esto más adelante): 

```
inspector-sbomgen plugin new --with-overrides
```

### Completando tu complemento
<a name="sbomgen-plugin-developer-guide-completing-your-plugin"></a>

 Tras el andamiaje, los archivos de complementos generados contienen `TODO` marcadores que indican dónde añadir la lógica específica del ecosistema. Revisa estos marcadores para convertir el andamio en un complemento funcional: 
+ Sustituya todos los `TODO` marcadores por sus valores reales
+ Actualice el patrón del archivo `discover()` para que coincida con los archivos de destino
+ Implemente la lógica de análisis `collect()` y `sbomgen.push_package()` solicite cada paquete

### Pruebe su complemento
<a name="sbomgen-plugin-developer-guide-test-your-plugin"></a>

 Hay dos formas de probar tus complementos: 

 **1. Arnés de pruebas integrado**: se utiliza `inspector-sbomgen plugin test` para validar la lógica del plugin durante el desarrollo. Esto ejecuta tus archivos `init_test.lua` de prueba sin necesidad de escanear un artefacto real: 

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

 Consulte [Guía de pruebas de complementos](sbomgen-plugin-testing-guide.md) para obtener más información sobre la escritura de archivos de prueba y el uso de la `testing.*` API. 

 **2. End-to-end**escanear: invoca tu complemento con los comandos estándar de sbomgen para comprobar que funciona con artefactos reales. Para este enfoque, debes proporcionar un artefacto que contenga los archivos a los que apunta tu complemento (por ejemplo, un directorio `requirements.txt` o equivalente) y la ruta al directorio de tu complemento: 

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

 El `--disable-native-scanners` indicador garantiza que solo se ejecuten tus complementos de Lua, lo que facilita las pruebas sin la salida de los escáneres integrados (nativos). 

## Configuración del IDE
<a name="sbomgen-plugin-developer-guide-ide-setup"></a>

 Sbomgen proporciona la finalización del código, la verificación de tipos y la documentación en línea para toda la `sbomgen.*` API de VS Code. 

### VS Code con Lua Language Server
<a name="sbomgen-plugin-developer-guide-vs-code-with-lua-language-server"></a>
+ [Instale la extensión Lua: sumneko.lua](https://marketplace.visualstudio.com/items?itemName=sumneko.lua)
+ Abre cualquier archivo de tu proyecto de plugin `.lua`

 Y ya está\! El `plugin new` comando genera `.vscode/settings.json` y `library/sbomgen.lua` detecta automáticamente el servidor de idiomas de Lua. Obtendrá inmediatamente: 
+ Completar el código para todas `sbomgen.*` las funciones
+ Consejos de parámetros con tipos
+ Pase el ratón sobre la documentación
+ Comprobación de tipos

## Estructura del directorio de complementos
<a name="sbomgen-plugin-developer-guide-plugin-directory-structure"></a>

 Los complementos de detección y recopilación de Sbomgen deben seguir la siguiente estructura de directorios: 

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

 Estos nombres de directorio tienen un significado semántico: sbomgen los usa para obtener los metadatos predeterminados para su complemento, incluidos el nombre del escáner, el nombre del evento, los grupos de escáneres y el filtrado de la plataforma. Esto reduce la cantidad de texto repetitivo que, de otro modo, tendrían que escribir los desarrolladores. La elección de los valores correctos garantiza que su complemento se integre correctamente con el modelo de selección y ejecución de escáneres de sbomgen. 

 Las siguientes secciones exploran la estructura de directorios con mayor detalle y proporcionan orientación sobre el significado semántico y las convenciones. 

### Plataforma
<a name="sbomgen-plugin-developer-guide-platform"></a>

 El directorio de la plataforma controla los sistemas operativos en los que se ejecuta tu complemento. 


| **Valor** | **Cuándo se debe usar** | 
| --- | --- | 
| cross-platform | El complemento funciona en cualquier sistema operativo (la mayoría de los complementos) | 
| linux | Lógica de detección específica para Linux | 
| windows | Lógica de detección específica para Windows | 
| macos | Lógica de detección específica para macOS | 

### Categoría
<a name="sbomgen-plugin-developer-guide-category"></a>

 El directorio de categorías determina los grupos de escáneres predeterminados asignados al complemento, lo que controla si se ejecuta de forma predeterminada o si requiere una suscripción explícita. Vea cómo [Selección de escáner](#sbomgen-plugin-developer-guide-scanner-selection) los grupos afectan a la ejecución. 


| **Valor** | **Grupos predeterminados** | **Cuándo se debe usar** | 
| --- | --- | --- | 
| proglang | programming-language-packages, pkg-scanner | Paquetes de lenguajes de programación (pip, npm, maven, etc.) | 
| os | os, pkg-scanner | Administradores de paquetes de sistema operativo (dpkg, rpm, apk, etc.) | 
| extra-ecosystems | extra-ecosystems, pkg-scanner | Aplicaciones y tiempos de ejecución (nginx, curl, wordpress, etc.) | 

 Si utilizas un nombre de categoría que no coincide con ninguno de los anteriores, el nombre de la categoría en sí se utiliza como grupo. 

### Ecosistema
<a name="sbomgen-plugin-developer-guide-ecosystem"></a>

 Un nombre para el ecosistema de paquetes específico (por ejemplo`python-pip`,,`python-poetry`,`debian-dpkg`,`curl`). Los nombres separados por guiones son una convención común, pero no un requisito estricto. 

 El nombre del escáner y el nombre del recopilador se derivan directamente del nombre del directorio del ecosistema. 

### Emparejo de nombres de eventos
<a name="sbomgen-plugin-developer-guide-event-name-pairing"></a>

 Los complementos de detección y recopilación situados en la misma ruta de directorio se emparejan automáticamente. Por ejemplo, un complemento de descubrimiento `discovery/cross-platform/proglang/python-pip/` se empareja automáticamente con`collection/cross-platform/proglang/python-pip/`. 

 Puedes anular esto definiendo `get_event_name()` y `subscribe_to_event()` en tus complementos. 

## Plugins de Discovery
<a name="sbomgen-plugin-developer-guide-discovery-plugins"></a>

 Un complemento de descubrimiento solo requiere la `discover()` función. Todas las demás funciones son opcionales; los valores predeterminados se derivan de la ruta del directorio. 

 La mayoría de los complementos de descubrimiento funcionan localizando archivos cuyos nombres o rutas identifican un ecosistema específico, `requirements.txt` por ejemplo, para Python pip, `package.json` npm o Rust `Cargo.lock` cargo. Las `sbomgen.find_files_by_*` funciones realizan esta coincidencia fuera de la máquina virtual de Lua, lo que las hace mucho más rápidas que iterar la lista completa de archivos en Lua: 

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

 `discover()`debe devolver una tabla (matriz) de cadenas de Lua. Si no se encuentra ningún archivo, devuelva una tabla vacía. `{}` 

### Patrones de descubrimiento comunes
<a name="sbomgen-plugin-developer-guide-common-discovery-patterns"></a>


| **Objetivo** | **Función recomendada** | 
| --- | --- | 
| Haga coincidir uno o más nombres de archivo exactos | sbomgen.find\_files\_by\_name({names}) | 
| Haga coincidir los nombres de los archivos sin distinguir entre mayúsculas y minúsculas | sbomgen.find\_files\_by\_name\_icase({names}) | 
| Haga coincidir por sufijo de ruta (por ejemplo,) /pom.properties | sbomgen.find\_files\_by\_suffix({suffixes}) | 
| Haga coincidir por expresión regular de ruta completa | sbomgen.find\_files\_by\_path\_regex({patterns}) | 
| Coincidencia de nombre base al estilo de Glob (por ejemplo,) \*.lock | sbomgen.glob\_find\_files(pattern) | 

 Cuando tu lógica requiera un filtrado posterior (por ejemplo, conservar los archivos que coincidan con un sufijo pero excluyendo los directorios de compilación y salida), combina una llamada con un bucle de 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()` el descubrimiento a menos que no haya otro método de comparación adecuado: copia todas las rutas a la máquina virtual de Lua y, si se trata de artefactos de gran tamaño, puede tardar varios segundos. Consulte el [Referencia de la API de complementos](sbomgen-plugin-api-reference.md) para obtener más información. 

### Descubrimiento de eventos múltiples
<a name="sbomgen-plugin-developer-guide-multi-event-discovery"></a>

 De forma predeterminada, todos los archivos devueltos por `discover()` se publican en un único evento (desde`get_event_name()`). Si el escáner necesita enrutar diferentes archivos a diferentes recopiladores, devuelva una tabla con claves: 

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

 Cuando `discover()` devuelve una tabla con claves de cadena, cada clave se trata como un nombre de evento independiente y su valor (una tabla de rutas de archivos) se publica en ese evento. Los complementos de colección se suscriben a eventos específicos `subscribe_to_event()` como de costumbre. 

 Esto es compatible con versiones anteriores: la devolución de una tabla secuencial `{"file1", "file2"}` sigue funcionando como modo de evento único. La detección es automática: las tablas con cualquier clave de cadena son de eventos múltiples, las tablas con claves de números enteros (o vacías) son de eventos únicos. 

 Cuando se utilizan eventos múltiples, no `get_event_name()` se usa para publicar (los nombres de los eventos provienen de las claves de las tablas devueltas). Sin embargo, se sigue llamando durante la carga del complemento para detectar colisiones, por lo que debería devolver un valor único o omitirse para usar el valor predeterminado. 

### Funciones de detección opcionales
<a name="sbomgen-plugin-developer-guide-optional-discovery-functions"></a>

 Todas ellas tienen valores predeterminados idénticos derivados de la ruta del directorio. Defínalos solo si necesita anular: 


| **Función** | **Predeterminado** | **Anular cuando...** | 
| --- | --- | --- | 
| get\_scanner\_name() | {ecosystem}(por ejemplo,python-pip) | ¿Desea un nombre de escáner personalizado | 
| get\_scanner\_description() | "Lua discovery plugin: {ecosystem}" | ¿Desea una descripción personalizada | 
| get\_scanner\_groups() | Derivado del directorio de categorías | Necesita grupos no estándar | 
| get\_event\_name() | Derivado de la ruta del directorio | Necesita un enrutamiento de eventos personalizado | 
| get\_localhost\_scan\_paths() | Ninguno | Tu complemento necesita que se escaneen rutas específicas durante los localhost escaneos | 

### Rutas de escaneo de Localhost
<a name="sbomgen-plugin-developer-guide-localhost-scan-paths"></a>

 Cuando sbomgen ejecuta un `localhost` escaneo, recorre los directorios especificados por el usuario además de las rutas predeterminadas declaradas por los escáneres. De forma predeterminada, los complementos de detección de Lua no aportan ninguna ruta, por lo que los archivos que no estén en los directorios especificados por el usuario no aparecerán en la lista de archivos. 

 Defina `get_localhost_scan_paths()` los directorios o rutas de archivos que el rastreador de localhost debe incluir: 

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

 Las rutas devueltas se añaden a la lista de escaneos del caminante solo durante los `localhost` escaneos; no tienen ningún efecto sobre `container` los escaneos. `directory` `archive` 

### Rutas de escaneo específicas de la plataforma
<a name="sbomgen-plugin-developer-guide-platform-specific-scan-paths"></a>

 Cuando los archivos que le interesan se encuentren en diferentes ubicaciones en Windows, macOS y Linux, ramifique `sbomgen.get_platform()` y devuelva las rutas correspondientes al 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
```

 En Windows, utilícelo `sbomgen.get_system_drive()` para resolver la letra de la unidad del sistema (por ejemplo,`"C:"`) en lugar de codificarla de forma rígida. Para las rutas derivadas de variables de entorno como `LOCALAPPDATA` o`PROGRAMFILES`, repita `sbomgen.get_env_vars()` y busque el valor por clave. Consulte la [Referencia de la API de complementos](sbomgen-plugin-api-reference.md) para obtener más información. 

## Plugins de colección
<a name="sbomgen-plugin-developer-guide-collection-plugins"></a>

 Un complemento de colección solo requiere la `collect()` función. Todas las demás funciones son opcionales. 

 `collect(file_path)`se invoca una vez por cada archivo descubierto por el complemento de detección emparejada. El patrón típico es: 
+ **Lea** el contenido del archivo utilizando `sbomgen.read_file()` (para archivos pequeños cargados en la memoria) o `sbomgen.open_file()` (para archivos grandes, lea line-by-line).
+ **Analice** el contenido: haga coincidir cadenas para manifiestos simples, `sbomgen.xml_decode()` JSON, XML o `sbomgen.search_binary()` binarios compilados. `sbomgen.json_decode()`
+ **Publica** cada paquete descubierto llamando `sbomgen.push_package()` con los metadatos del paquete.

```
-- 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()`no devuelve ningún valor. Cada `push_package()` llamada requiere `name``purl_type`, y`component_type`. Consulte todos [Referencia de la API de complementos](sbomgen-plugin-api-reference.md) los campos admitidos. 

### Adjuntar metadatos a los componentes
<a name="sbomgen-plugin-developer-guide-attaching-metadata-to-components"></a>

 **Sbomgen admite dos formas de adjuntar metadatos a un componente del paquete: los **calificadores de PURL y las propiedades de CyclonedX.**** Tienen diferentes propósitos, y la elección entre ellos tiene implicaciones en la forma en que Amazon Inspector identifica las vulnerabilidades en la SBOM resultante. 


| **Mecanismo** | **Dónde aparece** | **Úselo para** | 
| --- | --- | --- | 
| qualifiers | Dentro de la URL del paquete (por ejemplo,pkg:deb/debian/curl@7.88.1?arch=amd64) | Datos que forman parte de la identidad del paquete | 
| properties | En la matriz de la SBOM components[].properties | Metadatos descriptivos que no cambian la forma en que se identifica el paquete | 

 **Recomendación: prefiera las propiedades de CyclonedX (en su propio espacio de nombres) para los metadatos personalizados.** Las propiedades no alteran la identidad de un componente, por lo que no pueden afectar a la identificación de vulnerabilidades de Amazon Inspector. Reserve los calificadores de PURL para los casos en que el tipo de PURL de su ecosistema los requiera. 

#### Calificadores de PURL
<a name="sbomgen-plugin-developer-guide-purl-qualifiers"></a>

 Algunos calificadores de PURL tienen un significado semántico para Amazon Inspector e influyen en la identificación de vulnerabilidades. Por ejemplo, en `deb` los componentes, el Inspector utiliza calificadores, como `arch` y `distro` para seleccionar la fuente de vulnerabilidades correcta; en `generic` los componentes de los binarios compilados, calificadores, como `go_toolchain` o `rust_toolchain` identifica la cadena de herramientas utilizada. Establecer un calificador que el Inspector no reconoce u omitir uno que espera puede provocar que las vulnerabilidades se pasen por alto o se atribuyan erróneamente. 

 Consulte [¿Qué es la URL de un paquete?](https://docs.aws.amazon.com/inspector/latest/user/sbom-generator-purl-sbom.html) en la guía del usuario de Amazon Inspector para conocer las convenciones de calificación que el Inspector reconoce por tipo de PURL. 

 Establezca los calificadores mediante la tabla que aparece en`qualifiers`: `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",
    },
})
```

 Establece los clasificatorios únicamente cuando se ajusten a las expectativas del Inspector para el tipo PURL. Si necesita registrar metadatos que no forman parte de la identidad del paquete, utilice en su lugar las propiedades de CyclonedX. 

#### Propiedades de CyclonedX
<a name="sbomgen-plugin-developer-guide-cyclonedx-properties"></a>

 Las propiedades CyclonedX son anotaciones clave-valor que aparecen en la matriz de la SBOM. `components[].properties` Describen un componente sin afectar a la forma en que se identifica, por lo que son la opción más segura para los metadatos definidos por un complemento. 

 **Los `amazon:inspector:*` espacios de nombres están reservados para Amazon Inspector.** En concreto: 
+ `amazon:inspector:sbom_generator:*`— reservado para sbomgen y sus escáneres integrados.
+ `amazon:inspector:sbom_scanner:*`— reservado para la API de escaneo de Amazon Inspector.

 Los autores de los complementos no deben emitir claves dentro de estos espacios de nombres reservados. Escribir en ellos puede interferir con el comportamiento del Inspector y puede sobrescribirse. Para ver la lista completa de claves reservadas, consulte [Uso de espacios de nombres CyclonedX con](https://docs.aws.amazon.com/inspector/latest/user/cyclonedx-namespace.html) Amazon Inspector. 

 Utilice su propio espacio de nombres (normalmente el identificador de su organización o complemento) al definir las propiedades: 

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

#### Reglas de nomenclatura clave
<a name="sbomgen-plugin-developer-guide-key-naming-rules"></a>

 sbomgen procesa las claves de propiedad de la siguiente manera: 
+ Una clave que **contiene dos puntos** se usa textualmente en la SBOM. Incluye siempre al menos dos puntos en las claves para controlar el espacio de nombres.
+ A una clave que **no contenga dos puntos se le añade** automáticamente el prefijo, colocándola dentro del espacio de nombres reservado del Inspector. `amazon:inspector:sbom_generator:` Evite esta forma para las propiedades personalizadas.

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

 Las `sbomgen.properties.*` constantes existen para que los escáneres oficiales emitan claves consistentes dentro del espacio de nombres reservado. No son puntos de extensión para complementos personalizados; en su lugar, usa tu propio espacio de nombres. 

#### Propiedades y calificadores de los componentes secundarios
<a name="sbomgen-plugin-developer-guide-properties-and-qualifiers-on-child-components"></a>

 Los componentes independientes `children` están anidados. Cada elemento secundario tiene sus propias `qualifiers` tablas `properties` y los metadatos establecidos en el elemento principal no se propagan a los elementos secundarios. Establezca valores de forma explícita para cada niño que los necesite. 

### Funciones de recopilación opcionales
<a name="sbomgen-plugin-developer-guide-optional-collection-functions"></a>


| **Función** | **Predeterminado** | **Anular cuando...** | 
| --- | --- | --- | 
| get\_collector\_name() | {ecosystem}(por ejemplo,python-pip) | ¿Quieres un nombre de coleccionista personalizado | 
| get\_collector\_description() | empty string | ¿Quieres una descripción | 
| subscribe\_to\_event() | Derivado de la ruta del directorio | Necesita un enrutamiento de eventos personalizado | 

## Ejecutando tus complementos
<a name="sbomgen-plugin-developer-guide-running-your-plugins"></a>

 Para que los complementos generen metadatos de paquetes, sbomgen debe tener un artefacto para escanearlo que contenga los archivos a los que apunta su complemento (por ejemplo, un directorio con `requirements.txt` archivos de manifiesto de paquetes o archivos de manifiesto equivalentes). `package.json` 

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

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

 Ejemplo: 

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

### Con los escáneres nativos desactivados (modo solo para 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
```

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

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

## Listado de escáneres disponibles
<a name="sbomgen-plugin-developer-guide-listing-available-scanners"></a>

 Úselo `list-scanners` para ver todos los escáneres disponibles para sbomgen. Esto incluye los escáneres nativos integrados, cualquier complemento oficial de Lua incluido en sbomgen y cualquier complemento de Lua personalizado que hayas suministrado a través 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                    │
└─────────────────────┴────────┴───────────────────────────────┴─────────────────────────────┘
```

 La columna SOURCE muestra de dónde proviene cada escáner: 


| **Origen** | **Significado** | 
| --- | --- | 
| native | Escáner incorporado incluido con sbomgen | 
| official | Plugins Lua incluidos con sbomgen | 
| custom | El complemento de Lua proporcionado por el usuario se carga mediante --plugin-dir | 

 Si se ejecuta `list-scanners` sin `--plugin-dir` él, se incluyen ambos `native` y `official` escáneres, que están siempre disponibles. La `--plugin-dir` marca añade sus `custom` escáneres a la lista. 

 Para mostrar solo los escáneres Lua sin escáneres nativos: 

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

## Selección de escáner
<a name="sbomgen-plugin-developer-guide-scanner-selection"></a>

 Los complementos de Lua Discovery participan en el mismo modelo de selección de escáneres que los escáneres nativos integrados. De forma predeterminada, sbomgen ejecuta todos los escáneres cuyos grupos coinciden con los grupos de escáneres predeterminados para el tipo de artefacto. Puede anular esto con tres indicadores: 

### Ejecute solo escáneres específicos
<a name="sbomgen-plugin-developer-guide-run-only-specific-scanners"></a>

 Úselo `--scanners` para ejecutar solo los escáneres nombrados. Se excluyen todos los demás escáneres: 

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

 Esto solo ejecuta el `python-requirements` escáner. Puede pasar varios nombres de escáneres separados por comas o pasar el nombre de un grupo de escáneres (por ejemplo`programming-language-packages`) para activar todos los escáneres que pertenezcan a ese grupo. 

### Excluya escáneres específicos
<a name="sbomgen-plugin-developer-guide-exclude-specific-scanners"></a>

 Se utiliza `--skip-scanners` para excluir los escáneres con nombre asignado mientras se ejecuta todo lo demás: 

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

 Esto ejecuta todos los escáneres predeterminados excepto`python-poetry`. Por ejemplo`--scanners`, este indicador también acepta nombres de grupos, por lo que al pasarlos `--skip-scanners programming-language-packages` se deshabilitan todos los escáneres de ese grupo. 

**nota**  
`--scanners`y `--skip-scanners` se excluyen mutuamente. Pasar ambos produce un error.

### Agregue escáneres de grupos no predeterminados
<a name="sbomgen-plugin-developer-guide-add-scanners-from-non-default-groups"></a>

 El conjunto de escáneres predeterminado depende del tipo de artefacto que se esté escaneando (consulte la matriz que aparece a continuación). [Cómo afectan los grupos a la selección](#sbomgen-plugin-developer-guide-how-groups-affect-selection) Un escáner cuyos grupos no formen parte del conjunto predeterminado para el tipo de artefacto no se ejecutará a menos que lo active. `--additional-scanners`Utilícelo para añadir escáneres al conjunto predeterminado sin reemplazarlo: 

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

 Esto ejecuta todos los escáneres predeterminados para el tipo de artefacto, además. `my-extra-scanner` El indicador acepta una lista separada por comas de nombres de escáneres o grupos, y se apila con el conjunto predeterminado en lugar de reemplazarlo. Se utiliza `list-scanners` para comprobar a qué grupos pertenece un escáner. 

### Cómo afectan los grupos a la selección
<a name="sbomgen-plugin-developer-guide-how-groups-affect-selection"></a>

 La `get_scanner_groups()` función del complemento de detección determina a qué grupos pertenece el escáner. El funcionamiento predeterminado de un escáner depende tanto de sus grupos como del tipo de artefacto que se esté escaneando. La siguiente matriz muestra los grupos que se incluyen en el conjunto de escáneres predeterminado para cada tipo de artefacto: 


| **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 los escáneres de ese grupo se ejecutan de forma predeterminada para ese tipo de artefacto. A `—` significa que el grupo no está en el conjunto predeterminado, por lo que sus escáneres solo se ejecutan si se seleccionan explícitamente mediante `--scanners` o. `--additional-scanners` 

 Detalles destacables: 
+ **`custom`**siempre está en el conjunto predeterminado: los complementos personalizados que se cargan reciben `--plugin-dir` automáticamente el `custom` grupo, por lo que se ejecutan de forma predeterminada independientemente del tipo de artefacto.
+ **`extra-ecosystems`**está predeterminado para `container``localhost`, y `volume` escanea, pero no para `directory``archive`, o `binary` escanea. En el caso de esos tipos, hay que pasar por alto `--additional-scanners` (por nombre o por `extra-ecosystems` grupo) para incluirlos.
+ **`pkg-scanner`**es informativo: marca un escáner como recopilador de paquetes para mostrarlos en él`list-scanners`, pero no hace que el escáner funcione por sí solo. Combínelo con un grupo de ejecución (por ejemplo,`programming-language-packages`) en`get_scanner_groups()`.

 Por ejemplo, un complemento que `{sbomgen.groups.EXTRA_ECOSYSTEMS, sbomgen.groups.PACKAGE_COLLECTOR}` se devuelva se ejecutará de forma predeterminada en los escaneos de contenedores, hosts locales y volúmenes, pero será necesario `--additional-scanners` (o`--scanners`) en los escaneos de directorios, archivos y binarios. 

## Reglas de colisión de complementos
<a name="sbomgen-plugin-developer-guide-plugin-collision-rules"></a>

 Sbomgen aplica metadatos únicos en todos los complementos cargados para evitar la sobrescritura silenciosa y garantizar la integridad del SBOM. Cuando se detecta una colisión, se **omite** el último complemento y se registra una advertencia. 

### ¿Qué está marcado
<a name="sbomgen-plugin-developer-guide-what-is-checked"></a>


| **Metadatos** | **Alcance** | **En caso de colisión** | 
| --- | --- | --- | 
| Nombre del evento de descubrimiento (get\_event\_name) | Todos los complementos de descubrimiento | Se omitió el segundo complemento | 
| Nombre del escáner () get\_scanner\_name | Todos los complementos de descubrimiento | Se omitió el segundo complemento | 
| Nombre del recopilador () get\_collector\_name | Todos los complementos de la colección | Se omitió el segundo complemento | 

### ¿Qué está permitido
<a name="sbomgen-plugin-developer-guide-what-is-allowed"></a>

 Se **pueden** suscribir varios complementos de colección al mismo evento a través de`subscribe_to_event()`. Este es el patrón de distribución previsto: un plugin de descubrimiento puede alimentar a varios recopiladores, cada uno de los cuales realiza tareas diferentes (por ejemplo, uno extrae paquetes y otro detecta secretos). 

### Evitar colisiones
<a name="sbomgen-plugin-developer-guide-avoiding-collisions"></a>

 Si dos complementos utilizan el mismo nombre de escáner, nombre de evento o nombre de recopilador, se omite el segundo que se haya cargado. Para resolver las colisiones, cambie el nombre de los metadatos en conflicto definiendo la función de anulación adecuada en su complemento (`get_scanner_name()`,, o). `get_event_name()` `get_collector_name()` 

### Ejemplo de advertencia de colisión
<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.
```

 La advertencia indica qué complemento se omitió, qué colisionó, qué complemento ya tiene ese nombre y qué función cambiar. 

## Debugging
<a name="sbomgen-plugin-developer-guide-debugging"></a>

### Registro de la consola
<a name="sbomgen-plugin-developer-guide-console-logging"></a>

 Los complementos pueden emitir mensajes a la salida de la consola de sbomgen mediante las siguientes funciones: 


| **Función** | **Nivel** | **¿Visible por defecto?** | 
| --- | --- | --- | 
| sbomgen.log\_debug(message) | DEBUG | No, requiere --verbose | 
| sbomgen.log\_info(message) | INFO | Sí | 
| sbomgen.log\_warn(message) | WARN | Sí | 
| sbomgen.log\_error(message) | ERROR | Sí | 

 Todas las salidas de registro de un complemento llevan automáticamente el prefijo de la fuente y la ruta del complemento (por ejemplo,`[custom:python-pip]`), por lo que los mensajes de los distintos complementos son fáciles de distinguir. `log_info``log_warn`, y `log_error` siempre se imprime; `log_debug` solo se imprime cuando se invoca sbomgen con. `--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
```

### Puntos de interrupción
<a name="sbomgen-plugin-developer-guide-breakpoints"></a>

 Se usa `sbomgen.breakpoint()` para pausar la ejecución del complemento y bloquearlo hasta que presione Entrar. Funciona como un depurador simple: combínalo con sentencias de registro para inspeccionar el estado en puntos 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
```

 El mensaje de punto de interrupción se imprime en stderr. La ejecución se detiene hasta que pulse Entrar, lo que le da tiempo para revisar el resultado del registro. 

### Problemas comunes
<a name="sbomgen-plugin-developer-guide-common-issues"></a>


| **Síntoma** | **Causa** | **Corregir** | 
| --- | --- | --- | 
| El complemento no está cargado | Falta init.lua | Asegúrese de que el punto de entrada esté en la profundidad de directorio correcta | 
| «falta la función requerida» | Error tipográfico en el nombre de la función | Compruebe queget\_scanner\_name,get\_scanner\_description,get\_scanner\_groups,discover,get\_event\_name,get\_localhost\_scan\_paths, get\_collector\_namecollect, subscribe\_to\_event estén definidas | 
| El complemento de colección nunca se llamó | El nombre del evento no coincide | Verifica get\_event\_name() y subscribe\_to\_event() devuelve la misma cadena | 
| No hay paquetes en la SBOM | push\_packageno se ha llamado o faltan campos obligatorios | Asegúrese name de que component\_type estén configurados en todas las push\_package llamadas (incluidas las de los niños). purl\_type Usa sbomgen.component\_types.\* constantes. | 
| Error de tiempo de ejecución en el complemento | Error de Lua durante la ejecución | Compruebe la salida de sbomgen para ver si hay mensajes de advertencia con los detalles del error | 
| «OMITIDO: el nombre del evento de descubrimiento... ya está registrado» | Otro complemento usa el mismo nombre de evento | Cambie el nombre get\_event\_name() a un valor único | 
| «OMITIDO: el nombre del escáner... ya está registrado» | Otro complemento usa el mismo nombre de escáner | Cambie el nombre get\_scanner\_name() a un valor único | 
| «OMITIDO: el nombre del recopilador... ya está registrado» | Otro complemento usa el mismo nombre de recopilador | Cambie el nombre get\_collector\_name() a un valor único | 

## referencia de la API
<a name="sbomgen-plugin-developer-guide-api-reference"></a>

 El catálogo completo de funciones se incluye en un documento complementario: 

 **→ [Referencia de la API de complementos](sbomgen-plugin-api-reference.md)** 

 La referencia de la API abarca todas las `sbomgen.*` funciones (E/S de archivos, utilidades binarias, salida de paquetes, expresiones regulares, análisis estructurado, registro de Windows, registro, depuración), la `testing.*` API disponible en los archivos de prueba, todas las constantes integradas (,, `properties` `groups``component_types`,`platform`) y el ciclo de vida global de los complementos. 

## Gestión de errores
<a name="sbomgen-plugin-developer-guide-error-handling"></a>

 Las funciones de la API que pueden fallar devuelven dos valores:. `value, err` En caso de éxito, `err` es`nil`. En caso de error, el primer valor es `nil` y `err` es una cadena de error. 

```
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 complemento genera un error de Lua no controlado, sbomgen registra una advertencia y continúa con el siguiente archivo o complemento. Los demás complementos no se ven afectados. 

## Restricciones de Sandbox
<a name="sbomgen-plugin-developer-guide-sandbox-restrictions"></a>

 Los complementos se ejecutan en una máquina virtual Lua aislada con acceso limitado a la biblioteca estándar: 


| **Library** | **Disponible** | **Notas** | 
| --- | --- | --- | 
| base | ✓ | dofile,loadfile, se eliminan loadstring | 
| string | ✓ | Manipulación completa de cadenas | 
| table | ✓ | Manipulación completa de la tabla | 
| math | ✓ | Biblioteca matemática completa | 
| package | ✓ | require()restringido al directorio de complementos | 
| io | ✗ | Utilice sbomgen.\* I/O funciones en su lugar | 
| os | ✗ | Bloqueado por motivos de seguridad | 
| debug | ✗ | Bloqueado para evitar la introspección de las máquinas virtuales | 
| coroutine | ✗ | ¿No está cargado | 

 El acceso directo al sistema de archivos mediante `io.open` o no `os.execute` está disponible. Todas las operaciones con los archivos deben pasar por la `sbomgen` API, lo que garantiza un comportamiento coherente en todos los tipos de artefactos e impide que los complementos accedan a archivos ajenos al artefacto. 

 `require()`solo puede cargar módulos desde el árbol de directorios del plugin. El recorrido entre el directorio principal, por ejemplo, está bloqueado. `require("../shared")` 

## Compartir código entre complementos
<a name="sbomgen-plugin-developer-guide-sharing-code-between-plugins"></a>

 Puedes usarlo `require()` para cargar módulos auxiliares desde el directorio de tu complemento: 

```
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
```

 También se admiten subdirectorios con`init.lua`: 

```
my-ecosystem/
├── init.lua
└── parsers/
    └── init.lua
```

```
local parsers = require("parsers")
```

 `require()`está restringido al directorio de tu plugin. No puedes cargar módulos desde otros complementos o rutas del sistema. No se admiten bibliotecas Lua de terceros (p. ej., de LuaRocks); solo se pueden cargar los módulos auxiliares locales del directorio de complementos. 