
Sensitive Data Protectionを利用して、Cloud Storageバケット内のファイルから PII 情報を検出してみた
はじめに
こんにちは。
クラウド事業本部コンサルティング部の渡邉です。
クラウド移行や日々の業務の中で、Cloud Storage バケットに個人情報(PII: Personally Identifiable Information)が意図せず含まれたファイルが保存されるケースは少なくありません。
氏名・メールアドレス・電話番号はもちろん、日本ではマイナンバー(個人番号)や銀行口座番号なども規制対象となり、個人情報保護法や社内ポリシーへの対応が求められます。
Google Cloud では、Sensitive Data Protection という機密データを検出・分類・保護するためのサービスがあります。
本記事では、Sensitive Data Protection を利用して、Cloud Storage バケット内のファイルから PII 情報を検出する手順をご紹介します。
Sensitive Data Protection とは
Sensitive Data Protection(旧称: Cloud Data Loss Prevention / Cloud DLP)は、テキスト・画像・Cloud Storageなどに含まれる機密データを検出・分類・保護するためのサービスです。
主な機能としては以下の 3 つがあります。
| 機能 | 概要 |
|---|---|
| Inspection(検査) | Cloud Storage・BigQuery・Datastore の特定リソースを対象に、機密データを検出する |
| Discovery(検出) | 組織・フォルダ・プロジェクト全体を継続的に監視し、機密データを含むリソースをプロファイリングする |
| De-identification(匿名化) | 検出した機密データをマスキング・トークナイゼーション・編集などの方法で匿名化する |
本記事では Inspection 機能を使って、Cloud Storage バケット内のファイルに含まれる PII を検出してみます。
infoType とは
Sensitive Data Protection を利用する上で大事な要素として infoType があります。
infoTypeは、Sensitive Data Protectionが検出する機密情報の種類のことです。100 以上の組み込み infoType が提供されており、パターンマッチング・チェックサム検証・機械学習・コンテキスト分析などの手法で検出します。
代表的なグローバル infoType
代表的なグローバル infoType として以下のようなものがあります。
| infoType | 検出対象 |
|---|---|
PERSON_NAME |
氏名(フルネーム・部分名) |
EMAIL_ADDRESS |
メールアドレス |
PHONE_NUMBER |
電話番号 |
STREET_ADDRESS |
住所 |
CREDIT_CARD_NUMBER |
クレジットカード番号 |
日本固有の infoType
日本固有の infoType も存在しており、以下のようなものがあります。
| infoType | 検出対象 |
|---|---|
JAPAN_INDIVIDUAL_NUMBER |
マイナンバー(個人番号) |
JAPAN_BANK_ACCOUNT |
銀行口座番号 |
JAPAN_PASSPORT |
パスポート番号 |
JAPAN_DRIVERS_LICENSE_NUMBER |
運転免許証番号 |
JAPAN_CORPORATE_NUMBER |
法人番号 |
実際に試してみる
前提条件
- Google Cloud プロジェクトが作成済みであること
- 請求先アカウントがプロジェクトに紐付けられていること
gcloudCLI がインストール・認証済みであること- 操作するアカウントに以下の IAM ロールが付与されていること
| ロール | 必要な操作 |
|---|---|
roles/serviceusage.serviceUsageAdmin |
API の有効化 |
roles/storage.admin |
バケットの作成・ファイルのアップロード |
roles/dlp.admin |
インスペクションジョブの作成・実行 |
roles/bigquery.dataEditor + roles/bigquery.jobUser |
BigQuery データセットの作成・結果の書き込み |
ステップ 0. 環境変数を設定する
以降のコマンドで共通して使用する環境変数をあらかじめ設定しておきます。
export PROJECT_ID="your-project-id" # Google Cloud プロジェクト ID
export BUCKET_NAME="your-bucket-name" # Cloud Storage バケット名(グローバルで一意)
export LOCATION="asia-northeast1" # バケットを作成するリージョン
export BQ_DATASET="dlp_results" # 検出結果を保存する BigQuery データセット名
export BQ_TABLE="findings" # 検出結果を保存する BigQuery テーブル名
ステップ 1. Sensitive Data Protection API を有効化する
プロジェクトで Sensitive Data Protection API を有効化します。
gcloud services enable dlp.googleapis.com \
--project="${PROJECT_ID}"
Operation "operations/acat.p2-XXXXXXXXXXXX-60f85600-405b-428a-85f0-bd6362ee74c1" finished successfully.
ステップ 2. サンプルデータを準備して Cloud Storage にアップロードする
PII を含むファイルと含まないファイルの 2 種類を用意し、検出・非検出の両方を確認します。
sample_pii.csv には氏名、メールアドレス、電話番号、マイナンバーが含まれており、個人情報が含まれているファイルを用意します。
一方、sample_no_pii.csv には商品 ID・カテゴリ・価格・在庫数のみを含めており、個人を特定できる情報は一切含まれていません。ステップ 4 のインスペクション後に、このファイルについて findings が生成されないことを確認します。
# PII を含むサンプル CSV を作成
cat <<'EOF' > sample_pii.csv
name,email,phone,my_number
田中太郎,taro.tanaka@example.com,090-1234-5678,123456789012
鈴木花子,hanako.suzuki@example.com,080-9876-5432,234567890123
佐藤一郎,ichiro.sato@example.com,070-1111-2222,345678901234
EOF
# PII を含まないサンプル CSV を作成
cat <<'EOF' > sample_no_pii.csv
product_id,category,price,stock
P-001,電子機器,29800,150
P-002,書籍,3200,80
P-003,日用品,980,500
EOF
# バケットを作成
gcloud storage buckets create "gs://${BUCKET_NAME}" \
--project="${PROJECT_ID}" \
--location="${LOCATION}"
# 両ファイルをアップロード
gcloud storage cp sample_pii.csv sample_no_pii.csv "gs://${BUCKET_NAME}/"
Creating gs://your-bucket-name/...
Copying file://sample_pii.csv to gs://your-bucket-name/sample_pii.csv
Copying file://sample_no_pii.csv to gs://your-bucket-name/sample_no_pii.csv
Completed files 2/2 | 327.0B/327.0B
Average throughput: 11.1kiB/s

