Создание сертификатов для Ingress-объектов
1. Цель
Цель статьи — создание сертификатов для Ingress объектов, включая этапы:
-
Создание ресурса Issuer типа
SelfSignedв cert-manager; -
Создание ресурса Ingress с аннотацией к созданному Issuer, который будет автоматически выпускать сертификаты для Ingress.
2. Cert-manager
cert-manager создает сертификаты TLS для рабочих нагрузок в кластере Kubernetes или в платформе Nova и обновляет сертификаты до истечения срока их действия.
cert-manager может получать сертификаты от различных центров сертификации, включая: StarVault, Let’s Encrypt, HashiCorp Vault, Venafi и частные PKI.
С помощью ресурса сертификатов cert-manager’а, закрытый ключ и сертификат хранятся в Kubernetes Secret, который монтируется приложением Pod или используется контроллером Ingress. При использовании csi-driver, csi-driver-spiffe или istio-csr закрытый ключ генерируется по требованию, перед запуском приложения. Закрытый ключ никогда не покидает узел и не хранится в Kubernetes Secret.
3. Установка
cert-manager уже предустановлен в платформу Nova в пространство имен nova-cert-managment
Можете проверить установленный компонент командой:
$ kubectl get pods --namespace nova-cert-management
NAME READY STATUS RESTARTS AGE
nova-cert-manager-cainjector-759585c78d-tpwpn 1/1 Running 2 (15h ago) 26d
nova-cert-manager-dbc656674-g7c9b 1/1 Running 2 (15h ago) 26d
nova-cert-manager-webhook-6bfb9db944-ctxj6 1/1 Running 2 (15h ago) 26d
nova-trust-manager-65854d6d6c-mlgzj 1/1 Running 3 (15h ago) 26d
4. Issuers
Issuers и ClusterIssuers — это ресурсы Kubernetes, представляющие центры сертификации (ЦС), которые могут генерировать подписанные сертификаты, выполняя запросы на подписание сертификатов. Все сертификаты cert-manager требуют наличия аннотации к Issuer.
5. StarVault Issuer
StarVault Issuer представляет центр сертификации StarVault — многоцелевое хранилище секретов, которое можно использовать для подписания сертификатов для вашей инфраструктуры открытых ключей (PKI). StarVault является внешним проектом для cert-manager, поэтому в данном руководстве предполагается, что он развернут правильно, настроен и готов к подписанию. Подробнее о том, как настроить StarVault в качестве центра сертификации, вы можете прочитать здесь.
Тип Issuer обычно используется, когда StarVault уже используется в вашей инфраструктуре.
Для импортирования собственного сертификата в качестве центра сертификации в StarVault можно воспользоваться следующей командой:
$ starvault write pki/config/ca pem_bundle=@ca_bundle.pem (1)
-
ca_bundle.pem — файл, который последовательно содержит сертификат и ключ этого серитфиката.
5.1. Развертывание
Все StarVault Issuer имеют общую конфигурацию для запроса сертификатов: сервер, путь и сертификат ЦС:
-
Server— URL, по которому можно получить доступ к StarVault. -
Path— путь к StarVault, который будет использоваться для подписи. Обратите внимание, что путь должен использовать конечную точку sign. -
CA bundle— необязательное поле, содержащее закодированную в base64 строку сертификата центра сертификации, которому следует доверять соединение со StarVault. Обычно это поле всегда требуется при использовании https URL.
Сертификат можно получить с виртуальной машины с установленным StarVault по пути .
Ниже приведен пример части конфигурации с подключением сервера StarVault./opt/starvault/tls/tls.crt
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: starvault-issuer
namespace: sandbox
spec:
vault:
path: pki_int/sign/example-dot-com
server: https://starvault.vlab.local:8200
caBundle: <base64 encoded CA Bundle PEM file>
auth:
...
5.2. Аутентификация
5.2.1. A. Аутентификация через AppRole
AppRole — метод аутентификации в StarVault с помощью внутренней системы ролевой политики. Этот метод аутентификации требует, чтобы Issuer владел секретным ключом SecretID, RoleID роли, которую нужно принять, и путем к роли приложения. Секретный ключ ID должен храниться в Kubernetes Secret, который находится в том же пространстве имен, что и Issuer, или в пространстве имен ресурсов кластера в случае ClusterIssuer.
apiVersion: v1
kind: Secret
type: Opaque
metadata:
name: cert-manager-vault-approle
namespace: sandbox
data:
secretId: "MDI..."
После создания секрета, Issuer готов к развертыванию, Issuer ссылается на этот секрет, а также на ключ данных поля, хранящего идентификатор секрета.
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: starvault-issuer
namespace: sandbox
spec:
vault:
path: pki_int/sign/example-dot-com
server: https://starvault.vlab.local:8200
caBundle: <base64 encoded caBundle PEM file>
auth:
appRole:
path: approle
roleId: "291b9d21-8ff5-..."
secretRef:
name: cert-manager-vault-approle
key: secretId
5.2.2. Б. Аутентификация с помощью учетных записей служб Kubernetes
Для метода Kubernetes Auth требуется token_reviewer_jwt, который будет использоваться StarVault для аутентификации на сервере Kubernetes API.
token_reviewer_jwt может быть долгоживущим токеном учетной записи службы. Убедитесь, что токен связан с учетной записью сервиса, которая имеет необходимые разрешения для вызова TokenReview API.
Создание учетной записи службы Kubernetes и долгоживущего токена:
$ kubectl create serviceaccount -n sandbox starvault-issuer
Манифесты StarVault будут выглядеть следующим образом:
apiVersion: v1
kind: Secret
metadata:
name: starvault-issuer-secret
namespace: sandbox
annotations:
kubernetes.io/service-account.name: starvault-issuer
type: kubernetes.io/service-account-token
Разрешение учетной записи вызывать TokenReview API:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: starvault-auth-delegator
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:auth-delegator
subjects:
- kind: ServiceAccount
name: starvault-issuer
namespace: sandbox
Получение token_reviewer_jwt:
$ kubectl get secret starvault-issuer-secret -n sandbox -o jsonpath='{.data.token}' | base64 --decode -w0
Включение метода kubernetes auth в StarVault.
starvault auth enable -path=kubernetes-cluster001 kubernetes
kubectl config view --minify --flatten -ojson \
| jq -r '.clusters[].cluster."certificate-authority-data"' \
| base64 -d >/tmp/cacrt
starvault write auth/kubernetes-cluster001/config \
token_reviewer_jwt="<Token>"
kubernetes_host=<kubernetes-api-server-url> \
kubernetes_ca_cert=@/tmp/cacrt
Добавление роли RBAC, чтобы cert-manager мог получать токены для ServiceAccount:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: starvault-issuer
namespace: sandbox
rules:
- apiGroups: ['']
resources: ['serviceaccounts/token']
resourceNames: ['starvault-issuer']
verbs: ['create']
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: starvault-issuer
namespace: sandbox
subjects:
- kind: ServiceAccount
name: nova-cert-manager
namespace: nova-cert-management
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: starvault-issuer
Создание policy с названием policy-issuer в StarVault с минимальными правами для подписи сертификата:
path "pki_int/sign/example-dot-com" {
capabilities = ["create", "update"]}
Создание роль StarVault:
starvault write auth/kubernetes-cluster001/role/starvault-issuer-role \
bound_service_account_names=starvault-issuer \
bound_service_account_namespaces=sandbox \
audience="vault://sandbox/starvault-issuer" \
policies=policy-issuer \
ttl=24h
|
Рекомендуется использовать разные роли StarVault для каждого
|
Наконец, вы можете создать свой Issuer:
apiVersion: cert-manager.io/v1
kind: Issuer
metadata:
name: starvault-issuer
namespace: sandbox
spec:
vault:
path: pki_int/sign/example-dot-com
server: https://starvault.vlab.local:8200
auth:
kubernetes:
role: starvault-issuer-role
mountPath: /v1/auth/kubernetes-cluster001
serviceAccountRef:
name: starvault-issuer
5.3. Проверка развертывания Issuer
После развертывания StarVault Issuer будет отмечен как готовый, если его конфигурация соответствует действительности. Замените issuers ниже на clusterissuers, если развернут кластер.
StarVault Issuer проверяет StarVault, запрашивая конечную точку v1/sys/health, чтобы убедиться, что StarVault распечатан и инициализирован, прежде чем запрашивать сертификаты. Результат этого запроса заполнит столбец STATUS.
$ kubectl get issuers starvault-issuer -n sandbox -o wide
NAME READY STATUS AGE
starvault-issuer True Vault verified 8s
Теперь сертификаты можно запрашивать с помощью StarVault Issuer с именем starvault-issuer в пространстве имен sandbox.
6. Аннотация к Ingress ресурсу
Частым случаем использования cert-manager является запрос сертификатов, подписанных TLS, для защиты Ingress ресурсов. Это можно сделать, просто добавив аннотации к ресурсам Ingress, и cert-manager облегчит создание ресурса сертификата. За это отвечает небольшой подкомпонент cert-manager, ingress-shim.
6.1. Как это работает
Подкомпонент ingress-shim следит за ресурсами Ingress в кластере. Если он обнаружит Ingress с аннотациями, описанными в разделе Поддерживаемые аннотации, то проверит, что в том же пространстве имен, где находится ресурс Ingress, существует ресурс Certificate с именем, указанным в поле tls.secretName и настроенным, как описано в этом Ingress.
Приведенный ниже манифест создаст Ingress ресурс с привязкой к ранее созданному Issuer my-ca-issuer:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations: (1)
cert-manager.io/issuer: starvault-issuer
cert-manager.io/common-name: www.example.com
name: my-ingress
namespace: sandbox
spec:
rules:
- host: www.example.com
http:
paths:
- pathType: Prefix
path: /
backend:
service:
name: myservice
port:
number: 80
tls: (2)
- hosts:
- www.example.com
secretName: myingress-cert (3)
-
Добавление аннотации, указывающей какой issuer использовать
-
Размещение хоста в конфигурации TLS будет определять, что будет содержаться в subjectAltNames сертификата
-
cert-manager будет хранить сертификат в этом secret store
|
В платформе Nova, чтобы подписать сертификаты для своих сервисов достаточно указать в аннотации существующий ClusterIssuer |
6.2. Поддерживаемые аннотации
Можете указать следующие аннотации для ресурсов Ingress, чтобы вызвать автоматическое создание ресурсов сертификатов:
-
cert-manager.io/issuer: имяIssuer, который должен выпустить сертификат, необходимый для данногоIngress
⚠️ Эта аннотация не предполагает наличие Issuer с привязкой к пространству имен. По умолчанию будет использоваться cert-manager.io Issuer, однако в случае внешних типов Issuers должно быть использовано как для типов Issuers с привязкой к пространству имен, так и для типов Issuers с привязкой ко всему кластеру.
⚠️ Если используется Issuer для пространства имен, то он должен находиться в том же пространстве имен, что и ресурс Ingress.
-
cert-manager.io/cluster-issuer: имя ClusterIssuer для получения сертификата, необходимого для этогоIngress. Не имеет значения, в каком пространстве имен находится вашIngress, так как ClusterIssuers — это ресурс с привязкой ко всему кластеру.
⚠️ Эта аннотация является сокращением для ссылки на cert-manager.io ClusterIssuer без необходимости указывать группу и тип. Она не предназначена для указания внешнего Issuer с кластерной привязкой — для этого используйте аннотацию cert-manager.io/issuer.
Другие поддерживаемые опциональные аннотации вы можете найти на оффициальном сайте.