

기계 번역으로 제공되는 번역입니다. 제공된 번역과 원본 영어의 내용이 상충하는 경우에는 영어 버전이 우선합니다.

# 플러그인 개발자 안내서
<a name="sbomgen-plugin-developer-guide"></a>

 이 가이드에서는 사용자 지정 Lua 플러그인을 사용하여 Amazon Inspector SBOM 생성기(inspector-sbomgen)를 확장하는 방법을 설명합니다. 플러그인을 사용하면 sbomgen의 소스 코드를 수정하거나 다시 컴파일하지 않고도 새 패키지 에코시스템에 대한 지원을 추가할 수 있습니다.

 전체 함수 카탈로그는 단원을 참조하십시오[플러그인 API 참조](sbomgen-plugin-api-reference.md). 테스트 작성에 대한 지침은 단원을 참조하십시오[플러그인 테스트 가이드](sbomgen-plugin-testing-guide.md).

## 개요
<a name="sbomgen-plugin-developer-guide-overview"></a>

 Sbomgen 플러그인은 Lua로 작성되며 두 단계 파이프라인을 따릅니다.
+ **검색** - 아티팩트의 파일 목록을 스캔하고 에코시스템과 관련된 파일을 보고합니다.
+ **컬렉션** - 검색된 각 파일을 구문 분석하고 패키지 결과를 SBOM으로 푸시합니다.

