4. Secrets 静态存储风险:etcd 未加密、Base64 编码误解、RBAC 配置不当等常见漏洞
在云原生环境中,Secrets 的静态存储安全是准入策略评审的核心关注点。许多团队误以为将 Secret 存入 Kubernetes 即“安全”,但实际上,Secrets 在 etcd 中的存储方式、编码认知偏差以及访问控制缺失,构成了三大主要风险面。本章将逐一剖析这些漏洞,并提供对应的评审与加固策略。
4.1 风险全景:Secrets 静态存储三大漏洞
下表总结了 Secrets 在静态存储阶段最常见的三类安全漏洞及其影响范围:
| 漏洞类别 | 核心问题 | 攻击面 | 风险等级 |
|---|---|---|---|
| etcd 未加密 | etcd 数据存储未启用静态加密,Secret 以明文或可逆格式持久化 | etcd 备份泄露、磁盘窃取、管理员越权访问 | 严重 |
| Base64 编码误解 | 开发者误认为 Base64 是加密,导致 Secret 在 YAML/日志中明文暴露 | CI/CD 日志、版本控制系统、代码仓库泄露 | 高 |
| RBAC 配置不当 | 对 Secrets 的 get/list/watch 权限过度授予,非授权用户可读取敏感数据 | 集群内部横向移动、Pod 越权访问、审计缺失 | 高 |
4.2 etcd 未加密:静态存储的“最后一公里”风险
Kubernetes 默认将所有 Secret 对象以 Base64 编码 的形式存储在 etcd 中。如果 etcd 本身未启用静态加密(Encryption at Rest),任何能够直接访问 etcd 数据目录或备份文件的攻击者,都可以通过简单的 Base64 解码获取所有 Secrets 的明文内容。
4.2.1 评审要点:etcd 静态加密配置
在准入策略评审中,应检查集群是否启用了 EncryptionConfiguration 资源。以下是一个合规的加密配置示例:
apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
- resources:
- secrets
providers:
- aescbc:
keys:
- name: key1
secret: <base64-encoded-32-byte-key>
- identity: {} # 降级策略,仅用于迁移
4.2.2 风险影响链路
下图展示了 etcd 未加密场景下,Secret 泄露的完整攻击链路:
4.3 Base64 编码误解:不是加密,只是编码
Kubernetes Secret 对象中的 data 字段使用 Base64 编码,但 Base64 不是加密算法。任何拥有 Secret YAML 文件读取权限的人,都可以通过 echo <base64-string> | base64 --decode 获取明文。
4.3.1 编码 vs 加密:概念对比
| 特性 | Base64 编码 | AES-256 加密 |
|---|---|---|
| 目的 | 二进制数据文本化传输 | 数据机密性保护 |
| 可逆性 | 无需密钥,直接解码 | 需要密钥,解密 |
| 密钥管理 | 无 | 需要 KMS / 密钥轮换 |
| 合规要求 | 不满足任何合规标准 | 满足 PCI-DSS / SOC2 等 |
4.3.2 常见泄露场景
- Git 仓库泄露: 开发人员将包含 Base64 Secret 的 YAML 文件提交到公共仓库。
- CI/CD 日志:
kubectl get secret mysecret -o yaml的输出被打印到构建日志。 - 错误消息: 应用启动时打印包含 Base64 编码的配置信息。
4.4 RBAC 配置不当:谁可以读你的 Secrets?
Kubernetes RBAC 是控制 Secret 访问的核心机制。配置不当的 RBAC 策略可能导致非授权用户或 Pod 能够读取集群中的所有 Secrets。
4.4.1 最小权限原则评审清单
在准入策略评审中,应逐项检查以下 RBAC 配置:
- ClusterRole 聚合: 检查是否存在通配符
resources: ["*"]或verbs: ["*"]的 ClusterRole。 - Secrets 的 get/list/watch 权限: 确认只有必要的 ServiceAccount 拥有这些权限。
- RoleBinding 范围: 确保 RoleBinding 绑定到正确的命名空间,避免跨命名空间访问。
- 自动挂载: 检查 Pod 是否禁用了
automountServiceAccountToken,避免不必要的 Secret 访问。
4.4.2 风险 RBAC 配置示例
以下是一个典型的 高风险 RBAC 配置,应被准入策略拒绝:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: secret-reader-all
rules:
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get", "list", "watch"] # 允许读取所有命名空间的 Secrets
4.4.3 合规 RBAC 配置示例
以下是一个符合最小权限原则的配置:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: production
name: secret-reader-app
rules:
- apiGroups: [""]
resources: ["secrets"]
resourceNames: ["db-credentials", "api-"] # 仅允许读取指定 Secret
verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
namespace: production
name: app-secret-reader
subjects:
- kind: ServiceAccount
name: my-app
namespace: production
roleRef:
kind: Role
name: secret-reader-app
apiGroup: rbac.authorization.k8s.io
4.5 静态存储风险加固策略总结
下表汇总了针对上述三大漏洞的加固策略与准入策略评审要点:
| 风险类别 | 加固策略 | 准入策略评审项 |
|---|---|---|
| etcd 未加密 | 启用 EncryptionConfiguration,使用 KMS 提供者 | 检查集群是否配置了 EncryptionConfiguration 且包含 secrets 资源 |
| Base64 误解 | 使用 Sealed Secrets / External Secrets Operator 替代 | 禁止在 YAML 中直接使用 data 字段,强制使用 stringData 或外部引用 |
| RBAC 配置不当 | 实施最小权限原则,限制 resourceNames |
拒绝包含 secrets 且 verbs 包含 list/watch 的 ClusterRole |
data 字段的 Secret 对象。