# AWOOOI RBAC 權限架構設計 > **版本**: v1.0 > **建立日期**: 2026-03-20 > **負責人**: CISO > **狀態**: Phase 0 草稿 --- ## 概述 本文件定義 AWOOOI 的角色基礎存取控制 (RBAC) 架構,採用簡化設計原則,解決舊系統「8+ 角色難以理解」的痛點。 --- ## 設計原則 1. **簡單直觀**: 4 個核心角色,一目瞭然 2. **資源導向**: 角色 + 資源級權限,彈性組合 3. **最小權限**: 預設拒絕,明確授權 4. **可審計**: 所有權限變更留有記錄 --- ## 角色定義 ### 四大核心角色 | 角色 | 代碼 | 說明 | 典型用戶 | |------|------|------|---------| | **Owner** | `owner` | 組織擁有者,最高權限 | CEO, 創辦人 | | **Admin** | `admin` | 管理員,可管理用戶與設定 | CTO, CIO, 部門主管 | | **Member** | `member` | 成員,可操作與查看 | 工程師, 運維人員 | | **Viewer** | `viewer` | 觀察者,僅可查看 | 稽核人員, 實習生 | ### 角色繼承 ``` Owner └── Admin └── Member └── Viewer ``` - 上層角色繼承下層所有權限 - 權限向下傳遞,不可跨層授權 --- ## 權限矩陣 ### 系統級權限 | 權限 | Owner | Admin | Member | Viewer | |------|:-----:|:-----:|:------:|:------:| | 管理組織設定 | ✅ | ❌ | ❌ | ❌ | | 管理帳單 | ✅ | ❌ | ❌ | ❌ | | 邀請/移除用戶 | ✅ | ✅ | ❌ | ❌ | | 變更用戶角色 | ✅ | ✅¹ | ❌ | ❌ | | 管理 API Keys | ✅ | ✅ | ❌ | ❌ | | 查看審計日誌 | ✅ | ✅ | ❌ | ❌ | > ¹ Admin 只能指派 Member/Viewer,不可指派 Admin/Owner ### 模組級權限 | 模組 | 動作 | Owner | Admin | Member | Viewer | |------|------|:-----:|:-----:|:------:|:------:| | **Monitor** | 查看儀表板 | ✅ | ✅ | ✅ | ✅ | | | 配置告警規則 | ✅ | ✅ | ✅ | ❌ | | | 確認告警 | ✅ | ✅ | ✅ | ❌ | | **Deploy** | 查看部署 | ✅ | ✅ | ✅ | ✅ | | | 執行部署 | ✅ | ✅ | ✅² | ❌ | | | 回滾 | ✅ | ✅ | ✅² | ❌ | | | 批准部署 | ✅ | ✅ | ❌ | ❌ | | **Security** | 查看漏洞 | ✅ | ✅ | ✅ | ✅ | | | 執行掃描 | ✅ | ✅ | ✅ | ❌ | | | 標記已修復 | ✅ | ✅ | ✅ | ❌ | | **Tickets** | 查看工單 | ✅ | ✅ | ✅ | ✅ | | | 建立工單 | ✅ | ✅ | ✅ | ❌ | | | 關閉工單 | ✅ | ✅ | ✅³ | ❌ | | **Settings** | 查看設定 | ✅ | ✅ | ✅ | ❌ | | | 修改設定 | ✅ | ✅ | ❌ | ❌ | | **AI Copilot** | 使用 AI | ✅ | ✅ | ✅ | ✅ | | | 執行 AI 建議 | ✅ | ✅ | ✅² | ❌ | > ² 需資源級權限 > ³ 僅能關閉自己建立的工單 --- ## 資源級權限 ### 設計理念 角色定義「能做什麼」,資源權限定義「能對什麼做」。 ``` 最終權限 = 角色權限 ∩ 資源權限 ``` ### 資源類型 | 資源類型 | 代碼 | 說明 | |---------|------|------| | 主機 | `host` | 單一主機 | | 主機群組 | `host_group` | 主機群組 | | 服務 | `service` | 單一服務 | | Pipeline | `pipeline` | 部署流水線 | | 專案 | `project` | 整個專案 | ### 授權範例 ```json { "user_id": "u-001", "role": "member", "resource_permissions": [ { "resource_type": "host_group", "resource_id": "hg-web-servers", "actions": ["deploy", "rollback", "restart"] }, { "resource_type": "host_group", "resource_id": "hg-database", "actions": ["view"] // 只能看,不能操作 }, { "resource_type": "pipeline", "resource_id": "pl-api-deploy", "actions": ["execute", "view"] } ] } ``` ### 資源權限動作 | 資源類型 | 可用動作 | |---------|---------| | host / host_group | `view`, `deploy`, `rollback`, `restart`, `ssh`, `manage` | | service | `view`, `start`, `stop`, `restart`, `scale`, `manage` | | pipeline | `view`, `execute`, `approve`, `manage` | | project | `view`, `edit`, `delete`, `manage` | --- ## Multi-Sig 簽核機制 ### 適用場景 | 場景 | 風險等級 | 簽核要求 | |------|---------|---------| | 生產環境部署 | High | 2 人簽核 (含 1 Admin+) | | 資料庫 Schema 變更 | Critical | 2 人簽核 (含 CTO) | | 安全設定變更 | High | 2 人簽核 (含 CISO) | | 用戶權限提升 | Medium | 1 人簽核 (Admin+) | | 回滾操作 | Medium | 1 人簽核 (Admin+) | ### 簽核規則 ```typescript interface ApprovalPolicy { action: string; blastRadius: 'low' | 'medium' | 'high' | 'critical'; requiredSignatures: number; requiredRoles: Role[]; timeoutMinutes: number; escalationPolicy?: EscalationPolicy; } const policies: ApprovalPolicy[] = [ { action: 'deploy:production', blastRadius: 'high', requiredSignatures: 2, requiredRoles: ['admin', 'owner'], timeoutMinutes: 60, escalationPolicy: { afterMinutes: 30, notifyRoles: ['owner'], }, }, { action: 'security:config_change', blastRadius: 'high', requiredSignatures: 2, requiredRoles: ['admin'], // 至少一人必須有 CISO tag timeoutMinutes: 120, }, ]; ``` ### 簽核流程 ``` ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │ 請求發起 │ ─→ │ 等待簽核 │ ─→ │ 執行操作 │ │ (Member) │ │ (Admin+) │ │ (系統) │ └─────────────┘ └─────────────┘ └─────────────┘ │ ▼ ┌─────────────┐ │ 超時處理 │ │ (自動拒絕) │ └─────────────┘ ``` --- ## 資料模型 ### 資料庫 Schema ```sql -- 用戶表 CREATE TABLE users ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), email VARCHAR(255) NOT NULL UNIQUE, name VARCHAR(255) NOT NULL, role VARCHAR(50) NOT NULL DEFAULT 'viewer', created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), updated_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), last_login_at TIMESTAMP WITH TIME ZONE, is_active BOOLEAN DEFAULT TRUE, CONSTRAINT valid_role CHECK (role IN ('owner', 'admin', 'member', 'viewer')) ); -- 資源權限表 CREATE TABLE resource_permissions ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE, resource_type VARCHAR(50) NOT NULL, resource_id VARCHAR(255) NOT NULL, actions TEXT[] NOT NULL, granted_by UUID REFERENCES users(id), granted_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), expires_at TIMESTAMP WITH TIME ZONE, UNIQUE (user_id, resource_type, resource_id) ); -- 簽核請求表 CREATE TABLE approval_requests ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), action VARCHAR(100) NOT NULL, requester_id UUID NOT NULL REFERENCES users(id), target_resource_type VARCHAR(50) NOT NULL, target_resource_id VARCHAR(255) NOT NULL, blast_radius VARCHAR(20) NOT NULL, required_signatures INT NOT NULL, status VARCHAR(20) NOT NULL DEFAULT 'pending', metadata JSONB, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), expires_at TIMESTAMP WITH TIME ZONE NOT NULL, completed_at TIMESTAMP WITH TIME ZONE, CONSTRAINT valid_status CHECK (status IN ('pending', 'approved', 'rejected', 'expired', 'cancelled')) ); -- 簽核記錄表 CREATE TABLE approval_signatures ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), request_id UUID NOT NULL REFERENCES approval_requests(id) ON DELETE CASCADE, signer_id UUID NOT NULL REFERENCES users(id), decision VARCHAR(20) NOT NULL, comment TEXT, signed_at TIMESTAMP WITH TIME ZONE DEFAULT NOW(), UNIQUE (request_id, signer_id), CONSTRAINT valid_decision CHECK (decision IN ('approve', 'reject')) ); -- 審計日誌表 CREATE TABLE audit_logs ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID REFERENCES users(id), action VARCHAR(100) NOT NULL, resource_type VARCHAR(50), resource_id VARCHAR(255), old_value JSONB, new_value JSONB, ip_address INET, user_agent TEXT, created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() ); -- 索引 CREATE INDEX idx_resource_permissions_user ON resource_permissions(user_id); CREATE INDEX idx_resource_permissions_resource ON resource_permissions(resource_type, resource_id); CREATE INDEX idx_approval_requests_status ON approval_requests(status, expires_at); CREATE INDEX idx_audit_logs_user ON audit_logs(user_id, created_at); CREATE INDEX idx_audit_logs_resource ON audit_logs(resource_type, resource_id, created_at); ``` --- ## API 設計 ### 權限檢查 API ```typescript // POST /v1/auth/check-permission interface CheckPermissionRequest { userId: string; action: string; resourceType: string; resourceId: string; } interface CheckPermissionResponse { allowed: boolean; reason?: string; requiresApproval?: boolean; approvalPolicy?: ApprovalPolicy; } ``` ### 簽核 API ```typescript // POST /v1/approvals interface CreateApprovalRequest { action: string; targetResourceType: string; targetResourceId: string; metadata?: Record; } // POST /v1/approvals/{id}/sign interface SignApprovalRequest { decision: 'approve' | 'reject'; comment?: string; } ``` ### 用戶權限 API ```typescript // GET /v1/users/{id}/permissions interface UserPermissionsResponse { role: Role; systemPermissions: string[]; resourcePermissions: ResourcePermission[]; } // PUT /v1/users/{id}/role interface UpdateRoleRequest { role: Role; } // POST /v1/users/{id}/resource-permissions interface GrantResourcePermissionRequest { resourceType: string; resourceId: string; actions: string[]; expiresAt?: string; } ``` --- ## 安全考量 ### Token 管理 ```typescript interface JWTPayload { sub: string; // user_id role: Role; permissions: string[]; // 快取常用權限 iat: number; exp: number; } // Token 過期策略 const TOKEN_CONFIG = { accessTokenTTL: '15m', // 存取 Token refreshTokenTTL: '7d', // 刷新 Token rotateRefreshToken: true, // 刷新時輪換 }; ``` ### 敏感操作保護 1. **再次驗證**: 變更權限前要求重新輸入密碼 2. **操作冷卻**: 連續拒絕 3 次後鎖定 15 分鐘 3. **異常偵測**: 異地登入、異常時間操作告警 4. **Session 管理**: 支援踢出其他 Session ### 審計要求 所有以下操作必須記錄審計日誌: - 用戶登入/登出 - 角色變更 - 資源權限授予/撤銷 - 簽核操作 - 敏感資源存取 - 設定變更 --- ## 遷移策略 ### 舊系統角色對應 | 舊角色 | 新角色 | 補充權限 | |-------|-------|---------| | Super Admin | Owner | - | | Admin | Admin | - | | Manager | Admin | 資源級限制 | | Developer | Member | 開發資源權限 | | Operator | Member | 運維資源權限 | | Auditor | Viewer | 審計日誌存取 | | Guest | Viewer | - | | API User | Member | API 專用權限 | ### 遷移腳本 ```python # scripts/migrate_roles.py ROLE_MAPPING = { 'super_admin': 'owner', 'admin': 'admin', 'manager': 'admin', 'developer': 'member', 'operator': 'member', 'auditor': 'viewer', 'guest': 'viewer', 'api_user': 'member', } def migrate_user_role(old_user): new_role = ROLE_MAPPING.get(old_user.role, 'viewer') # 特殊處理: manager 需要資源級權限 if old_user.role == 'manager': grant_resource_permissions( user_id=old_user.id, resource_type='project', resource_id=old_user.managed_project, actions=['view', 'edit', 'manage'] ) return new_role ``` --- ## 變更記錄 | 日期 | 版本 | 變更 | 作者 | |------|------|------|------| | 2026-03-20 | v1.0 | 初版建立 | CISO | --- *此文件由 CISO 維護,所有權限相關開發必須遵守此架構。*