本文へ移動

2026-06-01 時点の資料です。読みやすさのために、一部の文字の色を濃くしています。

Scanning · Triggered by storage

ウイルス検査の連携Scanning

社外の取引先がファイルをアップロードする以上、ウイルス混入のリスクは避けられません。松葉は、アップロードされたファイルを、検査が終わるまで利用者の目に触れさせない仕組みを実装しました。鍵になるのは、ストレージへのファイル到着を「合図」にして検査サービスを自動起動する連携(Eventarc。イベント連携の仕組み)と、検査結果に応じた保管場所(バケット)の振り分けです。

実装済み: 連携と振り分けの仕組み(入出力は本番と同形) 今後: 検査エンジン(ClamAV)を接続
01

到着を合図に、検査して振り分けるArrive, scan, sort

利用者がアップロードしたファイルは、まず「未検査」の保管場所に入ります。その到着を Eventarc が検知して検査サービスを起こし、検査結果に応じて「検査済み」か「隔離」へ移します。検査が済むまで、ファイルは利用者からは見えません。

実線 = 実装済み・本番疎通済み 破線 = まだ接続していない(検査エンジン・Drive 同期)
図 01 · アップロード → 検知 → 検査 → 振り分け → 通知
アップロード利用者 → 直接保存未検査バケットアップロード直後の置き場利用者からは見えないEventarc到着を検知object.finalizedmatsuba-scanner(検査サービス)① 送信元を検証(OIDC。正規の連携元か)② 検査(検査エンジン ClamAV は今後接続)③ 結果に応じて保管場所を移す(GCS)④ DB を更新(検査状態・保管先)⑤ 結果イベントを発行(publish)起動(Push)検査済みバケット + file.scan_clean問題なし → 利用可能に。Drive 同期へ(Drive 同期は今後実装)隔離バケット + file.scan_infected感染 → 隔離。管理者へ通知問題なし感染検査が済むまで、ファイルは「未検査」バケットに留まり、利用者からは見えません。検査結果イベントは、発信箱(Outbox)を経由せず、検査サービスが直接発行します(理由は本ページ下段)。

状態の見える化: ファイルは「検査待ち」「検査中」「検査済み(問題なし)」「感染」といった状態を持ち、検査済みになって初めて利用者に提供されます。検査サービスは、検査が終わると保管場所を移し(未検査 → 検査済み、または隔離)、データベースの状態を更新し、結果をイベントとして知らせます。

このアプリでの例取引先がアップロードしたファイルは、検査が終わるまで「検査済み」の場所に現れないため、利用者がダウンロードすることはできません。問題がなければ「検査済み」に移って利用可能になり、感染が見つかれば「隔離」に移されて、業務の経路からは取り出せなくなります。
02

役割で分けた 5 つの保管場所Five buckets

ストレージ(Cloud Storage)のバケット(保管場所)を、役割ごとに 5 つに物理的に分けています。検査前・検査済み・隔離を別々の場所に分けることで、「うっかり感染ファイルを取り出す経路」をそもそも作りません。

保管場所(バケット)役割
未検査バケットアップロード直後の未検査ファイル(利用者には見えない)
検査済みバケット検査済みで問題なし。利用者がダウンロードできる
隔離バケット感染を検出して隔離。専用権限でしか取り出せない
ミラーバケット(ウイルス定義)検査エンジンのウイルス定義ファイルの保管(今後使用)
共有 ZIP バケット共有リンク用にまとめた ZIP の一時置き場

なぜ場所を分けるのか: 「未検査・検査済み・隔離」を 1 つの場所で状態フラグだけで区別すると、フラグの付け間違い 1 つで感染ファイルが利用可能になりかねません。物理的に別の場所に分け、業務 API には隔離バケットへのアクセス権限を一切与えないことで、設計の段階で危険な経路を断っています。最小権限(必要な権限だけを与える)の考え方を、検査の連携でも徹底しています。

03

取りこぼさない検査結果の発行Direct & idempotent

検査結果のイベントは、他の業務処理が使う発信箱(Outbox)を経由せず、検査サービスが直接発行します。これは手抜きではなく、検査の連携が持つ性質に合わせた意図的な設計です。

なぜ直接発行でよいのか: 検査の処理は、Eventarc が「届くまで何度でも再配信してくれる」仕組みの上で動きます。そのため、途中で失敗しても自動で再実行されるので、発信箱に溜めて後追いで送る必要がありません。あわせて、検査結果のイベントにはファイルの版から計算した決まった IDを付けます。同じファイルが再配信で 2 回検査されても、同じ ID になるため、受け取り側が「これは処理済み」と判定して二重処理を防げます(受け取り側の仕組みは「イベント駆動の整合性」へ)。

正直な注記: 現時点の検査サービスは、検査エンジン(ClamAV)をまだ接続しておらず、常に「問題なし」と判定する仮の検査で動いています。ただし、その前後(到着の検知・保管場所の振り分け・DB 更新・結果の発行)は本番と同じ作りです。今後の開発では、この仮の検査を実際の検査エンジンに差し替えて本稼働へ進めます。図で検査エンジンを破線にしているのは、この「あとは中身を差し込むだけ」という状態を表しています。