Signal Sciences WAF のログを収集する

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

このドキュメントでは、 Google Cloud Storage を使用して Signal Sciences WAF ログを Google Security Operations に取り込む方法について説明します。パーサーは、Signal Sciences ログを JSON 形式から Chronicle の統合データモデル(UDM)に変換します。2 つの主要なメッセージ構造を処理します。「RPC.PreRequest/PostRequest」メッセージは Grok パターンを使用して解析され、他のメッセージは JSON オブジェクトとして処理され、関連するフィールドが抽出されて UDM スキーマにマッピングされます。

始める前に

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

  • Google SecOps インスタンス
  • VPC フローが環境で設定され、アクティブになっている Google Cloud
  • Signal Sciences WAF への特権アクセス

Google Cloud Storage バケットの作成

  1. Google Cloud コンソールにログインします。
  2. [Cloud Storage バケット] のページに移動します。

    [バケット] に移動

  3. [作成] をクリックします。

  4. [バケットの作成] ページでユーザーのバケット情報を入力します。以下のステップでは、操作を完了した後に [続行] をクリックして、次のステップに進みます。

    1. [始める] セクションで、次の操作を行います。

      • バケット名の要件を満たす一意の名前を入力します(vpcflow-logs など)。
      • 階層名前空間を有効にするには、展開矢印をクリックして [Optimize for file oriented and data-intensive workloads] セクションを開き、[このバケットで階層的な名前空間を有効にする] を選択します。
      • バケットラベルを追加するには、展開矢印をクリックして [ラベル] セクションを開きます。
      • [ラベルを追加] をクリックし、ラベルのキーと値を指定します。
    2. [データの保存場所の選択] セクションで、次の操作を行います。

      • ロケーション タイプを選択してください。
      • ロケーション タイプのメニューを使用して、バケット内のオブジェクト データが永続的に保存されるロケーションを選択します。
      • クロスバケット レプリケーションを設定するには、[クロスバケット レプリケーションを設定する] セクションを開きます。
    3. [データのストレージ クラスを選択する] セクションで、バケットのデフォルトのストレージ クラスを選択します。あるいは、Autoclass を選択して、バケットデータのストレージ クラスを自動的に管理します。

    4. [オブジェクトへのアクセスを制御する方法を選択する] セクションで、[なし] を選択して公開アクセスの防止を適用し、バケットのオブジェクトの [アクセス制御モデル] を選択します。

    5. [オブジェクト データを保護する方法を選択する] セクションで、次の操作を行います。

      • [データ保護] で、バケットに設定するオプションを選択します。
      • オブジェクト データの暗号化方法を選択するには、[データ暗号化] というラベルの付いた展開矢印をクリックし、データの暗号化方法を選択します。
  5. [作成] をクリックします。

Signal Sciences WAF API キーを構成する

  1. Signal Sciences WAF ウェブ UI にログインします。
  2. [マイ プロフィール] > [API アクセス トークン] に移動します。
  3. [API アクセス トークンを追加] をクリックします。
  4. 一意のわかりやすい名前を指定します(例: Google SecOps)。
  5. [Create API access token] をクリックします。
  6. トークンをコピーして安全な場所に保存します。
  7. [I understand] をクリックして、トークンの作成を完了します。

