Keycloak ログを収集する

以下でサポートされています。

このドキュメントでは、Webhook を使用してログを Google Security Operations に push するように Keycloak を構成する方法について説明します。

Keycloak は、シングル サインオン(SSO)、ユーザー連携、ID ブローカリング、ソーシャル ログイン機能を提供するオープンソースの Identity and Access Management(IAM)ソリューションです。OpenID Connect、OAuth 2.0、SAML 2.0 の各プロトコルをサポートし、セキュリティ監査のためにユーザー イベント(ログイン、ログアウト、登録、パスワード変更)と管理者イベント(ユーザー、クライアント、レルム、ロールの管理オペレーション)を追跡します。

始める前に

次の前提条件を満たしていることを確認します。

  • Google SecOps インスタンス
  • 実行中の Keycloak インスタンス(バージョン 20 以降を推奨)
  • Keycloak 管理コンソールへの管理者アクセス権
  • 拡張機能をデプロイするための Keycloak サーバーのファイルシステムまたはコンテナへのアクセス
  • Google Cloud コンソールへのアクセス(API キーの作成用)

Google SecOps で Webhook フィードを作成する

フィードを作成する

  1. [設定] > [データ管理] > [フィード] に移動します。SIEM のみのプラットフォームを使用している場合は、[設定] > [フィード] に移動します。
  2. [Add New Feed] をクリックします。
  3. 次のページで、[単一のフィードを構成する] をクリックします。
  4. [フィード名] フィールドに、フィードの名前を入力します(例: Keycloak Events)。
  5. [Source type] として [Webhook] を選択します。
  6. [ログタイプ] として [Keycloak] を選択します。
  7. [次へ] をクリックします。
  8. 次の入力パラメータの値を指定します。
    • Split delimiter(省略可): \n を入力して、複数行のイベントを分割します(各 Webhook POST には 1 つのイベントが含まれているため、これは空のままにできます)。
    • Asset namespace: アセットの名前空間。
    • Ingestion labels: このフィードのイベントに適用されるラベル。
  9. [次へ] をクリックします。
  10. [Finalize] 画面で新しいフィードの設定を確認し、[送信] をクリックします。

秘密鍵を生成して保存する

フィードを作成したら、認証用の秘密鍵を生成する必要があります。

  1. フィードの詳細ページで、[Generate Secret Key] をクリックします。
  2. ダイアログに秘密鍵が表示されます。
  3. 秘密鍵をコピーして安全に保存します。

重要: 秘密鍵は 1 回しか表示されず、後で取得することはできません。秘密鍵を紛失した場合は、新しい秘密鍵を生成する必要があります。

フィード エンドポイント URL を取得する

  1. フィードの [詳細] タブに移動します。
  2. [エンドポイント情報] セクションで、[フィードのエンドポイント URL] をコピーします。
  3. URL の形式は次のとおりです。

    https://{region}-chronicle.googleapis.com/v1/{parent}/logs:import
    

    ここで、{region} は Google SecOps インスタンスのリージョン(us、europe、asia-southeast1 など)、{parent} は projects/<PROJECT_ID>/locations/<LOCATION>/instances/<INSTANCE_ID>/logTypes/<LOG_TYPE> 形式のリソースパスです。

  4. 次の手順で使用するために、この URL を保存します。

  5. [完了] をクリックします。

Google Cloud API キーを作成する

Chronicle では、認証に API キーが必要です。Google Cloud コンソールで制限付き API キーを作成します。

API キーを作成する

  1. Google Cloud コンソールの [認証情報] ページに移動します。
  2. プロジェクト(Chronicle インスタンスに関連付けられているプロジェクト)を選択します。
  3. [認証情報を作成] > [API キー] をクリックします。
  4. API キーが作成され、ダイアログに表示されます。
  5. [API キーを編集] をクリックしてキーを制限します。

API キーを制限する

  1. [API キー] の設定ページで、次の操作を行います。
    • 名前: わかりやすい名前を入力します(例: Chronicle Webhook API Key)。
  2. [API の制限] で次の操作を行います。
    1. [キーを制限] を選択します。
    2. [API を選択] プルダウンで、[Google SecOps API](または [Chronicle API])を検索して選択します。
  3. [保存] をクリックします。
  4. ページ上部の [API キー] フィールドから API キーの値をコピーします。
  5. API キーを安全に保存します。

