コンパニオン投稿 では、AI エージェントの実行が許可されている内容と、AI エージェントの実行が観察されている内容の間の最小特権のドリフトが gap として導入されました。その投稿では、gap が形成される理由、読み取り優先の観察によって許可された差分と観察されたの差分がどのように生成されるか、およびコードとしてのポリシーがアクセス時にどのようにそれを閉じるかという概念について説明しました。この投稿では、セキュリティ モジュール内でドリフトがどのようにして構造化され、分類され、トリアージ可能な結果となるのか、またドリフトが存在するとどうなるのかについて、さらに 1 層深く掘り下げて説明します。
簡単に言えば、ドリフトはダッシュボードのメトリックやログラインではありません。これは、分類、重大度、信頼レベル、トリアージ ライフサイクルを備えた永続的なエンティティです。異常キューに情報を提供し、フォレンジックのタイムラインを充実させ、何が証明できるか、何が証明できないかを正直に示します。
3つの信号源
アクセス マップ の各エッジは、オリジン (エージェント、アイデンティティ、セッション) とリソースの間のアクセス関係を記録します。各エッジには、Permitted と Observed という 2 つのブール値フラグが含まれています。興味深いエッジは、これらのフラグが一致しないエッジです。
しかし、旗は何もないところから現れるわけではありません。これらは別個の信号ソースから来ており、それぞれが異なる信頼プロファイルを持っています。
ポリシー (許可)。 signal_source=policy または signal_source=scoped_grant のエッジは、宣言された付与を表します。つまり、資格情報、IAM ロール、またはプラットフォーム独自のソーススコーププレーンがこのエージェントに実行を許可するものを示します。これらのエッジは、テレメトリで確認されるまで permitted=true, observed=false です。それらは天井です。 ID コネクタ (WIF 発行者、API キー名簿、ワークスペース ロール) がこの側にフィードします。ワークスペース内でそのルールの OAuth スコープを許可したフェデレーション サービス アカウントは、そのようなエッジの 1 つです。
テレメトリ (観測)。 OpenTelemetry トレース、pgAudit ログ、CloudTrail レコード、MCP アノテーション、A2A プロトコル観測、および GitHub/GitLab Webhook からの連携シグナル。これらは、observed=true のエッジを生成します。その信頼性はソースによって異なります。pgAudit READ 分類は attributed です (データベースは、誰がクエリを行ったのか、また、それが読み取りであったのか書き込みであったのかを知っています)。 MCP readOnlyHint は仕様上 approximate です — MCP 仕様自体には、ツールの注釈は信頼できないと記載されています。
カーネル (グラウンド トゥルース)。 eBPF バックストップ (signal_source=ebpf) は、システムコール レベルで監視します。これは、エージェントが回避できない信号です。 eBPF レイヤーが、協調テレメトリが報告しなかった connect() または write() を認識した場合、それはロギング gap ではなく、回避防止信号です。セキュリティ モジュールは、カーネル側と協調側の観察を相関のある異常に結合するため、エージェント自身のテレメトリを沈黙させることは死角ではなく発見となります。
アクセス マップはこれらのエッジに対するクエリであり、別個のスキーマではありません。最小特権ドリフトは、2 つのフラグが一致しないサブセットです。
ドリフトがどのように発見されるか
Permitted と Observed の不一致は生の信号です。エンジンは、異常キューに入る前に、ドリフトを 2 種類のいずれかに分類します。
// DriftKind は、許可された特権と監視された特権の間の最小特権のドリフトを分類します。
type DriftKind string
const (
// DriftUnusedGrant は、決して観察されない (オーバープロビジョニングされた) 許可されたアクセスです。
DriftUnusedGrant DriftKind = "unused_grant"
// DriftViolation は、許可されていない観察されたアクセスです。
DriftViolation DriftKind = "violation"
)
unused_grant は、エージェントがこれまでに行われていないことを実行できるというポリシーを意味します。これは死んだ特権であり、何の利益も得られずにリスクを背負います。これは、定期的なアクセス レビューのクリーンアップ信号であり、行使されていないものは取り消します。
violation は、エージェントがポリシーや許可の許可がないことを実行しているのが観察されたことを意味します。これはアクティブな発見です。これは、差分テーブル内の「未レビュー書き込み」と示されている行です。重要なエッジ、つまり異常キューが優先するエッジです。
分類は「問題あり」と「問題あり」の二者択一ではありません。 PrivilegeDrift 構造体は、問題のあるエッジとその種類を組み合わせます。
// PrivilegeDrift は最小権限の不一致であり、Permitted フラグと
// Observed フラグが一致しないエッジである。
type PrivilegeDrift struct {
Edge AccessEdge
Kind DriftKind
}
エッジ自体は、起源 (どのエージェント)、リソース、read/write モード、エッジを生成した信号源、帰属の信頼性、および観察ウィンドウ (FirstSeen、LastSeen、OccurrenceCount) といった完全な来歴を保持します。ドリフトの発見は、「どこかが間違っている」ということは決してありません。これは、特定のコレクターによって監視される特定のエージェント、特定のリソース、特定のアクセス モードを時間範囲とともに指します。
異常キュー: 「異なる」だけでなく機密扱い
セキュリティ モジュールは、異常ビュー (GET /v1/m/security/anomalies エンドポイント) を構築するときに、アクセス エッジ ストアからドリフトを取得し、各 violation を優先順位付きの異常に分類します。分類により、生のエッジが持たないコンテキストが追加されます。
アクセス ドリフト。 ベースライン: 観察されているが許可されていないアクセス。この異常のタイトルは「予期しないアクセス: 観察されましたが許可されていません」、重大度は中、confidence=approximate のフラグが付けられています。これは、ストアレベルのドリフトが生の信号であるためであり、エージェントから ID への完全なグラフとまだ調整されていないためです。調整されたビューは、アクセス マップ自体の /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 は意図的なものです。これは、アクセス マップの調整されたエージェントからアイデンティティへのビューではなく、生の店舗レベルの信号であることを消費者に伝えます。異常キューは、調整によって violation が表面化するのを待ちませんが、帰属が確定していないときに、その帰属が確定しているかのように振る舞うわけではありません。
信頼レベル: 何が証明できるか
アクセス マップ内のすべてのエッジには信頼レベルが含まれます。この製品では次の 2 つが使用されます。
-
帰属 (
confidence=attributed): アクセスはコレクター自身の証拠によって出所としっかりと結び付けられています。エージェントのデータベース ロールに名前を付ける pgAudit レコード、エージェントの IAM 資格情報に関連付けられた CloudTrail イベント、ランタイムがエージェントに解決したプロセス ID に関連付けられた eBPF 観察。アトリビューション チェーンはエンドツーエンドです。 -
近似 (
confidence=approximate): 帰属は推定されており、損失を伴う可能性があります。この信号は、複数のエージェントが同じ認証情報を使用する共有サービス アカウント、非可逆ストア (接続ごとの ID をログに記録しない Redis インスタンス)、または仕様で信頼できないとされている MCP アノテーションから送信されました。エッジは依然として信号ですが、オペレーターは証拠が弱いことを知っています。
信頼レベルは、異常の優先度スコアに影響します。優先度関数 (priorityFor) は各異常を 0 から 100 までスコア付けし、approximate の信頼ドリフトは割り引かれます。
if confidence == string(sdkmodel.ConfidenceApproximate) {
// 割引: 未調整のドリフトがうるさい
}
これにより、ノイズの多い共有 ID 信号が attributed violation を確実に押しのけるのを防ぎます。どちらもキューに表示されます。 approximate は 1 ランク下です。これは、フォレンジック強化と同じ原理です。共有 ID (SharedIdentity: true, AgentCount > 1) が見つかると、タイムラインには、帰属が正確であるかのように振る舞うのではなく、「エージェントごとの帰属が曖昧である可能性がある」ことが示されます。
この製品は決して確実性を偽ることはありません。 MCP アノテーションのみのエッジは、eBPF で確認されたエッジと同じ重みを持ちません。共有サービス アカウントからのドリフト検出結果は、エージェントごとの ID からのドリフト検出結果と同じ重みを持ちません。オペレーターは違いを確認し、それに応じて優先順位を付けます。
法医学タイムラインの漂流
ドリフト所見は異常キュー内にのみ存在するわけではありません。フォレンジック ケースが開かれ、そのタイムラインがハッシュ チェーン監査台帳から再構築されると、セキュリティ モジュールは対象者のドリフトを使用して再構築を強化します。
out.Drift = subjectDrift(r.Context(), sc, c.SubjectRef)
subjectDrift 関数は、サブジェクトが原点である violation 種類のドリフトについてアクセス エッジ ストアにクエリを実行し、driftRefDTO エントリのリストを返します。各エントリには、原点、リソース、アクセス モード、信号ソース、発生回数、最後に表示されたタイムスタンプが含まれます。これらは、セキュリティ モジュールによって再計算されるのではなく、ストア独自のドリフト計算から読み取られます。
タイムラインには対象者の身元属性とデータ系統も含まれるため、事件を検討する捜査官は、エージェントが誰として行動するのか(そしてそのアイデンティティが共有されているかどうか)、エージェントがアクセスすべきではないものに何にアクセスしたのか、どのデータから回答を導き出したのかなど、全体像を把握することができます。これらの各エンリッチメントは、近隣の不在を許容します。ナレッジ モジュールがインストールされていない場合、リネージュは偽造されるのではなく省略されます。 ID にエージェント バインディングが解決されていない場合、属性は作成されるのではなく、「まだバインドされていない」と表示されます。
トリアージのライフサイクル
ドリフトに起因する検出結果は、ステータス open でシステムに入ります。そこからは、標準的な発見トリアージ ライフサイクルに従います。
- 開く: 調査結果は存在しますが、まだ誰もそれに基づいて行動していません。
- トリアージ: オペレーターがそれを認識し、レビューのために割り当てられました。
- 解決済み: 根本的な原因は修正されました (付与が取り消され、ポリシーが強化され、エージェントの範囲が変更されました)。
- 却下: オペレーターがそれを確認し、実際のリスクではないと判断しました (既知の動作、approximate アトリビューションからの誤検知)。
すべてのトリアージ状態の変更は、実際のプリンシパルに対して自己監査されます。発見事項を却下する行為自体が改ざん防止台帳に記録されるため、監査人はどのようなドリフトが発生したかだけでなく、誰がそれをレビューし、何を決定したかを確認できます。調査結果の証拠 (種類、重大度、および詳細ハッシュ) は、作成後に変更できません。トリアージはワークフローの状態のみを変更します。
これが実際に何を意味するか
エージェントには、Claude ワークスペースをスコープとする API キーが与えられます。 ID コネクタは、ワークスペースの名簿を読み取り、ポリシー エッジを発行します。このキーは、このワークスペースで API を呼び出すことが許可されています。エージェントは 3 週間実行されます。テレメトリは、そのワークスペースで API を呼び出していることを示しています。ドリフトはありません。その後、展開の変更により、エージェントは 2 番目のワークスペースのキーにアクセスできるようになります。テレメトリは、両方のワークスペースを呼び出すエージェントを観察します。 2 番目のワークスペースにはポリシー エッジがありません。種類 violation のドリフト検出結果が作成されます。観察されていますが、許可されていません。これは、access_drift、重大度中、信頼度 approximate として異常キューに入ります (エッジはまだ ID グラフに対して調整されていません)。 2 番目のワークスペースのリソースに high 機密ラベルが付いている場合、重大度は昇格します。発見結果は、誰かが優先順位を付けるまでオペレーターのキューに残ります。
それがロギングと構造化ドリフトの違いです。調査結果は attributed (正直な自信を持って) 機密扱いであり、優先順位が付けられ、トリアージ可能です。誰かが解決するか却下するまで、この状態は継続します。エージェントが後にインシデント事件の対象となった場合、フォレンジック タイムラインに表示されます。そして、その製品に対して行われたすべてのアクションはチェーンに記録され、製品の完全性が証明されます。
ドリフトは最小化すべき指標ではありません。トリアージするための発見です。エージェントの実行が許可されている内容とエージェントの実行が観察されている内容の間の gap は、最小限の特権を適用するための最高の信号面です。ただし、それは gap が構造化され、機密扱いであり、証明できる内容について誠実である場合に限られます。
走行中のアクセスマップとドリフト路面を確認するには、アクセスマップ製品ページまたは製品概要をご覧ください。