R055LE/container-hardening-lab

GitHub: R055LE/container-hardening-lab

一个符合 CIS Benchmark 和 Iron Bank 标准的生产级容器加固实验室,集成了策略即代码、漏洞扫描、镜像签名、SBOM 生成与运行时检测的完整安全流水线。

Stars: 0 | Forks: 0

# 容器加固实验室 [![容器安全流水线](https://static.pigsec.cn/wp-content/uploads/repos/cas/77/778587f807914d9d4cf32dd1442b9f63581a3f7d02058c16cae31280d51a8a6c.svg)](https://github.com/R055LE/container-hardening-lab/actions/workflows/container-security.yml) 一个展示生产级容器加固、漏洞扫描和策略即代码执行的作品集项目 —— 符合 [CIS Docker Benchmark](https://www.cisecurity.org/benchmark/docker) 和 [DoD Iron Bank](https://ironbank.dso.mil/) 实践。 ## 本项目展示了什么 本实验室解决了生产环境中最常见的容器安全故障: - **容器以 root 身份运行** — 本仓库中的每个镜像都使用专用的非 root 用户 (UID 10001) - **臃肿的攻击面** — 多阶段构建剥离了构建工具;明确移除了 `wget`、`curl`、`perl` 和 SUID/SGID 二进制文件;Go 镜像使用 distroless(无 shell、无包管理器、无 libc) - **未固定或不受信任的基础镜像** — OPA 白名单强制执行批准的注册表,并对未固定的摘要发出警告 - **无准入控制** — Kyverno ClusterPolicies 在部署时阻止特权 pod、主机命名空间共享以及缺失的能力降级 - **无证据追踪** — 每个镜像都附带 CycloneDX + SPDX SBOM 和 Trivy CVE 报告;检查结果会作为 CI 构建的门槛 - **未签名的镜像** — 推送到 ghcr.io 的每个镜像都使用 Cosign 签名(通过 Sigstore 进行无密钥签名);Kyverno `verifyImages` 策略会在准入时拒绝未签名的镜像 - **无运行时可见性** — Falco 自定义规则检测加固容器内部的后渗透行为(生成 shell、执行包管理器、出站 C2 连接) ## 仓库结构 ``` . ├── images/ │ ├── python/ # python:3.12-slim — reference hardened image │ ├── node/ # node:20-slim — Express API │ ├── nginx/ # nginx:1.27-alpine — static file server │ └── go/ # distroless — statically compiled Go binary │ ├── policies/ │ ├── opa/ # Rego policies evaluated by Conftest against Dockerfiles │ │ ├── no-root.rego │ │ ├── no-privileged.rego │ │ └── image-source-allowlist.rego │ └── kyverno/ # Kubernetes admission policies │ ├── no-root.yaml │ ├── no-privileged.yaml │ └── image-source-allowlist.yaml │ ├── tests/ │ ├── opa/ # OPA unit tests (opa test) │ ├── kyverno/ # Kyverno CLI policy tests + fixture Pods │ └── structure/ # Container structure tests (runtime assertions) │ ├── examples/ │ └── unhardened/ # Deliberately insecure Dockerfile — failure demo │ ├── falco/ │ ├── rules/ # Custom Falco runtime detection rules │ └── docker-compose.yml # Local Falco demo setup │ ├── .github/workflows/container-security.yml # Full CI pipeline └── Makefile # Primary task interface ``` ## 加固控制措施 所有镜像均应用以下控制措施,并映射到 CIS Docker Benchmark 部分: | CIS 控制 | 功能描述 | 实现方式 | |---|---|---| | **4.1** 非 root 用户 | 防止容器被入侵后的权限提升 | 专用 `appuser`/`nginx` (UID 10001/101);在 `CMD` 之前设置 `USER` | | **4.2** 受信任的基础镜像 | 防止通过恶意基础镜像导致的供应链入侵 | OPA 白名单策略;仅允许官方 Docker Hub、GCR Distroless、Chainguard、Iron Bank 和 ECR | | **4.4** 多阶段构建 | 从最终镜像中剥离构建工具 | 构建器阶段安装依赖项;最终阶段仅复制构建产物 | | **4.7** 移除不必要的包 | 减少攻击面 | 移除 `wget`、`curl`、`perl`、`gcc`、`binutils`;通过二进制路径移除 BusyBox applets | | **4.8** 无 SUID/SGID 位 | 防止通过 setuid 二进制文件进行权限提升 | 在构建时运行 `find / -xdev -perm /4000 -o -perm /2000 -exec chmod ug-s` | | **4.9** 镜像中无机密信息 | 防止通过镜像检查导致凭据泄露 | 不包含带有凭据的 `ENV`;仅限运行时注入的机密信息 | | **5.2/5.3** 无主机命名空间 | 防止通过主机 PID/IPC/网络进行容器逃逸 | Kyverno 策略阻止 `hostPID`、`hostIPC` 和 `hostNetwork: true` | | **5.4** 无特权容器 | 防止完全访问主机 | Kyverno 策略阻止 `privileged: true`,要求 `allowPrivilegeEscalation: false`,要求 `capabilities.drop: ALL` | | **5.7** 非特权端口 | 避免需要 `CAP_NET_BIND_SERVICE` | 所有镜像暴露端口 ≥ 1024 (8000, 3000, 8080) | ## 测试层 测试套件包含四个独立的层,每层捕获不同类型的故障: ### 1. OPA 单元测试 — 策略逻辑 使用 `opa test` 测试 Rego 策略规则本身,无需 Docker。提供对策略正确性的快速反馈。 ``` make test-opa ``` 涵盖三个策略的 47 项测试: | 策略 | 测试数 | 验证内容 | |---|---|---| | `no-root.rego` | 13 | 检测缺失 `USER`、`USER root`、`USER 0`、`USER 0:group` | | `no-privileged.rego` | 14 | 检测 `RUN --privileged`,对低于 1024 的端口和 `--chown=root` 发出警告 | | `image-source-allowlist.rego` | 20 | 批准/拒绝注册表,对未固定的摘要发出警告,覆盖多阶段场景 | ### 2. Kyverno 策略测试 — 准入控制 使用 `kyverno test` 针对 fixture Pod 清单测试 Kyverno `ClusterPolicy` 规则。无需集群。 ``` make test-kyverno ``` 涵盖每条规则通过和失败案例的 13 项测试: | 测试 | Fixture | 预期结果 | |---|---|---| | 要求非 root 用户 | `pod-fail-runasroot.yaml` | 拒绝 | | 阻止 `runAsNonRoot: false` | `pod-fail-runasnonroot-false.yaml` | 拒绝 | | 阻止 `allowPrivilegeEscalation` | `pod-fail-privilege-escalation.yaml` | 拒绝 | | 阻止 `privileged: true` | `pod-fail-privileged.yaml` | 拒绝 | | 要求 `capabilities.drop: ALL` | `pod-fail-no-caps-drop.yaml` | 拒绝 | | 阻止 `hostPID/hostIPC/hostNetwork` | 3 个 fixture 文件 | 拒绝 | | 完全加固的 pod | `pod-pass-hardened.yaml` | 通过 | ### 3. Falco 规则验证 — 运行时检测规则 验证自定义 Falco 规则能否无错误加载 —— 语法、宏/列表解析以及字段引用都会被检查。使用 Falco 容器,因此不需要内核访问权限。 ``` make test-falco ``` 针对 Falco 的规则引擎,验证 `falco/rules/container-hardening-lab.yaml` 中的所有 5 条自定义规则。捕获 YAML 解析错误、无效的条件语法、未定义的宏/列表以及无法识别的字段名称。 ### 4. 容器结构测试 — 运行时断言 使用 `container-structure-test` 在运行时测试实际构建的镜像。这些测试捕获仅在镜像构建后才会出现的回归 —— 例如,包管理器静默地重新添加 SUID 二进制文件。 ``` make test-structure IMAGE=python # or node, nginx, go ``` 涵盖四个镜像的 53 项测试: | 镜像 | 测试数 | 检查内容 | |---|---|---| | `hardened-python` | 14 | UID 10001,无 SUID/SGID,无 wget/curl/perl/gcc,`/app` 工作目录,nologin shell,OCI 标签 | | `hardened-node` | 14 | UID 10001,无 SUID/SGID,无 wget/curl/perl,Express 可导入,`src/index.js` 存在,OCI 标签 | | `hardened-nginx` | 13 | UID 101,无 SUID/SGID,无 wget/curl,`server_tokens off`,端口 8080,安全标头,OCI 标签 | | `hardened-go` | 12 | UID 65532,无 shell/bash,无 wget/curl/apt/apk/gcc/go,存在 CA 证书,OCI 标签 (distroless) | ## 故障演示 `examples/unhardened/Dockerfile` 是故意设计为不安全的。CI 流水线断言 OPA linter 和 Trivy 扫描器**必须**对其进行标记 —— 干净的结果将意味着工具未正常工作。 Conftest 策略捕获的违规项: ``` FAIL - examples/unhardened/Dockerfile - docker.security - CIS 4.1: No USER instruction found. WARN - examples/unhardened/Dockerfile - docker.security - CIS 5.7: EXPOSE 80 uses a privileged port. WARN - examples/unhardened/Dockerfile - docker.security - Files COPY'd with --chown=root will not be writable by the app user. WARN - examples/unhardened/Dockerfile - docker.security - Image 'node:18' is not pinned to a digest. ``` Trivy 单独将 `node:18` 标记为带有 CRITICAL/HIGH CVE(该镜像有意固定为一个旧的、存在漏洞的版本)。 负向结构测试(`tests/structure/unhardened.yaml`)随后构建该镜像,并断言它**具有**加固镜像所消除的问题 —— 以 root 身份 (UID 0) 运行、存在 SUID 二进制文件、安装了 wget/curl/perl/apt-get。这使得前后的对比具体且可测试。 ## 前置条件 | 工具 | 版本 | 安装方式 | |---|---|---| | Docker | ≥ 24 | [docs.docker.com](https://docs.docker.com/get-docker/) | | Trivy | ≥ 0.69 | [aquasecurity.github.io/trivy](https://aquasecurity.github.io/trivy/latest/getting-started/installation/) | | Syft | ≥ 1.0 | [github.com/anchore/syft](https://github.com/anchore/syft#installation) | | Conftest | ≥ 0.57 | [conftest.dev](https://www.conftest.dev/install/) | | OPA | ≥ 0.70 | [openpolicyagent.org](https://www.openpolicyagent.org/docs/latest/#1-download-opa) | | Kyverno CLI | ≥ 1.17 | [kyverno.io/docs/kyverno-cli](https://kyverno.io/docs/kyverno-cli/) | | container-structure-test | ≥ 1.19 | [github.com/GoogleContainerTools/container-structure-test](https://github.com/GoogleContainerTools/container-structure-test#installation) | ## 快速开始 ``` # 仅运行 policy 测试 — 无需 Docker,快速反馈 make test # 运行所有测试,包括 Falco rule 验证(需要 Docker) make test-all # 构建、扫描并为所有镜像生成 SBOMs make all # 运行 container structure 测试(必须先构建镜像) make test-structure IMAGE=python make test-structure IMAGE=node make test-structure IMAGE=nginx make test-structure IMAGE=go # 单个镜像的独立 targets make build IMAGE=python make scan IMAGE=python make sbom IMAGE=python make lint IMAGE=python ``` 扫描报告和 SBOM 会写入 `reports//`: ``` reports/python/ ├── trivy.json # CVE scan results (JSON) ├── sbom.cyclonedx.json # Software Bill of Materials (CycloneDX) └── sbom.spdx.json # Software Bill of Materials (SPDX) ``` ## CI 流水线 GitHub Actions 工作流 (`.github/workflows/container-security.yml`) 会在每次推送和拉取请求时运行三个作业: ``` flowchart TD trigger([push / pull_request]):::event --> pt pt["**policy-tests**\nOPA unit tests — 47\nKyverno policy tests — 13\nFalco rule validation — 5 rules"]:::job pt --> fd pt --> ip subgraph fd [" failure-demo "] direction TB f1["Conftest must reject\nunhardened Dockerfile"]:::check f2["Trivy must find CVEs\nin node:18"]:::check end subgraph ip [" image-pipeline — python · node · nginx · go (parallel) "] direction TB i1["Lint Dockerfile\nConftest / OPA"]:::step --> i2 i2["Build image"]:::step --> i3 i3["Trivy scan\ngate: CRITICAL / HIGH = fail"]:::gate --> i4 i3 --> i5 i4["SARIF → GitHub\nSecurity tab"]:::output i5["Generate SBOM\nSyft — CycloneDX + SPDX"]:::step --> i6 i6["Container structure tests\n41 assertions"]:::step --> i7 i6 --> i8 i7[("Reports artifact\n30-day retention")]:::output i8["Push → ghcr.io\nCosign sign (keyless)"]:::sign end classDef event fill:#6366f1,stroke:#4f46e5,color:#fff classDef job fill:#0ea5e9,stroke:#0284c7,color:#fff classDef step fill:#10b981,stroke:#059669,color:#fff classDef gate fill:#f59e0b,stroke:#d97706,color:#fff classDef check fill:#ec4899,stroke:#db2777,color:#fff classDef output fill:#64748b,stroke:#475569,color:#fff classDef sign fill:#8b5cf6,stroke:#7c3aed,color:#fff ``` **`policy-tests`** 最先运行 —— 为每次推送提供快速反馈。OPA 和 Kyverno 测试不需要 Docker;Falco 验证使用 Falco 容器镜像来验证规则语法和字段引用。 **`failure-demo`** 断言未加固的 Dockerfile 和 `node:18` 基础镜像被正确标记。如果此处出现干净的结果,则作业失败,从而证明工具处于活动状态。 **`image-pipeline`** 在所有三个镜像上并行运行。Trivy 的扫描结果作为 SARIF 上传到 GitHub Security 标签页以进行分类处理。所有报告都将作为构建产物归档 30 天。 ## 镜像签名 CI 流水线推送到 `ghcr.io` 的每个镜像都使用 [Cosign](https://github.com/sigstore/cosign) 并通过 [Sigstore](https://sigstore.dev/) 进行无密钥签名。任何地方都不存储私钥 —— 签名与工作流的 GitHub Actions OIDC 身份绑定。 验证已签名的镜像(无需密钥): ``` cosign verify \ --certificate-identity-regexp \ "https://github.com/R055LE/container-hardening-lab/.github/workflows/container-security.yml@refs/heads/main" \ --certificate-oidc-issuer "https://token.actions.githubusercontent.com" \ ghcr.io/r055le/container-hardening-lab-python:latest ``` 成功验证确认该镜像是由此 CI 工作流从 `main` 分支构建并推送的 —— 而不是手动推送或来自被入侵的流水线。`policies/kyverno/verify-signatures.yaml` ClusterPolicy 在准入时强制执行此操作,拒绝任何引用来自此注册表且未签名镜像的 Pod。 ## 运行时安全 `falco/` 使用 [Falco](https://falco.org/)(CNCF 毕业项目)添加了一个运行时检测层。在构建时和部署时的控制措施减小攻击面的情况下,Falco 能够检测容器运行后发生的利用尝试。 五条自定义规则涵盖了后渗透的攻击链路: | 规则 | 捕获内容 | |---|---| | 生成 Shell | 在加固容器内启动的交互式 shell | | 包管理器 | 使用 `apt`、`pip`、`npm`、`apk` 安装攻击工具 | | 读取敏感文件 | 打开了 `/etc/shadow`、SSH 密钥、sudoers 文件 | | 意外出站连接 | 容器向外部地址发起 TCP 连接 (C2/数据渗透) | | 文件系统写入 | 写入非临时路径 (持久化尝试) | 使用 Docker Compose 在本地运行演示 —— 请参阅 [falco/README.md](falco/README.md) 获取详细操作指南。 ## 部署 (Kubernetes) 要在集群上强制执行准入策略: ``` # 应用 Kyverno ClusterPolicies kubectl apply -f policies/kyverno/ # 验证 — 此 Pod 应被阻止 kubectl apply -f tests/kyverno/resources/pod-fail-privileged.yaml ``` 策略默认以审计模式编写 (`validationFailureAction: Audit`)。在生产环境中请更改为 `Enforce`。
标签:DevSecOps, MITM代理, OPA/Kyverno, Web截图, 上游代理, 子域名突变, 容器安全, 日志审计, 策略即代码, 结构化提示词, 聊天机器人安全, 请求拦截, 逆向工具