# 27、容器安全加固

> 容器平台等保三级安全加固（Docker/Kubernetes/Harbor）：Docker 远程 API TLS 双向认证与 2375 明文收敛、daemon.json 基线（live-restore、log-driver max-size/max-file、userns-remap 用户命名空间重映射与 dockremap）、容器非 root 运行与 --privileged/capabilities/seccomp/AppArmor 收敛、镜像来源治理与 DOCKER_CONTENT_TRUST；Kubernetes 控制面 --anonymous-auth=false 与 RBAC cluster-admin 收敛、Pod Security Admission 分级、NodeRestriction、审计策略 --audit-log-maxage、etcd 静态加密 secretbox、NetworkPolicy；Harbor HTTPS 强制、harbor_admin_password 首启读取机制、Trivy 扫描阻断策略、机器人账号与垃圾回收；每节附核查命令、加固操作与 CIS/Docker Bench 对照。

---

LLMS index: [llms.txt](/wikis/llms.txt)

---

> 定位：容器技术栈（Docker / Kubernetes / Harbor）等保三级安全加固手册：按 00~10 编号分节覆盖基线自查、Docker 守护进程与远程 API、镜像治理、运行时隔离、用户命名空间、日志审计、Kubernetes 控制面与数据面、Harbor 私有仓库、备份恢复与版本生命周期，每节附核查命令、加固操作与官方依据。
>
> 适用版本：Docker Engine 24.x/25.x（daemon.json 配置参考以 docs.docker.com 现行版为准）、Kubernetes v1.28~v1.33（kubeadm 与二进制部署）、Harbor 2.x（v2.10+）。
> 配套测评：[Docker 容器运行平台测评](../../../gradeProtection/中间件与容器/docker/)、[Kubernetes 容器编排平台测评](../../../gradeProtection/中间件与容器/kubernetes/)、[Harbor 容器镜像仓库测评](../../../gradeProtection/中间件与容器/harbor/)。
>
> 使用说明：
>
> - 本文为**加固操作手册**：`systemctl restart docker`、修改 kube-apiserver 静态 Pod 参数（需重启控制面 Pod）、`docker restart` 均会造成业务中断，实施前必须完成变更审批、确认业务窗口、备份 `daemon.json`/`/etc/kubernetes/`/Harbor 数据目录，并准备**可执行的回滚预案**。
> - 先在测试集群或单节点灰度验证，确认业务容器与 Pod 正常后再推广；每完成一项立即用文中「核查方法」复核——`daemon.json` 修改后未重启守护进程不生效、`userns-remap` 启用后既有镜像与容器会被隔离到新的属主目录（官方建议在**新装环境**启用而非存量环境）。
> - 示例中的地址、账户、口令、路径均为演示值（如 `192.168.10.5`、`registry.demo.local`），现场须替换为真实值并脱敏；**严禁直接沿用示例口令**。
> - 命令回显与本文不一致时，先确认版本与部署形态（包管理器/二进制/kubeadm/Helm），再查阅对应版本文档换用等效命令；**版本差异不得直接作为「无法整改」的结论**，须给出替代措施并评估其实际效果。
> - 涉及远程 API、TLS、RBAC、准入的变更存在锁死自身风险：务必保留一条已验证的恢复通道（本机 root SSH、控制台访问、另一个 cluster-admin kubeconfig 或 bootstrap token）后再实施。
> - 加固完成后按「16、安全评估加固记录表3.0」逐项留痕，并纳入复测；测评判定口径以 GB/T 28448-2019 与《高风险判定指引》为准。
>
> 不适用标识说明：
>
> - 使用 `【不适用】` 明确标记现场可判定为不适用的控制点，并写明判定依据与承载该能力的上位组件。
> - 依据 GB/T 28448-2019「按测评对象实际承载功能与数据处理范围判定」原则：能力由云托管容器平台（ACK/GKE/EKS 等）、镜像仓库 SaaS、统一日志平台承载时，应注明测评单元边界后判定不适用或转由上位组件核查。
> - 产品版本确实不提供该能力时，须核查替代措施并按实际效果定档，不得直接判不适用。

## 测评项对照表

| 控制点（GB/T 22239-2019 安全计算环境-容器平台） | 对应章节 |
| --- | --- |
| 入侵防范：暴露面收敛、最小安装、漏洞修补 | 00、01、02 |
| 身份鉴别：管理入口鉴别、防窃听 | 01、06、08 |
| 访问控制：权限最小化、默认账户治理 | 03、06、08 |
| 安全审计：日志与留存 | 05 |
| 数据保密性：etcd 加密、TLS | 07 |
| 数据备份恢复 | 09 |
| 剩余信息保护：镜像与凭据清理 | 10 |

## 00 官方安全基线与自查

> **对应控制点**：GB/T 22239-2019 8.1.4.4 入侵防范 a)~f)
>
> **加固要点**：以官方文档与社区基线为整改标尺并定期自查：Docker 官方安全文档与守护进程攻击面说明（docs.docker.com/engine/security/）、CIS Docker Benchmark 与配套自查脚本 Docker Bench for Security（docker/docker-bench-security）、CIS Kubernetes Benchmark（cisecurity.org 入口）、Harbor 官方管理文档（goharbor.io/docs）。测评现场高频引用的容器逃逸与暴露面判定口径即来自这两套基准。
>
> **验证方法**：Docker Bench for Security 输出报告（WARN 项整改台账）、CIS 自查记录、版本台账。

