|
|
||
|---|---|---|
| .. | ||
| journeys | ||
| lib | ||
| smoke | ||
| README.md | ||
README.md
k6 API tests
完整的 Gateway API smoke + journey 測試套件。所有 36 個對外端點都至少在 smoke/ 或 journeys/ 裡有一發。
TL;DR
make k6-up # docker:mongo + redis + mailhog + postgres + zitadel
make k6-wait # 等 ZITADEL ready + 把 PAT 寫到 env file
make k6-gateway & # 起 gateway(背景;吃 etc/gateway.k6.yaml)
make k6-seed-admin # (rbac journey 才需要)seed tenant_admin user
make k6-all # 跑 smoke + journey
make k6-down # 清掉
單跑一個檔(記得先載入環境變數):
source deploy/zitadel/machinekey/k6.env
k6 run test/k6/smoke/health.js
k6 run test/k6/journeys/email_register_full.js
環境變數
| 變數 | 預設 | 說明 |
|---|---|---|
BASE_URL |
http://localhost:8888 |
Gateway base URL |
MAILHOG_URL |
http://localhost:8025 |
MailHog HTTP API(撈 email OTP) |
REDIS_ADDR |
localhost:6379 |
Redis 位址(撈 SMS OTP) |
TENANT_SLUG |
k6-tenant |
register payload tenant |
INVITE_CODE |
K6INVITE |
tenant 開啟 invite 時用 |
ADMIN_EMAIL / ADMIN_PASSWORD |
— | rbac journey seeded admin |
OTP_POLL_INTERVAL_MS |
300 |
OTP poll 頻率 |
OTP_POLL_TIMEOUT_MS |
5000 |
OTP poll 超時 |
目錄結構
test/k6/
├── README.md
├── lib/ # 共用 helper
│ ├── config.js # 環境變數 + unique() + SUCCESS_CODE
│ ├── http.js # get/post/...、checkEnvelope、withBearer
│ ├── otp.js # fetchEmailOTP (MailHog) / fetchSMSOTP (Redis)
│ ├── totp.js # HMAC-SHA1 TOTP(P4)
│ ├── auth.js # register / confirm / login / refresh helper(P2)
│ └── seed.js # tenant + invite + admin role bootstrap(P5)
├── smoke/ # 每個端點至少一發
│ ├── health.js # GET /api/v1/health
│ ├── auth_public.js # register / login / refresh / social-start (+negative)
│ ├── auth_bearer.js # logout
│ ├── member.js # me / patch / verify start+confirm / TOTP
│ ├── permission_read.js # catalog / me
│ └── permission_admin.js # roles CRUD / role-permissions / user-roles / mappings / policy reload
└── journeys/ # 完整流程
├── email_register_full.js # register → confirm OTP(MailHog) → me → patch → logout
├── login_refresh.js # login → refresh → me → logout
├── email_verify.js # register → confirm → email verify start → confirm
├── phone_verify.js # register → confirm → phone verify (Redis OTP)
├── totp_full.js # enroll → confirm → verify → backup-codes → disable
├── rbac_admin.js # role CRUD → assign → policy reload → me/permissions
└── token_exchange.js # ZITADEL id_token → CloudEP JWT
OTP 怎麼撈
- Email →
make k6-up含 MailHog(:1025 SMTP / :8025 HTTP API)。Gateway 把 OTP 寄到 MailHog;k6 透過/api/v2/search?kind=to&query=<email>撈到信件,從 body 抓 6 位數。 - SMS → mock provider 把 body 寫到
dev:notification:last:sms:<phone>(見 mock_sender.goWithMockRedis),k6 用k6/experimental/redis直接讀。
兩者都有 OTP_POLL_TIMEOUT_MS(預設 5 秒)保護,超時直接 fail。
覆蓋率(39 endpoints)
| 模組 | 端點 | 覆蓋 |
|---|---|---|
| Normal | GET /api/v1/health |
smoke/health |
| Auth 公開 | POST /register |
journeys/email_register_full + smoke/auth_public |
| Auth 公開 | POST /register/confirm |
journeys/email_register_full |
| Auth 公開 | POST /register/resend |
smoke/auth_public |
| Auth 公開 | POST /register/social/start |
smoke/auth_public (happy) |
| Auth 公開 | GET /register/social/callback |
smoke/auth_public (negative — TODO happy) |
| Auth 公開 | POST /login |
journeys/login_refresh + smoke/auth_public (negative) |
| Auth 公開 | POST /token/refresh |
journeys/login_refresh + smoke/auth_public (negative) |
| Auth 公開 | POST /token/exchange |
journeys/token_exchange (negative — TODO happy) |
| Auth 公開 | POST /login/social/start |
smoke/auth_public (happy) |
| Auth 公開 | GET /login/social/callback |
smoke/auth_public (negative — TODO happy) |
| Auth Bearer | POST /logout |
smoke/auth_bearer + journeys/email_register_full |
| Member | GET /me |
smoke/member + all journeys |
| Member | PATCH /me |
smoke/member + journeys/email_register_full |
| Member | POST /me/verifications/email/start |
smoke/member + journeys/email_verify |
| Member | POST /me/verifications/email/confirm |
smoke/member (negative) + journeys/email_verify (happy) |
| Member | POST /me/verifications/phone/start |
smoke/member + journeys/phone_verify |
| Member | POST /me/verifications/phone/confirm |
smoke/member (negative) + journeys/phone_verify (happy) |
| Member | GET /me/totp |
smoke/member + journeys/totp_full |
| Member | POST /me/totp/enroll-start |
smoke/member + journeys/totp_full |
| Member | POST /me/totp/enroll-confirm |
smoke/member (negative) + journeys/totp_full (happy) |
| Member | POST /me/totp/verify |
smoke/member (negative) + journeys/totp_full (happy) |
| Member | POST /me/totp/backup-codes |
smoke/member (negative) + journeys/totp_full (happy) |
| Member | DELETE /me/totp |
smoke/member + journeys/totp_full |
| Perm 讀 | GET /permissions/catalog |
smoke/permission_read + journeys/rbac_admin |
| Perm 讀 | GET /permissions/me |
smoke/permission_read + journeys/rbac_admin |
| Perm 管理 | GET /roles |
smoke/permission_admin + journeys/rbac_admin |
| Perm 管理 | POST /roles |
smoke/permission_admin + journeys/rbac_admin |
| Perm 管理 | PATCH /roles/:id |
smoke/permission_admin + journeys/rbac_admin |
| Perm 管理 | DELETE /roles/:id |
smoke/permission_admin + journeys/rbac_admin |
| Perm 管理 | GET /roles/:id/permissions |
smoke/permission_admin + journeys/rbac_admin |
| Perm 管理 | PUT /roles/:id/permissions |
smoke/permission_admin + journeys/rbac_admin |
| Perm 管理 | GET /users/:uid/roles |
smoke/permission_admin + journeys/rbac_admin |
| Perm 管理 | POST /users/:uid/roles |
smoke/permission_admin + journeys/rbac_admin |
| Perm 管理 | DELETE /users/:uid/roles/:role_id |
smoke/permission_admin + journeys/rbac_admin |
| Perm 管理 | GET /role-mappings |
smoke/permission_admin |
| Perm 管理 | PUT /role-mappings |
smoke/permission_admin |
| Perm 管理 | DELETE /role-mappings |
smoke/permission_admin |
| Perm 管理 | POST /policy/reload |
smoke/permission_admin + journeys/rbac_admin |
RBAC 系列(需 admin seed)
journeys/rbac_admin.js 需要 ADMIN_EMAIL / ADMIN_PASSWORD 環境變數。make k6-seed-admin
會跑 cmd/k6-seed-admin:
- 用 API 註冊一個固定的
k6-admin@k6.local - 從 MailHog 撈 OTP 完成 confirm
- 寫入 permission catalog + 預設 system roles(透過
internal/model/permission/seed) - 指派
tenant_admin給該 UID - 把
ADMIN_EMAIL / ADMIN_PASSWORD / ADMIN_UID寫到k6.env
k6-seed-admin 是冪等的,重跑沒事。
沒跑 seed 時,rbac_admin.js 會印 skip notice 並 exit 0(admin endpoint 的路由存在性
已由 smoke/permission_admin.js 涵蓋)。
已知無法純 k6 跑的
GET /api/v1/auth/register/social/callback與GET /api/v1/auth/login/social/callbackhappy path 需要 Google OAuth UI 跳轉,純 k6 無法走完。Smoke 只覆蓋 negative(無效 state → 400)。POST /api/v1/auth/token/exchangehappy path 需要一個來自 ZITADEL 的有效id_token;目前make k6-up的 ZITADEL bootstrap 只建 service account PAT,沒有開 OIDC client password grant,因此 happy 路徑 TODO,smoke 只跑 negative。要開:在deploy/zitadel/steps.yaml加 Application + password grant,再用/oauth/v2/token拿 id_token。
不要 commit 的東西
deploy/zitadel/machinekey/zitadel-admin-sa.token/.json已在.gitignore。etc/gateway.k6.yaml內的 secret 都是固定 dev 值,本機 / CI 可用,勿 上 prod。