# 機能設計書 169-Invoke-DbaDbPiiScan

## 概要

本ドキュメントは、dbatools PowerShellモジュールの`Invoke-DbaDbPiiScan`コマンドレットに関する機能設計書である。このコマンドは、データベース内のテーブルとカラムをスキャンし、PII（個人識別情報）を含む可能性のあるカラムを検出する機能を提供する。

### 本機能の処理概要

Invoke-DbaDbPiiScanは、データベースのテーブルをスキャンし、PIIを含む可能性のあるカラムを検出する。検出は3つの方法で行われる：データ型検出（geography型）、既知の名前パターンマッチング（列名の検査）、およびデータパターンマッチング（列データの正規表現検査）。

**業務上の目的・背景**：
GDPRやCCPAなどのプライバシー規制に対応するため、データベース内の個人情報を特定し、適切な保護措置を講じる必要がある。このコマンドは、PIIを含む可能性のあるカラムを自動的に検出し、データマスキング戦略の策定を支援する。

**機能の利用シーン**：
- データベースのプライバシー監査
- GDPR/CCPA準拠の評価
- データマスキング構成の準備
- 機密データの特定と分類
- データベース移行前のPII評価

**主要な処理内容**：
1. 既知の名前パターンの読み込み（pii-knownnames.json）
2. データパターンの読み込み（pii-patterns.json）
3. カスタムパターンのマージ（オプション）
4. 国/国コードによるフィルタリング
5. テーブル/カラムのスキャン
6. 3つの検出方法による評価
   - DataType: geography型の検出
   - KnownName: 列名パターンマッチング
   - Pattern: データ内容の正規表現マッチング
7. マスキング推奨事項の生成

**関連システム・外部連携**：
- SQL Server Database Engine
- pii-knownnames.json（既知の名前パターン定義）
- pii-patterns.json（データパターン定義）
- Invoke-DbaDbDataMasking（後続処理）

**権限による制御**：
- 対象テーブルに対するSELECT権限が必要
- SQL Server 2005以降をサポート（MinimumVersion 9）

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| - | CLIコマンド | 主機能 | コマンドラインからの直接実行 |

## 機能種別

セキュリティ / データ分析 / コンプライアンス

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| SqlInstance | DbaInstanceParameter[] | No | ターゲットSQL Serverインスタンス | - |
| SqlCredential | PSCredential | No | 代替資格情報 | - |
| Database | string[] | Yes | スキャン対象データベース | 必須チェック |
| Table | string[] | No | 対象テーブル名（未指定時は全テーブル） | - |
| Column | string[] | No | 対象カラム名（未指定時は全カラム） | - |
| Country | string[] | No | 国名フィルタ（例：United States） | - |
| CountryCode | string[] | No | 国コードフィルタ（例：US） | - |
| SampleCount | int | No | サンプル行数（デフォルト: 100） | - |
| KnownNameFilePath | string | No | カスタム既知名パターンJSONファイルパス | - |
| PatternFilePath | string | No | カスタムデータパターンJSONファイルパス | - |
| ExcludeDefaultKnownName | switch | No | デフォルト既知名パターンを除外 | - |
| ExcludeDefaultPattern | switch | No | デフォルトデータパターンを除外 | - |
| ExcludeTable | string[] | No | 除外テーブル名 | - |
| ExcludeColumn | string[] | No | 除外カラム名 | - |
| EnableException | switch | No | 例外を有効化 | - |

### 入力データソース

- コマンドライン引数
- pii-knownnames.json（bin/datamasking/）
- pii-patterns.json（bin/datamasking/）
- カスタムパターンファイル（オプション）

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| ComputerName | string | SQL Serverインスタンスのコンピュータ名 |
| InstanceName | string | SQL Serverインスタンス名 |
| SqlInstance | string | 完全なSQL Serverインスタンス名（computer\instance） |
| Database | string | スキャン対象データベース名 |
| Schema | string | テーブルを含むスキーマ名 |
| Table | string | PII検出テーブル名 |
| Column | string | PII検出カラム名 |
| PII-Category | string | PII分類カテゴリ（例：Identity, Location, Contact） |
| PII-Name | string | PII種別名（例：SSN, Geography, Phone） |
| FoundWith | string | 検出方法（DataType, KnownName, Pattern） |
| MaskingType | string | 推奨マスキング種別（例：Random, Shuffle, Partial） |
| MaskingSubType | string | マスキングサブ種別（例：Decimal, String, Date） |
| Country | string | 国名（Pattern検出時のみ） |
| CountryCode | string | 国コード（Pattern検出時のみ） |
| Pattern | string | マッチしたパターン |
| Description | string | パターン説明（Pattern検出時のみ） |