**核查方法**

```bash
# Docker Bench for Security（只读自查脚本，容器化运行）
docker run --rm --net none --pid host --userns host --cap-drop ALL \
  -v /var/lib:/var/lib:ro -v /var/run/docker.sock:/var/run/docker.sock:ro \
  -v /etc:/etc:ro --label docker_bench_security docker/docker-bench-security
docker version --format '{{.Server.Version}}'
kubectl version
docker compose version        # Harbor 2.x 部署侧
```

- 预期现象：自查报告 WARN 项有整改记录；三平台版本均在官方支持窗口内。

## 01 Docker 守护进程与远程 API 收敛（核心）

> **对应控制点**：GB/T 22239-2019 8.1.4.1 身份鉴别 c)、8.1.4.4 入侵防范 b) c)
>
> **加固要点**：Docker 守护进程默认仅监听本机 Unix socket（`/var/run/docker.sock`），**凡将 `-H tcp://0.0.0.0:2375` 明文开放远程 API，等同向网络开放 root 级主机控制通道**（官方安全文档明确要求守护进程仅可达于受信方）。确需远程管理时：仅绑定运维网段地址、强制 `--tlsverify` 双向证书认证（ca/server/client 三套证书）、防火墙仅放行堡垒机来源；`docker.sock` 不得挂载进业务容器；宿主机侧对 docker 组成员按最小化收敛（docker 组等价 root）。
>
> **验证方法**：`ss -lntp` 无 2375 明文监听、`docker context ls` 管理通道清单、TLS 证书连接实测、`docker inspect` 无 sock 挂载抽查。

<div class="alert alert-warning" role="alert"><div class="h4 alert-heading" role="heading">高风险提示</div>


2375/2376 端口对非运维网段开放且未启用 TLS 双向认证，或 `/var/run/docker.sock` 被挂载进业务容器，按《高风险判定指引》直接判高风险——通过该通道可在宿主机创建特权容器完成逃逸。

判定口径详见 [22、高风险判定指引与加固对照表](../../其他系统或设备/22高风险判定指引与加固对照表/)。
</div>


**核查方法**

```bash
ss -lntp | grep -E "2375|2376"
ps -ef | grep [d]ockerd
docker context ls
grep -R "hosts\|tls" /etc/docker/daemon.json
docker ps -q | xargs -I{} docker inspect {} --format '{{.Name}} {{json .Mounts}}' | grep docker.sock
```


<details class="td-details"><summary>示例输出（节选）</summary><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ ss -lntp <span class="p">|</span> grep <span class="m">237</span>
</span></span><span class="line"><span class="cl">LISTEN <span class="m">0</span> <span class="m">128</span> 192.168.10.5:2376 users:<span class="o">((</span><span class="s2">&#34;dockerd&#34;</span>,pid<span class="o">=</span>1122,fd<span class="o">=</span>7<span class="o">))</span>    <span class="c1"># 仅运维网段且 TLS</span>
</span></span><span class="line"><span class="cl">（无 0.0.0.0:2375 明文监听）
</span></span><span class="line"><span class="cl">$ ps -ef <span class="p">|</span> grep <span class="o">[</span>d<span class="o">]</span>ockerd
</span></span><span class="line"><span class="cl">root  <span class="m">1122</span>  /usr/bin/dockerd --tlsverify --tlscacert<span class="o">=</span>/etc/docker/ca.pem <span class="se">\
</span></span></span><span class="line"><span class="cl">  --tlscert<span class="o">=</span>/etc/docker/server-cert.pem --tlskey<span class="o">=</span>/etc/docker/server-key.pem <span class="se">\
</span></span></span><span class="line"><span class="cl">  -H<span class="o">=</span>fd:// -H<span class="o">=</span>tcp://192.168.10.5:2376
</span></span></code></pre></div>
</details>


**加固操作**（`/etc/docker/daemon.json` + 重启；证书生成走内部 CA，客户端配置 `docker context create` 分发）

```bash
# 生成服务端/客户端证书（官方 Protect the Docker daemon socket 章节流程，CA 为内部根）
systemctl stop docker
# 编辑 /etc/docker/daemon.json：见下方 JSON
systemctl start docker
docker --tlsverify --tlscacert=ca.pem --tlscert=cert.pem --tlskey=key.pem \
  -H=tcp://192.168.10.5:2376 version    # 验证 TLS 通道
```

```json
{
  "hosts": ["unix:///var/run/docker.sock", "tcp://192.168.10.5:2376"],
  "tls": true,
  "tlsverify": true,
  "tlscacert": "/etc/docker/ca.pem",
  "tlscert": "/etc/docker/server-cert.pem",
  "tlskey": "/etc/docker/server-key.pem",
  "live-restore": true,
  "log-driver": "json-file",
  "log-opts": { "max-size": "50m", "max-file": "5" }
}
```

- 预期现象：明文 API 关闭；无证书客户端连接被拒；`live-restore` 生效（守护进程重启不中断容器，`docker info` 显示 `Live Restore Enabled: true`）。

## 02 镜像治理与内容信任

> **对应控制点**：GB/T 22239-2019 8.1.4.4 入侵防范 a) d)（最小安装、数据有效性检验）
>
> **加固要点**：镜像来源白名单（仅内部 Harbor 或官方认证仓库，杜绝公网随手 `docker run`）；基础镜像定期重建扫描（配合 Harbor Trivy，见 08 节）；启用内容信任（Content Trust）验证镜像签名——环境变量 `DOCKER_CONTENT_TRUST=1` 后 pull 未签名镜像被拒（官方 Content trust in Docker 章节）；生产镜像使用 digest 固定（`nginx@sha256:...`）而非可变 tag；镜像构建走 CI 流水线留痕，禁止在生产宿主机现场构建。
>
> **验证方法**：`DOCKER_CONTENT_TRUST=1 docker pull` 拒绝未签名镜像实测、镜像清单 digest 抽查、CI 构建记录。

