加密 K8s Secrets 的几种方案
前言
你可能已经听过很多遍这个不算秘密的秘密了--Kubernetes Secrets 不是加密的!Secret 的值是存储在 etcd 中的 base64 encoded(编码) 字符串。这意味着,任何可以访问你的集群的人,都可以轻松解码你的敏感数据。任何人?是的,几乎任何人都可以,尤其是在集群的 RBAC 设置不正确的情况下。任何人都可以访问 API 或访问 etcd。也可能是任何被授权在 Namespace 中创建 pod 或 Deploy,然后使用该权限检索该 Namespace 中所有 Secrets 的人。 如何确保集群上的 Secrets 和其他敏感信息(如 token)不被泄露?在本篇博文中,我们将讨论在 K8s 上构建、部署和运行应用程序时加密应用程序 Secrets 的几种方法。
K8s 的 Secrets
在 Kubernetes 集群上运行的应用程序可以使用 Kubernetes Secrets,这样就无需在应用程序代码中存储 token 或密码等敏感数据。
当前默认 Kubernetes 集群内 Secrets 的典型工作流程如下:
Dev 阶段:使用 CICD 的应用程序开发人员将 git 作为管理部署到集群的配置的真实来源。访问控制有助于确保对该资源库的访问安全,但这本身并不总能确保应用程序的敏感信息不被泄露。
Ops 阶段:API 服务器会在集群上创建 Kubernetes Secrets 资源,你可以在这里 这里 阅读有关 Secrets 生命周期的更多信息。 存储在 etcd 中的 Secrets 可由应用程序 pod 以三种方式之一使用:
- 作为一个或多个容器的 卷挂载 中的文件。
- 作为容器 环境变量。
- 由 Pod 的 kubelet 在拉取镜像时使用。
在这三种情况下,密文中的值在使用前都会被解码 (decode)。
那么,既然我们知道了它的工作原理,为什么只对密文进行 base64 编码还不够呢?
Base64 编码为什么不算密文?
Base64 编码是一种二进制到文本的编码方案,它将 24 位二进制数据表示为 6 位 base64 数字。它用于在网络上传输大量数据,尤其是图像文件等大型文件。它的主要功能是在数据通过网络传输时提供数据的完整性。要明确,编码 (encode) 并不是加密 (encrypt)。
在任何 Linux 终端上试试这个。
$ echo -n 'not encrypted' | base64
bm90IGVuY3J5cHRlZA==
$ echo -n 'bm90IGVuY3J5cHRlZA==' | base64 --decode
not encrypted
如上,无论是在将 Secrets 传输到群集时,还是在群集上使用时,任何可以访问你系统的人都可以轻松解码你的 Secrets。
问题来了
作为 DevSecOps 管理员,您显然面临着两个挑战:
- 如何加密和管理集群外的敏感数据,即在构建和部署阶段进入集群之前?
- 如何在集群内运行应用程序时保护敏感数据的安全?
以下是加密 K8s Secrets 的几种方案。
在部署到群集之前对机密进行加密
作为将代码推送到 git 仓库(又称应用程序的 "真相源")的开发人员,您可以在将代码推送到 git 仓库之前对应用程序使用的敏感信息进行加密。下面将介绍两种常见的方法,用于在机密提交到 git 仓库并部署到 OpenShift 集群之前对其进行加密:
使用 Bitnami Sealed Secrets
Bitnami Sealed Secrets 简介
Bitnami Sealed Secrets: Kubernetes 的“加密的 Secrets”.
典型使用场景:
遇到的问题:“我可以在 git 中管理我所有的 K8s 配置,除了 Secrets。”
解决方案:将您的 Secret 加密到 SealedSecret 中,即使在公共存储库中也可以安全存储。SealedSecret 只能由目标集群中运行的控制器解密,其他人(甚至原始作者)无法从 SealedSecret 中获得原始 Secret。
Bitnami Sealed Secrets 使用流程
使用 Bitnami Sealed Secrets 的工作流程示例如下:
- 集群管理员在 K8s 集群上部署 Sealed secrets 控制器
- 开发者需要在本地计算机上安装
kubeseal
CLI。 - 开发者创建一个 Secret 资源,然后由
kubeseal
CLI 在运行时从控制器中获取密钥,对该资源进行加密或密封。对于网络受限的环境,公钥也可以存储在本地并由 kubeseal 使用。 Kubeseal 将创建一个SealedSecret
自定义资源。 - 开发者将此 CR 推送到自己的 git 仓库中
- 可使用 ArgoCD 等 CD 工具在集群上部署 CR。
- 控制器将检测到 SealedSecret 资源,并使用集群上的私钥对其进行解密。
使用 KSOPS/Mozilla SOPS
KSOPS/Mozilla SOPS 简介
- Mozilla SOPS - sops 是加密文件的编辑器,支持 YAML,JSON,ENV,INI 和 BINARY 格式,并使用 AWS KMS,GCP KMS,Azure Key Vault,age 和 PGP 进行加密。
- KSOPS - 一个灵活的 SOPS 加密资源的 Kustomize 插件
KSOPS/Mozilla SOPS 使用流程
如果使用 Argo CD 在 Kubernetes 中部署应用程序,则可以使用 Kustomize SOPS 插件,该插件用于解密使用 SOPS 加密的资源。
在集群上,管理员将:
- 部署 ArgoCD
- 使用 age 生成密钥
- 在 特定(如
GitOps
) Namespace 中创建存储公钥和私钥的密钥 - 定制 Argo CD 以使用 Kustomize SOPS 插件
- 将公钥推送到 Git 仓库
开发人员将:
- 在本地控制台创建 Secret
- 使用 SOPS CLI 下载公钥并加密密文
- 用加密后的 Secrets 生成 KSOPS yaml 并推送到 Git 仓库
ArgoCD 在集群上部署 Secrets 之前,会使用 KSOPS 对机密文件进行解密。
小结
上面这两种方法都适用于使用非对称加密技术对机密文件进行加密。两者都提供了在敏感数据作为 Secrets 部署到集群之前对其进行解密的方法。Sealed secrets 与 Kubernetes 原生集成。SOPS / KSOPS 可以独立工作,不需要集群上的控制器。另外,Sealed secrets 使用 AES-256-GCM 等强 crypto,而 SOPS 使用 gpg 和 age。SOPS 提供与云提供商 KMS 的集成,而 SealedSecrets 目前还没有,但计划在未来实现集成(参见 这里)。 SOPS 不只可以对 Secrets 的值加密,还支持 yaml、json、env var 和二进制值加密,因此也可用于加密 helm chart。
不过,正如你所看到的,加密的数据一旦进入集群,就会在使用前被解密。因此,这基本上只解决了部分问题。接下来,我们需要看看如何在群集中保护这些数据的安全。让我们看看在集群上加密数据的不同选项。
加密 K8s 群集上的 Secrets
K8s 的 etcd 加密选项
默认情况下,K8s 容器平台不对 etcd 数据进行加密。但是原生 K8s, 以及一些 K8s 发行版,提供了启用基于 etcd 的加密选项。
以下是相关的一些参考文档:
- 原生 K8s: 静态加密机密数据 | Kubernetes
- OpenShift: Encrypting etcd data | Security and compliance | OpenShift Container Platform 4.13
- K3s: Secret 加密 | K3s
读者可以进一步阅读以了解详情。
使用 KMS 驱动进行数据加密
除了上面 etcd 的(静态)加密方案之外,原生 K8s 和一些 K8s 发行版也提供了基于 KMS 驱动进行(动态)数据加密的方案。
以下是相关的一些参考文档:
- 原生 K8s: 使用 KMS 驱动进行数据加密 | Kubernetes
- GKE: 在应用层对 Secret 加密 | Google Kubernetes Engine (GKE) | Google Cloud
- Amazon EKS: Enabling secret encryption on an existing cluster - Amazon EKS
- 使用阿里云 KMS 进行 Secret 的落盘加密 (alibabacloud.com)
公有云/私有云/数据中心磁盘加密选项
在 K8s 中使用 EBS 的公有云/私有云/数据中心节点级加密可以提供额外的加密层。这里以公有云为例说明:
AWS: 在 AWS 上托管 K8s 群集时,可以启用 Amazon EBS 加密,为 EC2 实例提供加密。Amazon EBS 加密在创建加密卷和快照时使用 AWS KMS 密钥。它使用 AES-256-XTS 进行块密码加密。 创建加密 EBS 卷并将其附加到支持的实例类型时,以下类型的数据将被加密:
- 加密卷内的静态数据
- 卷和实例之间移动的所有数据
- 从加密卷创建的所有快照
- 从这些快照创建的所有卷
Azure: 为连接到 Azure Key Vault 的 Azure Managed Disks 提供加密选项
Google 为 Google Cloud Storage 提供加密选项。两者默认都使用 AES 256 密钥,但也可以使用客户管理和提供的密钥,并与 KMS 集成。
使用第三方 Secrets 存储集成的 Secrets
选择第三方 Secrets 存储的一个重要原因是,通过集中式 Secrets 存储解决方案,确保在集群之外管理 Secrets 的生命周期。这些 Secrets 存储提供的身份验证和授权策略及程序与群集上的不同,也许更适合控制应用程序数据访问。这些解决方案大多还提供监管机构要求的信封加密和 HSM 支持。流行的解决方案包括 HashiCorp Vault、CyberArk Conjur、AWS Secret Store、Azure Key Vault、Google Secret Manager、1Password 等。
Sidecar 解决方案
Vault 等解决方案可用于注入应用程序 pod 的特定 Secrets。在这种情况下,sidecar/init 容器都负责对 Secret Provider 进行身份验证,然后应用程序可以在必要时使用返回的 Secrets。与 Provider 的连接是通过 TLS 进行的,以确保 Secrets 检索的安全性。Vault 通过使用 响应封装 提供额外的安全性,这使您可以在中间人无法看到凭证的情况下传递凭证。选择这些解决方案的客户可以决定将机密存储在集群上或集群外。通常情况下,如果客户一直使用 Vault 来满足其基础架构和其他应用需求,他们会倾向于与这些解决方案集成,以便在 K8s 上获得无缝的机密管理体验。
Secrets 存储 CSI(SSCSI)驱动程序和提供商解决方案
Secrets Store CSI 驱动程序允许将 Secrets 和其他敏感信息作为卷挂载到应用程序 pod 中。Secrets Store CSI 驱动程序使用 gRPC 与提供程序通信,以便从 SecretProviderClass 自定义资源中指定的外部 Secrets Store 中检索 Secrets 内容。一旦连接了卷,其中的数据就会加载到容器的文件系统中。与上述从特定提供商引入 Secrets 内容的 sidecar 解决方案不同,SSCSI 驱动程序可以配置为从多个不同的 Secret Provider 检索 Secrets 内容。有关驱动程序和提供商如何工作的更多信息,请参阅 此处。
不希望将秘密存储在 etcd 中作为 Kubernetes 秘密的客户主要会选择 SSCSI,原因如下
- 他们可能有严格的合规性要求,因此有必要仅在中央存储区而非集群中存储和管理机密。
- 他们可能会在控制平面不由他们管理的环境中引入工作负载,因此他们希望完全控制工作负载的机密,而不相信平台管理员能做到这一点。例如,客户将工作负载引入托管服务提供商集群的租户中,或者将工作负载引入控制平面不由其管理的云平台中。
SSCSI 驱动程序并不直接提供保护非卷标挂载机密的方法,例如那些需要作为环境变量或镜像拉取机密的 Secrets,或者那些你可能直接在群集上创建用于管理 Ingress 证书的 Secrets。不过,你可以使用 sync secrets 功能,它可以创建 Kubernetes Secrets,然后为作为 Env 变量的 Secret 提供支持。
External Secrets Operator (ESO)
External Secrets Operator (ESO)是一种用户友好型解决方案,用于将外部秘密管理解决方案中的秘密同步到 Kubernetes Secrets 中。 ESO 作为部署资源运行在 Kubernetes 集群中,利用自定义资源定义(CustomResourceDefinitions,CRD)通过 SecretStore 资源配置对 Secret Provider 的访问,并利用 ExternalSecret 资源管理 Kubernetes 秘密资源。
客户在以下情况下会选择 ESO:
- 他们需要与平台轻松集成,并便于开发人员使用
- 他们对集群的控制平面高度信任--尤其是在如何对 etcd 进行加密配置或如何在集群上管理 RBAC 方面
- 他们在机密管理方面有多集群用例,需要跨集群机密集成
- 他们需要为非应用程序使用管理平台 Secrets,例如用于 Ingress、自动化、图像拉取的机密
- 需要在集群上修改 Secrets,并为特定应用提供模板
- 最后,也是最重要的一点是,他们的用例需要集群上的 Secrets
将应用程序与 HSM (硬件安全模块) 集成
最高级别安全,将应用程序或 K8s 与 HSM (硬件安全模块) 集成。细节略。
总结
今天,我们了解 K8s 提供的各种加密选项,以及每种选项如何保护敏感数据,可以根据您的使用案例和实际情况做出明智的选择。
以下是笔者的一些个人建议, 仅供参考:
- 主要使用 AWS 的,可以根据安全级别选择:EBS 加密或 KMS 加密
- 在数据中心使用 K8s, 且有 K8s 集群外的 Secrets 需要管理的,推荐使用 Hashicorp Vault
- 在数据中心使用 K8s, 且只有 K8s Secrets 加密需求,那么 etcd 静态加密、ESO 都是可以考虑的选项
三人行, 必有我师; 知识共享, 天下为公. 本文由东风微鸣技术博客 EWhisper.cn 编写.
加密 K8s Secrets 的几种方案的更多相关文章
- Spring Boot 配置文件密码加密两种方案
Spring Boot 配置文件密码加密两种方案 jasypt 加解密 jasypt 是一个简单易用的加解密Java库,可以快速集成到 Spring 项目中.可以快速集成到 Spring Boot 项 ...
- GPRS组网的几种方案【来自网络】
GPRS组网的几种方案:1) 方案一:中心采用ADSL等INTELNET公网连接,采用公网固定IP或者公网动态IP+DNS解析服务.此种方案向先INTERNET运营商申请ADSL等宽带业务. ...
- 加密传输SSL协议4_综合方案
隔了那么多天终于有时间继续把这个专题做完了,这次一定连续写完这方面的笔记. 上篇博文说明了非对称加密和对称加密各自的优缺点,那么就很自然的衍生出了一种综合的方案. 两种方案的结合--扬长避短 首先发送 ...
- ArcGIS JavaScript API4.8 底图选择的几种方案
创建一个HTML页面,引入ArcGIS JavaScript API,在<body>标签内创建一个div并添加ID值,在<head>标签内设置样式<style>,在 ...
- SSO解决session共享的几种方案
之前做项目遇到了这个sso系统,当时只是理解了一部分,今天偶尔发现一篇文章,觉得写的不错,增加了sso知识: 单点登录在现在的系统架构中广泛存在,他将多个子系统的认证体系打通,实现了一个入口多处使用, ...
- 记录一次k8s环境尝试过程(初始方案,现在已经做过很多完善,例如普罗米修斯)
记录一次Team k8s环境搭建过程(初始方案,现在已经做过很多完善,例如普罗米修斯) span::selection, .CodeMirror-line > span > span::s ...
- 【Win 10 应用开发】文件读写的三种方案
本文老周就跟伙伴们探讨一下关于文件读写的方法.总得来说嘛,有三种方案可以用,而且每种方案都各有特色,也说不上哪种较好.反正你得记住老祖宗留给我们的大智慧——事无定法,灵活运用者为上. OK,咱们开始吧 ...
- 集合框架,ArrayList和Vector的区别,让arrayList线程安全的几种方案
boolean add(E e) 将指定的元素添加到此列表的尾部. void add(int index, E element) 将指定的元素插入此列表中的指定位置. boolean addAll(C ...
- javascript 网络是否连接的几种方案
js 网络是否连接的几种方案 1.通过html5的新属性: window.onload = function () { var isOnLine = navigator.on ...
- javascript把IP地址转为数值几种方案,来挑战一下效率吧
先看看什么是IP地址: IP地址是一个32位的二进制数,通常被分割为4个“8位二进制数”(也就是4个字节).IP地址通常用“点分十进制”表示成(a.b.c.d)的形式,其中,a,b,c,d都是0~25 ...
随机推荐
- Bash 编程
原文:https://seankross.com/the-unix-workbench/bash-programming.html[1] 数学 创建math.sh: #!/usr/bin/env ba ...
- STL-set(ACM)
1.set只能insert().erase(),没有push()等操作 2.插入的元素自动排序按从小到大的顺序排 3.不会插入相同的元素,已经插入了6,之后就不会再插入了 4.时间复杂度为 O(log ...
- 从源码级深入剖析Tomcat类加载原理
众所周知,Java中默认的类加载器是以父子关系存在的,实现了双亲委派机制进行类的加载,在前文中,我们提到了,双亲委派机制的设计是为了保证类的唯一性,这意味着在同一个JVM中是不能加载相同类库的不同版本 ...
- 记录部署Datax、Datax-web 过程碰到的问题
我的第一篇博客 datax在网络上部署的文档有很多,这里不重复阐述,只描述过程中碰到的些许问题,记录下来. 1. 1 ERROR RetryUtil - Exception when calling ...
- python 星号(*) 还能这么用
哈喽大家好,我是咸鱼 今天跟大家介绍一下 python 当中星号(*)的一些用法 首先大家最常见的就是在 python 中 * 是乘法运算符,实现乘法 sum = 5 * 5 # 25 除此之外,还有 ...
- rabbitmq安装部署和常用命令
python操作rabbitmq rabbitmq实现可以使用java或者springboot的封装方法,自己创建实现,也可以使用中间件实现,相对于自建,使用rabbitmq应用场景及使用更系统安全. ...
- React框架学习基础篇-HelloReact-01
一直想掌握一门前端技术,于是想跟着张天宇老师学习,便开始学习React,以此来记录一下我的学习之旅. 学习一门新的技术首先是去官网看看,React官网链接是[https://zh-hans.react ...
- 使用 nuxt3 开发简约优雅的个人 blog
起因 很早前我就有过搭建个人博客的想法,但是我希望使用纯前端实现,这样就不需要付出额外的后端维护成本,维护成本又低,而且更加安全.网上也有很多博客框架但是也不符合我的需求,所以我使用了nuxt3 + ...
- 在映客的虚拟KTV里唱了一首“爱你”
如果你突然打了个喷嚏 那一定就是我在想你 如果半夜被手机吵醒 啊~那是你的虚拟 KTV 在响起 2022 年 5 月 18 日,映客 App 上线了业内首个元宇宙 K 歌玩法「全景 K 歌」,给用 ...
- 【调制解调】PM 调相
说明 学习数字信号处理算法时整理的学习笔记.同系列文章目录可见 <DSP 学习之路>目录,代码已上传到 Github - ModulationAndDemodulation.本篇介绍 PM ...