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

Машинный перевод. Авторитетным источником является английская версия; проверка носителем языка ещё не выполнена.

least-privilege

Разрешено против наблюдаемого: дрейф как ключевое обнаружение

Автор Olivares AI 9 мин чтения

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

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

Три источника сигналов

Каждое ребро в карте доступа фиксирует отношение доступа между источником (агентом, идентичностью, сеансом) и ресурсом. Каждое ребро несет два булевых флага: Permitted и Observed. Интерес представляют ребра, у которых эти флаги не совпадают.

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

Политика (разрешено). Ребро с signal_source=policy или signal_source=scoped_grant представляет собой заявленное разрешение: что-то, что учетные данные, роль IAM или собственная система определения области платформы указывают, что этот агент имеет право делать. Эти ребра являются permitted=true, observed=false до тех пор, пока телеметрия их не подтвердит. Они являются потолком. Коннекторы идентичности (WIF издатели, списки API-ключей, роли рабочего пространства) подпитывают эту сторону. Аккаунт федерации, которому разрешена область OAuth его правила в рабочем пространстве, является таким ребром.

Телеметрия (наблюдаемая). Кооперативные сигналы из трасс OpenTelemetry, журналов pgAudit, записей CloudTrail, аннотаций MCP, наблюдений по протоколу A2A и вебхуков GitHub/GitLab. Они создают связи там, где observed=true. Их доверие зависит от источника: классификация pgAudit READ является attributed (база данных знает, кто делал запрос и был ли он чтением или записью); MCP readOnlyHint является approximate по спецификации — сама спецификация MCP говорит, что аннотации инструментов недостоверны.

Ядро (истинные данные). Ограничитель eBPF (signal_source=ebpf) работает на уровне системных вызовов. Это сигнал, вокруг которого агент не может обойтись. Когда слой eBPF видит connect() или write(), которые не были зафиксированы совместной телеметрией, это не журналирующий gap — это сигнал против обхода. Модуль безопасности объединяет наблюдения со стороны ядра и со стороны совместной работы в коррелированную аномалию, поэтому агент, который отключает свою телеметрию, становится источником выявления, а не слепой зоной.

Карта доступа — это запрос к этим связям, а не отдельная схема. Дрейф наименьших привилегий — это подмножество, где два флага не совпадают.

Как дрейф становится источником выявления

Разногласие между Permitted и Observed является исходным сигналом. Движок классифицирует его в один из двух видов дрейфа, прежде чем он попадет в очередь аномалий:

// DriftKind классифицирует дрейф наименее привилегированного доступа между разрешенным и наблюдаемым.
type DriftKind string

const (
    // DriftUnusedGrant — это разрешенный доступ, который никогда не наблюдался (чересчур предоставленный доступ).
    DriftUnusedGrant DriftKind = "unused_grant"
    // DriftViolation — это наблюдаемый доступ, который не разрешен.
    DriftViolation DriftKind = "violation"
)

unused_grant означает, что политика говорит, что агент может что-то делать, чего никогда не наблюдалось. Это неиспользуемая привилегия — риск без какой-либо выгоды. Это сигнал для очистки при периодических проверках доступа: отзывайте то, что не используется.

violation означает, что агент был замечен за выполнением действия, которое не разрешено ни одной политикой или грантом. Это активная находка. Это строка в таблице diff, которая читается как “нераспознанная запись” — важное ребро, которое приоритетизируется в очереди аномалий.

Классификация не является бинарной между “в порядке” и “проблемой.” Структура PrivilegeDrift связывает нарушающее ребро с его типом:

// PrivilegeDrift — это несоответствие минимальным привилегиям: ребро, у которого флаги Permitted
// и Observed не совпадают.
type PrivilegeDrift struct {
    Edge AccessEdge
    Kind DriftKind
}