**核查方法**

```bash
docker images --digests
DOCKER_CONTENT_TRUST=1 docker pull demo.local/app:v1.2.3
grep -R "DOCKER_CONTENT_TRUST" /etc/profile.d/ /root/.bashrc 2>/dev/null
```


<details class="td-details"><summary>示例输出（节选）</summary><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ <span class="nv">DOCKER_CONTENT_TRUST</span><span class="o">=</span><span class="m">1</span> docker pull demo.local/app:v1.2.3
</span></span><span class="line"><span class="cl">Pull <span class="o">(</span><span class="m">1</span> of 1<span class="o">)</span>: demo.local/app@sha256:9c7f...
</span></span><span class="line"><span class="cl">docker.io/demo.local/app:v1.2.3 未启用签名的公共仓库：
</span></span><span class="line"><span class="cl">Error: remote does not have trusted data    <span class="c1"># 无签名镜像被拒</span>
</span></span></code></pre></div>
</details>


**加固操作**

```bash
# 对运维账户默认启用内容信任（按需，注意对既有脚本的影响——未签名仓库 pull 会失败）
echo 'export DOCKER_CONTENT_TRUST=1' > /etc/profile.d/docker-trust.sh
```

- 预期现象：签名验证开启；镜像台账中每条来源可追溯（仓库、digest、构建流水线编号）。

## 03 容器运行时隔离：非 root、去特权与能力收敛

> **对应控制点**：GB/T 22239-2019 8.1.4.2 访问控制 a)~f)、8.1.4.4 入侵防范
>
> **加固要点**：官方安全文档的优先级顺序：**容器内应用以非特权用户运行是防提权的第一道防线**（`docker run --user` 或镜像内 USER 指令）；禁止无业务必要的 `--privileged`（官方明确其给予几乎所有主机能力）；按需 `--cap-drop ALL` 后仅 `--cap-add` 单项能力；只读根文件系统 `--read-only`；资源限额（`--memory`/`--cpus`）防资源耗尽；seccomp 默认 profile 已启用（Docker 默认阻断数十个高危系统调用，自定义见官方 Seccomp security profiles 章节）；Ubuntu 宿主机确认 AppArmor profile 加载（官方 AppArmor security profiles for Docker 章节）。挂载最小化：不挂载 `/etc`、`/var/run`、`/root` 等宿主敏感目录，必需挂载尽量 `:ro`。
>
> **验证方法**：`docker inspect` 的 Privileged/CapAdd/User/ReadonlyRootfs 字段抽查、`docker info` 的 Security Options（seccomp/apparmor）、特权容器清单为空或有例外审批。

<div class="alert alert-warning" role="alert"><div class="h4 alert-heading" role="heading">高风险提示</div>


`--privileged`、`--pid=host`、`--network=host`、挂载 docker.sock 或宿主 `/` 目录的容器，以及以 root 长期运行且暴露公网端口的业务容器，按《高风险判定指引》判高风险（宿主机逃逸通道）。

判定口径详见 [22、高风险判定指引与加固对照表](../../其他系统或设备/22高风险判定指引与加固对照表/)。
</div>


**核查方法**

```bash
docker ps -q | xargs -I{} docker inspect {} --format \
  '{{.Name}} Priv={{.HostConfig.Privileged}} Caps={{.HostConfig.CapAdd}} User={{.Config.User}} RO={{.HostConfig.ReadonlyRootfs}}'
docker info --format '{{json .SecurityOptions}}'
docker ps -q | xargs -I{} docker inspect {} --format '{{.Name}} {{json .HostConfig.Binds}}'
```


