temporality
Изменить страницу↗
Инженерные документы

Управление секретами агентов (Secrets Management)

#1. Цель

Ввести секрет как first-class ресурс Temporality и закрыть класс проблем «агенты теряют / утекают / переизобретают свои токены доступа к внешним системам».

Секреты нужны агентам для работы с GitHub/GitLab, Jira, Slack, облачными API, базами данных и MCP-серверами. Сегодня эти креденшелы живут в контексте агента: в файлах эфемерного воркспейса, в переменных окружения песочницы, в аргументах команд. Это источник сразу нескольких проблем, и выбор хранилища сам по себе ни одну из них не решает.

Ключевой принцип документа: агент не должен держать сырые значения секретов. Агент оперирует ссылкой, значение разрешается ядром на границе исполнения инструмента и не проходит через модель, события и файлы.


#2. Проблематика текущего состояния


#3. Основные понятия

#3.1. Secret (секрет)

Org-scoped ресурс (как агенты, навыки и MCP-серверы):

workspace_secret
    id            TEXT PRIMARY KEY
    org_unit_id   TEXT NULL REFERENCES org_unit(id)   -- NULL = вся инсталляция
    name          TEXT          -- человекочитаемое имя, напр. github-repo-write
    provider      TEXT          -- где лежит значение: builtin | env (внешние хранилища — фаза 2)
    external_ref  TEXT NULL     -- ссылка на запись во внешнем хранилище (для не-builtin)
    description   TEXT
    created_at / updated_at

Секрет — это указатель + права, а не обязательно само значение. Для builtin-провайдера значение хранится в зашифрованной таблице Postgres, для внешних провайдеров — в них, а у нас только ссылка.

#3.2. Secret Reference (ссылка на секрет)

Строка вида secret://<name> (опционально secret://<name>#<key> для многозначных записей). Ссылки используются везде, где сегодня пишутся сырые ключи: в конфигурации агента, MCP-серверов, провайдеров моделей, триггеров.

Ссылка — это и есть интерфейс для модели: агент видит secret://github, но никогда — значение.

#3.3. Secret Provider (провайдер хранилища)

Интерфейс ядра, скрывающий конкретный бэкенд:

Get(reference, executionContext) -> (value, lease)
Issue(request, executionContext) -> (reference, lease)   -- для dynamic secrets
Revoke(lease)

Реализации: builtin (Postgres + envelope-шифрование AES-256-GCM) и env. Заявлено на фазу 2 (интерфейс бэкендов и lease-модель ниже — план): infisical, vault/openbao, aws-sm, gcp-sm, azure-kv. Выбор бэкенда — конфигурация инсталляции, не код.

#3.4. Credential Lease (аренда креденшела)

Выдача значения на ограниченный срок конкретному запуску. Lease несёт TTL, идентичность получателя (execution identity) и подлежит отзыву. Для статических секретов lease — это разрешение на кэширование в памяти ядра; для динамических — короткоживущий токен, сгенерированный провайдером.


#4. Принцип: агент не держит секрет

#4.1. Разрешение на границе исполнения

Единственная точка, где ссылка превращается в значение, — ядро в момент исполнения инструмента:

#4.2. Куда значение не попадает никогда

#4.3. Redaction как вторая линия

Даже при брокер-схеме журнал получает фильтр маскирования на ingest: известные форматы токенов (ghp_*, gho_*, AKIA*, xoxb-*, Bearer-заголовки, приватные ключи) заменяются на <redacted:kind>. Фильтр настроен на гарanteed-детектируемые паттерны и не пытается угадать «похожее на ключ» — чтобы не калечить легитимный контент. Это защита от человеческих ошибок вне брокер-пути, а не основной механизм.


#5. Границы доверия

┌──────────┐   ссылка secret://    ┌─────────────┐   lease + value   ┌────────────┐
│  Агент   │ ─────────────────────▶│    Ядро     │ ────────────────▶ │  Provider  │
└──────────┘                       │ (execution  │                   │ (vault/    │
       ▲                           │  identity)  │                   │  builtin)  │
       │ значение не проходит      └─────────────┘                   └────────────┘

#6. Динамические секреты и ротация

Федерация без статических токенов — отдельный приоритетный кейс:


#7. Аудит

Каждое обращение к секрету — событие journal:

secret.issued    (run_id, secret_id, lease_id, ttl)        -- выдан lease
secret.denied    (run_id, secret_id, policy_violation)      -- отказ с причиной

Заявлено на фазу 2: secret.accessed (использован в операции), secret.revoked (отзыв lease'ов).

Это даёт ответы на вопросы «кто пользовался скомпрометированным ключом», «какие секреты фактически не используются» (кандидаты на отзыв) — и ложится в существующую модель наблюдаемости: события видны в трейсе рана, агрегируются в таймлайне, экспортируются в SIEM.


#8. Доступ агента к секретам

Агенту доступны два инструмента:

В системном промпте агента фиксируется контракт: «секреты передаются ссылками secret://, значения подставляются системой; не пытайся читать, записывать или пересылать значения токенов».


#9. Отказоустойчивость


#10. Оценка бэкендов для больших компаний

Критерий Infisical Vault / OpenBao CyberArk Облачные SM builtin (Postgres)
Self-hosted, данные у себя ✅ open source ✅ (OpenBao — MPL; Vault — BUSL) ✅ (платный) ❌ ✅
Зрелость на enterprise-масштабе растёт ✅ доказан ✅ инкамбент ✅ в своём облаке локальный масштаб
Динамические секреты, TTL ✅ ✅ широчайшие ✅ частично ❌
HSM / FIPS ограниченно ✅ (Vault ent) ✅ зависит от облака ❌
Аудит → SIEM API, допиливать ✅ ✅ CloudTrail-стайл journal-события
Усилие внедрения недели месяцы месяцы низкое (если облако своё) дни
Конфликт с корпстандартом вероятен обычно уже одобрен обычно уже одобрен обычно уже одобрен нет

Выводы:

Архитектурный вывод: благодаря интерфейсу провайдера выбор бэкенда — конфигурация инсталляции. Начинаем с builtin, добавляем Infisical и Vault/OpenBao адаптеры, enterprise-клиент подключает то, что одобрено.


#11. API


#12. UI


#13. Фазы реализации

#Фаза 1 — брокер и builtin (закрывает основную боль)

Ресурс workspace_secret + миграция; ссылки secret:// в конфигах агентов/MCP/провайдеров; разрешение в ядре на границе инструментов (HTTP-заголовки, env песочницы, tmpfs); события secret.*; redaction-фильтр journal; тул secret_list; UI-раздел. Внешних зависимостей нет.

#Фаза 2 — внешние провайдеры

Интерфейс SecretProvider как публичный контракт; адаптеры Infisical и Vault/OpenBao; аутентификация ядра по execution identity; динамические секреты и ротация; revoke-операции; grants + policies-гейтинг.

#Фаза 3 — федерация и enterprise

GitHub Apps-брокер (installation-токены); OIDC/STS-федерация для облаков; экспорт аудита в SIEM; fail-open политики; синхронизация видимости с оргструктурой при её изменении (события org unit уже есть).


#14. Критерии готовности

#Фаза 1

#Фаза 2

#Фаза 3


#15. Открытые вопросы


#16. Архитектурные ограничения