🌐
← Secure by Design

SECURE BY DESIGN DAY 13

เริ่มทำควิซ ⚡
Part 3: Applying the Fundamentals | Chapter 13

Guidance on Microservices

Distributed Bounded Contexts 🌐⚡
📌 TITLE ANCHOR QUESTION ทำไมบทนี้ถึงชื่อนี้? และ Microservices เกี่ยวข้องกับ Security อย่างไร?

คำตอบและหมุดเชื่อมโยง: สถาปัตยกรรม Microservices นิยมนำมาใช้เพื่อแก้ปัญหาความเทอะทะของ Monolith แต่การแตกกระจายระบบออกเป็นนับสิบนับร้อยบริการย่อย ทำให้ "พื้นผิวการโจมตี (Attack Surface) ขยายใหญ่ขึ้นมหาศาล"

ผู้เขียนตั้งชื่อบทนี้ว่า "Guidance on microservices" เพื่อให้แนวทางชัดเจนว่า "เราไม่สามารถมองความปลอดภัยแบบคับแคบในระดับบริการเดี่ยว (Microservices Myopia) ได้อีกต่อไป" ทุกบริการต้องถูกปฏิบัติเหมือนเป็น Bounded Context ที่เข้มงวด ที่ต้องเลิกใช้ Anemic CRUD REST API หันมาใช้ Domain Operations, ส่งต่อ Identity Tokens (JWT) เพื่อไม่ให้สิทธิ์สูญหายกลางทาง, และทำ Domain-Oriented Logging ที่มี Traceability สมบูรณ์แบบข้ามเครือข่ายครับ!

Part 1 & 2 ที่ผ่านมา (Recap)

Days 1-7: รากฐาน DDD, Immutability, Domain Primitives, State Integrity, และ Entity Relay

ตำแหน่งปัจจุบัน (Where We Are)

Day 13 จาก 14 วัน — วันรองสุดท้าย! สวมเกราะความปลอดภัยและ DDD ให้แก่ระบบกระจายตัว (Distributed Systems)

เป้าหมายประจำวัน (Core Mission)

เรียนรู้ Domain Operations vs CRUD, การปกป้อง CIA-T & Sensitive Data, และ Domain-Oriented Logger API

02

เรื่องราวและมโนทัศน์เชิงลึก (Real Scenarios & Distributed Architecture)

🔓 SCENARIO 2.1 • กับดัก ANEMIC CRUD REST API และการแก้ไขด้วย DOMAIN OPERATIONS API Invariants

📖 เรื่องราวจริง: ช่องโหว่จากการเปิด Endpoint แบบ CRUD

ทีมพัฒนาสร้าง CustomerService ในสถาปัตยกรรม Microservices โดยเปิด REST API สไตล์ CRUD แบบเปิดกว้าง: PUT /customers/{id}/activated พร้อมส่ง Body {"activated": true}

💥 จุดเปราะบางทาง Security และ Logic:
• กฎธุรกิจระบุว่า "ลูกค้าจะถูก Activated ได้ก็ต่อเมื่อ 1) เซ็นสัญญาทางกฎหมายแล้ว และ 2) ชำระเงินงวดแรกเรียบร้อยแล้ว"
• การเปิด API แบบ CRUD ทำให้บริการอื่น (หรือแฮกเกอร์ที่ยิง REST API ตรงๆ) สามารถส่ง true เข้ามาเปิดใช้งานบัญชีได้ทันที โดย "ข้ามขั้นตอนการเซ็นสัญญาและการจ่ายเงิน" อย่างสิ้นเชิง!

🛡️ ปรับสู่ Domain Operations ใน Microservice API

กฎเหล็ก: "Microservice ไม่ใช่แค่ถังเก็บข้อมูล CRUD บนเครือข่าย แต่คือ Bounded Context ที่ต้องปกป้อง Invariants ของตนเอง"

ปิดเมธอด setActivated ทิ้ง แล้วเปิดเฉพาะ Endpoints ที่สะท้อนกิจกรรมทางธุรกิจจริง:

POST /customers/{id}/legal-agreements
POST /customers/{id}/confirmed-payments
POST /customers/{id}/welcome-calls
🎯 เมธอด isActivated() จะคำนวณสถานะภายในเองว่าเงื่อนไขครบทั้ง 3 ข้อหรือยัง หากอนาคตธุรกิจเพิ่มเงื่อนไขที่ 4 เราสามารถปรับแก้ภายในบริการได้ทันทีโดยไม่กระทบสัญญา API ของบริการภายนอกแม้แต่บรรทัดเดียว!
🕵️ SCENARIO 2.2 • ข้อมูลอ่อนไหวจากการรวมศูนย์ (DATA AGGREGATION) และกรอบ CIA-T ข้ามบริการ Identity Propagation

