Vận hành
1. Triển khai
| Thuộc tính | Giá trị |
|---|---|
| Image | registry/nx-seller-identity:<tag> |
| Container Port | 3000 |
| External Port | 31010 |
| Snowflake ID | 1 |
| Replicas (mặc định) | 1 (dev) / 2+ (staging+) |
| Resources (req/lim) | 200m / 1 CPU, 512Mi / 1Gi memory |
| Migration mode | Job RUN_MODE=migrate trước rollout |
| Live probe | GET /v1/api/identity/healthz |
| Ready probe | GET /v1/api/identity/readyz |
| JWKS endpoint | GET /jw-certs (công khai, BẮT BUỘC truy cập được từ mọi sister service) |
Nhãn routing Traefik
yaml
labels:
- "traefik.enable=true"
- "traefik.http.routers.identity.rule=PathPrefix(`/v1/api/identity`) || Path(`/jw-certs`)"
- "traefik.http.services.identity.loadbalancer.server.port=3000"Đường dẫn
/jw-certscố tình đặt ngoài/v1/api/identity/để sister có thể gọi trực tiếp mà không cần base path API.
Hạ tầng yêu cầu
| Phụ thuộc | Lý do |
|---|---|
| PostgreSQL | Datastore chính (schema identity + public.Configuration dùng chung) |
| Redis | Trạng thái OTP + auth cache + BullMQ cho queue mail |
| SMTP | Chuyển email — service vẫn khởi động khi thiếu nhưng flow mail sẽ thất bại |
| VN Pay SMS | Chuyển SMS — tương tự |
| JWKS keypair (env / secret) | Service từ chối khởi động nếu thiếu |
2. Observability
| Tín hiệu | Nguồn | Tìm ở đâu |
|---|---|---|
| Logs | stdout (IGNIS structured logger) | kubectl logs deploy/identity / Loki |
| Health | /healthz, /readyz | Gateway portal |
| OpenAPI live spec | GET /v1/api/identity/doc/openapi.json | Gateway portal |
| Metrics | Traefik gateway | Grafana |
| JWKS check | GET /jw-certs | Manual / synthetic monitor (mỗi 1m) |
Trường log quan trọng
| Trường | Nguồn | Ghi chú |
|---|---|---|
requestId | header X-Request-Id | Liên kết xuyên-service |
userId | JWT subject | Per-request |
identifier.scheme | flow đăng nhập | Email vs phone vs username |
otp.namespace | OTP service | verify-email / phone-auth / forgot-password |
kid | header JWT | Theo dõi xoay key |
3. Bảo mật
| Vấn đề | Giảm thiểu |
|---|---|
| Xoay JWKS | kid mới được publish; key cũ vẫn hợp lệ đến khi hết hạn; sister fetch khi miss |
| Private signing key | K8s Secret, đường dẫn file mount; không bao giờ dạng env-text |
| Lưu trữ mật khẩu | Bun.password hash (kiểu argon2) |
| OTP brute-force | Mã đã hash + tối đa 5 lần thử + lockout 10–15 phút + cooldown gửi lại 60s + hạn ngạch hàng ngày |
| Identifier enumeration | Yêu cầu OTP trả cùng response shape bất kể identifier có tồn tại hay không |
| AuthN | BASIC chỉ trên endpoint nội bộ; flow /auth/* công khai có rate limit (gateway) |
| AuthZ | Casbin qua PolicyDefinition |
| TLS | Kết thúc tại Nginx → Traefik → service ở plaintext |
| Network policy | Cilium — cho phép gateway + sister service + SMTP + Redis + Postgres |
| Mail/SMS providers | Credential mã hoá (AES-256-GCM) trong Configuration.credential |
4. Runbook
4.1 Lớp cảnh báo
| Cảnh báo | Trigger | Kiểm tra | Khắc phục | Escalate |
|---|---|---|---|---|
IdentityHighErrorRate | 5xx >5% trên 5m | kubectl logs ... | grep level=error | xác định endpoint lỗi | on-call backend |
IdentityJWKSDown | /jw-certs trả về non-200 | curl JWKS | restart pod; kiểm tra mount signing key | on-call SRE — ƯU TIÊN CAO (lan ra mọi sister) |
IdentityMailFailures | tăng vọt error rate gửi mail | lỗi Nodemailer | xác minh SMTP creds; kiểm tra provider | on-call backend |
IdentitySMSFailures | tăng vọt error rate gửi SMS | lỗi MQSMSComponent | xác minh VN Pay creds; kiểm tra provider | on-call backend |
IdentityOTPSpike | rate yêu cầu OTP >Nx baseline | application log | kiểm tra credential-stuffing; siết rate limit | on-call security |
IdentitySignInFailures | rate fail đăng nhập >5% | log | xác định IP bad-actor; kiểm tra mẫu user hợp lệ | on-call backend |
4.2 Thao tác phổ biến
| Thao tác | Lệnh |
|---|---|
| Tail logs | kubectl logs -n <ns> -f deploy/identity |
| Chạy migration | kubectl exec -it deploy/identity -- bun run migrate |
| Xác minh JWKS | curl -s <base>/jw-certs | jq .keys[0] |
| Inspect một user | SELECT * FROM "User" WHERE id = '...'; |
| Kiểm tra policy definition của user | SELECT * FROM "PolicyDefinition" WHERE subject_id = '<userId>' AND subject_type = 'User'; |
| Reset OTP lockout cho user | Xoá Redis key <namespace>:lock:<identifier> |
4.3 Kịch bản phục hồi
| Kịch bản | Phục hồi |
|---|---|
| Service crash | Mọi request đang xử lý sẽ thất bại; trạng thái OTP trong Redis vẫn còn |
| Provider Mail/SMS gián đoạn | Trạng thái OTP queue trong Redis; user yêu cầu lại sau khi provider hồi phục |
| Redis gián đoạn | Flow OTP thất bại (fail open: HTTP 503); auth cache tắt nhưng JWT verify vẫn hoạt động |
| Postgres gián đoạn | Mọi endpoint thất bại; user vẫn có thể xác minh JWT HIỆN HỮU (sister cache JWKS) |
| Mất signing key | Thảm hoạ — mọi JWT hiện tại không thể xác minh; xoay keypair + buộc mọi user đăng nhập lại |