Cloud Storage にアップロードされたドキュメントのマルウェア スキャンを自動化する

Last reviewed 2021-10-10 UTC

このチュートリアルでは、悪意のあるコードのドキュメントの評価を自動化するためのイベント ドリブン パイプラインを構築する方法について説明します。

Cloud Storage にアップロードされた多数のドキュメントを手動で評価することは、ほとんどのアプリにとって時間がかかりすぎます。

このパイプラインは、Google Cloud プロダクトと、ClamAV というオープンソースのウィルス対策エンジンを使用して構築されています。このチュートリアルでは、ClamAV は Cloud Run でホストされている Docker コンテナで実行されます。 パイプラインは、Cloud Logging にログエントリを書き込み、Cloud Monitoring に指標を記録します。

これらの Logging ログエントリを使用して、感染したドキュメントのログベースのアラートをトリガーできますが、このようなアラートの設定はこのチュートリアルの対象外です。

このチュートリアルでは、「マルウェア」という用語を、トロイの木馬、ウイルス、その他の悪意のあるコードを指す包括的な用語として使用します。

このチュートリアルでは、Cloud StorageCloud RunEventarcDockerNode.js の基本的な機能について理解していることを前提としています。

アーキテクチャ

次の図は、パイプラインのステップの概要を示しています。

マルウェア スキャン パイプラインのアーキテクチャ。

次のステップは、アーキテクチャ パイプラインの概要を示しています。

  • ファイルを Cloud Storage にアップロードします。
  • アップロード イベントにより、自動的にマルウェア スキャン サービスがトリガーされます。
  • マルウェア スキャン サービスが、アップロードされたドキュメントのマルウェアをスキャンします。
  • ドキュメントが感染している場合は、隔離されたバケットに移動されます。それ以外の場合は、感染していないスキャン済みドキュメントを保持する別のバケットにドキュメントが移動されます。

目標

  • ClamAV を使用してドキュメントのマルウェアをスキャンする Cloud Run マルウェア スキャン サービスを構築し、スキャン結果に基づいてスキャンされたドキュメントをクリーンなバケットまたは隔離されたバケットに移動します。

  • ドキュメントが Cloud Storage にアップロードされたときにマルウェア スキャン サービスをトリガーする Eventarc トリガーを作成します。

費用

このドキュメントでは、Google Cloud の次の課金対象のコンポーネントを使用します。

料金計算ツールを使うと、予想使用量に基づいて費用の見積もりを生成できます。 新しい Google Cloud ユーザーは無料トライアルをご利用いただける場合があります。

このドキュメントに記載されているタスクの完了後、作成したリソースを削除すると、それ以上の請求は発生しません。詳細については、クリーンアップをご覧ください。

始める前に

  1. Sign in to your Google Cloud account. If you're new to Google Cloud, create an account to evaluate how our products perform in real-world scenarios. New customers also get $300 in free credits to run, test, and deploy workloads.
  2. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  3. Make sure that billing is enabled for your Google Cloud project.

  4. Enable the Artifact Registry, Cloud Run, Eventarc, Logging, and Cloud Build APIs.

    Enable the APIs

  5. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  6. Make sure that billing is enabled for your Google Cloud project.

  7. Enable the Artifact Registry, Cloud Run, Eventarc, Logging, and Cloud Build APIs.

    Enable the APIs

  8. In the Google Cloud console, activate Cloud Shell.

    Activate Cloud Shell

    At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.

  9. このチュートリアルでは、すべてのコマンドを Cloud Shell で実行します。

環境設定

このセクションでは、チュートリアル全体で使用される値(リージョンやゾーンなど)の設定を行います。このチュートリアルでは、Cloud Run サービスのリージョンとして us-central1 を使用し、Eventarc トリガーと Cloud Storage バケットのロケーションとして us を使用します。

  1. Cloud Shell で、リージョンとロケーションを設定します。

    export REGION=us-central1
    export LOCATION=us
    
  2. プロジェクト ID で gcloud 環境を初期化し、環境変数を設定します。

    export PROJECT_ID=PROJECT_ID
    gcloud config set project "${PROJECT_ID}"
    

    プロジェクト ID に PROJECT_ID を設定します。

  3. 一意の名前で 3 つの Cloud Storage バケットを作成します。

    gsutil mb -l "${LOCATION}" "gs://unscanned-${PROJECT_ID}"
    gsutil mb -l "${LOCATION}" "gs://quarantined-${PROJECT_ID}"
    gsutil mb -l "${LOCATION}" "gs://clean-${PROJECT_ID}"
    

    ${PROJECT_ID} は、バケット名が一意となるようにするために使用されます。

