0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

DSPM・動的データマスキング・ABACで実装するデータ中心ゼロトラスト実践ガイド

0
Last updated at Posted at 2026-03-23

DSPM・動的データマスキング・ABACで実装するデータ中心ゼロトラスト実践ガイド

ゼロトラストは「ネットワーク境界を信頼しない」アプローチとして広く知られていますが、多くの組織ではネットワーク層やアイデンティティ層の対策に注力する一方で、データ層の保護が手薄なままです。CISA Zero Trust Maturity Model(ZTMM)v2.0 では5つの柱(Identity, Devices, Networks, Applications, Data)を定義しており、2025年1月のCISA報告書では「データ柱への対応リソースが不足しており、ZTAのリスク低減目標はデータ戦略なしには達成できない」と指摘されています。

本記事では、データそのものを保護する「データ中心ゼロトラスト」 の考え方と実装手法を、DSPM(Data Security Posture Management)、動的データマスキング、ABAC(Attribute-Based Access Control)の3つの柱で解説します。

この記事でわかること

  • CISA ZTMM v2.0 のデータ柱(Data Pillar)が求める8つの機能と成熟度段階の全体像
  • DSPM ツールによるデータ可視化・自動分類の仕組みと導入効果(インシデント対応50%高速化の報告)
  • Snowflake・BigQuery での動的データマスキングの具体的な SQL 実装方法
  • OPA(Rego)と Cedar によるデータアクセスの属性ベース制御(ABAC)ポリシー設計
  • トークン化・FPE(Format-Preserving Encryption)によるデータ自体の保護と PCI DSS 4.0 対応

対象読者

  • 想定読者: セキュリティ基盤に関心のある MLE(Machine Learning Engineer)・データエンジニア・インフラエンジニア
  • 必要な前提知識:
    • SQL の基本的な構文(CREATE, ALTER, CASE 式)
    • クラウドデータウェアハウス(Snowflake または BigQuery)の基礎操作
    • ゼロトラストの基本概念(「すべてのアクセスを検証する」という原則)
    • JSON / YAML の読み書き

関連記事: ゼロトラストの全体像については「NIST SP 800-207準拠のゼロトラストアーキテクチャをOSSで実装する実践ガイド」、成熟度モデルについては「CISA ZTMM v2.0の5柱で進めるゼロトラスト成熟度評価と段階的導入ガイド」も併せてご覧ください。本記事はこれらが扱わなかったデータ柱に特化した内容です。

結論・成果

