Database engine: креды для Postgres

Пошагово настраиваем выдачу временных пользователей PostgreSQL по запросу.

Database secrets engine — движок Vault, генерирующий временные учётные данные к базам данных (PostgreSQL, MySQL и др.) по запросу, создавая и удаляя пользователей в самой БД.

Это самый частый первый сценарий динамических секретов. Настройка состоит из двух частей: соединение (как Vault достучится до БД) и роль (какого пользователя и с какими правами создавать).

Шаг 1. Включить движок

vault secrets enable database

Шаг 2. Настроить соединение

Vault нужен привилегированный пользователь БД, под которым он будет создавать и удалять временных юзеров:

vault write database/config/orders-db \
  plugin_name=postgresql-database-plugin \
  allowed_roles="readonly" \
  connection_url="postgresql://{{username}}:{{password}}@db.internal:5432/orders?sslmode=require" \
  username="vault_admin" \
  password="super-admin-pass"

Плейсхолдеры {{username}} и {{password}} Vault подставит из своих полей — это позволяет ему потом ротировать собственный пароль.

Шаг 3. Описать роль

Роль задаёт SQL-команды создания и удаления пользователя и сроки аренды:

vault write database/roles/readonly \
  db_name=orders-db \
  creation_statements="CREATE ROLE \"{{name}}\" WITH LOGIN PASSWORD '{{password}}' VALID UNTIL '{{expiration}}'; GRANT SELECT ON ALL TABLES IN SCHEMA public TO \"{{name}}\";" \
  default_ttl=1h \
  max_ttl=24h

Здесь creation_statements — шаблон: Vault подставит уникальные {{name}}, {{password}} и {{expiration}} при каждом запросе. Роль даёт только SELECT — least privilege на уровне самой БД.

Шаг 4. Запросить креды

vault read database/creds/readonly
{
  "lease_id": "database/creds/readonly/7gH2k",
  "lease_duration": 3600,
  "data": {
    "username": "v-token-readonly-a1B2c3",
    "password": "X9-generated-pass"
  }
}

Приложение берёт эти username/password и подключается к PostgreSQL обычным образом — для самой БД это нормальный пользователь, просто временный.

Как работает под капотом

При запросе Vault под пользователем vault_admin выполняет creation_statements с подставленными значениями, создавая роль с VALID UNTIL равным концу аренды. Регистрируется lease. По истечении (или при revoke) Vault выполняет revocation_statements (по умолчанию — DROP ROLE), удаляя пользователя. VALID UNTIL в самой БД — дополнительная страховка: даже если Vault не успеет удалить роль, Postgres сам не пустит её после срока.

Частые ошибки

  • Дать роли широкие гранты (ALL PRIVILEGES) — временный юзер становится опасным; держите least privilege и в SQL.
  • Привилегированный пользователь Vault без прав CREATE ROLE — движок не сможет создавать юзеров.
  • Забыть allowed_roles в config — роль не сможет использовать это соединение.
  • Слишком большой max_ttl — теряется смысл короткоживущих кредов.

Итог

  • Database engine настраивается из соединения (привилегированный юзер) и роли (SQL создания/удаления).
  • Каждый запрос даёт уникального временного пользователя с VALID UNTIL на срок аренды.
  • Права роли в SQL держите минимальными — least privilege и на уровне БД.
Проверьте себя
1. Из каких двух частей состоит настройка database engine?
AListener и storage
BСоединение (как Vault ходит в БД) и роль (какого юзера создавать)
CПолитика и токен
DSeal и unseal
2. Зачем в creation_statements указывают VALID UNTIL '{{expiration}}'?
AДля ускорения запроса
BЧтобы сама БД отказала пользователю после срока, даже если Vault не успеет его удалить
CЭто обязательный синтаксис CREATE ROLE
DЧтобы зашифровать пароль
3. Под чьими правами Vault создаёт временных пользователей в БД?
AПод правами приложения
BПод привилегированным пользователем из config соединения
CПод root-токеном Vault
DПод анонимным доступом