DevOps

Настройка Vault Agent для chown TLS-сертификатов PostgreSQL

Как настроить Vault Agent sidecar в Kubernetes для динамической генерации и ротации TLS-сертификатов PostgreSQL в non-root контейнере. Решение проблем с chown 70:70 в split_cert.sh, vault pki и injector аннотации.

5 ответов 1 просмотр

Как настроить Vault Agent (sidecar), чтобы команда template command успешно выполняла chown 70:70 для генерируемых TLS-сертификатов PostgreSQL в общем volume (/vault/certs/postgres), монтируемом в контейнер Postgres? Почему скрипт split_cert.sh не может изменить владельца файлов на UID/GID 70:70 (пользователь postgres), и какие рекомендуемые подходы для динамической генерации и ротации сертификатов с non-root контейнером PostgreSQL?

Vault Agent в режиме sidecar для hashicorp vault генерирует динамические TLS-сертификаты PostgreSQL в общем volume /vault/certs/postgres, но скрипт split_cert.sh не может выполнить chown 70:70 из-за запуска от пользователя vault (uid=100, gid=1000) — возникает ошибка “Operation not permitted”. Это типичная проблема в vault kubernetes с non-root контейнером Postgres (UID/GID 70:70), где ручной chown от root работает, но автоматизация требует securityContext или initContainer. Рекомендуется использовать vault agent injector с аннотациями для прямой инъекции секретов и ротации postgres сертификат без постобработки скриптами.


Содержание


Введение в hashicorp vault и vault agent для PostgreSQL

Представьте: ваш PostgreSQL в Kubernetes работает в non-root контейнере под UID 70:70 для безопасности, но TLS-сертификаты нужно генерировать динамически. Здесь на помощь приходит hashicorp vault с vault agent в режиме sidecar. Это не просто хранение секретов — это полноценная система для выдачи и ротации postgres сертификат через vault pki.

Почему это актуально? В продакшене статические certs устаревают, а ручная ротация — это боль. Vault agent инжектирует секреты в shared volume, монтируемый в под PostgreSQL. Но вот засада: sidecar пишет файлы от своего пользователя (обычно uid=100), а Postgres их не видит под 70:70. Разберём по шагам, как это починить.

Hashicorp vault kubernetes упрощает жизнь с помощью Injector — мутирующий webhook, который добавляет sidecar автоматически по аннотациям. По данным официальной документации HashiCorp, это стандарт для postgresql tls.


Настройка vault kubernetes injector и sidecar для postgres сертификат

Сначала установите Vault Helm chart в кластер. Добавьте namespace с лейблом vault.hashicorp.com/role: postgres-role:

yaml
apiVersion: v1
kind: Namespace
metadata:
 name: postgres-ns
 labels:
 vault.hashicorp.com/role: postgres-role

Injector — это Deployment с webhook’ом. В values.yaml Helm укажите:

yaml
injector:
 enabled: true
 image:
 repository: hashicorp/vault

Для вашего Deployment Postgres добавьте аннотации:

yaml
apiVersion: apps/v1
kind: Deployment
metadata:
 annotations:
 vault.hashicorp.com/agent-inject: "true"
 vault.hashicorp.com/role: "postgres-role"
 vault.hashicorp.com/agent-inject-secret-postgres-tls: "pki/issue/postgres-server"
spec:
 template:
 spec:
 containers:
 - name: postgres
 image: postgres:15
 securityContext:
 runAsUser: 70
 runAsGroup: 70
 volumeMounts:
 - mountPath: /vault/certs/postgres
 name: vault-certs
 volumes:
 - name: vault-certs
 emptyDir: {}

Vault kubernetes добавит sidecar vault-agent с shared volume /vault/certs/postgres. Sidecar рендерит секреты из vault pki, а Postgres их читает. Но если нужен кастомный скрипт вроде split_cert.sh, проблемы с правами неизбежны.

А вы пробовали без скриптов? Injector может сам split’ить bundle в crt/key.


Конфигурация vault agent template для генерации TLS-сертификатов

Сердце — конфиг vault-agent-config.json в ConfigMap или secret. Для vault agent template:

json
{
 "vault": {
 "address": "http://vault.default.svc.cluster.local:8200"
 },
 "template": [{
 "source": "{{ with secret \"pki/issue/postgres-server\" \"common_name=postgres-server\" }} {{ .Data.certificate | b64decode }} {{ .Data.private_key | b64decode }} {{ end }}",
 "destination": "/vault/certs/postgres/bundle.pem",
 "command": "/scripts/split_cert.sh"
 }],
 "auto_auth": {
 "method": {
 "type": "kubernetes"
 }
 }
}

