Security Uplift — บรีฟสำหรับ agent ที่จะ apply ให้ service หนึ่งตัว
เอกสารใบสั่งงานสำหรับคน (หรือ AI) ที่ไม่เคยแตะระบบนี้มาก่อน: ต้องได้อะไรก่อนเริ่ม · ลำดับที่สลับไม่ได้ · สิ่งที่ห้ามตัดสินใจเอง · และเกณฑ์ว่า apply เสร็จแล้วจริง
อัปเดต: 2026-09-07
บรีฟสำหรับ agent ที่จะ apply ให้ service หนึ่งตัว
หน้านี้ไม่ได้สอนว่ากลไกทำงานยังไง และไม่มีขั้นตอนติดตั้ง — มันคือ ใบสั่งงาน ที่บอกว่า ทำงานนี้ต้องได้อะไรมาก่อน ทำตามลำดับไหน อะไรที่ห้ามตัดสินใจเอง และจะรู้ได้ยังไงว่าเสร็จแล้วจริง
ขั้นตอนจริงอยู่ที่หน้าติดตั้งรายกลไก (ภาพรวม) · สิ่งที่พังได้อยู่ที่ กับดักและคำเตือน · เปิดสองหน้านั้นคู่กันตลอดเวลาที่ลงมือ
0. งานนี้คืออะไร และไม่ใช่อะไร
คือ: เพิ่ม dependency กลาง (SupApp_util_lib) เข้า service หนึ่งตัว · wire DI กับ pipeline ·
ใส่ config ที่ปิดสวิตช์ไว้ทั้งหมด · แปะ attribute เฉพาะเส้นที่ตกลงกันไว้ · แล้วพิสูจน์ว่าของเดิมไม่พัง
ไม่ใช่: การเปิดใช้งานจริง · การเปลี่ยนพฤติกรรมของ endpoint ที่มีคนใช้อยู่ · การตัดสินว่า endpoint ไหน ควรมี role อะไร · การตัดสินว่าคอลัมน์ไหนควรถูกเข้ารหัส
รูปของ “เสร็จ” ที่ถูกต้องคือ: build/test ผ่านเท่าเดิม · สวิตช์ทุกตัวยัง
false· ของเดิมทำงานเหมือนเดิมทุกอย่าง ไม่ใช่ “เปิด flag แล้วเห็น 200”
1. ต้องได้อะไรมาก่อนเริ่ม — ขาดข้อไหนให้หยุดแล้วถามก่อน
| ต้องมี | ทำไม | ขาดแล้วเป็นยังไง |
|---|---|---|
| repo ของ service ที่จะ apply | ที่ทำงานหลัก | — |
repo Backend_Iac | config ที่ใช้จริงบน cluster อยู่ที่นั่น ไม่ใช่ในรีโป service | แก้ config แล้วไม่มีผลบน cluster · และ check-config-parity.py ทำ build fail |
| ชื่อ endpoint ที่จะใช้ทดสอบ (อย่างน้อย 2 เส้น) | เกณฑ์เลือกเส้นเป็น business judgment | เดาเองแล้วไปแตะ write path = เสี่ยงข้อมูลจริง |
| คนที่มีสิทธิ์ Key Vault | กุญแจของกลไก B / C / D ต้องอยู่ใน KV ก่อน เปิดสวิตช์ | เปิดสวิตช์แล้ว แอปไม่ boot |
| คำตอบว่าจะทำกลไกไหนบ้าง (A–F) | แต่ละตัวคนละความเสี่ยง ไม่จำเป็นต้องทำครบ | ทำเกินที่ขอ = scope บาน review ยาก |
ตรวจ 2 อย่างนี้ในรีโปก่อนตัดสินว่าทำกลไกไหนได้
grep -rn "DbContext" src/ # ไม่มี = กลไก C (at-rest) ทำไม่ได้ ข้ามไปเลย
grep -rn "\[Authorize" src/ # 0 hit = กลไก E ทดสอบไม่ได้ในรอบนี้ (ดูข้อ 3)
2. ลำดับที่สลับไม่ได้
- bump package ก่อน แล้ว build ให้ผ่าน โดยยังไม่ wire อะไรเลย — แยกปัญหา dependency ออกจากปัญหา wiring
- หาไฟล์ DI / pipeline ของ service เองก่อนแก้ — อย่าเปิด
Program.csแล้วแปะ หลาย service มีAddAppSecurity()/UseAppPipeline()ของตัวเอง แล้วProgram.csเรียกบรรทัดเดียวgrep -rn "AddAuthentication\|AddAuthorization(" src/ grep -rn "UseAuthorization()" src/ - wire DI + pipeline → boot → รัน test เดิมทั้งชุด ต้องผ่านเท่าเดิมทุกตัว · ตกแม้แต่ตัวเดียว = wiring ผิด ไม่ใช่เรื่อง flag
- ใส่ config ครบทุก key โดย
Enabledยังเป็นfalse— ใส่ที่ baseappsettings.json(ไฟล์นี้ไม่ถูก IaC overlay ทับ) - แปะ attribute เฉพาะเส้นที่ตกลงไว้
- หยุด แล้วรายงาน — การเปิดสวิตช์บน environment จริงเป็นการตัดสินใจของเจ้าของงาน ไม่ใช่ของคนทำ
🔴 A ต้องมาก่อนเสมอ · D ต้องมี B อยู่ก่อน (เปิด D โดยไม่มี B = แอปไม่ boot) ·
C ต้องมี DbContext
3. ห้ามตัดสินใจเอง — 6 ข้อนี้หยุดแล้วถามเสมอ
- ห้ามเปิดสวิตช์ (
Enabled,EncryptNewWrites) บน environment ไหนก็ตาม โดยไม่ได้รับอนุญาตเป็นรายครั้ง - ห้ามเติม
[Authorize]หรือ[Authorize(Roles = "…")]ที่ยังไม่มี — endpoint ที่เคยเรียกได้จะเรียกไม่ได้ สำหรับ caller ที่ไม่มี role นั้น นี่คือ business change ไม่ใช่งาน wiring - ห้ามแปะ
[EncryptedAtRest]บนคอลัมน์ที่ยังไม่มีมติ — สวิตช์มีตัวเดียวและคุมทุกคอลัมน์ที่แปะพร้อมกัน · และ การเปิดบน env จริงย้อนไม่สะอาด (แถวที่เป็น ciphertext แล้วไม่กลับเป็น plaintext) - ห้ามสลับ
Coverageเป็นRequireAll— โหมดนั้นครอบทุก endpoint และต้องไล่[Skip…]ให้ครบทั้งรีโปก่อน เป็นงานแยกรอบ - ห้ามถอด
EnableBuffering()เดิมของ service ออก ไม่ว่าด้วยเหตุผลใด — กลไก A พึ่งมันอยู่ - ห้ามแตะ config ของ prod —
Backend_Iacไม่มีโฟลเดอร์ prod ให้ใส่ค่าอยู่แล้ว ถ้ารู้สึกว่าต้องสร้าง แปลว่าเข้าใจผิด
ถ้าเจอทางแยกที่ตัดสินไม่ได้: หยุด เขียนว่าติดอะไร ตัวเลือกมีอะไร แล้วถาม อย่าเลือกเงียบ ๆ แล้วทำต่อ
4. เรื่อง config ที่พลาดกันบ่อยที่สุด
แก้ค่าใน env ไหน ต้องแก้ 2 ที่เสมอ
{service}/src/{Service}01.API/appsettings.{ENV}.json ← ค่าที่ dev อ่านตอนรันบนเครื่อง
Backend_Iac/config/{service}/{env}/appsettings.json ← ค่าที่ใช้จริงบน cluster
ตอน build CI เอาไฟล์ฝั่ง IaC ทับทั้งไฟล์ ไม่ merge ⇒ แก้ฝั่ง service อย่างเดียว = ไม่มีผลบน cluster · ลืมฝั่ง IaC = build fail ที่ด่าน parity · key ใหม่ทุกตัวต้องเข้า IaC ครบทุก env ที่ service นั้นรัน
ค่าที่เป็น secret (connection string, กุญแจ) อยู่ใน Key Vault เสมอ และมาถึง pod เป็น env var ⇒
แก้ appsettings ไม่มีผลกับค่าพวกนี้
5. ถ้ามีการแก้ entity หรือ schema
[EncryptedAtRest]ทำให้ค่าที่เก็บยาวขึ้น ~2.5–3 เท่า ⇒ ถ้าคอลัมน์แคบไปต้องขยาย ซึ่งเป็น migration- migration ทั้งชุด (entity · EF config · migration ·
ModelSnapshot) ต้อง author บน branchMIGRATIONไม่ใช่ feature branch แล้ว mergeMIGRATIONกลับเข้า feature branch — มี hook กันไว้อยู่แล้ว จะ deny ให้เอง ถ้าทำผิดที่ - ถ้าไม่แน่ใจว่าคอลัมน์กว้างพอไหม ถามก่อน อย่าเดา — พังตอน insert ไม่ใช่ตอน build
6. พิสูจน์ยังไงว่า apply เสร็จแล้วจริง
ทั้งหมดนี้ทำโดย สวิตช์ยังปิด
| เช็ค | ผลที่ถูก |
|---|---|
dotnet build -c Release | exit 0 และจำนวน warning เท่ากับ baseline ก่อนแก้ |
dotnet test -c Release | จำนวน test ที่ผ่าน เท่ากับ baseline ก่อนแก้ |
| boot ขึ้นมาจริงต่อ dev Key Vault + Redis | ไม่มี DI error · /health = 200 |
| ยิง endpoint ที่แปะ attribute ไว้ | 200 พร้อม body เป็น plaintext เหมือนเดิม |
| ยิง endpoint อื่นที่ไม่ได้แปะอะไร | เหมือนเดิมทุกอย่าง |
🔴 ต้องวัด baseline ก่อนแก้ บน commit เดียวกัน — “test ผ่าน 350 ตัว” ไม่มีความหมายถ้าไม่รู้ว่าก่อนแก้ผ่านกี่ตัว
ห้ามรายงานว่าเสร็จโดยไม่มี exit code จริงของคำสั่งที่รันเอง — ไม่ใช่ “น่าจะผ่าน” ไม่ใช่ “should work”
7. ตอนจะทดสอบกลไก A ต้องมี request ที่เซ็นจริง
service ตรวจลายเซ็นอย่างเดียว ไม่ได้เป็นคนสร้างลายเซ็น ⇒ curl ธรรมดายิงแล้วได้ 401 SIG_MISSING_HEADER
เสมอ ซึ่งไม่ได้แปลว่าอะไรผิด
ทางที่ใช้ได้มี 2 ทาง ทั้งคู่ต้องขอจากเจ้าของงาน (ไม่ได้อยู่ในรีโป service):
- Postman collection ที่เซ็น request ให้เองได้
- หน้าทดสอบบนเว็บ ที่กดปุ่มแล้วยิงด้วยลายเซ็นจริงจากเบราว์เซอร์
ยังไม่มีของสองอย่างนี้ = ยังพิสูจน์ A แบบเปิดสวิตช์ไม่ได้ ให้ทำถึงขั้น “wire แล้ว build/test ผ่าน” แล้วหยุด รายงานว่าติดตรงนี้ — อย่าประดิษฐ์วิธียิงเองแล้วสรุปว่าผ่าน
8. ลำดับการอ่าน
- ภาพรวม 6 กลไก — อ่านทั้งหน้าก่อนเริ่ม (สั้น)
- หน้าติดตั้งของกลไกที่จะทำ — A · B · C · D · E · F
- กับดักและคำเตือน — เปิดคู่กันตอนลงมือ ทุกขั้นในหน้าติดตั้งมีลิงก์ชี้มาที่หัวข้อของมัน
- ไม่เข้าใจว่ากลไกทำงานยังไง → หน้า 101 ของกลไกนั้น (ลิงก์อยู่หัวหน้าติดตั้งทุกหน้า)
9. รายงานกลับมาแบบไหน
- ไฟล์ที่แตะ และแตะอะไร (ไม่ใช่ diff ทั้งก้อน)
exit codeจริงของ build และ test พร้อมตัวเลข เทียบกับ baseline- กลไกที่ทำไม่ได้ พร้อมเหตุผลจากโค้ดจริง (เช่น
grep "\[Authorize" src/= 0 hit) - ทางแยกที่หยุดไว้เพราะตัดสินใจเองไม่ได้
- key ที่เพิ่มเข้า IaC และ env ที่ยังขาด