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)
| # | งาน | รายละเอียด |
|---|---|---|
| 1 | Inventory secret ที่เคยรั่วเข้า git (SG-02a) | รัน Gitleaks ทั้ง history ทุก repo: gitleaks detect --source . --log-opts="--all" → ได้ list สิ่งที่ต้อง rotate |
| 2 | Rotate ทุกตัวใน list | ถือว่า compromised ทั้งหมด — ตามลำดับ rotate ใน IMPL_PLAN_00 (ค่าใหม่พร้อมก่อน revoke ค่าเก่า) |
| 3 | ลบ demo project ที่มี EncryptionKey จริง (SG-02c) | Sentinel repo — ลบ project + rotate key นั้น |
| 4 | Purge 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 |
|---|---|---|
| 1 | Backend_Package/src/Extension/ConfigurationValidationExtensions.cs (ใหม่) | ValidateRequiredSecrets(params string[] keys) — เรียกหลัง build config, throw ถ้าค่าว่าง/"__VAULT__"/"changeme" |
| 2 | Program.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 partner | coordinate กับ partner |
| Entra client secrets | 12 เดือน (ตั้ง expiry ใน Entra) | สร้างใหม่ก่อนหมด → สลับ → ลบเก่า |
Implement:
- ตั้ง
expiresattribute บนทุก secret ใน KV (az keyvault secret set-attributes --expires) - Scheduled pipeline ใน
Backend_Iac/pipelines/— รายสัปดาห์ ตรวจ secret expiry < 30 วัน → แจ้ง Teams channel (มี azure-compliance tooling ช่วย scan ได้)
งาน 6.4 — Least-Privilege Audit (B5 trust boundary)
- Export role assignments ของทุก Managed Identity ต่อ KV:
az role assignment list --scope <kv-id> - ตรวจ: service A ไม่ควรอ่าน secret ของ service B ได้ — ถ้า KV แชร์กันใช้
ServicePrefixKeyVaultSecretManagerfilter ฝั่ง app อยู่แล้ว แต่สิทธิ์จริงที่ RBAC ต้องแคบด้วย (filter ฝั่ง app ไม่ใช่ security boundary) - ผลลัพธ์: ตาราง 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 แคบลง
⚠️ ข้อควรระวัง
- ห้าม purge ก่อน rotate — และห้าม rotate โดยไม่มีค่าใหม่พร้อมใช้
- AES key rotation ต้องมี key versioning ก่อน — มิฉะนั้นข้อมูลเก่าถอดไม่ได้ (data loss)
- Force-push เป็น hard-to-reverse — ต้องมี mirror backup ก่อนทำ + approve จากทีมเป็นลายลักษณ์
🎯 ถ้าเป็นผมจะทำอย่างไร (ความเห็น Fable)
- ลำดับคุณค่า/effort: 6.2 fail-fast ก่อนเพื่อน — โค้ด ~50 บรรทัดใน Package แต่กัน misconfig class ทั้งกลุ่ม (prod รันด้วย dummy เงียบๆ) ตลอดไป · 6.1 rotate ทำขนานเพราะต้อง coordinate คนนอก
- Purge git history: ผมจะเสนอให้ทำเฉพาะ repo ที่มี secret prod จริง (ThirdParty, Notification, Sentinel demo) ไม่ใช่ทุก repo — force-push ทั้ง org เจ็บเกินผลที่ได้ · สำคัญกว่าคือ rotate ให้ครบ — secret ที่ rotate แล้วค้างใน history = ขยะไม่ใช่ความเสี่ยง
- ตั้ง expiry บนทุก secret ตั้งแต่วันนี้ — เป็น az CLI loop เดียว ไม่ต้องรอ rotation policy จบ · alert pipeline ค่อยตาม — อย่างน้อย KV portal จะโชว์ expiring secrets ให้เห็นเอง
- AES key rotation: ออกแบบ key versioning ก่อน rotate ครั้งแรกเสมอ — นี่คือจุดที่ rotate แล้ว data loss ถาวรถ้าทำผิด · ผมจะ hold การ rotate AES ไว้ท้ายสุดจนกว่า
enc:v{n}:scheme จะพร้อม (สอดคล้อง S11 ของ SUPPLEMENTAL) - 6.4 least-privilege audit ทำเป็น script ไม่ใช่ manual — export role assignment เป็น scheduled pipeline รายเดือน + diff กับรอบก่อน — audit ครั้งเดียวเสื่อมทันทีที่มีคนแก้ role
📚 อ้างอิงมาตรฐาน (สำหรับใช้ในที่ประชุม):
| หลักการ | แหล่งอ้างอิง |
|---|---|
| Key lifecycle, rotation cadence, cryptoperiod | NIST SP 800-57 Part 1 Rev.5 — Recommendation for Key Management |
| Secrets lifecycle: สร้าง/แจก/rotate/revoke + fail-fast | OWASP Secrets Management Cheat Sheet |
| Key separation, dual-key rotation window | OWASP 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 |