作成した 3 つのバケットは、パイプラインのさまざまな段階でドキュメントを保持します。

  • unscanned-PROJECT_ID: 処理前のドキュメントを保持します。これは、ドキュメントのアップロード先となるバケットです。

  • quarantined-PROJECT_ID: マルウェア スキャン サービスでスキャンされ、マルウェアが含まれていると判断されたドキュメントが保持されます。

  • clean-PROJECT_ID: マルウェア スキャン サービスでスキャンされ、感染していないと判断されたドキュメントが保存されます。

マルウェア スキャン サービスのサービス アカウントの作成と権限の付与

このセクションでは、マルウェア スキャン サービスに使用するサービス アカウントを作成し、サービス アカウントに適切なロールを付与して、Cloud Storage バケットに対する読み取りと書き込みの権限を付与します。これは、アカウントに最小限の権限が付与され、必要なリソースにのみアクセスできるようにすることを目的としています。

  1. malware-scanner サービス アカウントを作成します。

    gcloud iam service-accounts create malware-scanner
    export SERVICE_ACCOUNT="malware-scanner@${PROJECT_ID}.iam.gserviceaccount.com"
    
  2. バケットにオブジェクト管理者ロールを付与して、サービスでスキャンされていないバケットからのドキュメントの読み取り、削除、検疫されたバケットとクリーンなバケットへのドキュメントの書き込ができるようにします。

    gsutil iam ch \
        "serviceAccount:${SERVICE_ACCOUNT}:objectAdmin" \
        "gs://unscanned-${PROJECT_ID}"
    gsutil iam ch \
        "serviceAccount:${SERVICE_ACCOUNT}:objectAdmin" \
        "gs://clean-${PROJECT_ID}"
    gsutil iam ch \
        "serviceAccount:${SERVICE_ACCOUNT}:objectAdmin" \
        "gs://quarantined-${PROJECT_ID}"
    
  3. サービスが Monitoring に指標を書き込むことができるように、指標の書き込みロールを付与します。

    gcloud projects add-iam-policy-binding \
          "${PROJECT_ID}" \
          --member="serviceAccount:${SERVICE_ACCOUNT}" \
          --role=roles/monitoring.metricWriter
    

Cloud Run にマルウェア スキャン サービスを作成する

このセクションでは、マルウェア スキャン サービスを Cloud Run にデプロイします。このサービスは Docker コンテナで実行され、次のものが含まれます。

  • マルウェア スキャン サービス用の Node.js ファイル。
  • サービスと ClamAV バイナリを含むイメージを構築する Dockerfile。
  • コンテナの起動時に ClamAV と freshclam デーモンを実行する bootstrap.sh シェル スクリプト。
  1. Cloud Shell で、コードファイルを含む GitHub リポジトリのクローンを作成します。

    git clone https://github.com/GoogleCloudPlatform/docker-clamav-malware-scanner.git
    
  2. cloudrun-malware-scanner ディレクトリに移動します。

    cd docker-clamav-malware-scanner/cloudrun-malware-scanner
    
  3. 前の手順で作成したサービス アカウントを使用して Cloud Run サービスを作成し、デプロイします。

    export SERVICE_NAME=malware-scanner
    gcloud beta run deploy "${SERVICE_NAME}" \
      --source . \
      --region "${REGION}" \
      --no-allow-unauthenticated \
      --memory 4Gi \
      --min-instances 1 \
      --no-cpu-throttling \
      --service-account="${SERVICE_ACCOUNT}" \
      --set-env-vars \
        "UNSCANNED_BUCKET=unscanned-${PROJECT_ID},
        CLEAN_BUCKET=clean-${PROJECT_ID},
        QUARANTINED_BUCKET=quarantined-${PROJECT_ID}"
    
  4. プロンプトが表示されたら、「Y」と入力します。

デプロイが完了すると、次のメッセージが表示されます。

Service [malware-scanner] revision [malware-scanner-NNNNN-XXX] has been deployed and is serving 100 percent of traffic.
Service URL: https://malware-scanner-XXXXXXXX-XX.a.run.app

Cloud Run サービスでは、すべての呼び出しの認証を行う必要があり、認証 ID がサービスに対する run.routes.invoke 権限を持っている必要があります。

実行中のサービスと ClamAV のバージョンを確認するには、次のコマンドを実行します。

curl -D - -H "Authorization: Bearer $(gcloud auth print-identity-token)"  \
     SERVICE_URL

SERVICE_URL は、以前確認したデプロイ出力で報告された URL です。

Eventarc Cloud Storage トリガーを作成する

