View a markdown version of this page

插件 API 参考 - Amazon Inspector

本文属于机器翻译版本。若本译文内容与英语原文存在差异,则一律以英文原文为准。

插件 API 参考

Inspector-sbomgen Lua 插件的完整 API 参考。有关编写插件的指南,请参阅插件开发者指南。有关测试的信息,请参阅插件测试指南

概述

运行时提供的所有函数均可通过全局sbomgen表(文件 I/O、正则表达式、日志记录、常量等)进行访问。此外,每个插件都定义了一小部分顶级全局函数(discover、、collectget_scanner_namesubscribe_to_event、等),sbomgen 在插件生命周期的定义时刻调用这些函数。这些记录在插件生命周期全局变量

*_test.lua文件中,sbomgen 还公开了一个testing全局变量,允许测试作者驱动发现→集合管道并做出断言。请参阅正在测试 API

沙盒限制

插件在沙箱 Lua 虚拟机中运行,标准库访问受限。有以下 Lua 标准库模块可用

模块 备注
base 核心功能(printtypetostringtonumberpairsipairspcall、、errorselectunpackrawgetrawset、、等)。 dofileloadfile、和loadstring被移除
string 全字符串操作(string.matchstring.findstring.formatstring.gsub、等)
table 全表操作(table.inserttable.removetable.sorttable.concat、等)
math 完整的数学库(math.floormath.maxmath.min、、等)
package require()可用,但仅限于插件自己的目录树中的模块。父目录遍历 () require("../shared") 已被阻止。 package.cpathpackage.path被清除。

出于安全性和稳定性考虑,明确禁止使用以下标准库模块:

模块 原因
io 直接文件系统访问已被阻止。所有文件操作都必须通过sbomgen.*函数,这些函数通过构件接口进行路由,以实现跨对象类型(目录、容器、卷等)的一致行为。
os 系统级操作(os.executeos.removeos.renameos.getenv、等)被阻止,以防止插件修改主机系统。
debug 阻止调试库是为了防止检查或修改 Lua VM 内部结构。
coroutine 协程未加载。

这些模块不在虚拟机的许可名单中,也无法通过插件访问。

注意

重要:所有文件都 I/O 必须经过sbomgen.*函数(例如sbomgen.read_filesbomgen.open_filesbomgen.get_file_list)。使用io.open或任何直接访问文件系统都会引发运行时错误。sbomgenAPI 可确保插件与构件抽象层交互,无论是扫描目录、容器映像、档案还是卷,工件抽象层都能提供一致的行为。

插件生命周期全局变量

插件是一个名为 Lua 的文件init.lua,它定义了某些顶级全局函数。这些全局变量sbomgen桌面上——它们是插件定义的函数,供sbomgen调用。发现插件和集合插件的有效全局变量集不同。对于下面的每个函数,如果插件省略了该函数,则使用表格中显示的默认值。

发现插件

函数 阿里 必填 默认(省略时) 描述
discover() 0 返回此插件找到的文件。返回路径字符串的顺序表(单事件模式)或由事件名称字符串键控的表,其值为路径表(多事件模式)。
get_event_name() 0 "lua:{platform}/{category}/{ecosystem}" 返回发布文件所依据的事件名称。在所有发现插件中必须是唯一的。
get_scanner_name() 0 生态系统目录名称 返回扫描仪的显示名称。在所有发现插件中必须是唯一的。
get_scanner_description() 0 "Lua discovery plugin: {ecosystem}" 返回人类可读的描述。
get_scanner_groups() 0 源自类别目录(参见开发者指南) 返回扫描仪组字符串表。使用sbomgen.groups.*常量。
get_localhost_scan_paths() 0 返回扫描本地主机构件时要包含的 file/directory 路径表。仅在localhost扫描时咨询。

集合插件

函数 阿里 必填 默认(省略时) 描述
collect(file_path) 1 每个发布到已订阅事件的文件都调用一次。解析文件并通过发送调查结果。sbomgen.push_package()不返回任何内容。
subscribe_to_event() 0 "lua:{platform}/{category}/{ecosystem}" 返回该收集器订阅的事件名称。应与相应的发现插件相匹配get_event_name()
get_collector_name() 0 生态系统目录名称 返回收藏家的显示名称。在所有集合插件中必须是唯一的。
get_collector_description() 0 ""(空) 返回人类可读的描述。

文件 I/O

