ServiceNow Security ログを収集する

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

このドキュメントでは、Webhook フィードを使用して ServiceNow セキュリティ イベントを Google Security Operations に送信する方法について説明します。ServiceNow Security パーサーは、ログインの失敗、SNC ログイン、管理者ログイン、権限借用、セキュリティ昇格などの ServiceNow Instance Security Center セキュリティ イベント用に設計されています(ServiceNow Instance Security Center セキュリティ イベントをご覧ください)。ServiceNow 統合は、各イベントを JSON として Google SecOps Webhook エンドポイントに投稿します。ここで、パーサーはイベントを Unified Data Model(UDM)に正規化します。

パーサーは、Failed LoginAdmin LoginSNC LoginImpersonationSecurity Elevation の 5 つのイベント値を認識します。各値は、sysevent キューに登録された ServiceNow イベントに対応しています。このドキュメントでは、Webhook フィード、フィードに POST するスクリプト インクルード、一致する sysevent レコードでトリガーされ、スクリプト インクルードを呼び出す 4 つのスクリプト アクションを作成します。

この 1 回限りの設定を行うと、ServiceNow は新しいセキュリティ イベントを Google SecOps に自動的に転送します。管理者による対応は不要です。

始める前に

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

  • Google SecOps インスタンス。
  • admin ロールを持つユーザー アカウント、または [System Definition] > [Script Includes][System Properties][System Policy] > [Events] > [Script Actions][Registry] への権限を持つユーザー アカウントがある ServiceNow インスタンス。
  • 既存の ServiceNow インスタンス セキュリティ センターの有効化。ISC は販売終了しており、新しいインスタンスで有効にすることはできません。
  • Google Google Cloud コンソールへの特権アクセス(API キーの作成用)。

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

以降のセクションでは、Google SecOps で Webhook フィードを作成する方法について説明します。

フィードを作成する

  1. [SIEM 設定] > [フィード] に移動します。
  2. [Add New Feed] をクリックします。
  3. 次のページで、[単一のフィードを設定] をクリックします。
  4. [フィード名] フィールドに、フィードの名前を入力します(例: ServiceNow Security Events)。
  5. [Source type] として [Webhook] を選択します。
  6. [ログタイプ] として [ServiceNow Security] を選択します。
  7. [次へ] をクリックします。
  8. 次の入力パラメータの値を指定します。

    • 分割区切り文字: 統合がリクエストごとに複数の JSON イベントを送信する場合は、\n を入力します。各リクエストに 1 つのイベントが含まれている場合は、空のままにします。
    • Asset namespace: アセットの名前空間
    • Ingestion labels: このフィードのイベントに適用されるラベル。
  9. [次へ] をクリックします。

  10. [Finalize] 画面で新しいフィードの設定を確認し、[送信] をクリックします。

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

  1. フィードの詳細ページで、[シークレット キーを生成] をクリックします。
  2. 秘密鍵をコピーして安全な場所に保存します。

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

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

    https://malachiteingestion-pa.googleapis.com/v2/unstructuredlogentries:batchCreate
    

    リージョン エンドポイントの場合:

    https://<REGION>-malachiteingestion-pa.googleapis.com/v2/unstructuredlogentries:batchCreate
    
  3. この URL は後の手順で使用するため、保存しておきます。

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

Google Cloud API キーを作成する

  1. Google Google Cloud コンソールの [認証情報] ページに移動します。
  2. Google SecOps インスタンスに関連付けられているプロジェクトを選択します。
  3. [認証情報を作成> API キー] をクリックします。
  4. [API キーを編集] をクリックして、キーを制限します。
  5. [名前] フィールドに、わかりやすい名前(例: ServiceNow Webhook API Key)を入力します。
  6. [API の制限] で次の操作を行います。

    1. [キーを制限] を選択します。
    2. [API を選択] リストで、[Google SecOps API] を選択します。
  7. [保存] をクリックします。

  8. API キーをコピーして、安全な場所に保存します。

Google SecOps の認証情報を ServiceNow に保存する

統合コードにシークレットが含まれないように、エンドポイント URL と認証情報を ServiceNow システム プロパティとして保存します。

  1. ServiceNow で、[System Properties] > sys_properties.list に移動します。
  2. [新規] をクリックして、次の構成の詳細を指定します。

    • 名前: x_chronicle.endpoint_url
    • : フィード エンドポイント URL を貼り付けます。
    • タイプ: string
  3. [送信] をクリックします。

  4. [新規] をクリックして、次の構成の詳細を指定します。

    • 名前: x_chronicle.api_key
    • : Google Cloud API キーを貼り付けます。
    • タイプ: password2
  5. [送信] をクリックします。

  6. [新規] をクリックして、次の構成の詳細を指定します。

    • 名前: x_chronicle.secret_key
    • : Google SecOps フィードの秘密鍵を貼り付けます。
    • タイプ: password2
  7. [送信] をクリックします。

