Files
aiagent/docs/multi-tenant-rbac-guide.md

571 lines
22 KiB
Markdown
Raw Normal View History

# 多租户与 RBAC 权限管理指南
> **Multi-Tenant & RBAC Guide** — 工作区隔离、角色权限、用户管理完整说明
本文档涵盖天工智能体平台 v1.2+ 的多租户架构、RBAC 权限体系、工作区管理和平台管理员功能。
---
## 一、多租户架构概览
### 1.1 什么是多租户
天工平台采用 **工作区 (Workspace)** 作为租户隔离的基本单元:
```
┌────────────────────────────────────────────────────┐
│ 天工平台 │
│ ┌──────────────┐ ┌──────────────┐ ┌───────────┐ │
│ │ 工作区 A │ │ 工作区 B │ │ 工作区 C │ │
│ │ (研发团队) │ │ (市场团队) │ │ (个人空间) │ │
│ │ │ │ │ │ │ │
│ │ Agent: 5 个 │ │ Agent: 3 个 │ │ Agent: 2 │ │
│ │ 工作流: 8 个 │ │ 工作流: 4 个 │ │ 工作流: 3 │ │
│ │ 知识库: 3 个 │ │ 知识库: 1 个 │ │ 知识库: 1 │ │
│ │ 成员: 12 人 │ │ 成员: 5 人 │ │ 成员: 1 │ │
│ └──────────────┘ └──────────────┘ └───────────┘ │
└────────────────────────────────────────────────────┘
```
### 1.2 核心隔离原则
| 隔离维度 | 说明 |
|----------|------|
| **数据隔离** | 每个工作区的 Agent、工作流、知识库、执行记录等数据完全隔离 |
| **成员隔离** | 工作区 A 的成员默认无法访问工作区 B 的任何资源 |
| **API 隔离** | 所有资源 API 自动按工作区过滤,返回结果仅限当前工作区 |
| **WebSocket 隔离** | 实时推送按工作区频道隔离,不会跨工作区串消息 |
### 1.3 JWT Token 中的工作区标识
登录或切换工作区后JWT Token 中会携带 `ws` 字段:
```json
{
"sub": "user-uuid-xxx",
"ws": "workspace-uuid-xxx",
"exp": 1712345678
}
```
所有后续 API 请求自动按此工作区范围过滤数据。
---
## 二、工作区管理
### 2.1 工作区列表
进入「工作区管理」页面,查看你有权限访问的所有工作区:
```
┌──────────────────────────────────────────────────────┐
│ 工作区管理 [+ 创建工作区] │
│ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ 研发团队 │ │ 个人空间 │ │ AI实验室 │ │
│ │ [默认] [管理员]│ │ [成员] │ │ [管理员] │ │
│ │ 描述... │ │ 描述... │ │ 描述... │ │
│ │ 状态: 启用 │ │ 状态: 启用 │ │ 状态: 停用 │ │
│ │ [进入] [管理]│ │ [进入] │ │ [进入] [管理]│ │
│ └─────────────┘ └─────────────┘ └─────────────┘ │
└──────────────────────────────────────────────────────┘
```
### 2.2 创建工作区
1. 点击「创建工作区」按钮
2. 填写工作区信息:
| 字段 | 说明 | 限制 |
|------|------|------|
| 名称 | 工作区唯一标识 | 1-100 字符 |
| 描述 | 可选说明信息 | 最多 1000 字符 |
| 最大成员数 | 工作区成员上限 | 1-500默认 50 |
3. 创建者自动成为该工作区的 **管理员 (admin)**
### 2.3 切换工作区
- 在工作区列表中点击「进入」自动切换
- 或通过顶部导航栏的工作区下拉选择器切换
- 切换后 JWT Token 刷新,后续所有操作在新工作区上下文中执行
### 2.4 管理工作区
点击「管理」进入工作区详情页,包含三个标签页:
**基本信息**
- 修改名称、描述、最大成员数
- 启用/停用工作区(停用后成员无法访问)
**成员管理**
- 查看当前成员列表(用户名、邮箱、角色)
- 添加新成员(按用户名查找)
- 修改成员角色(管理员 / 成员)
- 移除成员
**危险操作**
- 删除工作区(软删除,状态标记为 deleted
### 2.5 角色说明
| 角色 | 权限范围 |
|------|----------|
| **admin** (工作区管理员) | 管理成员、修改设置、删除工作区、创建/编辑/删除所有资源 |
| **member** (成员) | 查看和创建资源,编辑自己创建的资源 |
> **注意**: 工作区管理员 ≠ 平台管理员。工作区管理员仅管理当前工作区,平台管理员拥有全局权限。
---
## 三、RBAC 权限体系
### 3.1 系统角色
天工平台定义了 4 个系统级角色:
| 角色 | 说明 | 典型用户 |
|------|------|----------|
| **admin** (平台管理员) | 全局管理权限,绕过所有工作区限制 | 平台运维 |
| **developer** (开发者) | 创建和管理 Agent、工作流、知识库 | 核心开发 |
| **viewer** (只读用户) | 仅查看,无创建/编辑/删除权限 | 审计、管理层 |
| **operator** (操作员) | 管理执行、监控告警,但不创建新 Agent | 运维 |
### 3.2 权限列表 (23 项)
所有权限按资源类型分组:
| 权限码 | 说明 | developer | viewer | operator |
|--------|------|:---------:|:------:|:--------:|
| **workflow:create** | 创建工作流 | ✅ | ❌ | ❌ |
| **workflow:read** | 查看工作流 | ✅ | ✅ | ✅ |
| **workflow:update** | 编辑工作流 | ✅ | ❌ | ❌ |
| **workflow:delete** | 删除工作流 | ✅ | ❌ | ❌ |
| **workflow:execute** | 执行工作流 | ✅ | ❌ | ✅ |
| **workflow:publish** | 发布工作流 | ✅ | ❌ | ❌ |
| **agent:create** | 创建 Agent | ✅ | ❌ | ❌ |
| **agent:read** | 查看 Agent | ✅ | ✅ | ✅ |
| **agent:update** | 编辑 Agent | ✅ | ❌ | ❌ |
| **agent:delete** | 删除 Agent | ✅ | ❌ | ❌ |
| **agent:deploy** | 部署 Agent | ✅ | ❌ | ✅ |
| **agent:stop** | 停止 Agent | ✅ | ❌ | ✅ |
| **execution:read** | 查看执行记录 | ✅ | ✅ | ✅ |
| **execution:stop** | 中止执行 | ✅ | ❌ | ✅ |
| **data_source:create** | 创建数据源 | ✅ | ❌ | ❌ |
| **data_source:read** | 查看数据源 | ✅ | ✅ | ✅ |
| **data_source:update** | 编辑数据源 | ✅ | ❌ | ❌ |
| **data_source:delete** | 删除数据源 | ✅ | ❌ | ❌ |
| **model_config:create** | 创建模型配置 | ✅ | ❌ | ❌ |
| **model_config:read** | 查看模型配置 | ✅ | ✅ | ✅ |
| **model_config:update** | 编辑模型配置 | ✅ | ❌ | ❌ |
| **model_config:delete** | 删除模型配置 | ✅ | ❌ | ❌ |
| **permission:manage** | 管理权限 | ❌ | ❌ | ❌ |
> **admin 角色拥有所有 23 项权限(通配符 `*`),且绕过所有工作区成员资格检查。**
### 3.3 权限检查流程
```
API 请求
├─ 1. JWT 认证 (get_current_user)
│ └─ 失败 → 401 Unauthorized
├─ 2. 工作区成员资格检查 (get_workspace_membership)
│ ├─ 平台管理员 → 直接放行
│ ├─ 非成员 → 403 Forbidden
│ └─ 成员 → 继续
├─ 3. 细粒度权限检查 (WorkspacePermission)
│ ├─ 无该权限 → 403 Forbidden
│ └─ 有权限 → 继续
└─ 4. 执行请求
```
### 3.4 敏感操作保护
以下操作需要 **工作区管理员** 权限:
| 操作 | 端点 | 要求 |
|------|------|------|
| 删除 Agent | DELETE /agents/{id} | 工作区管理员 |
| 删除工作流 | DELETE /workflows/{id} | 工作区管理员 |
| 删除数据源 | DELETE /data-sources/{id} | 工作区管理员 |
| 删除模型配置 | DELETE /model-configs/{id} | 工作区管理员 |
| 删除定时任务 | DELETE /agent-schedules/{id} | 工作区管理员 |
| 部署 Agent | POST /agents/{id}/deploy | 工作区管理员 |
| 停止 Agent | POST /agents/{id}/stop | 工作区管理员 |
| 发布工作流 | POST /workflows/{id}/publish | 工作区管理员 |
| 重载工具 | POST /tools/reload | 工作区管理员 |
---
## 四、平台管理员功能
> 仅 `role=admin` 的用户可访问以下功能。
### 4.1 用户管理
进入「运维管理 → 用户管理」:
**用户列表**
```
┌──────────────────────────────────────────────────────────────────┐
│ 搜索: [________] 状态: [全部▾] 角色: [全部▾] │
├──────┬──────────┬──────┬──────┬──────┬────────┬──────┬──────────┤
│ 用户名 │ 邮箱 │ 角色 │ 状态 │ 订阅 │ 工作区数 │ 创建 │ 操作 │
├──────┼──────────┼──────┼──────┼──────┼────────┼──────┼──────────┤
│ admin │admin@.. │ 管理员│ 启用 │ 免费 │ 2 │06-01 │编辑 重置 │
│ 张三 │zhang@.. │ 开发者│ 启用 │ 专业 │ 1 │06-15 │编辑 重置 │
│ 李四 │li@.. │ 观察者│ 停用 │ 免费 │ 0 │06-20 │编辑 重置 │
└──────┴──────────┴──────┴──────┴──────┴────────┴──────┴──────────┘
```
**功能操作:**
- **创建用户**: 填写用户名、邮箱、密码6 位以上)、角色
- **编辑用户**: 修改用户名、邮箱、角色、手机号、状态、订阅等级
- **重置密码**: 为用户设置新密码
- **禁用/删除**: 软删除用户(设置 status=deleted平台管理员不可被删除
### 4.2 工作区全局管理
平台管理员在工作区管理页面看到全局视图:
```
┌── 所有工作区(平台管理员视图)──────────────────────────────────────┐
│ 搜索: [________] 状态: [全部▾] │
├──────────┬────────┬────────┬──────┬──────┬──────────┬────────────┤
│ 名称 │ 所有者 │ 成员数 │ 上限 │ 状态 │ 创建时间 │ 操作 │
├──────────┼────────┼────────┼──────┼──────┼──────────┼────────────┤
│ 研发团队 │ admin │ 12 │ 50 │ 启用 │ 2026-06 │ [进入][管理]│
│ AI实验室 │ 张三 │ 3 │ 20 │ 停用 │ 2026-07 │ [进入][管理]│
└──────────┴────────┴────────┴──────┴──────┴──────────┴────────────┘
```
**管理操作:**
- 点击「管理」可编辑任意工作区的名称和状态
- 可强制删除任意工作区(包括默认工作区)
- 所有操作记录在审计日志中
### 4.3 审计日志
进入「系统日志 → 审计日志」查看所有管理员操作记录:
- 操作人、操作类型CREATE/UPDATE/DELETE/LOGIN
- 资源类型、IP 地址
- 操作时间、操作结果
---
## 五、API 使用指南
### 5.1 认证与工作区切换
```bash
# 1. 登录获取 Token
curl -X POST http://localhost:8037/api/v1/auth/login \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "username=admin&password=123456"
# 响应: { "access_token": "eyJ...", "token_type": "bearer" }
# 2. 查看当前用户信息(含工作区列表)
curl http://localhost:8037/api/v1/auth/me \
-H "Authorization: Bearer $TOKEN"
# 响应包含:
# {
# "id": "...", "username": "admin", "role": "admin",
# "workspaces": [
# {"id": "ws-1", "name": "研发团队", "role": "admin"},
# {"id": "ws-2", "name": "个人空间", "role": "member"}
# ],
# "current_workspace_id": "ws-1"
# }
# 3. 切换工作区
curl -X POST http://localhost:8037/api/v1/auth/switch-workspace/ws-2 \
-H "Authorization: Bearer $TOKEN"
# 响应包含新的 Token携带新工作区 ID
```
### 5.2 工作区管理 API
```bash
# 创建工作区
curl -X POST http://localhost:8037/api/v1/workspaces \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"name": "新项目", "description": "项目协作空间", "max_members": 50}'
# 查看成员
curl http://localhost:8037/api/v1/workspaces/{ws_id}/members \
-H "Authorization: Bearer $TOKEN"
# 添加成员
curl -X POST http://localhost:8037/api/v1/workspaces/{ws_id}/members \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"username": "zhangsan", "role": "member"}'
# 修改成员角色
curl -X PUT http://localhost:8037/api/v1/workspaces/{ws_id}/members/{user_id} \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"role": "admin"}'
# 移除成员
curl -X DELETE http://localhost:8037/api/v1/workspaces/{ws_id}/members/{user_id} \
-H "Authorization: Bearer $TOKEN"
```
### 5.3 管理员 API
```bash
# 用户列表(分页、搜索、过滤)
curl "http://localhost:8037/api/v1/admin/users?page=1&page_size=20&search=admin&role=admin" \
-H "Authorization: Bearer $ADMIN_TOKEN"
# 创建用户
curl -X POST http://localhost:8037/api/v1/admin/users \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{"username":"newuser","email":"new@test.com","password":"123456","role":"developer"}'
# 编辑用户
curl -X PUT http://localhost:8037/api/v1/admin/users/{user_id} \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{"role":"viewer","status":"disabled"}'
# 重置密码
curl -X POST http://localhost:8037/api/v1/admin/users/{user_id}/reset-password \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{"new_password":"newpass123"}'
# 删除用户(软删除)
curl -X DELETE http://localhost:8037/api/v1/admin/users/{user_id} \
-H "Authorization: Bearer $ADMIN_TOKEN"
# 查看所有工作区
curl "http://localhost:8037/api/v1/admin/workspaces?page=1&page_size=20" \
-H "Authorization: Bearer $ADMIN_TOKEN"
# 查看任意工作区详情
curl http://localhost:8037/api/v1/admin/workspaces/{ws_id} \
-H "Authorization: Bearer $ADMIN_TOKEN"
# 编辑任意工作区
curl -X PUT http://localhost:8037/api/v1/admin/workspaces/{ws_id} \
-H "Authorization: Bearer $ADMIN_TOKEN" \
-H "Content-Type: application/json" \
-d '{"status":"disabled"}'
# 强制删除工作区
curl -X DELETE http://localhost:8037/api/v1/admin/workspaces/{ws_id} \
-H "Authorization: Bearer $ADMIN_TOKEN"
```
### 5.4 WebSocket 连接
WebSocket 连接需要传递 Token 作为 query 参数:
```javascript
// 执行状态实时推送
const ws = new WebSocket(
`ws://localhost:8037/api/v1/ws/executions/${executionId}?token=${jwtToken}`
);
ws.onmessage = (event) => {
const data = JSON.parse(event.data);
// data.type: "status" | "progress" | "error" | "pong"
console.log(data);
};
// 协作编辑
const collabWs = new WebSocket(
`ws://localhost:8037/api/v1/collaboration/ws/workflows/${workflowId}?token=${jwtToken}`
);
// 发送操作
collabWs.send(JSON.stringify({
type: "operation",
operation: {
type: "node_add",
node: { id: "...", type: "llm", position: { x: 100, y: 200 } }
}
}));
```
WebSocket 认证验证:
- JWT Token 有效性
- 用户存在且未被删除
- 工作区成员资格
- 资源归属当前工作区
### 5.5 错误码说明
| HTTP 状态码 | WebSocket 关闭码 | 说明 |
|:-----------:|:----------------:|------|
| 401 | 4001 | Token 无效或已过期 |
| 403 | 4003 | 无权访问(非工作区成员 / 无所需权限) |
| 403 | 4008 | 违反策略(如缺少 Token |
---
## 六、数据隔离详解
### 6.1 已隔离的资源
以下资源通过 `workspace_id` 字段实现完全隔离:
| 资源 | 表 | 隔离方式 |
|------|-----|----------|
| Agent | agents | 查询时自动按 workspace_id 过滤 |
| 工作流 | workflows | 查询时自动按 workspace_id 过滤 |
| 执行记录 | executions | 查询时自动按 workspace_id 过滤 |
| 数据源 | data_sources | 查询时自动按 workspace_id 过滤 |
| 模型配置 | model_configs | 查询时自动按 workspace_id 过滤 |
| 定时任务 | agent_schedules | 查询时自动按 workspace_id 过滤 |
| 知识库 | knowledge_bases | 查询时自动按 workspace_id 过滤 |
| 聊天消息 | chat_messages | 查询时自动按 workspace_id 过滤 |
| Agent 会话 | agent_sessions | 查询时自动按 workspace_id 过滤 |
| 告警规则 | alert_rules | 查询时自动按 workspace_id 过滤 |
| 节点模板 | node_templates | 查询时自动按 workspace_id 过滤 |
| 插件 | plugins | 查询时自动按 workspace_id 过滤 |
| 目标/任务 | goals / tasks | 查询时自动按 workspace_id 过滤 |
| 编排模板 | orchestration_templates | 查询时自动按 workspace_id 过滤 |
| 场景契约 | scene_contracts | 查询时自动按 workspace_id 过滤 |
| 团队 | teams | 查询时自动按 workspace_id 过滤 |
| 对话分支 | conversation_branches | 查询时自动按 workspace_id 过滤 |
| LLM 日志 | agent_llm_logs | 查询时自动按 workspace_id 过滤 |
| 知识条目 | knowledge_entries | 查询时自动按 workspace_id 过滤 |
| 告警日志 | alert_logs | 查询时自动按 workspace_id 过滤 |
### 6.2 创建时自动标记
所有新建资源自动 stamp 当前工作区 ID确保数据归属正确
```python
# 后端自动处理(以 Agent 为例)
agent = Agent(
...
user_id=current_user.id,
workspace_id=workspace_id, # 从 JWT ws 字段自动提取
)
```
---
## 七、常见场景
### 7.1 企业新员工入职
1. **管理员创建用户账号** — 进入「用户管理」→ 创建用户,设置角色为 `developer`
2. **将用户加入工作区** — 进入目标工作区「成员管理」→ 添加成员
3. **用户登录** — 使用分配的账号密码登录
4. **用户切换工作区** — 在工作区列表选择目标工作区进入
5. **开始工作** — 创建 Agent、工作流等
### 7.2 创建新团队协作空间
1. **创建工作区** — 点击「创建工作区」,命名为"XX 项目"
2. **添加团队成员** — 逐个添加成员账号
3. **设置成员角色** — 核心成员设为 `admin`(可管理成员),普通成员设为 `member`
4. **团队开始协作** — 所有成员在该工作区中创建的 Agent、工作流自动共享
### 7.3 权限审查
1. **平台管理员**进入「用户管理」查看所有用户及其角色
2. 检查是否有用户拥有不当权限(如普通用户被设为 `admin`
3. 通过「编辑用户」调整角色
4. 停用离职员工的账号(设置 status=disabled
### 7.4 审计追溯
1. 进入「系统日志 → 审计日志」
2. 按时间、用户、操作类型筛选
3. 查看关键操作:用户创建/删除、权限变更、工作区删除等
4. 所有敏感操作有完整审计轨迹
---
## 八、安全注意事项
### 8.1 密码安全
- 默认管理员密码 `123456` 应在首次部署后立即修改
- 通过个人设置或管理员强制重置修改密码
- 密码至少 6 位,建议使用强密码策略
### 8.2 权限最小化
- 给用户分配其工作需要的最低权限角色
- 默认使用 `developer` 角色,而非 `admin`
- 定期审查工作区成员列表,移除不再需要访问的用户
### 8.3 工作区删除
- 删除工作区是软删除status=deleted数据不会物理删除
- 需要彻底清理数据请联系平台管理员
- 默认工作区建议保留不删除
### 8.4 Token 安全
- JWT Token 包含工作区上下文,请妥善保管
- Token 过期后需重新登录
- WebSocket 连接的 Token 通过 query 参数传递,注意日志中不要泄露
---
## 附录 A: 角色权限矩阵速查
| 操作 | platform admin | workspace admin | developer | viewer | operator |
|------|:---:|:---:|:---:|:---:|:---:|
| 查看所有工作区 | ✅ | ❌ | ❌ | ❌ | ❌ |
| 管理所有工作区 | ✅ | ❌ | ❌ | ❌ | ❌ |
| 管理所有用户 | ✅ | ❌ | ❌ | ❌ | ❌ |
| 管理本工作区成员 | ✅ | ✅ | ❌ | ❌ | ❌ |
| 修改工作区设置 | ✅ | ✅ | ❌ | ❌ | ❌ |
| 创建 Agent/工作流 | ✅ | ✅ | ✅ | ❌ | ❌ |
| 编辑自己的资源 | ✅ | ✅ | ✅ | ❌ | ❌ |
| 删除自己的资源 | ✅ | ✅ | ✅ | ❌ | ❌ |
| 编辑他人的资源 | ✅ | ✅ | ❌ | ❌ | ❌ |
| 删除他人的资源 | ✅ | ✅ | ❌ | ❌ | ❌ |
| 部署/停止 Agent | ✅ | ✅ | ✅ | ❌ | ✅ |
| 执行工作流 | ✅ | ✅ | ✅ | ❌ | ✅ |
| 查看资源 | ✅ | ✅ | ✅ | ✅ | ✅ |
| 查看执行记录 | ✅ | ✅ | ✅ | ✅ | ✅ |
| 查看审计日志 | ✅ | ❌ | ❌ | ❌ | ❌ |
## 附录 B: 数据库表 workspace_id 标记
所有支持多租户隔离的数据表均包含 `workspace_id` 列:
```
agents agent_schedules alert_rules
alert_logs agent_execution_logs agent_llm_logs
agent_sessions chat_messages conversation_branches
data_sources executions goals
knowledge_bases knowledge_entries model_configs
node_templates plugins scene_contracts
orchestration_templates tasks teams
templates workflows tools
```
## 附录 C: 技术架构要点
- **后端框架**: FastAPI + SQLAlchemy ORM
- **认证**: JWT (python-jose) + bcrypt 密码哈希
- **依赖注入**: FastAPI `Depends()` 链式调用实现认证→授权→执行
- **数据隔离**: 所有查询通过 SQLAlchemy `filter(workspace_id=...)` 实现
- **WebSocket**: 连接注册表按 workspace_id 标记,防止跨工作区消息泄露
- **平台管理员绕过**: `user.role == "admin"` 跳过所有 workspace 成员资格检查
---
> 最后更新2026-07-04 | 适用版本 v1.2+