Linux ホストにスクリプトをデプロイして、Signal Sciences からログを取得し、 Google Cloudに保存します。

  1. SSH を使用して Linux ホストにログインします。
  2. Python ライブラリをインストールして、Signal Sciences WAF JSON を Cloud Storage バケットに保存します。

    pip install google-cloud-storage
    
  3. この環境変数を設定して、 Google Cloudの認証情報を含む JSON ファイルを呼び出します。

    export GOOGLE_APPLICATION_CREDENTIALS="path/to/your/service-account-key.json"
    
  4. この情報はハードコードできないため、次の環境変数を構成します。

    export SIGSCI_EMAIL=<Signal_Sciences_account_email>
    export SIGSCI_TOKEN=<Signal_Sciences_API_token>
    export SIGSCI_CORP=<Corporation_name_in_Signal_Sciences>
    
  5. 次のスクリプトを実行します。

    import sys
    import requests
    import os
    import calendar
    import json
    from datetime import datetime, timedelta
    from google.cloud import storage
    
    # Check if all necessary environment variables are set
    
    if 'SIGSCI_EMAIL' not in os.environ or 'SIGSCI_TOKEN' not in os.environ or 'SIGSCI_CORP' not in os.environ:
    print("ERROR: You need to define SIGSCI_EMAIL, SIGSCI_TOKEN, and SIGSCI_CORP environment variables.")
    print("Please fix and run again. Existing...")
    sys.exit(1)  # Exit if environment variables are not set
    
    # Define the Google Cloud Storage bucket name and output file name
    
    bucket_name = 'Your_GCS_Bucket'  # Replace with your GCS bucket name
    output_file_name = 'signal_sciences_logs.json'
    
    # Initialize Google Cloud Storage client
    
    storage_client = storage.Client()
    
    # Function to upload data to Google Cloud Storage
    
    def upload_to_gcs(bucket_name, data, destination_blob_name):
        bucket = storage_client.bucket(bucket_name)
        blob = bucket.blob(destination_blob_name)
        blob.upload_from_string(data, content_type='application/json')
        print(f"Data uploaded to {destination_blob_name} in bucket {bucket_name}")
    
    # Signal Sciences API information
    
    api_host = 'https://dashboard.signalsciences.net'
    # email = '[email protected]'  # Signal Sciences account email
    # token = 'XXXXXXXX-XXXX-XXX-XXXX-XXXXXXXXXXXX'  # API token for authentication
    # corp_name = 'Domain'  # Corporation name in Signal Sciences
    # site_names = ['testenv']  # Replace with your actual site names
    
    # List of comma-delimited sites that you want to extract data from
    
    site_names = [ 'site123', 'site345' ]        # Define all sites to pull logs from
    
    email = os.environ.get('SIGSCI_EMAIL')       # Signal Sciences account email
    token = os.environ.get('SIGSCI_TOKEN')       # API token for authentication
    corp_name = os.environ.get('SIGSCI_CORP')    # Corporation name in Signal Sciences
    
    # Calculate the start and end timestamps for the previous hour in UTC
    
    until_time = datetime.utcnow().replace(minute=0, second=0, microsecond=0)
    from_time = until_time - timedelta(hours=1)
    until_time = calendar.timegm(until_time.utctimetuple())
    from_time = calendar.timegm(from_time.utctimetuple())
    
    # Prepare HTTP headers for the API request
    
    headers = {
        'Content-Type': 'application/json',
        'x-api-user': email,
        'x-api-token': token
    }
    
    # Collect logs for each site
    
    collected_logs = []
    
    for site_name in site_names:
        url = f"{api_host}/api/v0/corps/{corp_name}/sites/{site_name}/feed/requests?from={from_time}&until={until_time}"
        while True:
            response = requests.get(url, headers=headers)
            if response.status_code != 200:
                print(f"Error fetching logs: {response.text}", file=sys.stderr)
                break
    
            # Parse the JSON response
    
            data = response.json()
            collected_logs.extend(data['data'])  # Add the log messages to our list
    
            # Pagination: check if there is a next page
    
            next_url = data.get('next', {}).get('uri')
            if not next_url:
                break
            url = api_host + next_url
    
    # Convert the collected logs to a newline-delimited JSON string
    
    json_data = '\n'.join(json.dumps(log) for log in collected_logs)
    
    # Save the newline-delimited JSON data to a GCS bucket
    
    upload_to_gcs(bucket_name, json_data, output_file_name)
    

    フィードを設定する

Google SecOps プラットフォームでフィードを設定するには、次の 2 つのエントリ ポイントがあります。

  • [SIEM 設定] > [フィード]
  • [コンテンツ ハブ] > [コンテンツ パック]

[SIEM 設定] > [フィード] でフィードを設定する

フィードを構成する手順は次のとおりです。

  1. [SIEM Settings] > [Feeds] に移動します。
  2. [Add New Feed] をクリックします。
  3. 次のページで [単一フィードを設定] をクリックします。
  4. [フィード名] フィールドに、フィードの名前を入力します(例: Signal Sciences WAF Logs)。
  5. [Source type] として [Google Cloud Storage] を選択します。
  6. [Log type] として [Signal Sciences WAF] を選択します。
  7. [Chronicle サービス アカウント] として [サービス アカウントを取得する] をクリックします。
  8. [次へ] をクリックします。
  9. 次の入力パラメータの値を指定します。

    • Storage Bucket URI: Google Cloud gs://my-bucket/<value> 形式のストレージ バケット URL。
    • URI Is A: [サブディレクトリを含むディレクトリ] を選択します。
    • Source deletion options: 必要に応じて削除オプションを選択します。

  10. [次へ] をクリックします。

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

