ServiceNow Security ログを収集する

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

このドキュメントでは、ビジネスルールで構成されたアウトバウンド Webhook を使用して、ServiceNow Security イベントを Google Security Operations にエクスポートする方法について説明します。取り込みラベルによって、未加工のログデータを構造化 UDM 形式に正規化するパーサーが識別されます。

統合アーキテクチャ

  • この統合では、ServiceNow ビジネスルールを使用して、セキュリティ イベントを Google SecOps にリアルタイムでプッシュします。

    ServiceNow Security Tables
        ↓ (Business Rules trigger on insert/update)
    ServiceNow RESTMessageV2 API
        ↓ (HTTP POST)
    Google Security Operations Webhook Endpoint
        ↓ (Parser: SERVICENOW_SECURITY)
    Unified Data Model (UDM)
    

統合の特徴:

  • イベント ドリブン プッシュ: 作成または更新されたときにすぐに送信されるイベント
  • リアルタイム: 低レイテンシ(秒)
  • 選択的エクスポート: エクスポートするテーブルとイベントを構成する
  • 一括エクスポートではない: 過去のデータは送信されません

始める前に

次の前提条件を満たしていることを確認してください。

  • Google SecOps インスタンス
  • セキュリティ インシデント対応(SIR)プラグインがインストールされている ServiceNow インスタンス
  • 次のロールを持つ ServiceNow ユーザー アカウント:
    • admin または sn_si.admin(ビジネスルールを作成する場合)
    • [System Definition] > [Business Rules] へのアクセス権
    • システム定義 > スクリプト インクルードへのアクセス
  • Google Google Cloud コンソールへの特権アクセス(API キーの作成用)

エクスポート用の ServiceNow Security テーブル

次の表に、SIEM 分析に関連するセキュリティ データを示します。

テーブル API 名 説明 優先度
セキュリティ インシデント sn_si_incident セキュリティ インシデント、調査 HIGH
観測可能 sn_si_observable IOC: IP アドレス、ドメイン、ファイル ハッシュ HIGH
システムログ syslog 認証イベント、ログイン失敗 MEDIUM
監査 sys_audit フィールド レベルの変更、権限の変更 MEDIUM
ユーザーロールの割り当て sys_user_has_role ロールの付与/取り消し LOW
セキュリティの検出結果 sn_si_finding セキュリティの検出と検出結果 LOW

このガイドでは、優先度「HIGH」のテーブルのビジネスルールの例を示します。同じパターンを使用して、統合を他のテーブルに拡張できます。

ServiceNow Security イベントを取り込むように Google SecOps でフィードを構成する

Webhook フィードを設定する

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

フィード パラメータを構成する

  1. 次の入力パラメータの値を指定します。

    • Split delimiter: ログ行を区切るには、\n と入力します。
    • アセットの名前空間: アセットの名前空間
    • Ingestion labels: このフィードのすべてのイベントに適用されるラベル。
  2. [次へ] をクリックします。

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

秘密鍵を生成してエンドポイント URL を取得する

  1. [秘密鍵を生成する] をクリックして、このフィードを認証するためのシークレット キーを生成します。
  2. シークレット キーをコピーして安全な場所に保存します。

  3. [詳細] タブに移動します。

  4. [エンドポイント情報] フィールドから、フィードのエンドポイント URL をコピーします。

    • エンドポイント URL の例: https://malachiteingestion-pa.googleapis.com/v2/unstructured/projects/PROJECT_ID/locations/LOCATION/instances/INSTANCE_ID/logTypes/SERVICENOW_SECURITY:import
  5. [完了] をクリックします。

認証用の API キーを作成する

  1. Google Cloud コンソールの [認証情報] ページに移動します。
  2. [認証情報を作成] をクリックして [API キー] を選択します。
  3. [キーを制限] をクリックします。
  4. [API の制限] で次の操作を行います。
    • [キーを制限] を選択します。
    • [Google SecOps API](Chronicle API)を選択します。
  5. [保存] をクリックします。
  6. API キーをコピーして、安全な場所に保存します。

