使用 Checkov 扫描 Terraform 第三方模块与私有模块
2026/9/16 18:53:05 网站建设 项目流程

使用 Checkov 扫描 Terraform 第三方模块与私有模块

【免费下载链接】checkovPrevent cloud misconfigurations and find vulnerabilities during build-time in infrastructure as code, container images and open source packages with Checkov by Bridgecrew.项目地址: https://gitcode.com/GitHub_Trending/ch/checkov

Checkov 在扫描 Terraform 配置时,默认只覆盖当前目录下直接定义的资源;而生产环境大量使用第三方模块(如官方 AWS EKS 模块)将资源抽象在模块内部,导致常规扫描出现覆盖盲区。本文以 docs/7.Scan Examples/Terraform.md 为核心,结合 checkov/terraform/module_loading 目录下的加载器源码,完整讲解如何通过--download-external-modules让 Checkov 下载并扫描外部模块、如何调整下载路径、如何使用 Terraform 已下载的模块(实验特性),以及如何为私有仓库、私有 Terraform Registry 和自建 VCS 配置认证凭据,最终实现对第三方与私有 Terraform 模块的全面策略覆盖。

一、问题背景:为什么第三方模块会逃过常规扫描

第三方 Terraform 模块的价值在于把由多个对象组成的复杂服务封装成少量配置。以官方 AWS EKS 模块为例,原本需要大量资源配置的集群,在配置文件中只需几行module声明:

module "eks" { source = "terraform-aws-modules/eks/aws" cluster_name = "my-cluster" cluster_version = "1.24" subnets = ["subnet-abcde012", "subnet-bcde012a", "subnet-fghi345a"] vpc_id = "vpc-1234556abcdef" worker_groups = [ { instance_type = "m4.large" asg_max_size = 5 } ] }

这种封装带来的副作用是:模块内部的 Terraform 配置被“抽象”掉了,常规的checkov -d .只能看到module块本身,无法触及模块内部定义的资源(如 EKS 节点组的 IAM 角色、安全组、自动扩缩组等),从而漏掉这些资源上的安全策略检查。

从源码结构看,这一覆盖盲区的根因在于 Checkov 的模块加载机制:ModuleLoaderRegistry(见 checkov/terraform/module_loading/registry.py)在load()时会对每个 loader 判断if not self.download_external_modules and loader.is_external: continue,即默认download_external_modules=False时会直接跳过所有外部加载器(loader.is_external = True,见 checkov/terraform/module_loading/loader.py)。因此只有显式开启外部模块下载,模块内部的资源才会被拉取并纳入扫描图。

二、启用外部模块下载:--download-external-modules

要让 Checkov 下载配置文件中引用的外部模块,在扫描时增加--download-external-modules true

checkov -d . --download-external-modules true

该参数对应的 CLI 定义位于 checkov/common/util/ext_argument_parser.py:

  • 帮助文本为“download external terraform modules from public git repositories and terraform registry”,即支持从公开 Git 仓库与 Terraform Registry 下载模块;
  • 默认值为None
  • 同时支持通过环境变量DOWNLOAD_EXTERNAL_MODULES传入。

执行后,Checkov 会将配置文件中引用的外部模块下载到当前目录下的.external_modules文件夹(默认目录常量DEFAULT_EXTERNAL_MODULES_DIR = ".external_modules",定义于 checkov/common/util/consts.py),随后对这些模块内部的资源执行与本地资源相同的策略检查。

下载路径的确定方式

从 registry.py 的源码可以看到,下载目标路径由root_dir + external_modules_folder_name + source拼接而成:

  • 在 Windows 上,由于路径命名字符限制,会改用模块source的 MD5 哈希值作为目录名;
  • 在 Linux/macOS 上,直接使用模块 source(如terraform-aws-modules/eks/aws)作为子目录名。

而 Registry 类模块(例如terraform-aws-modules/eks/aws)的下载路径还包含 host 名与版本号:external_modules_folder_name / tf_host_name / module_source / best_version(见 loaders/registry_loader.py),从而保证不同来源、不同版本的模块可以并存。

三、自定义外部模块下载路径

如果默认的.external_modules目录不符合项目约定,可通过--external-modules-download-path指定其他路径:

checkov -d . --download-external-modules true --external-modules-download-path example/path

该参数定义于 checkov/common/util/ext_argument_parser.py,默认值即DEFAULT_EXTERNAL_MODULES_DIR,并支持环境变量EXTERNAL_MODULES_DIR覆盖。对应的运行时读取逻辑在 checkov/common/util/env_vars_config.py:EXTERNAL_MODULES_DIR = os.getenv("EXTERNAL_MODULES_DIR", DEFAULT_EXTERNAL_MODULES_DIR)

