# 機能設計書 197-SAML設定

## 概要

本ドキュメントは、ChatwootにおけるSAML設定機能の設計を記載したものである。この機能はEnterprise版の機能であり、SAML（Security Assertion Markup Language）を使用したシングルサインオン（SSO）を設定・管理する。

### 本機能の処理概要

**業務上の目的・背景**：エンタープライズ環境では、社内の認証基盤（IdP: Identity Provider）と統合したシングルサインオンが求められる。SAML設定機能により、Azure AD、Okta、OneLoginなどの主要なIdPとの連携が可能となり、ユーザーは社内の認証情報でChatwootにログインできる。これにより、パスワード管理の一元化、セキュリティ強化、ユーザー体験の向上が実現される。

**機能の利用シーン**：管理者がSAML SSOを設定する際に使用する。IdPからのメタデータ（SSO URL、証明書、Entity ID）を登録し、ロールマッピングを設定することで、ユーザーのロールを自動的に割り当てることができる。

**主要な処理内容**：
1. SAML設定の作成・表示・更新・削除（CRUD）
2. IdPメタデータ（SSO URL、証明書、Entity ID）の管理
3. Service Provider Entity IDの自動生成
4. ロールマッピングの設定
5. 証明書の検証

**関連システム・外部連携**：外部IdP（Azure AD、Okta、OneLogin等）とのSAML連携。

**権限による制御**：管理者（Administrator）ロールのみアクセス可能。samlフィーチャーフラグが有効なアカウントのみ利用可能。ENABLE_SAML_SSO_LOGIN環境変数が有効である必要がある。

## 関連画面

| 画面No | 画面名 | 関連種別 | 関連する操作・処理 |
|--------|--------|----------|------------------|
| 79 | セキュリティ設定画面 | 主画面 | SAML設定の管理 |

## 機能種別

CRUD操作（設定管理）

## 入力仕様

### 入力パラメータ

| パラメータ名 | 型 | 必須 | 説明 | バリデーション |
|-------------|-----|-----|------|---------------|
| saml_settings[sso_url] | String | Yes | IdPのSSO URL | 必須 |
| saml_settings[certificate] | Text | Yes | IdPの公開証明書（X.509形式） | 必須、有効なX.509証明書 |
| saml_settings[idp_entity_id] | String | Yes | IdPのEntity ID | 必須 |
| saml_settings[sp_entity_id] | String | No | Service ProviderのEntity ID | 未指定時は自動生成 |
| saml_settings[role_mappings] | Hash | No | IdPグループとChatwootロールのマッピング | - |

### 入力データソース

- 管理画面からのフォーム入力

## 出力仕様

### 出力データ

| 項目名 | 型 | 説明 |
|--------|-----|------|
| id | Integer | SAML設定ID |
| sso_url | String | IdPのSSO URL |
| certificate | Text | IdPの公開証明書 |
| idp_entity_id | String | IdPのEntity ID |
| sp_entity_id | String | Service ProviderのEntity ID |
| role_mappings | JSON | ロールマッピング設定 |
| created_at | DateTime | 作成日時 |
| updated_at | DateTime | 更新日時 |

### 出力先

- JSON形式でAPIレスポンスとして返却

## 処理フロー

### 処理シーケンス

```
1. リクエスト受信
   ├─ ENABLE_SAML_SSO_LOGIN環境変数チェック
   ├─ samlフィーチャーフラグチェック
   └─ 認可チェック（AccountSamlSettingsPolicy）
2. アクション実行
   ├─ show: 現在の設定を返却
   ├─ create: 新規設定を作成
   ├─ update: 既存設定を更新
   └─ destroy: 設定を削除
3. 作成/更新時の処理
   ├─ sp_entity_idの自動生成（未指定時）
   ├─ 証明書のX.509形式検証
   └─ アカウントユーザーのproviderを更新
4. 削除時の処理
   └─ アカウントユーザーのproviderをemailにリセット
```

### フローチャート

```mermaid
flowchart TD
    A[リクエスト受信] --> B{ENABLE_SAML_SSO_LOGIN?}
    B -->|No| C[403 SSO not enabled]
    B -->|Yes| D{saml機能有効?}
    D -->|No| E[403 Feature not enabled]
    D -->|Yes| F{認可OK?}
    F -->|No| G[403 Forbidden]
    F -->|Yes| H{アクション?}
    H -->|show| I[設定返却]
    H -->|create| J[設定作成]
    H -->|update| K[設定更新]
    H -->|destroy| L[設定削除]
    J --> M[sp_entity_id生成]
    M --> N[証明書検証]
    N -->|OK| O[保存]
    N -->|NG| P[422 Invalid certificate]
    O --> Q[ユーザーprovider更新]
    L --> R[ユーザーproviderリセット]
```

