cover

把密碼寫在程式碼裡有多可怕?去 GitHub 搜 passwordapi_key,你會看到一堆活生生的 production credentials 公開在那裡。

先講結論

秘密與憑證管理的三個核心能力:安全存放、權限控制、自動輪替。用 Vault 或 KMS 取代環境變數硬編碼,每個 secret 都要有 owner,憑證要能自動更新。做不到自動輪替,至少要有到期告警。人員離職的時候,所有他接觸過的 secret 都要 rotate。


哪些東西算「秘密」?

比你想的多得多:

  • API Key / Token
  • Database Password
  • TLS 憑證與私鑰
  • OAuth Client Secret
  • SSH Key
  • 第三方服務的憑證檔案

如果這些東西出現在你的 git repo 裡,不管是 .envconfig.yml 還是 README 的範例——那就是一個等待被利用的漏洞。


為什麼環境變數不夠用?

很多人說「密碼放環境變數就好啦」。環境變數確實比硬編碼好,但它有幾個致命缺點:

  • 可以被 env/proc/*/environ dump 出來
  • 沒有存取記錄——誰讀了你不知道
  • 無法做動態輪替——改密碼要重啟服務
  • 無法做細粒度權限——能讀環境變數就能讀全部

正確做法是用 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 都有到期時間,所有存取都有記錄。