引言
Kubernetes 已经成为现代软件基础设施中不可或缺的一部分。因此,管理 Kubernetes 上的敏感数据也是现代软件工程的一个重要方面,这样您就可以将安全性重新置于 DevSecOps 中。Kubernetes 提供了一种使用 Secret
对象存储敏感数据的方法。虽然总比没有好,但它并不是真正的加密,因为它只是 base64 编码的字符串,任何有权访问集群或代码的人都可以对其进行解码。
注意:默认情况下,Kubernetes Secrets 未加密存储在 API 服务器的底层数据存储 (etcd) 中。具有 API 访问权限的任何人都可以检索或修改 Secret,任何具有 etcd 访问权限的人也可以。此外,任何有权在命名空间中创建 Pod 的人都可以使用该访问权限来读取该命名空间中的任何 Secret;这包括间接访问,例如创建 Deployment 的能力。— Kubernetes 文档
使用正确的 RBAC 配置和保护 API 服务器可以解决从集群读取 secret 的问题,了解有关 RBAC 和集群 API 安全性的更多信息请查看如何使用最佳实践保护您的 Kubernetes 集群。保护源代码中的的 secret 是更大的问题。每个有权访问包含这些 secret 的存储库的人也可以解码它们。这使得在 Git 中管理 Kubernetes secret 变得非常棘手。
让我们看看如何使用更安全的方式设置 secret :
Sealed Secrets
External Secrets Operator
Secrets Store CSI driver
您需要一个 Kubernetes 集群来运行示例。我使用 k3d 创建了一个本地集群。您也可以使用 kind 或 minikube 。
Sealed Secrets
Sealed Secrets
是一个开源的 Kubernetes 控制器和来自 Bitnami 的客户端 CLI 工具,旨在使用非对称密码加密解决“在 Git 中存储 secret ”问题的一部分。具有 RBAC 配置的 Sealed Secrets 防止非管理员读取 secret 是解决整个问题的绝佳解决方案。
Sealed Secrets
它的工作原理如下:
- 使用公钥和
kubeseal
CLI 在开发人员机器上加密 secret 。这会将加密的 secret 编码为 Kubernetes 自定义资源定义 (CRD)。 - 将 CRD 部署到目标集群。
Sealed Secret
控制器使用目标集群上的私钥对机密进行解密,以生成标准的 Kubernetes secret。
私钥仅供集群上的 Sealed Secrets 控制器使用,公钥可供开发人员使用。这样,只有集群才能解密机密,而开发人员只能对其进行加密。
优点
- 支持模板定义,以便可以将元数据添加到未加密的 secret 中。例如,您可以使用模板定义为未加密的 secret 添加标签和注释。
- 未加密的 secret 将由加密的 secret CRD 拥有,并在加密的 secret 更新时更新。
- 默认情况下,证书每 30 天轮换一次,并且可以自定义。
- secret 使用每个集群、命名空间和 secret 组合(私钥+命名空间名称+ secret 名称)的唯一密钥进行加密,防止解密中出现任何漏洞。在加密过程中,可以使用
strict
,namespace-wide
,cluster-wide
来配置范围。 - 可用于管理集群中的现有 secret。
- 具有 VSCode 扩展,使其更易于使用。
缺点
- 由于它将加密的 secret 解密为常规 secret ,如果您有权访问集群和命名空间,您仍然可以解码它们。
- 需要为每个集群环境重新加密,因为密钥对对于每个集群都是唯一的。
安装
在集群上安装 controller,在本地机器上安装 CLI。
- 从 release 页面下载
controller.yaml
。 - 执行
kubectl apply -f controller.yaml
将 controller 部署到集群中。控制器将安装到kube-system
命名空间下。 - 安装 CLI,通过
brew install kubeseal
安装,或者从 release 页面下载。
使用
让我们创建一个 sealed secret 。
- 创建一个 secret,通过命令
kubectl create secret
或者编写 yaml 文件,如下所示:
echo -n secretvalue | kubectl create secret generic mysecret \ --dry-run=client \ --from-file=foo=/dev/stdin -o yaml > my-secret.yaml
这将产生一个如下所示的 secret 定义;
# my-secret.yaml apiVersion: v1 data: foo: c2VjcmV0dmFsdWU= kind: Secret metadata: creationTimestamp: null name: mysecret
- 使用
kubeseal
CLI 加密 secret。这将使用从服务器获取的公钥加密 secret 并生成加密的 secret 定义。现在可以丢弃 my-secret.yaml 文件。您也可以下载公钥并在本地离线使用。
kubeseal --format yaml < my-secret.yaml > my-sealed-secret.yaml
这将产生一个加密的 secret 定义,my-sealed-secret.yaml,如下所示;
# my-sealed-secret.yaml apiVersion: bitnami.com/v1alpha1 kind: SealedSecret metadata: creationTimestamp: null name: mysecret namespace: default spec: encryptedData: foo: AgA6a4AGzd7qzR8mTPqTPFNor8tTtT5...== template: metadata: creationTimestamp: null name: mysecret namespace: default
此文件可以安全地提交到 Git 或与其他开发人员共享。
- 最后,您可以将其部署到要解封的集群中。
kubectl apply -f my-sealed-secret.yaml
- 现在,您可以在集群中看到未加密的 secret 。
kubectl describe secret mysecret
您可以像使用任何其他 Kubernetes 密钥一样在部署中使用此密钥。
External Secrets Operator
Sealed Secrets 是保护 secret 的方式之一,但除此之外还有更好的方法。使用 External Secrets Operator (ESO) 和外部 secret 管理系统,如 HashiCorp Vault、AWS Secrets Manager、Google Secrets Manager 或 Azure Key Vault。虽然设置起来有点复杂,但如果您使用云提供商来托管您的 Kubernetes 集群,这是一种更好的方法。ESO 支持许多这样的 secret 管理器并监视外部 secret 存储的变化,并使 Kubernetes secret 保持同步。
ESO
ESO 提供了四个 CRD 来管理 secret。ExternalSecret
和 ClusterExternalSecret
CRD 定义需要获取哪些数据以及如何转换这些数据。SecretStore
和 ClusterSecretStore
CRD 定义了与外部 secret 存储的连接细节。Cluster
前缀的 CRD 表示作用范围是集群。
它的工作原理如下;
- 创建
SecretStoreCRD
以定义与外部机密存储的连接详细信息。 - 在外部 secret 存储中创建 secret 。
- 创建一个
ExternalSecretCRD
来定义需要从外部 secret 存储中获取的数据。 - 将 CRD 部署到目标集群。
- ESO 控制器将从外部 secret 存储中获取数据并创建 Kubernetes secret 。
优点
- secret 存储在安全的外部 secret 管理器中,而不是代码存储库中。
- 使 secret 与外部 secret 管理器保持同步。
- 与许多外部 secret 管理者合作。
- 可以在同一个集群中使用多个 secret 存储。
- 提供用于监控的 Prometheus 指标。
缺点
- 需要精心设置才能使用。
- 创建一个 Kubernetes secret 对象,如果您有权访问集群和命名空间,则可以对其进行解码。
- 依靠外部 secret 管理器及其访问策略来确保安全。
安装
可以使用以下命令通过 Helm 安装 ESO :
helm repo add external-secrets https://charts.external-secrets.io helm install external-secrets \ external-secrets/external-secrets \ --namespace external-secrets \ --create-namespace
如果您想在 Helm release 中包含 ESO,请将 --set installCRDs=true
标志添加到上述命令中。
让我们看看如何将 ESO 与不同的 secret 管理器一起使用。