
把密碼寫在程式碼裡有多可怕?去 GitHub 搜 password 或 api_key,你會看到一堆活生生的 production credentials 公開在那裡。
先講結論
秘密與憑證管理的三個核心能力:安全存放、權限控制、自動輪替。用 Vault 或 KMS 取代環境變數硬編碼,每個 secret 都要有 owner,憑證要能自動更新。做不到自動輪替,至少要有到期告警。人員離職的時候,所有他接觸過的 secret 都要 rotate。
哪些東西算「秘密」?
比你想的多得多:
- API Key / Token
- Database Password
- TLS 憑證與私鑰
- OAuth Client Secret
- SSH Key
- 第三方服務的憑證檔案
如果這些東西出現在你的 git repo 裡,不管是 .env、config.yml 還是 README 的範例——那就是一個等待被利用的漏洞。
為什麼環境變數不夠用?
很多人說「密碼放環境變數就好啦」。環境變數確實比硬編碼好,但它有幾個致命缺點:
- 可以被
env或/proc/*/environdump 出來 - 沒有存取記錄——誰讀了你不知道
- 無法做動態輪替——改密碼要重啟服務
- 無法做細粒度權限——能讀環境變數就能讀全部
正確做法是用 Vault 或雲端的 Secret Manager,讓服務透過 API 取得短期 token,用完即失效。
# 用 Vault 取得短期資料庫帳號,TTL 到期自動失效
vault read database/creds/app-role憑證會過期,而且總是在最糟的時候
你知道 TLS 憑證過期造成的 outage 有多常見嗎?大公司都踩過這個坑——服務突然全部 HTTPS 失敗,一查才發現憑證過期了,三個月前就該更新但沒人記得。
解法是 自動化更新。用 cert-manager 搭配 Let’s Encrypt,憑證到期前自動換新:
apiVersion: cert-manager.io/v1
kind: Certificate
metadata:
name: api-cert
spec:
secretName: api-tls
issuerRef:
name: letsencrypt
dnsNames:
- api.example.com如果你的環境不能用自動更新,至少要有 到期前 30 天的告警。
Break-glass:緊急存取怎麼辦?
系統掛了、正常存取管道失效、需要緊急拿到 prod 的 secret——這種情境一定會發生。
你需要一個 break-glass 流程:
- 有明確的審批機制(至少兩個人 approve)
- 有時間窗口限制(15 分鐘後自動撤銷)
- 全程審計記錄
- 事件結束後回收所有緊急權限
path "secret/data/prod/*" {
capabilities = ["read"]
allowed_parameters = { "ttl" = ["15m"] }
}沒有 break-glass 流程,緊急情況下人們就會用「共享的 admin 帳號」——那東西一旦被建立就永遠不會被刪除。
人員離職的 checklist
有人離職的時候,你會 rotate 哪些東西?如果答案是「呃…」,那問題很大。
至少要做:
- 所有該員有權限存取的 API key 全部 rotate
- SSH key 撤銷
- VPN / 內部工具帳號停用
- 共用帳號密碼更換(對,共用帳號本身就是問題,但如果有的話)
每個 secret 都要有 owner,離職時才知道要改什麼。
延伸閱讀
密碼管理的最高境界是:沒有人知道密碼是什麼,包括你自己。所有存取都透過短期 token,所有 token 都有到期時間,所有存取都有記錄。