Keycloak でイベント ストレージを有効にする

Webhook 拡張機能を構成する前に、Keycloak でイベント ストレージを有効にして、イベントが生成され、転送に使用できるようにします。

ユーザー イベントを有効にする

  1. Keycloak 管理コンソールにログインします。
  2. 左上のレルム プルダウンから、モニタリングするレルムを選択します。
  3. [Realm Settings] > [Events] に移動します。
  4. [ユーザー イベントの設定] サブタブを選択します。
  5. [予定を保存] を有効にします。
  6. [有効期限] を設定します(推奨される最小期間: 7 日間)。
  7. [保存] をクリックします。

管理イベントを有効にする

  1. 同じ [Events] タブで、[Admin events settings] サブタブを選択します。
  2. [予定を保存] を有効にします。
  3. [表現を含める] を有効にして、変更されたオブジェクトの詳細をすべてキャプチャします。
  4. [有効期限] を設定します(推奨される最小期間: 7 日間)。
  5. [保存] をクリックします。

Webhook イベント リスナー拡張機能をインストールする

Keycloak には、ネイティブの Webhook イベント リスナーは含まれていません。Phase Two(p2-inc)の keycloak-events 拡張機能をインストールして、Webhook の配信を有効にします。

拡張機能をダウンロードしてデプロイする

  1. Maven Central の keycloak-events リリース ページから最新リリースの JAR をダウンロードするか、ソースからビルドします。

    git clone https://github.com/p2-inc/keycloak-events.git
    cd keycloak-events
    mvn clean install
    
  2. 生成された fat JAR ファイルを Keycloak の providers ディレクトリにコピーします。

    cp target/keycloak-events-*.jar /opt/keycloak/providers/
    
  3. Keycloak を再ビルドして再起動します。

    /opt/keycloak/bin/kc.sh build
    /opt/keycloak/bin/kc.sh start
    

Webhook イベント リスナーを有効にする

  1. Keycloak 管理コンソールにログインします。
  2. レルムのプルダウンからターゲット レルム を選択します。
  3. [Realm Settings] > [Events] に移動します。
  4. [イベント リスナー] プルダウンで、[ext-event-webhook] を選択します。
  5. [保存] をクリックします。

Keycloak Webhook を構成する

Webhook URL を作成する

  • Chronicle エンドポイント URL と API キーを組み合わせます。

    <ENDPOINT_URL>?key=<API_KEY>
    
  • 例:

    https://{region}-chronicle.googleapis.com/v1/{parent}/logs:import?key=AIzaSyD...
    

Keycloak REST API を使用して Webhook サブスクリプションを作成する

keycloak-events 拡張機能は、Webhook サブスクリプションを管理するための REST エンドポイントを提供します。Keycloak Admin REST API を使用して、Webhook を作成します。

ステップ 1: アクセス トークンを取得する

  • 管理者アカウントを使用して Keycloak にアクセス トークンをリクエストします。

    TOKEN=$(curl -sS -X POST "https://<KEYCLOAK_HOST>/realms/master/protocol/openid-connect/token" \
      -H "Content-Type: application/x-www-form-urlencoded" \
      --data-urlencode "grant_type=password" \
      --data-urlencode "client_id=admin-cli" \
      --data-urlencode "username=<ADMIN_USERNAME>" \
      --data-urlencode "password=<ADMIN_PASSWORD>" \
      | sed -n 's/.*"access_token":"\([^"]*\)".*/\1/p')
    

次のように置き換えます。

  • <KEYCLOAK_HOST>: Keycloak サーバーのホスト名とポート(例: keycloak.example.com:8443)
  • <ADMIN_USERNAME>: Keycloak 管理者のユーザー名
  • <ADMIN_PASSWORD>: Keycloak 管理者パスワード