ServiceNow 統合の認証情報を構成する

安全なアクセスを実現するため、Google SecOps の認証情報を ServiceNow システム プロパティとして保存します。

  1. ServiceNow で、[System Properties] > sys_properties.list に移動します。
  2. [New] をクリックします。
  3. 最初のプロパティを作成します。
    • 名前: x_chronicle.endpoint_url
    • : 前の手順でコピーしたフィードのエンドポイント URL を貼り付けます。
    • タイプ: string
  4. [送信] をクリックします。
  5. [新規] をクリックして、2 つ目のプロパティを作成します。
    • 名前: x_chronicle.api_key
    • : Google Cloud API キーを貼り付けます。
    • : password(値を暗号化します)
  6. [送信] をクリックします。
  7. [新規] をクリックして、3 つ目のプロパティを作成します。
    • 名前: x_chronicle.secret_key
    • : Google SecOps フィードの秘密鍵を貼り付けます。
    • : password(値を暗号化します)
  8. [送信] をクリックします。

再利用可能な Webhook ユーティリティのスクリプト インクルードを作成する

このスクリプト インクルードは、任意のビジネスルールから Google SecOps にイベントを送信するための再利用可能な関数を提供します。

  1. [System Definition> Script Includes] に移動します。
  2. [New] をクリックします。
  3. 次の構成の詳細を指定します。
    • 名前: ChronicleWebhookUtil
    • API 名: ChronicleWebhookUtil
    • クライアント呼び出し可能: チェックを外します
    • 有効: チェックボックスをオンにする
  4. [スクリプト] フィールドに次のコードを入力します。

    var ChronicleWebhookUtil = Class.create();
    ChronicleWebhookUtil.prototype = {
        initialize: function() {
            // Read credentials from System Properties
            this.endpointURL = gs.getProperty('x_chronicle.endpoint_url');
            this.apiKey = gs.getProperty('x_chronicle.api_key');
            this.secretKey = gs.getProperty('x_chronicle.secret_key');
        },
    
        sendEvent: function(eventData, eventType) {
            try {
                // Validate credentials
                if (!this.endpointURL || !this.apiKey || !this.secretKey) {
                    gs.error('[Chronicle] Missing configuration. Check System Properties: x_chronicle.*');
                    return false;
                }
    
                // Prepare payload
                var payload = {
                    event_type: eventType,
                    timestamp: new GlideDateTime().getDisplayValue(),
                    data: eventData,
                    source: "ServiceNow",
                    source_instance: gs.getProperty('instance_name')
                };
    
                // Create REST message
                var request = new sn_ws.RESTMessageV2();
                request.setEndpoint(this.endpointURL + '?key=' + this.apiKey);
                request.setHttpMethod('POST');
    
                // Set headers
                request.setRequestHeader('Content-Type', 'application/json');
                request.setRequestHeader('x-chronicle-auth', this.secretKey);
    
                // Set request body
                request.setRequestBody(JSON.stringify(payload));
    
                // Execute request
                var response = request.execute();
                var statusCode = response.getStatusCode();
                var responseBody = response.getBody();
    
                // Check response
                if (statusCode == 200 || statusCode == 201 || statusCode == 204) {
                    gs.info('[Chronicle] Event sent successfully: ' + eventType + ' | Status: ' + statusCode);
                    return true;
                } else {
                    gs.error('[Chronicle] Failed to send event: ' + eventType + ' | Status: ' + statusCode + ' | Response: ' + responseBody);
                    return false;
                }
    
            } catch (ex) {
                gs.error('[Chronicle] Exception sending event: ' + ex.message);
                return false;
            }
        },
    
        type: 'ChronicleWebhookUtil'
    };
    
  5. [送信] をクリックします。

イベント エクスポートのビジネスルールを作成する

ビジネスルールは、ServiceNow テーブルでレコードが作成または更新されると自動的にトリガーされます。Google SecOps にエクスポートするテーブルごとにビジネスルールを作成します。

ビジネスルール: セキュリティ インシデント

