Перейти к основному содержимому

Отчёты о rogue-агентах — это проблема атрибуции, а не безопасности

В отчётах об инцидентах указывается модель, но практически значимый артефакт — это цепочка делегирования, санкционировавшая запуск. Большинство стеков не могут её восстановить.

Крупный план серверной стойки с патч-кабелями и индикаторами, представляющий инфраструктуру, где применяется контроль доступа.

Что на самом деле описывают отчёты

Когда агент достигает государственного эндпоинта или корпоративного API без человека, отдавшего инструкцию в этот момент, история, которая за этим следует, обычно касается модели. Лаборатория, номер версии, порог возможностей. Такая формулировка понятна и хорошо воспринимается, но она отвечает на вопрос, который специалистам по реагированию на инциденты на самом деле не нужен. Вопрос, определяющий, что произойдёт дальше, уже: какой учётный данные были предъявлены, какие полномочия они несли и через какую цепочку делегирования они достигли этого эндпоинта.

Несколько недавних отчётов описывают взаимодействие агентов с внешними системами способами, которые оператор не давал напрямую в тот момент. Детали различаются, но форма последовательна: автономный или полуавтономный процесс составил запрос, и запрос был принят, потому что действительный учётный данные санкционировали его. Модель породила намерение. Учётные данные породили доступ. Только одно из них можно отозвать в течение следующих десяти минут.

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

Почему цепочка делегирования отсутствует

Причина, по которой большинство стеков не могут восстановить цепочку, в том, что они никогда не были спроектированы для её хранения. Три паттерна объясняют большую часть пробела.

Во-первых, учётные данные привязаны к сервису, а не к задаче. Агенту выдаётся токен или ключ с разрешениями, необходимыми интеграции, и этот грант сохраняется на протяжении всех запусков агента. Авторизация переживает намерение, которое её оправдывало. Грант, выданный, чтобы агент мог читать календарь для задачи планирования, всё ещё действителен шесть месяцев спустя, когда тот же агент занимается чем-то совершенно другим, потому что ничто в учётных данных не кодирует задачу.

Во-вторых, промежуточные переходы повторно используют родительские учётные данные вместо их ослабления. Планировщик порождает субагента. Субагент вызывает прокси инструмента. Прокси вызывает сторонний эндпоинт. На каждом переходе один и тот же bearer-токен передаётся дальше без изменений. Субагент обладает точно той же властью, что и корневой принципал, хотя его фактическая работа может требовать лишь её доли. Это удобно, и это единственный крупнейший фактор радиуса поражения в агентных системах.

Clear lab test tubes with measurement markings in a row, stock photo

В-третьих, логи записывают запрос, а не цепочку ответственности, которая его породила. Журнал доступа показывает, что запрос поступил с действительным токеном в определённое время. Он не показывает, какой шаг планировщика породил намерение, какой субагент его выполнил или к какой задаче относилась вся последовательность. Поэтому постфактум-реконструкция зависит от сопоставления временных меток и идентификаторов сессий в системах, которые никогда не были спроектированы для объединения. Это сопоставление — вывод. Вывод годится для постмортема и бесполезен для отзыва.

Минимально жизнеспособная запись атрибуции

Исправление — не обновление логирования. Это изменение того, что несёт исходящее действие и где записывается запись.

Каждое исходящее действие должно нести как минимум четыре поля:

  • принципал — идентичность, от имени которой совершается действие, разрешаемая в реальный аккаунт или сервисную идентичность
  • идентификатор задачи — стабильный id для единицы работы, которой служит действие, не сессия и не процесс
  • идентификатор родительского шага — шаг, породивший это действие, чтобы цепочка была связной структурой, а не плоским списком
  • фактически использованные полномочия — конкретное разрешение, которое потребило действие, выраженное в той же терминологии, по которой проверяет точка принуждения

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

