Как использовать Kubeseal, чтобы запечатать секрет, созданный по шаблону на шлеме?

Представьте себе такой секрет:

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. Удаление шаблонных строк helm 2. Создание sealedsecret 3. Создание шаблона sealedsecret с помощью helm

Но при этом запечатанный секрет не может быть расшифрован оператором на стороне кластера во время развертывания.


person Milad    schedule 30.09.2019    source источник
comment
Я не знаком с Kubeseal, но если вы хотите узнать об альтернативных решениях, вы можете ознакомиться с моим недавний пост.   -  person Omer Levi Hevroni    schedule 02.10.2019
comment
Спасибо @OmerLeviHevroni. Я получил ответ от mkmik на GitHub.   -  person Milad    schedule 03.10.2019
comment
@Milad Не могли бы вы также разместить здесь ответ от GitHub? Это было бы полезно для других людей с той же проблемой.   -  person Wytrzymały Wiktor    schedule 03.10.2019


Ответы (3)


mkmik ответил на мой вопрос на Github, поэтому я цитирую это и здесь только для записи.


Итак, вы составляете секретное значение с помощью шаблонов на стороне клиента. Части вашего файла secret.yaml являются секретными, но части должны содержать директивы шаблонов (if) и, следовательно, не могут быть зашифрованы.

У вас есть два варианта:

  1. вы каким-то образом шифруете свои секреты с помощью некоторого программного обеспечения хранилища на стороне клиента, возможно, с интеграцией с Helm (например, https://github.com/futuresimple/helm-secrets). Это требует, чтобы каждый пользователь (и среда CI), применяющий эту диаграмму управления, был в состоянии расшифровать секреты.

  2. вы повторно факторизуете свои секреты так, чтобы они были «атомарными», и использовали запечатанные секреты, чтобы извлечь выгоду из его подхода «одностороннего шифрования», который позволяет вашим пользователям DevOps (и автоматизации CI) применять диаграммы управления, даже не видя сами секретные ценности.

Остальная часть этого ответа предполагает, что вы выбрали вариант (2)


Теперь, когда вы решили использовать Helm, вы должны иметь дело с тем фактом, что шаблоны helm не являются файлами json / yaml, а являются шаблонами Go, и, следовательно, ими нельзя манипулировать с помощью инструментов, предназначенных для управления форматами структурированных данных.

К счастью, в kubeseal есть команда --raw, которая позволяет вам зашифровать отдельные секретные значения и поместить их вручную в любой формат файла, который вы используете для описания ваших ресурсов k8s.

Итак, предполагая, что вы хотите создать шаблон Helm для ресурса SealedSecrets, который принимает значения имени и метки в качестве параметров, а также выбирает, какие секреты помещать также на основе логического параметра 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 }}

Альтернативный подход - иметь два шаблона, один для prod и один для dev, и использовать логику шаблонов Helm для выбора нужного файла в зависимости от того, в какой среде вы развертываете.

В любом случае, каждый из этих BLOB-объектов base64 может быть создан с помощью:

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

Совет, вы можете передать секрет, если его нет в файле:

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

Затем вам нужно вставить вывод этой команды в свой шаблон Helm Go.

person Milad    schedule 07.10.2019
comment
Было бы неплохо, если бы kubeseal мог шифровать файлы Helm values.yaml. например github.com/markmclaren/sealed-secrets-file-encrypt - person Mark McLaren; 13.12.2019
comment
Вы не можете найти это нигде в Интернете. Это способ использования SealedSecrets с шаблонами руля. - person Alex Jolig; 21.05.2021

Мой подход

  1. Используйте разные файлы .values.yml для разных сред
  2. Создайте файлы .secrets.yml для хранения секретных значений (включите в .gitignore)
  3. Создайте хук предварительной фиксации git, который использует kubeseal --raw для шифрования отдельных секретов, а затем записывает их в файл значений.
  4. Сохраните файл значений в git.

Я написал суть по этому поводу: https://gist.github.com/foogunlana/b75175b425862b75c07b4e08e6e6e6e6e6e6e6

person Bo Ogunlana    schedule 14.04.2021
comment
Это отличное решение. Спасибо, что поделились. - person Nicolas Forney; 26.05.2021

Я бы не стал помещать учетные данные из разных сред в один секрет, так как его можно развернуть в другом кластере с другим запечатанным контроллером.

Почему бы вам просто не разделить секретные файлы для каждой среды?

Чтобы запечатать секрет, я использую следующую команду:

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

Вы можете определить имя контроллера и пространство имен контроллера выпуска helm следующим образом:

kubectl get HelmRelease -A -o jsonpath="{.items[?(@[email protected]=='sealed-secrets')]}"
person oliver nadj    schedule 14.10.2020