ステップ 2: Webhook を作成する

  • POST リクエストを送信して、ターゲット レルムの Webhook サブスクリプションを作成します。

    curl -sS -X POST "https://<KEYCLOAK_HOST>/realms/<REALM_NAME>/webhooks" \
      -H "Authorization: Bearer ${TOKEN}" \
      -H "Content-Type: application/json" \
      -d '{
        "enabled": "true",
        "url": "<ENDPOINT_URL>?key=<API_KEY>&secret=<SECRET_KEY>",
        "secret": "<WEBHOOK_HMAC_SECRET>",
        "eventTypes": ["*"]
      }'
    

次のように置き換えます。

  • <KEYCLOAK_HOST>: Keycloak サーバーのホスト名
  • <REALM_NAME>: モニタリングするレルムの名前(例: master、my-realm)
  • <ENDPOINT_URL>: 前にコピーした Chronicle フィード エンドポイントの URL
  • <API_KEY>: 前に作成した Google Cloud API キー
  • <SECRET_KEY>: 前に生成した Chronicle Webhook の秘密鍵
  • <WEBHOOK_HMAC_SECRET>: Webhook ペイロードの HMAC 署名用の任意のシークレット文字列(例: mySecretKey123)

ステップ 3: Webhook を確認する

  • レルムのすべての Webhook を一覧表示して、Webhook が作成されたことを確認します。

    curl -sS -X GET "https://<KEYCLOAK_HOST>/realms/<REALM_NAME>/webhooks" \
      -H "Authorization: Bearer ${TOKEN}" \
      -H "Accept: application/json"
    

レスポンスは、Webhook オブジェクトのリストを返します。Webhook が "enabled": "true" と正しい URL で表示されていることを確認します。

Webhook イベントタイプ

eventTypes フィールドには、送信するイベントをフィルタする式の配列を指定します。

  • * - すべてのイベントを送信する(SIEM 統合に推奨)
  • access.* - すべてのアクセス イベントを送信する
  • admin.* - すべての管理イベントを送信する
  • admin.USER-* - ユーザーに関連するすべての管理イベントを送信する
  • admin-USER-CREATE - ユーザー作成の管理イベントのみを送信する

Webhook ペイロード形式

  • Webhook は、JSON ペイロードを含む HTTP POST リクエストとしてイベントを送信します。ユーザー イベント ペイロードの例:

    {
      "id": "987865-1a2b-3c4d-9876-654321abc",
      "time": 1767799710612,
      "type": "LOGIN",
      "realmId": "12345abcde-1a2b-4d3c-9876-abcd456",
      "clientId": "account-console",
      "userId": "abcd456-1234-5678-abc9-987gfed654",
      "sessionId": "efghij-9876-abcd-456-11223344",
      "ipAddress": "203.0.113.45",
      "details": {
        "auth_method": "openid-connect",
        "auth_type": "code",
        "redirect_uri": "https://app.example.com/callback",
        "consent": "no_consent_required",
        "username": "jdoe"
      }
    }
    

Webhook の再試行動作

この拡張機能は、2xx 以外のレスポンスを受信すると、再試行に自動指数バックオフを使用します。

パラメータ デフォルト値 説明
backoffInitialInterval 500 ミリ秒 最初の再試行間隔
backoffMaxElapsedTime 900,000 ミリ秒(15 分) 合計再試行時間の最大値
backoffMaxInterval 180,000 ミリ秒(3 分) 再試行の最大間隔
backoffMultiplier 5 各再試行間隔の乗数
backoffRandomizationFactor 0.5 ジッターのランダム化係数

認証方法のリファレンス

Chronicle の Webhook フィードは、複数の認証方法をサポートしています。ベンダーがサポートしている方法を選択してください。

ベンダーがカスタム HTTP ヘッダーをサポートしている場合は、セキュリティを強化するためにこの方法を使用します。

  • リクエストの形式:

    POST <ENDPOINT_URL> HTTP/1.1
    Content-Type: application/json
    x-goog-chronicle-auth: <API_KEY>
    x-chronicle-auth: <SECRET_KEY>
    
    {
            "event": "data",
            "timestamp": "2025-01-15T10:30:00Z"
    }
    

メリット:

  • API キーとシークレットが URL に表示されない
  • より安全(ヘッダーはウェブサーバーのアクセスログに記録されない)
  • ベンダーが対応している場合に推奨される方法

方法 2: クエリ パラメータ