Команда command запускает скрипт после записи bundle.pem. split_cert.sh выглядит так:

bash
#!/bin/sh
openssl pkcs12 -in /vault/certs/postgres/bundle.pem -out /vault/certs/postgres/server.crt -clcerts -nokeys
openssl pkcs12 -in /vault/certs/postgres/bundle.pem -out /vault/certs/postgres/server.key -nocerts -nodes
chown 70:70 /vault/certs/postgres/server.*

Запускается от vault user — и chown фейлится. Документация по template предупреждает: права зависят от securityContext sidecar’а.

Интересно, зачем split’ить вручную? Vault может выдать отдельно cert/key через разные secrets.


Проблемы с chown в split_cert.sh и vault pki в non-root контейнере

Вот в чём собака зарыта. В обсуждении на Stack Overflow описана ваша ситуация: sidecar пишет bundle.pem от uid=100, скрипт пытается chown 70:70, но “Operation not permitted”. Почему?

  • Vault agent по умолчанию — non-root (uid=100, gid=1000).
  • Non-root Postgres (70:70) не читает файлы от 100:1000 без прав.
  • Shared emptyDir не позволяет chown без CAP_FOWNER или root.

Ручной kubectl exec -u 0 с chown работает, потому что root обходит лимиты. В vault pki bundle — это PKCS12, split нужен для crt/key, но права ломают цепочку.

Это не баг hashicorp vault agent, а фича безопасности Kubernetes. Без фикса ротация сломается при рестарте пода.


Решение прав доступа: от vault tls к UID 70:70 в PostgreSQL

Фиксим по шагам. Вариант 1: securityContext в sidecar (Injector позволяет патчить).

В аннотациях добавьте:

yaml
vault.hashicorp.com/agent-extra-volume-paths: '[{"path":"/scripts","mode":"0444"}]'

Но для chown — укажите в Deployment (Injector пропустит):

yaml
spec:
 template:
 spec:
 containers:
 - name: vault-agent # sidecar
 securityContext:
 runAsUser: 0 # root для chown
 capabilities:
 add: ["FOWNER"]

Вариант 2: InitContainer перед Postgres:

yaml
initContainers:
- name: cert-init
 image: bitnami/postgres:15 # или vault:1.15
 command: ["/bin/sh", "-c"]
 args:
 - |
 while true; do
 if [ -f /vault/certs/postgres/server.crt ]; then
 chown 70:70 /vault/certs/postgres/server.*
 break
 fi
 sleep 1
 done
 securityContext:
 runAsUser: 0
 volumeMounts:
 - mountPath: /vault/certs/postgres
 name: vault-certs

Вариант 3: install вместо cp/chown в скрипте:

bash
install -m 644 -o 70 -g 70 bundle.pem /vault/certs/postgres/server.crt # но требует root

Или sudoers в image sidecar’а (не рекомендуется). Лучше initContainer — он ждёт sidecar и фиксит права атомарно.

Для vault tls ротации добавьте vault.hashicorp.com/renew-interval: "24h".


HashiCorp рекомендует избегать скриптов: используйте несколько secrets.

Аннотация для отдельных файлов:

yaml
vault.hashicorp.com/agent-inject-secret-server-cert: "pki/cert/postgres-server"
vault.hashicorp.com/agent-inject-secret-server-key: "pki/private/postgres-server/key"
vault.hashicorp.com/template-server-cert: |
 {{ with secret "pki/issue/postgres-server" "common_name=postgres-server" -}}
 {{- .Data.certificate -}}
 {{- end -}}

Injector сам chown’ит по umask или fsGroup. В Pod spec:

yaml
securityContext:
 fsGroup: 70

Это магия: Kubernetes меняет группу на 70 при записи в volume. Работает для emptyDir/PVC. Для postgresql tls настройте в postgresql.conf:

ssl_cert_file = '/vault/certs/postgres/server.crt'
ssl_key_file = '/vault/certs/postgres/server.key'

Ротация? vault.hashicorp.com/agent-pre-populate-only: "false" — sidecar следит и обновляет.

Это чище, чем split_cert.sh. Примеры в доках подтверждают.


Примеры аннотаций и ротация сертификатов в hashicorp vault agent

Полный Deployment пример:

yaml
metadata:
 annotations:
 vault.hashicorp.com/agent-inject: 'true'
 vault.hashicorp.com/role: 'postgres-role'
 vault.hashicorp.com/agent-inject-template-server-cert: |
 {{ with secret "pki/issue/postgres-server" "ttl=24h" }}
 {{ .Data.certificate }}
 {{ end }}
 vault.hashicorp.com/template-path-server-cert: '/vault/certs/postgres/server.crt'
 vault.hashicorp.com/agent-inject-secret-ca: 'pki/cert/ca'
