Cribl StreamでClaude Complianceログを取り込みマスクして振り分ける
Cribl StreamのClaude Compliance Sourceで監査ログを取り込み、Mask Functionで機微項目を伏せ、RoutesでSIEMと長期保管に振り分ける設定手順です。
Cribl Streamには、Claude Compliance APIを定期的に呼び出してイベント化する専用のSourceがあります。Claude Enterpriseの監査ログをSIEMやeDiscoveryツールに流す前段で、ログの整形・マスク・振り分けをCribl側に任せたいときの入口です。
この記事では、Sourceの設定から、Mask Functionによる機微項目の伏せ字、Routesによる送信先の振り分けまでを順に組みます。ポーリングやカーソルの設計そのものはCompliance APIのSIEM連携が扱っており、Cribl Sourceはその部分を内部で肩代わりします。
Claude Compliance Sourceは何を取り込むか
Claude Compliance Sourceは、Cribl StreamがAnthropicのCompliance APIへ定期的に問い合わせる「Pull型」のSourceです。TLSはAPI側のHTTPSで確保され、イベントの分割(Event Breaker)はAnthropic Compliance Rulesetで自動的に行われます。分割ルールはユーザーが変更できません。
用途は、ClaudeのプラットフォームでのアクティビティをeDiscovery・DLP(情報漏えい防止)・SIEMに渡すことです。トークン使用量やコストのレポートは別物で、Claude Enterprise Analytics Sourceが受け持ちます。
使い始める前に必要なものは4つあります。
- Cribl Streamの環境(CloudまたはSelf-hosted)
- Compliance APIを有効にしたClaude Enterprise組織(Compliance APIの概要に有効化の前提があります)
- 取りたいエンドポイントに必要なスコープを持つCompliance Access Key
- Cribl WorkerからAnthropicのAPIホストへのHTTPS疎通(直接でもプロキシ経由でも可)
Admin APIキーはAccess Keyの代わりに使えますが、取れるのはActivity Feedだけです。チャット本文やプロジェクトまで集めたいなら、Compliance Access Keyが要ります。
curl --fail-with-body -sS \
"https://api.anthropic.com/v1/compliance/activities?limit=1" \
--header "x-api-key: $ANTHROPIC_COMPLIANCE_ACCESS_KEY" \
--header "anthropic-version: 2023-06-01"レスポンスのdataにactor・type・created_atを持つ1件が返れば、鍵は有効です。403や404が返るときはCompliance APIのエラー対処で原因を切り分けられます。
Sourceを追加する手順
画面の操作は次の流れです。QuickConnectとRoutesのどちらから入っても、General Settingsの項目は同じです。
Claude Compliance Sourceの作成
- 1
Sourceを追加する
Cribl StreamのWorker Groupを開き、QuickConnectの場合はRoutingからAdd Source、Routesの場合はData、Sourcesから追加します。
- 2
General Settingsを埋める
Input IDに一意の名前を付け、API keyにはストアド・テキストシークレットとしてCompliance Access Keyを登録します。Descriptionに「どのSIEMに流すか」を書いておくと後で追いやすくなります。
- 3
Endpointsを選ぶ
左のサイドバーでエンドポイントごとに有効・無効を切り替えます。初期状態で有効なのはActivitiesだけで、状態追跡も有効です。
- 4
接続先を決める
Connected Destinationsで、Send to RoutesとQuickConnectのどちらで出力するかを選びます。マスクや振り分けを入れるなら、Routes側です。
- 5
保存して反映する
SaveのあとCommit & Deployで反映します。Source画面のLive DataでStart Captureを押すと、取り込まれたイベントを確認できます。
エンドポイントごとの共通設定は、有効化のトグル、cronスケジュール、ジョブのタイムアウトの3つです。Activitiesの既定スケジュールは5分ごと(*/5 * * * *)、それ以外は毎日7時(0 7 * * *)です。ジョブのタイムアウトは既定300秒で、0にすると無制限になります。
どのエンドポイントを有効にするか
Sourceは、エンドポイントを2段に分けて扱います。Tier 1は必須のパスパラメーターを持たない一覧系で、Source自身が直接呼び出します。Tier 2はTier 1の応答から得たIDを使う詳細系で、親のTier 1を有効にすると同じジョブの中で自動的に取得されます。
| エンドポイント(Tier 1) | 取れるもの | ページング |
|---|---|---|
GET /v1/compliance/activities | 取れるもの組織内の監査証跡(1レコード=1アクション) | ページングカーソル |
GET /v1/compliance/apps/chats | 取れるものclaude.aiのチャットのメタデータ | ページングカーソル |
GET /v1/compliance/apps/projects | 取れるものプロジェクトの一覧 | ページングトークン |
GET /v1/compliance/groups | 取れるものRBAC・SCIMで作られたグループ | ページングトークン |
GET /v1/compliance/organizations | 取れるもの親組織にひもづく組織 | ページングトークン |
Tier 2は4つで、チャット本文(会話のメッセージとツール呼び出し)、プロジェクトの詳細(カスタム指示を含む)、組織ごとのユーザー、組織ごとのロールです。
注意したいのは、Tier 2を動かすための親データはイベントとして出ないことです。Chat Messagesを有効にすると、SourceはChatsからチャットIDを集めてメッセージを取りに行きますが、出力されるのはメッセージのイベントだけで、チャットのイベントは生成されません。チャットのメタデータも別途ほしいなら、Chatsのイベントをほかの手段で補う必要があります。
最初はActivitiesだけで始める理由
Tier 2は発見したIDの数だけリクエストを発行するため、リクエスト量が一気に増えます。ActivitiesとChatsは大きなページングになりやすく、Anthropic側のレート制限(HTTP 429)を受けやすい領域です。
初期設定のActivitiesだけを動かして取り込みと振り分けを固め、そのあとでChat Messagesなど内容を持つエンドポイントを足す順番だと、マスク漏れのまま本文が流れ出る事故を避けられます。
機微項目をMask Functionで伏せる
Activity Feedの1件には、操作した人を特定できる項目が入っています。user_actorのときはemail_address・user_id・ip_address・user_agentが、api_actorのときはapi_key_idとip_addressが付きます。これらを下流のSIEMで見せたくない場合は、Pipelineの中でMask Functionを使います。
まず取り込んだイベントの形を見る
マスクのルールは、フィールドの形で書き方が変わります。Live Dataで1件開き、actorが展開済みのフィールドになっているか、_rawの中の文字列になっているかを確かめてください。展開済みならactor.email_addressのようにネストしたパスで指定できます。Mask Functionのフィールド指定は、ワイルドカードとネストしたアドレスに対応しています。
Maskのルールを書く
Pipelineを作り、Mask Functionを追加して次のようにします。Cribl docsのSSN・クレジットカード番号の例が使っている型(C.Mask.md5でハッシュに置き換える)に合わせた構成例です。
Function: Mask
Apply to fields: actor.email_address
actor.ip_address
Match Regex: (.+)
Replace Expr: C.Mask.md5(g1)Match Regexで拾った内容は、Replace Expressionの結果に丸ごと置き換わります。Criblは、Match Regexに当たった元の文字列を、Replace Expressionに入れた分以外は保持しません。キー名などを残したいときは、キー名側をキャプチャグループにして${g1}として戻します。
ハッシュに置き換えると、同じ人の操作は同じ値としてSIEM上で束ねられます。誰かは分からなくても「同じ人が短時間に何度も操作した」という相関は残る、という性質です。
Mask Functionの出力は常に文字列です。数値のフィールドに使うと文字列になるため、必要ならNumerify Functionで戻します。
ファイル名やタイトルは伏せ字の対象にならない
AnthropicのActivity Feedでは、ファイル・プロジェクト文書・アーティファクトに関するアクティビティに、名前やタイトルは入りません。2026年9月24日以降、filenameとtitleは常にnull・空文字・省略のいずれかで、それ以前に記録された分も同様です。
名前はIDからマッチするコンテンツのエンドポイントで引く仕様なので、Activity Feedだけを流す構成なら、ファイル名のマスクは考えなくて済みます。会話本文を取り込むときは話が変わり、本文中のメールアドレスや社内コードなどを正規表現で拾うルールが必要になります。
SIEMと長期保管へ振り分ける
マスク済みのデータをSIEMへ、元のデータを長期保管へ、という構成は、RoutesのFinalトグルで組めます。
Routesの並べ方
アーカイブ用の Route を先に置く
Filterで対象を選び、加工しないPipelineを付けて長期保管のDestinationへ送ります。FinalをオフにするとCribl Streamは一致したイベントを複製して処理し、原本は次のRouteへ進みます。
SIEM 用の Route を後ろに置く
マスク用のPipelineを付け、SIEMのDestinationへ送ります。Finalがオンなので、一致したイベントはここで終わります。
要点はRouteの評価順です。RouteはList表示の上から順に評価され、Finalオン(既定)のRouteに一致したイベントは、それより下のRouteへ進みません。マスクしていない原本を保管するRouteは、必ずFinalオフにして上に置きます。逆順にすると、保管先に届くのは伏せ字後のデータだけになります。
Cribl docsのMask解説にも、未加工の値を保管先へ送りたい場合はRouteのDestinationでMaskの適用範囲を絞る、という説明があります。
Filter式はJavaScript互換です。Activity Feedのtypeでイベントを分けるなら、次のように書けます。
Route: claude-file-events Filter: type.startsWith('claude_file_')
Route: claude-chat-events Filter: type.startsWith('claude_chat_')
Route: claude-catchall Filter: trueclaude_file_uploadedやclaude_chat_createdのように、Anthropic側のアクティビティ種別はclaude_で始まるものが多くあります。種別の全値はAPIリファレンスの一覧で確かめてください。Feedには数百種類のtypeがあり、新しい種別が追加されることもあるため、最後は必ずFilterがtrueのキャッチオールRouteで受けます。Routesの解説も、常にキャッチオールRouteを置くことを推奨しています。
送信先が1つの並列接続で済むなら、Routesを経由しないQuickConnectでも足ります。ただしQuickConnectはRouteレベルのフィルタリングを持たないため、種別による振り分けやクローンには向きません。条件分岐を1つのRouteから多方向へ出すなら、Output Routerという手もあります。
スケジュール・状態管理・再試行
ポーリングのしくみは、Source側が持っています。Activitiesでは、リクエストにorder=ascを付け、レスポンスのlast_idとhas_moreを読み、last_idを次のリクエストのafter_idに渡します。AnthropicのAPI自体は新しい順に返すため、Sourceは昇順を指定して「前回の続きから」を作っています。
取得する時間範囲は、時間フィルターに対応するエンドポイントでEarliest(既定-7d@d)とLatest(既定now)を指定します。-7d@dは「7日前の0時」を意味します。状態追跡をオンにすると、実行のたびに最後に見たタイムスタンプを保存し、重複と取りこぼしを減らします。
状態追跡の式は、エンドポイントの時刻フィールドに合わせて初期設定されています。Chatsの例では、updated_atが保存済みのlatestCreatedAtより新しいときだけ状態を更新します。時間フィルターの挙動を変えたら、式も合わせて直す必要があります。Manage Stateから、保存された状態を見たり消したりできます。
再試行(Retries)の初期値は次のとおりです。
| 設定 | 初期値 |
|---|---|
| Retry type | 初期値Backoff |
| Retry limit | 初期値5(最大20) |
| Backoff multiplier | 初期値2 |
| Retry HTTP codes | 初期値429と503 |
| Honor Retry-After header | 初期値有効 |
429で止まる場合は、再試行の設定を伸ばすより先に、cronの間隔を広げて「穏やかなスケジュール」にする、というのがSourceページの示す対処です。リクエストが多いのはActivitiesとChats、そしてTier 2です。
つまずきやすい箇所
Chat Messagesを有効にしたつもりなのに本文が出ない、という場合は、上から順に確かめます。
取り込めないときの切り分け
- QLive Dataにイベントが出ているか?答えがない答えがはい
SourceのLogsタブで認証エラーと取得エラーを見ます。認証が通らない場合は、アクセスキー、ヘッダー名、組織識別子をAnthropicのCompliance APIドキュメントと突き合わせます。
- Qエンドポイントの Enabled はオンか?答えがオフだった答えがはい
初期状態で有効なのはActivitiesだけです。Chat Messagesを使うなら、親のChatsを有効にします。
- Qチャットや本文のイベントも出ているか?答えが出ていない答えがはい
Admin APIキーを使っていないか確かめます。Admin APIキーで取れるのはActivity Feedだけです。
それでも欠けるとき
MonitoringページでイベントやバイトのDropをスケジュールやAPIエラーと突き合わせます。ジョブのタイムアウト(既定300秒)も候補です。
Non-2xxの応答は、原則としてエラーとして扱われます。一部のサブタスクだけが失敗した場合や、HTTPクライアントが3xxに従った場合は例外になりうるため、詳細はジョブのメッセージで読みます。
もう1つ見落としやすいのが、Compliance APIを呼ぶ行為自体がアクティビティとして記録される点です。Compliance Access KeyでもAdmin APIキーでも、呼び出しはapi_actorのアクティビティになります。Cribl Streamが5分ごとにポーリングするほど、監査ログの中に自分の取得操作が増えていきます。SIEM側で分析するときは、このapi_actorを除外するか別Routeに分けておくと、人の操作が埋もれません。
また、claude_chat_viewedのような「閲覧」アクティビティは、Claudeのアプリが内容を読み込むたびに記録され、重複排除もされません。「人が見た」ではなく「アプリが読み込んだ」という意味なので、件数の多さをそのまま閲覧回数と読まないようにします。
取得設計と保管期間の考え方
Activity Feedは、発生から1分以内に取得でき、6年間保持されます。ただし記録はCompliance APIを有効にした時点から始まり、さかのぼっては取れません。Cribl側でSIEMや長期保管に流し始める前の期間は、Anthropic側にも存在しないことになります。
保持期間の読み方や、内部統制の記録義務との対応はCompliance APIのFAQに、Activity Feedのフィルターとカーソルの仕様はActivity Feedの使い方にあります。
CriblでSourceを組むと、ポーリングやカーソルの管理は設定画面の値に置き換わります。残る設計判断は、どの項目を伏せ、どのデータをどこに何年置くか、の2点です。Anthropic側が6年保持する以上、Cribl側の保管年数は、社内で求められる保存期間との差で決められます。