ファイル スキャン フレームワークのログを収集する

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

このドキュメントでは、Google Cloud Storage V2 を使用して File Scanning Framework ログを Google Security Operations に取り込む方法について説明します。

File Scanning Framework(FSF)は、Emerson Electric Co. が開発したオープンソースのモジュール型再帰ファイル スキャン ソリューションです。FSF はクライアント サーバー アーキテクチャを使用してファイルを分析し、ファイル メタデータ、YARA シグネチャの一致、抽出されたサブオブジェクト、モジュール固有のメタデータなどの詳細な JSON スキャン結果を生成します。

始める前に

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

  • Google SecOps インスタンス
  • Cloud Storage API が有効になっている GCP プロジェクト
  • GCS バケットを作成および管理する権限
  • GCS バケットの IAM ポリシーを管理する権限
  • ログ ディレクトリへの書き込みアクセス権を持つデプロイ済みの FSF サーバー インスタンス
  • FSF サーバーホストへの root または sudo アクセス権

Google Cloud Storage バケットを作成する

  1. Google Cloud Console に移動します。
  2. プロジェクトを選択するか、新しいプロジェクトを作成します。
  3. ナビゲーション メニューで、[Cloud Storage > バケット] に移動します。
  4. [バケットを作成] をクリックします。
  5. 次の構成情報を提供してください。

    設定
    バケットに名前を付ける グローバルに一意の名前(fsf-logs-secops など)を入力します。
    ロケーション タイプ ニーズに応じて選択します(リージョン、デュアルリージョン、マルチリージョン)。
    ロケーション ロケーションを選択します(例: us-central1)。
    ストレージ クラス Standard(アクセス頻度の高いログにおすすめ)。
    アクセス制御 均一(推奨)。
    保護ツール 省略可: オブジェクトのバージョニングまたは保持ポリシーを有効にします。
  6. [作成] をクリックします。

FSF ログの出力ディレクトリを構成する

FSF は、構成可能なログ ディレクトリに JSON スキャン結果を書き込みます。Google SecOps の取り込み専用のディレクトリを構成します。

  1. SSH 経由で FSF サーバーホストに接続します。
  2. FSF サーバー構成ファイルを開きます。

    sudo nano /opt/fsf/fsf-server/conf/config.py
    
  3. SCANNER_CONFIG 辞書を見つけます。

  4. LOG_PATH パラメータを専用ディレクトリに更新します。

    SCANNER_CONFIG = {
        'LOG_PATH': '/var/log/fsf',
        'YARA_PATH': '/opt/fsf/fsf-server/yara/rules.yara',
        'PID_PATH': '/tmp/scanner.pid',
        'EXPORT_PATH': '/tmp',
        'TIMEOUT': 60,
        'MAX_DEPTH': 10
    }
    
  5. ファイルを保存して閉じます。

  6. 適切な権限でログ ディレクトリを作成します。

    sudo mkdir -p /var/log/fsf
    sudo chown -R fsf:fsf /var/log/fsf
    sudo chmod 755 /var/log/fsf
    
  7. FSF サーバーを再起動して変更を適用します。

    sudo systemctl restart fsf
    
  8. FSF が新しいディレクトリにログを書き込んでいることを確認します。

    ls -lh /var/log/fsf/
    

Fluentd をインストールして構成する

Fluentd は FSF ログファイルを追跡し、Google Cloud Storage に送信します。

Fluentd をインストールする

  1. FSF サーバーホストに Fluentd(td-agent)をインストールします。

    curl -fsSL https://toolbelt.treasuredata.com/sh/install-ubuntu-jammy-td-agent4.sh | sh
    
  2. GCS 出力プラグインをインストールします。

    sudo td-agent-gem install fluent-plugin-gcs
    
  3. プラグインのインストールを確認します。

    td-agent-gem list | grep fluent-plugin-gcs
    

Fluentd 用の GCP サービス アカウントを作成する

  1. GCP Console で、[IAM と管理>サービス アカウント] に移動します。
  2. [サービス アカウントを作成] をクリックします。
  3. 次の構成の詳細を指定します。
    • サービス アカウント名: 「fsf-fluentd-shipper」と入力します。
    • サービス アカウントの説明: 「Service account for Fluentd to ship FSF logs to GCS」と入力します。
  4. [作成して続行] をクリックします。
  5. [このサービス アカウントにプロジェクトへのアクセスを許可する] セクションで、次の操作を行います。
    1. [ロールを選択] をクリックします。
    2. [ストレージ オブジェクト管理者] を検索して選択します。
  6. [続行] をクリックします。
  7. [完了] をクリックします。