Webhook ユーティリティのスクリプト インクルードを作成する

このスクリプト インクルードは、ServiceNow sn_ws.RESTMessageV2 スコープ API を使用して、JSON ペイロードを Google SecOps Webhook エンドポイントに投稿します。API キーとシークレット キーは HTTP ヘッダーとして送信されます。

  1. [System Definition> Script Includes] に移動します。
  2. [New] をクリックします。
  3. 次の構成情報を提供してください。

    • 名前: ChronicleWebhookUtil
    • API 名: ChronicleWebhookUtil
    • Client callable: チェックを外します
    • 有効: チェックボックスをオンにする
  4. [スクリプト] フィールドに次のコードを入力します。

    var ChronicleWebhookUtil = Class.create();
    ChronicleWebhookUtil.prototype = {
        initialize: function() {
            this.endpointURL = gs.getProperty('x_chronicle.endpoint_url');
            this.apiKey = gs.getProperty('x_chronicle.api_key');
            this.secretKey = gs.getProperty('x_chronicle.secret_key');
        },
    
        // payload: a plain object whose keys match the required JSON contract.
        sendEvent: function(payload) {
            try {
                if (!this.endpointURL || !this.apiKey || !this.secretKey) {
                    gs.error('[Chronicle] Missing configuration. Check System Properties: x_chronicle.*');
                    return false;
                }
    
                var request = new sn_ws.RESTMessageV2();
                request.setEndpoint(this.endpointURL);
                request.setHttpMethod('POST');
                request.setRequestHeader('Content-Type', 'application/json');
                request.setRequestHeader('X-goog-api-key', this.apiKey);
                request.setRequestHeader('X-Webhook-Access-Key', this.secretKey);
                request.setRequestBody(JSON.stringify(payload));
    
                var response = request.execute();
                var statusCode = response.getStatusCode();
    
                if (statusCode == 200 || statusCode == 201 || statusCode == 204) {
                    gs.info('[Chronicle] Event sent: ' + payload.event + ' | Status: ' + statusCode);
                    return true;
                }
    
                gs.error('[Chronicle] Failed to send event: ' + payload.event + ' | Status: ' + statusCode + ' | Response: ' + response.getBody());
                return false;
            } catch (ex) {
                gs.error('[Chronicle] Exception sending event: ' + ex.message);
                return false;
            }
        },
    
        type: 'ChronicleWebhookUtil'
    };
    
  5. [送信] をクリックします。

イベント レジストリを確認する

スクリプト アクションは、イベント名がイベント レジストリsysevent_register テーブル)に存在する場合にのみ実行されます。ServiceNow は、この統合で使用される 5 つのイベントをすぐに使用できる状態で提供していますが、エントリが欠落しているとエラーが発生せず、スクリプト アクションが実行されないため、確認することをおすすめします。

  1. ServiceNow で、[System Policy](sysevent_register.list)に移動します。
  2. [イベント名] 列で次の各エントリをフィルタし、レコードが存在することを確認します。

    • login
    • login.failed
    • impersonation.start
    • security.elevated_role.enabled
  3. エントリがない場合は、[新規] をクリックし、[イベント名] フィールドにない値を設定し、[テーブル] を Global [global] に設定して、[送信] をクリックします。

スクリプト アクションを作成する

各スクリプト アクションは、1 つの ServiceNow イベント名をサブスクライブします。ServiceNow が一致するレコードを sysevent キューに挿入すると、スクリプト アクションが実行され、イベント パラメータが読み取られ、ChronicleWebhookUtil が呼び出されてペイロードが POST されます。

パーサーは次の ServiceNow イベントにマッピングします。

パーサーの event ServiceNow イベント名 トリガー
Failed Login login.failed ログイン試行の失敗(任意の認証方法)。
Admin Login login admin ロールを持つユーザーによるログインの成功。
SNC Login login snc_external ロールを持つユーザーによるログインの成功。
Impersonation impersonation.start 管理者が別のユーザーになりすまします。
Security Elevation security.elevated_role.enabled ユーザーが security_admin または別の高権限ロールに昇格する。

loginlogin.failed は、parm1 をユーザー名に、parm2 を送信元 IP に設定します。他のイベントも同じ parm1/parm2 の規則に従いますが、正確な内容は ServiceNow のリリースによって異なります。各イベントのレジストリ エントリを開き、パラメータの説明が後述のスクリプトと一致していることを確認します。レジストリが異なる場合は、parm1 または parm2 の参照を調整します。