Сам край содержит полную информацию о происхождении: источник (какой агент), ресурс, режим доступа read/write, источник сигнала, который его сгенерировал, степень уверенности в атрибуции и окно наблюдения (FirstSeen, LastSeen, OccurrenceCount). Выявление дрейфа никогда не означает «что-то не так где-то». Оно указывает на конкретного агента, конкретный ресурс, конкретный режим доступа, наблюдаемый конкретным сборщиком, с указанием временного диапазона.

Очередь аномалий: не просто «отличается», а классифицировано

Когда модуль безопасности строит представление аномалий (конечная точка GET /v1/m/security/anomalies), он извлекает дрейф из хранилища access-edge и классифицирует каждый violation в приоритетную аномалию. Классификация добавляет контекст, которого сырой край не несет:

Дрейф доступа. Базовая линия: доступ, который был зафиксирован, но не разрешён. Аномалия называется «Неожиданный доступ: зафиксирован, но не разрешён», степень серьёзности — средняя, и помечена как confidence=approximate, потому что дрейф на уровне хранилища является необработанным сигналом — ещё не сверенным с полной графовой моделью «агент-к-идентичности». Сверенная версия находится в собственном эндпойнте карты доступа /drift; очередь аномалий использует необработанный сигнал и помечает его честно.