也就是说,除了命令行参数,你也可以通过环境变量统一配置:

export EXTERNAL_MODULES_DIR=example/path checkov -d . --download-external-modules true

四、实验特性:直接复用 Terraform 已下载的模块

对于已经在本地执行过terraform init的项目,.terraform目录中已包含模块源码。此时不必让 Checkov 重复下载,可以通过实验性环境变量启用对 Terraform 托管模块的复用:

CHECKOV_EXPERIMENTAL_TERRAFORM_MANAGED_MODULES=True checkov -d .

使用该模式时需要注意以下前提与限制(原文档明确说明,可与源码互相印证):

  • 该特性目前标记为Experimental(实验性),行为可能随版本演进发生变化;
  • 仅适用于对根目录的扫描,且该目录必须已执行过terraform init
  • 启用后 Checkov 不会重新下载外部模块,而是直接读取.terraform中 Terraform 已经拉取好的模块内容。

该环境变量的解析位于 checkov/common/util/env_vars_config.py:CHECKOV_EXPERIMENTAL_TERRAFORM_MANAGED_MODULES = convert_str_to_bool(os.getenv('CHECKOV_EXPERIMENTAL_TERRAFORM_MANAGED_MODULES', False)),默认关闭。在 registry.py 的load()中,开启该开关后,当模块版本为latest时会优先从module_latest缓存中查找对应版本的模块内容,从而避免向 Registry 发起版本查询与下载请求。

五、扫描私有 Terraform 模块:环境变量认证体系

如果模块存放在私有仓库或私有 Terraform Registry(Terraform Cloud、Terraform Enterprise,或 GitLab 等第三方托管平台),Checkov 可通过环境变量中的访问令牌尝试克隆并扫描这些模块。下表完整列出支持的凭据变量:

变量名说明
GITHUB_PAT具备私有仓库读取权限的 GitHub personal access token
BITBUCKET_TOKEN具备私有仓库读取权限的 Bitbucket personal access token
TF_HOST_NAMETerraform Registry 主机名(默认app.terraform.io)。例如:gitlab.com/example.com
TFC_TOKEN*(已弃用,请改用TF_REGISTRY_TOKEN)可访问私有 Registry 的 Terraform Cloud token
TF_REGISTRY_TOKEN私有 Registry 访问令牌(支持 Terraform Cloud / Enterprise 及第三方 Registry)
BITBUCKET_USERNAMEBitbucket 用户名(只能与BITBUCKET_APP_PASSWORD配合使用)
BITBUCKET_APP_PASSWORDBitbucket app password(只能与BITBUCKET_USERNAME配合使用)

这些环境变量的实际消费位置与源码一一对应,便于排查问题:

  • TF_HOST_NAMETF_REGISTRY_TOKEN:由 loaders/registry_loader.py 的discover()读取,其中TF_HOST_NAME默认取TFC_HOST_NAME(即app.terraform.io)。若同时设置了已弃用的TFC_TOKEN,源码会打印弃用警告并将其值覆盖给module_params.token
  • GITHUB_PAT:由 loaders/github_access_token_loader.py 读取,并将其转换为git::https://x-access-token:<token>@github.com/org/repo形式,通过 HTTP 基本认证克隆仓库;同时 loaders/git_loader.py 在普通 Git 加载器因“could not read Username for”失败时,会判断是否设置了GITHUB_PAT并转入 token 加载流程。
  • BITBUCKET_TOKEN/BITBUCKET_USERNAME/BITBUCKET_APP_PASSWORD:由 loaders/bitbucket_access_token_loader.py 读取;设置了BITBUCKET_TOKEN时用户名固定为x-token-auth,否则使用BITBUCKET_USERNAME+BITBUCKET_APP_PASSWORD组合。

自建(self-hosted)VCS 仓库的认证变量

如果模块托管在自建 VCS 上,还需配置以下三个环境变量:

变量名说明
VCS_BASE_URL自建 VCS 的基础 URL,例如https://example.com
VCS_USERNAME基本认证使用的用户名
VCS_TOKEN基本认证使用的密码

对应读取逻辑位于 loaders/git_loader.py 的discover():设置VCS_BASE_URL后,模块 source 前缀会变成git::https://example.com;当同时提供VCS_USERNAMEVCS_TOKEN时,在_is_matching_loader()(见 loaders/git_loader.py)中会把认证信息嵌入模块 URL,形如git::https://<username>:<token>@example.com/org/repo

常用场景配置示例

  • Terraform Cloud Registry 私有模块扫描(TF_HOST_NAME缺省即app.terraform.io):
# TF_HOST_NAME will default to app.terraform.io export TF_REGISTRY_TOKEN=xxxxxx checkov -d . --download-external-modules true
  • Terraform Enterprise Registry 私有模块扫描:
