Trivy 贡献指南:为现有云服务商(Provider)新增 Service 支持(以 AWS CodeBuild 为例)
本文为 Trivy IaC 检查体系贡献者指南的一部分,讲解如何为已有的云服务商(如 AWS)新增一个 Service(云服务)支持。读完本文,你将掌握:如何在 Provider 目录中定义承载扫描目标的数据结构(struct)、如何利用 iacTypes 包装类型保留资源的文件/行号元数据、如何编写 Terraform/CloudFormation 等 IaaS 到该结构的 Adapter,以及如何用 mage 命令自动生成并校验 Rego Schema。
什么是 Service,为什么需要新增
在 Trivy 的 IaC 误配置检查体系中,"service" 指的是云服务商(cloud provider)提供的一项服务,例如 AWS 的 RDS、S3、CodeBuild 等。所有已支持的服务定义都位于 pkg/iac/providers 目录中。
当你要为某个云服务写 Rego 检查(checks)时,首先要确认该 provider 下是否已经有目标 service;如果没有,就需要按本文的流程为其添加支持。这一步是后续编写内置检查(如 builtin.aws.rds.aws0176 这类规则)的前提——检查的 input 就是这些 service 结构体经 JSON 序列化后的 Schema。新增一个 service 需要两件事:
- 一个数据结构(struct):用于存放待扫描资源的属性信息;
- 一个或多个 Adapter:把各类扫描目标(Terraform、CloudFormation、Ansible 等)的原始输入转换成上述数据结构。
前置条件:确认服务尚未被支持
开始之前,请先检查 pkg/iac/providers 下目标 provider 的 struct 中是否已经包含你要添加的 service。以 AWS 为例,pkg/iac/providers/aws/aws.go 定义了 AWS 聚合结构,其中每个字段对应一个已支持的服务:
type AWS struct {
Meta Meta
AccessAnalyzer accessanalyzer.AccessAnalyzer
APIGateway apigateway.APIGateway
Athena athena.Athena
Cloudfront cloudfront.Cloudfront
CloudTrail cloudtrail.CloudTrail
CloudWatch cloudwatch.CloudWatch
CodeBuild codebuild.CodeBuild
Config config.Config
// ... 还有 DocumentDB、DynamoDB、EC2、ECR、ECS、EKS、IAM、KMS、
// Lambda、RDS、Redshift、S3、SAM、SNS、SQS、SSM、WorkSpaces 等
}
从源码结构看,AWS struct 的字段命名基本就是各 service 的包名(如 CodeBuild codebuild.CodeBuild、RDS rds.RDS)。如果你的目标服务不在其中,就可以继续下面的流程。
步骤一:在 provider 目录下创建 service 的数据结构
以给 AWS 添加 CodeBuild 服务为例。第一步是在 provider 目录下为新服务创建独立的子目录和文件,即 pkg/iac/providers/aws/codebuild/codebuild.go。
被扫描的输入是用户配置并希望检测误配置的 CodeBuild 资源,因此需要定义一个顶层 struct 来承载它:
type CodeBuild struct {
Projects []Project
}
CodeBuild 服务管理的是 Project 资源,因此再定义 Project struct 保存每个 Project 的属性;而 Project 又管理 ArtifactSettings:
type Project struct {
Metadata iacTypes.Metadata
ArtifactSettings ArtifactSettings
SecondaryArtifactSettings []ArtifactSettings
}
type ArtifactSettings struct {
Metadata iacTypes.Metadata
EncryptionEnabled iacTypes.BoolValue
}
以上正是仓库中 codebuild.go 的完整定义。其中有两个值得深入理解的 Trivy 约定:
1. 每个资源都内嵌 iacTypes.Metadata
iacTypes.Metadata 被嵌入到所有 Trivy 资源类型中,为每个资源提供一套统一的元数据,包括该资源定义所在的文件路径、行号以及资源名称(定义见 pkg/iac/types/metadata.go)。这保证了扫描报告能够精确指回 IaC 源码中的具体位置。
2. 用 iacTypes 包装类型代替裸的 string/bool
例如 ArtifactSettings 中,Project 可以有名称、也可以可选地开启加密,但这里没有直接使用 string 和 bool,而是使用 Trivy 类型 iacTypes.Metadata 和 iacTypes.BoolValue。这些类型(如 pkg/iac/types/bool.go、pkg/iac/types/string.go)对原始值进行包装,并额外携带"这个值是否由用户显式设置""值定义在哪个文件的哪一行"等元数据。
这一点在实际 Adapter 中体现得非常清楚。看 pkg/iac/adapters/terraform/aws/codebuild/adapt.go:
project := codebuild.Project{
Metadata: resource.GetMetadata(),
ArtifactSettings: codebuild.ArtifactSettings{
Metadata: resource.GetMetadata(),
EncryptionEnabled: types.BoolDefault(true, resource.GetMetadata()),
},
// ...
}
当 artifacts 块显式设置了 encryption_disabled = true 时,Adapter 会写入 types.Bool(false, ...)(有明确来源);而未显式设置时则回退为 types.BoolDefault(true, ...)(默认值)。从源码结构看,Rego 检查可以据此区分"用户明确关闭了加密"和"默认行为",从而减少误报。编写新的 service struct 时,建议参考 pkg/iac/providers 目录下的其他 provider 与 service,保持同样的命名与结构风格。
把新 service 注册到 provider struct
最后,在 provider 的聚合 struct 中引用你的新 service。对 AWS 而言,就是在 pkg/iac/providers/aws/aws.go 中添加字段并引入对应包:
type AWS struct {
...
CodeBuild codebuild.CodeBuild
...
}
步骤二:更新各 IaaS 的 Adapters
新增 service 后,需要更新所有会填充该 provider struct 的 adapter(位于 pkg/iac/adapters 目录)。以"为 Terraform 添加 CodeBuild 支持"为例,需要新增 pkg/iac/adapters/terraform/aws/codebuild/adapt.go,其核心调用链为:
func Adapt(modules terraform.Modules) codebuild.CodeBuild {
return codebuild.CodeBuild{
Projects: adaptProjects(modules),
}
}
func adaptProjects(modules terraform.Modules) []codebuild.Project {
var projects []codebuild.Project
for _, module := range modules {
for _, resource := range module.GetResourcesByType("aws_codebuild_project") {
projects = append(projects, adaptProject(resource))
}
}
return projects
}
Adapter 的工作模式是:遍历所有 Terraform module,按资源类型名(如 aws_codebuild_project)取出资源块,再逐字段映射到 service struct,并附带 GetMetadata() 记录文件/行号信息。
编写 Adapter 时请注意:
- 对照官方 IaC 资源的文档来理解各字段的语义。例如 CodeBuild 应参考 Terraform AWS Provider 中
aws_codebuild_project资源文档的字段定义(如artifacts块的type、encryption_disabled等); - 为每个 Adapter 编写测试:仓库中同目录下的 adapt_test.go 就是配套测试,覆盖了
artifacts块存在/缺失、secondary_artifacts等多个输入场景; - 如果该 provider 同时支持 CloudFormation、Ansible 等输入源,对应地也要更新 pkg/iac/adapters 下相应输入源(如
cloudformation/aws/...)的 adapter。
步骤三:生成并校验 Rego Schema
service 添加到 provider 后,还需要把它纳入 provider 的 Schema——Rego 检查正是通过 # METADATA 中的 schemas: input: schema["aws"] 将输入映射到具体的 provider/service 对象(详见 docs/community/contribute/checks/overview.md)。
这一过程已通过 mage 命令自动化。在 Trivy 仓库根目录执行:
mage schema:generate
mage schema:verify
从源码看,这两个目标最终会执行 magefiles/schema.go 中的逻辑(由 magefile.go 以 -tags=mage_schema 构建方式驱动):
schema:generate调用schemas.Build()基于 Go 结构反射构建出完整的 IaC Schema,将其 JSON 序列化后写入pkg/iac/rego/schemas/cloud.json;schema:verify则重新构建 Schema 并与已提交的cloud.json逐字节比对,若不一致会提示schema is out of date: please run 'mage schema:generate' and commit the changes。
因此完整的贡献流程是:定义 service struct → 注册到 provider → 编写各输入源的 Adapter 与测试 → mage schema:generate → 提交时运行 mage schema:verify 确保 Schema 已同步。
小结
为 Trivy 现有 provider 添加新 service 的三步走:
| 步骤 | 关键产物 | 参考路径 |
|---|---|---|
| 1. 定义数据结构 | service struct + iacTypes.Metadata/BoolValue 等包装类型,并注册进 provider struct |
pkg/iac/providers/aws/codebuild/codebuild.go、pkg/iac/providers/aws/aws.go |
| 2. 编写 Adapter | 将 Terraform/CloudFormation 等资源块映射为 service struct,配套测试 | pkg/iac/adapters/terraform/aws/codebuild/adapt.go |
| 3. 生成 Schema | mage schema:generate / mage schema:verify 维护 pkg/iac/rego/schemas/cloud.json |
magefiles/schema.go |
完成以上步骤后,该 service 即可作为 Rego 检查的输入,供社区在 docs/community/contribute/checks/overview.md 所述的流程中编写具体的安全规则。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0622
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00