<details class="td-details"><summary>示例输出（节选）</summary><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">/demo-web <span class="nv">Priv</span><span class="o">=</span><span class="nb">false</span> <span class="nv">Caps</span><span class="o">=[]</span> <span class="nv">User</span><span class="o">=</span>appuser <span class="nv">RO</span><span class="o">=</span><span class="nb">true</span>
</span></span><span class="line"><span class="cl">/demo-redis <span class="nv">Priv</span><span class="o">=</span><span class="nb">false</span> <span class="nv">Caps</span><span class="o">=[]</span> <span class="nv">User</span><span class="o">=</span><span class="m">999</span> <span class="nv">RO</span><span class="o">=</span><span class="nb">false</span>
</span></span><span class="line"><span class="cl">docker info --format <span class="s1">&#39;{{json .SecurityOptions}}&#39;</span>
</span></span><span class="line"><span class="cl"><span class="o">[</span><span class="s2">&#34;name=seccomp,profile=builtin&#34;</span>,<span class="s2">&#34;name=apparmor,profile=docker-default&#34;</span><span class="o">]</span>
</span></span></code></pre></div>
</details>


**加固操作**（以运行命令与 Dockerfile 两条路径落地，变更需重启容器窗口）

```bash
# 运行命令侧：非 root + 全量去能力 + 按需加回 + 只读根 + 资源限额
docker run -d --name demo-web \
  --user 1000:1000 --cap-drop ALL --cap-add NET_BIND_SERVICE \
  --read-only --tmpfs /tmp --memory 512m --cpus 1.0 \
  --restart unless-stopped demo.local/app:v1.2.3
```

```dockerfile
# Dockerfile 侧：镜像固化非 root 用户与最小内容
FROM registry.demo.local/base/nginx:1.24-alpine
RUN adduser -D -u 1000 appuser
USER appuser
```

- 预期现象：特权容器清单为空；`CapAdd` 均有业务依据；业务回归正常。

## 04 用户命名空间重映射（userns-remap）与 rootless

> **对应控制点**：GB/T 22239-2019 8.1.4.2 访问控制、8.1.4.4 入侵防范（提权防护）
>
> **加固要点**：官方 userns-remap 机制：把容器内 root 重映射为宿主机无特权的高位 UID 区间（经 `/etc/subuid`、`/etc/subgid` 管理，如 `dockremap:231072:65536`——容器内 UID 0 对应宿主 UID 231072，对宿主无任何特权）。`daemon.json` 配 `{"userns-remap": "default"}` 由 Docker 自动创建 `dockremap` 用户（也可指定既有用户）。官方注意事项：启用后既有镜像与容器会被隔离（对象移入 `/var/lib/docker/<uid>.<gid>/` 子目录，**建议在新装环境启用**）；与 `--privileged`、`--pid=host`、`--network=host` 不兼容（需 `--userns=host` 显式豁免，豁免须审批）。更彻底的隔离用 Rootless 模式（守护进程与容器均无 root，见官方 Rootless mode 章节），适配场景有限时保留 sock 权限收敛补偿。
>
> **验证方法**：`docker info` 出现 `userns` 安全选项、`grep dockremap /etc/subuid`、宿主 `/var/lib/docker/<uid>.<gid>/` 目录属主、容器内 root 对宿主文件无写入实测。

**核查方法**

```bash
docker info | grep -i -A2 "security"
grep dockremap /etc/subuid /etc/subgid
id dockremap
ls -ld /var/lib/docker/[0-9]*.[0-9]*/ 2>/dev/null
```


<details class="td-details"><summary>示例输出（节选）</summary><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ grep dockremap /etc/subuid /etc/subgid
</span></span><span class="line"><span class="cl">/etc/subuid:dockremap:231072:65536
</span></span><span class="line"><span class="cl">/etc/subgid:dockremap:231072:65536
</span></span><span class="line"><span class="cl">$ ls -ld /var/lib/docker/231072.231072/
</span></span><span class="line"><span class="cl">drwx------ <span class="m">11</span> <span class="m">231072</span> <span class="m">231072</span> <span class="m">4096</span> Jun <span class="m">21</span> 21:19 /var/lib/docker/231072.231072/
</span></span></code></pre></div>
</details>


**加固操作**（新装环境优先；存量环境须先导出容器清单并安排重建窗口）

```json
{ "userns-remap": "default" }
```

- 预期现象：重启后 `docker info` Security options 含 `userns`；既有镜像列表为空（对象已隔离）属正常现象；容器内 `cat /proc/self/uid_map` 显示映射区间。

## 05 日志与审计

> **对应控制点**：GB/T 22239-2019 8.1.4.3 安全审计 a)~d)
>
> **加固要点**：容器日志三路汇聚并留存不少于 6 个月：容器 stdout 日志（daemon.json 的 `log-driver`+`max-size`+`max-file`，防磁盘占满即防日志丢失）、守护进程日志（`journalctl -u docker`，外送 rsyslog）、宿主机 auditd 对 Docker 关键路径的审计规则（docker.sock、daemon.json、/var/lib/docker 的变更）。容器内应用日志沿用宿主日志通道或独立采集器，不留在容器可写层。日志外送至日志审计系统（《网络安全法》第 21 条留存口径）。
>
> **验证方法**：`docker info` 日志驱动与轮转参数回显、auditd 规则 `auditctl -l`、日志平台中容器日志最早时间戳。

**核查方法**

```bash
docker info --format '{{.LoggingDriver}}'
grep -A4 "log-driver" /etc/docker/daemon.json
journalctl -u docker --no-pager | tail -n 5
auditctl -l | grep docker
```


<details class="td-details"><summary>示例输出（节选）</summary><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ grep -A4 <span class="s2">&#34;log-driver&#34;</span> /etc/docker/daemon.json
</span></span><span class="line"><span class="cl"><span class="s2">&#34;log-driver&#34;</span>: <span class="s2">&#34;json-file&#34;</span>,
</span></span><span class="line"><span class="cl"><span class="s2">&#34;log-opts&#34;</span>: <span class="o">{</span> <span class="s2">&#34;max-size&#34;</span>: <span class="s2">&#34;50m&#34;</span>, <span class="s2">&#34;max-file&#34;</span>: <span class="s2">&#34;5&#34;</span> <span class="o">}</span>
</span></span><span class="line"><span class="cl">$ auditctl -l <span class="p">|</span> grep docker
</span></span><span class="line"><span class="cl">-w /etc/docker/daemon.json -p wa -k docker_config
</span></span><span class="line"><span class="cl">-w /var/run/docker.sock -p wa -k docker_sock
</span></span></code></pre></div>
</details>