### 플러그인 이벤트 모델
<a name="sbomgen-plugin-developer-guide-plugin-event-model"></a>

 검색 플러그인은 패키지 메타데이터가 포함된 파일이 인벤토리의 아티팩트에서 검색되었음을 컬렉션 플러그인에 알리는 방법이 필요합니다. 이러한 데이터 공유를 용이하게 하기 위해 검색 플러그인은 **이벤트 이름을** 정의하고 파일 경로 목록을 반환합니다. 컬렉션 플러그인은 해당 이벤트를 **구독**하고 일치하는 각 파일 경로를 수신합니다. 이렇게 하면 파일 감지가 구문 분석과 분리됩니다. 하나의 검색 플러그인이 여러 수집기(팬아웃 패턴)를 공급할 수 있습니다. 그러나 각 검색 플러그인에는 고유한 이벤트 이름이 있어야 하며 각 컬렉션 플러그인에는 고유한 수집기 이름이 있어야 합니다. 세부 정보는 [플러그인 충돌 규칙](#sbomgen-plugin-developer-guide-plugin-collision-rules) 섹션을 참조하세요.

 개발자는 이를 **관찰자** 설계 패턴으로 인식할 수 있습니다.

 이 설계를 통해 단일 검색 플러그인이 여러 독립적인 분석을 성능 있는 방식으로 트리거할 수 있습니다. 예를 들어 하나의 검색 플러그인은 아티팩트`requirements.txt`의 모든를 찾은 다음 피드할 수 있습니다.
+ 각 줄을 SBOM 조사 결과()로 구문 분석하는 **패키지 수집기**입니다`name==version`.
+ 실수로 버전으로 고정된 API 키 또는 토큰이 포함된 줄에 플래그를 지정하는 **보안 암호 수집기**입니다.
+ 고정되지 않은 또는 와일드카드 버전 지정자를 보고하는 **정책 수집**기입니다.

 각 수집기는 아티팩트의 파일 시스템을 다시 걷지 않고 동일한 파일 목록과 독립적으로 실행됩니다. 또한 플러그인 작성자는 해당 검색 플러그인을 변경하지 않고도 기존 이벤트를 구독하는 새 컬렉션 플러그인을 추가할 수 있습니다.

## 빠른 시작: 새 플러그인 생성
<a name="sbomgen-plugin-developer-guide-quick-start-creating-new-plugins"></a>

 새 플러그인을 생성하는 가장 빠른 방법은 내장 스캐폴딩 명령을 사용하는 것입니다.

```
inspector-sbomgen plugin new
```

 명령은 플러그인 이름과 프로젝트 디렉터리를 묻는 메시지를 표시합니다. Enter를 누르면 대괄호로 표시된 기본값이 허용됩니다.

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

 인수를 직접 전달할 수도 있습니다.

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

### 작업 예제로 시작
<a name="sbomgen-plugin-developer-guide-starting-with-a-working-example"></a>

 자체 로직을 작성하기 전에 플러그인을 실험하려면 `--with-example` 플래그를 사용하여 새 플러그인을 생성합니다.

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

 이렇게 하면 샘플 Lockfile 구문 분석기, 테스트 데이터 및 테스트 통과를 통해 완전히 작동하는 플러그인 프로젝트가 생성됩니다. 예제 플러그인은 `example.lock` 파일을 검색하고, `name==version` 항목을 구문 분석하고, 패키지를 SBOM으로 푸시합니다. 테스트를 즉시 실행하여 플러그인 시스템이 작동하는지 확인한 다음 코드를 수정하여 실제 에코시스템을 대상으로 지정할 수 있습니다.

 모든 선택적 재정의 함수(`get_scanner_name`, , `get_event_name``get_scanner_groups`, 다중 이벤트 검색 등)를 포함하는 고급 스캐폴딩의 경우 `--with-overrides` 플래그를 사용합니다(자세한 내용은 나중에 참조).

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

### 플러그인 완료
<a name="sbomgen-plugin-developer-guide-completing-your-plugin"></a>

 스캐폴딩 후 생성된 플러그인 파일에는 에코시스템별 로직을 추가할 위치를 나타내는 `TODO` 마커가 포함되어 있습니다. 다음 마커를 살펴보고 스캐폴드를 작동 플러그인으로 바꿉니다.
+ 모든 `TODO` 마커를 실제 값으로 바꾸기
+ 대상 파일`discover()`과 일치하도록에서 파일 패턴 업데이트
+ 에서 구문 분석 로직을 구현`collect()`하고 각 패키지에 `sbomgen.push_package()` 대해를 호출합니다.

### 플러그인 테스트
<a name="sbomgen-plugin-developer-guide-test-your-plugin"></a>

 플러그인을 테스트하는 방법에는 두 가지가 있습니다.

 **1: 내장 테스트 하네스** - 개발 중에 플러그인 로직을 검증`inspector-sbomgen plugin test`하는 데 사용합니다. 이렇게 하면 스캔할 실제 아티팩트 없이 `init_test.lua` 테스트 파일이 실행됩니다.

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

 테스트 파일 작성 및 `testing.*` API 사용에 대한 [플러그인 테스트 가이드](sbomgen-plugin-testing-guide.md) 자세한 내용은 섹션을 참조하세요.

 **2. End-to-end 스캔 -** 표준 sbomgen 명령을 사용하여 플러그인을 호출하여 실제 아티팩트에 대해 작동하는지 확인합니다. 이 접근 방식의 경우 플러그인 대상 파일(예: `requirements.txt` 또는 이에 상응하는 파일이 있는 디렉터리)이 포함된 아티팩트와 플러그인 디렉터리의 경로를 모두 제공해야 합니다.

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

 `--disable-native-scanners` 플래그는 Lua 플러그인만 실행되도록 하므로 내장(기본) 스캐너의 출력 없이 더 쉽게 테스트할 수 있습니다.

## IDE 설정
<a name="sbomgen-plugin-developer-guide-ide-setup"></a>

 Sbomgen은 VS Code의 전체 `sbomgen.*` API에 대한 코드 완성, 유형 확인 및 인라인 설명서를 제공합니다.

### Lua 언어 서버가 포함된 VS 코드
<a name="sbomgen-plugin-developer-guide-vs-code-with-lua-language-server"></a>
+ Lua 확장 프로그램 설치: [sumneko.lua](https://marketplace.visualstudio.com/items?itemName=sumneko.lua)
+ 플러그인 프로젝트에서 모든 `.lua` 파일 열기

 그럼 끝입니다. `plugin new` 명령은 Lua Language Server에서 자동으로 감지`library/sbomgen.lua`되는 `.vscode/settings.json` 및를 생성합니다. 즉시 다음을 얻을 수 있습니다.
+ 모든 `sbomgen.*` 함수에 대한 코드 완성
+ 유형이 있는 파라미터 힌트
+ 마우스 포인터 설명서
+ 유형 확인

## 플러그인 디렉터리 구조
<a name="sbomgen-plugin-developer-guide-plugin-directory-structure"></a>

 Sbomgen 검색 및 컬렉션 플러그인은 다음 디렉터리 구조를 준수해야 합니다.

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

 이러한 디렉터리 이름은 의미가 있습니다. sbomgen은 이를 사용하여 스캐너 이름, 이벤트 이름, 스캐너 그룹, 플랫폼 필터링 등 플러그인의 기본 메타데이터를 도출합니다. 이렇게 하면 개발자가 작성해야 하는 표준 문안의 양이 줄어듭니다. 올바른 값을 선택하면 플러그인이 sbomgen의 스캐너 선택 및 실행 모델과 올바르게 통합됩니다.

 아래 섹션에서는 디렉터리 구조를 자세히 살펴보고 의미와 규칙에 대한 지침을 제공합니다.

### 플랫폼
<a name="sbomgen-plugin-developer-guide-platform"></a>

 플랫폼 디렉터리는 플러그인이 실행되는 운영 체제를 제어합니다.


| **값** | **사용해야 하는 경우** | 
| --- | --- | 
| cross-platform | 플러그인은 모든 OS(대부분의 플러그인)에서 작동합니다. | 
| linux | Linux별 탐지 로직 | 
| windows | Windows별 탐지 로직 | 
| macos | macOS별 탐지 로직 | 

### 카테고리
<a name="sbomgen-plugin-developer-guide-category"></a>

 범주 디렉터리는 플러그인에 할당된 기본 스캐너 그룹을 결정하며, 플러그인은 기본적으로 실행되는지 또는 명시적 옵트인이 필요한지를 제어합니다. 그룹이 실행[스캐너 선택](#sbomgen-plugin-developer-guide-scanner-selection)에 미치는 영향은 섹션을 참조하세요.


| **값** | **기본 그룹** | **사용해야 하는 경우** | 
| --- | --- | --- | 
| proglang | programming-language-packages, pkg-scanner | 프로그래밍 언어 패키지(pip, npm, maven 등) | 
| os | os, pkg-scanner | OS 패키지 관리자(dpkg, rpm, apk 등) | 
| extra-ecosystems | extra-ecosystems, pkg-scanner | 애플리케이션 및 런타임(nginx, curl, wordpress 등) | 

 위의 항목과 일치하지 않는 범주 이름을 사용하는 경우 범주 이름 자체가 그룹으로 사용됩니다.

### 에코시스템
<a name="sbomgen-plugin-developer-guide-ecosystem"></a>

 특정 패키지 에코시스템의 이름(예: , `python-pip``python-poetry`, `debian-dpkg`, `curl`). 하이픈으로 묶인 이름은 일반적인 규칙이지만 엄격한 요구 사항은 아닙니다.

 스캐너 이름과 수집기 이름은 에코시스템 디렉터리 이름에서 직접 파생됩니다.

### 이벤트 이름 페어링
<a name="sbomgen-plugin-developer-guide-event-name-pairing"></a>

 동일한 디렉터리 경로의 검색 및 컬렉션 플러그인은 자동으로 페어링됩니다. 예를 들어의 검색 플러그인은와 `discovery/cross-platform/proglang/python-pip/` 자동으로 페어링됩니다`collection/cross-platform/proglang/python-pip/`.

 플러그인`subscribe_to_event()`에서 `get_event_name()` 및를 정의하여 이를 재정의할 수 있습니다.

## 검색 플러그인
<a name="sbomgen-plugin-developer-guide-discovery-plugins"></a>

 검색 플러그인에는 `discover()` 함수만 필요합니다. 다른 모든 함수는 선택 사항입니다. 기본값은 디렉터리 경로에서 파생됩니다.

 대부분의 검색 플러그인은 이름이나 경로가 Python pip, `requirements.txt` `package.json`npm 또는 `Cargo.lock` Rust 화물과 같은 특정 에코시스템을 식별하는 파일을 찾는 방식으로 작동합니다. `sbomgen.find_files_by_*` 함수는 Lua VM 외부에서이 일치를 수행하므로 Lua에서 전체 파일 목록을 반복하는 것보다 훨씬 빠릅니다.

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

 `discover()`는 문자열의 Lua 테이블(배열)을 반환해야 합니다. 파일을 찾을 수 없는 경우 빈 테이블을 반환합니다`{}`.

### 일반적인 검색 패턴
<a name="sbomgen-plugin-developer-guide-common-discovery-patterns"></a>


| **Goal** | **권장 함수** | 
| --- | --- | 
| 하나 이상의 정확한 파일 이름 일치 | sbomgen.find\_files\_by\_name({names}) | 
| 대/소문자를 구분하지 않고 파일 이름 일치 | sbomgen.find\_files\_by\_name\_icase({names}) | 
| 경로 접미사별 일치(예: /pom.properties) | sbomgen.find\_files\_by\_suffix({suffixes}) | 
| 전체 경로 정규식별 일치 | sbomgen.find\_files\_by\_path\_regex({patterns}) | 
| 글롭 스타일 기본 이름 일치(예: \*.lock) | sbomgen.glob\_find\_files(pattern) | 

 로직에 접미사와 일치하는 파일을 유지하되 빌드 출력 디렉터리는 제외하는 등 사후 필터링이 필요한 경우 `find_files_by_*` 호출을 Lua 루프와 결합합니다.

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

 다른 매처가 맞지 않는 한 검색`sbomgen.get_file_list()`하지 마세요. 모든 경로를 Lua VM으로 복사하고 큰 아티팩트에서 몇 초가 걸릴 수 있습니다. 자세한 내용은 [플러그인 API 참조](sbomgen-plugin-api-reference.md) 단원을 참조하십시오.

### 다중 이벤트 검색
<a name="sbomgen-plugin-developer-guide-multi-event-discovery"></a>

 기본적으로에서 반환되는 모든 파일은 단일 이벤트(에서)에 게시`discover()`됩니다`get_event_name()`. 스캐너가 다른 파일을 다른 수집기로 라우팅해야 하는 경우 키가 지정된 테이블을 대신 반환합니다.

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

 가 문자열 키가 있는 테이블을 `discover()` 반환하면 각 키가 별도의 이벤트 이름으로 처리되고 해당 값(파일 경로 테이블)이 해당 이벤트에 게시됩니다. 컬렉션 플러그인은 평소와 `subscribe_to_event()` 같이를 통해 특정 이벤트를 구독합니다.

 이는 이전 버전과 호환되므로 순차 테이블을 반환해도 단일 이벤트 모드로 `{"file1", "file2"}` 작동합니다. 자동 감지: 문자열 키가 있는 테이블은 다중 이벤트이고 정수 키만 있는(또는 비어 있는) 테이블은 단일 이벤트입니다.

 다중 이벤트를 사용하는 경우 `get_event_name()`는 게시에 사용되지 않습니다(이벤트 이름은 반환된 테이블 키에서 가져옵니다). 그러나 충돌 감지를 위해 플러그인을 로드하는 동안에도 여전히 호출되므로 고유한 값을 반환하거나 기본값을 사용하려면 생략해야 합니다.

### 선택적 검색 함수
<a name="sbomgen-plugin-developer-guide-optional-discovery-functions"></a>

 이 모든 항목에는 디렉터리 경로에서 파생된 sane 기본값이 있습니다. 재정의해야 하는 경우에만 정의합니다.


| **함수** | **기본값** | **재정의 시기...** | 
| --- | --- | --- | 
| get\_scanner\_name() | {ecosystem} (예: python-pip) | 사용자 지정 스캐너 이름을 원하는 경우 | 
| get\_scanner\_description() | "Lua discovery plugin: {ecosystem}" | 사용자 지정 설명을 원하는 경우 | 
| get\_scanner\_groups() | 범주 디렉터리에서 파생됨 | 비표준 그룹이 필요합니다. | 
| get\_event\_name() | 디렉터리 경로에서 파생됨 | 사용자 지정 이벤트 라우팅이 필요합니다. | 
| get\_localhost\_scan\_paths() | 없음 | 플러그인은 스캔 중에 특정 경로를 localhost 스캔해야 합니다. | 

### Localhost 스캔 경로
<a name="sbomgen-plugin-developer-guide-localhost-scan-paths"></a>

 sbomgen이 `localhost` 스캔을 실행하면 사용자 지정 디렉터리와 스캐너에서 선언한 기본 경로를 안내합니다. 기본적으로 Lua 검색 플러그인은 경로를 제공하지 않으므로 사용자 지정 디렉터리 외부의 파일은 파일 목록에 표시되지 않습니다.

 localhost 워커가 포함해야 하는 디렉터리 또는 파일 경로를 반환`get_localhost_scan_paths()`하도록 정의합니다.

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

 반환된 경로는 스캔 중에만 워커의 `localhost` 스캔 목록에 추가되며 `container`, `directory`또는 `archive` 스캔에는 영향을 주지 않습니다.

### 플랫폼별 스캔 경로
<a name="sbomgen-plugin-developer-guide-platform-specific-scan-paths"></a>

 관심 있는 파일이 Windows, macOS 및 Linux의 다른 위치에 있는 경우에서 분기`sbomgen.get_platform()`하고 호스트에 적합한 경로를 반환합니다.

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

 Windows에서는 `sbomgen.get_system_drive()`를 사용하여 시스템 드라이브 문자(예: `"C:"`)를 하드 코딩하는 대신 확인합니다. `LOCALAPPDATA` 또는와 같은 환경 변수에서 파생된 경로의 경우 `PROGRAMFILES`반복`sbomgen.get_env_vars()`하고 키별로 값을 조회합니다. 자세한 내용은 [플러그인 API 참조](sbomgen-plugin-api-reference.md) 단원을 참조하십시오.

## 컬렉션 플러그인
<a name="sbomgen-plugin-developer-guide-collection-plugins"></a>

 컬렉션 플러그인에는 `collect()` 함수만 필요합니다. 다른 모든 함수는 선택 사항입니다.

 `collect(file_path)`는 페어링된 검색 플러그인에서 검색한 파일당 한 번 호출됩니다. 일반적인 패턴은 다음과 같습니다.
+ `sbomgen.read_file()` (메모리에 로드된 작은 파일의 경우) 또는 `sbomgen.open_file()` (큰 파일의 경우 line-by-line 읽기)를 사용하여 파일의 콘텐츠를 **읽**습니다.
+ 콘텐츠 **구문 분석** - 단순 매니페스트, `sbomgen.json_decode()` JSON, `sbomgen.xml_decode()` XML 또는 컴파일된 바이너리`sbomgen.search_binary()`에 대한 문자열 일치.
+ 패키지의 메타데이터`sbomgen.push_package()`를 사용하여를 호출하여 검색된 각 패키지를 **게시**합니다.

```
-- REQUIRED: Called once per discovered file.
-- Parse the file and call sbomgen.push_package() for each package found.
function collect(file_path)
    local content, err = sbomgen.read_file(file_path)
    if err or not content then return end

    for line in content:gmatch("[^\r\n]+") do
        local name, version = line:match("^([%w%-%_%.]+)==(.+)$")
        if name and version then
            sbomgen.push_package({
                name = name,
                version = version,
                purl_type = "pypi",
                component_type = sbomgen.component_types.LIBRARY,
            })
        end
    end
end
```

 `collect()`는 값을 반환하지 않습니다. 모든 `push_package()` 호출에는 `name`, `purl_type`및가 필요합니다`component_type`. 지원되는 모든 필드는 [플러그인 API 참조](sbomgen-plugin-api-reference.md) 단원을 참조하십시오.

### 구성 요소에 메타데이터 연결
<a name="sbomgen-plugin-developer-guide-attaching-metadata-to-components"></a>

 Sbomgen은 **PURL 한정자와** **CycloneDX 속성**이라는 두 가지 방법으로 패키지 구성 요소에 메타데이터를 연결할 수 있습니다. 서로 다른 목적을 수행하며, 둘 중 하나를 선택하면 Amazon Inspector가 결과 SBOM의 취약성을 식별하는 방법에 영향을 미칩니다.


| **메커니즘** | **표시되는 위치** | **에 사용** | 
| --- | --- | --- | 
| qualifiers | 패키지 URL 내부(예: pkg:deb/debian/curl@7.88.1?arch=amd64) | 패키지 자격 증명의 일부인 데이터 | 
| properties | SBOM의 components[].properties 배열에서 | 패키지 식별 방법을 변경하지 않는 설명 메타데이터 | 

 **권장 사항: 사용자 지정 메타데이터에는 CycloneDX 속성(자체 네임스페이스 아래)을 선호합니다.** 속성은 구성 요소의 자격 증명을 변경하지 않으므로 Amazon Inspector의 취약성 식별에 영향을 미치지 않습니다. 에코시스템의 PURL 유형에 필요한 경우 PURL 한정자를 예약합니다.

#### PURL 한정자
<a name="sbomgen-plugin-developer-guide-purl-qualifiers"></a>

 일부 PURL 한정자는 Amazon Inspector에 의미가 있으며 취약성 식별에 영향을 미칩니다. 예를 들어 구성 `deb` 요소에서 Inspector는 `arch` 및와 같은 한정자를 사용하여 올바른 취약성 피드`distro`를 선택합니다. 컴파일된 바이너리의 `generic` 구성 요소에서와 같은 한정자를 `go_toolchain` 사용하거나 사용된 도구 체인을 `rust_toolchain` 식별합니다. 한정자 Inspector가 인식하지 못하거나 예상한 것을 생략하면 취약성이 누락되거나 잘못 귀속될 수 있습니다.

 [패키지 URL이란 무엇입니까?를](https://docs.aws.amazon.com/inspector/latest/user/sbom-generator-purl-sbom.html) 참조하세요. Inspector가 PURL 유형별로 인식하는 한정자 규칙에 대한 Amazon Inspector 사용 설명서의 .

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

 한정자는 PURL 유형에 대한 Inspector의 기대치에 맞는 경우에만 설정합니다. 패키지 자격 증명의 일부가 아닌 메타데이터를 기록해야 하는 경우 대신 CycloneDX 속성을 사용합니다.

#### CycloneDX 속성
<a name="sbomgen-plugin-developer-guide-cyclonedx-properties"></a>

 CycloneDX 속성은 SBOM의 `components[].properties` 배열에 나타나는 키-값 주석입니다. 식별 방식에 영향을 주지 않고 구성 요소를 설명하므로 플러그인 정의 메타데이터에 안전한 선택입니다.

 **`amazon:inspector:*` 네임스페이스는 Amazon Inspector용으로 예약되어 있습니다.** 구체적으로 설명하면 다음과 같습니다.
+ `amazon:inspector:sbom_generator:*` - sbomgen 및 내장 스캐너용으로 예약되어 있습니다.
+ `amazon:inspector:sbom_scanner:*` - Amazon Inspector 스캔 API용으로 예약되어 있습니다.

 플러그인 작성자는 이러한 예약된 네임스페이스 내에서 키를 내보내서는 안 됩니다. 이를 기록하면 Inspector의 동작에 방해가 될 수 있으며 덮어쓸 수 있습니다. 예약 키의 전체 목록은 [ Amazon Inspector에서 CycloneDX 네임스페이스 사용을 참조하세요](https://docs.aws.amazon.com/inspector/latest/user/cyclonedx-namespace.html).

 속성을 정의할 때 자체 네임스페이스(일반적으로 조직 또는 플러그인 식별자)를 사용합니다.

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

#### 키 이름 지정 규칙
<a name="sbomgen-plugin-developer-guide-key-naming-rules"></a>

 속성 키는 다음과 같이 sbomgen에서 처리됩니다.
+ **콜론이 포함된** 키는 SBOM에서 축어적으로 사용됩니다. 네임스페이스를 제어하려면 항상 키에 콜론을 하나 이상 포함해야 합니다.
+ **콜론이 포함되지 않은** 키에는 자동으로 접두사가 붙어 예약된 Inspector 네임스페이스 내에 `amazon:inspector:sbom_generator:` 배치합니다. 사용자 지정 속성의 경우이 셰이프를 사용하지 마세요.

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

 공식 스캐너가 예약된 네임스페이스 내에서 일관된 키를 내보내도록 `sbomgen.properties.*` 상수가 존재합니다. 사용자 지정 플러그인의 확장 지점이 아닙니다. 대신 자체 네임스페이스를 사용합니다.

#### 하위 구성 요소의 속성 및 한정자
<a name="sbomgen-plugin-developer-guide-properties-and-qualifiers-on-child-components"></a>

 중첩`children`은 독립적인 구성 요소입니다. 각 하위 항목에는 자체 `properties` 및 `qualifiers` 테이블이 있습니다. 상위 항목에 설정된 메타데이터는 하위 항목에 전파되지 않습니다. 필요한 각 하위 항목에 명시적으로 값을 설정합니다.

### 선택적 수집 함수
<a name="sbomgen-plugin-developer-guide-optional-collection-functions"></a>


| **함수** | **기본값** | **재정의 시기...** | 
| --- | --- | --- | 
| get\_collector\_name() | {ecosystem} (예: python-pip) | 사용자 지정 수집기 이름을 원하는 경우 | 
| get\_collector\_description() | 빈 문자열 | 설명을 원하는 경우 | 
| subscribe\_to\_event() | 디렉터리 경로에서 파생됨 | 사용자 지정 이벤트 라우팅이 필요합니다. | 

## 플러그인 실행
<a name="sbomgen-plugin-developer-guide-running-your-plugins"></a>

 플러그인이 패키지 메타데이터를 생성하려면 플러그인 대상이 되는 파일(예: , `requirements.txt` `package.json`또는 이에 상응하는 패키지 매니페스트 파일이 있는 디렉터리)이 포함된 스캔할 아티팩트가 sbomgen에 제공되어야 합니다.

### 기본 사용법
<a name="sbomgen-plugin-developer-guide-basic-usage"></a>

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

 예제: 

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

### 네이티브 스캐너가 비활성화된 경우(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
```

### 세부 정보 로깅 사용
<a name="sbomgen-plugin-developer-guide-with-verbose-logging"></a>

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

## 사용 가능한 스캐너 나열
<a name="sbomgen-plugin-developer-guide-listing-available-scanners"></a>

 를 사용하여 sbomgen`list-scanners`에 사용할 수 있는 모든 스캐너를 확인합니다. 여기에는 기본 제공 기본 스캐너, sbomgen과 번들로 제공되는 공식 Lua 플러그인,를 통해 제공한 사용자 지정 Lua 플러그인이 포함됩니다`--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                    │
└─────────────────────┴────────┴───────────────────────────────┴─────────────────────────────┘
```

 SOURCE 열에는 각 스캐너의 출처가 표시됩니다.


| **소스** | **의미** | 
| --- | --- | 
| native | sbomgen과 번들로 제공되는 내장 스캐너 | 
| official | sbomgen과 번들로 제공되는 Lua 플러그인 | 
| custom | 를 통해 로드된 사용자 제공 Lua 플러그인 --plugin-dir | 

 를 사용하지 `list-scanners` 않고 실행해도 `--plugin-dir` `native`와 `official` 스캐너가 모두 포함되며 항상 사용할 수 있습니다. `--plugin-dir` 플래그는 목록에 `custom` 스캐너를 추가합니다.

 네이티브 스캐너가 없는 Lua 스캐너만 나열하려면: 

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

## 스캐너 선택
<a name="sbomgen-plugin-developer-guide-scanner-selection"></a>

 Lua 검색 플러그인은 기본 제공 기본 스캐너와 동일한 스캐너 선택 모델에 참여합니다. 기본적으로 sbomgen은 그룹이 아티팩트 유형의 기본 스캐너 그룹과 일치하는 모든 스캐너를 실행합니다. 다음 세 가지 플래그로 이를 재정의할 수 있습니다.

### 특정 스캐너만 실행
<a name="sbomgen-plugin-developer-guide-run-only-specific-scanners"></a>

 를 사용하여 명명된 스캐너만 `--scanners` 실행합니다. 다른 모든 스캐너는 제외됩니다.

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

 그러면 `python-requirements` 스캐너만 실행됩니다. 쉼표로 구분된 여러 스캐너 이름을 전달하거나 스캐너 그룹 이름(예: `programming-language-packages`)을 전달하여 해당 그룹에 속하는 모든 스캐너를 활성화할 수 있습니다.

### 특정 스캐너 제외
<a name="sbomgen-plugin-developer-guide-exclude-specific-scanners"></a>

 다른 모든 `--skip-scanners` 항목을 실행하는 동안를 사용하여 명명된 스캐너를 제외합니다.

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

 이렇게 하면를 제외한 모든 기본 스캐너가 실행됩니다`python-poetry`. 와 마찬가지로 `--scanners`이 플래그는 그룹 이름도 허용하므로 전달하면 해당 그룹의 모든 스캐너가 `--skip-scanners programming-language-packages` 비활성화됩니다.

**참고**  
`--scanners` 및 `--skip-scanners`는 상호 배타적입니다. 둘 다 전달하면 오류가 발생합니다.

### 기본이 아닌 그룹에서 스캐너 추가
<a name="sbomgen-plugin-developer-guide-add-scanners-from-non-default-groups"></a>

 기본 스캐너 세트는 스캔 중인 아티팩트 유형에 따라 다릅니다([그룹이 선택에 미치는 영향](#sbomgen-plugin-developer-guide-how-groups-affect-selection)아래의 매트릭스 참조). 그룹이 아티팩트 유형에 대한 기본 세트의 일부가 아닌 스캐너는 옵트인하지 않는 한 실행되지 않습니다. `--additional-scanners`를 사용하여 스캐너를 교체하지 않고 기본 세트에 스캐너를 추가합니다.

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

 그러면 아티팩트 유형에 대한 모든 기본 스캐너와가 실행됩니다`my-extra-scanner`. 플래그는 쉼표로 구분된 스캐너 이름 또는 그룹 이름 목록과 기본 세트가 있는 스택을 대체하는 대신 허용합니다. `list-scanners`를 사용하여 스캐너가 속한 그룹을 확인합니다.

### 그룹이 선택에 미치는 영향
<a name="sbomgen-plugin-developer-guide-how-groups-affect-selection"></a>

 검색 플러그인의 `get_scanner_groups()` 함수에 따라 스캐너가 속한 그룹이 결정됩니다. 스캐너가 기본적으로 실행되는지 여부는 그룹과 스캔 중인 아티팩트 유형에 따라 달라집니다. 아래 매트릭스는 각 아티팩트 유형에 대한 기본 스캐너 세트에 포함되는 그룹을 보여줍니다.


| **Group** | **`directory` / `archive`** | **`container`** | **`localhost`** | **`volume`** | **`binary`** | 
| --- | --- | --- | --- | --- | --- | 
| os | — | ✓ | ✓ | ✓ | — | 
| programming-language-packages | ✓ | ✓ | ✓ | ✓ | — | 
| binary | ✓ | ✓ | — | — | ✓ | 
| extra-ecosystems | — | ✓ | ✓ | ✓ | — | 
| dockerfile | ✓ | ✓ | — | — | — | 
| custom | ✓ | ✓ | ✓ | ✓ | ✓ | 
| certificate | — | — | — | — | — | 
| machine-learning | — | — | — | — | — | 
| pkg-scanner | — | — | — | — | — | 

 ✓는 해당 그룹의 모든 스캐너가 해당 아티팩트 유형에 대해 기본적으로 실행됨을 의미합니다. 는 그룹이 기본 세트에 있지 않으므로 `--scanners` 또는를 통해 명시적으로 선택한 경우에만 스캐너가 실행`—`됩니다`--additional-scanners`.

 주목할 만한 세부 정보: 
+ **`custom`**는 항상 기본 세트에 있습니다.를 통해 로드된 사용자 지정 플러그인은 `custom` 그룹을 `--plugin-dir` 자동으로 수신하므로 아티팩트 유형에 관계없이 기본적으로 실행됩니다.
+ **`extra-ecosystems`**는 `container`, `localhost`및 `volume` 스캔의 경우 기본값이지만 `directory`, `archive`또는 `binary` 스캔의 경우 기본값이 아닙니다. 이러한 유형의 경우 이를 포함하려면 `--additional-scanners` (이름 또는 `extra-ecosystems` 그룹)을 전달해야 합니다.
+ **`pkg-scanner`**는 정보 제공용입니다. 스캐너를에 표시할 패키지 수집기로 표시`list-scanners`하지만 자체적으로 스캐너가 실행되지는 않습니다. 에서 실행 그룹(예: `programming-language-packages`)과 페어링합니다`get_scanner_groups()`.

 예를 들어가 반환하는 플러그인`{sbomgen.groups.EXTRA_ECOSYSTEMS, sbomgen.groups.PACKAGE_COLLECTOR}`은 기본적으로 컨테이너, localhost 및 볼륨 스캔에서 실행되지만 디렉터리, 아카이브 및 바이너리 스캔에서는 `--additional-scanners` (또는 `--scanners`)가 필요합니다.

## 플러그인 충돌 규칙
<a name="sbomgen-plugin-developer-guide-plugin-collision-rules"></a>

 Sbomgen은 로드된 모든 플러그인에 고유한 메타데이터를 적용하여 자동 덮어쓰기를 방지하고 SBOM 무결성을 보장합니다. 충돌이 감지되면 이후 플러그인을 **건너뛰**고 경고가 로깅됩니다.

### 확인 항목
<a name="sbomgen-plugin-developer-guide-what-is-checked"></a>


| **Metadata** | **범위** | **충돌 시** | 
| --- | --- | --- | 
| 검색 이벤트 이름(get\_event\_name) | 모든 검색 플러그인 | 두 번째 플러그인 건너뛰기 | 
| 스캐너 이름(get\_scanner\_name) | 모든 검색 플러그인 | 두 번째 플러그인 건너뛰기 | 
| 수집기 이름(get\_collector\_name) | 모든 컬렉션 플러그인 | 두 번째 플러그인 건너뛰기 | 

### 허용되는 항목
<a name="sbomgen-plugin-developer-guide-what-is-allowed"></a>

 여러 컬렉션 플러그인은를 통해 동일한 이벤트를 구독할 **수** 있습니다`subscribe_to_event()`. 이는 의도한 팬아웃 패턴입니다. 한 검색 플러그인은 각각 서로 다른 작업을 수행하는 여러 수집기를 공급할 수 있습니다(예: 한 검색 플러그인은 패키지를 추출하고 다른 검색 플러그인은 보안 암호를 탐지함).

### 충돌 방지
<a name="sbomgen-plugin-developer-guide-avoiding-collisions"></a>

 두 플러그인이 동일한 스캐너 이름, 이벤트 이름 또는 수집기 이름을 사용하는 경우 로드된 두 번째 플러그인은 건너뜁니다. 충돌을 해결하려면 플러그인(, `get_event_name()`또는 `get_scanner_name()`)에서 적절한 재정의 함수를 정의하여 충돌하는 메타데이터의 이름을 변경합니다`get_collector_name()`.

### 충돌 경고 예제
<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.
```

 경고는 건너뛴 플러그인, 충돌한 플러그인, 해당 이름을 이미 소유한 플러그인, 변경할 함수를 알려줍니다.

## 디버깅
<a name="sbomgen-plugin-developer-guide-debugging"></a>

### 콘솔 로깅
<a name="sbomgen-plugin-developer-guide-console-logging"></a>

 플러그인은 다음 함수를 사용하여 sbomgen의 콘솔 출력으로 메시지를 내보낼 수 있습니다.


| **함수** | **수준** | **기본적으로 표시됩니까?** | 
| --- | --- | --- | 
| sbomgen.log\_debug(message) | DEBUG | 아니요 -에 필요 --verbose | 
| sbomgen.log\_info(message) | INFO | 예 | 
| sbomgen.log\_warn(message) | WARN | 예 | 
| sbomgen.log\_error(message) | 오류 | 예 | 

 플러그인의 모든 로그 출력에는 플러그인의 소스 및 경로(예: `[custom:python-pip]`)가 자동으로 접두사로 지정되므로 다른 플러그인의 메시지는 쉽게 구분할 수 있습니다. `log_info`, `log_warn`및는 `log_error` 항상 인쇄되며 sbomgen이 로 호출될 때`log_debug`만 인쇄됩니다`--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
```

### 중단점
<a name="sbomgen-plugin-developer-guide-breakpoints"></a>

 `sbomgen.breakpoint()`를 사용하여 플러그인 실행을 일시 중지하고 Enter 키를 누를 때까지 차단합니다. 이는 미정제 디버거 역할을 합니다. 이를 로그 문과 결합하여 특정 지점에서 상태를 검사합니다.

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

 중단점 메시지는 stderr에 인쇄됩니다. Enter 키를 누를 때까지 실행이 일시 중지되어 로그 출력을 검토할 시간이 제공됩니다.

### 일반적인 문제
<a name="sbomgen-plugin-developer-guide-common-issues"></a>


| **증상** | **원인** | **수정** | 
| --- | --- | --- | 
| 플러그인이 로드되지 않음 | 누락된 init.lua | 진입점이 올바른 디렉터리 깊이에 있는지 확인 | 
| "필수 함수 누락" | 함수 이름의 오타 | get\_scanner\_name, , get\_scanner\_description, get\_scanner\_groups, discover, get\_localhost\_scan\_paths, get\_collector\_name, get\_event\_namecollect,가 정의subscribe\_to\_event되어 있는지 확인합니다. | 
| 컬렉션 플러그인이 호출되지 않음 | 이벤트 이름 불일치 | 동일한 문자열 확인 get\_event\_name() 및 subscribe\_to\_event() 반환 | 
| SBOM에 패키지 없음 | push\_package 호출되지 않음 또는 필수 필드 누락 | 모든 push\_package 통화(하위 포함)에서 namepurl\_type, 및 component\_type가 설정되어 있는지 확인합니다. sbomgen.component\_types.\* 상수를 사용합니다. | 
| 플러그인의 런타임 오류 | 실행 중 Lua 오류 | 오류 세부 정보가 포함된 경고 메시지가 있는지 sbomgen 출력 확인 | 
| “SKIPPED: 검색 이벤트 이름 ...이 이미 등록되어 있습니다.” | 다른 플러그인은 동일한 이벤트 이름을 사용합니다. | 고유한 값으로 이름 바꾸get\_event\_name()기 | 
| “SKIPPED: 스캐너 이름 ...이 이미 등록되어 있습니다.” | 다른 플러그인은 동일한 스캐너 이름을 사용합니다. | 고유한 값으로 이름 바꾸get\_scanner\_name()기 | 
| "SKIPPED: collector name ... is already registered" | 다른 플러그인은 동일한 수집기 이름을 사용합니다. | 고유한 값으로 이름 바꾸get\_collector\_name()기 | 

## API 참조
<a name="sbomgen-plugin-developer-guide-api-reference"></a>

 전체 함수 카탈로그는 컴패니언 문서에 유지됩니다.

 **→ [플러그인 API 참조](sbomgen-plugin-api-reference.md)** 

 API 참조는 모든 `sbomgen.*` 함수(파일 I/O, 바이너리 유틸리티, 패키지 출력, 정규식, 구조화된 구문 분석, Windows 레지스트리, 로깅, 디버깅), 테스트 파일에서 사용할 수 있는 `testing.*` API, 모든 내장 상수(`properties`, `groups`, `component_types`, `platform`), 플러그인 수명 주기 글로벌을 다룹니다.

## 오류 처리
<a name="sbomgen-plugin-developer-guide-error-handling"></a>

 실패할 수 있는 API 함수는의 두 값을 반환합니다`value, err`. 성공 시 `err`는 입니다`nil`. 실패 시 첫 번째 값은 `nil` 이고는 오류 문자열`err`입니다.

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

 플러그인에서 처리되지 않은 Lua 오류가 발생하면 sbomgen은 경고를 기록하고 다음 파일 또는 플러그인을 계속 진행합니다. 다른 플러그인은 영향을 받지 않습니다.

## 샌드박스 제한 사항
<a name="sbomgen-plugin-developer-guide-sandbox-restrictions"></a>

 플러그인은 표준 라이브러리 액세스가 제한된 샌드박스 Lua VM에서 실행됩니다.


| **라이브러리** | **사용 가능** | **참고** | 
| --- | --- | --- | 
| base | ✓ | dofile, loadfile, loadstring 제거됨 | 
| string | ✓ | 전체 문자열 조작 | 
| table | ✓ | 전체 테이블 조작 | 
| math | ✓ | 전체 수학 라이브러리 | 
| package | ✓ | require() 플러그인 디렉터리로 제한됨 | 
| io | ✗ | 대신 sbomgen.\* I/O 함수 사용 | 
| os | ✗ | 보안을 위해 차단됨 | 
| debug | ✗ | VM 내부 검사를 방지하기 위해 차단됨 | 
| coroutine | ✗ | 로드되지 않음 | 

 `io.open` 또는를 통한 직접 파일 시스템 액세스`os.execute`는 사용할 수 없습니다. 모든 파일 작업은 아티팩트 유형 전반에서 일관된 동작을 보장하고 플러그인이 아티팩트 외부의 파일에 액세스하지 못하도록 `sbomgen` API를 거쳐야 합니다.

 `require()`는 플러그인의 자체 디렉터리 트리 내에서만 모듈을 로드할 수 있습니다. 와 같은 상위 디렉터리 순회`require("../shared")`가 차단됩니다.

## 플러그인 간 코드 공유
<a name="sbomgen-plugin-developer-guide-sharing-code-between-plugins"></a>

 `require()`를 사용하여 플러그인의 디렉터리 내에서 헬퍼 모듈을 로드할 수 있습니다.

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

 를 사용하는 하위 디렉터리도 지원`init.lua`됩니다.

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

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

 `require()`는 플러그인의 디렉터리로 제한됩니다. 다른 플러그인 또는 시스템 경로에서는 모듈을 로드할 수 없습니다. 타사 Lua 라이브러리(예: LuaRocks)는 지원되지 않으므로 플러그인 디렉터리 내의 로컬 헬퍼 모듈만 로드할 수 있습니다.