如何使用Kubeseal密封掌舵式秘密?

时间:2019-09-30 03:35:47

标签: kubernetes kubernetes-helm kubernetes-secrets

想像这样的秘密:

apiVersion: v1
kind: Secret
metadata:
  name: {{ include "test-cicd.fullname" . }}
  labels:
    app.kubernetes.io/name: {{ include "test-cicd.name" . }}
    helm.sh/chart: {{ include "test-cicd.chart" . }}
    app.kubernetes.io/instance: {{ .Release.Name }}
    app.kubernetes.io/managed-by: {{ .Release.Service }}
type: Opaque
data:
  secret.yaml: |
    {{ if eq .Values.env "prod" }}
    foo: bar-prod
    foo2: bar2_prod
    {{ else if eq .Values.evn "dev" }}
    foo: bar-dev
    {{ end }}

是否可以使用Kubeseal将其密封? 现在完成操作后,我得到invalid map key: map[interface {}]interface {}{"include \"test-cicd.fullname\" .":interface {}(nil)},这可能是因为它不是“有效”的Yaml文件。

我尝试过的一件事是: 1.拆除头盔模板线 2.生成密封的秘密 3.使用头盔为密封的秘密模板

但是,这样做,集群侧操作员无法在部署时解密密封的秘密。

3 个答案:

答案 0 :(得分:2)

mkmik Github上回答了我的问题,所以我在这里也引用它作为记录。


因此,您正在使用客户端模板来构成一个秘密值。 您的secret.yaml文件的某些部分是秘密的,但是部分必须是模板指令(if),因此不能进行加密。