### 出力先

- コンソール（PSCustomObject配列）

## 処理フロー

### 処理シーケンス

```
1. beginブロック
   ├─ knownNamesの初期化
   ├─ patternsの初期化
   ├─ デフォルト既知名パターン読み込み（ExcludeDefaultKnownName=false時）
   ├─ デフォルトデータパターン読み込み（ExcludeDefaultPattern=false時）
   ├─ カスタム既知名パターン追加（KnownNameFilePath指定時）
   ├─ カスタムデータパターン追加（PatternFilePath指定時）
   ├─ SqlInstance必須チェック
   ├─ Database必須チェック
   └─ Country/CountryCodeフィルタ適用
2. processブロック
   ├─ SqlInstanceループ
   │   ├─ Connect-DbaInstance（MinimumVersion 9）
   │   └─ Databaseループ
   │       ├─ テーブル取得（Table指定/ExcludeTable適用）
   │       └─ テーブルループ
   │           ├─ カラム取得（Column指定/ExcludeColumn適用）
   │           └─ カラムループ
   │               ├─ DataType検出（geography）
   │               ├─ KnownName検出（列名パターン）
   │               └─ Pattern検出（データサンプル）
   └─ 結果出力
```

### フローチャート

```mermaid
flowchart TD
    A[開始] --> B[パターンファイル読み込み]
    B --> C{ExcludeDefaultKnownName?}
    C -->|No| D[pii-knownnames.json読み込み]
    C -->|Yes| E{ExcludeDefaultPattern?}
    D --> E
    E -->|No| F[pii-patterns.json読み込み]
    E -->|Yes| G[カスタムパターン追加]
    F --> G

    G --> H{KnownNameFilePath?}
    H -->|Yes| I[カスタム既知名追加]
    H -->|No| J{PatternFilePath?}
    I --> J
    J -->|Yes| K[カスタムパターン追加]
    J -->|No| L[パラメータ検証]
    K --> L

    L --> M{Country/CountryCode?}
    M -->|Yes| N[パターンフィルタ適用]
    M -->|No| O[SqlInstanceループ]
    N --> O

    O --> P[Connect-DbaInstance]
    P --> Q[Databaseループ]
    Q --> R[テーブル取得・フィルタ]
    R --> S[テーブルループ]
    S --> T[カラム取得・フィルタ]
    T --> U[カラムループ]

    U --> V{DataType = geography?}
    V -->|Yes| W[Location/Geography検出結果追加]
    V -->|No| X{KnownName検出}

    X --> Y{列名パターンマッチ?}
    Y -->|Yes| Z[KnownName検出結果追加]
    Y -->|No| AA{Pattern検出}

    W --> AA
    Z --> AA

    AA --> AB[サンプルデータ取得]
    AB --> AC{データパターンマッチ?}
    AC -->|Yes| AD[Pattern検出結果追加]
    AC -->|No| AE{次のカラム?}
    AD --> AE

    AE -->|Yes| U
    AE -->|No| AF{次のテーブル?}
    AF -->|Yes| S
    AF -->|No| AG{次のDB?}
    AG -->|Yes| Q
    AG -->|No| AH{次のインスタンス?}
    AH -->|Yes| O
    AH -->|No| AI[結果出力]
    AI --> AJ[終了]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-001 | DataType検出 | geography型カラムはLocation/Geographyとして検出 | 常時 |
| BR-002 | KnownName検出 | 列名がknownNamesパターンにマッチすれば検出 | knownNames存在時 |
| BR-003 | Pattern検出 | データがpatternsにマッチすれば検出 | patterns存在時 |
| BR-004 | SampleCount | サンプル行数（デフォルト100）で検査 | 常時 |
| BR-005 | 重複排除 | 同一カラムの同一PII種別は重複登録しない | 常時 |
| BR-006 | テキスト型のみTRIM | char/varchar/nchar/nvarchar型はLTRIM/RTRIM適用 | Pattern検出時 |

### 計算ロジック

**サンプルクエリ**:
```sql
SELECT TOP(100) LTRIM(RTRIM([ColumnName])) AS [ColumnName]
FROM [Schema].[Table]
```
- テキスト型のみLTRIM/RTRIM適用
- SampleCountで行数制御

## データベース操作仕様

### 操作別データベース影響一覧

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| サンプル取得 | 対象テーブル | SELECT（TOP N） | パターンマッチング用サンプル取得 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| - | ParseError | pii-knownnames.json解析失敗 | Stop-Function -Return |
| - | ParseError | pii-patterns.json解析失敗 | Stop-Function -Return |
| - | ParseError | カスタムパターンファイル解析失敗 | Stop-Function -Return |
| - | FileNotFound | カスタムパターンファイル不存在 | Stop-Function |
| - | InvalidArgument | SqlInstance未指定 | Stop-Function |
| - | InvalidArgument | Database未指定 | Stop-Function |
| - | ConnectionError | SQL Server接続失敗 | Stop-Function -Continue |
| - | QueryError | サンプルデータ取得失敗 | Stop-Function -Continue |

### リトライ仕様

リトライ機能なし（エラー発生時は次のカラム/テーブルに継続）

## トランザクション仕様

- 読み取り専用（SELECT TOP N）
- トランザクション管理なし

## パフォーマンス要件

- SampleCountで検査行数を制限（デフォルト100）
- 進捗表示（Write-Progress）
- 大規模データベースでは時間がかかる

## セキュリティ考慮事項

- 対象テーブルに対するSELECT権限が必要
- PII検出結果自体が機密情報となる可能性がある
- 出力結果の管理に注意

## 備考

- SQL Server 2005以降をサポート（MinimumVersion 9）
- 検出結果はInvoke-DbaDbDataMaskingへの入力として使用可能
- カスタムパターンファイルの形式はbin/datamasking/のJSON形式に準拠

---

## コードリーディングガイド

本機能を理解するために参照すべきファイルと、推奨する読み解き順序を以下に示す。

### 推奨読解順序

#### Step 1: データ構造を理解する

PIIスキャンのパターン定義とデータ構造を理解することが重要。

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | pii-knownnames.json | bin/datamasking/pii-knownnames.json | 既知の列名パターン定義 |
| 1-2 | pii-patterns.json | bin/datamasking/pii-patterns.json | データパターン定義 |
| 1-3 | 配列初期化 | 177-180行目 | knownNames, patternsの初期化 |

**読解のコツ**: 検出は3つの方法（DataType, KnownName, Pattern）で行われる。

#### Step 2: エントリーポイントを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | Invoke-DbaDbPiiScan.ps1 | `public/Invoke-DbaDbPiiScan.ps1` | 関数全体の構造とパラメータ定義 |

**主要処理フロー**:
1. **159-175行目**: パラメータ定義
2. **177-248行目**: beginブロック（パターン読み込み、検証）
3. **250-465行目**: processブロック（メインスキャン処理）

#### Step 3: パターンファイル読み込み

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | デフォルト既知名 | 183-191行目 | pii-knownnames.json読み込み |
| 3-2 | デフォルトパターン | 194-202行目 | pii-patterns.json読み込み |
| 3-3 | カスタム既知名 | 205-216行目 | KnownNameFilePath追加 |
| 3-4 | カスタムパターン | 218-229行目 | PatternFilePath追加 |
| 3-5 | 国フィルタ | 241-247行目 | Country/CountryCodeフィルタ |

**主要処理フロー**:
- **185行目**: `$script:PSModuleRoot\bin\datamasking\pii-knownnames.json`
- **196行目**: `$script:PSModuleRoot\bin\datamasking\pii-patterns.json`
- **242行目**: Country/CountryCodeでpatternsをフィルタリング

#### Step 4: PII検出処理

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 4-1 | DataType検出 | 319-334行目 | geography型の検出 |
| 4-2 | KnownName検出 | 336-378行目 | 列名パターンマッチング |
| 4-3 | Pattern検出 | 380-453行目 | データパターンマッチング |

**主要処理フロー**:
- **319行目**: `$columnobject.DataType.Name -eq "geography"`
- **341行目**: `$columnobject.Name -match $pattern`
- **388-392行目**: サンプルクエリ生成（LTRIM/RTRIM適用）
- **396行目**: `Invoke-DbaQuery`でサンプル取得
- **409行目**: `$dataset.$($columnobject.Name) -match $patternobject.Pattern`

### プログラム呼び出し階層図

```
Invoke-DbaDbPiiScan
    │
    ├─ Resolve-Path
    │      └─ パターンファイルパス解決
    │
    ├─ Get-Content | ConvertFrom-Json
    │      ├─ pii-knownnames.json
    │      └─ pii-patterns.json
    │
    ├─ Connect-DbaInstance
    │      └─ -MinimumVersion 9
    │
    ├─ $server.Databases[]
    │      └─ データベースアクセス
    │
    ├─ $db.Tables[]
    │      └─ テーブル取得
    │
    ├─ $tableobject.Columns[]
    │      └─ カラム取得
    │
    ├─ Invoke-DbaQuery
    │      └─ サンプルデータ取得
    │
    └─ 正規表現マッチング
           ├─ 列名マッチ（KnownName）
           └─ データマッチ（Pattern）