spec:
 securityContext:
 fsGroup: 70
 containers:
 - name: postgres
 volumeMounts:
 - mountPath: /var/lib/postgresql/data/certs # symlink или bind
 name: vault-certs

Ротация: sidecar проверяет TTL, перезапрашивает при истечении. Для hashicorp vault agent укажите failureMode: ignore в аннотациях, чтоб под стартовал без certs (graceful).

Тестируйте: kubectl logs vault-agent-xxxx покажет логи рендера.


Альтернативы и аналоги hashicorp vault для Kubernetes

Не фанат Vault? Cert-Manager + external issuer (ACME/VAULT) проще для postgres сертификат.

yaml
apiVersion: cert-manager.io/v1
kind: Certificate
spec:
 secretName: postgres-tls
 issuerRef:
 name: vault-issuer
 kind: ClusterIssuer

Или ExternalSecrets Operator: синхронит Vault в K8s secrets, затем volume mount. Но для динамики Vault выигрывает.

Kubernetes CSI driver secrets store — экспериментально. AWS/GCP Secrets Manager с sidecar proxies. Выбор за вами, но vault kubernetes — золотой стандарт для enterprise.


Источники

  1. Vault Agent template command cannot chown generated PostgreSQL certificates — Обсуждение проблемы chown в split_cert.sh для Vault Agent sidecar: https://stackoverflow.com/questions/79897791/vault-agent-template-command-cannot-chown-generated-postgresql-certificates-to-u
  2. Vault Agent with Kubernetes — Документация по настройке Vault Injector в Kubernetes: https://developer.hashicorp.com/vault/docs/platform/k8s/injector
  3. Vault Agent Template — Руководство по шаблонам и командам в Vault Agent: https://developer.hashicorp.com/vault/docs/agent/template
  4. Vault Injector Examples — Примеры аннотаций для секретов и TLS в Kubernetes: https://developer.hashicorp.com/vault/docs/platform/k8s/injector/examples

Заключение

Настройка vault agent для postgres сертификат в non-root PostgreSQL сводится к fsGroup=70 или initContainer — это решает chown без хаков. Забудьте split_cert.sh: используйте нативные шаблоны vault pki и аннотации injector для seamless ротации postgresql tls. В итоге — безопасные, динамические certs без даунтайма. Начните с теста в dev-ns, и ваш кластер скажет спасибо.

U

Vault Agent sidecar генерирует TLS-сертификаты для PostgreSQL в общем volume /vault/certs/postgres с помощью шаблона template и команды split_cert.sh. Скрипт извлекает server.crt и server.key из bundle.pem, но не может выполнить chown 70:70 из-за запуска от пользователя vault (uid=100, gid=1000) — ошибка “Operation not permitted”. Ручной chown от root работает, файлы читаются Postgres (70:70). Предложение: добавить sudoers для vault user или использовать install -o 70 -g 70. Это типичная проблема HashiCorp Vault Agent в Vault Kubernetes с non-root контейнерами.

HashiCorp Developer / Портал документации

Vault Agent Injector в Vault Kubernetes добавляет sidecar-контейнеры для рендеринга секретов в shared volume с помощью аннотаций вроде vault.hashicorp.com/agent-inject-secret. Поддерживает TLS volumes для client/CA certs и ключей (vault.hashicorp.com/tls-secret). Это позволяет динамически генерировать Postgres сертификат и PostgreSQL TLS без ручного chown, инжектируя секреты напрямую в под. Рекомендуется для HashiCorp Vault в K8s с ротацией certs.

HashiCorp Developer / Портал документации

Vault Agent template использует Consul Template для записи секретов из Vault PKI в файлы, включая Vault TLS certs. В конфиге template указывается contents с secret kt-int/issue/postgres-server и destination в shared volume. Команда (command) запускает скрипты вроде split_cert.sh для постобработки, но требует прав для chown в non-root setup. Идеально для HashiCorp Vault Agent с PostgreSQL.

HashiCorp Developer / Портал документации

Примеры аннотаций для Vault Injector в HashiCorp Vault Kubernetes: vault.hashicorp.com/agent-inject-template-db-creds для PostgreSQL creds и vault.hashicorp.com/ca-cert для TLS. Под добавляет init/sidecar контейнеры, монтирует shared volume для Postgres сертификат. После патча под reschedule’ится с Vault Agent, решая ротацию без ручного вмешательства в права доступа.

Авторы
U
Разработчик
Источники
Stack Overflow / Платформа вопросов и ответов
Платформа вопросов и ответов
HashiCorp Developer / Портал документации
Портал документации
Проверено модерацией
НейроОтветы
Модерация