## ビジネスルール

### 業務ルール

| ルールNo | ルール名 | 内容 | 適用条件 |
|---------|---------|------|---------|
| BR-197-01 | 環境変数必須 | ENABLE_SAML_SSO_LOGINが'true'である必要がある | 常時 |
| BR-197-02 | フィーチャーフラグ必須 | saml機能が有効である必要がある | 常時 |
| BR-197-03 | 管理者限定 | Administrator権限のみアクセス可能 | 常時 |
| BR-197-04 | 証明書検証 | X.509形式の有効な証明書のみ受け付ける | 作成/更新時 |
| BR-197-05 | SP Entity ID自動生成 | 未指定時は`{FRONTEND_URL}/saml/sp/{account_id}`を自動設定 | 作成時 |
| BR-197-06 | Provider自動更新 | SAML設定作成時にアカウントユーザーのproviderを'saml'に更新 | 作成時 |
| BR-197-07 | Providerリセット | SAML設定削除時にアカウントユーザーのproviderを'email'にリセット | 削除時 |

### 計算ロジック

**SP Entity ID自動生成**:
```ruby
def set_sp_entity_id
  base_url = GlobalConfigService.load('FRONTEND_URL', 'http://localhost:3000')
  self.sp_entity_id = "#{base_url}/saml/sp/#{account_id}"
end
```

**証明書フィンガープリント計算**:
```ruby
def certificate_fingerprint
  cert = OpenSSL::X509::Certificate.new(certificate)
  OpenSSL::Digest::SHA1.new(cert.to_der).hexdigest.upcase.gsub(/(.{2})(?=.)/, '\1:')
end
```

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

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

| 操作 | 対象テーブル | 操作種別 | 概要 |
|-----|-------------|---------|------|
| 設定表示 | account_saml_settings | SELECT | 現在の設定を取得 |
| 設定作成 | account_saml_settings | INSERT | 新規設定を作成 |
| 設定更新 | account_saml_settings | UPDATE | 既存設定を更新 |
| 設定削除 | account_saml_settings | DELETE | 設定を削除 |
| Provider更新 | users | UPDATE | 作成/削除時にproviderカラムを更新（Job経由） |

### テーブル別操作詳細

#### account_saml_settings

| 操作 | 項目（カラム名） | 更新値・取得条件 | 備考 |
|-----|-----------------|-----------------|------|
| INSERT | sso_url | リクエストパラメータ | 必須 |
| INSERT | certificate | リクエストパラメータ | 必須、X.509検証 |
| INSERT | idp_entity_id | リクエストパラメータ | 必須 |
| INSERT | sp_entity_id | 自動生成または指定値 | - |
| INSERT | role_mappings | リクエストパラメータ | JSON形式 |

## エラー処理

### エラーケース一覧

| エラーコード | エラー種別 | 発生条件 | 対処方法 |
|------------|----------|---------|---------|
| 403 | Forbidden | ENABLE_SAML_SSO_LOGINが無効 | エラーメッセージ表示 |
| 403 | Forbidden | saml機能が無効 | エラーメッセージ表示 |
| 403 | Forbidden | 管理者権限がない | エラーメッセージ表示 |
| 422 | Unprocessable Entity | 証明書が無効 | 証明書エラーメッセージ表示 |

### リトライ仕様

なし

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

- 設定の作成・更新・削除は単一トランザクションで実行
- Provider更新ジョブは非同期で実行（after_create_commit/after_destroy_commit）

## パフォーマンス要件

- 証明書検証はOpenSSLを使用して高速に実行

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

- 管理者権限のみアクセス可能
- フィーチャーフラグによる機能制御
- 証明書はX.509形式を検証
- SAML認証はセキュアな通信経路で実行

## 備考

- この機能はEnterprise版限定
- SAML設定後、ユーザーはSAML認証でログインするよう自動的に切り替わる
- ロールマッピングによりIdPのグループ情報に基づいてChatwootのロールを自動設定可能

---

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

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

### 推奨読解順序

#### Step 1: コントローラーを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 1-1 | saml_settings_controller.rb | `enterprise/app/controllers/api/v1/accounts/saml_settings_controller.rb` | SAML設定APIのエンドポイント |