**加固操作**

```bash
# auditd 规则（/etc/audit/rules.d/docker.rules，载入后 auditctl -R 或重启 auditd）
cat > /etc/audit/rules.d/docker.rules <<'EOF'
-w /etc/docker/daemon.json -p wa -k docker_config
-w /etc/docker -p wa -k docker_dir
-w /var/run/docker.sock -p wa -k docker_sock
EOF
augenrules --load
```

- 预期现象：规则加载成功；日志平台可检索 6 个月以上容器事件；`docker inspect` 日志路径在轮转目录内。

## 06 Kubernetes 控制面加固

> **对应控制点**：GB/T 22239-2019 8.1.4.1 身份鉴别、8.1.4.2 访问控制、8.1.4.3 安全审计
>
> **加固要点**：kube-apiserver 收敛：`--anonymous-auth=false`（默认 true，匿名请求映射 system:anonymous，关闭后未认证请求被拒）、`--insecure-port` 已废弃不得出现；RBAC 治理：`cluster-admin` ClusterRoleBinding 仅保留必要主体（审计 `kubectl get clusterrolebindings cluster-admin -o wide`），不为普通用户/组授予；准入链启用 `NodeRestriction`（kubelet 仅能修改自身 Node/Pod）与 Pod Security Admission（命名空间打 `pod-security.kubernetes.io/enforce` 标签，baseline/restricted 分级，v1.25 起稳定）；审计策略 `--audit-policy-file` 全量覆盖（至少 metadata 级，认证失败与特权操作升 Request 级），`--audit-log-maxage` ≥180 满足 6 个月留存（现行默认 366）；管理入口仅经堡垒机/运维网段访问 6443。ServiceAccount 治理：默认 token 自 v1.24 不再自动投影长期令牌，`automountServiceAccountToken: false` 按业务显式关闭。
>
> **验证方法**：apiserver 启动参数核查（静态 Pod YAML/`kubectl get --raw='/readyz?verbose'`）、无凭据 curl 6443 返回 401 实测、cluster-admin 绑定清单、审计日志样例（含 user/verb/resource/时间）、namespace PSA 标签清单。

<div class="alert alert-warning" role="alert"><div class="h4 alert-heading" role="heading">高风险提示</div>


API Server 匿名访问开启且 6443 暴露非运维网段、cluster-admin 绑定到普通用户/组、system:anonymous 被授予写权限，按《高风险判定指引》判高风险。

判定口径详见 [22、高风险判定指引与加固对照表](../../其他系统或设备/22高风险判定指引与加固对照表/)。
</div>


**核查方法**

```bash
kubectl get pods -n kube-system -l component=kube-apiserver -o yaml | grep -E "anonymous-auth|audit-policy|authorization-mode|admission"
kubectl get clusterrolebindings cluster-admin -o wide
kubectl get ns -L pod-security.kubernetes.io/enforce
curl -sk https://192.168.10.5:6443/version    # 预期 401 Unauthorized
kubectl auth can-i --list --as=system:anonymous
```


<details class="td-details"><summary>示例输出（节选）</summary><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ grep -E <span class="s2">&#34;anonymous-auth|authorization-mode&#34;</span> &lt;apiserver.yaml&gt;
</span></span><span class="line"><span class="cl">- --anonymous-auth<span class="o">=</span><span class="nb">false</span>
</span></span><span class="line"><span class="cl">- --authorization-mode<span class="o">=</span>Node,RBAC
</span></span><span class="line"><span class="cl">$ curl -sk https://192.168.10.5:6443/version
</span></span><span class="line"><span class="cl"><span class="o">{</span>
</span></span><span class="line"><span class="cl">  <span class="s2">&#34;kind&#34;</span>: <span class="s2">&#34;Status&#34;</span>,
</span></span><span class="line"><span class="cl">  <span class="s2">&#34;code&#34;</span>: 401, ...
</span></span><span class="line"><span class="cl"><span class="o">}</span>
</span></span><span class="line"><span class="cl">$ kubectl get clusterrolebindings cluster-admin -o wide
</span></span><span class="line"><span class="cl">NAME          ROLE                        SUBJECTS
</span></span><span class="line"><span class="cl">cluster-admin ClusterRole/cluster-admin   Group/system:masters      <span class="c1"># 仅控制面组</span>
</span></span></code></pre></div>
</details>


**加固操作**（修改 `/etc/kubernetes/manifests/kube-apiserver.yaml` 后静态 Pod 自动重启，须维护窗口）

```yaml
- command:
  - kube-apiserver
  - --anonymous-auth=false
  - --authorization-mode=Node,RBAC
  - --enable-admission-plugins=NodeRestriction
  - --audit-policy-file=/etc/kubernetes/audit-policy.yaml
  - --audit-log-path=/var/log/kubernetes/audit.log
  - --audit-log-maxage=365
  - --audit-log-maxbackup=10
  - --audit-log-maxsize=100
```

- 预期现象：匿名请求 401；审计日志持续落盘且含认证失败事件；PSA enforce 标签覆盖全部业务命名空间。

## 07 Kubernetes 数据面与 etcd 加密

