English translation is not available yet. Showing Russian content.
Как проектировать agent permissions (least privilege модель)?
Краткий тезис
Проектирование разрешений для AI-агентов строится на принципе наименьших привилегий (least privilege) — агент получает ровно столько доступа, сколько необходимо для выполнения конкретной задачи, и не больше. Ключевые механизмы: динамическое ограничение области (dynamic scoping) на уровне сессии и вызова, использование OAuth2- и JWT-токенов с ограниченным временем жизни, а также Human‑in‑the‑Loop (HITL) для опасных операций. Правильная модель permissions предотвращает утечки данных, несанкционированные действия и эскалацию привилегий через цепочки вызовов инструментов.
1. Термин: Agent permissions (разрешения агента)
Agent permissions — это набор прав, определяющих, какие инструменты (API, базы данных, файловые системы, внешние сервисы) может вызывать агент, какие данные он может читать/писать и в каких контекстах (сессиях, запросах) эти права действуют.
В отличие от традиционных RBAC (Role‑Based control|Access Control), где права привязаны к статической роли пользователя, агентская модель требует динамичности: один и тот же агент в разных сессиях может иметь разные разрешения в зависимости от запроса, доверенности пользователя и этапа выполнения задачи.
Термин «Least privilege» (наименьшие привилегии) — агент получает минимально необходимые права для выполнения текущего шага, а не максимально возможные.
2. Зачем нужна separate permission модель для агентов?
Без явного управления permissions агенты быстро становятся векторами атак:
| Риск | Пример |
|---|---|
| Утечка данных | Агент читает все документы, хотя нужен только один |
| Несанкционированная запись | Агент изменяет профиль другого пользователя |
| Эскалация привилегий | Агент вызывает инструмент, который сам вызывает другой инструмент с более широкими правами |
| Цепочка действий | Агент удаляет файл, а потом не может его восстановить, потому что права были временными |
Правильная модель permissions позволяет:
- Ограничить ущерб в случае компрометации агента (например, через prompt injection)
- Аудить каждое действие агента
- Динамически расширять/сужать права в зависимости от контекста
3. Принцип Least Privilege для агентов
Least privilege для агентов — это не просто «дать минимум прав при старте». Это continuous enforcement на каждом шаге:
- Минимальный набор инструментов — агент получает только те инструменты, которые прописаны в его конфигурации для данной задачи.
- Минимальные данные — агент видит только те документы/записи, которые релевантны запросу (фильтрация на уровне retrieval).
- Минимальная область влияния — агент может изменять только объекты, принадлежащие текущему пользователю или сессии.
Пример: агент поддержки клиентов
- Разрешено
read:tickets(только свои тикеты),write:notes(только заметки в своём тикете) - Запрещено
read:user_profiles, write:status (изменение статуса тикета — только через HITL)
4. Dynamic scoping — ключ к гибкости
Dynamic scoping — механизм, при котором разрешения определяются не статически (на уровне агента), а динамически на основе:
- Сессии пользователя — права привязаны к идентификатору сессии
- Запроса — из запроса извлекаются параметры (например, user_id, document_id)
- Вызова инструмента — каждый вызов получает свежий токен с ограниченным временем
Уровни dynamic scoping:
| Уровень | Описание | Пример |
|---|---|---|
| Session‑level | Права действуют только в пределах одной сессии (диалога) | Агент может читать документы, загруженные в эту сессию |
| Request‑level | Права действуют только на время обработки одного запроса | После ответа токен инвалидируется |
| Call‑level | Права действуют только на один вызов инструмента | Каждый вызов API получает одноразовый токен |
Реализация передача scoped‑токена в каждом вызове инструмента через context (например, в LangGraph — State).
5. Типы scopes (областей доступа)
Scopes (или scope tokens) — строковые идентификаторы, описывающие разрешения. Рекомендуется следовать синтаксису action:resource: read:documents, write:user_profile_own.
Примеры типовых scopes для агента:
| Scope | Описание | Когда использовать |
|---|---|---|
read:documents | Чтение документов из векторного хранилища | Для retrieval‑агентов |
write:user_profile_own | Запись только в свой профиль | Агент‑помощник, редактирующий профиль |
send:email | Отправка email (с HITL) | Агент‑коммуникатор |
execute:code_sandbox | Запуск кода в изолированной среде | Агент‑программист |
read:knowledge_base_kb42 | Чтение только из конкретной базы знаний | Для агента по продукту X |
Правила именования
- {action}:{resource} — широкий scope
- {action}:{resource}_{sub_resource} — более узкий
- {action}:{resource}?filter=owner_id — с фильтром по владельцу (dynamic scoping)
6. Human‑in‑the‑Loop (HITL) как разновидность permissions
Human‑in‑the‑Loop — обязательное подтверждение человека перед выполнением опасного действия. Это не отдельный scope, а gate (шлюз) на уровне runtime.
Примеры действий, требующих HITL:
- Отправка email от имени пользователя
- Удаление файлов
- Создание пользователей с повышенными правами
- Выполнение денежных транзакций
Реализация
# Псевдокод: вызов инструмента с HITL
tool_call = {
"tool": "send_email",
"params": {...},
"scope": "send:email",
"hitl_required": True
}
# Runtime приостанавливает выполнение, ждёт подтверждения от человека
response = await hitl_approve(tool_call)
Важно HITL не должен быть единственным барьером — scope всё равно должен быть минимальным (например, send:email только на свой домен).
7. Реализация: OAuth2 Scopes и JWT
Современные агенты обычно развёрнуты как микросервисы. Протокол OAuth2 с JWT (JSON Web Tokens) — стандарт де‑факто для передачи scopes.
Процесс:
- Аутентификация пользователя — получает access_token с базовыми scopes (например, role:user).
- Инициализация сессии агента — агент получает свой собственный JWT, подписанный сервером, с ограниченным временем жизни (TTL) и scopes, унаследованными от пользователя, но суженными до необходимого минимума.
- Каждый вызов инструмента — передаёт JWT, сервер проверяет:
- Возврат результата — токен не обновляется, после завершения сессии он теряет силу.
Пример структуры JWT (payload):
{
"sub": "agent_session_abc123",
"user_id": "user_42",
"scopes": ["read:documents_owned", "write:notes_own"],
"iat": 1717000000,
"exp": 1717003600,
"context": {
"session_id": "session_789",
"max_documents_read": 10
}
}
Дополнительные фичи
- One‑time tokens — для call‑level scoping (токен можно использовать только один раз)
- Token binding — привязка к конкретному агенту (проверка
client_id)
8. Аудит и мониторинг permissions
Даже идеальная модель permissions бесполезна без логирования. Каждый вызов инструмента должен записывать:
- ID сессии, пользователя, агента
- Запрошенный scope
- Результат проверки (allowed / denied)
- Время жизни токена
Инструменты: OpenTelemetry для трассировки, ELK Stack для анализа логов.
Пример структуры лога:
{
"timestamp": "2025-05-20T12:00:00Z",
"agent_id": "agent_support_v3",
"session_id": "sess_001",
"user_id": "u_42",
"tool": "read:documents",
"resource": "doc_123",
"scope_used": "read:documents_owned",
"allowed": true,
"decision_source": "JWT scope check"
}
9. Best practices и частые ошибки
Best practices:
- Используйте принцип «Deny by default» — всё, что не разрешено явно, запрещено.
- Передавайте scope через контекст (state), а не через глобальные переменные.
- Минимизируйте время жизни токена — 15–30 минут максимум для session‑level, 1 минута для call‑level.
- Регулярно ревьюите набор инструментов — удаляйте неиспользуемые.
- Тестируйте эскалацию привилегий — напишите тесты, где агент пытается вызвать инструмент с чужим ресурсом.
Частые ошибки:
| Ошибка | Последствие |
|---|---|
Слишком широкий scope (например, read:*) | Агент читает все данные, включая чужие |
| Статический scope без dynamic scoping | Невозможно ограничить по владельцу |
| Долгоживущие токены (часы/дни) | При утечке токена злоумышленник получает доступ на долгое время |
| Отсутствие HITL для опасных операций | Агент может удалить всё |
| Игнорирование контекста вызова (один scope для всех инструментов) | Потеря гранулярности |
10. Интеграция с agentic framework
Пример на LangGraph (концептуально):
class AgentState(TypedDict):
session_id: str
user_id: str
scopes: list[str] # динамический список
def get_token_for_tool(state: AgentState, tool_name: str) -> dict:
"""Генерирует или достаёт временный JWT для вызова инструмента."""
return {
"tool": tool_name,
"scopes": get_scopes_for_tool(state["scopes"], tool_name),
"exp": time.time() + 60
}
def call_tool(state: AgentState, tool_call: dict) -> dict:
token = get_token_for_tool(state, tool_call["tool"])
# Валидация на стороне сервера инструмента
result = actual_tool_invoke(tool_call, token=token)
return result
11. Сравнение с традиционными RBAC
| Характеристика | RBAC (статическая роль) | Agent Permissions (динамическая) |
|---|---|---|
| Гранулярность | Роль → набор разрешений | Scope + dynamic scoping + сессия |
| Изменяемость | Только через админ‑панель | Автоматически на основе запроса |
| Время жизни | Постоянно | Сессия / вызов / запрос |
| Поддержка HITL | Нет (обычно) | Встроенный механизм |
| Аудит | Логи входа/выхода | Лог каждого вызова инструмента |
Пет-проект для закрепления
Задача Создать микросервис‑агента, который помогает пользователю управлять личными заметками, но не может читать/писать чужие заметки.
Инструменты
- Python (FastAPI)
- JWT (PyJWT)
- LangChain / LangGraph для агента
- SQLite (база заметок с полем
owner_id) - Postman или curl для тестов
Шаги:
- Спроектировать API заметок — CRUD, поле
owner_id = user_id. - Реализовать OAuth2 flow — пользователь логинится, получает JWT с
user_idиrole. - Создать агента — два инструмента:
read_note(note_id)иwrite_note(note_id, content). Каждый инструмент принимает JWT текущей сессии. - Добавить dynamic scoping — в JWT добавить scope
notes:ownи ограничить доступ поowner_id:def read_note(note_id: str, token: dict): if "notes:own" not in token["scopes"]: raise PermissionDenied note = db.query(note_id) if note.owner_id != token["user_id"]: raise PermissionDenied return note - Добавить HITL для удаления заметки — запрос подтверждения.
- Написать тесты:
- Пользователь A не может прочитать заметку пользователя B
- Токен с истекшим сроком отклоняется
- Запрос на удаление приостанавливается до подтверждения
Ожидаемый результат Работающий агент, который строго соблюдает least privilege. Вы сможете продемонстрировать на собеседовании понимание механизмов JWT, dynamic scoping и HITL.
Связь с другими вопросами
| Вопрос | Тема |
|---|---|
| 888 | Инструменты и API для агентов |
| 889 | Память и контекст агента |
| 890 | Наблюдаемость агентов (traces, logs) |
| 891 | Безопасность агентских систем |
| 124 | Prompt injection и mitigation (пересечение с разрешениями) |
Навигация
- Предыдущий: 886
- Следующий: 888
- Индекс: 00. Индекс разборов