如何在 API Gateway 中使用 Secret Manager 来存储相关密钥?

更新时间 2023-01-04

什么是 Secret

在 IT 数据环境中,Secret 是数字特权凭据,通常是系统和应用程序用于身份验证或作为加密算法输入的凭据。比如程序连接数据库所需要的密码、加密通信用到的证书私钥等,都属于 Secret 的范畴。常见的 Secret 类型包括:

  • 加密密钥
  • 云服务访问凭据
  • 应用程序编程接口 (API) 密钥
  • 访问令牌
  • SSH(安全外壳)密钥

Secret Manager

Secret Manager 用于对 Secret 进行全生命周期的存储、检索、轮换和审计。HashiCorp Vault 是目前最常见的 Secret Manager 服务之一,其工作原理如下(图片来自 HashiCorp 官方):

secret manager

除了 HashiCorp Vault 之外, AWS、Google、Azure 等云厂商也都提供了 Secret Manager 服务。

使用 Secret Manager 构建应用程序除了能提升安全性之外,还具有以下功能:

  • 允许轻松地跨多台机器更新 Secret,应用程序无感。
  • 开发人员无需过多关注 Secret 的存储等,可以将关注点集中于业务逻辑本身。
  • Secret 轮转和吊销都无需重新部署或中断活动应用程序。
  • Secret Manager 提供了灵活且详细审计日志功能,可以跟踪到所有用户的历史访问记录,能更轻松地满足审核和合规性要求。

在 API Gateway 中使用 Secret Manager

API Gateway 作为业务流量的入口,往往包含了大量的 Secret 信息,例如 API 密钥、用于鉴权认证的 token 等,因此在 API Gateway 中集成 Secret Manager 具有重要意义。

API Gateway 使用 Secret 场景

Key Auth 是 API Gateway 中一种简单的身份认证方式。用户需要预设一个密钥,当客户端请求 API 时,将预设的密钥写入对应请求头,或者作为请求参数访问即可通过认证。然而,密钥泄露的情况非常普遍,密钥通常被储存在配置文件中,或作为变量被储存在代码中。如果没有妥善保存,密钥甚至会出现在 GitHub 等公开可见的代码库中,从而对安全构成重大威胁。为了防止密钥泄漏造成大的危害,管理员通常也会选择定期更新这些密钥,对于一些静态密钥,逐个机器更新配置文件,也将对服务的稳定性带来很大的危害。

API Gateway 集成 Secret Manager

在 API Gateway 中集成 Secret Manager后,可以将 Key Auth 认证预设的密钥存储在 Secret Manager 服务中。能有效解决密钥泄漏带来的一系列问题。API Gateway 只是密钥的使用方,真正的密钥值保存在外部 Secret Manager 服务中,API Gateway 中保存的只是密钥的引用,即使攻破了 API Gateway,也无法从代码或配置文件中获取到真正的密钥。另外,如果需要更新密钥的值,只需要在 Secret Manager 中更新即可,无需对 API Gateway 的代码或配置做任何修改,这也有效避免了 API Gateway 的重启。

api gateway secret manager

下面将以 Apache APISIX 为例,展示在 API Gateway 中何如使用 Secret Manager 来存储 Key Auth 的预设密钥。

Apache APISIX 在 Secret Manager 中的实践

Apache APISIX 是一个动态、实时、高性能的 API 网关, 提供负载均衡、动态上游、灰度发布、精细化路由、限流限速、服务降级、服务熔断、身份认证、可观测性等数百项功能。

在 3.1.0 版本中 Apache APISIX 引入了 APISIX Secret 资源用来集成不同的 Secret Manager。其工作时序如下:

apisix secret manager

下面使用 Vault 作为 Secret Manager 服务,以 Key Auth 身份认证为例,展示在 Apache APISIX 中如何使用 Secret Manager 保存密钥。

在 Vault 中创建密钥

在创建密钥之前,需要先启动 Vault 服务,由于本节分享了在 Apache APISIX 生态系统中使用 Vault 的最佳实践,关于 Vault 自身的配置不作详细描述,可以参考这里

在 Vault 中创建对应的密钥,可以使用如下命令:

1vault kv put apisix/jack jwt-key=value

上述命令在 Vault 的 apisix/jack 路径下创建了名为 auth-key 的密钥,值为 value。

在 APISIX 中配置

首先,通过 Admin API 添加 Secret 资源,配置 Vault 的地址等连接信息:

1curl http://127.0.0.1:9180/apisix/admin/secrets/vault/gateway \
2-H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
3{
4    "uri": "https://127.0.0.1:8200",
5    "prefix": "apisix",
6    "token": "root"
7}'

然后,使用 key-auth 插件创建一个消费者,为对应的路由或服务执行 Key Auth 认证。其中 key 字段引用 APISIX Secret 资源:

1curl http://127.0.0.1:9180/apisix/admin/consumers \
2-H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
3{
4    "username": "jack",
5    "plugins": {
6        "key-auth": {
7            "key": "$secret://vault/geteway/jack/auth-key"
8        }
9    }
10}'

通过上面两步操作,当用户请求命中 key-auth 插件时,会通过 Secret 组件提供的接口调用用户配置的 Secret Manager,获取到 key 在 Vault 中的真实值,如果没有找到 key 的值,插件会记录错误,并且无法执行 Key Auth 验证。

另外,Apache APISIX 将环境变量扩展成了一种简单的 Secret Manager 服务,APISIX 连接 Vault 的 token 也可以保存环境变量中。在 APISIX 启动之前,可以通过下面的命令设置环境变量:

1export VAULT_TOKEN="root"

在添加 Secret 资源时引用环境变量:

1curl http://127.0.0.1:9180/apisix/admin/kms/vault/1 \
2-H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
3{
4    "uri": "https://127.0.0.1:8200",
5    "prefix": "apisix",
6    "token": "$ENV://VAULT_TOKEN"
7}'

通过上面步骤,就可以实现将 Key Auth 认证需要的密钥存储在 Vault 中,而不是以明文的形式在配置插件时展示。

总结

在 API Gateway 中,包含大量的 Secret 信息,使用 Secret Manager 来管理 Secret 能保证所有 Secret 使用过程,不会有任何明文 Secret 信息出现在 API Gateway 中,有效提升提升了 API Gateway 的安全性和稳定性。Apache APISIX 作为全世界最活跃的开源 API Gateway,在 Secret Manager 上也有很好的支持,本文也以为 Key Auth 身份认证为例,展示了如何在 APISIX 中使用 Secret Manager 来管理密钥信息。