このビジネスルールは、セキュリティ インシデント イベントを Google SecOps にエクスポートします。

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

    実行するタイミング:

    フィールド
    名前 Chronicle - Export Security Incident
    テーブル Security Incident [sn_si_incident]
    有効 オン
    上級 オン
    日時 after
    挿入 オン
    更新 オン
    削除 省略可(削除を追跡する場合はオンにします)
    Order 100
  4. [詳細設定] タブをクリックし、[スクリプト] フィールドに次のコードを入力します。

    (function executeRule(current, previous /*null when async*/) {
    
        // Extract incident data
        var incidentData = {
            sys_id: current.getValue('sys_id'),
            number: current.getValue('number'),
            short_description: current.getValue('short_description'),
            description: current.getValue('description'),
            state: current.getDisplayValue('state'),
            priority: current.getDisplayValue('priority'),
            severity: current.getDisplayValue('severity'),
            risk_score: current.getValue('risk_score'),
            category: current.getDisplayValue('category'),
            subcategory: current.getDisplayValue('subcategory'),
            assigned_to: current.getDisplayValue('assigned_to'),
            assignment_group: current.getDisplayValue('assignment_group'),
            caller: current.getDisplayValue('caller'),
            affected_user: current.getDisplayValue('affected_user'),
            opened_at: current.getValue('opened_at'),
            closed_at: current.getValue('closed_at'),
            resolved_at: current.getValue('resolved_at'),
            sys_created_on: current.getValue('sys_created_on'),
            sys_updated_on: current.getValue('sys_updated_on'),
            sys_created_by: current.getValue('sys_created_by'),
            sys_updated_by: current.getValue('sys_updated_by'),
            work_notes: current.getValue('work_notes'),
            close_notes: current.getValue('close_notes')
        };
    
        // Send to Chronicle
        var chronicleUtil = new ChronicleWebhookUtil();
        chronicleUtil.sendEvent(incidentData, 'security_incident');
    
    })(current, previous);
    
  5. [送信] をクリックします。

ビジネスルール: オブザーバブル(IOC)

このビジネスルールは、オブザーバブル データ(IP アドレス、ドメイン、ファイル ハッシュ)を Google SecOps にエクスポートします。

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

    フィールド
    名前 Chronicle - Export Observable
    テーブル Observable [sn_si_observable]
    有効 オン
    上級 オン
    日時 after
    挿入 オン
    更新 オン
    Order 100
  4. [詳細設定] タブをクリックし、[スクリプト] フィールドに次のコードを入力します。

    (function executeRule(current, previous) {
    
        var observableData = {
            sys_id: current.getValue('sys_id'),
            value: current.getValue('value'),
            type: current.getDisplayValue('type'),
            finding: current.getDisplayValue('finding'),
            sighting_count: current.getValue('sighting_count'),
            notes: current.getValue('notes'),
            security_tags: current.getValue('security_tags'),
            mitre_technique: current.getDisplayValue('mitre_technique'),
            mitre_tactic: current.getDisplayValue('mitre_tactic'),
            mitre_malware: current.getDisplayValue('mitre_malware'),
            sys_created_on: current.getValue('sys_created_on'),
            sys_created_by: current.getValue('sys_created_by')
        };
    
        var chronicleUtil = new ChronicleWebhookUtil();
        chronicleUtil.sendEvent(observableData, 'observable');
    
    })(current, previous);
    
  5. [送信] をクリックします。

ビジネスルール: システム ログイン イベント

このビジネスルールは、認証イベントとログイン イベントを Google SecOps にエクスポートします。

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

    フィールド
    名前 Chronicle - Export System Log
    テーブル System Log [syslog]
    有効 オン
    上級 オン
    日時 after
    挿入 オン
    Order 100
    条件 current.level == "error" || current.source.indexOf("login") != -1
  4. [詳細設定] タブをクリックし、[スクリプト] フィールドに次のコードを入力します。

    (function executeRule(current, previous) {
    
        var logData = {
            sys_id: current.getValue('sys_id'),
            level: current.getValue('level'),
            source: current.getValue('source'),
            message: current.getValue('message'),
            sys_created_on: current.getValue('sys_created_on'),
            sys_created_by: current.getValue('sys_created_by')
        };
    
        var chronicleUtil = new ChronicleWebhookUtil();
        chronicleUtil.sendEvent(logData, 'system_log');
    
    })(current, previous);
    
  5. [送信] をクリックします。

