问题: “我可以在 git 中管理所有 K8s 配置,除了 Secrets。”
解决方案:将您的 Secret 加密到 SealedSecret 中,即使在公共存储库中也可以安全存储。 SealedSecret 只能由目标集群中运行的控制器解密,其他人(甚至原作者)都无法从 SealedSecret 中获取原始 Secret。
概述
SealedSecrets 作为秘密的模板
公钥/证书
范围
安装
自制
Mac端口
Linux
从源安装
定制化
舵图
控制器
库贝密封
升级
用法
管理现有秘密
修补现有秘密
更新现有机密
原始模式(实验)
验证密封的秘密
秘密轮换
密封钥匙更新
用户秘密轮换
提前更新密钥
关于密钥更新的常见误解
手动密钥管理(高级)
重新加密(高级)
详细信息(高级)
加密货币
发展
常问问题
如果您无法再访问集群,您仍然能够解密吗?
我如何备份我的 SealedSecrets?
我可以使用备份密钥离线解密我的秘密吗?
kubeseal 有哪些可用标志?
如何更新使用密封秘密加密的 JSON/YAML/TOML/.. 文件的部分内容?
我可以携带自己的(预先生成的)证书吗?
如果控制器不在kube-system
命名空间内运行,如何使用 kubeseal?
如何验证图像?
如何将一个控制器用于命名空间的子集
我可以配置控制器开封重试吗
社区
相关项目
密封的秘密由两部分组成:
集群端控制器/操作员
客户端实用程序: kubeseal
kubeseal
实用程序使用非对称加密来加密只有控制器才能解密的秘密。
这些加密的机密被编码在SealedSecret
资源中,您可以将其视为创建机密的秘诀。它看起来是这样的:
api版本:bitnami.com/v1alpha1kind:SealedSecretmetadata:名称:mysecret命名空间:mynamespacespec:加密数据:foo:AgBy3i4OJSWK + PiTySYZZA9rO43cGDEq.....
一旦解封,这将产生一个与此等效的秘密:
apiVersion: v1kind: Secretmetadata: name: mysecret 命名空间: mynamespacedata: foo: YmFy # <- base64 编码的“bar”
几秒钟后,这个正常的 kubernetes 密钥将出现在集群中,您可以像使用直接创建的任何密钥一样使用它(例如,从Pod
引用它)。
跳转到安装部分以启动并运行。
使用部分更详细地探讨了如何制作SealedSecret
资源。
前面的示例仅关注加密的秘密项目本身,但SealedSecret
自定义资源与其解封到的Secret
之间的关系在很多方面(但不是全部)与熟悉的Deployment
与Pod
类似。
特别是, SealedSecret
资源的注释和标签与从中生成的Secret
的注释不同。
为了捕捉这种区别, SealedSecret
对象有一个template
部分,它对您希望控制器放入未密封Secret
中的所有字段进行编码。
除了默认的 Go 文本模板函数之外,还可以使用 Sprig 函数库。
metadata
块按原样复制( ownerReference
字段将更新,除非禁用)。
其他秘密字段单独处理。复制type
和immutable
字段,并且data
字段可用于在Secret
上模板化复杂值。目前忽略所有其他字段。
apiVersion:bitnami.com/v1alpha1kind:SealedSecretmetadata:名称:mysecret 命名空间:mynamespace 注释:“kubectl.kubernetes.io/last-applied-configuration”:....spec:加密数据:.dockerconfigjson:AgBy3i4OJSWK+PiTySYZZA9rO43cGDEq .... . template: type: kubernetes.io/dockerconfigjson immutable: true # 这是将添加到输出秘密元数据中的标签和注释的示例: labels: "jenkins.io/credentials-type": usernamePassword comments: "jenkins. io/credentials-description":来自 Kubernetes 的凭证
控制器会将其解封为如下内容:
apiVersion:v1kind:Secretmetadata:名称:mysecret 命名空间:mynamespace 标签:“jenkins.io/credentials-type”:用户名密码注释:“jenkins.io/credentials-description”:来自 Kubernetes 所有者的凭据参考: - api版本:bitnami.com/v1alpha1 控制器:真实种类:SealedSecret 名称:mysecret uid:5caff6a0-c9ac-11e9-881e-42010aac003etype:kubernetes.io/dockerconfigjsonimmutable:truedata:.dockerconfigjson:ewogICJjcmVk ...
正如您所看到的,生成的Secret
资源是SealedSecret
的“依赖对象”,因此每当SealedSecret
对象更新或删除时,它都会被更新和删除。
密钥证书(公钥部分)用于密封秘密,并且在任何要使用kubeseal
的地方都需要可用。该证书不是秘密信息,但您需要确保使用正确的证书。
kubeseal
会在运行时从控制器获取证书(需要安全访问 Kubernetes API 服务器),这方便交互使用,但众所周知,当用户拥有具有特殊配置的集群(例如之间有防火墙的私有 GKE 集群)时,它会很脆弱。控制平面和节点。
另一种工作流程是使用kubeseal --fetch-cert >mycert.pem
将证书存储在某处(例如本地磁盘),并使用kubeseal --cert mycert.pem
离线使用它。该证书还会在启动时打印到控制器日志中。
自 v0.9.x 起,证书每 30 天自动更新一次。您和您的团队定期更新离线证书是一个很好的做法。为了帮助您解决这个问题,从 v0.9.2 开始, kubeseal
也接受 URL。您可以设置内部自动化以在您信任的地方发布证书。
kubeseal --cert https://your.intranet.company.com/sealed-secrets/your-cluster.cert
它还可以识别SEALED_SECRETS_CERT
环境变量。 (专业提示:另请参阅 direnv)。
注意:我们正在致力于提供密钥管理机制,将加密卸载到基于 HSM 的模块或托管云加密解决方案(例如 KMS)。
SealedSecrets 是来自最终用户的 POV 的“只写”设备。
这个想法是,SealedSecret 只能由目标集群中运行的控制器解密,其他人(甚至原作者)都无法从 SealedSecret 中获取原始 Secret。
用户可能有也可能没有直接访问目标集群的权限。更具体地说,用户可能有权也可能无权访问由控制器解封的 Secret。
在 k8s 上配置 RBAC 的方法有很多种,但禁止低权限用户读取 Secrets 是很常见的。为用户提供一个或多个具有更高权限的命名空间也很常见,这将允许他们创建和读取机密(和/或创建可以引用这些机密的部署)。
加密的SealedSecret
资源旨在安全地查看,而无需了解其隐藏的秘密。这意味着我们不能允许用户读取用于他们无权访问的命名空间的 SealedSecret,而只是将其副本推送到他们可以从中读取机密的命名空间中。
因此,密封秘密的行为就像每个命名空间都有自己独立的加密密钥一样,因此一旦您密封了命名空间的秘密,它就无法移动到另一个命名空间并在那里解密。
从技术上讲,我们并没有为每个命名空间使用独立的私钥,而是在加密过程中包含命名空间名称,从而有效地达到相同的结果。
此外,命名空间并不是 RBAC 配置可以决定谁可以看到哪个秘密的唯一级别。事实上,用户可以访问给定名称空间中名为foo
的机密,但不能访问同一名称空间中的任何其他机密。因此,默认情况下,我们不能让用户自由重命名SealedSecret
资源,否则恶意用户只需重命名该名称空间以覆盖用户有权访问的一个秘密,就能够解密该命名空间的任何 SealedSecret。我们使用与在加密密钥中包含命名空间相同的机制来包含秘密名称。
也就是说,在很多情况下您可能不关心这种级别的保护。例如,唯一有权访问集群的人要么是管理员,要么根本无法读取任何Secret
资源。您可能有一个将密封秘密移动到其他命名空间的用例(例如,您可能不知道预先命名空间名称),或者您可能不知道秘密的名称(例如,它可能包含基于该秘密的哈希值的唯一后缀)内容等)。
这些是可能的范围:
strict
(默认):秘密必须使用完全相同的名称和名称空间进行密封。这些属性成为加密数据的一部分,因此更改名称和/或命名空间将导致“解密错误”。
namespace-wide
:您可以在给定命名空间内自由重命名密封的秘密。
cluster-wide
:秘密可以在任何名称空间中解封,并且可以指定任何名称。
与name和namespace的限制相反,秘密项(即 JSON 对象密钥,如spec.encryptedData.my-key
)可以随意重命名,而不会失去解密密封秘密的能力。
使用--scope
标志选择范围:
kubeseal --scope 集群范围sealed-secret.json
还可以通过传递给kubeseal
输入密钥中的注释来请求范围:
sealedsecrets.bitnami.com/namespace-wide: "true"
-> 用于namespace-wide
sealedsecrets.bitnami.com/cluster-wide: "true"
-> 适用于cluster-wide
缺少任何此类注释都意味着strict
模式。如果两者都设置,则cluster-wide
优先。
注意:下一个版本将把它合并到一个单一的
sealedsecrets.bitnami.com/scope
注释中。
请参阅 https://github.com/bitnami-labs/sealed-secrets/releases 了解最新版本和详细安装说明。
云平台具体注意事项及说明:
吉凯
部署清单后,它将创建SealedSecret
资源并将控制器安装到kube-system
命名空间中,创建服务帐户和必要的 RBAC 角色。
片刻之后,控制器将启动,生成密钥对,并准备好运行。如果没有,请检查控制器日志。
官方控制器清单安装机制只是一个 YAML 文件。
在某些情况下,您可能需要应用自己的自定义设置,例如设置自定义命名空间或设置一些环境变量。
kubectl
对此有原生支持,请参阅 kustomize。
Sealed Secrets helm 图表现已正式支持并托管在此 GitHub 存储库中。
helm 仓库添加密封秘密 https://bitnami-labs.github.io/sealed-secrets
注意:Helm Chart 的版本控制方案与密封秘密项目本身的版本控制方案不同。
最初 Helm Chart 是由社区维护的,第一个版本采用了主要版本 1,而 Sealed Secrets 项目本身仍然是主要版本 0。这没关系,因为 Helm Chart 本身的版本并不一定是版本应用程序本身。然而这很令人困惑,所以我们当前的版本控制规则是:
SealedSecret
控制器版本方案:0.XY
helm图表版本方案:1.XY-rZ
因此,Helm Chart 可以有多个修订版,其中的修复仅适用于 Helm Chart,而不影响静态 YAML 清单或控制器映像本身。
注意:Helm Chart 自述文件仍然包含弃用通知,但它不再反映现实,并将在下一个版本中删除。
注意:Helm Chart 默认情况下安装名为
sealed-secrets
控制器,而kubeseal
命令行界面 (CLI) 尝试访问名为sealed-secrets-controller
控制器。您可以显式地将--controller-name
传递给 CLI:
kubeseal --控制器名称密封秘密
或者,您可以在安装图表时设置fullnameOverride
以覆盖名称。另请注意, kubeseal
假定控制器默认安装在kube-system
命名空间内。因此,如果您想使用kubeseal
CLI 而无需传递预期的控制器名称和命名空间,您应该像这样安装 Helm Chart:
helm install sealed-secrets -n kube-system --set-string fullnameOverride=sealed-secrets-controller sealed-secrets/sealed-secrets
在某些公司中,您可能只能访问单个名称空间,而不是完整的集群。
您可能遇到的最严格的环境之一是:
已使用某个service account
为您分配了一个namespace
。
您无权访问集群的其余部分,甚至无法访问集群 CRD。
您甚至可能无法在命名空间中创建更多服务帐户或角色。
您需要在所有部署中包含资源限制。
即使有这些限制,您仍然可以安装密封的 Helm Chart,只有一个先决条件:
集群必须已经安装了密封的机密 CRD 。
一旦您的管理员安装了 CRD(如果它们尚不存在),您可以通过准备 YAML 配置文件来安装图表,如下所示:
服务帐号: 创建:假 名称:{分配的服务帐户} RBAC: 创建:假 clusterRole:错误资源: 限制: 中央处理器:150m 内存:256Mi
注意:
不会创建服务帐户,而是使用分配给您的服务帐户。
{allocated-service-account}
是您在集群上分配的service account
的名称。
命名空间和集群中都不会创建 RBAC 角色。
必须指定资源限制。
这些限制是应该有效的示例,但您可能需要在特定设置中查看它们。
该文件准备好后,如果将其命名为config.yaml
您现在可以安装密封的机密 Helm Chart,如下所示:
helm install seal-secrets -n {分配的命名空间} sealed-secrets/sealed-secrets --skip-crds -f config.yaml
其中{allocated-namespace}
是您在集群中分配的namespace
空间的名称。
kubeseal
客户端也可在自制软件上使用:
酿造安装 kubeseal
kubeseal
客户端也可在 MacPorts 上使用:
端口安装 kubeseal
Nixpkgs 上也提供了kubeseal
客户端:(免责声明:不是由 bitnami-labs 维护)
nix-env -iA nixpkgs.kubeseal
可以使用以下命令在 Linux 上安装kubeseal
客户端:
KUBESEAL_VERSION='' # 将其设置为,例如 KUBESEAL_VERSION='0.23.0'curl -OL "https://github.com/bitnami-labs/sealed-secrets/releases/download/v${KUBESEAL_VERSION:?} /kubeseal-${KUBESEAL_VERSION:?}-linux-amd64.tar.gz"tar -xvzf kubeseal-${KUBESEAL_VERSION:?}-linux-amd64.tar.gz kubeseal sudo install -m 755 kubeseal /usr/local/bin/kubeseal
如果您的计算机上安装了curl
和jq
,则可以通过这种方式动态获取版本。这对于自动化等使用的环境非常有用。
# Fetch the latest sealed-secrets version using GitHub API KUBESEAL_VERSION=$(curl -s https://api.github.com/repos/bitnami-labs/sealed-secrets/tags | jq -r '.[0].name' | cut -c 2-) # Check if the version was fetched successfully if [ -z "$KUBESEAL_VERSION" ]; then echo "Failed to fetch the latest KUBESEAL_VERSION" exit 1 fi curl -OL "https://github.com/bitnami-labs/sealed-secrets/releases/download/v${KUBESEAL_VERSION}/kubeseal-${KUBESEAL_VERSION}-linux-amd64.tar.gz" tar -xvzf kubeseal-${KUBESEAL_VERSION}-linux-amd64.tar.gz kubeseal sudo install -m 755 kubeseal /usr/local/bin/kubeseal
其中KUBESEAL_VERSION
是您要使用的 kubeseal 版本的版本标记。例如: v0.18.0
。
如果您只需要最新的客户端工具,可以使用以下命令将其安装到$GOPATH/bin
中:
去安装 github.com/bitnami-labs/sealed-secrets/cmd/kubeseal@main
您可以指定发布标签或提交 SHA 而不是main
。
go install
命令会将kubeseal
二进制文件放置在$GOPATH/bin
:
$(go env GOPATH)/bin/kubeseal
升级客户端工具和/或控制器时,不要忘记查看发行说明,以获取有关可能发生的重大更改的指导。
目前,生产环境仅支持最新版本的 Sealed Secrets。
Sealed Secrets 控制器依靠稳定的 Kubernetes API 来保证与不同版本 Kubernetes 的兼容性。通常,1.16 以上的 Kubernetes 版本被认为是兼容的。但是,我们官方支持当前推荐的 Kubernetes 版本。此外,1.24 以上的版本在每个版本中都会通过我们的 CI 流程进行彻底验证。
# 以某种方式创建一个 json/yaml 编码的 Secret:# (注意使用 `--dry-run` - 这只是一个本地文件!)echo -n bar | kubectl create Secret generic mysecret --dry-run=client --from-file=foo=/dev/stdin -o json >mysecret.json# 这是重要的一点:kubeseal -f mysecret.json -w mysealedsecret.json#此时 mysealedsecret.json 可以安全地上传到 Github,# 在 Twitter 上发布,等等。# 最终:kubectl create -f mysealedsecret.json# 利润!kubectl 获取秘密 mysecret
请注意, SealedSecret
和Secret
必须具有相同的命名空间和名称。此功能可防止同一集群上的其他用户重复使用您的密封机密。有关详细信息,请参阅范围部分。
kubeseal
从输入密钥中读取命名空间,接受显式的--namespace
参数,并使用kubectl
默认命名空间(按该顺序)。原始Secret
上的任何标签、注释等都会保留,但不会自动反映在SealedSecret
中。
根据设计,该方案不对用户进行身份验证。换句话说,任何人都可以创建一个包含他们喜欢的任何Secret
SealedSecret
(只要命名空间/名称匹配)。这取决于您现有的配置管理工作流程、集群 RBAC 规则等,以确保仅将预期的SealedSecret
上传到集群。与现有 Kubernetes 的唯一变化是Secret
的内容现在在集群外部隐藏。
如果您希望 Sealed Secrets 控制器管理现有Secret
,您可以使用sealedsecrets.bitnami.com/managed: "true"
注释来注释您的Secret
。当解封具有相同名称和命名空间的SealedSecret
时,现有的Secret
将被覆盖,并且SealedSecret
将获得该Secret
的所有权(因此,当删除SealedSecret
时,该Secret
也会被删除)。
v0.23.0 中的新功能
在某些用例中,您不想替换整个Secret
,而只想添加或修改现有Secret
中的一些密钥。为此,您可以使用sealedsecrets.bitnami.com/patch: "true"
注释您的Secret
。使用此注释将确保Secret
中不存在于SealedSecret
中的密钥、标签和注释不会被删除,并且那些存在于SealedSecret
中的将被添加到Secret
中(存在的密钥、标签和注释) Secret
和SealedSecret
中的内容都会被SealedSecret
修改)。
此注释不会使SealedSecret
获得Secret
的所有权。您可以添加patch
和managed
注释以获得补丁行为,同时还获得Secret
的所有权。
如果您希望SealedSecret
和Secret
是独立的,这意味着当您删除SealedSecret
时Secret
不会随之消失,那么您必须使用注释sealedsecrets.bitnami.com/skip-set-owner-references: "true"
来注释该 Secret sealedsecrets.bitnami.com/skip-set-owner-references: "true"
。您还可以将sealedsecrets.bitnami.com/managed: "true"
添加到您的Secret
中,以便在SealedSecret
更新时更新您的 Secret。
如果您想添加或更新现有的密封秘密,而没有其他项目的明文,您只需复制并粘贴新的加密数据项目并将其合并到现有的密封秘密中。
您必须注意使用兼容的名称和命名空间密封更新的项目(请参阅上面有关范围的注释)。
如果您不想复制和粘贴,可以使用--merge-into
命令更新现有的密封机密:
回声 -n 酒吧 | kubectl 创建秘密通用 mysecret --dry-run=client --from-file=foo=/dev/stdin -o json | kubeseal > mysealedsecret.jsonecho -n baz | kubeseal > mysealedsecret.jsonecho -n baz | kubectl 创建秘密通用 mysecret --dry-run=client --from-file=bar=/dev/stdin -o json | kubeseal --merge-into mysealedsecret.json
使用kubectl
命令创建临时 Secret,然后在通过管道传输到kubeseal
后将其丢弃,这可能是一种非常不友好的用户体验。我们正在对 CLI 体验进行彻底改革。与此同时,我们提供了另一种模式,其中 kubeseal 只关心将值加密到标准输出,并且您有责任将其放入SealedSecret
资源中(与任何其他 k8s 资源不同)。
它还可以用作编辑器/IDE 集成的构建块。
缺点是您必须小心与密封范围、命名空间和名称保持一致。
查看范围
strict
范围(默认):
$ echo -n foo | 回声kubeseal --raw --namespace bar --name mysecretAgBChHUWLMx...
namespace-wide
范围:
$ echo -n foo | 回声kubeseal --raw --namespace bar --scope 命名空间-wideAgAbbFNkM54...
在SealedSecret
中包含sealedsecrets.bitnami.com/namespace-wide
注释
元数据:注释:sealedsecrets.bitnami.com/namespace-wide:“true”
cluster-wide
范围:
$ echo -n foo | 回声kubeseal --raw --scope 集群范围AgAjLKpIYV+...
在SealedSecret
中包含sealedsecrets.bitnami.com/cluster-wide
注释
元数据:注释:sealedsecrets.bitnami.com/cluster-wide:“true”
如果您想验证现有的密封秘密, kubeseal
有标志--validate
来帮助您。
提供一个名为sealed-secrets.yaml
的文件,其中包含以下密封秘密:
api版本:bitnami.com/v1alpha1kind:SealedSecretmetadata:名称:mysecret命名空间:mynamespacespec:加密数据:foo:AgBy3i4OJSWK + PiTySYZZA9rO43cGDEq.....
您可以验证密封的秘密是否已正确创建:
$ cat seal-secrets.yaml | kubeseal --验证
如果密封秘密无效, kubeseal
将显示:
$ cat seal-secrets.yaml | kubeseal --validateerror:无法解密密封的秘密
你应该经常轮换你的秘密。但由于您的秘密是用另一个秘密加密的,因此您需要了解这两层如何关联才能做出正确的决定。
长话短说:
如果密封私钥被泄露,您需要按照“早期密钥更新”部分中的说明进行操作,然后再旋转任何实际的秘密值。
SealedSecret 密钥更新和重新加密功能不能替代实际秘密值的定期轮换。
密封密钥每 30 天自动更新一次。这意味着将创建一个新的密封密钥并将其附加到控制器可用于解封SealedSecret
资源的活动密封密钥集。
最近创建的密封密钥是在您使用kubeseal
时用于密封新秘密的密钥,也是在您使用kubeseal --fetch-cert
时下载证书的密钥。
30 天的续订时间是一个合理的默认值,但可以根据需要使用SealedSecret
控制器的 pod 模板中的命令的--key-renew-period=
标志进行调整。 value
字段可以作为 golang 持续时间标志给出(例如: 720h30m
)。假设您已将 Sealed Secrets 安装到kube-system
命名空间中,请使用以下命令编辑 Deployment 控制器,并添加--key-renew-period
参数。关闭文本编辑器并且 Deployment 控制器已被修改后,将自动创建一个新的 Pod 来替换旧的 Pod。
kubectl edit deployment/sealed-secrets-controller --namespace=kube-system
值为0
将停用自动密钥更新。当然,您可能有一个有效的用例来停用自动密封密钥更新,但经验表明,新用户在完全理解密封秘密的工作原理之前,往往倾向于得出他们想要控制密钥更新的结论。请在下面的常见误解部分了解更多相关信息。
不幸的是,您不能使用例如“d”作为几天的单位,因为 Go stdlib 不支持它。不要用手掌打你的脸,而是以此为契机思考程序员所相信的关于时间的谎言。
一个常见的误解是,密钥更新通常被认为是密钥轮换的一种形式,其中旧密钥不仅过时而且实际上很糟糕,因此您想摆脱它。此功能历来被称为“密钥轮换”,这并没有帮助,这会增加混乱。
生成新密钥时,密封的秘密不会自动轮换,旧密钥也不会被删除。旧的SealedSecret
资源仍然可以解密(这是因为旧的密封密钥不会被删除)。
密封密钥更新和 SealedSecret 轮换不能替代轮换实际机密。
该工具的核心价值主张是:
将您的 Secret 加密到 SealedSecret 中,即使在公共存储库中也可以安全存储。
如果您将任何内容存储在版本控制存储中,特别是公共存储中,则必须假设您永远无法删除该信息。
如果密封密钥以某种方式从集群中泄漏,您必须将使用该密钥加密的所有SealedSecret
资源视为已泄露。集群中的密封密钥轮换次数,甚至现有 SealedSecrets 文件的重新加密都无法改变这一点。
最佳实践是定期轮换所有实际机密(例如更改密码)并使用这些新机密制作新的SealedSecret
资源。
但如果SealedSecret
控制器不更新密封密钥,则轮换将毫无意义,因为攻击者也可以解密新的秘密。因此,您需要同时执行这两件事:定期更新密封密钥并轮换您的实际秘密!
如果您知道或怀疑密封密钥已被泄露,您应该在开始密封新的轮换机密之前尽快更新密钥,否则攻击者也将获得对您的新机密的访问权限。
通过将当前时间戳传递到控制器到名为--key-cutoff-time
标志或名为SEALED_SECRETS_KEY_CUTOFF_TIME
环境变量,可以提前生成密钥。预期格式为 RFC1123,您可以使用date -R
unix 命令生成它。
密封的秘密密封密钥不是访问控制密钥(例如密码)。它们更像是您可以用来阅读发送给您的加密邮件的 GPG 密钥。让我们继续用电子邮件做类比:
想象一下,您有理由相信您的 GPG 私钥可能已被泄露。如果您做的第一件事就是删除您的私钥,那么您将失去更多。您将无法再访问之前使用该密钥发送的所有电子邮件(除非您拥有这些电子邮件的解密副本),也无法访问您尚未告知其使用新密钥的朋友发送的新电子邮件。
当然,这些加密电子邮件的内容并不安全,因为攻击者现在可能能够解密它们,但已经完成了。您突然失去阅读这些电子邮件的能力肯定不会消除损害。如果有的话,那就更糟了,因为你不再确定攻击者知道了什么秘密。您真正想做的是确保您的朋友停止使用您的旧密钥,并且从现在起所有进一步的通信都使用新密钥对进行加密(即您的朋友必须知道该新密钥)。
同样的逻辑也适用于 SealedSecrets。最终目标是保护您实际的“用户”秘密。 “封印”的秘密只是一个机制,一个“信封”。如果秘密被泄露,就没有回头路了,做过的事情就已经过去了。
您首先需要确保新的秘密不会使用旧的泄露密钥进行加密(在上面的电子邮件类比中,即:创建一个新的密钥对并向所有朋友提供新的公钥)。
第二个逻辑步骤是消除损害,这取决于秘密的性质。一个简单的例子是数据库密码:如果您不小心泄漏了数据库密码,您应该做的就是更改数据库密码(在数据库上;并撤销旧密码!)并使用以下内容更新SealedSecret
资源新密码(即再次运行kubeseal
)。
前面的部分描述了这两个步骤,尽管方式不太冗长。既然您已经更深入地掌握了基本原理,那么再次阅读它们并没有什么可耻的。
SealedSecret
控制器和相关工作流程旨在保留旧的密封密钥并定期添加新的密封密钥。除非您知道自己在做什么,否则不应删除旧密钥。
也就是说,如果您愿意,您可以手动管理(创建、移动、删除)密封密钥。它们只是普通的 k8s 秘密,位于SealedSecret
控制器所在的同一命名空间中(通常是kube-system
,但它是可配置的)。
您可以通过密封密钥的创造性管理来解决一些高级用例。例如,您可以在几个集群之间共享相同的密封密钥,以便您可以在多个集群中应用完全相同的密封秘密。由于密封密钥只是普通的 k8s 密钥,您甚至可以使用密封密钥本身并使用 GitOps 工作流程来管理您的密封密钥(当您想在不同集群之间共享相同密钥时很有用)!
使用除active
之外的任何内容标记密封密钥机密会有效地从SealedSecret
控制器中删除该密钥,但如果需要,它仍然可以在 k8s 中用于手动加密/解密。
注意SealedSecret
控制器当前不会自动拾取手动创建、删除或重新标记的密封密钥。管理员必须重新启动控制器才能应用效果。
在摆脱一些旧的密封密钥之前,您需要使用最新的私钥重新加密您的 SealedSecrets。
kubeseal --重新加密tmp.json && mv tmp.json my_sealed_secret.json
上面的调用将生成一个使用最新密钥进行新加密的新的密封秘密文件,而不会使秘密将集群留给客户端。然后,您可以将该文件保存在版本控制系统中( kubeseal --re-encrypt
不会更新集群内对象)。
目前,旧密钥不会被自动垃圾回收。
定期重新加密您的 SealedSecrets 是个好主意。但如上所述,不要让自己沉浸在错误的安全感中:您必须假设旧版本的SealedSecret
资源(使用您认为已失效的密钥加密的资源)仍然可能存在并且可供攻击者访问。即,重新加密并不能替代定期轮换您的实际秘密。
该控制器添加了一个新的SealedSecret
自定义资源。 SealedSecret
有趣的部分是 base64 编码的非对称加密Secret
。
控制器维护一组私钥/公钥对作为 kubernetes 秘密。密钥带有sealedsecrets.bitnami.com/sealed-secrets-key
标签,并在标签中标识为active
或compromised
。启动时,密封的秘密控制器将...
搜索这些密钥并将它们添加到其本地存储(如果它们被标记为活动)。
创建新密钥
启动密钥轮换周期
有关加密货币的更多详细信息可以在这里找到。
开发指南可以在开发者指南中找到。
是的,你可以!在一个文件中放入任意数量的秘密。确保通过---
对于 YAML 和 JSON 中的额外单个对象将它们分开。
不,私钥仅存储在控制器管理的 Secret 中(除非您有 k8s 对象的其他备份)。没有后门 - 如果没有用于加密给定 SealedSecrets 的私钥,您将无法解密它。如果您无法使用加密密钥访问 Secret,并且也无法访问集群中的 Secret 的解密版本,那么您将需要为所有内容重新生成新密码,并使用新密码再次密封它们密封钥匙等
如果您确实想备份加密私钥,可以通过具有适当访问权限的帐户轻松完成:
kubectl get Secret -n kube-system -l sealedsecrets.bitnami.com/sealed-secrets-key -o yaml >main.keyecho "---" >> main.key kubectl 获取秘密 -n kube-system seal-secrets-key -o yaml >>main.key
注意:仅当您在集群上安装了早于版本 0.9.x 的 seal-secrets 时,才需要第二条语句。
注意:此文件将包含控制器的公钥+私钥,并且应该保持安全!
注意:密封密钥更新后,您应该重新创建备份。否则,您的备份将无法解密新的密封秘密。
要在发生灾难后从备份中恢复,只需在启动控制器之前将这些机密放回原处 - 或者如果控制器已启动,则替换新创建的机密并重新启动控制器:
对于 Helm 部署:
kubectl apply -f main.key kubectl 删除 pod -n kube-system -l app.kubernetes.io/name=sealed-secrets
通过controller.yaml
清单进行部署
kubectl apply -f main.key kubectl 删除 pod -n kube-system -l name=sealed-secrets-controller
虽然将密封秘密视为秘密的长期存储系统不是推荐的用例,但有些人确实有一个合理的要求,即在 k8s 集群关闭时能够恢复秘密,并且不能将备份恢复到新的SealedSecret
控制器部署中实际的。
如果您已备份一个或多个私钥(请参阅上一问题),您可以使用kubeseal --recovery-unseal --recovery-private-key file1.key,file2.key,...
命令来解密密封的秘密文件。
您可以使用kubeseal --help
检查可用的标志。
kubernetes Secret
资源包含多个项目,基本上是键/值对的平面映射。 SealedSecrets 在该级别运行,并且不关心您在值中放入的内容。换句话说,它无法理解您可能放入秘密的任何结构化配置文件,因此无法帮助您更新其中的各个字段。
由于这是一个常见问题,特别是在处理遗留应用程序时,我们确实提供了一个可能的解决方法的示例。
是的,您可以向控制器提供您自己的证书,它会使用它们。请检查此处以获取解决方法。
kube-system
命名空间内运行,如何使用 kubeseal?如果您将控制器安装在与默认kube-system
不同的命名空间中,则需要将此命名空间提供给kubeseal
命令行工具。有两种选择:
您可以通过命令行选项--controller-namespace
指定命名空间:
kubeseal --controller-namespace seal-secretsmysealedsecret.json
通过环境变量SEALED_SECRETS_CONTROLLER_NAMESPACE
:
导出 SEALED_SECRETS_CONTROLLER_NAMESPACE=密封的秘密 kubesealmysealedsecret.json
我们的图像正在使用 cosign 进行签名。签名已保存在我们的 GitHub 容器注册表中。
v0.20.2 及之前版本的映像均使用 Cosign v1 进行签名。较新的映像使用 Cosign v2 进行签名。
验证图像非常简单:
# 导出 COSIGN_VARIABLE 设置 GitHub 容器注册表标志 pathexport COSIGN_REPOSITORY=ghcr.io/bitnami-labs/sealed-secrets-controller/signs# 验证在 GHCRcosign verify --key .github/workflows/cosign.pub ghcr 中上传的图像。 io/bitnami-labs/sealed-secrets-controller:latest# 验证 Dockerhub 中上传的镜像 cosign verify --key .github/workflows/cosign.pub docker.io/bitnami/sealed-secrets-controller:latest
如果您想将一个控制器用于多个命名空间,但不是所有命名空间,则可以使用命令行标志--additional-namespaces=
提供其他命名空间。确保在目标命名空间中提供适当的角色和角色绑定,以便控制器可以管理其中的机密。
答案是肯定的,您可以使用标志--max-unseal-retries
在控制器中配置重试次数。该标志允许您配置解封您的密封秘密的最大重试次数。
Kubernetes Slack 上的#sealed-secrets
单击此处注册 Kubernetes Slack 组织。
kubeseal-convert
:https://github.com/EladLeev/kubeseal-convert
Visual Studio 代码扩展:https://marketplace.visualstudio.com/items?itemName=codecontemplator.kubeseal
WebSeal:在浏览器中生成秘密:https://socialgouv.github.io/webseal
HybridEncrypt TypeScript 实现:https://github.com/SocialGouv/aes-gcm-rsa-oaep
[已弃用] 密封秘密操作员:https://github.com/disposab1e/sealed-secrets-operator-helm