export TF_HOST_NAME=tfe.example.com export TF_REGISTRY_TOKEN=xxxxxx checkov -d . --download-external-modules true
  • GitLab 公共 Registry 模块扫描:
export TF_HOST_NAME=gitlab.com checkov -d . --download-external-modules true
  • GitLab 自建 Registry 私有模块扫描(需要 read_api 权限的 job token 或个人访问令牌):
# A job token or a personal access token with the read_api scope is required export TF_HOST_NAME=gitlab.example.com export TF_REGISTRY_TOKEN=xxxxxx checkov -d . --download-external-modules true

六、模块加载器机制与下载流程

了解加载器的分工,有助于理解为何不同的模块 source 需要不同的凭据配置。Checkov 的模块加载采用“注册表 + 多个加载器”的架构:

  • ModuleLoaderRegistry(checkov/terraform/module_loading/registry.py)维护加载器列表loaders与模块内容缓存module_content_cache,在load()中依次尝试每个加载器,直到某个加载器成功返回模块内容或给出下一个待解析 URL;重复模块通过缓存避免重复下载。
  • 抽象基类ModuleLoader(checkov/terraform/module_loading/loader.py)定义discover()(从环境变量发现凭据)、_is_matching_loader()(判断能否处理该 source 类型)、_load_module()(实际下载)与_find_module_path()(查找已存在路径);所有加载器实例在构造时自动注册进全局module_loader_registry

具体加载器与其负责的 source 类型对应如下(均位于 checkov/terraform/module_loading/loaders):

加载器文件匹配的模块 source 类型
registry_loader.pyTerraform Registry 模块(如terraform-aws-modules/eks/aws),支持 Registry API 版本查询、X-Terraform-Get重定向下载、//子模块内层模块解析与归档(zip/tgz 等)解压
github_loader.pygithub.com/org/repogit@github.com:...git::git@github.com:...等 GitHub source
github_access_token_loader.py设置GITHUB_PAT后,将 GitHub SSH/HTTP source 转为 token 认证形式
bitbucket_loader.pybitbucket.org/...公开仓库
bitbucket_access_token_loader.py设置BITBUCKET_TOKEN或用户名 + app password 后的 Bitbucket 私有仓库
git_loader.pygit::通用 Git source,并支持自建 VCS 的VCS_BASE_URL/VCS_USERNAME/VCS_TOKEN
local_path_loader.py本地路径引用的模块(无需下载)

从加载流程看,registry.py 中的if not self.download_external_modules and loader.is_external: continue是全局开关:只有开启--download-external-modules,上述外部加载器才会被尝试。因此,无论扫描公有还是私有模块,第一步都是先带上该参数。

七、扫描效果验证与使用建议

  • 验证覆盖范围:开启下载后,检查.external_modules(或自定义路径)目录中是否生成了对应模块的源码目录,即可确认下载是否成功;模块内部的资源随后会出现在 Checkov 的扫描报告中。
  • 版本锁定与缓存:Registry 加载器会对每个模块源查询可用版本并按语义化版本约束选择最优版本(见 loaders/registry_loader.py),版本列表会被缓存(modules_versions_cache),因此同一项目重复扫描不会反复触发网络请求。
  • 凭据最小化:私有模块仅需授予“可读”权限的令牌;GitLab 自建 Registry 场景按官方要求使用带read_apiscope 的令牌。
  • 与 CI/CD 集成:上述环境变量与 CLI 参数均可直接放入 CI 任务(如 GitHub Actions、GitLab CI、Jenkins)的步骤中;也可通过DOWNLOAD_EXTERNAL_MODULESEXTERNAL_MODULES_DIR等环境变量统一管理配置。

八、小结

要让 Checkov 的 Terraform 扫描真正覆盖到第三方与私有模块,核心动作有三步:一是通过--download-external-modules true显式开启外部模块下载;二是按模块来源配置对应的认证环境变量(TF_REGISTRY_TOKENGITHUB_PATBITBUCKET_TOKENVCS_*等);三是对自建 Registry 额外指定TF_HOST_NAME。在此基础上,还可通过--external-modules-download-path定制下载目录,或利用实验性的CHECKOV_EXPERIMENTAL_TERRAFORM_MANAGED_MODULES复用terraform init已下载的模块。这些行为均可在 checkov/terraform/module_loading 的加载器源码与 checkov/common/util/ext_argument_parser.py 的参数定义中得到印证,相关示例与测试可进一步参考 tests/terraform/module_loading 目录下的用例。

【免费下载链接】checkovPrevent cloud misconfigurations and find vulnerabilities during build-time in infrastructure as code, container images and open source packages with Checkov by Bridgecrew.项目地址: https://gitcode.com/GitHub_Trending/ch/checkov

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询