所有文件操作都必须通过 sbomgen.* API 进行。无法通过 Lua 的io库直接访问文件系统(请参阅沙盒限制)。sbomgen文件 I/O 函数通过工件接口进行路由,确保您的插件无论是扫描磁盘上的目录、容器映像、压缩存档还是已装入的卷,都能以相同的方式工作。

sbomgen.get_file_list()

以字符串表的形式返回构件中的所有文件路径。

  • 返回:{string, ...}— 绝对文件路径字符串表

  • 性能:此函数将构件中的每个文件路径都作为 Lua 字符串复制到 Lua VM 中。对于大型工件(例如,包含30万多个文件的本地主机扫描),仅此一项就需要几秒钟。在 Lua 中迭代返回的表string.match()会增加更多的开销——完整扫描可能需要 15 秒以上。工件中的文件越多,插件的速度就越慢。

注意

尽可能首选以下有针对性的替代方案:

函数 在... 时使用
sbomgen.find_files_by_name() 你知道要匹配的确切文件名(例如,"requirements.txt""curl"
sbomgen.find_files_by_name_icase() 同上,但不区分大小写
sbomgen.find_files_by_suffix() 你需要匹配路径后缀(例如,,"/pom.properties""curlver.h"
sbomgen.find_files_by_path_regex() 你需要全路径正则表达式匹配
sbomgen.glob_find_files() 你需要全局风格的基本名称匹配

这些函数在 Lua VM 之外执行匹配,仅返回匹配的路径,即使在 300K 文件工件上也能在 1 毫秒内完成。get_file_list()仅当您的匹配逻辑无法用上述任何一种表达时才使用。

-- AVOID in discovery plugins when possible: local files = sbomgen.get_file_list() for _, f in ipairs(files) do if string.match(f, "pattern$") then ... end end -- PREFER: local matches = sbomgen.find_files_by_name({"target-file.txt"})

sbomgen.read_file(path)

读取文件的全部内容并将其作为字符串返回。

  • 退货:string, err

  • 失败时:nil, error_string

local content, err = sbomgen.read_file("/app/package.json") if err then sbomgen.log_error("read failed: " .. err) return end

sbomgen.open_file(path)

打开文件进行流式读取。返回一个 FileHandle 对象。对于不切实际地将全部内容加载到内存中的大型文件,请使用此选项。

  • 退货:FileHandle, err

local fh, err = sbomgen.open_file(path) if err then return end local line = fh:read_line() while line do -- process line line = fh:read_line() end fh:close()

sbomgen.glob_find_files(pattern)

返回与 filepath.Match Go glob 模式匹配的文件。该模式与基本文件名相匹配。

  • 退货:{string, ...}, err

local files, err = sbomgen.glob_find_files("*.txt")

sbomgen.get_file_list()与一起使用string.match可进行完整路径模式匹配。

sbomgen.find_files_by_name(names)

返回其基本名称(最后一个路径组件)与给定名称之一完全匹配的文件。迭代和比较发生在 Go 中,这使得迭代和比较比在 Lua sbomgen.get_file_list() 中迭代要快得多。

  • 参数:names— 字符串表(要匹配的基本名称)

  • 返回:{string, ...}— 匹配的文件路径(无错误元组)

local curl_bins = sbomgen.find_files_by_name({"curl", "curl.exe"}) local headers = sbomgen.find_files_by_name({"curlver.h"})

sbomgen.find_files_by_name_icase(names)

返回基本名称与给定名称之一匹配的文件,忽略大小写。例如,"version"匹配VERSIONVersion、和version。比如find_files_by_name,匹配发生在 Lua 虚拟机之外。

  • 参数:names— 字符串表(要匹配的基本名称,不区分大小写)

  • 返回:{string, ...}— 匹配的文件路径(无错误元组)

local version_files = sbomgen.find_files_by_name_icase({"version"}) local war_files = sbomgen.find_files_by_name_icase({"jenkins.war"})

sbomgen.find_files_by_suffix(suffixes)

返回其完整 (forward-slash-normalized) 路径以给定后缀之一结尾的文件。比如find_files_by_name,匹配发生在 Lua 虚拟机之外。

  • 参数:suffixes— 字符串表(要匹配的路径后缀)

  • 返回:{string, ...}— 匹配的文件路径(无错误元组)

local pom_files = sbomgen.find_files_by_suffix({"/pom.properties"}) local release_headers = sbomgen.find_files_by_suffix({"ap_release.h", "opensslv.h"})

sbomgen.find_files_by_path_regex(patterns)

返回 forward-slash-normalized路径与任何给定 Go (RE2) 正则表达式模式匹配的文件。匹配发生在 Lua VM 之外,这使得在大文件列表上更有效率。

  • 参数:patterns— Go 正则表达式字符串表

  • 返回:{string, ...}— 匹配的文件路径(无错误元组)

  • 引发:如果任何模式无法编译,则会出现 Lua 错误

local configs = sbomgen.find_files_by_path_regex({"/etc/.*\\.conf$", "/opt/.*/config\\.json$"})

性能:find_files_by_*vs get_file_list

对于发现插件,最好使用find_files_by_namefind_files_by_suffix、或find_files_by_path_regex而不是get_file_list()在 Lua 中进行迭代。在包含 30 万个文件的本地主机扫描中,在 Lua 中迭代文件列表大约需要 15 string.match() 秒,而在 1 毫秒内find_files_by_name完成。不同之处在于,将每个文件路径作为字符串get_file_list()复制到 Lua VM 中,然后 Lua 解释每个路径的循环和模式匹配。这些find_files_by_*函数在 Lua VM 之外执行匹配并仅返回匹配的路径,从而避免了复制和每个路径的解释开销。

get_file_list()仅当您需要无法用基本名称、后缀或正则表达式匹配表示的自定义匹配逻辑时才使用。

sbomgen.read_dir(path)

列出目录中的条目。

  • 退货:{{name, is_dir}, ...}, err

local entries, err = sbomgen.read_dir("/app/node_modules") if err then return end for _, e in ipairs(entries) do if e.is_dir then sbomgen.log_debug("directory: " .. e.name) end end

sbomgen.file_stat(path)

返回有关文件的元数据。

  • 退货:{is_regular, is_dir, size}, err

local info, err = sbomgen.file_stat(path) if err then return end if info.is_regular and info.size > 0 then -- process file end

sbomgen.read_zip_entry(path, entry_path)

从 ZIP、JAR 或 WAR 存档中读取单个条目。

  • 退货:string, err

local manifest, err = sbomgen.read_zip_entry( "/app/lib/example.jar", "META-INF/MANIFEST.MF" )

sbomgen.search_binary(path, regex)

将文件解析为 ELF、PE 或 Mach-O 二进制文件,然后在默认 constant/variable 部分中搜索 Go 正则表达式匹配项。

  • 返回:string|nil, err— 匹配的字符串,如果不匹配则返回 nil

local version, err = sbomgen.search_binary(path, "Version:\\s+([\\d.]+)") if version then sbomgen.log_info("found version: " .. version) end

sbomgen.search_binary_all(path, regex [, n])

将文件解析为 ELF、PE 或 Mach-O 二进制文件,并返回默认部分中所有唯一的第一个捕获组匹配项。 constant/variable 通过n以限制结果。

  • 返回:{string, ...}|nil, err— 匹配字符串表,如果没有匹配项,则返回 nil

local versions, err = sbomgen.search_binary_all(path, "version[= ]+([\\d.]+)", 5) if versions then for _, v in ipairs(versions) do sbomgen.log_info("found: " .. v) end end

sbomgen.search_binary_raw(path, regex)

在整个二进制文件中搜索第一个正则表达式匹配项,而不限于特定部分。在基于节的搜索 (search_binary) 不足时使用,例如,当版本字符串位于非标准部分时。

  • 返回:string|nil, err— 匹配的字符串,如果不匹配则返回 nil

local version, err = sbomgen.search_binary_raw(path, "ProductVersion[\\x00\\s]+([\\d.]+)")

FileHandle 方法

FileHandle 对象由返回sbomgen.open_file()

fh:read_line()

读取下一行(不含换行符)。nil在 EOF 时返回。

  • 退货:string|nil, err

fh:read(n)

读取最多n字节。nil在 EOF 时返回。

  • 退货:string|nil, err

fh:close()

关闭文件句柄。完成后请务必关闭手柄。

二进制实用程序

sbomgen.sha256(path)

返回文件内容的十六进制编码 SHA-256 哈希值。

  • 退货:string, err

local hash, err = sbomgen.sha256("/app/bin/server") if hash then sbomgen.log_info("SHA-256: " .. hash) end

sbomgen.contains_bytes(path, patterns)

检查文件是否包含每个给定的字节模式。按与输入模式相同的顺序返回布尔值表。

  • 退货:{bool, ...}, err

local results, err = sbomgen.contains_bytes(path, { "\xff Go buildinf:", -- Go build identifier "/rustc/", -- Rust build identifier }) if results then local is_go = results[1] local is_rust = results[2] end

sbomgen.get_pe_version_info(path)

从二进制文件中解析 Windows PE 版本资源。返回包含版本字段的表,或者nil, err如果该文件不是 PE 二进制文件或没有版本资源。

  • 退货:{product_version, file_version, string_table}, err

product_versionfile_version字段来自 PE FixedFileInfo 结构,格式为"major.minor.build.revision"。该string_table字段是一个由区域代码键控的嵌套表(例如,"040904B0"对于美国英语 Unicode)。每个语言环境都映射到从 PE 中抽取的 name/value 对表StringFileInfoProductVersionProductNameFileDescription、、等)。PE 二进制文件可能会暴露一个或多个语言环境。

local info, err = sbomgen.get_pe_version_info(file_path) if err then return end -- Fixed version fields (always flat) local product_ver = info.product_version -- e.g. "25.1.0.0" local file_ver = info.file_version -- e.g. "25.1.0.0" -- String table — iterate locales, or address a known locale by key for locale, fields in pairs(info.string_table or {}) do sbomgen.log_info(string.format("%s ProductName=%s", locale, fields.ProductName or "")) end -- US English Unicode is the most common locale for PE files local us = (info.string_table or {})["040904B0"] if us then local display_ver = us.ProductVersion -- e.g. "25.01" local name = us.ProductName -- e.g. "7-Zip" end

sbomgen.parse_product_version(path)

便捷包装器,仅返回 PE 二进制文件中的产品版本字符串。 FixedFileInfo相当于打电话get_pe_version_info(path)和读书product_version

  • 退货:string, err

local version, err = sbomgen.parse_product_version(file_path) if version then sbomgen.log_info("product version: " .. version) end

sbomgen.parse_file_version(path)

便捷包装器,仅返回 PE 二进制文件中的文件版本字符串。 FixedFileInfo相当于打电话get_pe_version_info(path)和读书file_version

  • 退货:string, err

local version, err = sbomgen.parse_file_version(file_path) if version then sbomgen.log_info("file version: " .. version) end

Package 输出

sbomgen.push_package(pkg)

将软件包查找结果推送到 SBOM 中。仅在集合插件中可用。

pkg表支持以下字段:

字段 Type 必填 描述
name 字符串 软件包名称
version 字符串 已解析的版本字符串
namespace 字符串 PURL 命名空间(例如,"curl""wordpress/plugin"
purl_type 字符串 PURL 类型(例如、"pypi"、、"npm""cargo""deb""generic"
component_type 字符串 CycloneDX 组件类型;使用sbomgen.component_types.*常量(例如)sbomgen.component_types.LIBRARY
qualifiers PURL 限定符作为键值对(出现在软件包 URL 中)
properties CycloneDX 组件属性作为键值对(参见)CycloneDX 属性
children 嵌套子包,每个子包的形状都与pkg(递归验证必填字段)
sbomgen.push_package({ name = "requests", version = "2.28.1", purl_type = "pypi", component_type = sbomgen.component_types.LIBRARY, qualifiers = { example_qualifier = "example_qualifier_value" }, properties = { -- Use your own namespace; amazon:inspector:* is reserved for Amazon Inspector. ["acme:example:extra_field"] = "example_value", }, })

CycloneDX 属性

CycloneDX 属性是附加到 SBOM 中组件的键值元数据。它们不同于 PURL 预选赛:

  • qualifiers— PURL 预选赛。它们成为软件包 URL 字符串的一部分(例如pkg:deb/debian/curl@7.88.1?arch=amd64)。一些 PURL 限定符对 Amazon Inspector 具有语义意义,会影响漏洞识别。请参阅什么是包裹 URL? 了解检查员的每种类型的惯例。

  • properties— CycloneDX 组件属性。它们显示在 SBOM 的components[].properties数组中,不会更改组件的标识方式。

保留的命名空间

CycloneDX 属性命名空间amazon:inspector:*系列是为 Amazon Inspector 保留的:

  • amazon:inspector:sbom_generator:*— 由 sbomgen 及其内置扫描仪使用。

  • amazon:inspector:sbom_scanner:*— 由 Amazon Inspector Scan API 使用。

插件定义的属性不得使用这些命名空间。写入保留的命名空间可能会与 Inspector 所依赖的值发生阴影或冲突,并且在漏洞识别过程中可能会错误地解释生成的 SBOM。有关保留密钥的完整列表,请参阅在 Amazon Inspector 中使用 CycloneDX 命名空间。

密钥命名规则

传递给的属性键sbomgen.push_package()的处理方式如下:

输入键 SBOM 中生成的密钥 推荐用于自定义插件?
包含:(例如,acme:my_plugin:field 逐字使用 — 将所有插件定义的属性放在你自己的命名空间中
:(例如,field 自动添加前缀为 amazon:inspector:sbom_generator:field 不是 — 这会写入保留的命名空间

请务必在您定义的属性键中至少包含一个冒号。使用您的组织或插件独有的命名空间(例如acme:python-pip:*):

properties = { -- Custom namespace — safe to use (recommended) ["acme:python-pip:manifest_path"] = file_path, ["acme:python-pip:pinned"] = "true", -- Fully-qualified key outside amazon:inspector:* — also fine ["my:custom:namespace:key"] = "value", -- No colon: avoid — ends up as "amazon:inspector:sbom_generator:custom_field" -- custom_field = "value", }

由 sbomgen 设置的属性

Sbomgen 可以将自己的属性附加到它发出的每个组件上。这些值来自保留的amazon:inspector:sbom_generator:*命名空间,不应由插件生成。观察到的运行时行为:

  • source_path总是由 sbomgen 添加的。

  • source_file_scanner并在启用source_package_collector--enable-debug-props时添加。

Amazon Inspector 用户指南:将 Cy cloneDX 命名空间与 Amazon Inspector 一起使用

属性常量

内置的属性键常量可通过sbomgen.properties获得。下面的每个常量都解析为保留amazon:inspector:sbom_generator:*命名空间内的一个密钥。这些常量的存在是为了让 sbomgen 的内置扫描器发出一致的属性键。它们不是自定义插件的扩展点——在自定义插件中使用它们会写入保留的命名空间,而 Inspector 可以依赖这些值。见保留的命名空间上文。

例如acme:my_plugin:*,自定义插件作者应在自己的命名空间下定义属性,而不是重复使用这些常量。

常量 已解析值
sbomgen.properties.NAMESPACE amazon:inspector:sbom_generator:
sbomgen.properties.VENDOR amazon:inspector:sbom_generator:vendor
sbomgen.properties.FILE_SIZE_BYTES amazon:inspector:sbom_generator:file_size_bytes
sbomgen.properties.KERNEL_COMPONENT amazon:inspector:sbom_generator:kernel_component
sbomgen.properties.RUNNING_KERNEL amazon:inspector:sbom_generator:running_kernel
sbomgen.properties.UNRESOLVED_VERSION amazon:inspector:sbom_generator:unresolved_version
sbomgen.properties.TRANSITIVE_DEPENDENCY amazon:inspector:sbom_generator:experimental:transitive_dependency
sbomgen.properties.GO_REPLACE_DIRECTIVE amazon:inspector:sbom_generator:replaced_by
sbomgen.properties.DUPLICATE_PACKAGE amazon:inspector:sbom_generator:is_duplicate_package
sbomgen.properties.DUPLICATE_PURL amazon:inspector:sbom_generator:duplicate_purl
sbomgen.properties.DOCKERFILE_CHECK amazon:inspector:sbom_generator:dockerfile_finding
sbomgen.properties.CERTIFICATE_FINDING amazon:inspector:sbom_generator:certificate_finding
sbomgen.properties.CERTIFICATE_SUBJECT_NAME amazon:inspector:sbom_generator:certificate:subject_name
sbomgen.properties.CERTIFICATE_ISSUER_NAME amazon:inspector:sbom_generator:certificate:issuer_name
sbomgen.properties.CERTIFICATE_SIGNATURE_ALGORITHM amazon:inspector:sbom_generator:certificate:signature_algorithm
sbomgen.properties.CERTIFICATE_NOT_VALID_BEFORE amazon:inspector:sbom_generator:certificate:not_valid_before
sbomgen.properties.CERTIFICATE_NOT_VALID_AFTER amazon:inspector:sbom_generator:certificate:not_valid_after
sbomgen.properties.WINDOWS_REGISTRY_KEY amazon:inspector:sbom_generator:registry_key
sbomgen.properties.SUBSCRIPTION_ENABLED amazon:inspector:sbom_generator:subscription:enabled
sbomgen.properties.SUBSCRIPTION_NAME amazon:inspector:sbom_generator:subscription:name
sbomgen.properties.SUBSCRIPTION_LOCKED_VERSION amazon:inspector:sbom_generator:subscription:locked_version
sbomgen.properties.OPENSSL_FULL_VERSION amazon:inspector:sbom_generator:openssl:full_version
sbomgen.properties.HARDENED_IMAGE_VENDOR amazon:inspector:sbom_generator:hardened_image:vendor

扫描仪组

发现插件必须通过声明其扫描器组get_scanner_groups()。群组对扫描仪进行分类,并允许用户有选择地启用或禁用类别。常量可通过以下方式sbomgen.groups获得:

常量 描述
sbomgen.groups.OS "os" 操作系统包管理器(dpkg、rpm 等)
sbomgen.groups.PROGRAMMING_LANGUAGE "programming-language-packages" 语言包管理器(pip、npm、maven 等)
sbomgen.groups.BINARY "binary" 编译后的二进制分析(Go、Rust)
sbomgen.groups.PACKAGE_COLLECTOR "pkg-scanner" 一般包裹集合
sbomgen.groups.EXTRA_ECOSYSTEMS "extra-ecosystems" 其他生态系统(curl、nginx 等)
sbomgen.groups.CERTIFICATE "certificate" 证书扫描
sbomgen.groups.CUSTOM "custom" 自动添加到通过加载的所有自定义插件中 --plugin-dir
sbomgen.groups.MACHINE_LEARNING "machine-learning" 机器学习模型检测

示例:

function get_scanner_groups() return {sbomgen.groups.PROGRAMMING_LANGUAGE, sbomgen.groups.PACKAGE_COLLECTOR} end

组件类型常量

中的component_type字段push_package()必须是 CycloneDX 1.5 组件类型之一。常量可通过以下方式sbomgen.component_types获得:

常量
sbomgen.component_types.APPLICATION "application"
sbomgen.component_types.FRAMEWORK "framework"
sbomgen.component_types.LIBRARY "library"
sbomgen.component_types.CONTAINER "container"
sbomgen.component_types.PLATFORM "platform"
sbomgen.component_types.OPERATING_SYSTEM "operating-system"
sbomgen.component_types.DEVICE "device"
sbomgen.component_types.DEVICE_DRIVER "device-driver"
sbomgen.component_types.FIRMWARE "firmware"
sbomgen.component_types.FILE "file"
sbomgen.component_types.MACHINE_LEARNING_MODEL "machine-learning-model"
sbomgen.component_types.DATA "data"

示例:

sbomgen.push_package({ name = "requests", version = "2.28.1", purl_type = "pypi", component_type = sbomgen.component_types.LIBRARY, })

平台常量

用于比较sbomgen.get_platform()的常量。可通过sbomgen.platform以下方式获得:

常量
sbomgen.platform.LINUX "linux"
sbomgen.platform.WINDOWS "windows"
sbomgen.platform.DARWIN "darwin"

示例:

if sbomgen.get_platform() == sbomgen.platform.WINDOWS then -- Windows-specific logic end

Artication

sbomgen.get_platform()

返回运行时平台字符串(例如"linux""windows""darwin")。

sbomgen.get_artifact_type()

返回正在扫描的工件的类型(例如"directory""archive")。

sbomgen.should_collect_licenses()

true如果用户通过启用了许可证收集,则返回--collect-licenses

sbomgen.get_env_vars()

{key, value}条目表的形式返回工件中的环境变量。

local env_vars = sbomgen.get_env_vars() for _, env in ipairs(env_vars) do if env.key == "NODE_ENV" then sbomgen.log_info("Node environment: " .. env.value) end end

sbomgen.get_system_drive()

从构件的环境中返回系统驱动器号(例如"C:")。读取SystemDrive环境变量,"C:"如果未设置,则默认为。这相当于 Lua。strutils.GetSystemDriverLetter()

local drive = sbomgen.get_system_drive() local program_files = drive .. "/Program Files/"

系统信息

这些函数返回有关工件操作系统和硬件的元数据。如果信息不可用(例如,扫描没有操作系统元数据的目录时),则值可能为空字符串。

函数 返回值
sbomgen.get_os_name() 操作系统名称(例如"Ubuntu""Alpine Linux"
sbomgen.get_os_version() 操作系统版本(例如,"22.04""3.18"
sbomgen.get_os_codename() 操作系统代号(例如,,"jammy""bookworm"
sbomgen.get_os_id() 操作系统标识符(例如"ubuntu""alpine"
sbomgen.get_kernel_name() 内核名称(例如"Linux"
sbomgen.get_kernel_version() 内核版本字符串
sbomgen.get_cpu_arch() CPU 架构(例如,"x86_64""aarch64"
sbomgen.get_hostname() 系统的主机名

正则表达式

Lua 的内置模式缺少交替 (|)、量词范围 ({n,}) 和前瞻等功能。为了缩小这一差距,sbomgen 直接暴露了 Go 的软件包。regexp这些函数使用 Go 正则表达式语法 (RE2),而不是 Lua 模式。

sbomgen.regex_find(str, pattern)

返回 Go 正则表达式模式的第一个匹配项,或者nil如果没有匹配则返回。

  • 退货:string|nil, err

local version = sbomgen.regex_find(content, "\\d+\\.\\d+\\.\\d+")

sbomgen.regex_match(str, pattern)

返回第一个匹配的捕获组。索引 1 为完整匹配,2+ 为捕获组。

  • 退货:{string, ...}|nil, err

local groups = sbomgen.regex_match(content, "(MySQL|MariaDB) (\\d+)\\.(\\d+)\\.(\\d+)") if groups then local db_type = groups[2] -- "MySQL" or "MariaDB" local major = groups[3] end

sbomgen.regex_find_all(str, pattern [, n])

返回所有不重叠的匹配项。通过n以限制结果(默认值:全部)。

  • 退货:{string, ...}|nil, err

local versions = sbomgen.regex_find_all(content, "\\d+\\.\\d+\\.\\d+")

sbomgen.regex_replace(str, pattern, replacement)

替换所有匹配项。替换字符串可以使用$1$2、等作为捕获组引用。

  • 退货:string, err

local cleaned = sbomgen.regex_replace(raw_version, "(1[6-9]\\d{8,}|buildkitsandbox.*)$", "")

何时使用正则表达式与 Lua 模式

使用 Lua 的内置 string.match /来string.find制作简单的模式 — 它们速度更快,不需要转义反斜杠。需要sbomgen.regex_*时使用:

  • 交替:(foo|bar)

  • 量词范围:\d{8,}

  • 复杂的字符类无法在 Lua 模式中表达

结构化解析

Sbomgen 公开了用于将结构化文本格式直接解码为 Lua 表的轻量级助手。

sbomgen.json_decode(str)

将 JSON 字符串解析为 Lua 表。

  • 退货:table|nil, err

local doc, err = sbomgen.json_decode('{"name":"requests","version":"2.28.1"}') if err then return end sbomgen.log_info(doc.name)

sbomgen.xml_decode(str)

将 XML 字符串解析为 Lua 表。

  • 退货:table|nil, err

XML 值使用以下形状:

  • _name— 元素名称

  • _attr— 属性表(如果存在)

  • _text— 修剪后的文本内容(如果存在)

  • 数字索引 1..n-子元素

local doc, err = sbomgen.xml_decode('<package id="Newtonsoft.Json" version="13.0.3" />') if err then return end sbomgen.log_info(doc._attr.id)

Windows 注册表

这些函数提供对 Windows 注册表的只读访问权限。在非 Windows 构件上,registry_open_key返回错误。注册表访问器在首次使用时会延迟初始化,并且支持实时 Windows API 访问(在 Windows 上进行本地主机扫描)和基于文件的 REGF 配置单元解析(容器/卷扫描)。

sbomgen.registry_open_key(path)

打开注册表项。返回必须用其关闭的密钥手柄registry_close

  • 退货:key, err

local key, err = sbomgen.registry_open_key("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\7-Zip") if err then return end -- use key... sbomgen.registry_close(key)

sbomgen.registry_get_string(key, value_name)

从打开的注册表项中读取字符串值。

  • 退货:string, err

local version, err = sbomgen.registry_get_string(key, "DisplayVersion")

sbomgen.registry_get_integer(key, value_name)

从打开的注册表项中读取整数值。

  • 退货:number, err

sbomgen.registry_get_strings(key, value_name)

从打开的注册表项中读取多字符串 (REG_MULTI_SZ) 值。返回字符串表。

  • 退货:{string, ...}, err

local paths, err = sbomgen.registry_get_strings(key, "DependsOnService") if paths then for _, p in ipairs(paths) do sbomgen.log_info("depends on: " .. p) end end

sbomgen.registry_get_subkeys(key)

返回打开的注册表项下的所有子项名称。

  • 退货:{string, ...}, err

local subkeys, err = sbomgen.registry_get_subkeys(key) for _, name in ipairs(subkeys) do local subkey, err = sbomgen.registry_open_key(parent_path .. "\\" .. name) -- ... end

sbomgen.registry_close(key)

关闭注册表项句柄。垃圾回收器也会自动关闭密钥句柄,但建议明确关闭。

日志记录

日志消息将写入 sbomgen 的控制台输出中。插件发出的每条消息都会自动以插件的源标签和生态系统为前缀,例如:

[custom:python-pip] Parsing requirements.txt

log_infolog_warn,并log_error始终打印。 log_debug仅在使用调用 sbomgen 时才会打印。--verbose

函数 级别 默认情况下可见?
sbomgen.log_debug(message) 调试 否 — 需要 --verbose
sbomgen.log_info(message) INFO
sbomgen.log_warn(message) 警告
sbomgen.log_error(message) ERROR

string.format用于格式化消息:

sbomgen.log_info(string.format("found %d packages in %s", count, file_path))

调试函数

sbomgen.breakpoint(message)

打印message到 stderr 并阻止执行,直到用户按下 Enter。如果省略,message则打印一条默认消息。

将其用作粗略的调试器,方法是在插件的关键点放置断点,然后运行--verbose以查看周围的日志输出。

sbomgen.log_info("state: " .. some_variable) sbomgen.breakpoint("paused after state dump — press Enter to continue")

正在测试 API

全局testing表下的函数仅在加载的插件测试文件 (*_test.lua) 中可用inspector-sbomgen plugin test。它们在运行时在发现或集合插件中不可用。完整的 sbomgen.* API 也可以在测试文件中找到,但是需要构件的sbomgen.*函数(例如sbomgen.read_file())只有在扫描内部调用时才会产生有意义的结果。有关叙事指南,请参阅插件测试指南

扫描功能

每个扫描函数都会创建一个给定类型的工件,针对它运行当前插件的 discovery→collection 管道,然后返回结果结果。path参数是相对于测试文件的目录进行解析的。

函数 Artical 那种
testing.scan_directory(path) 目录
testing.scan_archive(path) 目录(的别名scan_directory
testing.scan_localhost(path) 本地主机
testing.scan_binary(path) 二元
testing.scan_volume(path)
testing.scan_container(path) Container

所有六个都返回一个结果表,其形状如下所示。

结果形状

每个查找结果表仅投影下面列出的字段。特别是,namespace并且purl_type不是单独投影的——它们被合并到完整的purl字符串中。

local result = testing.scan_directory("_testdata/example") -- result.findings -- array of finding tables -- result.findings[i].name -- string -- result.findings[i].version -- string -- result.findings[i].component_type -- string -- result.findings[i].purl -- string (the full Package URL, or "" if none) -- result.findings[i].properties -- table<string, string> -- result.findings[i].children -- array of finding tables (same shape, recursive)

断言

函数 签名 描述
testing.assert_equals (expected: any, actual: any, message?: string) 如果出现则失败tostring(expected) ~= tostring(actual)
testing.assert_not_equals (expected: any, actual: any, message?: string) 如果出现则失败tostring(expected) == tostring(actual)
testing.assert_true (value: any, message?: string) 如果valuefalse或则失败nil
testing.assert_false (value: any, message?: string) 如果不valuefalse是,则失败nil
testing.assert_nil (value: any, message?: string) 如果不value是,则失败nil
testing.assert_not_nil (value: any, message?: string) 如果value是则失败nil
testing.assert_contains (haystack: string, needle: string, message?: string) 如果haystack不包含needle(子字符串匹配),则失败。
testing.assert_matches (str: string, pattern: string, message?: string) 如果与给定的 Go (RE2) 正则表达式str不匹配,则失败。
testing.assert_length (tbl: table, expected: integer, message?: string) 如果#tbl不等于,则失败expected

控制流

函数 签名 描述
testing.fail (message: string) 使用给定消息立即使当前测试失败。
testing.skip (message: string) 跳过当前测试。结果被报告为已跳过,而不是失败。

测试发现

文件匹配test_中名称以开头的任何全局 Lua 函数*_test.lua都被视为测试。测试文件必须位于正常{phase}/{platform}/{category}/{ecosystem}/深度旁边。init.lua夹具数据位于测试文件_testdata/旁边,运行器在搜索测试文件_testdata/时不会进入测试文件。

错误处理

可能失败的 API 函数返回两个值:value, err. 成功时,errnil。失败时,第一个值为nilerr为错误字符串。

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 会记录警告,然后继续处理下一个文件或插件。其他插件不受影响。