ビジネスルール: 監査証跡(権限の変更)

このビジネスルールは、監査証跡の目的でフィールド レベルの変更をエクスポートします。

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

    フィールド
    名前 Chronicle - Export Audit Changes
    テーブル Audit [sys_audit]
    有効 オン
    上級 オン
    日時 after
    挿入 オン
    Order 100
    条件 次のスクリプトをご覧ください。

    条件(重大な変更のみをフィルタ):

    ```javascript
    current.tablename == 'sys_user_has_role' || current.tablename == 'sys_user_group_member' || current.tablename == 'sn_si_incident' || current.fieldname == 'active' || current.fieldname == 'locked_out'
    ```
    
  4. [詳細設定] タブをクリックし、[スクリプト] フィールドに次のコードを入力します。

    (function executeRule(current, previous) {
    
        var auditData = {
            sys_id: current.getValue('sys_id'),
            tablename: current.getValue('tablename'),
            documentkey: current.getValue('documentkey'),
            fieldname: current.getValue('fieldname'),
            oldvalue: current.getValue('oldvalue'),
            newvalue: current.getValue('newvalue'),
            user: current.getDisplayValue('user'),
            reason: current.getValue('reason'),
            sys_created_on: current.getValue('sys_created_on')
        };
    
        var chronicleUtil = new ChronicleWebhookUtil();
        chronicleUtil.sendEvent(auditData, 'audit_change');
    
    })(current, previous);
    
  5. [送信] をクリックします。

省略可: エクスポートする追加のテーブル

ユーザーロールの割り当ての変更

セキュリティ監査のためにロールの付与と取り消しをエクスポートします。

  • sys_user_has_role テーブルにビジネスルールを作成します。

    (function executeRule(current, previous) {
    
        var roleData = {
            sys_id: current.getValue('sys_id'),
            user: current.getDisplayValue('user'),
            role: current.getDisplayValue('role'),
            granted_by: current.getDisplayValue('granted_by'),
            state: current.getValue('state'),
            sys_created_on: current.getValue('sys_created_on')
        };
    
        var chronicleUtil = new ChronicleWebhookUtil();
        chronicleUtil.sendEvent(roleData, 'role_assignment');
    
    })(current, previous);
    

セキュリティの検出結果

セキュリティの検出と検出結果をエクスポートします。

  • sn_si_finding テーブルにビジネスルールを作成します。

    (function executeRule(current, previous) {
    
        var findingData = {
            sys_id: current.getValue('sys_id'),
            finding: current.getValue('finding'),
            confidence: current.getValue('confidence'),
            severity: current.getDisplayValue('severity'),
            observable: current.getDisplayValue('observable'),
            sys_created_on: current.getValue('sys_created_on')
        };
    
        var chronicleUtil = new ChronicleWebhookUtil();
        chronicleUtil.sendEvent(findingData, 'finding');
    
    })(current, previous);
    

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

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

UDM マッピング テーブル

ServiceNow フィールド UDM マッピング ロジック
number metadata.product_event_type インシデント番号またはイベント番号
short_description security_result.summary セキュリティ イベントの簡単な説明
severity security_result.severity イベントの重大度レベル
priority security_result.priority イベントの優先度
caller principal.user.userid イベントを報告またはトリガーしたユーザー
affected_user target.user.userid セキュリティ イベントの影響を受けたユーザー
assigned_to security_result.action_details インシデントに割り当てられたアナリスト
sys_created_on metadata.event_timestamp イベント作成のタイムスタンプ
value(観測可能) network.ip または network.dns.questions.name オブザーバブル値(IP、ドメイン、ハッシュ)
type(観測可能) security_result.detection_fields.value オブザーバブルのタイプ(IP アドレス、ドメイン、ファイル ハッシュ)

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