# CredManager 初期セットアップ手順書（情報システム管理者向け）

本書は CredManager を自組織に導入する情報システム管理者向けの **living document** です。記載は CredManager 同梱の `setup-access-tiers.ps1` / `setup-sharepoint.ps1` / アプリ内セットアップウィザード / 診断機能 / 環境設定の **実装そのもの** に基づいています。スクリーンショットは別途貼り込む前提でプレースホルダを置いています。

> 本書は旧 `docs/credmanager-admin-setup-guide.md` を置き換える最新版です。旧ガイドは手動 CLI 手順のみで、セットアップウィザード・ネイティブバックアップ・ARM 権限・break-glass バックアップ等を含みません。

- 想定読者: Azure / PowerShell / SharePoint の基本操作ができる社内情シス管理者
- 表記: 📷 マークは後からスクリーンショットを貼る箇所。`TODO`/`要確認` はコードから断定できずポータル等での確認が必要な箇所。

---

## 目次

1. [概要・前提](#1-概要前提)
2. [Entra アプリ登録と管理者同意](#2-entra-アプリ登録と管理者同意)
3. [Azure バックボーン（setup-access-tiers.ps1）](#3-azure-バックボーンsetup-access-tiersps1)
4. [SharePoint（setup-sharepoint.ps1）](#4-sharepointsetup-sharepointps1)
5. [アプリ配布・初回起動](#5-アプリ配布初回起動)
6. [セットアップウィザード（簡易/詳細）](#6-セットアップウィザード簡易詳細)
7. [検証（診断 / Key Vault バックアップ状態）](#7-検証診断--key-vault-バックアップ状態)
8. [運用（break-glass バックアップ / 自動督促 / 復旧）](#8-運用break-glass-バックアップ--自動督促--復旧)
9. [トラブルシューティング](#9-トラブルシューティング)

---

## 1. 概要・前提

CredManager は Windows デスクトップアプリ（単独 exe / .NET 8 WPF）です。データは内部に持たず、各 PC のアプリがサインインユーザーの権限で次の組織リソースに接続して動作します。

- **SharePoint リスト** — 暗号化済みクレデンシャル本体（`CredManagerItems`）と設定（`CredManagerSetting`）の保存先
- **Azure Key Vault** — アクセス区分ごとの鍵暗号鍵（KEK, RSA-2048）の保管先。エンベロープ暗号化の鍵ラップ／アンラップに使用
- **Microsoft Entra ID** — サインインと、区分の閲覧可否（Entra セキュリティグループのメンバーシップ）の管理

### 1.1 構成図

```mermaid
flowchart LR
    subgraph PC["利用者 PC"]
      App["CredManager.exe"]
    end
    subgraph Entra["Microsoft Entra ID"]
      AppReg["アプリ登録 CredManager"]
      Groups["区分グループ\n(社外秘 / 管理部 / ...)"]
    end
    subgraph Azure["Azure サブスクリプション"]
      KV["Key Vault\n(RBAC モード)"]
      Keys["区分別 KEK\n(credmanager-kek 等)"]
    end
    subgraph M365["Microsoft 365"]
      SP["SharePoint サイト\n(CredManagerItems / CredManagerSetting)"]
    end
    App -->|"サインイン (User.Read / Sites.ReadWrite.All)"| AppReg
    App -->|"区分判定 (checkMemberGroups)"| Groups
    App -->|"資格情報 CRUD"| SP
    App -->|"DEK の wrap/unwrap (Key Vault user_impersonation)"| Keys
    App -->|"Owner 判定 / Vault 状態照会 (ARM)"| KV
    Groups -. "Key Vault Crypto User (鍵単位スコープ)" .-> Keys
```

### 1.2 暗号方式（参考）

- 各クレデンシャルのパスワードは項目ごとに生成した DEK で **AES-256-CBC** 暗号化。
- DEK は区分に対応する Key Vault 鍵（KEK）で **RSA-OAEP ラップ**して保存。
- 復号は逆順（Key Vault で DEK をアンラップ → AES 復号）。Key Vault へのアクセスはサインインユーザーの委任トークン（`user_impersonation`）で行う。

### 1.3 前提条件

**必要なリソース／権限**

| 区分 | 内容 |
|---|---|
| Microsoft Entra ID テナント | Microsoft 365 を含む |
| Azure サブスクリプション | Key Vault 用。操作者は対象スコープで **所有者（Owner）** または **ユーザーアクセス管理者** 相当（Key Vault 作成 + 鍵スコープのロール割当てに必要） |
| Entra ID 権限 | アプリ登録、`Group.ReadWrite.All` の委任同意（グループ新規作成・読取） |
| SharePoint | サイト作成権限（SharePoint 管理者等）。既存サイト利用時はサイト所有者 |

**ツール（導入者の PC）**

- PowerShell 7+（`pwsh`）推奨。Windows PowerShell 5.1 でも動作（モジュール版が分岐）。
- 以下は **スクリプトが未導入なら自動インストール**（`CurrentUser` スコープ）するため事前導入は必須ではない:
  - `setup-access-tiers.ps1`: `Az.Accounts` / `Az.Resources` / `Az.KeyVault` / `Microsoft.Graph.Authentication` / `Microsoft.Graph.Groups`
  - `setup-sharepoint.ps1`: `PnP.PowerShell`（PS7+ は最新版、PS5.1 は 1.12.0）

> 本セットアップは **導入者（管理者）の PC** で実行するものです。各利用者の PC を直接構成するものではありません。利用者は exe を配るだけで動きます（[セクション 5](#5-アプリ配布初回起動)）。

### 1.4 2 つの導入経路

CredManager のプロビジョニングには 2 経路があり、**どちらも同じ 2 本のスクリプトを実行**します。

- **経路 A: アプリ内セットアップウィザード**（推奨・初回向け） — GUI でパラメータを入力すると、ウィザードが `setup-access-tiers.ps1` → `setup-sharepoint.ps1` を非対話で順に実行。→ [セクション 6](#6-セットアップウィザード簡易詳細)
- **経路 B: スクリプト直接実行**（上級者・CI 向け） — PowerShell から各スクリプトを手動実行。→ [セクション 3](#3-azure-バックボーンsetup-access-tiersps1)・[4](#4-sharepointsetup-sharepointps1)

いずれの経路でも、先に [セクション 2 のアプリ登録](#2-entra-アプリ登録と管理者同意) を済ませる必要があります。

---

## 2. Entra アプリ登録と管理者同意

CredManager はサインインユーザー自身の権限で動作する **公開クライアント（デスクトップ）アプリ**です。ITSN が配布する製品では、マルチテナント共有アプリの既定クライアント ID が焼き込まれています:

- 既定 Client ID: `eef1c3d3-3c89-442b-84f9-a3e48660a2de`（`AppSettings.MultiTenantBakedInClientId`）

自組織専用にアプリ登録を作る場合、または上記アプリへ顧客テナントの同意を与える場合の手順を示します。

### 2.1 アプリ登録（自組織で新規作成する場合）

> 📷 [スクリーンショット] Microsoft Entra 管理センター — アプリの登録（新規登録）
> 想定 URL: https://entra.microsoft.com/#view/Microsoft_AAD_RegisteredApps/ApplicationsListBlade
> ナビ: Entra 管理センター → アプリケーション → アプリの登録 → 新規登録
> （ここに画像を貼る）

1. 「新規登録」。名前は任意（例: `CredManager`）。サポートされるアカウントの種類は運用に合わせて選択（マルチテナント運用なら「任意の組織ディレクトリ内のアカウント」）。
2. 「認証」→ プラットフォームを追加 → **モバイル アプリケーションとデスクトップ アプリケーション** → リダイレクト URI に **`http://localhost`** を追加。
   - これは MSAL の対話型サインイン／管理者同意のリダイレクト先として実装が使用します。

> 📷 [スクリーンショット] アプリ登録 — 認証（リダイレクト URI）
> 想定 URL: https://entra.microsoft.com/#view/Microsoft_AAD_RegisteredApps/ApplicationMenuBlade/~/Authentication
> ナビ: 対象アプリ → 管理 → 認証
> （ここに画像を貼る）

### 2.2 必要な API のアクセス許可（委任）

「API のアクセス許可」→ アクセス許可の追加 で、以下の **委任（Delegated）** 権限を付与します。

| API | アクセス許可 | 用途（実装上の根拠） |
|---|---|---|
| Microsoft Graph | `User.Read` | サインイン（`AuthService.Scopes`） |
| Microsoft Graph | `Sites.ReadWrite.All` | SharePoint リストの読み書き（`AuthService.Scopes`） |
| Microsoft Graph | `GroupMember.Read.All`（要確認） | 区分判定 `/me/checkMemberGroups`（`UserAccessTierService` → `GraphService.CheckMemberGroupsAsync`）。**要確認**: 実装は `User.Read` 文脈で呼んでおり環境によっては追加同意なしで通るが、テナントによっては `GroupMember.Read.All` または `Directory.Read.All` の同意が必要。区分が全件「非表示」になる場合に追加する（[9 章](#9-トラブルシューティング)参照） |
| Azure Key Vault | `user_impersonation` | DEK の wrap/unwrap（`MsalTokenCredential` → `https://vault.azure.net/.default`） |
| Azure Service Management | `user_impersonation` | break-glass の Owner 判定・Vault 状態照会（`AzureRbacService` / `KeyVaultStatusService` → `https://management.azure.com/.default`）。**これが無いと「キー情報のバックアップ（機密）」と「Key Vault バックアップ状態」が動作しない** |

> 📷 [スクリーンショット] アプリ登録 — API のアクセス許可
> 想定 URL: https://entra.microsoft.com/#view/Microsoft_AAD_RegisteredApps/ApplicationMenuBlade/~/CallAnAPI
> ナビ: 対象アプリ → 管理 → API のアクセス許可
> （ここに画像を貼る）

### 2.3 管理者同意

上記の権限（特に Azure Service Management）は **管理者同意** が必要です。2 通りあります。

**方法 1: ポータルで同意**

> 📷 [スクリーンショット] アプリ登録 — 「<テナント> に管理者の同意を与えます」
> 想定 URL: https://entra.microsoft.com/#view/Microsoft_AAD_RegisteredApps/ApplicationMenuBlade/~/CallAnAPI
> ナビ: 対象アプリ → 管理 → API のアクセス許可 → 「<テナント> に管理者の同意を与えます」ボタン
> （ここに画像を貼る）

**方法 2: 管理者同意 URL（アプリ内に組込み済み）**

CredManager は同意 URL を生成・表示します（`AppSettings.GetAdminConsentUrl`）。形式は **プレーンな `/organizations/adminconsent`**（`v2.0/` なし・`scope` 引数なし）で、**アプリ登録に構成された全 API 権限に一括同意** します。後から権限（ARM 等）を追加しても同じ URL で同意し直せます。

```
https://login.microsoftonline.com/organizations/adminconsent?client_id=eef1c3d3-3c89-442b-84f9-a3e48660a2de&redirect_uri=http%3A%2F%2Flocalhost
```

- アプリ内の導線:
  - 環境設定画面 → 補助ナビゲーション → **「管理者同意 URL を開く」**
  - セットアップウィザードの **「管理者同意」ステップ**（URL がテキストボックスに表示されコピー可能）
  - セットアップ診断で同意不足が疑われる項目の remediation ボタン

> 📷 [スクリーンショット] Web ブラウザ — 管理者同意の確認画面
> 想定 URL: 上記 adminconsent URL
> ナビ: 全体管理者アカウントでサインイン → 要求された権限を確認 → 承諾
> （ここに画像を貼る）

4. 同意後、アプリ登録「概要」の **アプリケーション (クライアント) ID** と **ディレクトリ (テナント) ID** を控えます（環境設定／スクリプト引数で使用）。

---

## 3. Azure バックボーン（setup-access-tiers.ps1）

Key Vault・区分鍵・Entra グループ・鍵スコープ RBAC・ネイティブバックアップを **冪等に** プロビジョニングします（無ければ作る／あれば再利用。削除系操作は一切なし）。

### 3.1 パラメータ

| パラメータ | 必須 | 内容 |
|---|---|---|
| `-SubscriptionId` | ○ | 対象 Azure サブスクリプション ID |
| `-ResourceGroup` | ○ | リソースグループ名（無ければ作成） |
| `-VaultName` | ○ | Key Vault 名（テナント内一意） |
| `-Location` | | 既定 `japaneast` |
| `-TiersJsonPath` | △ | 区分定義 JSON のパス（推奨）。未指定かつ `-Tiers` も無ければ対話入力 |
| `-Tiers` | △ | 区分定義のオブジェクト配列（直接指定） |
| `-AccessTiersJsonOutputPath` | | 出力先。既定はスクリプト同階層の `accessTiers.json` |
| `-NonInteractive` | | ウィザード等からの非対話実行用（終了時の `Read-Host` を抑止） |

区分定義 JSON（`-TiersJsonPath`）の形式:

```json
[
  { "DisplayName": "社外秘", "KeyName": "credmanager-kek",
    "GroupName": "CredManager-Confidential", "GroupObjectId": null }
]
```

- `GroupObjectId` を指定 → 既存グループを再利用。`null`/空 → `GroupName` で新規作成。

### 3.2 実行する処理（順序）

1. 依存モジュール確認・自動インストール（`Az.Accounts` / `Az.Resources` / `Az.KeyVault` / `Microsoft.Graph.Authentication` / `Microsoft.Graph.Groups`）。
2. サインイン: `Connect-AzAccount`（既存コンテキスト再利用）+ `Connect-MgGraph -Scopes Group.ReadWrite.All, Directory.Read.All`。
3. リソースグループを確認／作成。
4. **Key Vault を RBAC モード + purge protection 有効で確認／作成**。
   - 新規作成: `New-AzKeyVault ... -DisableRbacAuthorization:$false -EnablePurgeProtection`（= RBAC モード）。soft-delete は既定で有効。
   - 既存再利用: 許可モデルが RBAC でなければ `Update-AzKeyVault -DisableRbacAuthorization $false` で **能動的に RBAC へ切替**。purge protection 未有効なら `Update-AzKeyVault -EnablePurgeProtection -DisableRbacAuthorization $false`（許可モデルを倒さないため現行値を必ず併記）。
   - ⚠ purge protection は **一度有効化すると無効化できません**（スクリプトはログで明示してから実行）。
5. 区分ごとに:
   - Key Vault 鍵（KEK, RSA-2048, Software）を確認／作成。
   - **ネイティブバックアップ**: `Backup-AzKeyVaultKey` で暗号化 blob を `accessTiers.json` と同じフォルダに保存（ファイル名 `keyvault-native-backup-<キー名>-<YYYYMMDD>.blob`）。同日再実行は上書き。
   - Entra セキュリティグループを用意（`GroupObjectId` 指定なら検証して再利用、無ければ `GroupName` で新規作成）。
   - **鍵単位スコープ**で対象グループに `Key Vault Crypto User` ロールを割当て（RBAC 伝播待ちのリトライ付き）。
6. `accessTiers.json` を出力（`NativeKeyBackupUtc`〔ネイティブバックアップ取得日時〕を含む）。

> **鍵単位スコープが区分分離の肝**: ロールは `/subscriptions/.../vaults/<vault>/keys/<key>` という鍵単位スコープに割当てます。Vault 全体スコープにするとすべてのグループが全鍵を使え、区分分離が崩れます。鍵単位スコープ割当ては Azure CLI / PowerShell が必要（ポータル GUI 不可）。

### 3.3 出力 accessTiers.json

```json
{
  "_comment": "Generated by setup-access-tiers.ps1 ...",
  "NativeKeyBackupUtc": "2026-05-28T00:00:00Z",
  "AccessTiers": [
    { "DisplayName": "社外秘", "KeyVaultKeyName": "credmanager-kek",
      "EntraGroupObjectId": "<YOUR_GROUP_OBJECT_ID>" }
  ]
}
```

このファイルを `setup-sharepoint.ps1` がそのまま読み込みます（2 本のスクリプトはこの JSON を介して疎結合）。

### 3.4 直接実行の例

```powershell
pwsh .\setup-access-tiers.ps1 `
    -SubscriptionId <YOUR_SUBSCRIPTION_ID> `
    -ResourceGroup <YOUR_RESOURCE_GROUP> `
    -VaultName <YOUR_VAULT_NAME> `
    -Location japaneast `
    -TiersJsonPath .\tiers-input.json
```

> 📷 [スクリーンショット] PowerShell — setup-access-tiers.ps1 実行と完了サマリ
> ナビ: 導入者 PC の PowerShell（pwsh）で上記コマンドを実行
> （ここに画像を貼る）

> 完了サマリには、保存したネイティブバックアップ blob の一覧と、**「同一サブスクリプション・同一地域の Key Vault にしか復元できない」** 旨が表示されます。blob は `accessTiers.json` とは別の安全な場所に保管してください。

---

## 4. SharePoint（setup-sharepoint.ps1）

サイト（未存在時）・`CredManagerItems` リスト・`CredManagerSetting` リスト・バージョン管理を冪等にプロビジョニングします。

### 4.1 パラメータ

| パラメータ | 必須 | 内容 |
|---|---|---|
| `-TenantId` | | 未指定ならサインイン後に Graph `/organization` から自動検出 |
| `-SharePointRootUrl` | | 未指定なら「ルート URL またはテナント名」を 1 度プロンプト。`https://contoso.sharepoint.com` でも `contoso` でも可 |
| `-SiteUrl` | | 未指定なら既定 `<root>/sites/CredManager` を提示して確認 |
| `-SiteTitle` | | サイト表示名。既定 `CredManager` |
| `-ListName` | | 既定 `CredManagerItems`（アプリの environment.json と一致させる） |
| `-ClientId` | | 未指定なら Graph で表示名 `CredManager` のアプリを検索 → 採用、無ければ入力。PnP 接続にも使用。既定 `eef1c3d3-3c89-442b-84f9-a3e48660a2de` |
| `-KeyVaultUri` | | 未指定ならプロンプト。Key Vault の自動作成はしない（[3 章](#3-azure-バックボーンsetup-access-tiersps1)が担当） |
| `-EnvironmentJsonOutputPath` | | **指定時のみ** environment.json を生成（シングルテナント上書き運用向け）。未指定ならゼロ設定運用で生成しない |
| `-AccessTiersJsonPath` | | 未指定ならスクリプト同階層の accessTiers.json を探索 |
| `-NonInteractive` | | 非対話実行用 |

### 4.2 実行する処理（順序）

1. `PnP.PowerShell` の確認・自動インストール（PS7+ は最新版、PS5.1 は 1.12.0）。
2. サインイン用 URL 決定 → `Connect-PnPOnline -Interactive -ClientId <id>`（別ウィンドウのブラウザ）。
3. テナント ID 自動検出（`Invoke-PnPGraphMethod organization`）。
4. サイト URL 既定提示・確認。
5. Client ID を Graph 検索 or 入力。
6. Key Vault URI をプロンプト（未指定時）。
7. サイト存在確認 → 無ければ **Communication Site を作成**（作成後の接続成立までリトライ）。
8. **`CredManagerItems` リスト**と列を冪等作成:
   - `Title`（表示名「名前」）/ `Description`（説明）/ `ConnectionInfo`（接続先）/ `AccountId`（アカウントID）/ `EncryptedPassword`（暗号化パスワード）/ `Iv`（初期化ベクトル）/ `WrappedKey`（ラップ済みキー）/ `MfaConfigs`（MFA設定）/ `GroupName`（グループ）/ `AccessTier`（アクセス区分・選択肢 `社外秘`/`管理部`/`4等級以上`・既定 `社外秘`・入力可）/ `AuditLog`（監査ログ）/ `IsDeleted`（削除済み・Boolean）
   - **バージョン管理を有効化**（`Set-PnPList -EnableVersioning $true`、誤削除・誤編集からの item 単位復旧手段）。
9. **`CredManagerSetting` リスト**と列を冪等作成:
   - `Title`（キー / 区分名）/ `EntryType`（選択肢 `Setting`/`AccessTier`）/ `SettingValue`（値）/ `KeyVaultKeyName`（Key Vault キー名）/ `EntraGroupId`（Entra グループ ID）
   - 行投入: `Setting` 行に `KeyVaultUri`、`accessTiers.json` の `NativeKeyBackupUtc` があれば `NativeKeyBackupUtc` 行、`AccessTier` 行を区分ごとに（`accessTiers.json` 由来）。
10. `-EnvironmentJsonOutputPath` 指定時のみ environment.json を生成。

### 4.3 直接実行の例

```powershell
pwsh .\setup-sharepoint.ps1 `
    -SiteUrl https://contoso.sharepoint.com/sites/CredManager `
    -ClientId eef1c3d3-3c89-442b-84f9-a3e48660a2de `
    -KeyVaultUri https://<YOUR_VAULT_NAME>.vault.azure.net/ `
    -AccessTiersJsonPath .\accessTiers.json
```

> 📷 [スクリーンショット] Web ブラウザ — PnP 対話型サインイン
> 想定 URL: 組織の SharePoint ルート（例 https://contoso.sharepoint.com）
> ナビ: スクリプト実行時に自動で開くブラウザで組織アカウントにサインイン
> （ここに画像を貼る）

> 📷 [スクリーンショット] SharePoint — CredManagerItems リスト
> 想定 URL: <SiteUrl>/Lists/CredManagerItems
> ナビ: 対象サイト → サイト コンテンツ → CredManagerItems
> （ここに画像を貼る）

---

## 5. アプリ配布・初回起動

### 5.1 ゼロ設定運用（推奨・マルチテナント）

利用者 PC には **`CredManager.exe` を配置するだけ**で動きます（`environment.json` 不要）。アプリは起動時に次のカスケードで設定を解決します（`App.OnStartup`）:

1. テナント ID: environment.json → 空ならサインイン後の検出値
2. Client ID: environment.json → 焼き込み既定 `eef1c3d3-...`
3. SharePoint サイト: environment.json → 空なら Graph で表示名 `CredManager` を検索
4. Key Vault URI: environment.json → `CredManagerSetting` の `KeyVaultUri` 設定行
5. 区分マッピング: ローカル `accessTiers.json` → `CredManagerSetting` の `AccessTier` 行

### 5.2 environment.json 上書き運用（シングルテナント）

環境固有値を事前配布したい場合、exe と同じフォルダに `environment.json` を置きます（固定 5 項目スキーマ）:

```json
{
  "TenantId": "<YOUR_TENANT_ID>",
  "ClientId": "eef1c3d3-3c89-442b-84f9-a3e48660a2de",
  "SharePointSiteUrl": "https://contoso.sharepoint.com/sites/CredManager",
  "SharePointListName": "CredManagerItems",
  "KeyVaultUri": "https://<YOUR_VAULT_NAME>.vault.azure.net/"
}
```

- `setup-sharepoint.ps1` を `-EnvironmentJsonOutputPath <path>` 付きで実行すると、この形式で自動生成できます。
- 同様に `accessTiers.json` を exe と同階層に置くと、区分マッピングをローカル優先で固定できます（`CredManagerSetting` より優先）。

> ⚠ `environment.json` と `accessTiers.json` は ITSN 固有のローカル設定のため、製品リポジトリには含めません（`.gitignore` 済み）。配布パッケージにのみ同梱します。

### 5.3 初回サインイン

> 📷 [スクリーンショット] CredManager アプリ — サインイン画面
> （ここに画像を貼る）

1. 起動するとサインイン画面が表示されます（サイレント取得を試行 → 不可なら「サインイン」ボタン）。
2. 組織アカウントでサインイン（ブラウザが開きます）。
3. サインイン画面には **「オフライン復旧モード...」** ボタンもあり、サインイン不要で `.cmkb` バックアップから読み取り専用復元ができます（[8 章](#8-運用break-glass-バックアップ--自動督促--復旧)）。

---

## 6. セットアップウィザード（簡易/詳細）

アプリ内ウィザードは GUI 入力から `setup-access-tiers.ps1` → `setup-sharepoint.ps1` を非対話で順に実行します（PowerShell コマンドを直接打つ必要がない）。

- 起動: 環境設定画面 → **「初回セットアップ ウィザード」**ボタン（実効サイト未解決の初回時のみ有効）。
- 実行エンジン: `pwsh.exe` を優先し、無ければ `powershell.exe` にフォールバック（`-NoProfile -ExecutionPolicy Bypass -File`）。出力は画面にリアルタイム表示。
- environment.json は **生成しません**（ゼロ設定運用前提）。

> 📷 [スクリーンショット] CredManager アプリ — セットアップウィザード（モード選択）
> （ここに画像を貼る）

### 6.1 ステップ構成

| # | ステップ | 簡易モード | 詳細モード |
|---|---|---|---|
| 1 | モード選択 | ✓ | ✓ |
| 2 | 概要 | ✓ | ✓ |
| 3 | 区分定義（DataGrid） | **スキップ** | ✓ |
| 4 | Azure 構成 | ✓ | ✓ |
| 5 | SharePoint 構成 | ✓ | ✓ |
| 6 | 確認 | ✓ | ✓ |
| 7 | 実行 | ✓ | ✓ |
| 8 | 管理者同意 | ✓ | ✓ |
| 9 | 完了（グループ メンバー追加案内） | ✓ | ✓ |

### 6.2 簡易モード（小規模・既定）

区分定義ステップをスキップし、1 区分を自動生成 + Azure 既定値をプリフィル:

- 区分: 表示名 `標準` / 鍵名 `credmanager-kek` / グループ名 `CredManager 利用者`
- Azure: リソースグループ `CredManager-RG` / Key Vault 名 `credmanager-<ランダム4桁hex>`（グローバル一意化） / リージョン `japaneast`

### 6.3 詳細モード

区分定義 DataGrid で複数区分を定義（表示名 / Key Vault キー名 / Entra グループ名 or 既存 ObjectId）。既定で `社外秘`（鍵 `credmanager-kek` / グループ `CredManager-Confidential`）が 1 件プリロード。

### 6.4 入力項目（Azure / SharePoint ステップ）

- Azure 構成: サブスクリプション ID / リソースグループ / Key Vault 名 / リージョン
- SharePoint 構成: サイト URL / サイト表示名 / リスト名
- Key Vault URI はウィザードが `https://<Vault名>.vault.azure.net/` として自動導出し SharePoint スクリプトへ渡します。

> 📷 [スクリーンショット] CredManager アプリ — ウィザード Azure 構成ステップ
> （ここに画像を貼る）

### 6.5 実行・完了

- 「実行する」で 2 本のスクリプトが順に走り、進捗ログが画面に表示されます。失敗時は「戻る」でステップを修正して再試行できます（冪等なので安全）。
- 成功すると自動で **管理者同意ステップ**に進みます。同意 URL をコピーしてブラウザで開きます。
- 完了ステップに、各区分の **Entra グループへメンバーを追加** する案内（グループ名 + ObjectId + 「Entra で開く」ボタン）が表示されます。

> 📷 [スクリーンショット] CredManager アプリ — ウィザード完了（メンバー追加案内）
> （ここに画像を貼る）

> 反映にはアプリの再起動が必要です。

---

## 7. 検証（診断 / Key Vault バックアップ状態）

### 7.1 セットアップ診断

環境設定画面 → 補助ナビゲーション → **「セットアップ診断」**。読み取り専用で次の 10 項目を順に判定し、NG 項目には修正導線（ウィザード / 管理者同意 URL / キー情報バックアップ）を提示します（`SetupDiagnosticService`）。

| # | 項目 | 主な判定内容 |
|---|---|---|
| 1 | サインイン | アクセストークン取得済みか |
| 2 | SharePoint サイト検出 | 構成済みサイト到達 or Graph 検索でヒット |
| 3 | CredManagerSetting リスト | 存在 + `KeyVaultUri` 設定行 + AccessTier 行 |
| 4 | CredManagerItems リスト | 存在・読み取り可 |
| 5 | Key Vault 到達性 | 代表鍵への wrap 成功（401/403/404 を区別） |
| 6 | 区分鍵の存在 | 全区分の鍵が Vault に存在するか |
| 7 | 鍵への暗号アクセス（RBAC） | アクセス可能区分で wrap/unwrap 通過 |
| 8 | Entra グループ／区分判定 | メンバーシップ判定が成功し、アクセス可能区分を解決 |
| 9 | 管理者同意 | Graph 呼出しが通っているかで間接判定 |
| 10 | キー情報バックアップ（B2） | `BreakGlassLastBackupUtc` が閾値 `BreakGlassBackupMaxAgeDays`（既定 30 日）以内か |

> 📷 [スクリーンショット] CredManager アプリ — セットアップ診断（チェックリスト）
> （ここに画像を貼る）

### 7.2 Key Vault バックアップ状態

環境設定画面 → 補助ナビゲーション → **「Key Vault バックアップ状態」**。サインインユーザーのトークンで Vault をライブ照会し、読み取り専用表示します（`KeyVaultStatusService`）。

- 許可モデル（**Purge Protection 有効/無効**。無効なら警告 + 有効化コマンド提示）
- soft-delete 保持日数 / RBAC 認可モード
- 各区分 KEK 鍵の存在・有効状態・作成日時
- `NativeKeyBackupUtc`（記録があれば）
- 照会できない項目は「確認不可」と表示（権限不足・通信失敗でもクラッシュしない）

> 📷 [スクリーンショット] CredManager アプリ — Key Vault バックアップ状態
> （ここに画像を貼る）

### 7.3 区分アクセスの動作確認

1. 既定区分のグループに所属するアカウントでサインインし、クレデンシャルの新規登録・パスワード表示（復号）ができることを確認。
2. 複数区分: ある区分のグループにのみ属するアカウントで、**属さない区分の項目は一覧に表示されない**（非表示で足切り）ことを確認。

> 区分の閲覧可否は Entra グループのメンバーシップ（`/me/checkMemberGroups`）で判定し、**アクセス権の無い区分の項目は一覧から除外**されます。件数・バッジ・グループ別カウントもアクセス可能な項目だけで一貫します。

---

## 8. 運用（break-glass バックアップ / 自動督促 / 復旧）

CredManager には Azure / M365 が **完全に失われた場合** の復旧手段（break-glass）が 2 系統あります。

### 8.1 系統 1: キー情報バックアップ（.cmkb / 顧客保有パスフレーズ）

Azure に一切依存せず復旧できる自己完結ファイル。資格情報そのものを顧客保有のパスフレーズで暗号化（Argon2id 鍵導出 + AES-256-GCM）。

- **取得**: 環境設定画面 → **「キー情報のバックアップ（機密）」**ボタン（Vault に対する **Owner ロール所持者のみ** 有効。ロールが無い／ARM 同意が無いと静かに無効化）。
  - 警告承諾 → パスフレーズ入力（2 回・最低 12 文字）→ カバレッジ確認 → `.cmkb` 保存（既定名 `credmanager-keybackup-YYYYMMDD.cmkb`）。
  - 完了時、`CredManagerSetting/BreakGlassLastBackupUtc` を更新し、`BreakGlassBackupHistory`（JSON 配列・最大 50 件）に 1 エントリ追記。
  - **ファイルとパスフレーズは別々の安全な場所に保管**。両方揃わないと復号不能、パスフレーズ紛失で永久に復号不能。

> 📷 [スクリーンショット] CredManager アプリ — キー情報のバックアップ（警告 / パスフレーズ）
> （ここに画像を貼る）

- **自動督促（B2）**: 起動時、Owner かつ前回バックアップから閾値（`BreakGlassBackupMaxAgeDays`、既定 30 日）超過 or 未取得なら督促ダイアログ（「今すぐ取得 / 後で」）。「後で」はそのセッション中のみ抑止。
- **復旧**: サインイン画面 → **「オフライン復旧モード...」**。`.cmkb` 選択 → パスフレーズ → 読み取り専用一覧表示（コピー可・パスワード表示/非表示）。完全オフラインで完結。

> 📷 [スクリーンショット] CredManager アプリ — オフライン復旧モード（読み取り専用一覧）
> （ここに画像を貼る）

### 8.2 系統 2: Key Vault ネイティブバックアップ（鍵の blob）

`setup-access-tiers.ps1` がセットアップ時に各 KEK の暗号化 blob を保存（`keyvault-native-backup-<キー名>-<YYYYMMDD>.blob`）。

- **制約**: **同一サブスクリプション・同一地域の Key Vault にしか復元できません**。テナント／サブスクリプション／地域をまたぐ災害は系統 1（.cmkb）を使用。
- 復元は `Restore-AzKeyVaultKey` を使用（本書のセットアップ範囲外）。

### 8.3 区分の追加・メンバー変更

- **メンバー追加/削除**: Entra グループ（同期グループならオンプレ AD）のメンバー変更で行う。反映に時間差あり。
- **区分の追加**: (1) Key Vault に新鍵作成 → (2) Entra グループ用意 → (3) 鍵単位スコープで `Key Vault Crypto User` 割当て → (4) `accessTiers.json`（または `CredManagerSetting` の AccessTier 行）に追記。`setup-access-tiers.ps1` を区分追加して再実行するのが簡単（冪等）。
- **鍵管理**: RBAC モードのため、鍵の作成・ローテーション・削除には別途 `Key Vault Crypto Officer` 等が必要（Owner 単独では鍵操作不可）。

---

## 9. トラブルシューティング

実運用で確認された事象と対処（`SESSION-LOG.md` の知見を反映）。

### 9.1 全鍵で 403「Key Vault へのアクセスに失敗」→ Vault が Access Policy モードに倒れている

- **症状**: アクセス権があるはずの区分で復号が失敗。アプリのエラーは「Key Vault へのアクセスに失敗（HTTP 403）。許可モデル等が変わった可能性。管理者に確認を」。
- **原因の代表例**: Key Vault の許可モデルが **RBAC → アクセスポリシー** に倒れている。アクセスポリシーには利用者が含まれないため全鍵が 403。**鍵スコープの RBAC ロール割当て自体は残っており、許可モデルを RBAC に戻すだけで即回復**（割当ての再作成は不要）。
- **確認**: ポータル → Key Vault → アクセス構成 → 許可モデルが「Azure ロールベースのアクセス制御」か。
  > 想定 URL: https://portal.azure.com/#browse/Microsoft.KeyVault%2Fvaults → 対象 Vault → 設定 → アクセス構成
- **復旧**: `Update-AzKeyVault -VaultName <vault> -ResourceGroupName <rg> -DisableRbacAuthorization $false`
- **再発防止**: 修正済みの `setup-access-tiers.ps1` は、purge protection 更新等の `Update-AzKeyVault` 呼出しに必ず `-DisableRbacAuthorization $false` を併記し、既存 Vault が Access Policy なら能動的に RBAC へ戻す。
- **注意（Az.KeyVault 6.x）**: 許可モデル操作のパラメータは **`-DisableRbacAuthorization`**（旧名 `-EnableRbacAuthorization` は削除済み）。一方、`Get-AzKeyVault` の戻り **プロパティ名は `EnableRbacAuthorization`**（入力と出力で名前が逆）。

### 9.2 「キー情報のバックアップ」「Key Vault バックアップ状態」が動かない／無効

- **原因**: アプリ登録に **Azure Service Management（ARM）の `user_impersonation`** 委任権限 + 管理者同意が無い（`AADSTS65001`）。
- **対処**: [2.2](#22-必要な-api-のアクセス許可委任)・[2.3](#23-管理者同意)。同意後はサイレントで ARM トークンが取れ、Owner ゲートが有効化。
- 環境設定ロード時の Owner 判定は **サイレント取得のみ**で行うため、未同意でもブラウザ popup は出ず、ボタンが静かに無効化されツールチップに理由が出る。

### 9.3 サインイン後に全項目が見えない／区分が表示されない

- **原因**: グループメンバーシップ判定（`/me/checkMemberGroups`）が拒否、またはユーザーがどの区分グループにも属していない。
- **対処**: アプリ登録に `GroupMember.Read.All`（または `Directory.Read.All`）委任 + 管理者同意があるか確認（**要確認**: 既定の `User.Read` で通る環境もある）。利用者を該当区分の Entra グループに追加。

### 9.4 トークン失効「セッションが切れました」

- **症状**: 稼働中に MS365 トークン（特にリフレッシュトークン）が失効し、Key Vault アクセスが 401/UI 要求に。
- **対処**: メインウィンドウ右上の **セッション状態ピル**（緑=接続済み / 赤=再ログインが必要）をクリックして対話的再認証。成功すれば再起動なしで復旧（MSAL は scope ごとにトークンをキャッシュ）。

### 9.5 サインインで個人 MSA が選ばれてしまう（管理者の Az 操作時）

- **症状**: `Connect-AzAccount` が `live.com#<user>` の個人 MSA を選び、サブスクリプションにアクセスできない。
- **対処**: WAM を無効化（Az バージョン依存）するか、`Connect-AzAccount -UseDeviceAuthentication` の **デバイスコードフロー**（15 分以内に完了）で、ブラウザ上で組織アカウントを明示選択。

### 9.6 PowerShell モジュール / 実行環境

- スクリプトはモジュールを `CurrentUser` スコープで自動インストール。失敗時は手動: `Install-Module Az.Accounts,Az.Resources,Az.KeyVault,Microsoft.Graph.Authentication,Microsoft.Graph.Groups -Scope CurrentUser` / `Install-Module PnP.PowerShell -Scope CurrentUser`（PS5.1 は `-RequiredVersion 1.12.0`）。
- 企業プロキシで PSGallery がブロックされる場合は TLS 1.2 / プロキシ設定を確認。

### 9.7 日本語を含む PowerShell スクリプトの文字化け

- Windows PowerShell 5.1 は BOM なし UTF-8 の日本語を誤解釈することがある。スクリプトは **UTF-8 with BOM** で保存する（同梱物は対応済み）。

---

## 付録: 主要な既定値・識別子

| 項目 | 値 |
|---|---|
| 既定 Client ID（マルチテナント共有アプリ） | `eef1c3d3-3c89-442b-84f9-a3e48660a2de` |
| 管理者同意 URL 形式 | `https://login.microsoftonline.com/organizations/adminconsent?client_id=<id>&redirect_uri=http%3A%2F%2Flocalhost` |
| リダイレクト URI | `http://localhost` |
| 既定リスト名 | `CredManagerItems` / `CredManagerSetting` |
| サインイン Graph スコープ | `User.Read`, `Sites.ReadWrite.All` |
| Key Vault スコープ | `https://vault.azure.net/.default`（`user_impersonation`） |
| ARM スコープ | `https://management.azure.com/.default`（`user_impersonation`） |
| Owner 組み込みロール定義 ID | `8e3af657-a8ff-443c-a75c-2fe8c4bcb635` |
| 区分鍵に割当てる RBAC ロール | `Key Vault Crypto User`（鍵単位スコープ） |
| バックアップ閾値 設定キー | `BreakGlassBackupMaxAgeDays`（既定 30） |
| 最終バックアップ記録キー | `BreakGlassLastBackupUtc` / 履歴 `BreakGlassBackupHistory`（最大 50 件） |
| ネイティブバックアップ記録キー | `NativeKeyBackupUtc` |

---

## 要確認 / TODO 一覧（コードから断定できなかった箇所）

- **[要確認] グループ判定の API 権限**: アプリは `/me/checkMemberGroups` を `User.Read` 文脈で呼ぶ。テナントによっては `GroupMember.Read.All` または `Directory.Read.All` の委任同意が必要。実テナントのアプリ登録で必要権限を確定する（[2.2](#22-必要な-api-のアクセス許可委任) / [9.3](#93-サインイン後に全項目が見えない区分が表示されない)）。
- **[TODO] Azure ポータルのディープリンク URL**: 各スクショの「想定 URL」はベスト努力。実環境で正確な deep link を貼り直す（ナビ階層は確定記載済み）。
- **[TODO] スクリーンショット差し込み**: 📷 プレースホルダ箇所に実画面を貼る（Web/ポータル系・アプリ系）。
- **[要確認] ネイティブバックアップ blob の復元手順**: `Restore-AzKeyVaultKey` の具体手順は本書のセットアップ範囲外。災害復旧 runbook 側で別途整備。
- **[要確認] Sites.Selected による権限最小化**: 旧ガイドが触れていた `Sites.Selected`（対象サイトのみに権限を絞る）案は本実装では未検証。採用する場合は別途検証。
