在 Kubernetes 集群内集成 Checkov:以只读 Job 方式扫描运行时资源
【免费下载链接】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 本质上是一个面向构建期的静态代码扫描工具,但 Kubernetes 集群中运行的资源与构建期的声明式描述(YAML/JSON)具有完全相同的结构,因此 Checkov 完全可以部署进集群内部,以只读权限扫描真实的运行时资源并输出违规报告。本文将基于当前仓库的 Kubernetes 集成文档 与 kubernetes/ 目录下的完整实现,讲解如何把 Checkov 以 Kubernetes Job 形式部署到集群、如何解读其 RBAC 权限模型、如何理解运行脚本的数据流,以及如何在运行时场景下跳过与 CI 语义冲突的检查项。
为什么要在集群内运行 Checkov
Checkov 的常规用法是在构建阶段对基础设施即代码(IaC)文件做静态分析:提交代码 → CI 触发扫描 → 输出违规报告。但这种方式只能覆盖“仓库里写的配置”,无法覆盖“集群里实际运行的资源”。例如:
- 运维人员通过
kubectl run临时创建的 Pod; - 通过 Helm、Kustomize 或其他工具在运行时生成的资源;
- 其他团队直接
kubectl apply进集群的配置。
Checkov 的静态扫描模型与 Kubernetes 资源模型天然兼容——集群中的 Deployment、Service、NetworkPolicy 等资源与仓库里的 YAML 文件拥有相同的apiVersion、kind、metadata、spec结构。因此可以让 Checkov 在集群内部以只读访问方式枚举并导出全部资源,再对其执行与构建期完全一致的扫描逻辑(复用 checkov/kubernetes/runner.py 中的 Kubernetes Runner),从而对集群的“实际状态”做合规审计。
这种模式的一个关键差异在于报告维度:构建期 Checkov 报告的是“不合规的文件”,而运行时没有文件概念,报告对象是集群中的资源对象(如Deployment.default.nginx)。从 kubernetes_utils.py 可以看到,Kubernetes Runner 通过get_resource_id生成{Kind}.{namespace}.{name}形式的资源标识,这正是运行时报告的组织方式。
前置条件
在集群中运行 Checkov 之前需要满足以下条件:
- Kubernetes CLI 访问权限:必须能够通过
kubectl访问目标集群(文档原话:To run Checkov in your cluster, you must have Kubernetes CLI access to the cluster)。Job 容器内部会调用kubectl枚举集群资源,容器本身不依赖外部凭据,而是通过 ServiceAccount 挂载的集群内凭据完成认证。 - 集群支持创建 Namespace、ServiceAccount、ClusterRole、ClusterRoleBinding 与 Job:清单需要相应的创建权限。
- 容器运行时能拉取镜像:默认使用
bridgecrew/checkov-k8s:latest,并设置了imagePullPolicy: Always。
部署:一条命令创建完整的只读扫描 Job
文档给出的部署命令为:
kubectl apply -f https://raw.githubusercontent.com/bridgecrewio/checkov/main/kubernetes/checkov-job.yaml在当前仓库中,该清单即 kubernetes/checkov-job.yaml。与文档中的一句话部署相比,仓库内的完整清单实际包含五个对象,各司其职:
| 对象 | 名称 | 作用 |
|---|---|---|
| Namespace | checkov | 隔离扫描任务及其配套对象 |
| ServiceAccount | checkov(namespace: checkov) | 为 Job 提供集群内身份 |
| ClusterRole | checkov-view | 只读权限集合,覆盖绝大多数资源类型,但不含 secrets |
| ClusterRoleBinding | checkov | 将 ServiceAccount 绑定到 ClusterRole |
| Job | checkov(namespace: checkov) | 执行一次性的扫描任务 |
应用后可通过以下命令查看任务状态与输出:
kubectl get jobs -n checkov kubectl logs job/checkov -n checkov权限模型:只读、最小化、不含 Secrets
checkov-viewClusterRole 的设计遵循最小权限原则,核心特征如下:
- 权限动词全部为
get、list、watch,没有任何create、update、patch、delete; - 覆盖的资源包括:ConfigMap、Endpoint、PersistentVolumeClaim、Pod、ReplicationController、ServiceAccount、Service、Deployment、DaemonSet、StatefulSet、ReplicaSet、CronJob、Job、Ingress、NetworkPolicy、PodSecurityPolicy、Role/RoleBinding/ClusterRole/ClusterRoleBinding、ResourceQuota、LimitRange、HorizontalPodAutoscaler、PodDisruptionBudget、Namespace、metrics.k8s.io 的 Pods/Nodes 等;
- 刻意排除了
secrets资源:清单注释明确写明 “View all resources EXCEPT secrets”,避免扫描器触达敏感凭据; - 通过 ClusterRoleBinding 将
checkovServiceAccount 绑定到该只读角色,Job 的 Pod 通过serviceAccountName: checkov显式使用这一身份(见 checkov-job.yaml)。
Job 的安全基线
清单中的 Job 本身也贯彻了安全加固,这与 Checkov 自身的 Kubernetes 策略(CKV_K8S 系列)理念一致:
securityContext.runAsNonRoot: true且runAsUser: 12000(与 Dockerfile 中创建的checkov系统用户 UID 12000 对应,见 kubernetes/Dockerfile);- 容器级
securityContext设置allowPrivilegeEscalation: false并drop: [ALL]全部 Linux capabilities; - Pod 级
seccompProfile.type: RuntimeDefault; restartPolicy: Never,保证 Job 失败后不会无限重启污染日志;- 资源配额
requests/limits均为内存 256Mi、CPU 500m,防止扫描失控占用集群资源。
关于跳过注释的说明
清单的 Job 与 Pod 模板注解中声明了四个checkov.io/skip*跳过项,这是“用 Checkov 扫描 Checkov 自身”时产生的豁免,值得逐个理解(对应实现位于 checkov/kubernetes/checks/resource/k8s/):
CKV_K8S_22=Checkov requires filesystem write access to dump resource definitions:该检查对应 ReadOnlyFilesystem.py,要求容器只读文件系统。而扫描器需要把导出的资源定义写入/data目录,因此豁免;CKV_K8S_38=Service Account is required for read-only API access:该检查对应 ServiceAccountTokens.py,要求关闭automountServiceAccountToken。但本 Job 恰恰需要 ServiceAccount 令牌来完成只读 API 访问,因此豁免;CKV_K8S_14=Preferring latest rules every run - image pull always:对应 ImageTagFixed.py,该检查要求镜像 tag 固定、不得使用latest。而镜像bridgecrew/checkov-k8s:latest配合imagePullPolicy: Always是为了每次运行都拉取最新规则,属于有意为之;CKV_K8S_43=Preferring latest rules every run - image pull always:对应 ImageDigest.py,同样是对“镜像未使用 digest 固定版本”的豁免。
从源码看,注解形式的跳过机制在 kubernetes_utils.py 的get_skipped_checks中实现:它遍历资源metadata.annotations,识别以checkov.io/skip、bridgecrew.io/skip、cortex.io/skip开头的注解键,解析检查ID=原因格式并返回为跳过项列表。这意味着你在集群中扫描到的任何资源,也可以就地添加同样的注解来声明豁免原因。
运行原理:从集群枚举到静态扫描
文档只给出了部署与查看日志的命令,但其背后是一条完整的“导出 → 落盘 → 扫描 → 上报”流水线,由 kubernetes/run_checkov.sh 承载,该脚本也是镜像 kubernetes/Dockerfile 的 ENTRYPOINT。
第一步:枚举并导出资源
脚本内置一个资源类型列表,涵盖 ClusterRole、ClusterRoleBinding、ConfigMap、CronJob、DaemonSet、Deployment、Endpoint、HPA、Ingress、Job、LimitRange、NetworkPolicy、PodDisruptionBudget、Pod、PodSecurityPolicy、ReplicaSet、ReplicationController、ResourceQuota、Role、RoleBinding、ServiceAccount、Service、StatefulSet 等 23 类资源,随后循环执行:
kubectl get $resource --all-namespaces -oyaml | yq eval 'del(.items[] | select(.metadata.ownerReferences)) ' - > /data/runtime.${resource}.yaml其中两个细节值得注意:
--all-namespaces:枚举全集群资源而非单个命名空间;del(.items[] | select(.metadata.ownerReferences)):借助 yq 删除带有ownerReferences的子资源(例如 Deployment 自动衍生的 ReplicaSet、ReplicaSet 衍生的 Pod),避免重复扫描由上层控制器管理的对象。
导出的 YAML 统一写入/data目录,这也是 Job 注解中声明“需要文件系统写权限”的原因。
第二步:执行 Checkov 扫描
导出完成后,脚本根据是否存在 API Key 选择两种模式:
模式一:本地扫描(无 API Key)
checkov -s -d /data --framework kubernetes "$@"参数含义:
-s:soft-fail 软失败模式,扫描发现的违规不会导致进程以非零退出码结束,适合只读审计场景;-d /data:扫描目录指向导出的资源文件;--framework kubernetes:仅启用 Kubernetes 框架,避免对导出的 YAML 做其他框架的误判;"$@":透传用户在命令中附加的任意 Checkov 参数(例如--skip-check、--compact等)。
模式二:平台上报(存在 API Key)
checkov -s -d /data --bc-api-key "$apikey" --repo-id "$repoid" --branch runtime --framework kubernetes "$@"当挂载了/etc/checkov/apikey与可选的/etc/checkov/repoid(可通过 Secret 卷挂载实现)时,会将扫描结果上报到 Bridgecrew/Checkov 平台,--repo-id缺省为runtime/unknown,--branch固定为runtime,用于在平台上区分“运行时扫描”与“构建期扫描”。
第三步:镜像内容
kubernetes/Dockerfile 揭示了运行环境的关键构成:
- 基础镜像
python:3.11-slim,通过 kubernetes/requirements.txt 安装固定版本checkov==3.3.14(锁版本保证了行为可复现); - 安装
kubectl客户端(从官方 release 通道下载 stable 版本); - 安装
yq(v4.16.2)用于 YAML 处理; - 创建 UID 12000 的非 root 用户
checkov,并设置/data、/app、/home/checkov的属主,配合清单中的runAsUser: 12000以非 root 身份运行。
与构建期扫描的关系:同一套引擎
运行时扫描并没有引入新的检测逻辑,而是复用构建期的 Kubernetes Runner。从 checkov/kubernetes/runner.py 的源码结构看:
- Runner 的
check_type = CheckType.KUBERNETES,与 CLI 中--framework kubernetes对应; - 扫描前会构建 Kubernetes 局部图(
KubernetesLocalGraph,见 runner 中build_graph_from_definitions的调用),支持跨资源的图查询类检查; check_definitions对每个文件中的每个实体调用注册表扫描,并通过get_skipped_checks消费注解形式的跳过项;- 扫描结果以
Record形式写入Report,资源标识采用{Kind}.{namespace}.{name}格式,例如Deployment.default.checkov; - 同时支持镜像引用检测(
KubernetesImageReferencerManager),可以对资源中引用的容器镜像做额外检查。
文件类型支持方面,kubernetes_utils.py 定义了K8_POSSIBLE_ENDINGS = {".yaml", ".yml", ".json"},同时排除package.json/package-lock.json,避免把 Node 项目文件误当 Kubernetes 资源。
实战要点与常见问题
1. 查看扫描结果
kubectl get jobs -n checkov kubectl logs job/checkov -n checkovkubectl get jobs用于确认 Job 是否进入Complete状态;kubectl logs job/checkov输出 Checkov 的完整报告(PASSED/FAILED/SKIPPED 列表与汇总统计)。Job 的restartPolicy: Never意味着一次运行结束即终止,日志会保留供复查。
2. 追加自定义参数
由于脚本会透传"$@",你可以直接在容器命令中追加参数,例如:
kubectl create job checkov-custom --from=cronjob/checkov -- \ --skip-check CKV_K8S_20 --compact或在本地基于镜像手动执行:docker run --rm bridgecrew/checkov-k8s:latest --compact。
3. 接入平台上报
将 API Key 以 Secret 形式挂载到/etc/checkov/apikey(可选/etc/checkov/repoid),脚本会自动切换到平台上报模式:
kubectl create secret generic checkov-api \ --namespace checkov \ --from-file=apikey=./apikey \ --from-file=repoid=./repoid4. 理解资源标识与报告差异
运行时报告的resource字段是Deployment.default.nginx这类“集群坐标”而非文件路径,这是运行时模式与构建期模式最大的感官差异——同一份违规,构建期指向nginx.yaml第 N 行,运行时指向集群里具体的资源对象。
5. 权限边界确认
若你的集群启用了额外的 CRD 或需要扫描 Secret,默认的checkov-viewClusterRole 并不包含它们。此时需要在 kubernetes/checkov-job.yaml 的rules中按需补充apiGroups/resources/verbs。请务必权衡:加入secrets的list/get权限意味着扫描器可以触达集群全部敏感凭据,需谨慎评估合规与安全风险。
总结
Checkov 的 Kubernetes 集成提供了一种“构建期扫描 + 运行时审计”的双轨合规方案:构建期守住 IaC 仓库的入口质量,运行时则通过 kubernetes/checkov-job.yaml 部署的只读 Job 持续校验集群的实际状态。整个方案建立在“Kubernetes 资源即代码”这一核心事实上——run_checkov.sh 负责把运行时资源还原成 Checkov 熟悉的 YAML 形态,checkov/kubernetes/runner.py 则复用与构建期完全一致的检测引擎,从而保证两套环境下策略语义一致、报告口径统一。对于需要在生产集群中建立持续合规基线、又不想引入集群内常驻 Agent 的团队而言,这是一个低侵入、可审计、随取随用的务实选择。
【免费下载链接】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),仅供参考