🚗 ปริศนา Sensitive Data จาก Data Aggregation

คำว่า "Sensitive Data (ข้อมูลอ่อนไหว)" ไม่ได้จำกัดอยู่แค่ข้อมูลลับสุดยอด เช่น รหัสผ่าน หรือเลขบัตรประชาชน:

• เลขทะเบียนรถยนต์ (Plate Number): ในบริการที่จอดรถ ไม่ใช่ข้อมูลลับเพราะติดอยู่ท้ายรถมองเห็นได้ทั่วไป
• เมื่อเกิด Data Aggregation: นำ Plate Number + Geolocation + Timestamp มารวมกันในบริการวิเคราะห์ จะกลายเป็น "ข้อมูลสอดแนมการเดินทางส่วนบุคคล" ที่ต้องปกป้องมิติ Confidentiality ทันที!

🛡️ กรอบ CIA-T ในสถาปัตยกรรม Microservices

Confidentiality & Identity Tokens: เมื่อ Request ไหลข้ามบริการ 3-4 ชั้น บริการปลายทางมักสูญเสียบริบทว่าใครสั่งงาน ต้องส่ง Identity Token (JWT) แนบไปด้วยเสมอ เพื่อให้ทุกบริการตรวจ Authorization ได้ด้วยตนเอง
Integrity & Authoritative Source: ดึงข้อมูลจากบริการที่เป็นเจ้าของข้อมูลจริง (Authoritative Source) เสมอ แทนการก็อปปี้ไปพักไว้หลายที่ และใช้ Cryptographic Signature (HMAC/SHA-256) ป้องกันการปลอมแปลง
IDENTITY PROPAGATION FLOW (OAUTH 2.0 / JWT)
Client ──(JWT Token)──▶ API Gateway ──(Pass JWT)──▶ Order Service ──(Pass JWT)──▶ Payment Service
📜 SCENARIO 2.3 • TRACEABILITY ข้ามบริการ และสถาปัตยกรรม DOMAIN-ORIENTED LOGGER API Auditing & Logging

🏷️ 4 องค์ประกอบเหล็กของ Microservices Logging

เมื่อมีการขยายสเกลเป็นหลายร้อย Pods/Containers ทุก Log บรรทัดที่ส่งเข้า Centralized Logging ต้องมี 4 เสาหลักเพื่อรับประกัน Traceability:

1. Service Name เช่น booking-service
2. Service Version เช่น v2.4.1
3. Unique Instance ID เช่น pod-8f9d76-x81
4. Trace ID (Correlation) UUID วิ่งข้ามทุก Services

🛡️ Domain-Oriented Logger API

การใช้ logger.info() ดั้งเดิม เสี่ยงต่อการเผลอพิมพ์ข้อมูลลับปะปนลงไป วิธีแก้คือสร้าง Interface ตามกิจกรรมทางธุรกิจ:

// Interface ชัดเจนตาม Ubiquitous Language:
public interface BookingLogger {
  void bookingCanceled(BookingId id, User user);
  void bookingFailed(BookingId id, Reason r);
}
🎯 คลาสธุรกิจเรียกเฉพาะเจาะจง ส่วน Logger Implementation เบื้องหลังจะแยกข้อมูลลับ (Audit vs. Technical Logs) และแปลงเป็น Structured JSON ให้อัตโนมัติ!
3 คุณลักษณะสำคัญของ MICROSERVICE ที่ดี (DESIGNED FOR RESILIENCE)
1. Independent Runtimes

มี Process และหน่วยความจำของตนเอง ไม่แชร์ Runtime หรือฐานข้อมูลข้ามกัน

2. Independent Updates

Deploy และทดสอบเป็นเอกเทศได้ตลอดเวลาโดยไม่ต้องรอ Deploy พร้อมบริการอื่น (ไม่ใช่ Distributed Monolith)

3. Designed for Down

พร้อมทำงานต่อได้เสมอแม้บริการแวดล้อมอื่นล่ม ผ่าน Circuit Breakers, Bulkheads และ Fallback

03

แบบฝึกหัดปฏิบัติตามสถานการณ์จริง (Hands-on Refactoring)

Before: Anemic CRUD API & Raw Logging เสี่ยงข้ามกฎธุรกิจ & ไร้ Traceability
// โค้ดเดิม: เปิด API แบบ CRUD และใช้ Generic Logger สุ่มเสี่ยง
public class CustomerController {
    private static final Logger logger = LoggerFactory.getLogger(CustomerController.class);
    private CustomerRepository repository;

