Vault как центр сертификации для Kubernetes

Kubernetes – это открытая система управления контейнерами, с помощью которой можно управлять кластером контейнеров Linux. Чтобы защитить данные кластера, можно использовать TLS-сертификаты. Однако внедрение TLS в Kubernetes – довольно трудоёмкий процесс (не говоря уже о восстановлении и отзыве сертификатов). А что, если таких сертификатов нужно несколько? В таких ситуациях на помощь приходит Vault – инструмент управления конфиденциальными данными. С помощью Vault можно хранить ключи API, пароли, сертификаты, учетные данные БД и многое другое. Vault предоставляет удобный интерфейс, а также обеспечивает контроль доступа и надёжное логирование данных.

Это руководство поможет разработать и внедрить центр сертификации (ЦС) для Kubernetes с помощью Vault.

1: Подготовка и планирование

Прежде чем приступать к разработке ЦС, изучите все пути взаимодействия и передачи данных в кластере.

Предположим, все операции Kubernetes проходят через отдельный apiserver. Ноды должны принимать подключения только от других равноправных нод и apiserver. Клиенты Kubernetes или другие клиенты не должны иметь возможности напрямую подключаться к кластеру (в противном случае можно было бы обойти ограничения доступа). Клиенты apiserver также должны получать клиентский сертификат.

Учитывая эти предварительные данные. Вы можете создать два ЦС для кластера. Первый центр будет создавать сертификаты, относящиеся к кластеру (для каждой ноды и для сервера apiserver), а второй будет обслуживать компоненты Kubernetes.

Проект центров сертификации готов, теперь можно приступать к его реализации. Во-первых, нужно создать центры сертификации и настроить роли для выдачи сертификатов. Затем нужно настроить политику vault для управления доступом к ролям ЦС и создать токены аутентификации. В завершение необходимо использовать токены, чтобы загрузить сертификаты для каждого сервиса.

2: Создание центров сертификации

Ниже вы найдёте сценарий, который загружает ЦС в Vault. Этот сценарий монтирует новый интерфейс pki к уникальным путям кластера и генерирует root сертификат для каждого бэкенда pki (срок действия сертификата – 10 лет).

vault mount -path $CLUSTER_ID/pki/$COMPONENT pki
vault mount-tune -max-lease-ttl=87600h $CLUSTER_ID/pki/etcd
vault write $CLUSTER_ID/pki/$COMPONENT/root/generate/internal \
common_name=$CLUSTER_ID/pki/$COMPONENT ttl=87600h

В клиентских сертификатах Kubernetes можно использовать поле Common Name (CN) в качестве имени пользователя. Это можно использовать для создания ролей для каждого набора запросов сертификатов.

vault write $CLUSTER_ID/pki/etcd/roles/member \
allow_any_name=true \
max_ttl="720h"

Такая роль Может создать сертификат, действительный в течение 30 дней, для каждого отдельного CN. Ниже вы найдёте роль для Kubernetes, которая может создавать сертификат только с CN kubelet.

vault write $CLUSTER_ID/pki/k8s/roles/kubelet \
allowed_domains="kubelet" \
allow_bare_domains=true \
allow_subdomains=false \
max_ttl="720h"

Каждая роль может быть ограничена одним CN (то есть создавать сертификаты только для определённого имени, например, kube-proxy или kube-scheduler), что позволяет распределить создание сертификатов для разных компонентов Kubernetes между несколькими ролями.

Если сервер apiserver является высокодоступным и работает отдельно от контроллера, можно сгенерировать для них общий закрытый ключ с помощью флага –service-account-private-key-file.

openssl genrsa 4096 > token-key
vault write secret/$CLUSTER_ID/k8s/token key=@token-key
rm token-key

Кроме ролей нужно также создать политики для каждого компонента кластера. Политика позволяет ограничить доступ. Ниже вы найдёте политику для нод кластера, которая открывает доступ к созданию сертификата.

cat <<EOT | vault policy-write $CLUSTER_ID/pki/etcd/member -
path "$CLUSTER_ID/pki/etcd/issue/member" {
policy = "write"
}
EOT

Эта политика сервера apiserver позволяет создать сертификат и прочитать закрытый ключ учетной записи сервиса, сгенерированный выше.