> **对应控制点**：GB/T 22239-2019 8.1.4.7 数据完整性、8.1.4.8 数据保密性
>
> **加固要点**：etcd 是集群全量状态库，三级要求落地三件事：**静态加密**——kube-apiserver 启用 `--encryption-provider-config`（EncryptionConfiguration，官方现行推荐 `secretbox` 加密 Secret；kms v2 自 v1.29 稳定，对接外部 KMS 更佳），并以 `k8s:enc:` 前缀验证实际落密；**传输加密**——apiserver 与 etcd 间 `--etcd-cafile/--etcd-certfile/--etcd-keyfile` 证书双向认证，etcd 2379 仅监听管理网/本机（`ss -lntp | grep 2379`）；**访问控制**——etcd 证书与 key 文件权限 600，仅控制面节点可达。数据面：Pod 出网按 NetworkPolicy 白名单化（默认全通须整改）；Secret 不落明文（避免 env 明文注入，优先 volume 挂载或外部密钥管理）；镜像来源与签名策略经准入（Gatekeeper/Kyverno 或仓库侧策略）管控。
>
> **验证方法**：`kubectl get secret -o jsonpath` 数据带 `k8s:enc:` 前缀、etcdctl 直读为密文、2379 监听地址与防火墙策略、NetworkPolicy 覆盖清单。

**核查方法**

```bash
kubectl get secret demo-secret -n demo-ns -o jsonpath='{.data.password}' | base64 -d | head -c 40
grep -R "encryption-provider-config\|etcd-cafile" /etc/kubernetes/
ss -lntp | grep 2379
kubectl get networkpolicy -A
ETCDCTL_API=3 etcdctl --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/server.crt --key=/etc/kubernetes/pki/etcd/server.key \
  get /kubernetes/secrets/demo-ns/demo-secret --print-value-only | head -c 60
```


