# HasAccess 与 Authorize 鉴权差异及 IAM 迁移方案

## Introduction

本文基于当前实现，梳理两套鉴权系统（RBAC `HasAccess` 与 IAM `Authorize`）的行为差异，并给出迁移到 IAM Service 的高层分阶段方案、风险与验收标准。文档目标是为后续工程实施与评审提供统一基线。

## Motivation or Background

当前用户鉴权仍存在双路径：

- 旧路径：`HasAccess(HasAccessReq)`，使用 RBAC `Role -> Privilege` 判定权限。
- 新路径：`Authorize(AuthorizeRequest)`，使用 IAM `Role -> Policy -> Permission` 解析权限。

在 `pkg/controller/auth/auth.go` 中，`AuthzForUser` 由 `enableIAMAuth` 开关决定走 `Authorize` 还是 `HasAccess`；`AuthzForAPIKey` 已固定走 `Authorize`。这导致：

- 权限模型与语义在运行期并存，维护和排障成本高。
- API Key 的 tenant scope 能力只在新路径有效，旧路径无法覆盖。
- 用户组继承、权限缓存等 IAM 能力无法在旧路径统一生效。

迁移目标：统一到 IAM 鉴权模型，降低双轨复杂度，并保留可灰度、可回滚能力。

## Detailed Design

### 1. 现状对比（从实现出发）

#### 1.1 入口与开关

- 用户鉴权入口：`pkg/controller/auth/auth.go` `AuthzForUser`。
  - `EnableIAMAuth=true`：调用 `authCli.Authorize`。
  - `EnableIAMAuth=false`：调用 `authCli.HasAccess`。
- API Key 鉴权入口：`AuthzForAPIKey`，始终调用 `authCli.Authorize`。

#### 1.2 Principal 支持差异

- `HasAccessReq`：仅 `email + uri + method`。
- `AuthorizeRequest`：支持 `user_email` 与 `api_key_name` 两种 principal（`pkg/controller/user/auth_controller.go` 中 user 优先于 api key）。

#### 1.3 权限模型差异

- 旧模型：`Role -> Privilege(resource, operation string)`。
- 新模型：`Role -> Policy -> Permission(resource, operations[])`。
  - IAM 解析由 `ResolveEntityPermissions` 提供（`pkg/service/iam/permission_resolver.go`）。

#### 1.4 匹配语义差异

- 旧路径（`HasPrivilege` + `matchOperation`）：
  - `operation` 为字符串，可 `*`、精确匹配、正则匹配。
  - `resource` 支持 `*`、精确匹配、正则匹配。
- 新路径（`hasPermissionV2` + `matchOperationV2`）：
  - `operations` 为 `[]iam.Operation` 枚举集合（含 `OperationAll(*)`）。
  - `resource` 支持 `*`、精确匹配、正则匹配（并带 regex cache）。

#### 1.5 作用域能力差异

- `AuthorizeResponse` 包含 `RoleScope(role_name, allowed_tenant_ids)`。
- 中间件使用 `CtxRoleScope` 执行 tenant/cluster 级限制（`pkg/controller/middleware.go`）。
- `HasAccess` 路径没有等价 scope 语义，无法承载同级别租户约束。

#### 1.6 继承与缓存差异

- IAM 支持用户组父子继承与用户所属组递归解析（含深度保护）。
- IAM 支持权限缓存、预热（WarmUp）与失效重建（Clear/Reset）。
- 旧 RBAC 路径无等价继承与缓存体系。

### 2. 迁移步骤（高层分阶段）

#### Phase 1: 权限模型对齐

- 盘点现有 RBAC `Privilege(resource, operation)`。
- 建立映射到 IAM `Policy/Role/RoleBinding` 的规则（尤其是 operation 正则到枚举集合的收敛规则）。
- 为 API Key 与 User 分别核对绑定关系完整性。

#### Phase 2: 影子校验（不切主判定）

