Trivy 误配置扫描配置指南:自定义检查、命名空间与内联忽略规则详解
【免费下载链接】trivyFind vulnerabilities, misconfigurations, secrets, SBOM in containers, Kubernetes, code repositories, clouds and more项目地址: https://gitcode.com/GitHub_Trending/tr/trivy
Trivy 的 misconfiguration(误配置)扫描器支持高度可定制的运行方式:你可以只启用特定的配置扫描器子集、加载自定义 Rego 检查与数据、控制 Rego 编译错误的容忍度,并通过行内注释精确忽略某条资源的误配置发现。本文基于 Trivy 官方文档与源码实现,系统讲解这些配置项的用法、参数含义与底层原理,帮助你针对 Terraform、CloudFormation、Helm、Dockerfile 以及任意 JSON/YAML 配置文件构建贴合自身业务的扫描策略。
启用误配置扫描器的子集
默认情况下,Trivy 会启用所有内置的配置扫描器。如果你只想关注特定类型的配置文件,可以通过--misconfig-scanners选项指定一个逗号分隔的扫描器类型列表:
trivy config --misconfig-scanners=terraform,dockerfile .上面的命令只会扫描与 Terraform 和 Dockerfile 相关的误配置,其他类型的配置文件将被跳过。
从源码看,该选项在 pkg/flag/misconf_flags.go 中定义为MisconfigScannersFlag,其配置项名称为misconfiguration.scanners,也就是说你同样可以在 Trivy 配置文件(trivy.yaml)中以如下形式固化默认值:
misconfiguration: scanners: - terraform - dockerfile该 flag 的默认值是analyzer.TypeConfigFiles中除去 YAML 与 JSON 之外的全部配置类型,这正与下文“JSON/YAML 默认不扫描”的行为相呼应。当你显式传入--misconfig-scanners时,会覆盖这一默认集合。
加载自定义检查(Checks)
内置检查(内置在builtin.*命名空间下)之外,你可以通过--config-check加载自己的 Rego 检查文件或目录。该选项可以重复指定,以加载多个文件或目录:
trivy config --config-check custom-policy/policy --config-check combine/policy --config-check policy.rego --namespaces user myapp此外,你还可以把检查打包成 OCI 镜像托管在容器镜像仓库中,通过--checks-bundle-repository直接加载整个检查包:
trivy config --checks-bundle-repository myregistry.local/mychecks --namespaces user myapp在 pkg/flag/misconf_flags.go 中,ChecksBundleRepositoryFlag的默认值是policy.BundleRepository与policy.BundleVersion组合出的官方仓库地址;你只需要把它替换成自己的私有仓库即可加载自定义的检查集合。
传递自定义数据(Custom Data)
部分检查在做判断时需要额外的参考数据(例如“允许创建的端口列表”“可信容器镜像仓库列表”)。你可以通过--config-data(原文档中的--data)传入包含 JSON(*.json)与 YAML(*.yaml)文件的目录,Trivy 会递归搜索这些目录。该选项可以重复指定多个目录:
cd examples/misconf/custom-data trivy config --config-check ./my-check --data ./data --namespaces user ./configs例如,把允许的服务端口维护在独立的 YAML 文件中,然后在 Rego 检查里通过import data.services引入(详见 Custom Data):
services: ports: - "20" - "20/tcp" - "23"import data.services ports := services.ports自定义数据也可以用来覆盖内置检查的默认值,例如ksv0125.trusted_registries(可信容器镜像仓库列表)与ds031.included_envs(允许的环境变量列表),只需按相同的键路径在数据文件中给出即可。
指定检查命名空间(Namespaces)
默认情况下 Trivy 只评估定义在builtin.*包中的检查。如果你的自定义检查写在其他包(例如package user.mycheck)里,就必须通过--namespaces告知 Trivy 需要评估的包前缀。该选项可重复指定多个包前缀:
trivy config --config-check ./my-check --namespaces main --namespaces user ./configs对应到源码 pkg/iac/rego/scanner.go 中,Scanner维护了一个ruleNamespaces集合,初始时克隆builtinNamespaces,随后在ScanInput遍历策略时通过getModuleNamespace(module)取出每个 Rego 模块的包名,仅当顶层包名存在于ruleNamespaces中才会执行该模块。这就是为什么没有显式指定--namespaces时自定义包下的检查不会生效。
限制 Rego 编译错误数量
Trivy 默认会容忍一定数量的 Rego 编译错误,超过阈值即终止编译并结束扫描。你可以通过--rego-error-limit调整该上限:
trivy config --rego-error-limit 20 ./configs- 当编译错误数量超过该上限时,Trivy 会终止扫描;
- 设为
--rego-error-limit 0表示严格模式,不允许任何编译错误。
该默认值定义在源码 pkg/iac/rego/scanner.go 中:
// DefaultAllowedRegoErrors defines the default number of Rego compile errors // that the scanner will tolerate. This value is set explicitly instead of // relying on OPA's ast.CompileErrorLimitDefault to avoid depending on upstream changes. const DefaultAllowedRegoErrors = 10可见默认容忍上限为 10 个编译错误,且刻意没有依赖 OPA 上游的默认常量,以避免上游变更影响 Trivy 的行为。Scanner结构体中的maxAllowedErrors字段即承载这一限制。
私有 Terraform 注册中心
Trivy 可以从私有 Terraform registry 下载模块代码。凭证只能通过TF_TOKEN_前缀的环境变量传递,目前不支持.terraformrc或terraform.rc文件。
命名规则(引自 Terraform 官方文档)如下:
- 环境变量名 =
TF_TOKEN_+ 域名,域名中的句点编码为下划线。例如变量TF_TOKEN_app_terraform_io的值会作为app.terraform.io主机的 Bearer 授权令牌; - 含非 ASCII 字符的域名必须转换为带 ACE 前缀的 punycode。例如
例えば.com的令牌必须设置在TF_TOKEN_xn--r8j3dr99h_com中; - 主机名中的连字符通常不是合法的变量名字符,可编码为双下划线。例如域名
café.fr可写作TF_TOKEN_xn--caf-dma_fr或TF_TOKEN_xn____caf__dma_fr。
如果多个变量解析到同一个主机名,Trivy 会优先选择“连字符未编码为双下划线”的那个变量名。
扫描任意 JSON 与 YAML 配置
Trivy 内置检查并不覆盖任意 JSON/YAML 配置,因此默认禁用对这两类文件的扫描。需要时,把json或yaml加入--misconfig-scanners:
trivy config --misconfig-scanners=json,yaml --config-check ./serverless.rego --check-namespaces user ./iac启用后,Trivy 会把每个文件“原样”作为输入传给 Rego 检查。下面是一个完整的可运行示例:扫描一个 Serverless Framework 的 YAML 配置,用自定义检查约束服务名必须以aws-开头。
iac/serverless.yaml:
service: serverless-rest-api-with-pynamodb frameworkVersion: ">=2.24.0" plugins: - serverless-python-requirementsserverless.rego:
# METADATA # title: Serverless Framework service name not starting with "aws-" # description: Ensure that Serverless Framework service names start with "aws-" # schemas: # - input: schema["serverless-schema"] # custom: # avd_id: AVD-SF-0001 # severity: LOW package user.serverless001 deny[res] { not startswith(input.service, "aws-") res := result.new( sprintf("Service name %q is not allowed", [input.service]), input.service ) }执行结果:
$ trivy config --misconfig-scanners=json,yaml --config-check ./serverless.rego --check-namespaces user ./iac serverless.yaml (yaml) Tests: 4 (SUCCESSES: 3, FAILURES: 1) Failures: 1 (UNKNOWN: 0, LOW: 1, MEDIUM: 0, HIGH: 0, CRITICAL: 0) LOW: Service name "serverless-rest-api-with-pynamodb" is not allowed ═════════════════════════════════════════════════════════════════════════════════════════════════════════ Ensure that Serverless Framework service names start with "aws-"通过 Schema 做类型检查
在上述示例中,检查的元数据声明了输入 schema:input: schema["serverless-schema"],这使 Trivy 能对传入的 IaC 文件做类型检查,从而在 Rego 求值前发现结构不符的问题。除了在检查元数据中声明 schema,你还可以用--config-file-schemas显式传入 schema 文件:
trivy config --misconfig-scanners=json,yaml --config-check ./serverless.rego --check-namespaces user --config-file-schemas ./serverless-schema.json ./iac几点行为说明:
- 一旦指定
--config-file-schemas,Trivy 会确保每个输入 IaC 文件都通过 schema 类型检查;如果输入文件不匹配任何传入的 schema,它将被忽略; - 如果 schema 定义在检查的元数据中,且位于
--config-check指定的目录内,则会被自动加载(详见 Input Schema),并仅用于 Rego 类型检查; - 当你暂时不想做类型检查时,不必传输入 schema——这对于“为 Trivy 尚未支持的新服务快速编写 Rego 检查并直接喂入 IaC 输入”的场景非常有用;
--config-file-schemas也支持逗号分隔的文件路径列表或一个目录作为输入;指定多个 schema 时,每个 schema 都会与所有输入文件逐一比对。
从 pkg/flag/misconf_flags.go 可以看到,该 flag 的配置项名称为misconfiguration.config-file-schemas,其用途描述正是“指定 JSON 配置 schema 路径,用于判断文件是否匹配某种配置,并把 schema 传给 Rego 检查做类型检查”。
通过内联注释忽略误配置资源
Trivy 支持对Terraform、CloudFormation、Helm 与 Dockerfile这四种配置文件,用紧邻资源定义的内联注释忽略误配置发现。这与.trivyignore(对整个扫描目录生效)不同,内联忽略只作用于单条资源定义。
忽略注释的格式为trivy:ignore:<rule>,紧跟在格式对应的行注释标记之后。忽略规则中必须包含检查元数据中存在的标识符之一:ID、long id 或别名,且均不区分大小写,例如AWS-0089、aws-0089或任意大小写组合都可以。
例如忽略 Terraform HCL 中的AVD-GCP-0051:
#trivy:ignore:AVD-GCP-0051 resource "google_container_cluster" "example" { name = var.cluster_name location = var.region }同一行可以写多条忽略规则:
#trivy:ignore:AVD-GCP-0051 trivy:ignore:AVD-GCP-0053 resource "google_container_cluster" "example" { name = var.cluster_name location = var.region }也可以使用 long id,其格式为<provider>-<service>-<short-code>。例如对下面的检查元数据:
# custom: # id: AVD-AWS-0089 # avd_id: AVD-AWS-0089 # provider: aws # service: s3 # severity: LOW # short_code: enable-logging其 long id 为aws-s3-enable-logging。
CloudFormation 示例(#trivy:ignore:*表示忽略该资源上的所有检查):
AWSTemplateFormatVersion: "2010-09-09" Resources: #trivy:ignore:* S3Bucket: Type: 'AWS::S3::Bucket' Properties: BucketName: test-bucketHelm 示例——忽略规则必须放在 YAML 对象之前,因为只有对象位置才携带忽略所需的定位数据:
serviceAccountName: "testchart.serviceAccountName" containers: # trivy:ignore:KSV018 - name: "testchart" securityContext: runAsUser: 1000 runAsGroup: 3000 image: "your-repository/your-image:your-tag" imagePullPolicy: "Always"注意:基于“缺失资源”的检查无法内联忽略
内联忽略只对与已有资源关联的检查生效。对于那些由“资源缺失”触发的检查(例如 Dockerfile 缺少USER指令触发的AVD-DS-0002),无法通过内联注释忽略,请改用 .trivyignore.yaml 文件处理。
忽略规则的过期时间
可以为忽略规则指定yyyy-mm-dd格式的过期时间,确保被忽略的问题不会被遗忘,值得在未来重新审视:
#trivy:ignore:aws-s3-enable-logging:exp:2024-03-10 resource "aws_s3_bucket" "example" { bucket = "test" }aws-s3-enable-logging这条检查会在2024-03-10之前一直被忽略,过期后重新生效。
对应到源码 pkg/iac/ignore/parse.go,expiryDateParser使用time.Parse("2006-01-02", str)解析该字段;一旦过期时间早于当前时间,规则即失效。在 pkg/iac/ignore/rule.go 中,exp段通过time.Now().Before(expiry)判断是否仍在有效期内。
按属性值忽略资源
对于使用for-each元参数批量创建的资源,你可以按属性值精确忽略某一条。注意:属性值不要加引号(即使该属性实际是字符串):
locals { ports = ["3306", "5432"] } #trivy:ignore:aws-ec2-no-public-ingress-sgr[from_port=3306] resource "aws_security_group_rule" "example" { for_each = toset(local.ports) type = "ingress" from_port = each.key to_port = each.key protocol = "TCP" cidr_blocks = ["0.0.0.0/0"] security_group_id = aws_security_group.example.id source_security_group_id = aws_security_group.example.id }aws-ec2-no-public-ingress-sgr这条检查只会对端口3306的资源实例被忽略(示例中5432仍会被报告)。若要忽略不同属性值的多个资源,可以写多条规则:
#trivy:ignore:aws-ec2-no-public-ingress-sgr[from_port=3306] #trivy:ignore:aws-ec2-no-public-ingress-sgr[from_port=5432]也可以在同一条规则中按多个属性组合忽略:
locals { rules = { first = { port = 1000 type = "ingress" }, second = { port = 1000 type = "egress" } } } #trivy:ignore:aws-ec2-no-public-ingress-sgr[from_port=1000,type=egress] resource "aws_security_group_rule" "example" { for_each = { for k, v in local.rules : k => v } type = each.value.type from_port = each.value.port to_port = each.value.port protocol = "TCP" cidr_blocks = ["0.0.0.0/0"] security_group_id = aws_security_group.example.id source_security_group_id = aws_security_group.example.id }上面的规则只会忽略type=egress且from_port=1000的那条资源。检查同样支持嵌套属性:
#trivy:ignore:*[logging_config.prefix=myprefix] resource "aws_cloudfront_distribution" "example" { logging_config { include_cookies = false bucket = "mylogs.s3.amazonaws.com" prefix = "myprefix" } }忽略模块(Module)内部的问题
第三方模块源码可能无法修改,此时无法在模块内部加忽略注释。你可以在module块上方添加忽略规则:
#trivy:ignore:aws-s3-enable-logging module "s3_bucket" { source = "terraform-aws-modules/s3-bucket/aws" bucket = "my-s3-bucket" }也可以按属性值精确忽略模块实例化的某个 bucket:
locals { bucket = ["test1", "test2"] } #trivy:ignore:*[bucket=test1] module "s3_bucket" { for_each = toset(local.bucket) source = "terraform-aws-modules/s3-bucket/aws" bucket = each.value }通配符支持
忽略规则中的id与ws(workspace)段支持通配符*:
# trivy:ignore:aws-s3-*:ws:dev-*该规则会忽略所有以aws-s3-开头的检查,且仅对匹配dev-*模式的工作区生效。
从实现层面看,pkg/iac/ignore/rule.go 中的MatchPattern会把通配符模式编译为大小写不敏感的正则表达式(*对应.*)再做匹配;pkg/iac/ignore/parse.go 则负责把trivy:ignore:...行解析为id、exp、ws等分段,其中checkIDParser会截断[之后的部分以分离属性条件。相关的解析与匹配逻辑均有对应测试覆盖,参见 pkg/iac/ignore/rule_test.go 与 pkg/iac/scanners/terraform/ignore_test.go。
小结
Trivy 的 misconfiguration 配置体系围绕“扫描什么、用什么检查、如何放行”三条主线展开:--misconfig-scanners控制扫描器子集与是否启用 JSON/YAML;--config-check、--checks-bundle-repository、--config-data与--namespaces共同构成自定义检查生态的加载与运行机制;--rego-error-limit与--config-file-schemas则分别保障了 Rego 编译的稳定性与输入的规范性。内联注释忽略规则为 Terraform、CloudFormation、Helm 与 Dockerfile 提供了粒度精确到单条资源的豁免能力,配合过期时间、属性匹配、模块级忽略与通配符,足以覆盖绝大多数误报治理场景。
相关参考资料:
- misconfiguration 配置文档
- 自定义数据 Custom Data
- 输入 Schema 文档
- 过滤与 .trivyignore.yaml
- flag 定义源码
- Rego 扫描器源码
- 忽略规则解析源码
- 忽略规则匹配源码
【免费下载链接】trivyFind vulnerabilities, misconfigurations, secrets, SBOM in containers, Kubernetes, code repositories, clouds and more项目地址: https://gitcode.com/GitHub_Trending/tr/trivy
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考