ログイン失敗スクリプト アクションを作成する

  1. [System Policy] > [Events] > [Script Actions] に移動します。
  2. [New] をクリックします。
  3. 次の構成情報を提供してください。

    • 名前: Chronicle - Failed Login
    • イベント名: login.failed
    • 有効: チェックボックスをオンにする
  4. [スクリプト] フィールドに次のコードを入力します。

    (function runAction(/*GlideRecord*/ current, /*GlideRecord*/ event) {
        new ChronicleWebhookUtil().sendEvent({
            event: 'Failed Login',
            event_created: event.sys_created_on.getValue(),
            user: event.parm1.toString(),
            ip_address: event.parm2.toString()
        });
    })(current, event);
    
  5. [送信] をクリックします。

ログイン スクリプト アクションを作成する

このスクリプト アクションは、ログインが成功するたびに実行され、ログインしたユーザーが admin または snc_external のロールを持っている場合にのみレコードを転送します。event フィールドが適切に設定されます。

  1. [System Policy] > [Events] > [Script Actions] に移動します。
  2. [New] をクリックします。
  3. 次の構成情報を提供してください。

    • 名前: Chronicle - Login
    • イベント名: login
    • 有効: チェックボックスをオンにする
  4. [スクリプト] フィールドに次のコードを入力します。

    (function runAction(/*GlideRecord*/ current, /*GlideRecord*/ event) {
        var userName = event.parm1.toString();
        var ipAddress = event.parm2.toString();
    
        var user = new GlideRecord('sys_user');
        if (!user.get('user_name', userName)) {
            return;
        }
    
        function hasRole(roleName) {
            var role = new GlideRecord('sys_user_has_role');
            role.addQuery('user', user.sys_id);
            role.addQuery('role.name', roleName);
            role.query();
            return role.next();
        }
    
        var eventValue;
        if (hasRole('snc_external')) {
            eventValue = 'SNC Login';
        } else if (hasRole('admin')) {
            eventValue = 'Admin Login';
        } else {
            return;
        }
    
        new ChronicleWebhookUtil().sendEvent({
            event: eventValue,
            event_created: event.sys_created_on.getValue(),
            user: userName,
            ip_address: ipAddress
        });
    })(current, event);
    
  5. [送信] をクリックします。

なりすましスクリプト アクションを作成する

  1. [System Policy] > [Events] > [Script Actions] に移動します。
  2. [New] をクリックします。
  3. 次の構成情報を提供してください。

    • 名前: Chronicle - Impersonation
    • イベント名: impersonation.start
    • 有効: チェックボックスをオンにする
  4. [スクリプト] フィールドに次のコードを入力します。

    (function runAction(/*GlideRecord*/ current, /*GlideRecord*/ event) {
        new ChronicleWebhookUtil().sendEvent({
            event: 'Impersonation',
            event_created: event.sys_created_on.getValue(),
            user: event.parm1.toString(),       // impersonator
            snc_user: event.parm2.toString()    // impersonated user
        });
    })(current, event);
    
  5. [送信] をクリックします。

セキュリティ昇格スクリプト アクションを作成する

  1. [System Policy] > [Events] > [Script Actions] に移動します。
  2. [New] をクリックします。
  3. 次の構成情報を提供してください。

    • 名前: Chronicle - Security Elevation
    • イベント名: security.elevated_role.enabled
    • 有効: チェックボックスをオンにする
  4. [スクリプト] フィールドに次のコードを入力します。

    (function runAction(/*GlideRecord*/ current, /*GlideRecord*/ event) {
        new ChronicleWebhookUtil().sendEvent({
            event: 'Security Elevation',
            event_created: event.sys_created_on.getValue(),
            user: event.parm1.toString()
        });
    })(current, event);
    
  5. [送信] をクリックします。

統合を確認する

次のいずれかの方法を使用します。

合成イベントで検証する

実際のセキュリティ イベントを待たずに各スクリプト アクションをすぐにテストするには、バックグラウンド スクリプトからイベントをキューに登録します。

  1. ServiceNow で、[System Definition] > [Scripts - Background] に移動します。
  2. [スクリプトを実行] フィールドに次のいずれかの行を入力し、[スクリプトを実行] をクリックします。

    gs.eventQueue('login.failed', null, 'test.user', '203.0.113.45');
    gs.eventQueue('login', null, 'admin', '203.0.113.45');
    gs.eventQueue('impersonation.start', null, 'admin', 'test.user');
    gs.eventQueue('security.elevated_role.enabled', null, 'admin', 'security_admin');
    
  3. Event Manager ジョブがキューを処理するまで 1 分ほど待ちます。

