如何通过yaml将秘密文件设置为kubernetes秘密?
Posted
技术标签:
【中文标题】如何通过yaml将秘密文件设置为kubernetes秘密?【英文标题】:How to set secret files to kubernetes secrets by yaml? 【发布时间】:2016-08-21 15:22:12 【问题描述】:我想将文件存储在 Kubernetes Secrets 中,但我还没有找到使用 yaml
文件的方法。
我已经能够使用带有kubectl
的cli:
kubectl create secret generic some-secret --from-file=secret1.txt=secrets/secret1.txt
但是当我在yaml
中尝试类似的东西时:
apiVersion: v1
kind: Secret
metadata:
name: some-secret
type: Opaque
data:
secret1.txt: secrets/secret1.txt
我遇到了这个错误:
[pos 73]: json: error decoding base64 binary 'assets/elasticsearch.yml': illegal base64 data at input byte 20
我正在关注本指南http://kubernetes.io/docs/user-guide/secrets/。它解释了如何使用yaml
创建秘密,但不解释如何使用yaml
从文件 创建秘密。
有可能吗?如果是这样,我该怎么做?
【问题讨论】:
您在问题中提到的使用yml
文件是否有任何方法可以做到这一点?喜欢不运行kubectl create secret generic some-secret --from-file=
?
对原始字符串输入使用stringData:
,对base64
编码数据使用data:
。
【参考方案1】:
正如上一篇文章所回答的,我们需要向文件提供编码为 based64 的证书/密钥。
以下是证书的通用示例(在本例中为 SSL):
secret.yml.tmpl
:
apiVersion: v1
kind: Secret
metadata:
name: test-secret
namespace: default
type: Opaque
data:
server.crt: SERVER_CRT
server.key: SERVER_KEY
预处理文件以包含证书/密钥:
sed "s/SERVER_CRT/`cat server.crt|base64 -w0`/g" secret.yml.tmpl | \
sed "s/SERVER_KEY/`cat server.key|base64 -w0`/g" | \
kubectl apply -f -
请注意,证书/密钥使用 base64 编码,不带空格 (-w0)。
对于 TLS 可以很简单:
kubectl create secret tls test-secret-tls --cert=server.crt --key=server.key
【讨论】:
值得注意的是(以防有人误解)文件 server.crt 和 server.key 通常是包含一个短标题的文件,一个长字符串是一个 base64 编码,由一些空格和新行,然后是一个短页脚。插入到 yaml 中的字符串是通过在这些现有文件上运行编码器生成的进一步的 base64 编码。因此最终有 2 个级别的 base64 编码。尝试从文件内部复制字符串并直接使用它们(因为它们已经是 base64 编码)不起作用。【参考方案2】:您可以使用 --dry-run 标志来准备包含文件数据的 YAML。
kubectl create secret generic jwt-certificates --from-file=jwt-public.cer --from-file=jwt-private.pfx --dry-run=true --output=yaml > jwt-secrets.yaml
编辑
感谢@Leopd 对 API 弃用的评论,新的 kubectl 使用这个命令:
kubectl create secret generic jwt-certificates --from-file=jwt-public.cer --from-file=jwt-private.pfx --dry-run=client --output=yaml > jwt-secrets.yaml
在我的机器上我还有旧的 kubectl 版本
【讨论】:
这是迄今为止最简单的解决方案 将--dry-run=true
替换为 --dry-run=client
(旧 API 已弃用)【参考方案3】:
当使用CLI
格式时,基本上你是在将它发布到服务器端之前使用 yaml 的生成器。
由于 Kubernetes 是中间有 REST API 的客户端-服务器应用程序,并且操作需要是原子的,因此发布的 YAML 需要包含文件的内容,最好的方法是将其嵌入为 base64 格式排队。如果文件可以以其他方式嵌入会很好(缩进可以用来创建文件的边界),但直到现在我还没有看到任何这样的例子。
话虽如此,在 yaml 上放置文件引用是不可能的,没有 yaml 的飞行前渲染以包含内容。
【讨论】:
【参考方案4】:所以我刚刚学习了一个我错过的超级有用的 k8s 基础,然后发现它有一个与之相关的安全漏洞,并想出了一个解决方案。
TLDR: 您可以在您的秘密仓库中将明文多行字符串/文本文件作为 secret.yaml ! :) (注意,我建议将其存储在 Hashicorp Vault 中,您可以存储具有秘密的版本化配置文件,并通过 Vault 网页轻松查看/编辑它们,并且与 git repo 不同,您可以进行细粒度访问控制,管道可以使用 REST API 来提取更新的秘密,这也使密码轮换变得很容易。)
cleartext-appsettings-secret.yaml appsettings.Dummy.json 是默认文件名(密钥的密钥) (我使用单词默认文件名,因为您可以在 yaml 挂载中覆盖它) 而明文json码就是文件内容(秘钥的值)
apiVersion: v1
kind: Secret
metadata:
name: appsettings
namespace: api
type: Opaque
stringData:
appsettings.Dummy.json: |-
"Dummy":
"Placeholder":
"Password": "blank"
当我 kubectl apply -f cleartext-appsettings-secret.yaml kubectl 获取秘密 appsettings -n=api -o yaml 秘密在注释中以明文形式显示...
apiVersion: v1
data:
appsettings.Dummy.json: ewogICJEdW1teSI6IHsKICAgICJQbGFjZWhvbGRlciI6IHsKICAgICAgIlBhc3N3b3JkIjogImJsYW5rIgogICAgfQogIH0KfQ==
kind: Secret
metadata:
annotations:
kubectl.kubernetes.io/last-applied-configuration: |
"apiVersion":"v1","kind":"Secret","metadata":"annotations":,"name":"appsettings","namespace":"api","stringData":"appsettings.Dummy.json":"\n \"Dummy\": \n \"Placeholder\": \n \"Password\": \"blank\"\n \n \n","type":"Opaque"
creationTimestamp: 2019-01-31T02:50:16Z
name: appsettings
namespace: api
resourceVersion: "4909"
selfLink: /api/v1/namespaces/api/secrets/appsettings
uid: f0629027-2502-11e9-9375-6eb4e0983acc
显然,用于创建注释中显示的秘密的 yaml 是 kubectl apply -f secret.yaml 自 2016 年以来的预期行为/已作为错误报告发布,但问题在没有解决的情况下关闭/它们是忽略它与修复它。
如果您原来的 secret.yaml 是 base64 的,则注释至少是 base64 的,但在这种情况下,它是非 base64 的人类可读明文。
注意1:命令式秘密创建不会发生这种情况 kubectl create secret generic appsettings --from-file appsettings.Dummy.json --namespace=api
注意 2:支持声明性 appsettings-secret.yaml 的另一个原因是,当需要编辑 kubectl apply -f 时将配置密钥,但如果您运行该 create 命令,它会说错误已经存在并且您必须先删除它,然后它才能让您再次运行创建命令。
注意 3:kubectl create secret generic name --from-file file --namespace / 反对 secret.yaml 的原因是 kubectl show secret 不会显示最后一次编辑秘密的时间。与创建命令一样,因为您必须在重新创建它之前将其删除,您将根据它存在的时间知道它最后一次编辑的时间,因此这对审计试用很有好处。 (但有更好的审计方法)
kubectl apply -f cleartext-appsettings-secret.yaml kubectl annotate secret appsettings -n=api kubectl.kubernetes.io/last-applied-configuration- kubectl 获取秘密 appsettings -n=api -o yaml 抵消泄漏
apiVersion: v1
data:
appsettings.Dummy.json: ewogICJEdW1teSI6IHsKICAgICJQbGFjZWhvbGRlciI6IHsKICAgICAgIlBhc3N3b3JkIjogImJsYW5rIgogICAgfQogIH0KfQ==
kind: Secret
metadata:
creationTimestamp: 2019-01-31T03:06:55Z
name: appsettings
namespace: api
resourceVersion: "6040"
selfLink: /api/v1/namespaces/api/secrets/appsettings
uid: 43f1b81c-2505-11e9-9375-6eb4e0983acc
type: Opaque
【讨论】:
【参考方案5】:您可以使用secode 将秘密值替换为base64
编码字符串,只需执行以下操作:
secode secrets.yaml > secrets_base64.yaml
当在列表 (kind: List
) 中定义时,它对所有 data
字段进行编码,并使用每个 yaml
文件的多个机密 (kind:Secret
)。
免责声明:我是作者
【讨论】:
类似的机制是在你的 yaml 文件中使用stringData
键来提供非 base64 编码的数据,并允许 Kubernetes 自动进行编码。 kubernetes.io/docs/concepts/configuration/secret【参考方案6】:
对于房间中的 Windows 用户,将其用于每个 .cer 和 .key(示例显示 .key 被编码以插入 YAML 文件):
$Content = Get-Content -Raw -Path C:\ssl-cert-decrypted.key
[Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes($Content)) | Out-File -FilePath C:\ssl-cert-decrypted.key.b64
打开新的.b64
文件并将(单行)输出粘贴到您的 YAML 文件中 - 请注意,如果将 YAML 文件签入其中包含此信息的源代码存储库,则密钥将被有效地泄露因为 base64 不是加密。
【讨论】:
以上是关于如何通过yaml将秘密文件设置为kubernetes秘密?的主要内容,如果未能解决你的问题,请参考以下文章
Promtail 基本身份验证在 helm values.yaml 中使用 kubernetes 秘密