Private Docs

IMPL PLAN 06 — Secrets & Key Management

ล้างหนี้เก่า (rotate + purge git history) และวางวินัยใหม่ (fail-fast, rotation policy) บน Key Vault ที่มีโครงสร้างครบแล้ว

อัปเดต: 2026-07-07

IMPL PLAN 06 — Secrets & Key Management (Key Vault)

วันที่: 07/07/2026 · สถานะ: ⏳ รอ verify · Priority: 🔴 0.1 ผูก Phase 0 / ที่เหลือ Phase 2 อ้างอิง: DISCUSSION หมวด 6 · SG-02a/b/c, SG-19 จาก COMPLIANCE

สรุป

โครงสร้าง KV มีครบแล้ว (KV ทุก service + CSI driver + Workload Identity + ServicePrefixKeyVaultSecretManager) — งานคือ ล้างหนี้เก่า (rotate ของที่รั่ว + purge git history) และ วางวินัยใหม่ (fail-fast, rotation policy, least-privilege audit)


Sequence Diagram — เส้นทาง Secret ที่ถูกต้อง (target state)

sequenceDiagram
    autonumber
    participant Dev as Developer
    participant ADO as Azure DevOps
    participant KV as Key Vault
    participant CSI as CSI Driver / Config Provider
    participant Pod as Service Pod

    Note over Dev,KV: สร้าง/หมุน secret — ไม่ผ่าน git เลย
    Dev->>KV: az keyvault secret set (หรือ IaC pipeline ที่มีสิทธิ์)
    Note over KV: naming: {service-prefix}-{Section}--{Key}<br/>+ ตั้ง expiry date ทุก secret

    Note over Pod,KV: ตอน startup
    Pod->>CSI: mount / AddAzureKeyVaultWithServicePrefix
    CSI->>KV: GET secrets (Workload Identity — ไม่มี credential ใน pod)
    KV-->>CSI: ค่า secret
    CSI-->>Pod: inject เข้า IConfiguration
    Pod->>Pod: 🔧 ใหม่: fail-fast validation —<br/>secret บังคับตัวไหนว่าง/placeholder → throw ตอน boot

    Note over ADO,KV: เฝ้าระวัง
    ADO->>KV: scheduled pipeline ตรวจ expiry < 30 วัน → แจ้งเตือน
    ADO->>ADO: Gitleaks ใน CI กัน secret ใหม่เข้า git (IMPL_PLAN_01)

งาน 6.1 — ล้างหนี้เก่า (คู่กับ IMPL_PLAN_00 งาน 0.1)

#งานรายละเอียด
1Inventory secret ที่เคยรั่วเข้า git (SG-02a)รัน Gitleaks ทั้ง history ทุก repo: gitleaks detect --source . --log-opts="--all" → ได้ list สิ่งที่ต้อง rotate
2Rotate ทุกตัวใน listถือว่า compromised ทั้งหมด — ตามลำดับ rotate ใน IMPL_PLAN_00 (ค่าใหม่พร้อมก่อน revoke ค่าเก่า)
3ลบ demo project ที่มี EncryptionKey จริง (SG-02c)Sentinel repo — ลบ project + rotate key นั้น
4Purge git history (SG-02b)ดู procedure ด้านล่าง — ทำหลัง rotate เสร็จเท่านั้น (purge ก่อน rotate = เสียหลักฐานว่าอะไรรั่ว)

Purge Procedure (ต่อ repo ที่มี secret ใน history)

# ใช้ git-filter-repo (แนะนำกว่า BFG) — ตัวอย่าง
git clone --mirror <repo-url> repo-mirror; cd repo-mirror
git filter-repo --replace-text ..\secrets-to-purge.txt   # ไฟล์ list ค่า secret → ***REMOVED***
git push --force --all; git push --force --tags

⚠️ force-push กระทบทุกคน: ทุก clone/branch ค้างต้อง re-clone · PR เก่า diff เพี้ยน · ต้องประกาศ + นัด window + freeze merge — ตัดสินใจร่วมทีม (decision ในที่ประชุม) ไม่ทำเงียบๆ


งาน 6.2 — Fail-Fast Placeholder Validation (SG-19)

ปัญหา: prod config เป็น placeholder ว่าง — ถ้า KV inject พลาด service รันด้วยค่า dummy เงียบๆ

#ไฟล์Action
1Backend_Package/src/Extension/ConfigurationValidationExtensions.cs (ใหม่)ValidateRequiredSecrets(params string[] keys) — เรียกหลัง build config, throw ถ้าค่าว่าง/"__VAULT__"/"changeme"
2Program.cs ทุก service (ผ่าน Template ก่อน)ประกาศ list secret บังคับของตัวเอง เช่น ["ConnectionStrings:Default", "AzureAd:ClientSecret", "SignatureValidation:SecretKey"]

Verify: ตั้ง secret หาย 1 ตัวบน dev → pod CrashLoopBackOff พร้อม error message ชัดเจน (ดีกว่า run แล้วพังเงียบ)


งาน 6.3 — Rotation Policy + Expiry Alert