Cloud Storageにファイルがアップロードされた
バケットに sample_no_pii.csvと sample_pii.csvの 2 ファイルが正常にアップロードされていることを確認できます。
ステップ 3. 検出結果の出力先 BigQuery データセットを作成する
検出結果(findings)を BigQuery に保存するために、出力先データセットをあらかじめ作成しておきます。
bq --project_id="${PROJECT_ID}" mk \
--dataset \
--location="${LOCATION}" \
"${PROJECT_ID}:${BQ_DATASET}"
Dataset 'your-project-id:dlp_results' successfully created.

検出結果を保存するデータセットの作成
dlp_results データセットが asia-northeast1 リージョンに正常に作成されていることを確認できます。
ステップ 4. インスペクションジョブを実行する
gcloud alpha dlp datasources gcs inspect "gs://${BUCKET_NAME}/*" \
--project="${PROJECT_ID}" \
--job-id=pii-scan-job-01 \
--info-types=PERSON_NAME,EMAIL_ADDRESS,PHONE_NUMBER,JAPAN_INDIVIDUAL_NUMBER,JAPAN_BANK_ACCOUNT \
--min-likelihood=possible \
--include-quote \
--file-size-limit=104857600 \
--output-table="${PROJECT_ID}.${BQ_DATASET}.${BQ_TABLE}"
createTime: '2026-07-09T20:58:48.283625Z'
inspectDetails:
requestedOptions:
jobConfig:
actions:
- saveFindings:
outputConfig:
table:
datasetId: dlp_results
projectId: your-project-id
tableId: findings
inspectConfig:
includeQuote: true
infoTypes:
- name: PERSON_NAME
- name: EMAIL_ADDRESS
- name: PHONE_NUMBER
- name: JAPAN_INDIVIDUAL_NUMBER
- name: JAPAN_BANK_ACCOUNT
limits: {}
minLikelihood: POSSIBLE
storageConfig:
cloudStorageOptions:
bytesLimitPerFile: '104857600'
fileSet:
url: gs://your-bucket-name/*
snapshotInspectTemplate: {}
result: {}
lastModified: '2026-07-09T20:58:55.323419Z'
name: projects/your-project-id/dlpJobs/i-pii-scan-job-01
state: PENDING
type: INSPECT_JOB
主なオプションの説明は以下のとおりです。
| オプション | 説明 |
|---|---|
--info-types |
検出する infoType をカンマ区切りで指定 |
--min-likelihood |
検出の確度の閾値(possible / likely / very-likely など) |
--include-quote |
検出した実際のテキストを結果に含める |
--file-size-limit |
各ファイルからスキャンする最大バイト数(デフォルト: 1024) |
--output-table |
結果を保存する BigQuery テーブル(形式: project.dataset.table) |
ステップ 5. 検出結果を確認する
Google Cloud コンソールの [Sensitive Data Protection] > [検査] ページを開くと、ジョブの進捗状況を確認できます。状態が 完了 になっていれば、インスペクションは終了しています。

