Vault для секретов
AiHummer хранит все доступы — токены каналов, пароли SMTP/IMAP, OAuth-токены, ключи LLM на арендатора (BYOK) — в зашифрованном vault для секретов. Vault использует конвертное шифрование, поэтому значение в покое нельзя прочитать из одной только базы данных, и устроен так, что секрет никогда не попадает в контекст модели и в логи.
Конвертное шифрование
Vault использует двухуровневую иерархию ключей:
- Мастер-ключ (KEK) — задаётся через
AIHUMMER_MASTER_KEY, это base64-кодированное значение из 32 байт — оборачивает и разворачивает ключи данных. Он не покидает хост и никогда не пишется в базу. - Ключ шифрования данных на арендатора (DEK) шифрует сами значения секретов алгоритмом AES-256-GCM (аутентифицированное шифрование). У каждого арендатора свой DEK, поэтому ключами одного арендатора нельзя расшифровать секреты другого.
Значения секретов хранятся как шифротекст; DEK хранится обёрнутым в KEK. Расшифровка происходит в памяти в момент, когда секрет нужен (например, когда коннектор проходит аутентификацию), а открытый текст затем отбрасывается.
AIHUMMER_MASTER_KEY (KEK) ──оборачивает──▶ DEK арендатора ──AES-256-GCM──▶ значение секрета
[!NOTE] Vault опирается на расширение PostgreSQL
pgcrypto. Убедитесь, что оно доступно в вашей базе — это часть стандартных системных требований.
Мастер-ключ
Мастер-ключ — это bootstrap-значение: он читается из окружения при старте и не настраивается из веб-админки.
# /home/.aihummer/etc/gateway.env
# 32 случайных байта в base64
AIHUMMER_MASTER_KEY=Base64Of32RandomBytes==
Сгенерировать его можно так:
openssl rand -base64 32
[!WARNING] Мастер-ключ нужен для расшифровки всего содержимого vault. Относитесь к нему как к корню ваших секретов и делайте резервную копию отдельно от базы данных — если вы его потеряете, зашифрованные значения восстановить нельзя.
Без мастер-ключа
Если AIHUMMER_MASTER_KEY не задан, vault и всё, что от него зависит,
отключены: хранение секретов в покое, vault доступов и ключи BYOK на
арендатора выключены. Это намеренное поведение fail-closed — продукт не
переходит молча к хранению секретов в открытом виде.
Секреты не доходят до модели
Это важнейшее свойство vault, и оно структурное, а не просто напоминание о политике.
[!DANGER] Секреты никогда не внедряются в системный промпт, в историю диалога или в любой видимый модели текст и никогда не пишутся в логи. Инструменты, которым нужен доступ, получают его из vault в момент вызова, внутри gateway, и используют для аутентификации исходящего запроса — модель видит только результат вызова инструмента, а не сам секрет.
Поскольку интерактивность строится на вызове инструментов (см. Guardrails и защиту от инъекций), нет пути, по которому промпт мог бы попросить модель «зачитать» сохранённый секрет: у модели нет его копии для чтения.
Общие и персональные доступы
Vault различает общие (на уровне рабочей области) и персональные (на пользователя) доступы. Персональные OAuth2-токены, полученные через поток Connections, хранятся в vault и разрешаются по действующему пользователю, с fallback на рабочую область, где это уместно. Это позволяет одному инструменту действовать от имени разных пользователей с их собственной авторизацией, ни разу не раскрывая токен одного пользователя другому.
Куда дальше
- RBAC и scoped API-ключи — кто может читать или менять конфигурацию, опирающуюся на vault.
- Row-Level Security — изоляция на арендатора в базе данных, на которой стоит vault.
- Guardrails и защита от инъекций — почему модель нельзя обманом заставить выдать секрет.