Механизм, который заставляет это работать, — ослабление полномочий на каждом переходе. Когда порождается субагент, он получает грант, который является строгим подмножеством полномочий его вызывающего — никогда надмножеством, никогда равным множеством, если только задача действительно не требует полных полномочий и это требование не является явным. Ослабление применяется на границе, где создаётся дочерний элемент, а не заявляется дочерним элементом. Прокси инструмента, получающий запрос, предъявляет свой собственный ослабленный грант, а не токен вызывающего.

Второй механизм — где записывается запись. Данные атрибуции должны выдаваться в точке принуждения — месте, которое фактически решает, продолжится ли запрос, — а не собираться позже из журналов приложений. Журналы приложений пишутся кодом, который может быть с ошибками, обойдён или просто отсутствовать на некоторых путях. Точка принуждения по определению видит каждый запрос и уже знает проверенные полномочия. Запись там принципала, id задачи, id родительского шага и использованных полномочийMan adjusting a vintage oscilloscope in a studio with a gray background

{ "principal": "svc:reporting-agent",
  "task_id": "tsk_8f21",
  "parent_step": "stp_04",
  "scope": "calendar.read",
  "target": "external.example.gov",
  "decision": "allow" }

Такая запись — не строка лога в обычном смысле. Это ребро в графе, и оно записано компонентом, который имел полномочия сказать «нет».

Последствия для проектирования

Как только цепочка существует, реагирование на инциденты меняет характер. Вопрос «что сделал агент» становится обходом: начать с принципала, пройти вперёд к задаче, пройти вперёд к каждому шагу, перечислить каждый затронутый эндпоинт. Вопрос «как он туда попал» становится обратным обходом от эндпоинта к корневому гранту. Оба — запросы к структуре, которую вы уже поддерживаете, а не расследования, проводимые постфактум.

Отзыв становится привязанным к задаче, а не к сервисному аккаунту. Если одна задача ведёт себя неправильно, вы отзываете гранты, выданные для этой задачи, и всё, что ниже по потоку. Остальная работа агента продолжается. Это разница между локализацией инцидента и отключением возможности. Это также разница между отзывом, вступающим в силу за секунды, и тем, который требует аудита каждой интеграции, к которой прикасается сервисный аккаунт, прежде чем вы осмелитесь его отключить.

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

Честный компромисс в том, что ослабление и записи по каждому действию стоят инженерных усилий и создают трение. Каждый переход должен согласовать более узкий грант, а значит, компоненты, порождающие субагентов, должны знать, что субагенту понадобится, до его запуска. Это проектная约束, и она действительно сложнее, чем передача токена. Также есть реальная стоимость производительности и хранения при записи ребра в каждой точке принуждения вместо выборочного логирования. Для агентного трафика с высоким объёмом объём записей пропорционален объёму действий, и это не бесплатно.

Контраргумент в том, что стоимость платится один раз, при проектировании, а альтернатива платится многократно, в каждом инциденте, в худших условиях. Система, которая не может восстановить свою собственную цепочку делегирования, не имеет проблемы атрибуции во время нормальной работы. Она возникает в тот момент, когда кто-то задаёт вопрос, на который она не может ответить, — именно тогда, когда ответ важнее всего.

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

ПоделитьсяXLinkedInПостоянная ссылка6 мин чтения

Связанное чтение

На какие вопросы это отвечает

Why is the delegation chain usually missing from agent systems?

Because credentials are scoped to a service rather than a task, intermediate hops re-use the parent token instead of attenuating it, and access logs record the request rather than the chain of custody that produced it. Reconstruction then depends on inference rather than a record.

What should a minimum viable attribution record contain?

A principal, a task identifier, a parent step identifier, and the scope actually exercised. Written at the enforcement point, these four fields form a directed graph from any action back to its root principal.

What does scope attenuation mean in practice?

Each hop in the delegation chain receives a grant that is a strict subset of its caller's authority. A sub-agent cannot hold a superset of its caller's permissions, and attenuation is enforced where the child is created, not asserted by the child.

What is the trade-off of per-action attribution records?

Attenuation requires each spawning component to know what its sub-agent will need before it runs, and writing an edge record at every enforcement point adds storage and performance cost proportional to action volume. The cost is paid once in design rather than repeatedly in incidents.