cat <<EOT | vault policy-write $CLUSTER_ID/pki/k8s/kube-apiserver -
path "$CLUSTER_ID/pki/k8s/issue/kube-apiserver" {
policy = "write"
}
path "secret/$CLUSTER_ID/k8s/token" {
policy = "read"
}
EOT

Теперь у вас есть структура ЦС и политики, созданные в Vault. После этого необходимо настроить каждый компонент для извлечения и обновления своих сертификатов.

3: Извлечение сертификатов

У каждого устройства есть токен Vault, который можно продлить на неопределенный срок. Этот токен предоставляется только тем политикам, которые ему необходимы. Установить роль токена в Vault можно так:

vault write auth/token/roles/k8s-$CLUSTER_ID \
period="720h" \
orphan=true \
allowed_policies="$CLUSTER_ID/pki/etcd/member,$CLUSTER_ID/pki/k8s/kube-apiserver..."

Затем с помощью этой роли можно собрать токены для указанных политик данной ноды К примеру, сгенерировать токен можно с помощью этой команды:

vault token-create \
-policy="$CLUSTER_ID/pki/etcd/member" \
-role="k8s-$CLUSTER"

Осталось только настроить соответствующие сертификаты для каждого сервиса.

4: Настройка сервисов

Для настройки сервисов можно использовать consul-template. Это средство позаботится об обновлении токена Vault, получении новых сертификатов и уведомлении служб о необходимости перезапуска при наличии новых сертификатов. Конфигурация consul-template выглядит так:

{
"template": {
"source": "/opt/consul-template/templates/cert.template",
"destination": "/opt/certs/etcd.serial",
"command": "/usr/sbin/service etcd restart"
},
"vault": {
"address": "VAULT_ADDRESS",
"token": "VAULT_TOKEN",
"renew": true
}
}

Инструмент consul-template содержит только один файл для каждого шаблона, а сам сертификат необходимо разделить на компоненты (сертификат, закрытый ключ). Для этого можно использовать этот плагин, который принимает данные, путь к файлу и информацию о его владельце. Шаблон сертификата для нод использует этот плагин:

{{ with secret "$CLUSTER_ID/pki/data/issue/member" "common_name=$FQDN"}}
{{ .Data.serial_number }}
{{ .Data.certificate | plugin "certdump" "/opt/certs/etcd-cert.pem" "etcd"}}
{{ .Data.private_key | plugin "certdump" "/opt/certs/etcd-key.pem" "etcd"}}
{{ .Data.issuing_ca | plugin "certdump" "/opt/certs/etcd-ca.pem" "etcd"}}
{{ end }}

Процесс etcd имеет следующие параметры, благодаря чему и равноправные ноды, и клиенты должны предоставить сертификат Vault, чтобы создать подключение.

--peer-cert-file=/opt/certs/etcd-cert.pem
--peer-key-file=/opt/certs/etcd-key.pem
--peer-trusted-ca-file=/opt/certs/etcd-ca.pem
--peer-client-cert-auth
--cert-file=/opt/certs/etcd-cert.pem
--key-file=/opt/certs/etcd-key.pem
--trusted-ca-file=/opt/certs/etcd-ca.pem
--client-cert-auth

Сервер apiserver использует шаблон сертификата для связи с кластером и ещё один шаблон для компонентов Kubernetes; для настройки процесса использованы такие флаги:

--etcd-certfile=/opt/certs/etcd-cert.pem
--etcd-keyfile=/opt/certs/etcd-key.pem
--etcd-cafile=/opt/certs/etcd-ca.pem
--tls-cert-file=/opt/certs/apiserver-cert.pem
--tls-private-key-file=/opt/certs/apiserver-key.pem
--client-ca-file=/opt/certs/apiserver-ca.pem

Первые три флага позволяют серверу apiserver взаимодействовать с кластером. Два флага TLS позволяют ему обслуживать API по соединению TLS; последний флаг позволяет ему проверять сертификаты клиентов (они должны быть подписаны центром сертификации, выдавшим сертификат apiserver).

Заключение

Каждому компоненту архитектуры можно присвоить уникальный сертификат, и весь процесс полностью автоматизирован. Кроме того, вы можете получить доступ к логу, в котором регистрируются все выданные сертификаты и отслеживается истечение срока действия сертификата и его ротация.

Используя Vault в качестве центра сертификации, вы можете значительно сократить усилия, необходимые для создания и поддержки кластеров Kubernetes.

Tags: , ,

Добавить комментарий