Платформенная команда разворачивает Claude Code для десятка инженеров. Чтобы инструмент приносил пользу, его подключают к нескольким MCP-серверам: один читает монорепозиторий, другой обращается к реплике для отчётности, третий заводит тикеты. В течение недели агент уже читает исходный код, обращается к базе данных и вызывает внутренние инструменты — и никто не может ответить на вопрос, который рано или поздно задаст аудитор: какой агент что сделал, с каким ресурсом и можете ли вы доказать, что данные не были изменены задним числом?
Это не гипотетический пробел. Независимое отраслевое исследование (CSA/Token, n=418) показало, что примерно у 82% организаций работают AI-агенты, о которых они не знают, и лишь около 21% ведут их инвентаризацию в реальном времени. Claude Code и MCP — ровно тот класс возможностей, который внедряется быстро и опережает аудиторскую готовность. Хорошая новость: защищённый журнал достижим целиком внутри вашего периметра, без выхода за его пределы каких-либо полезных данных или секретов.
Почему очевидная конфигурация не проходит аудит
При типичном первом развёртывании используется один общий набор учётных данных. Каждый экземпляр Claude Code аутентифицируется на уровне MCP и в нижестоящих базах данных под одной и той же служебной учётной записью — mcp-runner, ci-bot, что-то столь же обезличенное. Это работает и незаметно разрушает привязку действий.
Когда десять агентов действуют как один субъект, журнал аудита базы данных показывает десять операций записи от mcp-runner — и не более того. Вы не можете определить, какая инженерная сессия выполнила UPDATE, был ли он инициирован из интерактивного запроса Claude Code или из фонового задания, какой MCP-инструмент оказался в цепочке вызова. По данным независимого исследования (Optro), доля организаций, способных проследить действие агента до конкретного человека, составляет около 28%. Общая служебная учётная запись — одна из структурных причин, по которым привязка действий рушится: журнал аудита может показать, что произошло, но никогда — какой агент это сделал.
Второй провал — целостность. Даже команды, которые ведут журнал по каждому действию, обычно пишут его в изменяемое хранилище. Если журналы лежат в той же системе, до которой может добраться злоумышленник (или сбойный агент), формулировка «у нас есть журналы» — не то же самое, что «у нас есть доказательства». Аудитор проводит между ними чёткую границу.
Идентичность для каждого агента — это фундамент
Всё, что строится дальше, зависит от привязки действий, поэтому сначала наведите порядок с идентичностью. Вместо одного общего токена выдавайте отдельную короткоживущую идентичность каждому агенту — в идеале каждой сессии. Идентичность сопровождает запрос внутрь MCP-сервера и в любой ресурс, к которому обращается агент, поэтому субъект, зафиксированный на стороне базы данных, — это сам агент, а не обезличенный runner.
Именно это наполняет смыслом принцип least-privilege. Агента для отчётности можно закрепить в режиме только на чтение на реплике для отчётности; релизному агенту даётся запись лишь в те артефакты, которыми он владеет. Теперь единичная зафиксированная операция записи за пределами этих рамок — точный, привязываемый сигнал, а не шум в общей учётной записи. Сформулированное как политика, намерение предельно прямолинейно:
agent "reporting-assistant" {
# Сессия Claude Code через MCP-сервер отчётности
resource "prod-postgres/reporting_replica" {
access = "read" # SELECT only
deny = ["write", "ddl"]
}
resource "s3://billing-exports" {
access = "read"
}
on_violation {
action = "block_and_alert" # отказать в момент доступа, не только логировать
}
}
Дело не в синтаксисе — дело в том, что политика называет агента, называет ресурс и разделяет чтение от чтения/записи. Именно это разделение и есть вся суть.
Относитесь к аннотациям MCP как к недоверенным сигналам
MCP-инструменты могут описывать себя аннотациями вроде readOnlyHint и destructiveHint. Они действительно полезны для первичной сортировки — инструмент, объявляющий себя деструктивным, заслуживает более жёсткой политики. Но спецификация MCP прямо указывает, что это подсказки, и клиенты не должны полагаться на них при принятии решений о безопасности. Они исходят от сервера — а именно его вы и подвергаете аудиту. Инструмент может объявить readOnlyHint: true и всё равно выполнить запись — из-за ошибки, неверной настройки или намеренного обхода.
Поэтому верная позиция — подтверждение, а не доверие. Воспринимайте аннотацию как заявление, а затем сверяйте её с фактической истиной с уровня, который инструмент не контролирует:
- Журналы аудита базы данных (например, PostgreSQL pgAudit) показывают, действительно ли выполнялся
SELECTилиUPDATE. - Спаны OpenTelemetry от MCP-сервера и нижестоящих сервисов показывают граф вызовов и выполненные операции.
- Сигналы ядра eBPF — последний рубеж против обхода: системный вызов записи в файл или сокет наблюдаем на уровне ядра независимо от того, что инструмент заявил в пользовательском пространстве.
Когда аннотация говорит «только чтение», а ядро увидело запись, это противоречие — главный вывод: инструмент с readOnlyHint, выполнивший запись в prod-postgres, — это ровно тот дрейф от least-privilege, ради которого стоит кого-то поднять среди ночи. Расхождение между тем, что политика разрешила, и тем, что сборщики наблюдали, — вот где живёт реальный риск.
Журнал, который примет аудитор
Журнал становится доказательством, только если он защищён от подделки. Записывайте каждое событие в журнал, доступный только для добавления, с хеш-цепочкой: каждая запись включает хеш предыдущей, поэтому любая правка или удаление ниже по цепочке разрывает её и становится обнаружимым. Каждая строка привязывает действие к конкретному агенту, называет ресурс, фиксирует чтение или чтение/запись и несёт уровень достоверности — attributed, когда и идентичность, и результат подтверждены, approximate, когда что-то пришлось вывести логически. Достоверность показывается честно; приблизительное совпадение никогда не выдаётся за доказанное.
ts=2026-06-08T09:14:02Z agent=reporting-assistant@s3f1 tool=sql-read resource=prod-postgres/reporting_replica op=R outcome=allow conf=attributed prev=8a1c…
ts=2026-06-08T09:14:05Z agent=reporting-assistant@s3f1 tool=export-writer resource=s3://billing-exports op=R outcome=allow conf=attributed prev=2f90…
ts=2026-06-08T09:17:48Z agent=data-export-job@b22e tool=sql-write resource=prod-postgres/customers op=RW outcome=DENY conf=attributed prev=c7d3… policy=read_only_violation
Третья строка — это та, что важна аудитору: попытка записи в таблицу, на которую у агента не было права записи, отклонённая в момент доступа, привязанная к именованному агенту и закреплённая в цепочке. Поскольку политика применяется в момент доступа — а не просто записывается постфактум — этот отказ является средством контроля, а не разбором последствий.
Ещё два свойства делают журнал устойчивым. Привилегированные просмотры сами проходят аудит: обращение к карте доступа фиксируется, поэтому на вопрос «кто что видел» можно ответить. И экспорт доказательств защищён от подделки — вы передаёте аудитору подписанный фрагмент цепочки, который он может проверить независимо, а не CSV, который ему придётся принимать на веру.
| Свойство | Общая служебная учётная запись | Идентичность для каждого агента + журнал с хеш-цепочкой |
|---|---|---|
| Привязка действий | Один субъект для всех агентов | Действие привязано к конкретному агенту/сессии |
| Чтение и запись | Смешаны | Разделены и проверяются политикой |
| Целостность | Изменяемые журналы | Только добавление, цепочка рвётся при правке |
| Экспорт, готовый для аудитора | CSV на доверии | Подписанный, независимо проверяемый фрагмент |
Почему здесь важна локальная развёртка
Всё это работает без выхода чего-либо за пределы вашей сети. Сборщик наблюдает — журналы, OpenTelemetry, eBPF как рубеж на уровне ядра — а не встраивается в путь данных агента, поэтому при сбое он никогда не ломает ни агента, ни стоящий за ним production-запрос. Журнал хранит отношения доступа, а не полезные данные: он фиксирует, что reporting-assistant прочитал reporting_replica, но не возвращённые им строки. Входные данные, способные нести секреты или PII, редактируются и проходят сканирование на секреты до того, как что-либо будет записано. Для air-gapped-сред, контуров под GDPR или с ограничениями по резидентности данных это разница между аудиторской готовностью, которую можно отстоять, и той, которую отстоять нельзя: никакие данные об использовании Claude Code и MCP не покидают вашу сеть, потому что система изначально не видит сами данные.
Claude Code и MCP стоят того, чтобы их развернуть. Им просто нужен аудиторский журнал, выстроенный так же, как вы выстроили бы его для любой другой привилегированной автоматизации — сначала идентичность, затем подтверждение результатов, затем закрепление доказательств. Если вы хотите увидеть, как карта доступа и защищённый от подделки журнал сочетаются друг с другом, модель безопасности и обзор продукта раскрывают каждый из них подробнее.