```

### データフロー図

```
[入力]                           [処理]                              [出力]

pii-knownnames.json ──────────▶ JSON解析
pii-patterns.json ────────────▶
KnownNameFilePath ────────────▶ カスタムパターン追加
PatternFilePath ──────────────▶
                                        │
                                        ▼
Country/CountryCode ──────────▶ パターンフィルタリング
                                        │
                                        ▼
SqlInstance ──────────────────▶ Connect-DbaInstance
SqlCredential ────────────────▶
                                        │
Database ─────────────────────▶ データベース取得
                                        │
Table/ExcludeTable ───────────▶ テーブルフィルタリング
                                        │
Column/ExcludeColumn ─────────▶ カラムフィルタリング
                                        │
                                        ▼
                               ┌────────────────────┐
                               │ DataType検出       │
                               │ (geography型)      │
                               └────────────────────┘
                                        │
                                        ▼
                               ┌────────────────────┐
                               │ KnownName検出      │
                               │ (列名パターン)     │
                               └────────────────────┘
                                        │
                                        ▼
SampleCount ──────────────────▶┌────────────────────┐
                               │ Pattern検出        │
                               │ SELECT TOP(N)     │
                               │ (データパターン)   │
                               └────────────────────┘
                                        │
                                        ▼
                               ┌────────────────────┐
                               │ PSCustomObject生成  │──────▶ コンソール出力
                               │ - Database         │
                               │ - Schema           │
                               │ - Table            │
                               │ - Column           │
                               │ - PII-Category     │
                               │ - PII-Name         │
                               │ - FoundWith        │
                               │ - MaskingType      │
                               │ - MaskingSubType   │
                               └────────────────────┘
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| Invoke-DbaDbPiiScan.ps1 | `public/Invoke-DbaDbPiiScan.ps1` | ソース | メイン関数定義 |
| pii-knownnames.json | `bin/datamasking/pii-knownnames.json` | 構成 | 既知の列名パターン定義 |
| pii-patterns.json | `bin/datamasking/pii-patterns.json` | 構成 | データパターン定義 |
| Invoke-DbaDbDataMasking.ps1 | `public/Invoke-DbaDbDataMasking.ps1` | ソース | 後続マスキング処理 |
| New-DbaDbMaskingConfig.ps1 | `public/New-DbaDbMaskingConfig.ps1` | ソース | マスキング構成生成 |