データ中心ゼロトラストを導入することで、以下の効果が報告されています。

  • Zscaler の報告によると、DSPM 戦略を持つ組織はセキュリティインシデント対応時間が 50%短縮 されている(Zscaler DSPM Predictions 2025
  • 動的データマスキングの導入により、機密データへの不正アクセスリスクを 大幅に低減 しつつ、正規ユーザーの業務効率を維持できる
  • ABAC モデルによるアクセス制御は、2025年の研究で 精度96.8% を達成(Symmetry Journal, 2025
  • PCI DSS 4.0(2025年3月施行)対応では、トークン化が 74%の組織で最多の採用手法 となっている(Protegrity PCI Survey

CISA ZTMM データ柱の全体像を理解する

まず、データ中心ゼロトラストのフレームワークを理解しましょう。CISA ZTMM v2.0 のデータ柱は、以下の8つの機能で構成されています。

データ柱の8機能と成熟度段階

機能 説明 Initial Advanced Optimal
インベントリ管理 データの自動発見・カタログ化 一部自動化 全社自動化 継続的インベントリ + 動的DLP
分類 機密度に基づくラベル付け 手動ラベル 一部自動分類 全社ML自動分類
可用性 冗長性と高可用性の確保 一部クラウド 主にクラウド 動的最適化
アクセス制御 最小権限の自動適用 一部自動化 属性ベース制御 JIT/JEA動的制御
暗号化 保存時・転送時・使用時の暗号化 転送時 + 一部保存時 全暗号化 + 鍵ローテーション 使用時暗号化 + 暗号敏捷性
可視性・分析 データアクセスの監視と分析 一部自動分析 全社分析 + 予測分析 ライフサイクル全体の分析
自動化 ポリシーの自動適用 一部自動化 主に自動化 全自動化
ガバナンス データライフサイクルポリシー 手動実施 統合定義 動的適用

出典: CISA Zero Trust Maturity Model v2.0Microsoft CISA ZTMM Data Pillar Guide

なぜデータ柱が重要なのか:

  • ネットワーク境界の保護だけでは、内部脅威やクラウド環境でのデータ漏洩を防げない
  • IDC の予測によると、2026年までにデータ量は 221,000エクサバイト に達する(年間成長率21.2%)
  • データ層のゼロトラストなしでは、ZTA の全体的なリスク低減目標は達成できない

注意: 多くの組織はネットワーク・ID層の成熟度が Advanced に達している一方で、データ柱は Initial にとどまっています。本記事はこのギャップを埋めるための具体的な実装手法を解説します。

データ中心ゼロトラストの3層防御モデル

データ中心ゼロトラストでは、以下の3層で防御を構築します。

  1. 第1層(可視化・分類): DSPM でデータを発見し、機密度を自動分類する
  2. 第2層(アクセス制御): ABAC ポリシーで「誰が、どのデータに、どの条件で」アクセスできるかを制御し、動的データマスキングで非権限者への表示を制限する
  3. 第3層(データ保護): トークン化・FPE・カラムレベル暗号化でデータ自体を保護する

この3層を組み合わせることで、仮に1層が突破されても他の層で防御できる多層防御を実現します。

DSPMでデータを可視化・分類する

DSPM(Data Security Posture Management)は、ML を活用してクラウド環境全体のデータを自動発見・分類し、セキュリティリスクを可視化するアプローチです。MLE にとっては「モデルの学習データやフィーチャーストアにどんな機密データが含まれているか」を把握する基盤になります。

DSPM の基本アーキテクチャ

DSPM ツールは以下のパイプラインでデータを処理します。

クラウドプロバイダ別のデータ分類サービス

各クラウドプロバイダは、DSPM の基盤となるデータ分類サービスを提供しています。

サービス プロバイダ 主な機能 検出対象
Amazon Macie AWS ML活用のS3データ分類 PII, PCI, カスタムパターン
Cloud DLP Google Cloud BigQuery自動プロファイリング 150+の検出器、カスタム辞書
Microsoft Purview Azure 統合データガバナンス 300+の機密情報タイプ、ML分類器

出典: AWS MacieMicrosoft Purview DSPM

AWS Macie によるデータ分類の実装例

以下は、AWS Macie を使って S3 バケット内の機密データを自動分類する設定例です。

# macie_scanner.py
# AWS Macie を使った S3 データ分類ジョブの作成
import boto3
import json
from datetime import datetime

def create_classification_job(bucket_name: str, account_id: str) -> dict:
    """S3バケットの機密データ分類ジョブを作成する。

    ML(機械学習)のコンテキストでは、学習データやフィーチャーストアの
    S3バケットに対して実行し、PII等の機密データ混入を検出する。
    """
    macie = boto3.client("macie2")

    # カスタム検出器: MLモデルの学習データに含まれやすいパターン
    custom_data_identifier = macie.create_custom_data_identifier(
        name="MLTrainingDataPII",
        description="ML学習データ内のPII検出",
        regex="[0-9]{3}-[0-9]{4}-[0-9]{4}",  # 日本の電話番号パターン
        keywords=["氏名", "住所", "電話番号", "メールアドレス"],
        maximumMatchDistance=50,
    )

    # 分類ジョブの作成
    response = macie.create_classification_job(
        jobType="ONE_TIME",
        name=f"ml-data-scan-{datetime.now().strftime('%Y%m%d')}",
        s3JobDefinition={
            "bucketDefinitions": [
                {
                    "accountId": account_id,
                    "buckets": [bucket_name],
                }
            ],
            "scoping": {
                "includes": {
                    "and": [
                        {
                            "simpleScopeTerm": {
                                "comparator": "STARTS_WITH",
                                "key": "OBJECT_KEY",
                                "values": ["training-data/", "features/"],
                            }
                        }
                    ]
                }
            },
        },
        customDataIdentifierIds=[
            custom_data_identifier["customDataIdentifierId"]
        ],
        description="ML学習データの機密データスキャン",
    )
    return response


def get_findings_summary(job_id: str) -> dict:
    """分類ジョブの結果サマリーを取得する。"""
    macie = boto3.client("macie2")

    findings = macie.list_findings(
        findingCriteria={
            "criterion": {
                "classificationDetails.jobId": {
                    "eq": [job_id],
                }
            }
        }
    )

    if not findings["findingIds"]:
        return {"status": "clean", "findings_count": 0}

    details = macie.get_findings(findingIds=findings["findingIds"])
    severity_counts = {}
    for finding in details["findings"]:
        severity = finding["severity"]["description"]
        severity_counts[severity] = severity_counts.get(severity, 0) + 1

    return {
        "status": "findings_detected",
        "findings_count": len(findings["findingIds"]),
        "severity_breakdown": severity_counts,
    }

なぜ Macie を選んだか:

  • S3 に保存された ML 学習データのスキャンに特化している
  • カスタム検出器で日本語のPIIパターンも定義可能
  • 代替案の Google Cloud DLP は BigQuery との統合が強いが、S3 データには Macie が適している

注意点:

Macie は S3 バケットのスキャンに特化しているため、RDS や DynamoDB のデータ分類には別途 AWS Glue DataBrew や手動スキャンが必要です。また、大量のオブジェクトをスキャンするとコストが増加するため、スキャン対象のプレフィックスを絞ることを推奨します。

DSPM導入のよくある失敗パターン

最初は「全データソースを一括スキャンしよう」と考えがちですが、実際にはスキャン対象の優先順位付けが重要です。ML パイプラインの場合、以下の順序で段階的に導入すると効果的です。

  1. 最優先: フィーチャーストア(本番データが含まれやすい)
  2. 次に: 学習データセット(PIIが混入しやすい)
  3. その後: モデルアーティファクト(メタデータに機密情報が含まれる場合がある)

動的データマスキングでアクセス時にデータを保護する

動的データマスキング(DDM: Dynamic Data Masking)は、データ自体は変更せず、クエリ実行時にユーザーの権限に応じてデータの表示を制御する仕組みです。Pythonのデコレータに例えると、元の関数(データ)は変更せず、呼び出し時の振る舞い(表示)だけを変えるイメージです。

Snowflake での動的データマスキング実装

Snowflake Enterprise Edition 以上で利用可能な DDM の実装例を紹介します。

-- =====================================================
-- Snowflake 動的データマスキング実装
-- 前提: Enterprise Edition 以上
-- =====================================================

-- 1. マスキング管理用ロールの作成
USE ROLE SECURITYADMIN;
CREATE ROLE IF NOT EXISTS masking_admin;
GRANT CREATE MASKING POLICY ON SCHEMA ml_platform.public TO ROLE masking_admin;
GRANT APPLY MASKING POLICY ON ACCOUNT TO ROLE masking_admin;

-- 2. メールアドレスのマスキングポリシー
-- ANALYST ロールは全文表示、SUPPORT はドメインのみ、それ以外は完全マスク
USE ROLE masking_admin;
CREATE OR REPLACE MASKING POLICY ml_platform.public.email_mask
    AS (val STRING) RETURNS STRING ->
    CASE
        WHEN CURRENT_ROLE() IN ('DATA_SCIENTIST', 'ML_ENGINEER') THEN val
        WHEN CURRENT_ROLE() IN ('SUPPORT') THEN REGEXP_REPLACE(val, '.+\@', '****@')
        ELSE '***MASKED***'
    END;

-- 3. 電話番号の部分マスキング(下4桁のみ表示)
CREATE OR REPLACE MASKING POLICY ml_platform.public.phone_mask
    AS (val STRING) RETURNS STRING ->
    CASE
        WHEN CURRENT_ROLE() IN ('DATA_SCIENTIST') THEN val
        ELSE CONCAT('***-****-', RIGHT(val, 4))
    END;

-- 4. 数値データのマスキング(年収等)
-- ハッシュ化して統計分析は可能だが個人特定は不可にする
CREATE OR REPLACE MASKING POLICY ml_platform.public.salary_mask
    AS (val NUMBER) RETURNS NUMBER ->
    CASE
        WHEN CURRENT_ROLE() IN ('DATA_SCIENTIST') THEN val
        WHEN CURRENT_ROLE() IN ('ANALYST') THEN
            ROUND(val, -4)  -- 万単位に丸める(統計分析用)
        ELSE 0
    END;

-- 5. ポリシーをテーブルのカラムに適用
ALTER TABLE ml_platform.public.customers
    MODIFY COLUMN email SET MASKING POLICY ml_platform.public.email_mask;
ALTER TABLE ml_platform.public.customers
    MODIFY COLUMN phone SET MASKING POLICY ml_platform.public.phone_mask;
ALTER TABLE ml_platform.public.customers
    MODIFY COLUMN annual_salary SET MASKING POLICY ml_platform.public.salary_mask;

-- 6. タグベースマスキング(推奨: 大規模環境向け)
-- タグを使うと、同じ機密度のカラムに一括でポリシーを適用できる
CREATE OR REPLACE TAG ml_platform.public.pii_level
    ALLOWED_VALUES 'HIGH', 'MEDIUM', 'LOW';

-- タグにマスキングポリシーを紐付け
ALTER TAG ml_platform.public.pii_level
    SET MASKING POLICY ml_platform.public.email_mask;

-- カラムにタグを設定するだけで自動的にマスキングが適用される
ALTER TABLE ml_platform.public.customers
    MODIFY COLUMN email SET TAG ml_platform.public.pii_level = 'HIGH';

出典: Snowflake Dynamic Data Masking Documentation

BigQuery での動的データマスキング実装

BigQuery でも同様のマスキングをポリシータグで実現できます。

-- =====================================================
-- BigQuery 動的データマスキング実装
-- =====================================================

-- 1. ポリシータグの分類体系(Taxonomy)を作成
-- (Google Cloud Console または gcloud CLI で作成)
-- gcloud data-catalog taxonomies create "data_sensitivity" \
--     --location=asia-northeast1 \
--     --display-name="データ機密度分類"

-- 2. ポリシータグを作成
-- gcloud data-catalog taxonomies policy-tags create "PII_HIGH" \
--     --taxonomy="projects/my-project/locations/asia-northeast1/taxonomies/data_sensitivity" \
--     --display-name="高機密PII"

-- 3. データマスキングルールの定義
-- BigQuery ではマスキングルールをポリシータグに紐付ける
-- 利用可能なマスキングタイプ:
--   - SHA256: ハッシュ化(結合キーとして利用可能)
--   - DEFAULT_MASKING_VALUE: デフォルト値に置換
--   - NULLIFY: NULLに置換
--   - DATE_YEAR_MASK: 年のみ保持

-- 4. 特定ロールへのマスキング解除(Fine-Grained Reader)
-- gcloud bigquery tables set-iam-policy customers policy.json
-- policy.json で roles/bigquery.maskedReader と
-- roles/bigquery.fineGrainedReader を設定

-- 5. クエリ結果の確認例
-- Fine-Grained Reader ロール: 元の値が表示される
SELECT email, phone, annual_salary
FROM `my-project.ml_platform.customers`
LIMIT 5;
-- 結果: taro@example.com, 090-1234-5678, 6500000

-- Masked Reader ロール: マスクされた値が表示される
-- 結果: SHA256ハッシュ値, NULL, NULL

Snowflake vs BigQuery のマスキング機能比較

機能 Snowflake BigQuery
マスキング粒度 カラム単位 カラム単位(ポリシータグ経由)
ポリシー言語 SQL CASE式 組み込みマスキングタイプ
カスタムマスキング 自由なSQL式 限定的(SHA256, NULL, デフォルト値等)
タグベース一括適用 対応 対応(ポリシータグ)
必要エディション Enterprise以上 全エディション
行レベルセキュリティ Row Access Policy Row-Level Security

トレードオフ: Snowflake はカスタムマスキングの自由度が高い(任意の SQL 式を記述可能)が、Enterprise Edition 以上が必要です。BigQuery は全エディションで利用可能ですが、マスキングタイプが限定的です。ML パイプラインで部分マスキング(例: 年収を万単位に丸める)が必要な場合は Snowflake が適しています。

ABAC + ポリシーエンジンでデータアクセスを制御する

RBAC(Role-Based Access Control)では「データサイエンティストロール → 全テーブルにアクセス可能」のような粗い制御しかできません。ABAC(Attribute-Based Access Control)では、ユーザー属性、リソース属性、環境属性を組み合わせて動的にアクセス判定を行います。Pythonの型システムに例えると、RBAC が isinstance(user, DataScientist) なら、ABAC は user.department == "ml" and resource.sensitivity <= user.clearance_level and context.time.is_business_hours() のようなきめ細かい判定です。

OPA(Open Policy Agent)によるABAC実装

OPA は Rego というポリシー言語を使い、JSON データに対する柔軟なアクセス制御を実現します。

# data_access_policy.rego
# ML データプラットフォームのデータアクセスABACポリシー
package data.access

import rego.v1

# デフォルトはアクセス拒否
default allow := false

# 機密度レベル定義: 1=LOW, 2=MEDIUM, 3=HIGH
# sensitivity_level は整数(1-3)で統一

# ルール1: ユーザーの部門とデータの所有部門が一致する場合にアクセス許可
allow if {
    input.user.department == input.resource.owner_department
    input.resource.sensitivity_level <= input.user.clearance_level
}

# ルール2: データサイエンティストは学習データにアクセス可能
# ただし、機密度が3(HIGH)の場合は追加承認が必要
allow if {
    input.user.role == "data_scientist"
    input.resource.type == "training_data"
    input.resource.sensitivity_level < 3
}

# ルール3: 高機密データへのアクセスは承認済みかつ業務時間内のみ
allow if {
    input.resource.sensitivity_level == 3
    input.user.has_approval == true
    is_business_hours(input.context.timestamp)
}

# ルール4: 匿名化済みデータには誰でもアクセス可能
allow if {
    input.resource.anonymized == true
}

# 業務時間の判定(JST 9:00-18:00)
is_business_hours(ts) if {
    hour := time.clock(time.parse_rfc3339_ns(ts))[0]
    hour >= 0  # UTC 0:00 = JST 9:00
    hour < 9   # UTC 9:00 = JST 18:00
}

# マスキングレベルの決定
masking_level := "none" if {
    allow
    input.user.clearance_level >= input.resource.sensitivity_level
}

masking_level := "partial" if {
    allow
    input.user.clearance_level < input.resource.sensitivity_level
}

masking_level := "full" if {
    not allow
}

以下は、OPA サーバーにポリシー評価をリクエストする Python クライアントの例です。

# opa_client.py
# OPA にデータアクセスの判定を問い合わせるクライアント
import httpx
from dataclasses import dataclass
from datetime import datetime, timezone


@dataclass
class AccessRequest:
    """データアクセスリクエスト。

    ML パイプラインでのデータアクセスを OPA に問い合わせる際に使用する。
    """
    user_id: str
    user_role: str
    user_department: str
    user_clearance_level: int
    resource_id: str
    resource_type: str
    resource_sensitivity_level: int
    resource_owner_department: str
    has_approval: bool = False


async def evaluate_access(
    opa_url: str,
    request: AccessRequest,
) -> dict:
    """OPA にアクセス判定を問い合わせる。

    Returns:
        {"allow": bool, "masking_level": "none"|"partial"|"full"}
    """
    input_data = {
        "input": {
            "user": {
                "id": request.user_id,
                "role": request.user_role,
                "department": request.user_department,
                "clearance_level": request.user_clearance_level,
                "has_approval": request.has_approval,
            },
            "resource": {
                "id": request.resource_id,
                "type": request.resource_type,
                "sensitivity_level": request.resource_sensitivity_level,
                "owner_department": request.resource_owner_department,
                "anonymized": False,
            },
            "context": {
                "timestamp": datetime.now(timezone.utc).isoformat(),
            },
        }
    }

    async with httpx.AsyncClient(timeout=5.0) as client:
        response = await client.post(
            f"{opa_url}/v1/data/data/access",
            json=input_data,
        )
        response.raise_for_status()
        result = response.json().get("result", {})

    return {
        "allow": result.get("allow", False),
        "masking_level": result.get("masking_level", "full"),
    }

出典: OPA ABAC Implementation GuideOPA Documentation

Cedar によるデータアクセスポリシー

Cedar は AWS が開発した認可ポリシー言語で、RBAC・ABAC・ReBAC をすべてサポートしています。Amazon Verified Permissions と統合して利用します。

// cedar_data_policy.cedar
// ML データプラットフォームのデータアクセスポリシー(Cedar)

// ポリシー1: データサイエンティストは自部門のデータにアクセス可能
permit(
    principal is DataPlatform::User,
    action == DataPlatform::Action::"ReadData",
    resource is DataPlatform::Dataset
) when {
    principal.department == resource.ownerDepartment &&
    resource.sensitivityLevel <= principal.clearanceLevel
};

// ポリシー2: 匿名化済みデータは全員アクセス可能
permit(
    principal is DataPlatform::User,
    action == DataPlatform::Action::"ReadData",
    resource is DataPlatform::Dataset
) when {
    resource.isAnonymized == true
};

// ポリシー3: 高機密データへのアクセスを禁止(承認なし)
forbid(
    principal is DataPlatform::User,
    action == DataPlatform::Action::"ReadData",
    resource is DataPlatform::Dataset
) when {
    resource.sensitivityLevel == 3 &&
    !(principal in DataPlatform::Group::"HighSensitivityApproved")
};

// ポリシー4: モデル学習での全データアクセス(バッチ処理用)
permit(
    principal is DataPlatform::ServiceAccount,
    action == DataPlatform::Action::"BatchRead",
    resource is DataPlatform::Dataset
) when {
    principal.purpose == "model_training" &&
    resource.allowBatchAccess == true
};

出典: Cedar Policy Language Overview

OPA vs Cedar の比較

項目 OPA(Rego) Cedar
開発元 CNCF(オープンソース) AWS(オープンソース)
ポリシー言語 Rego(Datalog系) Cedar(独自DSL)
学習曲線 中〜高(Rego独自の構文) 低〜中(自然言語に近い)
静的解析 限定的 形式検証ツール付属
マネージドサービス Styra DAS Amazon Verified Permissions
Kubernetes統合 Gatekeeper / OPA Envoy なし
適用領域 汎用(API, K8s, データ, CI/CD) 主にアプリケーション認可

なぜ使い分けるのか:

  • OPA: Kubernetes 環境やマイクロサービス全体のポリシー統合が必要な場合に適している。ML プラットフォームが K8s 上で稼働している場合は OPA を推奨
  • Cedar: AWS ネイティブ環境で Amazon Verified Permissions と組み合わせる場合に適している。形式検証ツールでポリシーの矛盾を事前検出できる点がメリット

ハマりポイント: OPA の Rego は Datalog ベースの宣言型言語であり、手続き型プログラミングに慣れた開発者は最初戸惑います。特に、「変数の再代入ができない」「ルール内の式はすべて AND 条件」という性質を理解するまで書きにくく感じます。Rego のPlayground(play.openpolicyagent.org)で試しながら学ぶことを推奨します。

トークン化と暗号化でデータ自体を保護する

第3層として、データ自体を保護する手法を見ていきます。動的データマスキングが「見せ方の制御」であるのに対し、トークン化と暗号化はデータの実体を保護します。

トークン化 vs FPE vs カラムレベル暗号化

手法 仕組み フォーマット維持 可逆性 主な用途
トークン化 元データをランダムトークンに置換 設定次第 トークンヴォルトで可逆 PCI DSS(カード番号)
FPE フォーマット維持暗号化 維持する 鍵で復号可能 レガシーシステム連携
カラムレベル暗号化 カラム単位でAES等で暗号化 維持しない 鍵で復号可能 高機密データ保護

HashiCorp Vault によるトークン化の実装

HashiCorp Vault の Transform シークレットエンジンは、NIST が承認した FF3-1 アルゴリズムによる FPE とトークン化を提供します。

# vault_tokenizer.py
# HashiCorp Vault Transform エンジンを使ったデータトークン化
import hvac


def setup_vault_transform(vault_url: str, vault_token: str) -> None:
    """Vault Transform エンジンの初期設定。

    FPE(FF3-1)を使った電話番号のトークン化を設定する。
    """
    client = hvac.Client(url=vault_url, token=vault_token)

    # Transform エンジンを有効化
    client.sys.enable_secrets_engine(
        backend_type="transform",
        path="transform",
    )

    # アルファベット定義(日本の電話番号: 数字とハイフン)
    client.secrets.transform.create_or_update_alphabet(
        mount_point="transform",
        name="phone-digits",
        alphabet="0123456789",
    )

    # テンプレート定義(電話番号フォーマット: 090-XXXX-XXXX)
    client.secrets.transform.create_or_update_template(
        mount_point="transform",
        name="phone-number",
        template_type="regex",
        pattern=r"(\d{3})-(\d{4})-(\d{4})",
        alphabet="phone-digits",
    )

    # トランスフォーメーション定義(FPE)
    client.secrets.transform.create_or_update_transformation(
        mount_point="transform",
        name="phone-fpe",
        transformation_type="fpe",
        template="phone-number",
        tweak_source="internal",
        allowed_roles=["ml-pipeline"],
    )

    # ロール定義
    client.secrets.transform.create_or_update_role(
        mount_point="transform",
        name="ml-pipeline",
        transformations=["phone-fpe"],
    )


def tokenize_phone(
    vault_url: str,
    vault_token: str,
    phone_number: str,
) -> str:
    """電話番号をFPEでトークン化する。

    元の電話番号と同じフォーマット(XXX-XXXX-XXXX)を維持したまま
    暗号化される。レガシーシステムのカラム長制約を壊さない。
    """
    client = hvac.Client(url=vault_url, token=vault_token)
    result = client.secrets.transform.encode(
        mount_point="transform",
        role_name="ml-pipeline",
        value=phone_number,
        transformation="phone-fpe",
    )
    return result["data"]["encoded_value"]


def detokenize_phone(
    vault_url: str,
    vault_token: str,
    tokenized_phone: str,
) -> str:
    """トークン化された電話番号を復元する。"""
    client = hvac.Client(url=vault_url, token=vault_token)
    result = client.secrets.transform.decode(
        mount_point="transform",
        role_name="ml-pipeline",
        value=tokenized_phone,
        transformation="phone-fpe",
    )
    return result["data"]["decoded_value"]


# 使用例
# 元の値:     090-1234-5678
# トークン化: 090-8371-2094 (同じフォーマットだが異なる値)
# 復元:       090-1234-5678

出典: HashiCorp Vault Transform Secrets Engine

なぜ FPE を選ぶのか:

  • フォーマット維持: 電話番号やカード番号のフォーマット(桁数、ハイフン位置)を維持するため、レガシーシステムのスキーマ変更が不要
  • NIST 承認: FF3-1 アルゴリズムは NIST が承認した暗号方式
  • 代替案との比較: 通常の AES 暗号化はデータ長が変わるため、既存の DB カラム長制約に抵触する場合がある

制約条件:

FPE はフォーマット維持の制約上、通常の AES 暗号化と比較してセキュリティマージンが小さいとされています。入力空間が小さい場合(例: 4桁のPIN)は推奨されません。NIST SP 800-38G Rev.1 では入力が100万通り以上(約20ビット)であることを推奨しています。電話番号(10桁 = 100億通り)は十分な入力空間を持ちます。

データ中心保護の選定フローチャート

よくある問題と解決方法

問題 原因 解決方法
マスキングポリシー適用後にクエリが遅くなる マスキング関数がクエリプランを変更する マスキング関数を単純に保つ(CASE式のみ)。UDF呼び出しを避ける
OPA の応答遅延 ポリシー評価が複雑すぎる バンドルサイズを小さくし、部分評価(Partial Evaluation)を活用する
FPE でトークン化した値がユニーク制約に違反 異なる入力が同じ出力にマッピング Tweak値(初期化ベクトル相当)をレコードごとに変える
DSPM スキャンのコストが高い 全データソースを毎日スキャンしている 差分スキャンに切り替え、変更のあったオブジェクトのみスキャンする
Cedar ポリシーの矛盾 permit と forbid が同じリクエストにマッチ Cedar の形式検証ツール cedar-policy-validator で事前チェック

まとめと次のステップ

まとめ:

  • データ中心ゼロトラストは、CISA ZTMM のデータ柱に基づき、可視化 → アクセス制御 → データ保護の3層で構築する
  • DSPM はデータの自動発見・分類を行い、「何を守るべきか」を明確にする基盤となる
  • 動的データマスキング(Snowflake / BigQuery)はデータを変更せずにアクセス時の表示を制御する
  • ABAC(OPA / Cedar)はユーザー・リソース・環境の属性を組み合わせたきめ細かいアクセス判定を実現する
  • トークン化・FPE はデータ自体を保護し、PCI DSS 4.0 等のコンプライアンス要件に対応する

次にやるべきこと:

  1. 現状評価: CISA ZTMM のデータ柱で自組織の成熟度を評価し、Initial → Advanced に進むべき機能を特定する
  2. DSPM 導入: まずフィーチャーストアや学習データに対して AWS Macie / Cloud DLP / Microsoft Purview でスキャンを実施し、機密データの所在を把握する
  3. 段階的実装: 動的データマスキングを最もリスクの高いテーブルから適用し、ABAC ポリシーを OPA / Cedar で設計・テストする

参考


注意: この記事はAI(Claude Code)により自動生成されました。内容の正確性については複数の情報源で検証していますが、実際の利用時は公式ドキュメントもご確認ください。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?