您有两个选择:

  1. 您可以使用某些客户端保险库管理软件以某种方式对您的机密进行加密,可能与头盔整合(例如https://github.com/futuresimple/helm-secrets)。这就要求每个应用该掌舵表的用户(和CI环境)都能够解密机密。

  2. 您可以重构秘密,使秘密成为“原子的”秘密,并使用密封的秘密来受益于其“单向加密”方法,该方法使您的devops用户(和CI自动化)可以应用舵图,而自己却看不到秘密值。

此答案的其余部分假定您选择了选项(2)


现在,由于您决定使用Helm,因此您必须处理以下事实:Helm模板不是json / yaml文件,而是Go语言的模板,因此无法通过设计用于操纵结构化数据格式的工具来操纵它们。

幸运的是,kubeseal有一个--raw命令,它使您可以加密各个秘密值,并将其手动设置为用来描述k8s资源的任何文件格式。

因此,假设您要为SealedSecrets资源创建一个Helm模板,该模板将名称和标签值作为参数,并且还根据布尔prod / dev参数选择要放置的秘密,此示例可能对您有用:

apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
  name: {{ include "test-cicd.fullname" . }}
  annotations:
    # this is because the name is a deployment time parameter
    # consider also using "cluster-wide" if the namespace is also a parameter
    # please make sure you understand the implications, see README
    sealedsecrets.bitnami.com/namespace-wide: "true"
  labels:
    app.kubernetes.io/name: {{ include "test-cicd.name" . }}
    helm.sh/chart: {{ include "test-cicd.chart" . }}
    app.kubernetes.io/instance: {{ .Release.Name }}
    app.kubernetes.io/managed-by: {{ .Release.Service }}
type: Opaque
spec:
  template:
    metadata:
      labels:
        app.kubernetes.io/name: {{ include "test-cicd.name" . }}
        app.kubernetes.io/instance: {{ .Release.Name }}
        app.kubernetes.io/managed-by: {{ .Release.Service }}
  encryptedData:
    {{ if eq .Values.env "prod" }}
    foo: AgASNmKx2+QYbbhSxBE0KTa91sDBeNSaicvgBPW8Y/q/f806c7lKfF0mnxzEirjBsvF67C/Yp0fwSokIpKyy3gXtatg8rhf8uiQAA3VjJGkl5VYLcad0t6hKQyIfHsD7wrocm36uz9hpH30DRPWtL5qy4Z+zbzHj8AvEV+xTpBHCSyJPF2hyvHXTr6iQ6KJrAKy04MDwjyQzllN5OQJT2w4zhVgTxXSg/c7m50U/znbcJ1x5vWLXLSeiDRrsJEJeNoPQM8OHmosf5afSOTDWQ4IhG3srSBfDExSFGBIC41OT2CUUmCCtrc9o61LJruqshZ3PkiS7PqejytgwLpw/GEnj2oa/uNSStiP9oa9mCY6IUMujwjF9rKLIT456DlrnsS0bYXO2NmYwSfFX+KDbEhCIVFMbMupMSZp9Ol2DTim5SLIgIza/fj0CXaO3jGiltSQ0aM8gLSMK9n3c1V+X5hKmzMI3/Xd01QmhMmwqKp+oy21iidLJjtz67EiWyfIg1l7hiD5IIVlM9Gvg3k67zij5mOcXPkFnMmUQhQWxVKgAf4z8qEgprt03C+q+Wwwt25UDhQicpwoGtVQzU5ChJi09ja5LeW4RrvDf2B5KRp9HXoj1eu93MMl1Kcnx+X7uVT5OqQz28c4wOLT4FDItFzh8zREGZbiG/B3o1vI8MmwvxXj++pQ7SfBxoz9Xe8gmQ7BuXno=
    foo2: AgAkaTBYcESwogPiauZ15YbNldmk4a9esyYuR2GDt7hNcv+ycPLHmnsJcYs0hBtqucmrO3HbgCy/hQ6dMRCY12RA7w7XsFqNjZy3kavnhqwM6YkHntK2INwercRNQpO6B9bH6MxQTXcxfJbPqaPt30iTnTAhtpN47lueoyIoka4WWzwG/3PAikXhIlkTaq0hrclRJHRqg4z8Kmcaf5A/BRL2xX8syHbjA7MK9/OoK+zytv+LGrbLLHUtuhNNNQ2PG9u05rP6+59wRduQojEDtB9FTCa+daS+04/F4H1vi6XUNnjkK+Xna1T2Eavyuq2GieKj/7ig96et/4HoTAz44zwVhh8/pk0IFC8srcH3p+rFtZZmjvbURrFahEjFZbav3BDMBNhrU8SI3MDN0Abiyvz4vJJfSxIYcyLD1EQ507q7ZXrqYN/v1EiYgYUACi0JGxSWHB9TlCkZOAdCl+hroXEhBN2u5utLJ12njBQJ8ACNQDOYf+CmtV0y7foCZ6Aaap0pV7a8twyqK8c17kImzfi102Zel8ALfLAzdAXBV9c1+1pH76turnTCE33aSMQlaVF3VTmFQWqB8uIO/FQhZDPo8u/ki3L8J31nepup4/WE7i59IT0/9qGh2LKql4oAv6v4D7qtKziN6DvG7bsJlj14Dln0roiTfTWEEnBqdDER+GKZJlKayOWsPQdN0Wp+2KVfwLM=
    {{ else if eq .Values.evn "dev" }}
    foo: AgAkaTBYcESwogPi..........
    {{ end }}

另一种方法是拥有两个模板,一个用于生产产品,一个用于开发人员,并使用Helm模板逻辑根据您要部署到的环境选择正确的文件。

无论如何,每个base64 Blob都可以通过以下方式产生:

$ kubeseal --raw --scope namespace-wide --from-file=yoursecret.txt

专业提示,如果密码不在文件中,则可以通过管道传输密码:

$ echo -n yoursecret | kubeseal --raw --scope namespace-wide --from-file=/dev/stdin

然后,您必须将该命令的输出粘贴到Helm Go模板中。

答案 1 :(得分:1)

我的方法

  1. 针对不同的环境使用不同的 .values.yml 文件
  2. 创建 .secrets.yml 文件来存储秘密值(包含在 .gitignore 中)
  3. 制作一个 git pre-commit 钩子,使用 kubeseal --raw 加密各个秘密,然后将它们写入值文件
  4. 将值文件存储在 git 中。

我写了一个要点:https://gist.github.com/foogunlana/b75175b4ff62bc07258ea78274c698cd

答案 2 :(得分:0)

我不会将来自不同环境的凭据放到一个秘密中,因为它可以通过不同的密封控制器部署到不同的集群中。

为什么不为每个环境单独隔离秘密文件?

为了密封秘密,我使用以下命令:

kubeseal --name=name-of-the-config --controller-namespace=fluxcd \
       --controller-name=sealed-secrets  --format yaml \
      < secret.yaml > sealedsecret.yaml

您可以通过以下方式检测头盔释放的控制器名称和控制器名称空间:

kubectl get HelmRelease -A -o jsonpath="{.items[?(@.spec.chart@.name=='sealed-secrets')]}"