【K8s】肿么办??Kubernetes Secrets并不是Secret哟!!
@TOC
推荐超级课程:
作为一个 Kubernetes 专家,你可能已经听过这个并不那么秘密的秘密很多次 — Kubernetes Secrets 并不加密! Secret 的值是在 etcd 中存储的 base64 编码 字符串。
这意味着任何能够访问您集群的人都可以轻松解码您的敏感数据。任何人?是的,几乎任何人都可以,特别是如果集群的 RBAC 配置不正确的话。任何人都可以访问 API 或访问 etcd。
也可能是任何有权限在命名空间内创建 pod 或部署的人,然后使用该权限检索该命名空间中的所有 Secrets。如何确保在构建、部署和运行 K8s 应用程序时,集群上的 Secrets 和其他敏感信息(如令牌)不被泄露?在本博客文章中,我们将讨论在构建、部署和运行应用程序时加密应用程序 Secrets 的几种方式。
Kubernetes Secrets
在 Kubernetes 集群上运行的应用程序可以使用 Kubernetes Secrets,这消除了在应用程序代码中存储敏感数据(如令牌或密码)的需求。
当前默认 Kubernetes 集群中 Secrets 的典型工作流程如下:
- 开发阶段:应用程序开发人员使用 CICD 并将 git 作为管理部署到集群的配置的真相源。访问控制有助于保护对存储库的访问,但仅凭此可能不足以确保应用程序的敏感信息不被暴露。
- 运维阶段:API 服务器在集群上创建 Kubernetes Secrets 资源。你可以在这里
了解更多有关 Secrets 生命周期的信息。存储在 etcd 中的 Secrets 可以通过应用程序 pod 的三种方式之一使用:
- 作为挂载为卷的文件 。
- 作为容器的环境变量 。
- 当拉取镜像时由 pod 的 kubelet 使用 。
在这三种情况下,密文中的值在使用前被解码。
现在我们知道它是如何工作的,为什么仅仅对密文进行 base64 编码还不够呢?
为什么不认为 Base64 编码是密文?
Base64 编码是一种二进制到文本的编码方案,它将 24 位的二进制数据表示为 6 位的 base64 数字。它被用于在网络上传输大量的数据,尤其是大文件,如图像文件。它的主要功能是 在网络传输过程中提供数据完整性 。明确一点,编码并非加密。
在任何 Linux 终端上尝试:
$ echo -n 'not encrypted' | base64
bm90IGVuY3J5cHRlZA==
$ echo -n 'bm90IGVuY3J5cHRlZA==' | base64 --decode
not encrypted
如上所示,任何可以访问您系统的人都可以轻松解码您的 Secrets,无论是它们在传输到集群时还是在集群上使用时。
问题出现了
作为一名 DevSecOps 管理员,显然你面临着两个挑战:
- 敏感数据在集群之外是如何加密和管理的,即在构建和部署阶段进入集群之前?
- 在集群内运行应用程序时,如何确保敏感数据安全?
以下是几种加密 K8s Secrets 的选项。
作为将代码推送到 git 存储库(也就是您应用程序的“真相源”)的开发人员,您可以在将代码推送到 git 存储库之前对应用程序使用的敏感信息进行加密。
以下是将Secrets加密并提交到 OpenShift 集群之前的两种常见方法:
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
创建一个键,将公钥和私钥存储在特定(例如)命名空间中- 自定义 Argo CD 使用 Kustomize SOPS 插件
- 将公钥推送到 Git 存储库
开发人员将:
- 在本地控制台中创建 Secret
- 使用 SOPS CLI 下载公钥并加密密文
- 使用加密 Secrets 生成 KSOPS yaml 并将其推送到 Git 存储库
ArgoCD 在部署 Secrets 到集群之前使用 KSOPS 解密Secrets文件。
以上两种方法都适用于使用非对称加密技术加密机密文件。二者在将敏感数据部署为 Secrets 到集群之前提供了解密敏感数据的方法。
Sealed secrets 与 Kubernetes 本机集成。SOPS / KSOPS 可独立运行,无需在集群上安装控制器。此外,Sealed secrets 使用强大的 加密 ,如 AES-256-GCM ,而 SOPS 使用 gpg 和 age 。
SOPS 不仅可以加密 Secrets 的值,还支持加密 yaml、json、env var 和二进制值,因此也可用于加密 helm charts。
然而,正如你所看到的,一旦加密数据进入集群,它在使用前就会被解密。因此,这基本上只解决了问题的一部分。接下来,我们需要看看如何在集群中保护这些数据。让我们看看在集群上加密数据的不同选项。
K8s 的 etcd 加密选项
默认情况下,K8s 容器平台不加密 etcd 数据。但原生 K8s,以及一些 K8s 发行版,提供了启用基于 etcd 的数据加密的选项。
以下是一些相关的参考文档:
- 原生 K8s:[在静态|https://kubernetes.io/docs/tasks/administer-cluster/encrypt-data/)
- OpenShift:加密 etcd 数据 | 安全性和合规性 | OpenShift 容器平台 4.13
- K3s:Secret 加密 | K3s
读者可以进一步阅读以了解更多。
使用 KMS 驱动程序进行数据加密
除了上述基于 etcd(静态)的加密方案,原生 K8s 和一些 K8s 发行版还提供基于 KMS 驱动程序的(动态)数据加密方案。
以下是一些相关的参考文档:
- 原生 K8s:使用 KMS 驱动程序进行数据加密 | Kubernetes
- GKE:在应用程序层加密 Secrets | Google Kubernetes Engine(GKE)| Google Cloud
- Amazon EKS:在现有集群上启用密钥加密 - Amazon EKS
公共云/私有云/数据中心磁盘加密选项
在 K8s 中使用 EBS 的公共云/私有云/数据中心节点级加密可以提供额外的加密层。这里以公共云为例:
- 所有数据位于加密卷中的数据。
- 所有移动到卷和实例之间的数据。
- 所有从加密卷创建的快照。
- 从这些快照创建的所有卷。
- Azure:提供Azure 管理磁盘的 连接到 Azure Key Vault 的加密选项
- Google 为Google 云存储 提供加密选项。两者默认使用 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 容器负责向密钥提供程序进行身份验证,若应用程序需要,则可以使用返回的 Secrets。连接到提供器是通过 TLS 确保 Secrets 检索的安全性。
选择这些解决方案的客户可以决定在集群内或外存储 Secrets。通常情况下,如果客户一直在为他们的基础设施和其他应用程序需求使用 Vault,他们往往会倾向于与这些解决方案集成,以便在 K8s 上实现无缝的 Secrets 管理体验。
Secrets 存储 CSI(SSCSI)驱动程序和提供程序解决方案
Secrets 存储 CSI 驱动程序允许将 Secrets 和其他敏感信息作为卷挂载到应用程序 pod 中。Secrets 存储 CSI 驱动程序使用 gRPC 与提供程序通信,以从 SecretProviderClass 自定义资源指定的外部 Secrets 存储中检索 Secrets 内容。一旦卷被附加,其中的数据将加载到容器的文件系统中。
与上面描述的旁路方案不同,后者从特定提供程序中拉取 Secrets 内容,SSCSI 驱动程序可以配置以从多个不同的 Secret 提供者检索 Secrets 内容。有关驱动程序和提供程序如何工作的更多信息,请参阅此处 。
不想将 Secrets 存储在 etcd 中作为 Kubernetes Secrets 的客户主要会选择 SSCSI,原因如下:
- 他们可能有严格的合规要求,因此有必要仅存储和管理中央存储中的 Secrets,而不是在集群中。
- 他们可能会将工作负载引入一个由他们管理的控制平面不管理的环境中,因此他们希望完全控制工作负载的机密性,并不信任平台管理员来做到这一点。例如,客户将工作负载带到托管提供商集群的租户中,或将工作负载带入其控制平面不由它们管理的云平台。
- SSCSI 驱动程序没有直接提供保护非卷挂载的 Secrets 内容的方法,例如那些需要作为环境变量或图像拉取的内容,或者您可能直接在集群上创建以管理入口证书的内容。但是,您可以使用同步 Secrets 功能,创建 Kubernetes Secrets,然后提供对 Secrets 作为 Env 变量的支持。
外部Secrets Operator(ESO)
External Secrets Operator(ESO)是一个用户友好的解决方案,用于将外部Secrets管理解决方案中的Secrets同步到Kubernetes Secrets中。ESO作为一个部署资源在Kubernetes集群中运行,通过自定义资源定义(CRD)配置通过SecretStore资源访问Secrets提供者,并使用ExternalSecret资源管理KubernetesSecrets资源。
在以下情况下,客户将选择ESO:
- 他们轻松集成平台,并且易于开发人员使用
- 他们对集群的控制平面有很高的信任度 — 尤其是关于如何加密etcd或如何管理集群上的RBAC的配置。
- 他们有一个需要跨集群Secrets集成的多集群用例
- 他们需要为非应用程序使用管理平台Secrets,比如Ingress、自动化、镜像拉取的Secrets
- Secrets需要在集群上进行修改,并为特定应用程序提供模板
- 最重要的是,他们的用例需要在集群上的Secrets
最高级别的安全性,集成应用程序或K8s与HSM(硬件安全模块)。详细信息已省略。
结语
今天,我们将探讨K8s提供的各种加密选项以及每个选项如何保护敏感数据,以便您根据您的用例和现实做出明智选择。
以下是一些建议,仅供参考:
- 主要使用AWS,可以根据安全级别选择:EBS加密或KMS加密
- 如果在数据中心使用K8s,并且需要管理在K8s集群外的Secrets,则建议使用Hashicorp Vault。
- 如果在数据中心使用K8s,只需要K8s Secrets加密,则etcd静态加密和ESO是可以考虑的选项。