Content Hub からフィードを設定する

次のフィールドに値を指定します。

  • Storage Bucket URI: Google Cloud gs://my-bucket/<value> 形式のストレージ バケット URL。
  • URI Is A: [サブディレクトリを含むディレクトリ] を選択します。
  • Source deletion options: 必要に応じて削除オプションを選択します。

詳細オプション

  • フィード名: フィードを識別する事前入力された値。
  • ソースタイプ: Google SecOps にログを収集するために使用される方法。
  • アセットの名前空間: フィードに関連付けられた名前空間。
  • Ingestion Labels: このフィードのすべてのイベントに適用されるラベル。

UDM マッピング テーブル

ログフィールド UDM マッピング ロジック
CLIENT-IP target.ip CLIENT-IP ヘッダー フィールドから抽出されます。
CLIENT-IP target.port CLIENT-IP ヘッダー フィールドから抽出されます。
接続 security_result.about.labels この値は、未加工ログの Connection フィールドから取得され、security_result.about.labels にマッピングされます。
Content-Length security_result.about.labels この値は、未加工ログの Content-Length フィールドから取得され、security_result.about.labels にマッピングされます。
Content-Type security_result.about.labels この値は、未加工ログの Content-Type フィールドから取得され、security_result.about.labels にマッピングされます。
created metadata.event_timestamp この値は、未加工ログの created フィールドから取得され、metadata.event_timestamp にマッピングされます。
details.headersIn security_result.about.resource.attribute.labels この値は、未加工ログの details.headersIn フィールドから取得され、security_result.about.resource.attribute.labels にマッピングされます。
details.headersOut security_result.about.resource.attribute.labels この値は、未加工ログの details.headersOut フィールドから取得され、security_result.about.resource.attribute.labels にマッピングされます。
details.id principal.process.pid この値は、未加工ログの details.id フィールドから取得され、principal.process.pid にマッピングされます。
details.method network.http.method この値は、未加工ログの details.method フィールドから取得され、network.http.method にマッピングされます。
details.protocol network.application_protocol この値は、未加工ログの details.protocol フィールドから取得され、network.application_protocol にマッピングされます。
details.remoteCountryCode principal.location.country_or_region この値は、未加工ログの details.remoteCountryCode フィールドから取得され、principal.location.country_or_region にマッピングされます。
details.remoteHostname target.hostname この値は、未加工ログの details.remoteHostname フィールドから取得され、target.hostname にマッピングされます。
details.remoteIP target.ip この値は、未加工ログの details.remoteIP フィールドから取得され、target.ip にマッピングされます。
details.responseCode network.http.response_code この値は、未加工ログの details.responseCode フィールドから取得され、network.http.response_code にマッピングされます。
details.responseSize network.received_bytes この値は、未加工ログの details.responseSize フィールドから取得され、network.received_bytes にマッピングされます。
details.serverHostname principal.hostname この値は、未加工ログの details.serverHostname フィールドから取得され、principal.hostname にマッピングされます。
details.serverName principal.asset.network_domain この値は、未加工ログの details.serverName フィールドから取得され、principal.asset.network_domain にマッピングされます。
details.tags security_result.detection_fields この値は、未加工ログの details.tags フィールドから取得され、security_result.detection_fields にマッピングされます。
details.tlsCipher network.tls.cipher この値は、未加工ログの details.tlsCipher フィールドから取得され、network.tls.cipher にマッピングされます。
details.tlsProtocol network.tls.version この値は、未加工ログの details.tlsProtocol フィールドから取得され、network.tls.version にマッピングされます。
details.userAgent network.http.user_agent この値は、未加工ログの details.userAgent フィールドから取得され、network.http.user_agent にマッピングされます。
details.uri network.http.referral_url この値は、未加工ログの details.uri フィールドから取得され、network.http.referral_url にマッピングされます。
eventType metadata.product_event_type この値は、未加工ログの eventType フィールドから取得され、metadata.product_event_type にマッピングされます。
headersIn security_result.about.labels この値は、未加工ログの headersIn フィールドから取得され、security_result.about.labels にマッピングされます。
headersOut security_result.about.labels この値は、未加工ログの headersOut フィールドから取得され、security_result.about.labels にマッピングされます。
id principal.process.pid この値は、未加工ログの id フィールドから取得され、principal.process.pid にマッピングされます。
メッセージ metadata.description この値は、未加工ログの message フィールドから取得され、metadata.description にマッピングされます。
method network.http.method この値は、未加工ログの method フィールドから取得され、network.http.method にマッピングされます。
ModuleVersion metadata.ingestion_labels この値は、未加工ログの ModuleVersion フィールドから取得され、metadata.ingestion_labels にマッピングされます。
msgData.actions security_result.action この値は、未加工ログの msgData.actions フィールドから取得され、security_result.action にマッピングされます。
msgData.changes target.resource.attribute.labels この値は、未加工ログの msgData.changes フィールドから取得され、target.resource.attribute.labels にマッピングされます。
msgData.conditions security_result.description この値は、未加工ログの msgData.conditions フィールドから取得され、security_result.description にマッピングされます。
msgData.detailLink network.http.referral_url この値は、未加工ログの msgData.detailLink フィールドから取得され、network.http.referral_url にマッピングされます。
msgData.name target.resource.name この値は、未加工ログの msgData.name フィールドから取得され、target.resource.name にマッピングされます。
msgData.reason security_result.summary この値は、未加工ログの msgData.reason フィールドから取得され、security_result.summary にマッピングされます。
msgData.sites network.http.user_agent この値は、未加工ログの msgData.sites フィールドから取得され、network.http.user_agent にマッピングされます。
プロトコル network.application_protocol この値は、未加工ログの protocol フィールドから取得され、network.application_protocol にマッピングされます。
remoteCountryCode principal.location.country_or_region この値は、未加工ログの remoteCountryCode フィールドから取得され、principal.location.country_or_region にマッピングされます。
remoteHostname target.hostname この値は、未加工ログの remoteHostname フィールドから取得され、target.hostname にマッピングされます。
remoteIP target.ip この値は、未加工ログの remoteIP フィールドから取得され、target.ip にマッピングされます。
responseCode network.http.response_code この値は、未加工ログの responseCode フィールドから取得され、network.http.response_code にマッピングされます。
responseSize network.received_bytes この値は、未加工ログの responseSize フィールドから取得され、network.received_bytes にマッピングされます。
serverHostname principal.hostname この値は、未加工ログの serverHostname フィールドから取得され、principal.hostname にマッピングされます。
serverName principal.asset.network_domain この値は、未加工ログの serverName フィールドから取得され、principal.asset.network_domain にマッピングされます。
tags security_result.detection_fields この値は、未加工ログの tags フィールドから取得され、security_result.detection_fields にマッピングされます。
timestamp metadata.event_timestamp この値は、未加工ログの timestamp フィールドから取得され、metadata.event_timestamp にマッピングされます。
tlsCipher network.tls.cipher この値は、未加工ログの tlsCipher フィールドから取得され、network.tls.cipher にマッピングされます。
tlsProtocol network.tls.version この値は、未加工ログの tlsProtocol フィールドから取得され、network.tls.version にマッピングされます。
URI target.url この値は、未加工ログの URI フィールドから取得され、target.url にマッピングされます。
userAgent network.http.user_agent この値は、未加工ログの userAgent フィールドから取得され、network.http.user_agent にマッピングされます。
uri network.http.referral_url この値は、未加工ログの uri フィールドから取得され、network.http.referral_url にマッピングされます。
X-ARR-SSL network.tls.client.certificate.issuer 値は、grok フィルタと kv フィルタを使用して X-ARR-SSL ヘッダー フィールドから抽出されます。
metadata.event_type イベントタイプは、ターゲット情報とプリンシパル情報の有無に基づいてパーサーによって決定されます。ターゲットとプリンシパルの両方が存在する場合、イベントタイプは NETWORK_HTTP です。プリンシパルのみ存在する場合、イベントタイプは STATUS_UPDATE です。それ以外の場合、イベントタイプは GENERIC_EVENT です。
metadata.log_type この値は SIGNAL_SCIENCES_WAF にハードコードされています。
metadata.product_name この値は Signal Sciences WAF にハードコードされています。
metadata.vendor_name この値は Signal Sciences にハードコードされています。
principal.asset.hostname 値は principal.hostname フィールドから取得されます。
target.asset.hostname 値は target.hostname フィールドから取得されます。
target.asset.ip 値は target.ip フィールドから取得されます。
target.user.user_display_name 値は、grok フィルタを使用して message_data フィールドから抽出されます。
target.user.userid 値は、grok フィルタを使用して message_data フィールドから抽出されます。

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