サービス アカウントキーの作成

  1. [サービス アカウント] リストで、サービス アカウント(fsf-fluentd-shipper)をクリックします。
  2. [キー] タブに移動します。
  3. [鍵を追加] > [新しい鍵を作成] の順にクリックします。
  4. キーのタイプとして [JSON] を選択します。
  5. [作成] をクリックします。
  6. JSON キーファイルがパソコンにダウンロードされます。
  7. 鍵ファイルを FSF サーバーホストに転送します。

    scp /path/to/downloaded-key.json user@fsf-server:/etc/td-agent/gcp-key.json
    
  8. 鍵ファイルに適切な権限を設定します。

    sudo chown td-agent:td-agent /etc/td-agent/gcp-key.json
    sudo chmod 600 /etc/td-agent/gcp-key.json
    

GCS バケットに対する IAM 権限を付与する

  1. [Cloud Storage] > [バケット] に移動します。
  2. バケット名(fsf-logs-secops)をクリックします。
  3. [権限] タブに移動します。
  4. [アクセス権を付与] をクリックします。
  5. 次の構成の詳細を指定します。
    • プリンシパルを追加: サービス アカウントのメールアドレス(例: fsf-fluentd-shipper@PROJECT_ID.iam.gserviceaccount.com)を入力します。
    • ロールを割り当てる: [Storage オブジェクト管理者] を選択します。
  6. [保存] をクリックします。