Secret ประเภทCadence เสนอวิธี rotate
API keys (service-to-service)6 เดือนdual-key window: ฝั่งรับรับ 2 key ชั่วคราว → caller เปลี่ยน → ถอด key เก่า
HMAC signing keys (IMPL_PLAN_02)6 เดือนเหมือน API key
AES encryption keys (field/at-rest)12 เดือน หรือเมื่อสงสัยรั่ว⚠️ ข้อมูลเก่าถอดด้วย key เดิม — ต้องทำ key versioning (enc: payload ผูก key id) หรือ re-encrypt batch — ออกแบบก่อน rotate ครั้งแรก
External partner credentials (DGA ฯลฯ)ตาม contract partnercoordinate กับ partner
Entra client secrets12 เดือน (ตั้ง expiry ใน Entra)สร้างใหม่ก่อนหมด → สลับ → ลบเก่า

Implement:

  1. ตั้ง expires attribute บนทุก secret ใน KV (az keyvault secret set-attributes --expires)
  2. Scheduled pipeline ใน Backend_Iac/pipelines/ — รายสัปดาห์ ตรวจ secret expiry < 30 วัน → แจ้ง Teams channel (มี azure-compliance tooling ช่วย scan ได้)

งาน 6.4 — Least-Privilege Audit (B5 trust boundary)

  1. Export role assignments ของทุก Managed Identity ต่อ KV: az role assignment list --scope <kv-id>
  2. ตรวจ: service A ไม่ควรอ่าน secret ของ service B ได้ — ถ้า KV แชร์กันใช้ ServicePrefixKeyVaultSecretManager filter ฝั่ง app อยู่แล้ว แต่สิทธิ์จริงที่ RBAC ต้องแคบด้วย (filter ฝั่ง app ไม่ใช่ security boundary)
  3. ผลลัพธ์: ตาราง identity × secret scope → แก้ role ที่กว้างเกิน (เช่น Key Vault Secrets Officer ที่ควรเป็น Secrets User)

Verify รวม

  • Gitleaks full-history scan = list ครบ + ทุกตัว rotate แล้ว
  • History purge เสร็จ + ทีม re-clone (ถ้าที่ประชุม approve)
  • ทุก service มี fail-fast validation + ทดสอบ secret หาย → boot fail
  • ทุก secret ใน KV มี expiry + alert pipeline รัน
  • ตาราง least-privilege ทำเสร็จ + role แคบลง

⚠️ ข้อควรระวัง

  1. ห้าม purge ก่อน rotate — และห้าม rotate โดยไม่มีค่าใหม่พร้อมใช้
  2. AES key rotation ต้องมี key versioning ก่อน — มิฉะนั้นข้อมูลเก่าถอดไม่ได้ (data loss)
  3. Force-push เป็น hard-to-reverse — ต้องมี mirror backup ก่อนทำ + approve จากทีมเป็นลายลักษณ์

🎯 ถ้าเป็นผมจะทำอย่างไร (ความเห็น Fable)

  1. ลำดับคุณค่า/effort: 6.2 fail-fast ก่อนเพื่อน — โค้ด ~50 บรรทัดใน Package แต่กัน misconfig class ทั้งกลุ่ม (prod รันด้วย dummy เงียบๆ) ตลอดไป · 6.1 rotate ทำขนานเพราะต้อง coordinate คนนอก
  2. Purge git history: ผมจะเสนอให้ทำเฉพาะ repo ที่มี secret prod จริง (ThirdParty, Notification, Sentinel demo) ไม่ใช่ทุก repo — force-push ทั้ง org เจ็บเกินผลที่ได้ · สำคัญกว่าคือ rotate ให้ครบ — secret ที่ rotate แล้วค้างใน history = ขยะไม่ใช่ความเสี่ยง
  3. ตั้ง expiry บนทุก secret ตั้งแต่วันนี้ — เป็น az CLI loop เดียว ไม่ต้องรอ rotation policy จบ · alert pipeline ค่อยตาม — อย่างน้อย KV portal จะโชว์ expiring secrets ให้เห็นเอง
  4. AES key rotation: ออกแบบ key versioning ก่อน rotate ครั้งแรกเสมอ — นี่คือจุดที่ rotate แล้ว data loss ถาวรถ้าทำผิด · ผมจะ hold การ rotate AES ไว้ท้ายสุดจนกว่า enc:v{n}: scheme จะพร้อม (สอดคล้อง S11 ของ SUPPLEMENTAL)
  5. 6.4 least-privilege audit ทำเป็น script ไม่ใช่ manual — export role assignment เป็น scheduled pipeline รายเดือน + diff กับรอบก่อน — audit ครั้งเดียวเสื่อมทันทีที่มีคนแก้ role

📚 อ้างอิงมาตรฐาน (สำหรับใช้ในที่ประชุม):

หลักการแหล่งอ้างอิง
Key lifecycle, rotation cadence, cryptoperiodNIST SP 800-57 Part 1 Rev.5 — Recommendation for Key Management
Secrets lifecycle: สร้าง/แจก/rotate/revoke + fail-fastOWASP Secrets Management Cheat Sheet
Key separation, dual-key rotation windowOWASP Key Management Cheat Sheet
KV expiry, access model, least privilege (official)Azure Key Vault — Best practices
Purge secret จาก git history (ขั้นตอน + ข้อควรระวัง official)GitHub Docs — Removing sensitive data from a repository