Secret 管理的難題
我們的應用在執行過程中,通常需要一些 secret,比如資料庫密碼、第三方 API 的 key、私鑰等。為了規避安全風險,這些資料並不能隨著程式碼直接提交進入版本管理系統。管理這些 secret 通常有幾種簡單的做法:
- 在要部署的機器上配置成系統環境變數
- 將 secret 存放在 CI/CD 系統中,在軟體 build 時打包,隨著 binary 一起部署到伺服器
以上方案都存在以下缺點:
- 繁瑣且容易出錯,需要手工 SSH 到伺服器上或者在 CI/CD 系統中修改。
- 沒有版本管理,不能看到誰做了什麼變更,也不能便利地 revert。一旦手工修改出錯且沒備份,可能就沒法還原了。
技術選型
市面上有很多 secret 管理解決方案,我們調研過:SOPS、Vault、AWS Secrets Manager 等產品。
其中,Vault 過於複雜,對我們的使用場景簡直是「大炮打蚊子」。AWS Secrets Manager 其實挺易用,可它並不能很好地與 Kubernetes 搭配,還會引入「雲廠商鎖定」的問題。
而 SOPS 兼顧了簡單與 K8S 的協調,正好符合了我們的需求。
引入 SOPS
SOPS 是由 Mozilla(Firefox 開發商)開發的一款 secret 管理工具,它支援使用 AWS KMS、GCP KMS、Azure Key Vault、PGP 加密 YAML、JSON、ENV、INI 以及二進位制格式的檔案。包含的 secret 檔案經過 SOPS 加密後,我們就能放心的將他們存放到版本管理中了。
我們公司選擇使用 AWS KMS 服務,在使用 SOPS 加解密前需要使用者電腦上插入 Yubikey 通過裝置二次認證,加強安全性。AWS KMS 還能在 IAM 按人員分別配置不同的許可權,比如允許使用者 tony
只能加解密 example
應用的 development
環境的 secret。
在使用 SOPS 之後,我們公司內部的 secret 管理工作流就變成了:
- 使用 SOPS 在本地修改 secret
- 提交到版本管理
- CI/CD 將 secret 解密,並部署到伺服器
相比之前的方案,我們直接將 secret 加入到版本管理中,獲得了以下好處:
- 管理方便,我們在本地一行命令就能完成更改,然後提交。
- 方便回溯和審計,能看到 secret 版本歷史,修改錯誤也能快速 revert。
- 程式碼和 secret 的同步(之前我們如果在程式碼中做了修改 secret 名稱等不相容的變更,運維和開發就需要協調程式碼部署和 secret 變更同時進行)。
當然缺點也必然存在,如果你的原始碼和用來加密 secret 的私鑰或 credential 同時發生了洩露,那麼攻擊者就可以解密獲得這些 secret 的明文。
但任何方案都有風險,需要同時丟失多份資訊才可能造成洩露,肯定好過直接在程式碼倉庫中明文儲存 secret,從之前國內的幾起程式碼洩露事故中,就會發現這麼做的公司並不少。
將 Secret 部署到 Kubernetes
我們公司的應用都是部署在 K8S 上,在應用打包時就將解密的 secret 打包進入 image 的風險太大,一旦 Docker image 發生了洩露,後果不堪設想。並且開發者有許可權拉取應用 image 用於本地開發,可他們並不該有許可權檢視這些 secret。
還好社群也考慮到了這個問題,如果你也在使用 Helm 管理 K8S 應用,可以通過 helm-secrets 外掛將 SOPS 與 Helm 整合。開發過程中直接將 Helm value 加密,helm-secret 會自動幫我們在 helm apply
時解密 value。
我們只需要在 Chart template 中宣告好 K8S 的 Secret 資源,我們的 secret 就可以被部署為 K8S Secrets 啦。然後將 secret 以環境變數或檔案的形式掛載進 Pod,就能被應用讀取到了。
結語
這篇文章僅是我司在使用 SOPS 管理 secret 上的實踐經驗,得益於 SOPS 的簡單方便,你還能探索將 SOPS 用於其他需要管理敏感資訊的場景,記得分享給我們你的實踐經驗。
由於官方文件已經足夠詳細,我們並沒有重複創作,入門請參閱官方文件。
本作品採用《CC 協議》,轉載必須註明作者和本文連結