このセクションでは、Eventarc が Cloud Storage イベントをキャプチャするための権限と、これらのイベントを Cloud Run malware-scanner サービスに送信するためのトリガーを追加します。

  1. 2021 年 4 月 8 日より前に作成された既存のプロジェクトを使用している場合は、Pub/Sub をプッシュ通知用に構成します。

  2. Cloud Shell で、Cloud Storage サービス アカウントに roles/pubsub.publisher ロールを付与します。

    STORAGE_SERVICE_ACCOUNT=$(gsutil kms serviceaccount -p "${PROJECT_ID}")
    
    gcloud projects add-iam-policy-binding "${PROJECT_ID}" \
      --member "serviceAccount:${STORAGE_SERVICE_ACCOUNT}" \
      --role "roles/pubsub.publisher"
    
  3. malware-scanner サービス アカウントで Cloud Run サービスを呼び出し、Eventarc イベント レシーバーとして機能できるようにします。

    gcloud run services add-iam-policy-binding malware-scanner \
      --region="${REGION}" \
      --member "serviceAccount:${SERVICE_ACCOUNT}" \
      --role roles/run.invoker
    gcloud projects add-iam-policy-binding "${PROJECT_ID}"
      --member "serviceAccount:${SERVICE_ACCOUNT}"
      --role "roles/eventarc.eventReceiver"
    
  4. スキャンされていない Cloud Storage バケット内のファイナライズされたオブジェクト イベントをキャプチャして、Cloud Run サービスに送信する Eventarc トリガーを作成します。トリガーでは、認証に malware-scanner サービス アカウントが使用されます。

    gcloud eventarc triggers create trigger-gcs-malware-scanner \
      --destination-run-service="${SERVICE_NAME}" \
      --destination-run-region="${REGION}" \
      --location="${LOCATION}" \
      --event-filters="type=google.cloud.storage.object.v1.finalized" \
      --event-filters="bucket=unscanned-${PROJECT_ID}" \
      --service-account="${SERVICE_ACCOUNT}"
    

    次のエラーが表示された場合は、1 分ほど待ってからコマンドを再実行してください。

    ERROR: (gcloud.eventarc.triggers.create) INVALID_ARGUMENT: The request was invalid: Bucket "unscanned-PROJECT_ID" was not found. Please verify that the bucket exists.

ファイルをアップロードしてパイプラインをテストする

クリーンな(マルウェアのない)ファイルと感染したファイルを 1 つずつアップロードして、パイプラインをテストします。

  1. サンプル テキスト ファイルを作成するか、既存のクリーンなファイルを使用して、パイプライン プロセスをテストします。

  2. サンプル データファイルをスキャンされていないファイル バケットにコピーします。

    gsutil cp filename "gs://unscanned-${PROJECT_ID}"
    

    filename を、クリーンなテキスト ファイルの名前に置き換えます。マルウェア スキャン サービスは、各ドキュメントを検査し、適切なバケットに移動します。このドキュメントは clean-PROJECT_ID バケットに移動されます。

  3. パイプラインでドキュメントの処理に数秒かかります。その後 clean-PROJECT_ID バケットをチェックして、処理されたドキュメントがあるかどうかを確認します。

    gsutil ls -r "gs://clean-${PROJECT_ID}"
    
  4. スキャンされていないバケットからドキュメントが削除されました。

    gsutil ls -r "gs://unscanned-${PROJECT_ID}"
    
  5. EICAR 標準のマルウェア対策テスト署名を含むeicar-infected.txtというファイルをunscanned-PROJECT_IDバケットにアップロードします。

    echo -e 'X5O!P%@AP[4\PZX54(P^)7CC)7}$EICAR-STANDARD-ANTIVIRUS-TEST-FILE!$H+H*' \
        | gsutil cp - "gs://unscanned-${PROJECT_ID}/eicar-infected.txt"
    
  6. 数秒待ってから、quarantined-PROJECT_ID バケットをチェックし、ドキュメントがパイプラインを正常に通過したかどうかを確認します。また、マルウェアに感染したドキュメントが検出されると、Logging のログエントリが記録されます。

    gsutil ls -r "gs://quarantined-${PROJECT_ID}"
    
  7. スキャンされていないバケットからドキュメントが削除されました。

    gsutil ls -r "gs://unscanned-${PROJECT_ID}"
    

サービスのモニタリング

サービスは、Cloud Logging と Cloud Monitoring を使用してモニタリングできます。

ログの表示

  1. Google Cloud コンソールで、Cloud Logging ログ エクスプローラ ページに移動します。

    [ログ エクスプローラ] に移動

  2. [ログのフィールド] フィルタが表示されない場合は、[ログのフィールド] ボタンをクリックします。

  3. [ログのフィールド] フィルタで、[Cloud Run のリビジョン] をクリックします。

  4. [ログフィールド] フィルタの [サービス名] セクションで、[マルウェア スキャン] をクリックします。