インスペクションジョブ
ジョブ名(pii-scan-job-01)をクリックすると詳細画面が表示されます。

インスペクションジョブの詳細画面
検出数は 12 件、スキャンされたバイト数は 268 B、エラーは 0 でした。infoType 別の内訳は次のとおりです。
| infoType | 件数 | 割合 |
|---|---|---|
PHONE_NUMBER |
6 | 50% |
EMAIL_ADDRESS |
3 | 25% |
PERSON_NAME |
3 | 25% |
JAPAN_INDIVIDUAL_NUMBER |
0 | 0% |
JAPAN_BANK_ACCOUNT |
0 | 0% |
結果の内訳をみると、JAPAN_INDIVIDUAL_NUMBER(マイナンバー)が 0 件でした。今回サンプルデータに含めた 12 桁の数字のマイナンバーを想定した数字(123456789012 など)は、チェックサム検証を通過しなかったため、マイナンバーとして認識されず、PHONE_NUMBER として 3 件誤検出されていました。これは「マイナンバーとして検出できなかった」だけでなく、「別の infoType として誤って分類された」ことを意味します。このような誤検出は --min-likelihood の閾値を引き上げることで調整することができますが、その分検出漏れが増えるトレードオフがあります。本番環境での利用前には、実際のデータで動作を確認し、精度とカバレッジのバランスを調整することが重要になります。
ジョブが完了すると、指定した BigQuery テーブルに findings が保存されます。コンソールの Job details ページで [結果を BigQuery で表示] をクリックすると、BigQuery Web UI から結果を確認できます。

テーブルに格納されたfindings
テーブルのプレビューには 12 件すべての finding が表示されています。quote 列には検出された実際の値(氏名・メールアドレス・電話番号)が格納されており、メールアドレスは VERY_LIKELY、氏名は LIKELY〜POSSIBLE という確度で評価されていることが確認できます。
BigQueryに検出結果を保存しているので、SQLを利用してファイルごとの findings 件数を確認することができます。
SELECT
info_type.name,
locations.container_name,
COUNT(locations.container_name) AS count
FROM `PROJECT_ID.DATASET.TABLE_ID`,
UNNEST(location.content_locations) AS locations
GROUP BY locations.container_name, info_type.name
ORDER BY count DESC;

ファイルごとのfindings件数の確認
クエリ結果には gs://.../sample_pii.csv のみが表示され、sample_no_pii.csv はどの行にも含まれていません。PII を含まないファイルについては findings が生成されないことが確認できました。
まとめ
Sensitive Data Protection の Inspection 機能を使って、Cloud Storage バケット内のファイルから PII を検出し、結果を BigQuery に出力する手順をご紹介しました。
Sensitive Data Protection には、100 以上の組み込み infoType が用意されており、メールアドレス・電話番号といったグローバルな PII から、マイナンバー・銀行口座番号など日本固有の情報まで幅広くカバーしています。検出結果を BigQuery に蓄積することで、ファイルをまたいだ横断的な分析や、継続的なコンプライアンス監視基盤として活用できます。最初の 1 GB までは無料でスキャンできるため、まずはサンプルデータで動作を確認してから本格導入を検討することができます。
なお、今回の検証でも、マイナンバーのつもりで用意した 12 桁の数字がチェックサム検証を通過できず JAPAN_INDIVIDUAL_NUMBER として検出されなかった一方、同じ値が PHONE_NUMBER として誤検出されるケースが見られました。組み込み infoType は完全な精度を保証するものではなく、検出漏れと誤検出はトレードオフの関係にあります。本番環境への導入前には、実際のデータを使った動作確認と --min-likelihood の閾値調整を行うことを強くおすすめします。
Cloud Storage に多くのデータを保存している方や、個人情報保護の観点からデータガバナンスを強化したい方は、ぜひ Sensitive Data Protection の活用を検討してみてください。
この記事が誰かの助けになれば幸いです。
以上、クラウド事業本部コンサルティング部の渡邉でした!