    // 💥 Danger 1: Anemic CRUD - ให้คนนอกสั่งเปิดใช้งานได้โดยข้ามกฎธุรกิจ!
    @PutMapping("/customers/{id}/status")
    public ResponseEntity<Void> updateStatus(@PathVariable String id, @RequestBody StatusDto dto) {
        // 💥 Danger 2: Log สตริงดิบ ไม่มี Trace ID หรือ Instance ID
        logger.info("Updating status for " + id + " to " + dto.isActivated());

        Customer customer = repository.findById(id);
        customer.setActivated(dto.isActivated()); // ข้ามสัญญาและการจ่ายเงิน!
        repository.save(customer);
        return ResponseEntity.ok().build();
    }
}
⚠️ จุดบกพร่องร้ายแรง: ใครก็สามารถยิง isActivated: true เข้ามาข้ามขั้นตอนการจ่ายเงินและเซ็นสัญญาทางกฎหมายได้ทันที และ Log ไม่มี Trace ID ทำให้แกะรอยข้าม Microservices ไม่ได้
After: Domain Operations & Domain-Oriented Logger Bounded Context & Trace ID
// โค้ดใหม่: ปิด CRUD หันมาเปิดเฉพาะ Domain Operations ที่สื่อเจตนาทางธุรกิจ
public class CustomerController {
    private final CustomerApplicationService customerService;
    private final CustomerAuditLogger auditLogger; // Domain Logger

    public CustomerController(CustomerApplicationService svc, CustomerAuditLogger log) {
        this.customerService = notNull(svc);
        this.auditLogger = notNull(log);
    }

    // 1. Domain Operation: บันทึกการเซ็นสัญญา
    @PostMapping("/customers/{id}/legal-agreements")
    public ResponseEntity<Void> addLegalAgreement(
            @PathVariable String id, @RequestBody AgreementDto dto,
            @RequestHeader("X-Trace-Id") String rawTrace) {

        CustomerId customerId = new CustomerId(id);
        AgreementId agreementId = new AgreementId(dto.getAgreementId());
        TraceId traceId = new TraceId(rawTrace);

        customerService.addLegalAgreement(customerId, agreementId);
        auditLogger.legalAgreementAdded(customerId, agreementId, traceId);
        return ResponseEntity.accepted().build();
    }

    // 2. Domain Operation: บันทึกการชำระเงิน (คำนวณ isActivated ภายในเอง!)
    @PostMapping("/customers/{id}/confirmed-payments")
    public ResponseEntity<Void> addConfirmedPayment(...) { /* ... */ }
}
🛡️ จุดเปลี่ยนสำคัญ: เลิกเปิด API แบบ setActivated แต่เปลี่ยนเป็น Domain Operations ที่ชัดเจน, บังคับแปลงข้อมูลเข้า Domain Primitives ทันที, และใช้ Domain-Oriented Logger ร่วมกับ Trace ID ปลอดภัย 100%!
04

ชุดควิซประเมินความรู้ประจำวัน

ตอบปุ๊บ รู้ผลเฉลยทันที พร้อมคำอธิบายและหลอดพลังงาน Microservices Charge

Distributed Energy
0 / 10
📌 CLOSING TITLE CONNECTION WRAP-UP สรุปหมุดเชื่อมโยงกลับหาหัวข้อบท

สรุปการเชื่อมโยงกลับสู่ Chapter 13 — Guidance on microservices

เรื่องราวการเลิกใช้ Anemic CRUD API หันมาใช้ Domain Operations, การส่งต่อ Identity Tokens ป้องกันสิทธิ์สูญหาย, และการสร้าง Domain-Oriented Logger API ในวันนี้ ล้วนเป็นคำตอบที่ชัดเจนของหัวข้อบท "Guidance on microservices" ว่า สถาปัตยกรรม Microservices จะปลอดภัยได้ ก็ต่อเมื่อเราปฏิบัติต่อแต่ละบริการในฐานะ Bounded Context ที่เข้มงวด การออกแบบ API ให้สะท้อนกิจกรรมทางธุรกิจจริง และการเฝ้าระวังมิติ CIA-T ข้ามทั้งระบบ จะช่วยเปลี่ยนระบบกระจายที่ซับซ้อนให้กลายเป็นป้อมปราการที่แข็งแกร่งและปลอดภัยจากภายในสู่ภายนอกครับ!

พร้อมก้าวสู่บทสรุปส่งท้ายของการเดินทาง 14 วันแล้วหรือยัง? Next: Day 14 — Chapter 14: A final word: Don’t forget about security! (สร้างวัฒนธรรม Antifragile Security) ➔