- 线上继续沿用当前主判定路径。
- 旁路执行另一条路径做比对（同一 `uri/method/principal`），记录 allow/deny 差异。
- 形成差异报表：按接口、角色、principal 类型聚合。

#### Phase 3: 灰度切换

- 按环境/流量逐步开启 `enableIAMAuth`（先低风险环境）。
- 重点观察：
  - 403 比例与趋势。
  - 关键 API 成功率。
  - scope 拦截是否符合预期（tenant/cluster 越权拦截）。
- 对高差异接口优先修正 IAM 权限映射后再扩大灰度。

#### Phase 4: 全量与收敛

- 全量切换用户鉴权到 `Authorize`。
- 冻结旧 RBAC 鉴权写入/维护路径，保留只读观察窗口。
- 在稳定窗口后下线 `HasAccess` 依赖路径。

#### Rollback 策略

- 通过关闭 `enableIAMAuth` 快速回退用户鉴权到 `HasAccess`。
- 回退时保留 IAM 数据与映射成果，支持后续再次灰度。

### 3. 公共接口与兼容性说明

- 本方案仅新增设计文档，不修改 API/Proto/类型。
- 重点参考的现有接口语义：
  - `HasAccessReq/HasAccessResp`
  - `AuthorizeRequest/AuthorizeResponse`
  - `RoleScope`

兼容性检查点：

- 升级兼容：`enableIAMAuth` 默认关闭时维持旧行为。
- 降级兼容：可随时回退开关。
- 外部组件兼容：鉴权调用链保持通过现有 `AuthService` gRPC 协议。

## Test Design

### Functional Tests

- 文档正确性对照：
  - `pkg/controller/user/auth_controller.go`
  - `pkg/controller/auth/auth.go`
  - `pkg/service/iam/permission_resolver.go`
  - `pkg/controller/middleware.go`
- 关键语义对照测试：
  - `pkg/controller/user/auth_controller_test.go`
  - `pkg/controller/auth/auth_test.go`

### Scenario Tests

- 迁移实施阶段应建立以下验证指标：
  - 判定一致性：`HasAccess` vs `Authorize` allow/deny 差异率。
  - 稳定性：切换期间 403 比例、关键 API 成功率、错误类型分布。
  - Scope 有效性：受限 API Key 对 tenant/cluster 的越权访问拦截率。

### Compatibility Tests

- 鉴权能力兼容：
  - User 鉴权在开关两侧行为可解释且可回退。
  - API Key `RoleScope` 在灰度和全量阶段保持生效。
- 系统兼容：
  - 中间件上下文（`CtxRoleScope`）在未设置、空 scope、限制 scope 三种状态行为一致。
- 升降级兼容：
  - 开关关闭恢复旧路径，开关开启走新路径，均可稳定运行。

## Impacts & Risks

### Impacts

- 正向影响：
  - 权限模型统一，降低维护成本。
  - API Key 范围控制能力与 user 鉴权路径可在同一体系演进。
  - 权限继承与缓存能力可统一利用。

### Risks

- 语义漂移风险：旧 `operation` 正则与新枚举集合不完全等价。
- 资源正则兼容风险：历史规则在新路径下可能出现边界差异。
- 现状限制风险：`RoleScope` 当前主要用于 API Key，用户侧范围控制策略需后续明确。

## Unresolved Questions

- 是否需要在用户鉴权也引入与 API Key 一致的 `RoleScope` 执行语义。
- 历史 `operation` 正则向 IAM 枚举集合映射的统一规则是否需要固化为工具或校验器。
- `HasAccess` 下线前稳定观察窗口长度与准入门槛（差异率阈值、403 阈值）需在实施前明确。

## Assumptions

- 受众为后续实施迁移的后端工程师与 Reviewer。
- 当前需要高层可执行方案，不展开逐接口 runbook 级细节。
- 本轮只产出设计文档，不改动业务代码、配置和测试。
- 迁移开关以 `enableIAMAuth` 为主，并按环境分阶段启用。
