# セキュリティ設計書

## 概要

本ドキュメントは、Chatwootアプリケーションのセキュリティ設計について記載する。認証・認可、通信セキュリティ、データ保護、レート制限、監査ログなどの観点からセキュリティ対策を網羅的に説明する。

## 認証設計

### 認証方式

Chatwootは以下の複数の認証方式をサポートしている。

| 認証方式 | 説明 | 実装 |
| --- | --- | --- |
| メール/パスワード認証 | Devise + DeviseTokenAuthによるトークンベース認証 | `devise :database_authenticatable` |
| OAuth認証 (Google) | OmniAuthによるGoogle OAuth2連携 | `omniauth :google_oauth2` |
| SAML認証 | OmniAuthによるSAML連携 | `omniauth :saml` |
| APIアクセストークン | 永続的なAPIアクセストークン | `AccessToken`モデル |
| MFA (二要素認証) | TOTP + バックアップコード | `two_factor_authenticatable` |

#### パスワード要件

`config/initializers/secure_password.rb`において以下のパスワード要件が設定されている。

| 項目 | 設定値 |
| --- | --- |
| 最小文字数 | 6文字 |
| 最大文字数 | 128文字 |
| 大文字必須数 | 1文字以上 |
| 小文字必須数 | 1文字以上 |
| 数字必須数 | 1文字以上 |
| 特殊文字必須数 | 1文字以上 |
| ハッシュアルゴリズム | bcrypt (stretches: 11) |

### セッション管理

| 項目 | 設定値 | 備考 |
| --- | --- | --- |
| セッションストア | cookie_store | `config/initializers/session_store.rb` |
| セッションキー | `_chatwoot_session` | Cookie名 |
| SameSite属性 | lax | CSRF対策 |
| トークン有効期限 | 2ヶ月 | DeviseTokenAuth設定 |
| 同時デバイス数上限 | 25 | 超過時は古いトークンを削除 |
| サインアウト時のRemember Me無効化 | 有効 | `expire_all_remember_me_on_sign_out = true` |
| パスワードリセット有効期限 | 6時間 | `reset_password_within = 6.hours` |
| パスワード変更時のトークン無効化 | 有効 | `remove_tokens_after_password_reset = true` |

## 認可設計

### 権限体系

Chatwootは`AccountUser`モデルを通じてアカウント単位のロールベースアクセス制御(RBAC)を実装している。

| ロール | 権限 | 説明 |
| --- | --- | --- |
| administrator | 管理者権限 | アカウント設定、ユーザー管理、全リソースへのフルアクセス |
| agent | エージェント権限 | 割り当てられた受信トレイ・会話への参照・操作権限 |
| AgentBot | Bot権限 | 限定されたAPIエンドポイントへのアクセス（会話操作等） |

### アクセス制御

Punditポリシーベースの認可システムを採用している。

#### ポリシー構造

```
app/policies/
├── application_policy.rb      # 基底ポリシー
├── account_policy.rb          # アカウント操作権限
├── conversation_policy.rb     # 会話アクセス権限
├── inbox_policy.rb            # 受信トレイ権限
├── user_policy.rb             # ユーザー管理権限
└── ...
```

#### 主要ポリシー例

**AccountPolicy:**
- `show?`: administrator または agent
- `update?`: administrator のみ
- `subscription?`, `checkout?`: administrator のみ

**ConversationPolicy:**
- `index?`: 全ユーザー
- `show?`: administrator, AgentBot, または該当受信トレイ/チームへのアクセス権を持つエージェント
- `destroy?`: administrator のみ

**InboxPolicy:**
- `index?`: 全ユーザー
- `create?`, `update?`, `destroy?`: administrator のみ
- `show?`: 割り当てられた受信トレイのみ（AgentBotは全て参照可）

#### AgentBotアクセス制限

`AccessTokenAuthHelper`にてBotがアクセス可能なエンドポイントを明示的に制限している。

```ruby
BOT_ACCESSIBLE_ENDPOINTS = {
  'api/v1/accounts/conversations' => %w[toggle_status toggle_priority create update custom_attributes],
  'api/v1/accounts/conversations/messages' => ['create'],
  'api/v1/accounts/conversations/assignments' => ['create']
}
```

## 通信セキュリティ

| 項目 | 対策 |
| --- | --- |
| HTTPS | アプリケーションレベルでは未強制（インフラ層で対応想定） |
| HSTS | 未設定（インフラ層で対応想定） |
| CSP | コメントアウト状態（`config/initializers/content_security_policy.rb`） |
| CORS | 設定あり（`config/initializers/cors.rb`） |
| Permissions Policy | コメントアウト状態 |

### CORS設定

```ruby
# 常に許可
resource '/packs/*', headers: :any, methods: [:get, :options]
resource '/audio/*', headers: :any, methods: [:get, :options]
resource '/public/api/*', headers: :any, methods: :any

# 条件付き（開発環境または CW_API_ONLY_SERVER=true）
resource '*', headers: :any, methods: :any, expose: %w[access-token client uid expiry]

# 条件付き（ENABLE_API_CORS=true）
resource '/api/*', headers: :any, methods: :any, expose: %w[access-token client uid expiry]
```

## データセキュリティ

### 暗号化

| 対象 | 暗号化方式 |
| --- | --- |
| パスワード | bcrypt (cost factor: 11) |
| OTPシークレット | Rails暗号化（deterministic） |
| OTPバックアップコード | Rails暗号化 |
| メールチャネルパスワード (IMAP/SMTP) | Rails暗号化（条件付き） |
| Twilio認証トークン | Rails暗号化（条件付き） |
| その他チャネル認証情報 | Rails暗号化（条件付き） |