実際のイベントで確認する

統合を確認するには、ServiceNow で次のいずれかのマッピングされたセキュリティ イベントを生成します。

  • ログイン失敗: プライベート ブラウザ ウィンドウで /login.do を開き、無効なパスワードを送信します。
  • 管理者ログイン: 通常とは異なる IP アドレスから admin ロールを持つユーザーでログインします。
  • 権限借用: 管理者アカウントから別のユーザーの権限を借用します。
  • セキュリティの昇格: admin ロールを持つユーザーから security_admin ロールに昇格します。

転送を確認する

  1. ServiceNow で、[System Policy] > [Events] > [Event Log]sysevent.list)に移動し、対応するイベント名を含むレコードが表示されることを確認します。
  2. ServiceNow で、[System Logs > System Log > All] に移動し、ステータス 200、201、または 204 の [Chronicle] Event sent: ... 情報メッセージが表示されることを確認します。[Chronicle] Failed to send event または [Chronicle] Exception sending event メッセージは、認証情報または接続の問題を示します。
  3. Google SecOps で、metadata.vendor_name = "SERVICENOW"metadata.product_name = "SERVICENOW_SECURITY" の UDM 検索を実行します。
  4. イベントが表示され、metadata.event_typeUSER_LOGIN または USER_CHANGE_PERMISSIONS に設定され、principal.user.userid が入力されていることを確認します。

認証方法のリファレンス

Google SecOps Webhook フィードは、API キーとシークレット キーを HTTP ヘッダーまたは URL クエリ パラメータとして受け入れます。このガイドでは、ヘッダー メソッドを使用します。これは、sn_ws.RESTMessageV2 がカスタム ヘッダーをサポートしているため、認証情報が URL やサーバー アクセスログに記録されないためです。

このガイドで使用されているヘッダー:

  • X-goog-api-key: Google SecOps API の Google Cloud API キー。
  • X-Webhook-Access-Key: Google SecOps によって生成されたフィードの秘密鍵。

統合でカスタム ヘッダーを送信できない場合は、代わりにエンドポイント URL に認証情報を追加します。

<ENDPOINT_URL>?key=<API_KEY>&secret=<SECRET_KEY>

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

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

ボリュームを制御するには、検出に必要なセキュリティ イベントのみを送信します。ソースがバーストでイベントを生成する場合は、\n 分割区切り文字を使用して、リクエストごとに複数のイベントをバッチ処理します。

Google SecOps フィードの詳細については、Google SecOps フィードのドキュメントをご覧ください。各フィードタイプの要件については、タイプ別のフィード構成をご覧ください。

フィードの作成時に問題が発生した場合は、Google SecOps サポートにお問い合わせください。

UDM マッピング テーブル

ログフィールド UDM マッピング ロジック
event extensions.auth.type マッピング: "Failed Login", "SNC Login", "Admin Login", "Impersonation"MACHINE
event_created metadata.event_timestamp yyyy-MM-dd HH:mm:ss として解析
event_type metadata.event_type 名前変更済み/マッピング済み
event metadata.product_event_type event != `` の場合にマッピングされます
ip_address principal.ip 統合済み
user principal.user.userid user != `` の場合にマッピングされます
created_by target.user.userid created_by != `` の場合にマッピングされます
snc_user target.user.userid snc_user != `` の場合にマッピングされます
timestamp event1.idm.read_only_udm.metadata.event_timestamp 変更履歴からマッピング
data.sys_id event1.idm.read_only_udm.metadata.product_log_id 変更履歴からマッピング
data.message_data event1.idm.read_only_udm.metadata.description 変更履歴からマッピング
data.source event1.idm.read_only_udm.principal.resource.name 変更履歴からマッピング
source event1.idm.read_only_udm.additional.fields 変更履歴からマッピング
data.sys_created_on event1.idm.read_only_udm.metadata.collected_timestamp 変更履歴からマッピング
data.sys_created_by event1.idm.read_only_udm.principal.user.userid 変更履歴からマッピング
data.user event1.idm.read_only_udm.principal.user.userid 変更履歴からマッピング
source_instance event1.idm.read_only_udm.principal.namespace 変更履歴からマッピング
data.role event1.idm.read_only_udm.target.resource.attribute.roles 変更履歴からマッピング
data.granted_by event1.idm.read_only_udm.target.user.userid 変更履歴からマッピング
data.level event1.idm.read_only_udm.security_result.severity 変更履歴からマッピング
data.state event1.idm.read_only_udm.security_result.action_details 変更履歴からマッピング

変更履歴

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

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