Fluentd を構成する

  1. FSF サーバーホストで、Fluentd 構成ファイルを作成します。

    sudo nano /etc/td-agent/td-agent.conf
    
  2. 次の構成を追加します。

    # Tail FSF JSON logs
    <source>
        @type tail
        path /var/log/fsf/*.log
        pos_file /var/log/td-agent/fsf.log.pos
        tag fsf.scan
        read_from_head true
        <parse>
            @type json
            time_key timestamp
            time_format %Y-%m-%dT%H:%M:%S.%L%z
        </parse>
    </source>
    
    # Ship to Google Cloud Storage
    <match fsf.scan>
        @type gcs
        project YOUR_GCP_PROJECT_ID
        keyfile /etc/td-agent/gcp-key.json
        bucket fsf-logs-secops
        object_key_format %{path}%{time_slice}_%{index}.%{file_extension}
        path fsf-logs/
        <buffer tag,time>
            @type file
            path /var/log/td-agent/buffer/gcs
            timekey 3600
            timekey_wait 10m
            timekey_use_utc true
            chunk_limit_size 10MB
        </buffer>
        <format>
            @type json
        </format>
        store_as json
        auto_create_bucket false
    </match>
    
  3. YOUR_GCP_PROJECT_ID は実際の GCP プロジェクト ID に置き換えます。

  4. ファイルを保存して閉じます。

  5. バッファ ディレクトリを作成します。

    sudo mkdir -p /var/log/td-agent/buffer/gcs
    sudo chown -R td-agent:td-agent /var/log/td-agent/buffer
    
  6. Fluentd を再起動して構成を適用します。

    sudo systemctl restart td-agent
    
  7. 起動時に Fluentd を起動できるようにします。

    sudo systemctl enable td-agent
    
  8. Fluentd が実行されていることを確認します。

    sudo systemctl status td-agent
    

ログ転送を確認する

  1. Fluentd ログでエラーを確認します。

    sudo tail -f /var/log/td-agent/td-agent.log
    
  2. テスト FSF スキャンをトリガーしてログを生成します。

    echo "test content" > /tmp/test.txt
    /opt/fsf/fsf-client/fsf_client.py /tmp/test.txt --suppress-report
    
  3. Fluentd がログを処理して送信するまで 1 ~ 2 分待ちます。

  4. GCP Console で、[Cloud Storage> バケット] に移動します。

  5. バケット名(fsf-logs-secops)をクリックします。

  6. fsf-logs/ 接頭辞に移動します。

  7. タイムスタンプ付きの JSON ファイルが作成されていることを確認します。

  8. ファイルをダウンロードして検査し、FSF スキャン結果が JSON 形式で含まれていることを確認します。

Google SecOps サービス アカウントを取得する

Google SecOps は、一意のサービス アカウントを使用して GCS バケットからデータを読み取ります。このサービス アカウントにバケットへのアクセス権を付与する必要があります。

サービス アカウントのメールアドレスを取得する

  1. [SIEM 設定] > [フィード] に移動します。
  2. [Add New Feed] をクリックします。
  3. [単一フィードを設定] をクリックします。
  4. [フィード名] フィールドに、フィードの名前を入力します(例: FSF File Scanning Logs)。
  5. [ソースタイプ] として [Google Cloud Storage V2] を選択します。
  6. [ログタイプ] として [ファイル スキャン フレームワーク] を選択します。
  7. [サービス アカウントを取得する] をクリックします。一意のサービス アカウント メールアドレスが表示されます(例:)。

    secops-12345678@secops-gcp-prod.iam.gserviceaccount.com
    
  8. 次のステップで使用するメールアドレスをコピーします。

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

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

    • ストレージ バケットの URL: 接頭辞パスを含む GCS バケット URI を入力します。

      gs://fsf-logs-secops/fsf-logs/
      
    • Source deletion option: 必要に応じて削除オプションを選択します。

      • なし: 転送後にファイルを削除しません(テストにおすすめ)。
      • 転送されたファイルを削除する: 転送が完了した後にファイルを削除します。
      • 転送されたファイルと空のディレクトリを削除する: 転送が完了した後にファイルと空のディレクトリを削除します。

    • ファイルの最大経過日数: 指定した日数以内に変更されたファイルを含めます(デフォルトは 180 日)。

    • アセットの名前空間: アセットの名前空間

    • Ingestion labels: このフィードのイベントに適用されるラベル。

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

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

Google SecOps サービス アカウントに IAM 権限を付与する

Google SecOps サービス アカウントには、GCS バケットに対する Storage オブジェクト閲覧者ロールが必要です。

  1. [Cloud Storage] > [バケット] に移動します。
  2. バケット名(fsf-logs-secops)をクリックします。
  3. [権限] タブに移動します。
  4. [アクセス権を付与] をクリックします。
  5. 次の構成の詳細を指定します。
    • プリンシパルを追加: Google SecOps サービス アカウントのメールアドレスを貼り付けます。
    • ロールを割り当てる: [Storage オブジェクト閲覧者] を選択します。
  6. [保存] をクリックします。

取り込みを確認する

  1. 最初の取り込みが完了するまで 10 ~ 15 分待ちます。
  2. Google SecOps で、[SIEM 設定] > [フィード] に移動します。
  3. フィードを見つけます(FSF File Scanning Logs)。
  4. [ステータス] が [アクティブ] と表示されていることを確認します。
  5. フィード名をクリックして、取り込み指標を表示します。
  6. [取り込まれたイベント] の数が増加していることを確認します。
  7. Google SecOps の [検索] に移動します。
  8. 検索クエリを実行して、FSF ログが取り込まれていることを確認します。

    metadata.log_type = "FILE_SCANNING_FRAMEWORK"
    
  9. FSF スキャン結果が検索結果に表示されることを確認します。

トラブルシューティング

GCS にログが表示されない

  • FSF が /var/log/fsf/ にログを書き込んでいることを確認します。

    ls -lh /var/log/fsf/
    tail -f /var/log/fsf/*.log
    
  • Fluentd ログでエラーを確認します。

    sudo tail -f /var/log/td-agent/td-agent.log
    
  • GCP サービス アカウント キーが有効で、正しい権限が付与されていることを確認します。

  • Fluentd 構成のバケット名が実際のバケット名と一致していることを確認します。

Fluentd の権限エラー

  • サービス アカウント(fsf-fluentd-shipper)にバケットに対するストレージ オブジェクト管理者ロールがあることを確認します。
  • Fluentd 構成の鍵パスが正しいことを確認します。
  • 鍵ファイルに適切な所有者と権限があることを確認します。

    ls -l /etc/td-agent/gcp-key.json
    

Google SecOps でログが取り込まれない

  • Google SecOps サービス アカウントにバケットに対する Storage オブジェクト閲覧者ロールがあることを確認します。
  • フィード構成のバケット URI が正しく、末尾のスラッシュが含まれていることを確認します。
  • 指定された接頭辞パスの GCS バケットにファイルが存在することを確認します。
  • [SIEM 設定] > [フィード] でフィードのステータスを確認し、エラー メッセージがないか確認します。

FSF ログが想定される形式になっていない

  • FSF が JSON 出力を書き込むように構成されていることを確認します(デフォルトの動作)。
  • Fluentd の <parse> セクションが @type json で構成されていることを確認します。
  • ログファイルを検査して、有効な JSON が含まれていることを手動で確認します。

    head -n 1 /var/log/fsf/*.log | jq .
    

UDM マッピング テーブル

ログフィールド UDM マッピング ロジック
CompressType_label、compressed_parents about.labels CompressType_label(キー「Compress Type」、メッセージに「Compress Type」が含まれている場合は Object.EXTRACT_ZIP.Object_0.Compress Type の値)と compressed_parents(キー「Compressed Parent Files」、Object.EXTRACT_ZIP.Object_0.META_VT_CACHE.vt_data.additional_info.compressed_parents から連結)からマージ
Object.EXTRACT_EMBEDDED.Object_0.META_BASIC_INFO.MD5、Object.EXTRACT_ZIP.Object_0.META_BASIC_INFO.MD5、Object.EXTRACT_SWF.META_BASIC_INFO.MD5、Object.EXTRACT_GZIP.META_BASIC_INFO.MD5、Object.EXTRACT_CAB.Object_0.META_BASIC_INFO.MD5 intermediary.file.md5 EXTRACT_EMBEDDED が存在する場合は Object.EXTRACT_EMBEDDED.Object_0.META_BASIC_INFO.MD5 の値、EXTRACT_ZIP が存在する場合は Object.EXTRACT_ZIP.Object_0.META_BASIC_INFO.MD5 の値、EXTRACT_SWF が存在する場合は Object.EXTRACT_SWF.META_BASIC_INFO.MD5 の値、EXTRACT_GZIP が存在する場合は Object.EXTRACT_GZIP.META_BASIC_INFO.MD5 の値、それ以外の場合は Object.EXTRACT_CAB.Object_0.META_BASIC_INFO.MD5
Object.EXTRACT_EMBEDDED.Object_0.Description intermediary.file.mime_type 値を直接コピー
Object.EXTRACT_EMBEDDED.Object_0.META_BASIC_INFO.SHA1、Object.EXTRACT_ZIP.Object_0.META_BASIC_INFO.SHA1、Object.EXTRACT_SWF.META_BASIC_INFO.SHA1、Object.EXTRACT_GZIP.META_BASIC_INFO.SHA1、Object.EXTRACT_CAB.Object_0.META_BASIC_INFO.SHA1 intermediary.file.sha1 EXTRACT_EMBEDDED が存在する場合は Object.EXTRACT_EMBEDDED.Object_0.META_BASIC_INFO.SHA1 の値、EXTRACT_ZIP が存在する場合は Object.EXTRACT_ZIP.Object_0.META_BASIC_INFO.SHA1 の値、EXTRACT_SWF が存在する場合は Object.EXTRACT_SWF.META_BASIC_INFO.SHA1 の値、EXTRACT_GZIP が存在する場合は Object.EXTRACT_GZIP.META_BASIC_INFO.SHA1 の値、それ以外の場合は Object.EXTRACT_CAB.Object_0.META_BASIC_INFO.SHA1 の値
Object.EXTRACT_EMBEDDED.Object_0.META_BASIC_INFO.SHA256、Object.EXTRACT_ZIP.Object_0.META_BASIC_INFO.SHA256、Object.EXTRACT_SWF.META_BASIC_INFO.SHA256、Object.EXTRACT_GZIP.META_BASIC_INFO.SHA256、Object.EXTRACT_CAB.Object_0.META_BASIC_INFO.SHA256 intermediary.file.sha256 EXTRACT_EMBEDDED が存在する場合は Object.EXTRACT_EMBEDDED.Object_0.META_BASIC_INFO.SHA256 の値、EXTRACT_ZIP が存在する場合は Object.EXTRACT_ZIP.Object_0.META_BASIC_INFO.SHA256 の値、EXTRACT_SWF が存在する場合は Object.EXTRACT_SWF.META_BASIC_INFO.SHA256 の値、EXTRACT_GZIP が存在する場合は Object.EXTRACT_GZIP.META_BASIC_INFO.SHA256 の値、それ以外の場合は Object.EXTRACT_CAB.Object_0.META_BASIC_INFO.SHA256 の値
Object.EXTRACT_EMBEDDED.Object_0.META_BASIC_INFO.Size、Object.EXTRACT_ZIP.Object_0.META_BASIC_INFO.Size、Object.EXTRACT_SWF.META_BASIC_INFO.Size、Object.EXTRACT_GZIP.META_BASIC_INFO.Size、Object.EXTRACT_CAB.Object_0.META_BASIC_INFO.Size intermediary.file.size EXTRACT_EMBEDDED が存在する場合は Object.EXTRACT_EMBEDDED.Object_0.META_BASIC_INFO.Size の値、EXTRACT_ZIP が存在する場合は Object.EXTRACT_ZIP.Object_0.META_BASIC_INFO.Size の値、EXTRACT_SWF が存在する場合は Object.EXTRACT_SWF.META_BASIC_INFO.Size の値、EXTRACT_GZIP が存在する場合は Object.EXTRACT_GZIP.META_BASIC_INFO.Size の値、EXTRACT_CAB が存在する場合は Object.EXTRACT_CAB.Object_0.META_BASIC_INFO.Size の値。末尾の「 .*」が削除され、uinteger に変換されます。
Object.EXTRACT_ZIP.Object_0.META_VT_CACHE.vt_data.scan_id intermediary.resource.id 値を直接コピー
Object.EXTRACT_ZIP.Object_0.META_VT_CACHE.vt_data.permalink intermediary.url 値を直接コピー
Object.META_EMERSON_INFO.results intermediary.user.email_addresses 結果配列の matched_email からマージされました
Summary.Observations metadata.description 配列から連結され、「, 」区切り文字が使用され、先頭のカンマが削除されました
スキャン時刻 metadata.event_timestamp yyyy-MM-dd HH:mm:ss 形式の日付フィルタを使用して変換
ソース metadata.event_type Source が空でない場合は「SCAN_FILE」、それ以外の場合は「GENERIC_EVENT」に設定します。
Object.META_VT_CACHE._id metadata.product_log_id 値を直接コピー
result.ad_data.message network.http.response_code grok パターン INT を使用して、result.ad_data.message から整数として抽出されます
ソース principal.hostname 値を直接コピー
Object.META_EMERSON_INFO.result_summary、Object.EXTRACT_ZIP.Object_0.META_VT_CACHE.vt_data.verbose_msg security_result.summary 存在する場合は Object.META_EMERSON_INFO.result_summary に設定し、存在しない場合は Object.EXTRACT_ZIP.Object_0.META_VT_CACHE.vt_data.verbose_msg に設定します。
ファイル名 target.file.full_path 値を直接コピー
Object.META_BASIC_INFO.MD5 target.file.md5 値を直接コピー
Summary.Yara target.file.mime_type Summary.Yara の最初のインデックスから抽出され、大文字に変換され、Yara が存在する場合は「FT_」が削除されます。それ以外の場合は、EXTRACT_ZIP が存在する場合は「ZIP」、EXTRACT_SWF が存在する場合は「SWF」、EXTRACT_GZIP が存在する場合は「GZIP」、EXTRACT_CAB が存在する場合は「CAB」に設定されます。
Object.META_BASIC_INFO.SHA1、Object.META_VT_CACHE.SHA1 target.file.sha1 Object.META_BASIC_INFO.SHA1 が空でない場合はその値、それ以外の場合は Object.META_VT_CACHE.SHA1
Object.META_BASIC_INFO.SHA256 target.file.sha256 値を直接コピー
Object.META_BASIC_INFO.Size target.file.size 末尾の「 .*」を削除して uinteger に変換
metadata.vendor_name 「EMERSON」に設定
metadata.product_name 「FILE SCANNING FRAMEWORK」に設定

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