<details class="td-details"><summary>示例输出（节选）</summary><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ kubectl get secret demo-secret -o <span class="nv">jsonpath</span><span class="o">=</span><span class="s1">&#39;{.data.password}&#39;</span> <span class="p">|</span> base64 -d <span class="p">|</span> head -c <span class="m">40</span>
</span></span><span class="line"><span class="cl">k8s:enc:aescbc:v1:key1:ﬁ��...            <span class="c1"># k8s:enc: 前缀=已静态加密</span>
</span></span><span class="line"><span class="cl">$ etcdctl get ... --print-value-only <span class="p">|</span> head -c <span class="m">60</span>
</span></span><span class="line"><span class="cl">k8s:enc:aescbc:v1:key1:��<span class="o">}</span>...            <span class="c1"># etcd 侧同为密文</span>
</span></span><span class="line"><span class="cl">$ ss -lntp <span class="p">|</span> grep <span class="m">2379</span>
</span></span><span class="line"><span class="cl">LISTEN <span class="m">0</span> <span class="m">128</span> 192.168.10.5:2379 users:<span class="o">((</span><span class="s2">&#34;etcd&#34;</span>,pid<span class="o">=</span>990,fd<span class="o">=</span>6<span class="o">))</span>   <span class="c1"># 未绑 0.0.0.0</span>
</span></span></code></pre></div>
</details>


**加固操作**（先创建 EncryptionConfiguration，再改 apiserver 参数重启；旧 Secret 须重写一遍才会被加密——官方文档以 `kubectl get secrets --all-namespaces -o json | kubectl replace -f -` 触发重写）

```yaml
# /etc/kubernetes/enc-config.yaml（官方 Encrypting Secret Data at Rest 章节示例结构）
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources: ["secrets"]
  providers:
  - secretbox:
      keys:
      - name: key1
        secret: <32字节随机base64>
  - identity: {}
```

- 预期现象：新写入 Secret 带 `k8s:enc:` 前缀；etcd 直读密文；2379 不对业务网段开放。

## 08 Harbor 私有仓库加固

> **对应控制点**：GB/T 22239-2019 8.1.4.1~8.1.4.4（仓库作为镜像供应链核心组件）
>
> **加固要点**：`harbor.yml` 强制 HTTPS（自签证书须向 docker daemon 与 k8c节点分发 CA；HTTP-only 对外即高风险）；`harbor_admin_password` 仅**首次启动**从配置文件读取（改口令须登录控制台，不能只改 yml——官方 Reconfigure 文档口径），初始 `Harbor12345` 必改；认证模式按需接 OIDC/LDAP（`db_auth` 本地账户配强口令策略）；关闭 `self_registration` 自助注册（按需）；项目公开性默认私有、按最小可见开放；机器人账号（robot account）替代人员共享凭据拉取，设有效期与最小项目权限；Trivy 漏洞扫描开启并配置「高危阻断拉取」策略（Prevent images with vulnerability severity of High or higher from pulling）；部署后启用审计日志留存与日志外送；定期垃圾回收（GC）清理无引用镜像层。
>
> **验证方法**：HTTPS 访问与证书有效期、admin 口令登录实测、`GET /api/v2.0/configurations` 的 self_registration/scan 策略回显、机器人账号清单与到期时间、GC 计划任务截图。

**核查方法**

```bash
grep -E "^hostname|^https|admin_password" /path/to/harbor/harbor.yml | sed 's/password.*/password: ***/'
curl -s -o /dev/null -w "%{http_code}\n" https://registry.demo.local/api/v2.0/health
curl -su admin:*** https://registry.demo.local/api/v2.0/configurations | jq '.self_registration, .scan_all_policy'
docker compose ps        # Harbor 安装目录（v2 语法）
```


<details class="td-details"><summary>示例输出（节选）</summary><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ curl -s https://registry.demo.local/api/v2.0/health
</span></span><span class="line"><span class="cl"><span class="o">{</span><span class="s2">&#34;status&#34;</span>:<span class="s2">&#34;healthy&#34;</span>,<span class="s2">&#34;components&#34;</span>:<span class="o">[]}</span>
</span></span><span class="line"><span class="cl">$ curl -su admin:*** .../api/v2.0/configurations <span class="p">|</span> jq <span class="s1">&#39;.self_registration&#39;</span>
</span></span><span class="line"><span class="cl"><span class="nb">false</span>        <span class="c1"># 自助注册已关闭</span>
</span></span></code></pre></div>
</details>


**加固操作**（`harbor.yml` 修改后执行 `./prepare` 与 `docker compose down && docker compose up -d`，须窗口）

```yaml
# harbor.yml 关键项
hostname: registry.demo.local
https:
  certificate: /data/cert/registry.crt
  private_key: /data/cert/registry.key
harbor_admin_password: <首次部署时的强口令，之后经控制台修改>
```

- 预期现象：HTTP 跳转 HTTPS；扫描策略生效（高危镜像 pull 被拒实测）；机器人账号按项目最小授权。

## 09 备份恢复

> **对应控制点**：GB/T 22239-2019 8.1.4.9 数据备份恢复 a)~c)
>
> **加固要点**：三平台各自的恢复面：Docker——`daemon.json`、证书、自定义 systemd 单元与命名数据卷纳入配置管理，容器重建以编排（compose 文件/K8s 清单）为准而非手工 docker run 复现；Kubernetes——etcd 定期快照（`etcdctl snapshot save`；v3.5+ 校验用 `etcdutl snapshot status`）异地存放，Velero 备份工作负载与 PV，**恢复演练每半年至少一次并留痕**；Harbor——按官方升级/备份章节导出 `/data/database`、registry 存储、harbor.yml 与 secrets 归档。集群多副本（etcd 3 节点、控制面 HA）作为冗余不替代备份。
>
> **验证方法**：快照清单与 `snapshot status` 输出、Velero 备份清单（`velero backup get`）、Harbor 归档清单、最近一次恢复演练记录。

**核查方法**

```bash
ls -l /backup/etcd-snapshots/ | tail -n 3
ETCDCTL_API=3 etcdutl snapshot status /backup/etcd-snapshots/snap-latest.db -w table 2>/dev/null \
  || ETCDCTL_API=3 etcdctl snapshot status /backup/etdb-snapshots/snap-latest.db -w table
velero backup get
docker run --rm -v /backup:/backup -v /var/lib/docker/volumes:/volumes alpine ls /backup
```


<details class="td-details"><summary>示例输出（节选）</summary><div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">$ etcdutl snapshot status /backup/etcd-snapshots/snap-latest.db -w table
</span></span><span class="line"><span class="cl">+----------+----------+------------+------------+
</span></span><span class="line"><span class="cl"><span class="p">|</span>   HASH   <span class="p">|</span> REVISION <span class="p">|</span> TOTAL KEYS <span class="p">|</span> TOTAL SIZE <span class="p">|</span>
</span></span><span class="line"><span class="cl">+----------+----------+------------+------------+
</span></span><span class="line"><span class="cl"><span class="p">|</span> 0x1a2b3c <span class="p">|</span>  <span class="m">8941234</span> <span class="p">|</span>       <span class="m">2011</span> <span class="p">|</span>      <span class="m">29</span> MB <span class="p">|</span>
</span></span><span class="line"><span class="cl">+----------+----------+------------+------------+
</span></span></code></pre></div>
</details>


**加固操作**（快照属运维变更，按计划任务窗口执行）

```bash
# etcd 定期快照（cron 示例）
ETCDCTL_API=3 etcdctl --endpoints=https://127.0.0.1:2379 \
  --cacert=/etc/kubernetes/pki/etcd/ca.crt \
  --cert=/etc/kubernetes/pki/etcd/server.crt \
  --key=/etc/kubernetes/pki/etcd/server.key \
  snapshot save /backup/etcd-snapshots/snap-$(date +%F).db
```

- 预期现象：快照按期生成且 `snapshot status` 校验通过；恢复演练记录在案。

## 10 剩余信息保护与版本生命周期

> **对应控制点**：GB/T 22239-2019 8.1.4.10 剩余信息保护、8.1.4.4 入侵防范（补丁管理）

**核查方法**

```bash
docker ps -a --filter "status=exited" --format "{{.Names}} {{.RunningFor}}"
docker images --format "{{.Repository}}:{{.Tag}} {{.CreatedSince}}" | sort -k2 | head
docker ps -q | xargs -I{} docker inspect {} --format '{{.Name}}' | wc -l
kubectl get secrets -A | wc -l
```

- 加固要点：停用容器、超过留存期的旧镜像、失效 ServiceAccount 令牌与机器人凭据定期清理并留处置记录（`docker container prune`/`docker image prune` 属变更类，走审批）；环境变量中的明文口令改用 secret 机制（Docker secrets/K8s Secret 加密/外部 KMS）。
- 版本生命周期：Kubernetes 官方仅维护最近三个小版本（升级滚动计划）；Docker Engine 跟随发行版/官方源补丁；Harbor 跟随 goharbor releases；三平台升级台账与窗口记录纳入测评证据。
- 预期现象：无长期 Exited 容器与半年以上未引用镜像；凭据无明文残留；升级记录完整。

## 参考依据

- GB/T 22239-2019《信息安全技术 网络安全等级保护基本要求》（8.1.4 安全计算环境各控制点）：[http://openstd.samr.gov.cn/bzgk/gb/newGbInfo?hcno=BAFB47E8874764186BDB7865E8344DAF](http://openstd.samr.gov.cn/bzgk/gb/newGbInfo?hcno=BAFB47E8874764186BDB7865E8344DAF)
- GB/T 28448-2019《信息安全技术 网络安全等级保护测评要求》（测评对象边界认定、单元测评实施与结果判定）：[http://openstd.samr.gov.cn/bzgk/gb/newGbInfo?hcno=7E736CDF4502B6FF1258DD250AA3EC8C](http://openstd.samr.gov.cn/bzgk/gb/newGbInfo?hcno=7E736CDF4502B6FF1258DD250AA3EC8C)
- Docker 官方安全文档（守护进程攻击面、保护 Docker 守护进程 socket、seccomp/AppArmor、Rootless mode、Content trust）：[https://docs.docker.com/engine/security/](https://docs.docker.com/engine/security/)
- Docker 官方用户命名空间隔离文档（userns-remap 启用、dockremap 与 /etc/subuid、已知限制——2026-09 全文核验）：[https://docs.docker.com/engine/security/userns-remap/](https://docs.docker.com/engine/security/userns-remap/)
- Docker 官方 dockerd 配置参考（daemon.json 的 hosts/tls/tlsverify/live-restore/log-driver/log-opts）：[https://docs.docker.com/reference/dockerd/](https://docs.docker.com/reference/dockerd/)
- Docker Bench for Security 与 CIS Docker Benchmark：[https://github.com/docker/docker-bench-security](https://github.com/docker/docker-bench-security)、[https://www.cisecurity.org/benchmark/docker/](https://www.cisecurity.org/benchmark/docker/)
- Kubernetes 官方文档（kube-apiserver 命令行参考、Pod Security Admission、RBAC、审计策略、Secret 静态加密、etcd 运维——与站内测评篇同期核验）：[https://kubernetes.io/docs/reference/command-line-tools-reference/kube-apiserver/](https://kubernetes.io/docs/reference/command-line-tools-reference/kube-apiserver/)、[https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/](https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/)
- CIS Kubernetes Benchmark 入口：[https://www.cisecurity.org/benchmark/kubernetes/](https://www.cisecurity.org/benchmark/kubernetes/)
- Harbor 官方文档（harbor.yml 配置、重新配置生命周期、漏洞扫描、机器人账号、垃圾回收、备份）：[https://goharbor.io/docs/](https://goharbor.io/docs/)
- 《网络安全等级保护测评高风险判定指引》（中关村信息安全测评联盟团体标准），站内对照表：[22、高风险判定指引与加固对照表](../../其他系统或设备/22高风险判定指引与加固对照表/)
- 命令核验说明：本文命令已于 2026-09 对照 docs.docker.com（security/userns-remap 全文、dockerd 参考）、kubernetes.io（kube-apiserver 参考、Encrypting Secret Data at Rest）、goharbor.io/docs 核验，并与站内 [Docker](../../../gradeProtection/中间件与容器/docker/)、[Kubernetes](../../../gradeProtection/中间件与容器/kubernetes/)、[Harbor](../../../gradeProtection/中间件与容器/harbor/) 三篇测评篇的核验结论互证；四处须留意：① `daemon.json` 的 `hosts` 与 systemd 单元 `ExecStart -H` 冲突会启动失败，改动前先 `systemctl cat docker` 确认；② `userns-remap` 建议新装环境启用，存量环境启用后既有镜像/容器不可见（对象被隔离属预期而非故障）；③ etcd 静态加密只对新写入 Secret 生效，存量 Secret 须触发重写；④ 快照校验命令在 etcd v3.5+ 迁移为 `etcdutl snapshot status`（旧 `etcdctl snapshot status` 仍可用以现场版本为准）。

## 关联文章

- 配套测评：[Docker 容器运行平台测评](../../../gradeProtection/中间件与容器/docker/)、[Kubernetes 容器编排平台测评](../../../gradeProtection/中间件与容器/kubernetes/)、[Harbor 容器镜像仓库测评](../../../gradeProtection/中间件与容器/harbor/)、[Elasticsearch 搜索与分析平台测评](../../../gradeProtection/中间件与容器/elasticsearch/)
- 同目录：[21、Web中间件安全加固](../21web中间件安全加固/)、[26、Redis数据库加固](../26redis数据库加固/)
- 主机层配套：[11、Linux操作系统加固手册](../../服务器/11linux操作系统加固手册/)（容器宿主机按主机层加固）
- 通用加固方案：[17、加固方案总纲](../../其他系统或设备/17网络设备安全设备服务器数据库和应用系统的加固方案/)
- 取证记录：[16、安全评估加固记录表3.0](../../其他系统或设备/16安全评估加固记录表3.0/)
- 高风险口径：[22、高风险判定指引与加固对照表](../../其他系统或设备/22高风险判定指引与加固对照表/)
- 板块目录：[系统管理软件·平台](../)