ログクエリの結果には、サービスからのログが表示されます。このログには、アップロードした 2 つのファイルに対するスキャン リクエストとステータスを示すいくつかの行が含まれています。次に例を示します。

Info: "Scan request for gs://unscanned-PROJECT_ID/filename, (##### bytes) scanning with clam ClamAV 0.103.3/26347/Mon Nov 8 09:19:39 2021"
Info: "Scan status for gs://unscanned-PROJECT_ID/filename: CLEAN (##### bytes in #### ms)"
...
Info: "Scan request for gs://unscanned-PROJECT_ID/eicar-infected.txt, (69 bytes) scanning with clam ClamAV 0.103.3/26347/Mon Nov 8 09:19:39 2021"
Warning: "Scan status for gs://unscanned-PROJECT_ID/eicar-infected.txt: INFECTED stream: Eicar-Signature FOUND (69 bytes in ### ms)"

ClamAV のバージョンとウイルス署名のリビジョンが、感染したテストファイルのウイルス名とともに報告されています。

これらのログメッセージを使用して、ウイルスが検出された時点またはスキャン中に障害が発生したときのアラートを設定できます。

指標の表示

このサービスでは、モニタリングとアラートの目的で次の指標が生成されます。

  • 処理された感染していないファイルの数:
    custom.googleapis.com/opencensus/malware-scanning/clean_files
  • 処理された感染ファイルの数:
    custom.googleapis.com/opencensus/malwares-canning/infected_files
  • ファイルのスキャンに費やした時間:
    custom.googleapis.com/opencensus/malware-scanning/scan_duration
  • スキャンされた総バイト数:
    custom.googleapis.com/opencensus/malware-scanning/bytes_scanned
  • 失敗したマルウェア スキャンの数:
    custom.googleapis.com/opencensus/malwares-canning/scans_failed

これらの指標は、Cloud Monitoring の Metrics Explorer で表示できます。

  1. Google Cloud コンソール で、Cloud Monitoring の [Metrics Explorer] ページに移動します。

    Metrics Explorer に移動

  2. [指標] フィールドをクリックして、フィルタ文字列 malware を入力します。

  3. [OpenCensus/malware-scanning/clean_files] 指標を選択します。グラフには、感染していないファイルがスキャンされた時を示すデータポイントが表示されます。

指標を使用してパイプラインをモニタリングし、ウイルスが検出された時点、またはファイルの処理に失敗した場合のアラートを作成できます。

その他の詳細を表示するために、さまざまな指標ラベルで指標を分類できます。

  • 転送元バケット
  • 転送先バケット
  • clam_version
  • cloud_run_revision

複数のバケットの処理

マルウェア スキャン サービスは複数のソースバケットからファイルをスキャンし、クリーンなバケットと隔離されたバケットに分けて送信できます。

この高度な構成はこのチュートリアルの範囲外ですが、以下におおまかな手順を示します。

  1. スキャンされていない、クリーンで検疫されたさまざまな Cloud Storage バケットを作成します。

  2. さまざまなバケットの malware-scanner サービス アカウントに適切なロールを付与します。

  3. 構成ファイル config.json を編集して、各構成のバケット名を指定します。

    {
      "buckets": [
        {
          "unscanned": "unscanned-bucket-1",
          "clean": "clean-bucket-1",
          "quarantined": "quarantined-bucket-1"
        },
        {
          "unscanned": "unscanned-bucket-2",
          "clean": "clean-bucket-2",
          "quarantined": "quarantined-bucket-2"
        }
      ]
    }
    
  4. malware-scanner サービスをデプロイし、3 つの XXX_BUCKET=... 変数の代わりに環境変数 CONFIG_FILE=./config.json を指定します。これにより、ファイルの構成が使用されます。

  5. スキャンされないバケットごとに Eventarc トリガーを作成し、トリガー名とバケット名を毎回変更します。

クリーンアップ

このチュートリアルで使用したリソースについて、Google Cloud アカウントに課金されないようにするには、リソースを含むプロジェクトを削除するか、プロジェクトを維持して個々のリソースを削除します。

プロジェクトの削除

  1. In the Google Cloud console, go to the Manage resources page.

    Go to Manage resources

  2. In the project list, select the project that you want to delete, and then click Delete.
  3. In the dialog, type the project ID, and then click Shut down to delete the project.

次のステップ

  • Cloud Storage のドキュメントを確認する。
  • Google Cloud に関するリファレンス アーキテクチャ、図、チュートリアル、ベスト プラクティスを確認する。Cloud Architecture Center を確認します。