ベンダーがカスタム ヘッダーをサポートしていない場合は、URL に認証情報を追加します。

  • URL 形式:

    <ENDPOINT_URL>?key=<API_KEY>&secret=<SECRET_KEY>
    
  • 例:

    https://{region}-chronicle.googleapis.com/v1/{parent}/logs:import?key=AIzaSyD...&secret=abcd1234...
    
  • リクエストの形式:

    POST <ENDPOINT_URL>?key=<API_KEY>&secret=<SECRET_KEY> HTTP/1.1
    Content-Type: application/json
    
    {
            "event": "data",
            "timestamp": "2025-01-15T10:30:00Z"
    }
    

デメリット:

  • URL に表示される認証情報
  • ウェブサーバーのアクセスログに記録される可能性がある
  • ヘッダーよりも安全性が低い

方法 3: ハイブリッド(URL + ヘッダー)

一部の構成では、URL に API キー、ヘッダーに秘密鍵を使用します。

  • リクエストの形式:

    POST <ENDPOINT_URL>?key=<API_KEY> HTTP/1.1
    Content-Type: application/json
    x-chronicle-auth: <SECRET_KEY>
    
    {
            "event": "data",
            "timestamp": "2025-01-15T10:30:00Z"
    }
    

認証ヘッダー名

Chronicle では、認証に次のヘッダー名を使用できます。

API キーの場合:

  • x-goog-chronicle-auth(推奨)
  • X-Goog-Chronicle-Auth(大文字と小文字を区別しない)

秘密鍵の場合:

  • x-chronicle-auth(推奨)
  • X-Chronicle-Auth(大文字と小文字を区別しない)

Webhook の制限とベスト プラクティス

リクエストに関する上限

上限 値
最大リクエスト サイズ 4 MB
最大 QPS(秒間クエリ数) 15,000
リクエストのタイムアウト 30 秒
再試行の動作 指数バックオフによる自動

UDM マッピング テーブル

ログフィールド UDM マッピング ロジック
payload.client_id additional.fields payload.client_id、payload.realm_id から作成されたフィールドと統合
payload.realm_id additional.fields
source_timestamp metadata.event_timestamp パターン ISO8601 と yyyy-MM-dd'T'HH:mm:ss.SSSZ を使用して日付フィルタで解析
payload.ip_address metadata.event_type payload.ip_address が空でない場合は「STATUS_UPDATE」に設定します。それ以外の場合、uuid が空でない場合は「USER_UNCATEGORIZED」に設定します。それ以外の場合は「GENERIC_EVENT」に設定します。
uuid metadata.event_type
payload.type metadata.product_event_type 値が直接コピーされる
payload.session_id network.session_id 値が直接コピーされる
payload.ip_address principal.ip 値が直接コピーされる
source_metadata.schema principal.resource.attribute.labels source_metadata.schema、source_metadata.table、source_metadata.is_deleted(文字列に変換)、source_metadata.change_type、source_metadata.tx_id、source_metadata.lsn から作成されたラベルと統合されます。
source_metadata.table principal.resource.attribute.labels
source_metadata.is_deleted principal.resource.attribute.labels
source_metadata.change_type principal.resource.attribute.labels
source_metadata.tx_id principal.resource.attribute.labels
source_metadata.lsn principal.resource.attribute.labels
uuid principal.user.userid 値が直接コピーされる
オブジェクト security_result.detection_fields object、read_method、payload.id から作成されたラベルと統合
read_method security_result.detection_fields
payload.id security_result.detection_fields
redirect_uri target.url 値が直接コピーされる
ユーザー名 target.user.userid 値が直接コピーされる
metadata.product_name metadata.product_name 「KEYCLOAK」に設定します。
metadata.vendor_name metadata.vendor_name 「KEYCLOAK」に設定します。
username" from "details_json target.user.userid 変更履歴からマッピング
redirect_uri" from "details_json target.url 変更履歴からマッピング
realm_id" and "client_id additional.fields 変更履歴からマッピング

変更ログ

このパーサーの変更ログを表示する

さらにサポートが必要な場合 コミュニティ メンバーや Google SecOps のプロフェッショナルから回答を得ることができます。