Проблема: «Я могу управлять всеми настройками K8s в git, кроме секретов».
Решение: зашифруйте свой секрет в SealedSecret, который можно безопасно хранить даже в общедоступном хранилище. SealedSecret может быть расшифрован только контроллером, работающим в целевом кластере, и никто другой (даже первоначальный автор) не может получить исходный секрет из SealedSecret.
Обзор
SealedSecrets как шаблоны для секретов
Открытый ключ/сертификат
Области применения
Установка
Домашнее пиво
МакПортс
Линукс
Установка из исходников
Настроить
Карта руля
Контроллер
Кубесил
Обновление
Использование
Управление существующими секретами
Исправление существующих секретов
Обновить существующие секреты
Необработанный режим (экспериментальный)
Подтвердите запечатанный секрет
Секретная ротация
Обновление пломбировочного ключа
Ротация секретов пользователей
Раннее продление ключа
Распространенные заблуждения о продлении ключей
Ручное управление ключами (расширенное)
Повторное шифрование (расширенное)
Подробности (расширенно)
Крипто
Разработка
Часто задаваемые вопросы
Сможете ли вы расшифровать данные, если у вас больше нет доступа к кластеру?
Как мне сделать резервную копию моих SealedSecrets?
Могу ли я расшифровать свои секреты в автономном режиме с помощью резервного ключа?
Какие флаги доступны для kubeseal?
Как обновить части файла JSON/YAML/TOML/.., зашифрованные с помощью секретных секретов?
Могу ли я принести свои собственные (заранее созданные) сертификаты?
Как использовать kubeseal, если контроллер работает не в пространстве имен kube-system
?
Как проверить изображения?
Как использовать один контроллер для подмножества пространств имен
Могу ли я настроить повторные попытки распечатывания контроллера?
Сообщество
Связанные проекты
«Sealed Secrets» состоит из двух частей:
Контроллер/оператор на стороне кластера
Клиентская утилита: kubeseal
Утилита kubeseal
использует асимметричное шифрование для шифрования секретов, которые может расшифровать только контроллер.
Эти зашифрованные секреты закодированы в ресурсе SealedSecret
, который можно рассматривать как рецепт создания секрета. Вот как это выглядит:
apiVersion: bitnami.com/v1alpha1kind: SealedSecretmetadata: name: mysecret namespace: mynamespacespec: EncryptedData: foo: AgBy3i4OJSWK+PiTySYZZA9rO43cGDEq.....
После распечатки это создаст секретный эквивалент этого:
apiVersion: v1kind: Secretmetadata: name: mysecret namespace: mynamespacedata: foo: YmFy # <- "bar" в кодировке base64
Этот обычный секрет Kubernetes появится в кластере через несколько секунд. Вы сможете использовать его так же, как и любой секрет, который вы создали бы напрямую (например, ссылаться на него из Pod
).
Перейдите в раздел «Установка», чтобы приступить к работе.
В разделе «Использование» более подробно описано, как создавать ресурсы SealedSecret
.
Предыдущий пример фокусировался только на самих зашифрованных секретных элементах, но отношения между настраиваемым ресурсом SealedSecret
и Secret
который он раскрывает, во многом (но не во всех) похожи на знакомые Deployment
vs Pod
.
В частности, аннотации и метки ресурса SealedSecret
не совпадают с аннотациями Secret
, который создается на его основе.
Чтобы уловить это различие, объект SealedSecret
имеет раздел template
, который кодирует все поля, которые контроллер должен поместить в незапечатанный Secret
.
Библиотека функций Sprig доступна в дополнение к функциям Go Text Template по умолчанию.
Блок metadata
копируется как есть (поле ownerReference
будет обновляться, если оно не отключено).
Другие секретные поля обрабатываются индивидуально. Поля type
и immutable
поля копируются, а поле data
можно использовать для шаблонирования сложных значений в Secret
. Все остальные поля в настоящее время игнорируются.
apiVersion: bitnami.com/v1alpha1kind: SealedSecretmetadata: name: mysecret namespace: аннотации mynamespace: "kubectl.kubernetes.io/last-applied-configuration": ....spec: EncryptedData: .dockerconfigjson: AgBy3i4OJSWK+PiTySYZZA9rO43cGDEq.... . шаблон: type: kubernetes.io/dockerconfigjson immutable: true # это пример меток и аннотаций, которые будут добавлены к выходным секретным метаданным: labels: "jenkins.io/credentials-type": usernamePassword annotations: "jenkins.io/credentials -description»: учетные данные от Kubernetes.
Контроллер распечатал бы это во что-то вроде:
apiVersion: v1kind: Secretmetadata: name: mysecret namespace: mynamespace labels: "jenkins.io/credentials-type": аннотации usernamePassword: "jenkins.io/credentials-description": учетные данные от владельца KubernetesReferences: - apiVersion: контроллер bitnami.com/v1alpha1: true вид: SealedSecret имя: mysecret uid: 5caff6a0-c9ac-11e9-881e-42010aac003etype: kubernetes.io/dockerconfigjsonimmutable: truedata: .dockerconfigjson: ewogICJjcmVk...
Как видите, сгенерированный ресурс Secret
является «зависимым объектом» SealedSecret
и поэтому будет обновляться и удаляться всякий раз, когда объект SealedSecret
обновляется или удаляется.
Сертификат ключа (часть открытого ключа) используется для запечатывания секретов и должен быть доступен везде, где будет использоваться kubeseal
. Сертификат не является секретной информацией, хотя вам необходимо убедиться, что вы используете правильный сертификат.
kubeseal
будет получать сертификат от контроллера во время выполнения (требуется безопасный доступ к серверу API Kubernetes), что удобно для интерактивного использования, но известно, что он ненадежен, когда у пользователей есть кластеры со специальными конфигурациями, такие как частные кластеры GKE, между которыми установлены межсетевые экраны. плоскость управления и узлы.
Альтернативный рабочий процесс — сохранить сертификат где-нибудь (например, на локальном диске) с помощью kubeseal --fetch-cert >mycert.pem
и использовать его в автономном режиме с помощью kubeseal --cert mycert.pem
. Сертификат также печатается в журнале контроллера при запуске.
Поскольку сертификаты версии 0.9.x автоматически обновляются каждые 30 дней. Рекомендуется периодически обновлять автономный сертификат вы и ваша команда. Чтобы помочь вам в этом, начиная с версии 0.9.2 kubeseal
также принимает URL-адреса. Вы можете настроить внутреннюю автоматизацию для публикации сертификатов там, где вы доверяете.
kubeseal --cert https://your.intranet.company.com/sealed-secrets/your-cluster.cert
Он также распознает переменную среды SEALED_SECRETS_CERT
. (совет: см. также direnv).
ПРИМЕЧАНИЕ . Мы работаем над созданием механизмов управления ключами, которые переносят шифрование на модули на базе HSM или управляемые облачные криптографические решения, такие как KMS.
SealedSecrets с точки зрения конечного пользователя являются устройством «только для записи».
Идея состоит в том, что SealedSecret может быть расшифрован только контроллером, работающим в целевом кластере, и никто другой (даже первоначальный автор) не может получить исходный секрет из SealedSecret.
Пользователь может иметь или не иметь прямого доступа к целевому кластеру. Точнее, пользователь может иметь или не иметь доступ к секрету, раскрытому контроллером.
Есть много способов настроить RBAC на k8s, но довольно часто запрещают пользователям с низким уровнем привилегий читать секреты. Также распространено предоставление пользователям одного или нескольких пространств имен, где у них есть более высокие привилегии, что позволит им создавать и читать секреты (и/или создавать развертывания, которые могут ссылаться на эти секреты).
Зашифрованные ресурсы SealedSecret
разработаны таким образом, чтобы их можно было безопасно просматривать без каких-либо знаний о секретах, которые они скрывают. Это означает, что мы не можем позволить пользователям читать SealedSecret, предназначенный для пространства имен, к которому у них нет доступа, и просто помещать его копию в пространство имен, из которого они смогут читать секреты.
Таким образом, Sealed-secrets ведет себя так , как если бы каждое пространство имен имело свой собственный независимый ключ шифрования, и, следовательно, как только вы запечатаете секрет для пространства имен, его нельзя будет переместить в другое пространство имен и расшифровать там.
Технически мы не используем независимый закрытый ключ для каждого пространства имен, а вместо этого включаем имя пространства имен в процесс шифрования, фактически достигая того же результата.
Более того, пространства имен — не единственный уровень, на котором конфигурации RBAC могут решать, кто какой секрет может видеть. Фактически, пользователи могут получить доступ к секрету с именем foo
в данном пространстве имен, но не к любому другому секрету в том же пространстве имен. Таким образом, по умолчанию мы не можем разрешить пользователям свободно переименовывать ресурсы SealedSecret
иначе злонамеренный пользователь сможет расшифровать любой SealedSecret для этого пространства имен, просто переименовав его, чтобы перезаписать тот секретный ресурс, к которому у пользователя есть доступ. Мы используем тот же механизм, который использовался для включения пространства имен в ключ шифрования, чтобы также включить секретное имя.
Тем не менее, существует множество сценариев, в которых вас может не волновать этот уровень защиты. Например, единственные люди, которые имеют доступ к вашим кластерам, — это либо администраторы, либо они вообще не могут читать ни один Secret
ресурс. У вас может быть вариант использования для перемещения запечатанного секрета в другие пространства имен (например, вы можете заранее не знать имя пространства имен) или вы можете не знать имя секрета (например, он может содержать уникальный суффикс, основанный на хеше содержание и т. д.).
Вот возможные области применения:
strict
(по умолчанию): секрет должен быть запечатан с точно таким же именем и пространством имен . Эти атрибуты становятся частью зашифрованных данных , и поэтому изменение имени и/или пространства имен приведет к «ошибке расшифровки».
namespace-wide
: вы можете свободно переименовывать запечатанный секрет в пределах данного пространства имен.
cluster-wide
: секрет может быть раскрыт в любом пространстве имен и ему может быть присвоено любое имя.
В отличие от ограничений имени и пространства имен , секретные элементы (т. е. ключи объекта 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.
В некоторых случаях вам может потребоваться применить свои собственные настройки, например установить собственное пространство имен или установить некоторые переменные env.
kubectl
есть встроенная поддержка для этого, см. настройку.
Таблица управления Sealed Secrets теперь официально поддерживается и размещена в этом репозитории GitHub.
репозиторий Helm добавить запечатанные секреты https://bitnami-labs.github.io/sealed-secrets
ПРИМЕЧАНИЕ. Схема управления версиями диаграммы управления отличается от схемы управления версиями самого проекта «Запечатанные секреты».
Первоначально диаграмма управления поддерживалась сообществом, и в первой версии была принята основная версия 1, в то время как сам проект запечатанных секретов все еще имеет старшую версию 0. Это нормально, поскольку версия самой диаграммы управления не обязательно должна быть версией самого приложения. Однако это сбивает с толку, поэтому наше текущее правило управления версиями таково:
Схема версии контроллера SealedSecret
: 0.XY
Схема версии рулевой карты: 1.XY-rZ
Таким образом, может существовать несколько версий управляющей диаграммы с исправлениями, которые применяются только к управляющей диаграмме, не затрагивая статические манифесты YAML или сам образ контроллера.
ПРИМЕЧАНИЕ. Файл сведений о контрольной таблице по-прежнему содержит уведомление об устаревании, но оно больше не отражает реальности и будет удалено в следующем выпуске.
ПРИМЕЧАНИЕ. По умолчанию управляющая диаграмма устанавливает контроллер с именем
sealed-secrets
, а интерфейс командной строки (CLI)kubeseal
пытается получить доступ к контроллеру с именемsealed-secrets-controller
. Вы можете явно передать--controller-name
в CLI:
kubeseal --controller-name запечатанные-секреты
Кроме того, вы можете установить fullnameOverride
при установке диаграммы, чтобы переопределить имя. Также обратите внимание, что kubeseal
предполагает, что контроллер по умолчанию установлен в пространстве имен kube-system
. Итак, если вы хотите использовать CLI kubeseal
без необходимости передавать ожидаемое имя контроллера и пространство имен, вам следует установить Helm Chart следующим образом:
helm install запечатанные секреты -n kube-system --set-string полное имяOverride=запечатанные-секреты-контроллер запечатанные-секреты/запечатанные-секреты
В некоторых компаниях вам может быть предоставлен доступ только к одному пространству имен, а не ко всему кластеру.
Одна из наиболее ограничительных сред, с которой вы можете столкнуться, это:
Вам было выделено namespace
с некоторой service account
.
У вас нет доступа к остальной части кластера, даже к CRD кластера.
Возможно, вы даже не сможете создавать дополнительные учетные записи или роли служб в своем пространстве имен.
Вам необходимо включить ограничения ресурсов во все ваши развертывания.
Даже с учетом этих ограничений вы все равно можете установить запечатанную секретную карту управления, есть только одно предварительное условие:
В кластере уже должны быть установлены CRD с запечатанными секретами .
После того, как ваши администраторы установили CRD, если их там еще не было, вы можете установить диаграмму, подготовив файл конфигурации YAML, например этот:
сервисаккаунт: создать: ложь имя: {выделенная-служебная-учетная запись} рбак: создать: ложь кластерРоль: ложные ресурсы: пределы: процессор: 150 м память: 256Ми
Обратите внимание, что:
Учетные записи служб не создаются, вместо них будет использоваться выделенная вам.
{allocated-service-account}
— это имя service account
которую вы выделили в кластере.
Роли RBAC не создаются ни в пространстве имен, ни в кластере.
Необходимо указать лимиты ресурсов.
Ограничения — это образцы, которые должны работать, но вы можете просмотреть их в своей конкретной настройке.
Как только этот файл будет готов, если вы назвали его config.yaml
вы можете установить запечатанную секретную диаграмму Helm следующим образом:
helm install запечатанные секреты -n {выделенное пространство имен} запечатанные секреты/запечатанные секреты --skip-crds -f config.yaml
Где {allocated-namespace}
— это имя namespace
вам было выделено в кластере.
Клиент kubeseal
также доступен на homebrew:
заварить установку кубесил
Клиент kubeseal
также доступен на MacPorts:
установка порта kubeseal
Клиент kubeseal
также доступен на Nixpkgs: ( ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ : Bitnami-labs не поддерживается)
nix-env -iA nixpkgs.kubeseal
Клиент kubeseal
можно установить в Linux, используя следующие команды:
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
Вместо main
вы можете указать тег выпуска или SHA фиксации.
Команда go install
поместит двоичный файл kubeseal
в $GOPATH/bin
:
$(go env GOPATH)/bin/kubeseal
Не забудьте просмотреть примечания к выпуску, чтобы узнать о возможных критических изменениях при обновлении клиентского инструмента и/или контроллера.
В настоящее время для производственных сред поддерживается только последняя версия Sealed Secrets.
Контроллер Sealed Secrets обеспечивает совместимость с различными версиями Kubernetes, полагаясь на стабильный API Kubernetes. Обычно версии Kubernetes выше 1.16 считаются совместимыми. Однако мы официально поддерживаем рекомендуемые на данный момент версии Kubernetes. Кроме того, версии выше 1.24 проходят тщательную проверку в рамках нашего процесса CI при каждом выпуске.
# Каким-то образом создайте секрет в формате json/yaml:# (обратите внимание на использование `--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
.
По своей конструкции эта схема не осуществляет аутентификацию пользователя . Другими словами, любой может создать SealedSecret
содержащий любой Secret
, который ему нравится (при условии совпадения пространства имен и имени). Это зависит от вашего существующего рабочего процесса управления конфигурацией, правил кластера RBAC и т. д., чтобы обеспечить загрузку в кластер только предполагаемого SealedSecret
. Единственное отличие от существующих Kubernetes заключается в том, что содержимое Secret
теперь скрыто за пределами кластера.
Если вы хотите, чтобы контроллер Sealed Secrets управлял существующим Secret
, вы можете аннотировать свой Secret
с помощью аннотации sealedsecrets.bitnami.com/managed: "true"
. Существующий Secret
будет перезаписан при распечатывании SealedSecret
с тем же именем и пространством имен, и SealedSecret
станет владельцем Secret
(так что при удалении SealedSecret
Secret
также будет удален).
Новое в версии 0.23.0
В некоторых случаях вы не хотите заменять весь Secret
, а просто добавляете или изменяете некоторые ключи из существующего Secret
. Для этого вы можете аннотировать свой Secret
с помощью sealedsecrets.bitnami.com/patch: "true"
. Использование этой аннотации гарантирует, что секретные ключи, метки и аннотации в Secret
, которых нет в SealedSecret
, не будут удалены, а те, которые присутствуют в SealedSecret
будут добавлены в Secret
(существующие секретные ключи, метки и аннотации как в Secret
, так и в SealedSecret
будут изменены SealedSecret
).
Эта аннотация не заставляет SealedSecret
стать владельцем Secret
. Вы можете добавить как patch
, так и managed
аннотации, чтобы получить поведение исправления, а также стать владельцем Secret
.
Если вы хотите, чтобы SealedSecret
и Secret
были независимыми, то есть при удалении SealedSecret
Secret
не исчезнет вместе с ним, тогда вам необходимо добавить к этому секрету аннотацию sealedsecrets.bitnami.com/skip-set-owner-references: "true"
. sealedsecrets.bitnami.com/skip-set-owner-references: "true"
перед применением шагов использования. Вы также можете добавить sealedsecrets.bitnami.com/managed: "true"
в свой Secret
, чтобы ваш секрет обновлялся при обновлении SealedSecret
.
Если вы хотите добавить или обновить существующие запечатанные секреты, не имея открытого текста для других элементов, вы можете просто скопировать и вставить новые зашифрованные элементы данных и объединить их с существующим запечатанным секретом.
Вы должны позаботиться о том, чтобы запечатать обновленные элементы совместимым именем и пространством имен (см. примечание об областях выше).
Вы можете использовать команду --merge-into
для обновления существующих запечатанных секретов, если вы не хотите копировать и вставлять:
эхо -н бар | kubectl create secret generic mysecret --dry-run=client --from-file=foo=/dev/stdin -o json | kubeseal > mysealedsecret.jsonecho -n baz | kubectl create secret generic mysecret --dry-run=client --from-file=bar=/dev/stdin -o json | kubeseal --merge-in mysealedsecret.json
Создание временного секрета с помощью команды kubectl
только для того, чтобы выбросить его после передачи в kubeseal
может быть весьма недружелюбным пользовательским опытом. Мы работаем над пересмотром интерфейса командной строки. Тем временем мы предлагаем альтернативный режим, в котором kubeseal заботится только о шифровании значения в стандартный вывод, и вы обязаны поместить его в ресурс SealedSecret
(мало чем отличающийся от любого другого ресурса k8s).
Он также может быть полезен в качестве строительного блока для интеграции редактора и IDE.
Обратной стороной является то, что вам нужно быть осторожным, чтобы согласовать область запечатывания, пространство имен и имя.
См. области
strict
область действия (по умолчанию):
$ echo -n foo | kubeseal --raw --namespace bar --name mysecretAgBChHUWLMx...
область действия namespace-wide
:
$ echo -n foo | kubeseal --raw --namespace bar --scope namespace-wideAgAbbFNkM54...
Включите аннотацию sealedsecrets.bitnami.com/namespace-wide
в файл SealedSecret
метаданные: аннотации: Seedsecrets.bitnami.com/namespace-wide: «true»
область действия cluster-wide
:
$ echo -n foo | kubeseal --raw --scope для всего кластераAgAjLKpIYV+...
Включите аннотацию sealedsecrets.bitnami.com/cluster-wide
в файл SealedSecret
метаданные: аннотации: Seedsecrets.bitnami.com/cluster-wide: «true»
Если вы хотите проверить существующий запечатанный секрет, у kubeseal
есть флаг --validate
который поможет вам.
Предоставление файла с именем sealed-secrets.yaml
, содержащего следующий запечатанный секрет:
apiVersion: bitnami.com/v1alpha1kind: SealedSecretmetadata: name: mysecret namespace: mynamespacespec: EncryptedData: foo: AgBy3i4OJSWK+PiTySYZZA9rO43cGDEq.....
Вы можете проверить, был ли запечатанный секрет правильно создан или нет:
$ cat запечатанный-секреты.yaml | kubeseal --проверить
В случае неверного запечатанного секрета kubeseal
покажет:
$ cat запечатанный-секреты.yaml | kubeseal --validateerror: невозможно расшифровать запечатанный секрет
Вы всегда должны менять свои секреты. Но поскольку ваши секреты зашифрованы другим секретом, вам необходимо понять, как связаны эти два слоя, чтобы принимать правильные решения.
ТЛ;ДР:
Если запечатывающий закрытый ключ скомпрометирован, вам необходимо следовать инструкциям, приведенным ниже в разделе «Раннее обновление ключа», прежде чем менять какие-либо фактические секретные значения.
Функции обновления и повторного шифрования ключей SealedSecret не заменяют периодическую ротацию ваших фактических секретных значений.
Ключи пломбирования автоматически обновляются каждые 30 дней. Это означает, что создается новый ключ запечатывания, который добавляется к набору активных ключей запечатывания, которые контроллер может использовать для распечатывания ресурсов SealedSecret
.
Последний созданный ключ запечатывания используется для запечатывания новых секретов при использовании kubeseal
, и именно тот, сертификат которого загружается при использовании kubeseal --fetch-cert
.
Время продления в 30 дней является разумным значением по умолчанию, но его можно изменить по мере необходимости с помощью флага --key-renew-period=
для команды в шаблоне модуля контроллера SealedSecret
. Поле value
может быть указано как флаг длительности golang (например: 720h30m
). Предполагая, что вы установили Sealed Secrets в пространство имен kube-system
, используйте следующую команду для редактирования контроллера развертывания и добавьте параметр --key-renew-period
. Как только вы закроете текстовый редактор и контроллер развертывания будет изменен, новый модуль будет автоматически создан для замены старого модуля.
kubectl edit deployment/sealed-secrets-controller --namespace=kube-system
Значение 0
отключит автоматическое продление ключа. Конечно, у вас может быть действительный вариант использования для отключения автоматического обновления запечатанных ключей, но опыт показывает, что новые пользователи часто склонны делать поспешные выводы о том, что им нужен контроль над обновлением ключей, прежде чем полностью понять, как работают запечатанные секреты. Подробнее об этом читайте в разделе «Распространенные заблуждения» ниже.
К сожалению, вы не можете использовать, например, «d» в качестве единицы измерения дней, поскольку это не поддерживается стандартной библиотекой Go. Вместо того, чтобы ударять себя ладонью по лицу, воспользуйтесь этим как возможностью поразмышлять над ложью, в которую верят программисты о времени.
Распространенным заблуждением является то, что обновление ключа часто рассматривается как форма ротации ключей, когда старый ключ не только устарел, но и на самом деле плох, и поэтому вы хотите от него избавиться. Не помогает и то, что эту функцию исторически называли «поворотом клавиш», что может еще больше запутать.
Запечатанные секреты не меняются автоматически, а старые ключи не удаляются при создании новых ключей. Старые ресурсы SealedSecret
все еще можно расшифровать (поскольку старые ключи запечатывания не удаляются).
Обновление ключа запечатывания и ротация SealedSecret не заменяют ротацию ваших реальных секретов.
Основное ценностное предложение этого инструмента:
Зашифруйте свой секрет в SealedSecret, который можно безопасно хранить даже в общедоступном хранилище.
Если вы храните что-либо в хранилище с контролем версий, особенно в общедоступном, вы должны исходить из того, что никогда не сможете удалить эту информацию.
Если ключ запечатывания каким-либо образом ускользнет из кластера, вы должны считать все ваши ресурсы SealedSecret
зашифрованные этим ключом, скомпрометированными. Никакая ротация ключей запечатывания в кластере или даже повторное шифрование существующих файлов SealedSecrets не смогут этого изменить.
Лучше всего периодически менять все ваши настоящие секреты (например, менять пароль) и создавать новые ресурсы SealedSecret
с этими новыми секретами.
Но если бы контроллер SealedSecret
не обновлял запечатывающий ключ, такая ротация была бы спорной, поскольку злоумышленник мог бы просто расшифровать и новые секреты. Таким образом, вам нужно делать и то, и другое: периодически обновлять ключ печати и менять свои настоящие секреты!
Если вы знаете или подозреваете, что ключ опечатывания был скомпрометирован, вам следует как можно скорее обновить ключ, прежде чем вы начнете запечатывать свои новые повернутые секреты, в противном случае вы также предоставите злоумышленникам доступ к вашим новым секретам.
Ключ можно сгенерировать раньше, передав текущую временную метку контроллеру в флаг --key-cutoff-time
или переменную окружения SEALED_SECRETS_KEY_CUTOFF_TIME
. Ожидаемый формат — RFC1123, его можно сгенерировать с помощью команды unix date -R
.
Ключи запечатывания секретов не являются ключами контроля доступа (например, паролем). Они больше похожи на ключ GPG, который вы можете использовать для чтения зашифрованной почты, отправленной вам. Давайте продолжим аналогию с электронной почтой:
Представьте, что у вас есть основания полагать, что ваш личный ключ GPG мог быть скомпрометирован. Вы потеряете больше, чем выиграете, если первым делом просто удалите свой закрытый ключ. Все предыдущие электронные письма, отправленные с этим ключом, больше не доступны вам (если у вас нет расшифрованной копии этих писем), а также новые электронные письма, отправленные вашими друзьями, которым вы еще не успели сказать, чтобы они использовали новый ключ.
Конечно, содержимое этих зашифрованных писем небезопасно, поскольку злоумышленник теперь может их расшифровать, но что сделано, то сделано. Ваша внезапная потеря способности читать эти электронные письма, конечно, не компенсирует ущерб. Во всяком случае, это хуже, потому что вы больше не знаете наверняка, какой секрет узнал злоумышленник. Что вам действительно нужно сделать, так это убедиться, что ваш друг перестал использовать ваш старый ключ и что с этого момента все дальнейшее общение будет шифроваться с помощью новой пары ключей (т. е. ваш друг должен знать об этом новом ключе).
Та же логика применима и к SealedSecrets. Конечная цель — защитить ваши настоящие «пользовательские» секреты. «Запечатывающие» тайны — это всего лишь механизм, «конверт». Если секрет раскрыт, пути назад нет, что сделано, то сделано.
Сначала вам необходимо убедиться, что новые секреты не будут зашифрованы с помощью этого старого скомпрометированного ключа (в приведенной выше аналогии с электронной почтой: создайте новую пару ключей и дайте всем своим друзьям новый открытый ключ).
Второй логический шаг – нейтрализация ущерба, который зависит от характера секрета. Простым примером является пароль базы данных: если вы случайно разгласили пароль своей базы данных, вам нужно просто изменить пароль базы данных (в базе данных и отозвать старый!) и обновить ресурс SealedSecret
с помощью новый пароль (т.е. снова запустите kubeseal
).
Оба шага описаны в предыдущих разделах, хотя и менее подробно. Нет ничего постыдного в том, чтобы перечитать их еще раз, теперь, когда вы более глубоко поняли основную причину.
Контроллер SealedSecret
и связанный с ним рабочий процесс предназначены для хранения старых ключей опломбирования и периодического добавления новых. Не следует удалять старые ключи, если вы не знаете, что делаете.
При этом при желании вы можете вручную управлять (создавать, перемещать, удалять) ключами пломбирования . Это обычные секреты k8s, находящиеся в том же пространстве имен, что и контроллер SealedSecret
(обычно kube-system
, но это можно настроить).
Существуют сложные варианты использования, которые можно решить путем творческого управления ключами опечатывания. Например, вы можете использовать один и тот же ключ запечатывания в нескольких кластерах, чтобы можно было применять один и тот же запечатанный секрет в нескольких кластерах. Поскольку ключи запечатывания — это обычные секреты k8s, вы даже можете использовать сами запечатанные секреты и использовать рабочий процесс GitOps для управления ключами запечатывания (полезно, если вы хотите использовать один и тот же ключ в разных кластерах)!
Пометка секретного ключа чем-либо, кроме active
эффективно удаляет ключ из контроллера SealedSecret
, но он по-прежнему доступен в k8s для ручного шифрования/дешифрования, если это необходимо.
ПРИМЕЧАНИЕ. Контроллер SealedSecret
в настоящее время не распознает автоматически созданные, удаленные или перемаркированные ключи запечатывания вручную. Чтобы эффект вступил в силу, администратор должен перезапустить контроллер.
Прежде чем вы сможете избавиться от некоторых старых ключей печати, вам необходимо повторно зашифровать ваши SealedSecrets с помощью новейшего закрытого ключа.
kubeseal --re-encrypttmp.json && mv tmp.json my_sealed_secret.json
Приведенный выше вызов создаст новый запечатанный секретный файл, свежезашифрованный последним ключом, без передачи секретов клиенту из кластера. Затем вы можете сохранить этот файл в своей системе контроля версий ( kubeseal --re-encrypt
не обновляет объект в кластере).
В настоящее время старые ключи не удаляются автоматически.
Рекомендуется периодически повторно шифровать файлы SealedSecrets. Но, как упоминалось выше, не убаюкивайте себя ложным чувством безопасности: вы должны предположить, что старая версия ресурса SealedSecret
(зашифрованная ключом, который вы считаете мертвым) все еще потенциально существует и доступна для злоумышленников. Т.е. повторное шифрование не заменяет периодическую смену ваших реальных секретов.
Этот контроллер добавляет новый пользовательский ресурс SealedSecret
. Интересная часть SealedSecret
— это асимметрично зашифрованный Secret
в кодировке Base64.
Контроллер поддерживает набор пар частного/открытого ключей в качестве секретов Kubernetes. Ключи помечены sealedsecrets.bitnami.com/sealed-secrets-key
и обозначены в метке как active
или compromised
. При запуске контроллер запечатанных секретов...
Найдите эти ключи и добавьте их в локальное хранилище, если они помечены как активные.
Создать новый ключ
Запустите цикл вращения ключа
Более подробную информацию о криптовалюте можно найти здесь.
Рекомендации по разработке можно найти в Руководстве разработчика.
Да, вы можете! Сохраняйте столько секретов, сколько захотите, в один файл. Обязательно разделите их через ---
для YAML и, в качестве дополнительных, отдельных объектов в JSON.
Нет, закрытые ключи хранятся только в секрете, управляемом контроллером (если у вас нет другой резервной копии ваших объектов k8s). Никаких бэкдоров нет — без секретного ключа, используемого для шифрования данного SealedSecrets, вы не сможете его расшифровать. Если вы не можете получить доступ к Секретам с ключами шифрования, а также не можете получить доступ к расшифрованным версиям ваших Секретов, живущим в кластере, то вам нужно будет заново сгенерировать новые пароли для всего, запечатать их снова новым пломбировочный ключ и т. д.
Если вы хотите сделать резервную копию закрытых ключей шифрования, это легко сделать из учетной записи с подходящим доступом:
kubectl get secret -n kube-system -l Sealedsecrets.bitnami.com/sealed-secrets-key -o yaml >main.keyecho "---" >> main.key kubectl get secret -n kube-system запечатанный-секретный ключ -o yaml >>main.key
ПРИМЕЧАНИЕ. Второй оператор понадобится только в том случае, если вы когда-либо устанавливали в своем кластере запечатанные секреты старше версии 0.9.x.
ПРИМЕЧАНИЕ. Этот файл будет содержать открытый и закрытый ключи контроллера, и его следует хранить в безопасности!
ПРИМЕЧАНИЕ. После обновления ключа запечатывания вам следует заново создать резервную копию. В противном случае ваша резервная копия не сможет расшифровать новые запечатанные секреты.
Чтобы восстановить резервную копию после какого-либо сбоя, просто верните эти секреты перед запуском контроллера — или, если контроллер уже был запущен, замените вновь созданные секреты и перезапустите контроллер:
Для развертывания Helm:
kubectl применить -f main.key kubectl delete pod -n kube-system -l app.kubernetes.io/name=sealed-secrets
Для развертывания через манифест controller.yaml
kubectl применить -f main.key kubectl delete 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
? Если вы установили контроллер в пространство имен, отличное от kube-system
по умолчанию, вам необходимо предоставить это пространство имен инструменту командной строки kubeseal
. Есть два варианта:
Вы можете указать пространство имен с помощью параметра командной строки --controller-namespace
:
kubeseal --controller-namespace запечатанные секретыmysealedsecret.json
Через переменную среды SEALED_SECRETS_CONTROLLER_NAMESPACE
:
экспорт SEALED_SECRETS_CONTROLLER_NAMESPACE=запечатанные секреты kubesealmysealedsecret.json
Наши изображения подписываются с помощью cosign. Подписи сохранены в нашем реестре контейнеров GitHub.
Изображения до версии 0.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# проверить изображение, загруженное в Dockerhubcosign проверить --key .github/workflows/cosign.pub docker.io/bitnami/sealed-secrets-controller:latest
Если вы хотите использовать один контроллер для более чем одного пространства имен, но не для всех пространств имен, вы можете предоставить дополнительные пространства имен с помощью флага командной строки --additional-namespaces=
. Убедитесь, что вы предоставили соответствующие роли и привязки ролей в целевых пространствах имен, чтобы контроллер мог управлять там секретами.
Ответ — да, вы можете настроить количество повторов в вашем контроллере, используя флаг --max-unseal-retries
. Этот флаг позволяет вам настроить максимальное количество повторных попыток раскрытия ваших запечатанных секретов.
#sealed-secrets в Kubernetes Slack
Нажмите здесь, чтобы зарегистрироваться в организации 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