Предположительно Egress/exfiltration. Когда ресурс на границе дрейфа является сетевым узлом для внешнего, непринадлежащего частной сети назначения (коннектор eBPF генерирует их как tcp://host:port URI), аномалия переклассифицируется в egress_exfil_suspected и повышается до высокого уровня важности. Агент, записывающий данные во внешний узел, к которому ему никогда не предоставлялся доступ, представляет собой иной тип обнаружения, чем агент, читающий таблицу базы данных, к которой у него не было прав доступа.

Повышение чувствительности. Когда ресурс несет метку чувствительности (high или secret), серьезность повышается независимо от того, является ли доступ исходящим. violation в отношении ресурса с высокой чувствительностью требует более быстрого рассмотрения, даже если назначение внутреннее.

Каждая аномалия содержит evidence карту с исходными деталями:

ev := map[string]any{
    "origin_kind":      edge.OriginKind,
    "origin_id":        edge.OriginID.String(),
    "resource_id":      edge.ResourceID.String(),
    "mode":             string(edge.Mode),
    "signal_source":    string(edge.SignalSource),
    "occurrence_count": edge.OccurrenceCount,
    "reconciled":       false,
}

reconciled: false преднамеренный. Он сообщает потребителю, что это сигнал на уровне магазина в исходном виде, а не согласованное представление access map от агента к идентичности. Очередь аномалий не ждет согласования, чтобы показать violation — но она не притворяется, что атрибуция окончательна, когда это не так.

Уровни доверия: что можно доказать

Каждое ребро в access map несет уровень доверия. Продукт использует два:

  • Приписанный (confidence=attributed): доступ надежно связан с источником собственными доказательствами коллектора. Запись pgAudit с указанием роли базы данных агента, событие CloudTrail, связанное с учетными данными IAM агента, наблюдение eBPF, связанное с идентификатором процесса, который runtime сопоставила с агентом. Цепочка атрибуции от начала до конца.

  • Примерно (confidence=approximate): атрибуция выводится и может быть неточной. Сигнал поступил с общего сервисного аккаунта, где несколько агентов используют одни и те же учетные данные, из ненадежного источника (экземпляр Redis, который не ведет лог идентичности для каждого подключения) или из аннотации MCP, которая, согласно спецификации, считается ненадежной. Связь все еще является сигналом — но оператор знает, что доказательство слабее.

Уровень доверия влияет на оценку приоритета аномалии. Функция приоритета (priorityFor) оценивает каждую аномалию от 0 до 100, и приблизительное отклонение доверия учитывается со скидкой:

if confidence == string(sdkmodel.ConfidenceApproximate) {
    // скидка: несогласованное отклонение является шумным
}

Это предотвращает вытеснение шумного сигнала с общей идентичностью сигнала с чёткой attributed violation. Оба появляются в очереди; approximate имеет более низкий рейтинг. Это тот же принцип, который применяется при судебно-экспертном обогащении: когда обнаруживается общая идентичность (SharedIdentity: true, AgentCount > 1), в хронике отмечается, что «принадлежность к агенту может быть неоднозначной», вместо того чтобы притворяться, что принадлежность точная.

Продукт никогда не подделывает уверенность. Край с пометкой только-аннотация MCP не имеет той же значимости, что подтверждённый eBPF. Выявление дрейфа с учётной записи общего сервиса не имеет той же значимости, что и с идентичности отдельного агента. Оператор видит разницу и распределяет по приоритету соответственно.

Дрейф в судебно-экспертной хронике

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

out.Drift = subjectDrift(r.Context(), sc, c.SubjectRef)

Функция subjectDrift выполняет запрос к хранилищу access-edge для дрейфа по типу нарушения, где субъект является источником, и возвращает список записей driftRefDTO — каждая из которых содержит источник, ресурс, режим доступа, источник сигнала, количество случаев и временную метку последнего обнаружения. Эти данные считываются из собственного расчета дрейфа хранилища и не пересчитываются модулем безопасности.

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

Жизненный цикл сортировки

Находка, возникшая из дрейфа, поступает в систему со статусом open. Далее она проходит стандартный жизненный цикл сортировки находок:

  • открыто: находка существует, никто ещё не предпринял действий.
  • triaged: оператор подтвердил это, назначил на проверку.
  • resolved: основная причина была устранена (грант был отозван, политика ужесточена, агент перераспределен).
  • dismissed: оператор проверил это и определил, что это не реальная угроза (известное поведение, ложное срабатывание от атрибуции approximate).

Каждое изменение состояния триажа самоаудируется по отношению к реальному субъекту. Сам факт отклонения находки фиксируется в журнале с защитой от подделки, поэтому аудитор может увидеть не только, какие изменения произошли, но и кто их проверял и какое было принято решение. Доказательства находки (ее тип, степень серьезности и хеш деталей) неизменны после создания; изменения триажа касаются только состояния рабочего процесса.

Что это означает на практике

Агенту предоставлен API-ключ, назначенный для рабочего пространства Claude. Коннектор идентичности считывает список участников рабочего пространства и создает политику: этому ключу разрешено вызывать API в этом рабочем пространстве. Агент работает в течение трех недель. Телеметрия показывает, что он вызывает API в этом рабочем пространстве — отклонений нет. Затем изменение в развертывании дает агенту доступ к ключу второго рабочего пространства. Телеметрия фиксирует, что агент обращается к обоим рабочим пространствам. Для второго рабочего пространства политика отсутствует. Создается находка о дрейфе типа violation: произошло, но не разрешено. Она попадает в очередь аномалий как access_drift, средняя степень серьезности, доверие approximate (политика еще не согласована с графом идентичности). Если ресурс во втором рабочем пространстве имеет метку чувствительности high, степень серьезности повышается. Находка остается в очереди оператора до тех пор, пока кто-то ее не классифицирует.

Вот в чем разница между логированием и структурированным дрейфом: находка классифицируется, attributed (с честным уровнем уверенности), приоритизируется и подлежит триажу. Она сохраняется до тех пор, пока кто-то не разрешит её или не отклонит. Она появляется в судебной временной шкале, если агент впоследствии становится объектом рассмотрения инцидента. И каждое действие, предпринятое с ней, фиксируется в цепочке, чью целостность продукт может доказать.


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

Чтобы увидеть карту доступа и поверхность дрейфа на действующем имении, посетите страницу продукта с картой доступа или обзор продукта.

Похожие материалы

Часто задаваемые вопросы

В чем разница между дрейфом unused_grant и дрейфом violation?

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

Почему дисконтирование очереди аномалий отражает дрейф приблизительной уверенности?

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

Узнайте, до чего могут добраться ваши агенты

Olivares AI — открытая self-hosted платформа для управления вашим парком AI. Разверните её на собственной инфраструктуре и получите карту доступа, которую давно запрашивают ваши команды безопасности и платформ.