четверг, 17 июля 2025 г.

Wildcard SSL сертификат

Понадобилось сгенерировать wildcard SSL сертификат и раскладывать его по пространствам имён в Kubernetes кластере. Этот сертификат будет использоваться в тестах которые выполняются для набора приложений на каждый запрос на слияние.

В cert-manager настроен ClusterIssuer LE с валидацией через DNS01. Выпуск wildcard сертификата у Let's Encrypt поддерживается только через DNS валидацию и протокол ACMEv2. В примере использован сервис Cloud DNS от Google Cloud Platform.

apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-production
spec:
  acme:
    email: certificates@example.com
    privateKeySecretRef:
      name: letsencrypt-production
    server: https://acme-v02.api.letsencrypt.org/directory
    solvers:
    - dns01:
        cloudDNS:
          project: GCP_PROJECT_ID

Манифест для wildcard сертификата (сам сертификат и ключ будут созданы в пространстве имён cert-manager)

apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
  name: wildcard-example-com
  namespace: cert-manager
spec:
  commonName: '*.example.com'
  dnsNames:
  - '*.example.com'
  issuerRef:
    kind: ClusterIssuer
    name: letsencrypt-production
  privateKey:
    algorithm: RSA
    size: 2048
  secretName: wildcard-example-com-tls

Cert-manager не умеет раскидывать секреты самостоятельно и я использовал Kyverno (т.к. он у нас уже используется), но сам cert-manager предлагает использовать reflector или kubernetes-replicator.

Политика Kyverno настроена копировать секрет только в определённые пространства имён, которые соответствуют шаблону "test-*".

apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: copy-wildcard-example-com-tls-secret
spec:
  rules:
  - name: copy-wildcard-example-com-tls-secret
    match:
      any:
      - resources:
          kinds:
          - Namespace
          names:
          - "test-*"
    generate:
      apiVersion: v1
      kind: Secret
      name: wildcard-example-com-tls
      namespace: '{{request.object.metadata.name}}'
      synchronize: true
      clone:
        name: wildcard-example-com-tls
        namespace: cert-manager

Чтобы у Kyverno были права работать с секретами нужно добавить дополнительные разрешения в values чарта Kyverno

admissionController:
  rbac:
    clusterRole:
      extraResources:
        - apiGroups:
            - ''
          resources:
            - secrets
          verbs:
            - get
            - list
backgroundController:
  rbac:
    clusterRole:
      extraResources:
        - apiGroups:
            - ''
          resources:
            - secrets
          verbs:
            - get
            - create
            - update
            - delete

Без дополнительных прав у Kyverno создание политики она будет завершаться ошибками:

  •  admission webhook "validate-policy.kyverno.svc" denied the request: path: spec.rules[0].generate..: system:serviceaccount:kyverno:kyverno-admission-controller requires permissions list,get for resource v1/Secret in namespace {{request.object.metadata.name}}
  • admission webhook "validate-policy.kyverno.svc" denied the request: path: spec.rules[0].generate..: system:serviceaccount:kyverno:kyverno-background-controller requires permissions get,create,update,delete for resource v1/Secret in namespace {{request.object.metadata.name}}

Теперь при создании нового пространства имён (например test-app-pr-123) в нём будет создана копия секрета содержащая wildcard сертификат.

В виде альтернативы можно назначить этот сертификат как сертификат по-умолчанию в ингрес контроллере и тогда можно обойтись без копирования секретов и Kyverno. 

Комментариев нет:

Отправить комментарий