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 バケットの作成
- Google Cloud コンソールにログインします。
[Cloud Storage バケット] のページに移動します。
[作成] をクリックします。
[バケットの作成] ページでユーザーのバケット情報を入力します。以下のステップでは、操作を完了した後に [続行] をクリックして、次のステップに進みます。
[始める] セクションで、次の操作を行います。
- バケット名の要件を満たす一意の名前を入力します(vpcflow-logs など)。
- 階層名前空間を有効にするには、展開矢印をクリックして [Optimize for file oriented and data-intensive workloads] セクションを開き、[このバケットで階層的な名前空間を有効にする] を選択します。
- バケットラベルを追加するには、展開矢印をクリックして [ラベル] セクションを開きます。
- [ラベルを追加] をクリックし、ラベルのキーと値を指定します。
[データの保存場所の選択] セクションで、次の操作を行います。
- ロケーション タイプを選択してください。
- ロケーション タイプのメニューを使用して、バケット内のオブジェクト データが永続的に保存されるロケーションを選択します。
- クロスバケット レプリケーションを設定するには、[クロスバケット レプリケーションを設定する] セクションを開きます。
[データのストレージ クラスを選択する] セクションで、バケットのデフォルトのストレージ クラスを選択します。あるいは、Autoclass を選択して、バケットデータのストレージ クラスを自動的に管理します。
[オブジェクトへのアクセスを制御する方法を選択する] セクションで、[なし] を選択して公開アクセスの防止を適用し、バケットのオブジェクトの [アクセス制御モデル] を選択します。
[オブジェクト データを保護する方法を選択する] セクションで、次の操作を行います。
- [データ保護] で、バケットに設定するオプションを選択します。
- オブジェクト データの暗号化方法を選択するには、[データ暗号化] というラベルの付いた展開矢印をクリックし、データの暗号化方法を選択します。
[作成] をクリックします。
Signal Sciences WAF API キーを構成する
- Signal Sciences WAF ウェブ UI にログインします。
- [マイ プロフィール] > [API アクセス トークン] に移動します。
- [API アクセス トークンを追加] をクリックします。
- 一意のわかりやすい名前を指定します(例:
Google SecOps
)。 - [Create API access token] をクリックします。
- トークンをコピーして安全な場所に保存します。
- [I understand] をクリックして、トークンの作成を完了します。
Linux ホストにスクリプトをデプロイして、Signal Sciences からログを取得し、 Google Cloudに保存します。
- SSH を使用して Linux ホストにログインします。
Python ライブラリをインストールして、Signal Sciences WAF JSON を Cloud Storage バケットに保存します。
pip install google-cloud-storage
この環境変数を設定して、 Google Cloudの認証情報を含む JSON ファイルを呼び出します。
export GOOGLE_APPLICATION_CREDENTIALS="path/to/your/service-account-key.json"
この情報はハードコードできないため、次の環境変数を構成します。
export SIGSCI_EMAIL=<Signal_Sciences_account_email> export SIGSCI_TOKEN=<Signal_Sciences_API_token> export SIGSCI_CORP=<Corporation_name_in_Signal_Sciences>
次のスクリプトを実行します。
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 設定] > [フィード] でフィードを設定する
フィードを構成する手順は次のとおりです。
- [SIEM Settings] > [Feeds] に移動します。
- [Add New Feed] をクリックします。
- 次のページで [単一フィードを設定] をクリックします。
- [フィード名] フィールドに、フィードの名前を入力します(例:
Signal Sciences WAF Logs
)。 - [Source type] として [Google Cloud Storage] を選択します。
- [Log type] として [Signal Sciences WAF] を選択します。
- [Chronicle サービス アカウント] として [サービス アカウントを取得する] をクリックします。
- [次へ] をクリックします。
次の入力パラメータの値を指定します。
- Storage Bucket URI: Google Cloud
gs://my-bucket/<value>
形式のストレージ バケット URL。 - URI Is A: [サブディレクトリを含むディレクトリ] を選択します。
Source deletion options: 必要に応じて削除オプションを選択します。
- Storage Bucket URI: Google Cloud
[次へ] をクリックします。
[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 のプロフェッショナルから回答を得ることができます。