feat(callback): add callback
This commit is contained in:
211
LOCAL_E2E_RUNBOOK.md
Normal file
211
LOCAL_E2E_RUNBOOK.md
Normal file
@@ -0,0 +1,211 @@
|
||||
# 本地端到端联调(iam-service + cms-service)
|
||||
|
||||
目标:
|
||||
|
||||
- 生成临时 RSA 公私钥供 iam-service 使用(RS256)
|
||||
- 启动 iam-service(签发 token、发布 JWKS、提供权限裁决 `/authorize/check`)
|
||||
- 启动 cms-service(本地验签 + 调用 IAM 做权限裁决)
|
||||
- 在两个服务的 Scalar 页面完成:创建租户 → 注册用户 → 登录 → 调用 CMS 资源接口,验证“认证/权限由 IAM 控制”
|
||||
|
||||
> 本文不要求修改任何业务代码;只需要本地导出环境变量或创建 `.env` 文件。
|
||||
|
||||
## 0. 前置条件
|
||||
|
||||
- Rust(支持 edition 2024)与 Cargo
|
||||
- PostgreSQL(本机或 Docker),并可使用 `psql`
|
||||
- `openssl`
|
||||
|
||||
端口默认:
|
||||
|
||||
- iam-service:3000
|
||||
- cms-service:3100
|
||||
|
||||
## 1. 准备数据库(推荐:Docker 一键起 PostgreSQL)
|
||||
|
||||
启动 PostgreSQL:
|
||||
|
||||
```bash
|
||||
docker run --rm -d --name local-pg \
|
||||
-e POSTGRES_PASSWORD=postgres \
|
||||
-p 5432:5432 \
|
||||
postgres:16
|
||||
```
|
||||
|
||||
创建 iam/cms 两个数据库与用户(示例账号,可按需调整):
|
||||
|
||||
```bash
|
||||
docker exec -i local-pg psql -U postgres <<'SQL'
|
||||
CREATE USER iam_service_user WITH PASSWORD 'iam_service_password';
|
||||
CREATE DATABASE iam_service_db OWNER iam_service_user;
|
||||
GRANT ALL PRIVILEGES ON DATABASE iam_service_db TO iam_service_user;
|
||||
|
||||
CREATE USER cms_service_user WITH PASSWORD 'cms_service_password';
|
||||
CREATE DATABASE cms_service_db OWNER cms_service_user;
|
||||
GRANT ALL PRIVILEGES ON DATABASE cms_service_db TO cms_service_user;
|
||||
SQL
|
||||
```
|
||||
|
||||
准备连接串(后续会分别用于两服务):
|
||||
|
||||
- IAM:`postgres://iam_service_user:iam_service_password@127.0.0.1:5432/iam_service_db`
|
||||
- CMS:`postgres://cms_service_user:cms_service_password@127.0.0.1:5432/cms_service_db`
|
||||
|
||||
## 2. 生成临时 RSA 公私钥(RS256)
|
||||
|
||||
```bash
|
||||
KEY_DIR="$(mktemp -d)"
|
||||
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out "$KEY_DIR/jwt_private_key.pem"
|
||||
openssl pkey -in "$KEY_DIR/jwt_private_key.pem" -pubout -out "$KEY_DIR/jwt_public_key.pem"
|
||||
|
||||
chmod 600 "$KEY_DIR/jwt_private_key.pem"
|
||||
chmod 644 "$KEY_DIR/jwt_public_key.pem"
|
||||
|
||||
echo "KEY_DIR=$KEY_DIR"
|
||||
```
|
||||
|
||||
说明:
|
||||
|
||||
- 私钥:PKCS#8 PEM(`BEGIN PRIVATE KEY`)
|
||||
- 公钥:PKCS#8 公钥 PEM(`BEGIN PUBLIC KEY`)
|
||||
- 该目录是临时目录,重启/清理后会消失;适合本地联调
|
||||
|
||||
## 3. 启动 iam-service(签发 token + JWKS + 权限裁决)
|
||||
|
||||
在一个终端中执行(建议在 `iam-service` 目录下):
|
||||
|
||||
```bash
|
||||
cd /home/shay/project/backend/iam-service
|
||||
|
||||
export PORT=3000
|
||||
export DATABASE_URL='postgres://iam_service_user:iam_service_password@127.0.0.1:5432/iam_service_db'
|
||||
|
||||
# 用于 refresh token 指纹(不是 JWT 签名密钥),本地随便填一个即可
|
||||
export JWT_SECRET='local-dev-refresh-token-pepper'
|
||||
|
||||
export JWT_KEY_ID='local-dev'
|
||||
export JWT_PRIVATE_KEY_PEM="$(cat "$KEY_DIR/jwt_private_key.pem")"
|
||||
export JWT_PUBLIC_KEY_PEM="$(cat "$KEY_DIR/jwt_public_key.pem")"
|
||||
|
||||
# 初始化/重建 DB(会清库重建,适合开发环境)
|
||||
BACKUP=0 ./scripts/db/rebuild_iam_db.sh
|
||||
|
||||
cargo run
|
||||
```
|
||||
|
||||
启动后:
|
||||
|
||||
- IAM Scalar:`http://127.0.0.1:3000/scalar`
|
||||
- JWKS:`http://127.0.0.1:3000/.well-known/jwks.json`
|
||||
|
||||
## 4. 启动 cms-service(本地验签 + 调 IAM 裁权)
|
||||
|
||||
在另一个终端中执行(建议在 `cms-service` 目录下):
|
||||
|
||||
```bash
|
||||
cd /home/shay/project/backend/cms-service
|
||||
|
||||
export PORT=3100
|
||||
export DATABASE_URL='postgres://cms_service_user:cms_service_password@127.0.0.1:5432/cms_service_db'
|
||||
|
||||
export IAM_BASE_URL='http://127.0.0.1:3000'
|
||||
|
||||
# CMS 默认会走 IAM_BASE_URL + /.well-known/jwks.json 拉取公钥
|
||||
# 如需显式指定:
|
||||
# export IAM_JWKS_URL='http://127.0.0.1:3000/.well-known/jwks.json'
|
||||
|
||||
# 初始化/重建 DB(会回滚并重建 cms schema;适合开发环境)
|
||||
./scripts/db/rebuild_cms_db.sh
|
||||
|
||||
cargo run
|
||||
```
|
||||
|
||||
启动后:
|
||||
|
||||
- CMS Scalar:`http://127.0.0.1:3100/scalar`
|
||||
|
||||
## 5. 在 Scalar 中跑通“租户 → 注册 → 登录 → 调用 CMS 接口”
|
||||
|
||||
### 5.1 在 IAM Scalar 创建租户
|
||||
|
||||
打开 `http://127.0.0.1:3000/scalar`:
|
||||
|
||||
1) 调用 `POST /tenants/register`
|
||||
|
||||
示例 body:
|
||||
|
||||
```json
|
||||
{ "name": "Tenant A" }
|
||||
```
|
||||
|
||||
从响应中拿到 `tenant_id`(UUID)。
|
||||
|
||||
### 5.2 在 IAM Scalar 注册首个用户(自动 Admin + CMS 权限)
|
||||
|
||||
调用 `POST /auth/register`:
|
||||
|
||||
- Header:`X-Tenant-ID: <tenant_id>`
|
||||
- Body:
|
||||
|
||||
```json
|
||||
{ "email": "admin@example.com", "password": "Passw0rd!" }
|
||||
```
|
||||
|
||||
重要说明:
|
||||
|
||||
- 该租户的**首个用户**会自动触发 bootstrap:创建/获取 `Admin` 角色,并授予该租户下的全量非 `iam:*` 权限(包含 `cms:*` 权限),再绑定给该用户。
|
||||
|
||||
### 5.3 在 IAM Scalar 登录拿 token
|
||||
|
||||
调用 `POST /auth/login`:
|
||||
|
||||
- Header:`X-Tenant-ID: <tenant_id>`
|
||||
- Body:
|
||||
|
||||
```json
|
||||
{ "email": "admin@example.com", "password": "Passw0rd!" }
|
||||
```
|
||||
|
||||
保存响应中的:
|
||||
|
||||
- `access_token`
|
||||
- `refresh_token`(可选,用于测试刷新)
|
||||
|
||||
### 5.4 在 CMS Scalar 调用资源接口(验证由 IAM 裁权)
|
||||
|
||||
打开 `http://127.0.0.1:3100/scalar`,选择任意需要权限的接口,例如:
|
||||
|
||||
- `POST /v1/columns`(需要 `cms:column:write`)
|
||||
|
||||
在请求中设置:
|
||||
|
||||
- `Authorization: Bearer <access_token>`
|
||||
- `X-Tenant-ID: <tenant_id>`
|
||||
|
||||
若一切正常:
|
||||
|
||||
- CMS 会先本地验签 token(auth-kit)
|
||||
- 然后调用 IAM 的 `POST /authorize/check` 判断权限
|
||||
- IAM 返回 allowed 后,CMS 才会执行业务写入
|
||||
|
||||
验证建议:
|
||||
|
||||
- 观察 iam-service 控制台日志:应能看到 `/authorize/check` 的请求
|
||||
- 如将 `access_token` 改成无效字符串,CMS 会直接返回 401(本地验签失败,不会去请求 IAM)
|
||||
|
||||
## 6. 常见问题(本地联调)
|
||||
|
||||
### 6.1 CMS 返回 401 MissingAuthHeader
|
||||
|
||||
- 检查是否在 CMS 请求里设置了 `Authorization: Bearer <access_token>`
|
||||
- 检查 token 是否复制完整(不要带引号/空格)
|
||||
|
||||
### 6.2 CMS 返回 400 Missing X-Tenant-ID header
|
||||
|
||||
- CMS 需要 `X-Tenant-ID`
|
||||
- 若同时提供 token + header,但 tenant_id 不一致会返回 403(tenant:mismatch)
|
||||
|
||||
### 6.3 CMS 返回 403 PermissionDenied
|
||||
|
||||
- 表示 IAM 裁权拒绝(例如用户没有 `cms:*` 权限)
|
||||
- 你可以在 IAM 中调用 `GET /me/permissions` 查看当前用户权限
|
||||
|
||||
Reference in New Issue
Block a user