使用 SOPS 管理 Secret

Secret 管理的难题

我们的应用在运行过程中,通常需要一些 secret,比如数据库密码、第三方 API 的 key、私钥等。为了规避安全风险,这些数据并不能随着代码直接提交进入版本管理系统。管理这些 secret 通常有几种简单的做法:

  1. 在要部署的机器上配置成系统环境变量
  2. 将 secret 存放在 CI/CD 系统中,在软件 build 时打包,随着 binary 一起部署到服务器

以上方案都存在以下缺点:

  1. 繁琐且容易出错,需要手工 SSH 到服务器上或者在 CI/CD 系统中修改。
  2. 没有版本管理,不能看到谁做了什么变更,也不能便利地 revert。一旦手工修改出错且没备份,可能就没法还原了。

而我们要介绍的 SOPS,不仅能够解决上述问题,还具备简单、灵活、安全的特性。

为什么选 SOPS

市面上有很多 secret 管理解决方案,我们调研过:VaultAWS Secrets Manager 等产品。

其中,Vault 过于复杂,对我们的使用场景简直是「大炮打蚊子」。AWS Secrets Manager 其实挺易用,可它并不能很好地与 Kubernetes 搭配,还会引入「云厂商锁定」的问题。

引入 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 管理工作流就变成了:

  1. 在本地开发中解密文件
  2. 修改 secret
  3. 保存并加密文件
  4. 提交到版本管理
  5. CI/CD 将 secret 解密,并部署到服务器

这里的 1–3 步都被 SOPS 优化得非常方便好用,一行命令搞定。

相比之前的方案,我们直接将 secret 加入到版本管理中,获得了以下好处:

  1. 管理方便,我们在本地一行命令就能完成更改,然后提交。
  2. 方便回溯,能看到 secret 版本历史,修改错误也能快速 revert。
  3. 代码和 secret 的同步(之前我们如果在代码中做了修改 secret 名称等不兼容的变更,运维和开发就需要协调代码部署和 secret 变更同时进行)。

当然缺点也必然存在,如果你的源代码和用来加密 secret 的私钥或 credential 同时发生了泄露,那么攻击者就可以解密获得这些 secret 的明文。

但任何方案都有风险,需要同时丢失多份信息才可能造成泄露,肯定好过直接在代码仓库中明文存储 secret,从之前国内的几起代码泄露事故中,就会发现这么做的公司并不少。

将 Secret 部署到 Kubernetes

我们公司的应用都部署在 K8S 上,如果在应用打包时就将解密的 secret 打包进入 image 的风险太大,一旦 Docker image 发生了泄露,后果不堪设想。并且开发者有权限拉取应用 image 用于本地开发,可他们并不该有权限查看这些 secret。

还好社区也考虑到了这个问题,如果你也在使用 Helm 管理 K8S 应用,可以通过 helm-secret 插件将 SOPS 与 Helm 集成。开发过程中直接将 Helm value 加密,helm-secret 会自动帮我们在 helm apply 时解密 value。

我们只需要在 Chart template 中声明好 K8S 的 Secret 资源,我们的 secret 就可以被部署为 K8S Secrets 啦。之后只需要将 secret 以环境变量或文件的形式挂载进 Pod,就能被应用读取到了。

结语

这篇文章仅是我司在使用 SOPS 管理 secret 上的实践经验,得益于 SOPS 的简单方便,你还能探索将 SOPS 用于其他需要管理敏感信息的场景,记得分享给我们你的实践经验。

由于官方文档已经足够详细,我们并没有重复创作,入门请参阅官方文档

编辑于 03-09