注: チャネル認証情報の暗号化は`Chatwoot.encryption_configured?`がtrueの場合のみ有効。

### 機密情報管理

#### ログフィルタリング

`config/initializers/filter_parameter_logging.rb`にて以下のパラメータをログから除外している。

- password, secret, _key, auth, crypt, salt
- certificate, otp, access, private, protected, ssn
- otp_secret, otp_code, backup_code, mfa_token, otp_backup_codes
- token（website_token以外）

## 入出力対策

| 脅威 | 対策 |
| --- | --- |
| XSS | Railsデフォルトのエスケープ機構（ERB自動エスケープ）、html_safe/rawの使用なし |
| SQLインジェクション | Active RecordのパラメータバインディングおよびStrong Parameters |
| CSRF | DeviseTokenAuth使用によりトークンベース認証、セッションのSameSite=lax設定 |

### CSRF対策の注意点

`ApplicationController`にて`skip_before_action :verify_authenticity_token`が設定されており、CSRF保護は**無効化**されている。これはAPIサーバーとしての運用を想定しており、トークンベース認証によりCSRFリスクを軽減している。

### Strong Parameters

全コントローラーでStrong Parametersによる入力バリデーションを実施している。

例: `Api::V1::AccountsController`
```ruby
def account_params
  params.permit(:account_name, :email, :name, :password, :locale, :domain, :support_email, :user_full_name)
end
```

## レート制限 (Rack::Attack)

`config/initializers/rack_attack.rb`にて包括的なレート制限を実装している。

### 全般

| 項目 | 制限 |
| --- | --- |
| 全リクエスト/IP | 3000リクエスト/分（環境変数で変更可） |
| 有効環境 | 本番環境のみ（ENABLE_RACK_ATTACK=trueがデフォルト） |

### 認証関連

| エンドポイント | 制限 |
| --- | --- |
| Super Admin ログイン (IP) | 5回/5分 |
| Super Admin ログイン (Email) | 5回/15分 |
| 通常ログイン (IP) | 5回/5分（MFA検証除く） |
| 通常ログイン (Email) | 10回/15分（MFA検証除く） |
| パスワードリセット (IP) | 5回/30分 |
| パスワードリセット (Email) | 5回/1時間 |
| 確認メール再送 (IP) | 5回/30分 |
| MFA検証 (IP) | 5回/分 |
| MFAログイン (IP) | 10回/分 |
| MFAログイン (Token) | 10回/分 |
| アカウント作成 (IP) | 5回/30分 |

### Widget API

| エンドポイント | 制限 |
| --- | --- |
| 会話作成 | 6回/12時間 |
| コンタクト更新 | 60回/1時間 |
| Widget表示（新規セッション） | 5回/1時間 |

### アプリケーションAPI

| エンドポイント | 制限 |
| --- | --- |
| トランスクリプト取得 | 30回/1時間/アカウント |
| ファイルアップロード | 60回/1時間/アカウント |
| コンタクト検索 | 100回/分/アカウント |
| レポートAPI（ユーザー別） | 100回/分/ユーザー |
| レポートAPI（アカウント別） | 1000回/分/アカウント |

### セーフリスト

- localhost (127.0.0.1, ::1)
- RACK_ATTACK_ALLOWED_IPS環境変数で指定されたIP
- /health エンドポイント

## 監査ログ

Enterprise Editionでは`audited` gemを使用した監査ログ機能を提供している。

### 設定

```ruby
# config/initializers/audited.rb
Audited.config do |config|
  config.audit_class = 'Enterprise::AuditLog'
end
```

### 監査対象

| モデル | 監査対象フィールド | トリガー |
| --- | --- | --- |
| Account | updated_at以外の全フィールド | update |
| AccountUser | availability, role, account_id, inviter_id, user_id | create, update |
| User | availability, display_name, email, name | 手動ログ（sign_in/sign_out） |
| Inbox | 設定による | create, update |
| Team | 設定による | create, update |
| Webhook | 設定による | create, update |
| Conversation | 設定による | create, update |
| AutomationRule | 設定による | create, update |
| Macro | 設定による | create, update |

### ログ種別

| ログ種別 | 記録内容 | 保持期間 |
| --- | --- | --- |
| 監査ログ (audits) | action, audited_changes, remote_address, request_uuid, username | 未指定（DBに永続化） |
| Rack::Attackブロックログ | IP, パス, ユーザー識別子, アカウントID, メソッド, UA | アプリケーションログに出力 |

## 備考

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

1. **CSPの未設定**: Content Security Policyがコメントアウトされており、XSS攻撃への追加的な防御が未実装。本番環境では有効化を推奨。

2. **CSRF保護の無効化**: APIサーバーとしての設計上CSRFトークン検証は無効化されているが、トークンベース認証により保護されている。

3. **暗号化の条件付き有効化**: チャネル認証情報の暗号化は`Chatwoot.encryption_configured?`に依存しており、暗号化キーの設定が必須。

4. **CORS設定**: 開発環境および`CW_API_ONLY_SERVER=true`の場合、全オリジンからのアクセスが許可される。本番環境では適切な制限を設定すること。

5. **Action Cable**: `disable_request_forgery_protection = true`が設定されており、WebSocket接続時のCSRF検証が無効化されている。

6. **OmniAuth State検証**: Google OAuth2で`provider_ignores_state: true`が設定されており、state検証が無効化されている。
