LabHub
学习 学习路径 课程

Kubernetes 运维实务

Secret — 存在哪里,谁读得到

在 LabHub 中继续学习

一句话总结

Kubernetes Secret的base64是编码,不是加密,在默认设置下以明文存储在etcd中。拿到etcd磁盘的人就拿到所有秘密。

概念图: 编码,不是加密 · 直接写入等d · 1层 — 存储时加密(EncryptionConfiguration). · 顺序都是全部

为什么需要这个?

第一次看到Secret宣言时,它看起来像一个无法辨认价格的字符串,看起来像一个加密文件。但只需一个命令就可以还原它。

kubectl get secret app-db -o jsonpath='{.data.password}' | base64 -d
# pr0d-Db-Pass

没有密钥也没有秘密。base64只是为了将二进制文件安全地转换为文本的一种表达方式。更重要的事实是接下来。在基本设置的群集中,apiserver将Secret 直接写入等d。获得等d快照文件、磁盘映像、备份存档的人可以在其中直接读取密码字符串。在前一个模块中学习了如何弹出快照并将其移动,所以也应该了解该文件是多么敏感的东西。

怎么行动

应对是层层堆积的。

1层 — 存储时加密(EncryptionConfiguration). apiserver 设置文件物理写入等d之前,先加密Secret。

apiVersion: apiserver.config.k8s.io/v1
kind: EncryptionConfiguration
resources:
  - resources: [secrets]
    providers:
      - aescbc:
          keys:
            - name: key1
              secret: <32바이트 base64 키>
      - identity: {}

这里的顺序都是全部。列表中的第一个提供商被用来写,读的时候从上面开始依次尝试。identity因为意味着“不加密”,所以必须放在最后。放在前面的话,从那一刻开始就会恢复到平文保存。而且即使更改设置,**现有对象在重新写之前也会保持为平文。**需要读一遍整个内容后再重新写。

**2层——信封加密(KMS v2)。**将密钥写入集群设置文件最终又会产生另一个秘密。KMS提供商将这个问题分为两层。数据用数据密钥(DEK)加密,然后将该数据密钥再次加密为KMS的主密钥(KEK)。主密钥在集群外的硬件安全模块或云KMS中,apiserver只能通过连接到Unix套接字上的插件进行访问。旋转密钥时不需要重新加密所有数据也是一个很大的优点。

3层 — 访问控制(RBAC)。即使将存储加密,对可以通过API读取的人也没有用。在哪个命名空间get secrets有权限的人会读取那个命名空间的所有秘密。出于方便,给予的编辑权限实际上实际上是生产资格证阅览权限的情况非常常见。要缩小范围的话resourceNames不能给罗起名字。

rules:
  - apiGroups: [""]
    resources: ["secrets"]
    resourceNames: ["db-password"]
    verbs: ["get"]

只是**resourceNameslistwatch不适用。**因为列表查询是无法提前知道对象名称的请求。所以名称单位限制是get是缩小的工具,list答案是一开始就不给。

4层——将值放在群集之外。 External Secrets Operator等工具将实际值放在秘密管理器中,只在群集中提交引用。SecretStore去“从哪里拿来”,ExternalSecret定义这个“用什么名字做什么”。Manifest中没有值,所以可以直接在仓库上提交。但是,因为操作员最终会创建Cluster Secret,所以前面RBAC和存储时的加密问题仍然存在。

最后immutable: true有。如果锁定不能更改价格,就会阻止因错误而发生的更改,而且kubelet不必进行更改监控,也会增加负载。要更改的话,必须创建一个新的名称并转移引用。

在现场相遇的样子

第一,应对时间也是成熟度。衡量秘密管理的水平的问题不是“是否隐藏得好”,而是“假设这个值现在被公开了,需要几分钟才能销毁和更换”。如果答案是时间单位,那么比起买更多的工具,首先要制定轮换路线。

第二,泄露应对的顺序。在Github历史记录中发现密钥时,第一步不是重写历史记录,而是销毁。公开的值会在几秒钟内被自动扫描仪收集,所以无论如何删除历史记录,已经复制过的值都无法恢复。销毁→影响调查→历史记录整理是正确的顺序。

**第三,环境变量不是存储位置,而是传递方式。**注入容器中的环境变量在同一主机上/proc/<PID>/environ被读取,继承到子进程中,并泄漏到崩溃报告和日志中。文件挂载更安全的理由就在这里。

下次实习要做的事情

创建Secret,直接反向base64后,保存时填写加密设置和KMS v2信封加密设置。无偿创建外部秘密存储库关联配置文件,resourceNames制作一个只打开一个秘密的角色,确认其限制。制作一个不变的Secret,看到无法修改,最后直接查询etcd,留下显示平文的证据,整理应对方案。