11.10 · Scorecard + ปัญหา API surface
บทสุดท้ายของ Volume 11 — สรุปคะแนนรวมของ API surface ระบบ VTRC พร้อมระบุปัญหาเร่งด่วนและแนวทางการปรับปรุง
Scorecard — รวม 3 services
ให้คะแนนแต่ละด้านของ API surface ใน 3 services โดยใช้เกณฑ์: 5 = production-grade, 3 = ใช้งานได้แต่มีข้อจำกัด, 1 = เสี่ยง
| ด้าน | vtrc-api | cu-central-api | centralize-api | หมายเหตุ |
|---|---|---|---|---|
| Documentation | 1.5 | 1.0 | 2.5 | มีแค่ centralize Swagger และยังไม่สมบูรณ์ |
| Auth consistency | 3.5 | 2.0 | 1.0 | vtrc-api ดีสุด แต่ cu-central-api public เยอะ centralize-api ไม่มี auth |
| Error model | 3.5 | 3.0 | 2.0 | มี code catalog แต่ไม่สม่ำเสมอ |
| Validation | 3.0 | 2.5 | 4.0 | centralize-api ใช้ class-validator (ดีสุด) |
| Versioning | 1.0 | 1.0 | 2.0 | ไม่มี v1/v2, centralize มี global prefix /api |
| Rate limiting | 1.0 | 1.0 | 1.0 | ไม่มีเลย |
| Observability | 2.0 | 2.0 | 2.0 | มี log แต่ไม่มี metrics/tracing |
| Testability | 1.0 | 1.0 | 1.5 | ไม่มี test ใน service ใด |
| Security posture | 2.5 | 2.0 | 1.5 | apiKey ฝัง source, centralize ไม่มี auth |
| Performance | 3.0 | 2.5 | 2.5 | ไม่มี cache, DataLoader หรือ batching |
คะแนนรวม
| Service | คะแนนเฉลี่ย | ระดับ |
|---|---|---|
| vtrc-api | 2.4 / 5 | ใช้งานได้ แต่มีหนี้เทคนิคสะสม |
| cu-central-api | 1.9 / 5 | เสี่ยงด้าน security (public operations เยอะ) |
| centralize-api | 1.9 / 5 | เสี่ยงด้าน security (ไม่มี auth) |
| ระบบรวม | 2.1 / 5 | ทำงานได้ แต่ต้องปรับปรุงด่วนหลายจุด |
ปัญหาเร่งด่วน — 10 อันดับแรก
เรียงตามความรุนแรง (severity × probability × impact)
1. 🔴 centralize-api ไม่มี auth จริง (@Public() ทุก route)
ที่ตั้ง: centralize-api/src/modules/employee/employee.controller.ts:38-120 (ทุก method)
ปัญหา: ทุก endpoint ใช้งานได้โดยไม่ต้อง JWT — ใครเข้าถึง intranet ก็ยิงได้
ผลกระทบ: ข้อมูล HR รั่ว — พนักงานทุกคน (เงินเดือน, ตำแหน่ง, หน่วยงาน)
แก้ไข: ลบ @Public() ออกจาก method ที่ sensitive + เปิดใช้ JWT guard จริง
2. 🔴 cu-central-api HRMI domain public ทั้งหมด (26 ops)
ที่ตั้ง: cu-central-api/main-api/src/typeDefs/hrmi.js (ทั้งไฟล์ไม่มี @auth)
ปัญหา: createLeaveDocument, fetchMedicalExpenses, ฯลฯ — ใครมี apiKey ก็ยิงได้
ผลกระทบ: สร้าง/ลบเอกสารลาของพนักงานคนอื่นได้
แก้ไข: เพิ่ม @auth ในทุก mutation + ตรวจ ownership ใน resolver
3. 🔴 apiKey ฝังใน source code
ที่ตั้ง:
vtrc-api/api/src/config.js:42-148(6 keys × 2 env)cu-central-api/main-api/src/lib/auth/auth.controller.js:257-271(2 keys)
ปัญหา: secret อยู่ใน git — ทุกคนที่ clone repo ได้ก็ได้ key
ผลกระทบ: apiKey รั่ว → ผู้โจมตีปลอมตัวเป็นแอป
แก้ไข: ย้ายไป env หรือ secret manager (AWS Secrets Manager, Vault)
4. 🔴 vtrc-api ใช้ 404 แทน 401 บน REST
ที่ตั้ง: vtrc-api/api/src/routes.js (หลายจุด เช่น 525, 580, 677, 729)
ปัญหา: auth fail → 404 ทำให้คิดว่าไฟล์ไม่มี จริง ๆ token หมดอายุ
ผลกระทบ: debug ยาก, frontend จัดการ error ผิด
แก้ไข: เปลี่ยนเป็น 401 + JSON error body
5. 🟠 /webdeployment endpoint ไม่มี auth
ที่ตั้ง: vtrc-api/api/src/routes.js:975
ปัญหา: trigger deploy script โดยไม่ต้อง auth
ผลกระทบ: ผู้โจมตีสามารถ trigger deploy ได้ (RCE-level)
แก้ไข: เพิ่ม HMAC signature check หรือ IP whitelist
6. 🟠 static file serving เปิดหมด
ที่ตั้ง: vtrc-api/api/src/routes.js:986-988
ปัญหา: app.use('/', express.static(PWD + '/storage')) — ทุกไฟล์ใน storage เข้าถึงได้โดยไม่ต้อง auth
ผลกระทบ: ไฟล์ sensitive (เช่น payslip ที่อัปโหลด) รั่ว
แก้ไข: เพิ่ม auth middleware หรือใช้ presigned URL เท่านั้น
7. 🟠 ไม่มี rate limiting
ที่ตั้ง: ทั้ง 3 services
ปัญหา: ไม่มี express-rate-limit หรือ custom throttle
ผลกระทบ: DDoS ได้ง่าย โดยเฉพาะ endpoint PDF/export ที่ใช้ CPU หนัก
แก้ไข: ติดตั้ง rate limit middleware (เช่น 100 req/min ต่อ IP)
8. 🟠 typo ติดใน schema สาธารณะ
ที่ตั้ง:
ResposeStatus(ควรเป็นResponseStatus) — vtrc-apiINTENAL_SERVER_ERROR(ควรเป็นINTERNAL) — cu-central-apiSubscribtion(ควรเป็นSubscription) — cu-central-apifetchAuthSessionMoblie(ควรเป็นMobile) — vtrc-api
ปัญหา: typo ติดใน schema ที่ frontend ใช้อยู่ → แก้ไม่ได้โดยไม่ break client
ผลกระทบ: ดูไม่เป็นมืออาชีพ, debug สับสน
แก้ไข: coordinate กับ frontend + เปลี่ยนใน major version
9. 🟡 cu-central-api /auth/signinbypass เปิดอยู่
ที่ตั้ง: cu-central-api/main-api/src/lib/auth/auth.js:127-149
ปัญหา: endpoint ที่ login ไม่ต้องใช้ password
ผลกระทบ: ถ้าเปิดใน production — เป็น backdoor
แก้ไข: ตรวจ env ว่าถูก disable ใน prod หรือยัง
10. 🟡 PDF deletePDF 5 วินาที
ที่ตั้ง: vtrc-api/api/src/routes.js:73-82
ปัญหา: หลัง generate PDF แล้ว 5 วินาที deletePDF ลบไฟล์
ผลกระทบ: ถ้า download ช้ากว่า 5 วิ → ไฟล์หาย → 404
แก้ไข: ใช้ streaming หรือเพิ่ม timeout เป็น 5 นาที
ปัญหาที่พบบ่อยตอนพัฒนา
1. ไม่รู้ว่าใช้ GraphQL หรือ REST
- ใช้ GraphQL สำหรับ query/mutation ทั่วไป
- ใช้ REST สำหรับ binary (PDF, file, Excel)
- frontend ส่วนใหญ่ใช้ทั้งคู่ในหน้าเดียวกัน
2. SourceDB ต้องระบุทุกครั้ง
- ใน cu-central-api SourceDB มาจาก profileKey
- ถ้าลืม → query อาจ return ข้อมูลผิดคน
3. JWT 2 ตัว
- frontend ใช้ JWT vtrc-api เท่านั้น
- แต่ debug ฝั่ง vtrc-api ต้องรู้ว่ามี JWT cu-central-api ซ่อนอยู่ใน Session
4. Forward retry ทำให้ latency สูง
- ถ้า JWT cu-central-api หมดอายุ → refresh + retry
- เพิ่ม 200-500 ms ต่อ request
5. Error code ไม่สม่ำเสมอ
- vtrc-api:
TOKEN_EXPIRED - cu-central-api:
ACCESS_TOKEN_INVALID - centralize-api: 401 (HTTP)
- client ต้องจัดการทั้งหมด
แนวทางการปรับปรุงระยะยาว
ระยะสั้น (1-3 เดือน)
- ย้าย apiKey ออกจาก source → env / secret manager
- เพิ่ม rate limiting ทุก service
- เปลี่ยน REST 404 → 401 ใน vtrc-api
- ลบ
/webdeploymentหรือเพิ่ม auth - ตรวจ
/auth/signinbypassใน prod
ระยะกลาง (3-6 เดือน)
- เพิ่ม
@authใน HRMI ของ cu-central-api - เปิด JWT guard จริง ใน centralize-api (ลบ
@Public()บาง route) - เพิ่ม DataLoader ใน resolver ที่มี N+1
- migrate memoryStorage → diskStorage ใน multer
- เพิ่ม OpenTelemetry เพื่อ trace forward chain
ระยะยาว (6-12 เดือน)
- API versioning —
/api/v1/.../api/v2/... - GraphQL schema registry — ทำให้ breaking change ตรวจได้
- migrate Apollo → Apollo Server 4 (ปัจจุบันใช้ v2)
- consolidate cu-central-api + centralize-api — มี 2 service ที่ทำงานคล้ายกัน
- move file storage → S3/GCS — ลด disk dependency
Best practices สำหรับทีมใหม่
ตอนเขียน GraphQL operation ใหม่
- ใช้
@auth(accessRole: [...])เสมอ (ยกเว้น field ที่ตั้งใจ public) - ใช้ custom scalar (
Date,JSON) แทน string - ระบุ return type ให้ชัดเจน — หลีกเลี่ยง
JSONเมื่อเป็นไปได้ - ใช้ input type สำหรับ mutation ที่มี argument เยอะ
ตอนเขียน REST endpoint ใหม่
- ตัดสินใจ auth ให้ชัดเจน (apiKey / JWT / signed URL / public)
- ใช้ HTTP status ที่ถูกต้อง (200/400/401/404/500)
- มี response envelope ที่สม่ำเสมอ (
{ data, error }) - เพิ่ม rate limit
ตอนเขียน forward (vtrc-api → cu-central-api)
- ใช้
GraphqlCDWithTokenเสมอ (ไม่ใช่ fetch ตรง ๆ) - จับ error ที่ cu-central-api ส่งกลับ + map ให้เป็น vtrc-api error code
- log ทุก forward call (เพื่อ debug)
- ระวัง SourceDB — ส่ง profileKey เสมอ
ตอน debug
- ดู บท 10.2 ก่อน — ตรวจ header
- ดู บท 10.7 — เข้าใจ error code
- ดู บท 10.9 — ถ้าเป็น forward chain
- ดู log ฝั่ง server — error ที่ frontend เห็นอาจถูก mask ใน prod
สรุป Volume 11
Volume นี้ครอบคลุม API surface ของระบบ VTRC ทั้งหมด — 3 services, 400 endpoints/operations, 3 ภาษา (JS, JS, TS), 2 frameworks (Apollo, NestJS)
จุดแข็ง
- Service layering ชัดเจน — frontend → vtrc-api → cu-central-api
- GraphQL ใช้แล้วดี — frontend มี type safety
- Signed URL สำหรับ PDF — ป้องกัน enumeration
- centralize-api มี Swagger — เริ่มต้น documentation
- class-validator ใน centralize-api — validation ดี
จุดอ่อน
- Auth coverage ไม่สม่ำเสมอ — public operations เยอะ
- apiKey ฝัง source — secret management ไม่ดี
- ไม่มี rate limit — DDoS ได้ง่าย
- ไม่มี test — ทุก service
- typo ติดใน schema — ดูไม่เป็นมืออาชีพ
สิ่งที่ต้องทำต่อ
- ปรับปรุง security — ดู Volume 10
- เพิ่ม business logic docs — ดู Volume 12
- ปรับปรุง infrastructure — ดู Volume 13
ไฟล์อ้างอิงหลัก
| ไฟล์ | หน้าที่ |
|---|---|
vtrc-api/api/src/index.js | Apollo + Express bootstrap |
vtrc-api/api/src/routes.js | REST 30 endpoints |
vtrc-api/api/src/typeDefs/*.js | GraphQL schema (44 files) |
vtrc-api/api/src/resolvers/*.js | GraphQL resolvers (42 files) |
vtrc-api/api/src/centralize/controllers/graphql.js | Forward engine |
vtrc-api/api/src/centralize/graphql/queries.js | 68 forward query templates |
vtrc-api/api/src/centralize/graphql/mutations.js | 17 forward mutation templates |
vtrc-api/api/src/lib/responErrors.js | Error factory |
cu-central-api/main-api/src/index.js | cu-central Apollo + Express |
cu-central-api/main-api/src/typeDefs/*.js | cu-central schema (32 files) |
cu-central-api/main-api/src/lib/auth/auth.js | REST auth endpoints |
cu-central-api/main-api/src/lib/responseAndLog.js | Error factory |
centralize-api/src/main.ts | NestJS bootstrap |
centralize-api/src/modules/employee/employee.controller.ts | 14 endpoints |
centralize-api/libs/exception/http-exception.filter.ts | Error filter |
centralize-api/docs/document.config.ts | Swagger config |
Volume 11 จบลงตรงนี้
Volume ถัดไป: Volume 12 · Business Logic — เจาะลึก business rule ของแต่ละ domain (leave, welfare, fund, payroll)