**主要処理フロー**:
1. **2行目**: `before_action :check_saml_sso_enabled` - 環境変数チェック
2. **3行目**: `before_action :check_saml_feature_enabled` - フィーチャーフラグチェック
3. **4行目**: `before_action :check_authorization` - 認可チェック
4. **5行目**: `before_action :set_saml_settings` - 設定オブジェクトの取得/生成
5. **7行目**: `show`アクション - 設定表示
6. **9-16行目**: `create`アクション - 新規作成
7. **18-24行目**: `update`アクション - 更新
8. **26-29行目**: `destroy`アクション - 削除

#### Step 2: モデルを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 2-1 | account_saml_settings.rb | `enterprise/app/models/account_saml_settings.rb` | SAML設定モデル |

**主要処理フロー**:
1. **22-25行目**: バリデーション設定
2. **26行目**: 証明書のカスタムバリデーション
3. **28行目**: `before_validation :set_sp_entity_id` - SP Entity ID自動生成
4. **30行目**: `after_create_commit :update_account_users_provider` - Provider更新
5. **31行目**: `after_destroy_commit :reset_account_users_provider` - Providerリセット
6. **33-35行目**: `saml_enabled?`メソッド
7. **37-47行目**: `certificate_fingerprint`メソッド
8. **51-54行目**: `set_sp_entity_id`メソッド
9. **72-78行目**: `certificate_must_be_valid_x509`バリデーション

#### Step 3: ユーザービルダーを理解する

| 順序 | ファイル | パス | 読解ポイント |
|-----|---------|------|-------------|
| 3-1 | saml_user_builder.rb | `enterprise/app/builders/saml_user_builder.rb` | SAMLユーザー作成ロジック |

**主要処理フロー**:
1. **8-12行目**: `perform`メソッド - ユーザー検索/作成とアカウント追加
2. **16-26行目**: `find_or_create_user`メソッド - 既存ユーザー検索または新規作成
3. **41-54行目**: `create_user`メソッド - 新規ユーザー作成
4. **56-71行目**: `add_user_to_account`メソッド - アカウントへのユーザー追加
5. **73-82行目**: `apply_role_mappings`メソッド - ロールマッピングの適用

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

```
SamlSettingsController
    │
    ├─ check_saml_sso_enabled (before_action)
    │      └─ GlobalConfigService.load('ENABLE_SAML_SSO_LOGIN')
    │
    ├─ check_saml_feature_enabled (before_action)
    │      └─ Current.account.feature_enabled?('saml')
    │
    ├─ check_authorization (before_action)
    │      └─ authorize(AccountSamlSettings)
    │
    ├─ set_saml_settings (before_action)
    │      └─ Current.account.saml_settings || build_saml_settings
    │
    ├─ create
    │      └─ AccountSamlSettings#save
    │             └─ after_create_commit: update_account_users_provider
    │                    └─ Saml::UpdateAccountUsersProviderJob
    │
    └─ destroy
           └─ AccountSamlSettings#destroy!
                  └─ after_destroy_commit: reset_account_users_provider
                         └─ Saml::UpdateAccountUsersProviderJob
```

### データフロー図

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

sso_url            ───▶ SamlSettingsController
certificate        ───▶     │
idp_entity_id      ───▶     ▼
sp_entity_id       ───▶ before_action checks
role_mappings      ───▶     │
                            ▼
                    create/update/destroy
                            │
                            ▼
                    AccountSamlSettings
                            │
                    ┌───────┴───────┐
                    ▼               ▼
              set_sp_entity_id  certificate_validation
                    │               │
                    └───────┬───────┘
                            ▼
                         save
                            │
                            ▼
                    after_commit
                            │
                            ▼
                    UpdateAccountUsersProviderJob
                            │
                            ▼
                    { saml_settings }
```

### 関連ファイル一覧

| ファイル | パス | 種別 | 役割 |
|---------|------|------|------|
| saml_settings_controller.rb | `enterprise/app/controllers/api/v1/accounts/saml_settings_controller.rb` | ソース | SAML設定APIコントローラー |
| account_saml_settings.rb | `enterprise/app/models/account_saml_settings.rb` | ソース | SAML設定モデル |
| saml_user_builder.rb | `enterprise/app/builders/saml_user_builder.rb` | ソース | SAMLユーザー作成ビルダー |
| account_saml_settings_policy.rb | `enterprise/app/policies/account_saml_settings_policy.rb` | ソース | 認可ポリシー |
| routes.rb | `config/routes.rb` | 設定 | ルーティング定義（85行目） |
