# Momentry API Key 管理系統設計 | 項目 | 內容 | |------|------| | 版本 | V1.2 | | 日期 | 2026-03-21 | | 狀態 | 開發中 | --- ## 1. 概述 ### 1.1 目標 建立安全的 API Key 管理機制,支援: - 多類型 API Key(系統、用戶、服務) - 自動過期與輪換 - 異常使用偵測 - 強制更新機制 - 完整審計日誌 - Gitea Token 整合 - n8n API Key 整合 ### 1.2 設計原則 | 原則 | 說明 | |------|------| | 最小權限 | 每個 Key 僅授予必要權限 | | 定期輪換 | 自動過期強制更新 | | 追蹤可審 | 所有操作都有日誌 | | 分離儲存 | Key 與使用者資料分離 | --- ## 2. API Key 類型 ### 2.1 Key 類型矩陣 | 類型 | 前綴 | 用途 | 預設有效期 | 輪換方式 | |------|------|------|------------|----------| | `system` | `msys_` | 系統內部服務 | 365 天 | 手動 | | `user` | `muser_` | 個人用戶 | 90 天 | 自動 | | `service` | `msvc_` | 服務間通訊 | 180 天 | 自動 | | `integration` | `mint_` | 第三方整合 | 30 天 | 強制更新 | | `emergency` | `memg_` | 緊急存取 | 24 小時 | 一次性 | ### 2.2 Key 格式 ``` {prefix}{uuid_v4}_{timestamp}_{checksum} ``` **範例:** ``` msys_a1b2c3d4-e5f6-7890-abcd-ef1234567890_1710998400_sha256 ``` --- ## 3. 資料庫 Schema ### 3.1 api_keys 表 ```sql CREATE TABLE api_keys ( id BIGSERIAL PRIMARY KEY, key_id VARCHAR(64) UNIQUE NOT NULL, -- 公開 Key ID key_hash VARCHAR(128) NOT NULL, -- SHA256 哈希 key_prefix VARCHAR(8) NOT NULL, -- Key 前綴 name VARCHAR(128) NOT NULL, -- Key 名稱 key_type VARCHAR(32) NOT NULL, -- system/user/service/integration/emergency user_id BIGINT, -- 關聯用戶 (nullable for system) service_name VARCHAR(64), -- 服務名稱 (for service keys) permissions JSONB NOT NULL DEFAULT '[]', -- 權限列表 expires_at TIMESTAMP, -- 過期時間 last_used_at TIMESTAMP, -- 最後使用時間 last_used_ip VARCHAR(45), -- 最後使用 IP usage_count BIGINT DEFAULT 0, -- 使用次數 status VARCHAR(16) DEFAULT 'active', -- active/suspended/expired/revoked rotation_required BOOLEAN DEFAULT FALSE, -- 強制輪換標記 rotation_reason VARCHAR(256), -- 輪換原因 created_at TIMESTAMP DEFAULT NOW(), updated_at TIMESTAMP DEFAULT NOW() ); CREATE INDEX idx_api_keys_key_id ON api_keys(key_id); CREATE INDEX idx_api_keys_user_id ON api_keys(user_id); CREATE INDEX idx_api_keys_type ON api_keys(key_type); CREATE INDEX idx_api_keys_status ON api_keys(status); CREATE INDEX idx_api_keys_expires ON api_keys(expires_at); ``` ### 3.2 api_key_audit_log 表 ```sql CREATE TABLE api_key_audit_log ( id BIGSERIAL PRIMARY KEY, key_id VARCHAR(64) NOT NULL, action VARCHAR(32) NOT NULL, -- created/used/rotated/revoked/expired/suspended actor VARCHAR(64), -- 操作者 (user_id or 'system') ip_address VARCHAR(45), user_agent VARCHAR(512), request_path VARCHAR(256), response_code INTEGER, details JSONB, created_at TIMESTAMP DEFAULT NOW() ); CREATE INDEX idx_audit_key_id ON api_key_audit_log(key_id); CREATE INDEX idx_audit_action ON api_key_audit_log(action); CREATE INDEX idx_audit_created ON api_key_audit_log(created_at); ``` ### 3.3 api_key_rotation_log 表 ```sql CREATE TABLE api_key_rotation_log ( id BIGSERIAL PRIMARY KEY, key_id VARCHAR(64) NOT NULL, old_key_id VARCHAR(64), new_key_id VARCHAR(64), rotation_type VARCHAR(32) NOT NULL, -- scheduled/manual/forced/emergency reason VARCHAR(256), triggered_by VARCHAR(64), -- system/user/scheduler grace_period_end TIMESTAMP, -- 寬限期結束時間 created_at TIMESTAMP DEFAULT NOW() ); ``` --- ## 4. API Key 狀態機 ``` ┌──────────────┐ │ created │ └──────┬───────┘ │ ▼ ┌────────────────────┐ │ active │◄─────────────┐ └─────────┬──────────┘ │ │ │ ┌─────────────┼─────────────┐ │ │ │ │ │ ▼ ▼ ▼ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ suspended │ │ expired │ │ revoked │─────┘ └──────────┘ └──────────┘ └──────────┘ ``` ### 狀態轉換規則 | 從 | 到 | 觸發條件 | |----|----|----------| | created | active | 啟用 Key | | active | suspended | 異常使用偵測 | | active | expired | 達到過期時間 | | active | revoked | 手動撤銷 | | suspended | active | 解除鎖定 | | suspended | revoked | 確認異常 | | expired | active | 重新啟用 | --- ## 5. 異常偵測機制 ### 5.1 異常指標 | 指標 | 閾值 | 處置 | |------|------|------| | 每分鐘請求數 | > 1000 | 警告 | | 每小時請求數 | > 10000 | 鎖定 | | 錯誤率 | > 50% | 警告 | | 不同 IP 數 | > 5/小時 | 警告 | | 非工作時間使用 | 深夜請求 | 警告 | | 異常模式 | 暴力破解 | 鎖定 | ### 5.2 異常處理流程 ``` 異常偵測 │ ▼ ┌─────────┐ │ 分析 │──→ 排除正常流量 └────┬────┘ │ ▼ ┌─────────┐ │ 評估 │──→ 輕微 → 警告 └────┬────┘ │ ▼ ┌─────────┐ │ 處置 │──→ 嚴重 → 鎖定 + 輪換 └─────────┘ ``` --- ## 6. 強制更新機制 ### 6.1 觸發條件 | 條件 | 嚴重性 | 動作 | |------|--------|------| | 疑似洩露 | 高 | 立即停用 + 強制輪換 | | 異常使用 | 中 | 警告 + 建議輪換 | | 計劃性維護 | 低 | 通知 + 排程輪換 | | 政策要求 | 高 | 強制輪換 | | 過期 | 低 | 停用 + 通知 | ### 6.2 強制輪換流程 ``` 1. 系統偵測到需要強制更新 │ ▼ 2. 建立新 Key(保留舊 Key 在寬限期內) │ ▼ 3. 發送通知(Email/Slack/Redis PubSub) │ ▼ 4. 寬限期開始(預設 24 小時) │ ├── 在寬限期內更新 → 完成輪換 │ └── 寬限期結束 → 舊 Key 停用 ``` ### 6.3 寬限期配置 | Key 類型 | 寬限期 | |----------|--------| | system | 72 小時 | | user | 24 小時 | | service | 48 小時 | | integration | 24 小時 | | emergency | 0 小時 | --- ## 7. CLI 管理命令 ### 7.1 命令列表 ```bash # Key 管理 momentry api-key create --name "My Key" --type user --permissions read,write momentry api-key list --type user momentry api-key info momentry api-key revoke --reason "安全原因" # 輪換管理 momentry api-key rotate # 正常輪換 momentry api-key force-rotate # 強制輪換 momentry api-key rotation-status # 查看輪換狀態 # 異常管理 momentry api-key suspend --reason "異常使用" momentry api-key unsuspend momentry api-key blacklist # 列入黑名單 # 審計 momentry api-key audit --since 7d momentry api-key stats --type service --period 30d ``` ### 7.2 輸出範例 ```bash $ momentry api-key list --type service ┌────────────────────────────────────┬─────────┬──────────────┬────────────────┐ │ Key ID │ Name │ Status │ Expires │ ├────────────────────────────────────┼─────────┼──────────────┼────────────────┤ │ msvc_a1b2c3d4_1710998400_sha256 │ N8N │ active │ 2026-09-21 │ │ msvc_e5f6g7h8_1713600000_sha256 │ OpenCode│ rotation_req │ 2026-09-21 │ └────────────────────────────────────┴─────────┴──────────────┴────────────────┘ ⚠️ 1 個 Key 需要輪換 ``` --- ## 8. 實現計畫 ### Phase 1: 核心功能 - [ ] 資料庫 Schema - [ ] Key 生成與哈希 - [ ] 基本 CRUD API - [ ] 過期檢查 ### Phase 2: 安全機制 - [ ] 異常偵測 - [ ] 自動鎖定 - [ ] 強制輪換 - [ ] 寬限期管理 ### Phase 3: 管理工具 - [ ] CLI 命令 - [ ] 審計日誌 - [ ] 統計報表 - [ ] 通知系統 ### Phase 4: 自動化 - [ ] 定時輪換排程 - [ ] Prometheus 指標 - [ ] Alertmanager 整合 - [ ] 自動化回應 --- ## 9. 安全考量 ### 9.1 Key 儲存 - 明文 Key 只顯示一次(創建時) - 儲存時使用 SHA256 哈希 - 使用 Fernet 對稱加密敏感配置 ### 9.2 傳輸安全 - 所有 API 必須使用 HTTPS - Key 在 Header 中傳輸(X-API-Key) - 避免 Key 在 URL 中 ### 9.3 存取控制 - 只有管理員可創建/撤銷 Key - 用戶只能管理自己的 Key - 系統 Key 需要特殊權限 --- ## 10. 環境變數配置 ```bash # API Key 管理 MOMENTRY_API_KEY_GRACE_PERIOD=86400 # 寬限期(秒) MOMENTRY_API_KEY_MAX_PER_USER=5 # 每用戶最大 Key 數 MOMENTRY_API_KEY_ROTATION_DAYS=90 # 自動輪換天數 # 異常偵測 MOMENTRY_API_KEY_RATE_LIMIT=1000 # 每分鐘限制 MOMENTRY_API_KEY_ERROR_THRESHOLD=0.5 # 錯誤率閾值 MOMENTRY_API_KEY_IP_LIMIT=5 # 每小時 IP 限制 # 通知 MOMENTRY_API_KEY_ALERT_WEBHOOK= # 異常通知 webhook ``` --- ## 11. Gitea API Token 整合 ### 11.1 概述 支援透過 API Key 管理系統建立和管理 Gitea Personal Access Tokens,採用「建立時納管」模式。 ### 11.2 納管模式 ``` 使用者提供帳號密碼 → 呼叫 Gitea API 建立 Token → 明文只顯示一次 → 同步儲存至管理系統 ``` **特點:** - Token 明文僅在建立時取得 - 管理系統記錄 Token 元數據(不含明文) - 支援本地查詢和刪除 ### 11.3 資料庫結構 ```sql CREATE TABLE gitea_tokens ( id SERIAL PRIMARY KEY, gitea_token_id BIGINT NOT NULL, -- Gitea 內部 Token ID gitea_user VARCHAR(128) NOT NULL, -- Gitea 用戶名 token_name VARCHAR(128) NOT NULL, -- Token 名稱 token_last_eight VARCHAR(8) NOT NULL, -- SHA1 最後 8 碼(顯示用) scopes JSONB DEFAULT '[]', -- 權限範圍 api_key_id VARCHAR(48), -- 關聯的 API Key ID(可選) last_verified TIMESTAMP, -- 最後驗證時間 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, UNIQUE(gitea_user, token_name) ); ``` ### 11.4 Token 權限範圍 | 範圍 | 說明 | |------|------| | `read:repository` | 讀取倉庫 | | `write:repository` | 寫入倉庫 | | `read:issue` | 讀取議題 | | `write:issue` | 寫入議題 | | `read:user` | 讀取用戶資訊 | | `write:write` | 修改用戶資訊 | | `read:organization` | 讀取組織 | | `write:organization` | 修改組織 | | `read:package` | 讀取套件 | | `write:package` | 發布套件 | | `read:notification` | 讀取通知 | | `write:notification` | 修改通知 | | `read:admin` | 管理員讀取 | | `write:admin` | 管理員寫入 | ### 11.5 CLI 命令 #### 建立 Token ```bash # 基本用法 momentry gitea create \ --username \ --password \ --token-name \ --scopes "read:repository,write:repository" # 範例:建立整合用 Token momentry gitea create \ --username admin \ --password "MyPassword123" \ --token-name "ci-pipeline" \ --scopes "read:repository,write:repository,read:issue,write:issue" ``` **輸出範例:** ``` ✅ Gitea Token created successfully! ┌─────────────────────────────────────────────────────────────────────────────┐ │ ⚠️ IMPORTANT: Save this token now - it will not be shown again! │ └─────────────────────────────────────────────────────────────────────────────┘ Token ID: 9 Token Name: ci-pipeline SHA1: 9a4f282e9ba817b430082e6bff2c18e2ae38e480 Last 8: ae38e480 Authorization Header: Authorization: token 9a4f282e9ba817b430082e6bff2c18e2ae38e480 ``` #### 列出 Token ```bash # 列出用戶的所有 Token momentry gitea list \ --username \ --password ``` **輸出範例:** ``` 📋 Gitea Tokens for user: admin ┌────────────────────────────────────────────────────────────────────────────┐ │ ID │ Name │ Last 8 │ Registered │ ├────────────────────────────────────────────────────────────────────────────┤ │ 9 │ ci-pipeline │ ae38e480 │ ✓ │ │ 8 │ dev-token │ 1234abcd │ - │ └────────────────────────────────────────────────────────────────────────────┘ Total: 2 token(s) ``` #### 刪除 Token ```bash # 刪除指定 Token momentry gitea delete \ --username \ --password \ --token-name ``` #### 查詢本地記錄 ```bash # 查詢已納管的 Token 記錄 momentry gitea verify --token-name ``` **輸出範例:** ``` 📋 Gitea Token: ci-pipeline User: admin Token ID: 9 Last 8: ae38e480 Scopes: ["read:repository","write:repository"] Created: 2026-03-21 06:44:55.577586 UTC Last Verified: never ``` ### 11.6 使用範圍 #### 適用場景 | 場景 | 說明 | |------|------| | CI/CD 整合 | 建立專用 Token 用於自動化流程 | | 服務間通訊 | 建立 Token 供其他服務存取 Gitea API | | 開發環境 | 為開發者建立短期 Token | | 監控整合 | 建立只讀 Token 用於監控和報告 | #### 限制 | 限制 | 說明 | |------|------| | 明文 Token | 僅在建立時取得,無法再次查詢 | | 管理 API | 需要帳號密碼(BasicAuth) | | Token 驗證 | 只能透過 API 呼叫驗證有效性 | | 同步刪除 | 本地刪除不會自動同步到 Gitea | ### 11.7 環境變數 ```bash # Gitea 連線設定 GITEA_URL=http://localhost:3000 # Gitea API URL ``` ### 11.8 安全考量 | 項目 | 措施 | |------|------| | 密碼傳輸 | 僅在 CLI 命令中使用,不儲存 | | Token 儲存 | 本地僅存元數據,不含明文 | | 權限最小化 | 建議僅授予必要權限 | | 定期輪換 | 建議定期更新 Token | --- ## 12. n8n API Key 整合 ### 12.1 概述 支援透過 API Key 管理系統建立和管理 n8n API Keys,採用「建立時納管」模式。 ### 12.2 納管模式 ``` 使用者提供現有 n8n API Key → 呼叫 n8n API 建立新 Key → 明文只顯示一次 → 同步儲存至管理系統 ``` **特點:** - 需要一個現有的 n8n API Key 作為管理憑證 - API Key 明文僅在建立時取得 - 管理系統記錄 Key 元數據(不含明文) - 支援本地查詢和刪除 ### 12.3 資料庫結構 ```sql CREATE TABLE n8n_api_keys ( id SERIAL PRIMARY KEY, n8n_key_id VARCHAR(64) UNIQUE NOT NULL, -- n8n 內部 Key ID label VARCHAR(100) NOT NULL, -- Key 標籤 api_key_last_eight VARCHAR(8) NOT NULL, -- API Key 最後 8 碼(顯示用) momentry_api_key_id VARCHAR(48), -- 關聯的 API Key ID(可選) expires_at TIMESTAMP WITH TIME ZONE, -- 過期時間 last_verified TIMESTAMP WITH TIME ZONE, -- 最後驗證時間 created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP ); ``` ### 12.4 認證方式 n8n 使用 JWT-based API Key,透過 `X-N8N-API-KEY` Header 認證: ```bash curl -H "X-N8N-API-KEY: " https://n8n.example.com/api/v1/workflows ``` ### 12.5 CLI 命令 #### 建立 API Key ```bash # 基本用法 momentry n8n create \ --api-key \ --label \ --expires-in-days # 範例:建立 CI/CD 用 Key momentry n8n create \ --api_key "n8n_api_xxxxxxxxxxxx" \ --label "ci-pipeline" \ --expires-in-days 90 ``` **輸出範例:** ``` ✅ n8n API Key created successfully! ┌─────────────────────────────────────────────────────────────────────────────┐ │ ⚠️ IMPORTANT: Save this API key now - it will not be shown again! │ └─────────────────────────────────────────────────────────────────────────────┘ Key ID: abc123-def456 Label: ci-pipeline API Key: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9... Usage: curl -H 'X-N8N-API-KEY: eyJhbGciOiJIUz...' https://n8n.momentry.ddns.net/api/v1/workflows ``` #### 列出 API Keys ```bash # 列出所有 API Keys momentry n8n list --api-key ``` **輸出範例:** ``` 📋 n8n API Keys ┌────────────────────────────────────────────────────────────────────────────┐ │ Label │ ID │ ├────────────────────────────────────────────────────────────────────────────┤ │ ci-pipeline │ abc123-def456-789 │ │ monitoring │ xyz789-abc123-456 │ └────────────────────────────────────────────────────────────────────────────┘ Total: 2 key(s) ``` #### 刪除 API Key ```bash # 刪除指定 API Key momentry n8n delete \ --api-key \ --label ``` #### 查詢本地記錄 ```bash # 查詢已納管的 API Key 記錄 momentry n8n verify --label ``` **輸出範例:** ``` 📋 n8n API Key: ci-pipeline Key ID: abc123-def456 Last 8: ...JVCJ9 Created: 2026-03-21 06:44:55.577586 UTC Expires: 2026-06-19 06:44:55.577586 UTC Last Verified: never ``` ### 12.6 使用範圍 #### 適用場景 | 場景 | 說明 | |------|------| | CI/CD 整合 | 建立專用 Key 用於自動化流程 | | 監控整合 | 建立只讀 Key 用於監控工作流狀態 | | 服務間通訊 | 建立 Key 供其他服務呼叫 n8n API | | 開發環境 | 為開發者建立短期 Key | #### 限制 | 限制 | 說明 | |------|------| | 明文 API Key | 僅在建立時取得,無法再次查詢 | | 管理憑證 | 需要一個現有的 n8n API Key | | 本地刪除 | 不會自動同步到 n8n | | 權限範圍 | 非 Enterprise 版無細粒度權限 | ### 12.7 環境變數 ```bash # n8n 連線設定 N8N_URL=https://n8n.momentry.ddns.net # n8n API URL ``` ### 12.8 安全考量 | 項目 | 措施 | |------|------| | 管理 Key | 需妥善保管,作為管理其他 Key 的憑證 | | API Key 儲存 | 本地僅存元數據,不含明文 | | 過期機制 | 建議設定過期時間 | | 定期輪換 | 建議定期更新 Key | --- ## 13. 參考文檔 - PostgreSQL Schema - Redis Key 設計( MOMENTRY_CORE_REDIS_KEYS.md) - 監控系統(MOMENTRY_CORE_MONITORING.md) - Gitea 安裝指南(INSTALL_GITEA.md) - n8n API 文件(https://docs.n8n.io/api/authentication/)