随着微服务架构的兴起,保持服务安全变得比以前更有挑战性。多个后端 server 实例使用单一的静态密钥凭访问数据库 server 会带来巨大的风险。如果发生密钥凭证泄露,整个系统都会受到影响。为了解决密钥凭证泄露所带来的影响,只能撤销这个密钥凭证。而撤销密钥凭证会导致大规模的服务中断。对开发者来说,服务大规模中断是开发者最不想看到事情。

虽然我们不能提前预知将来会出现哪些安全漏洞,但是我们可以通过配置多个密钥来控制这些安全漏洞的影响范围。为了避免这样的情况,像 HashiCorp Vault (下文简称 Vault)这样密钥凭证解决方案 应运而生。本文演示了如何将 Vault 与 Apache APISIX 的jwt-auth插件集成,在为服务提供高并发低延迟的卓越性能的同时,为服务的安全保驾护航。

什么是 Vault

Vault 旨在帮助用户管理服务密钥的访问权限,并在多个服务之间安全地传输这些密钥。密钥可以是任何形式的凭证,因为密钥可用于解锁敏感信息,所以需要严密控制密钥。密钥的形式可以是密码、API 密钥、SSH 密钥、RSA 令牌或 OTP。事实上,密钥泄露的情况非常普遍:密钥通常被储存在配置文件中,或作为变量被储存在代码中,如果没有妥善保存,密钥甚至会出现在 GitHub、BitBucket 或 GitLab 等公开可见的代码库中,从而对安全构成了重大威胁。Vault 通过集中密钥解决了这个问题。它为静态密钥提供加密存储,生成具 有TTL 租约的动态密钥,对用户进行认证,以确保他们有权限访问特定的密钥。因此,即使在安全漏洞的情况下,影响范围也小得多,并能得到更好的控制。

Vault 提供了一个用户界面用于密钥管理,使控制和管理权限变得非常容易。不仅如此,它还提供了灵活且详细审计日志功能,能跟踪到所有用户的历史访问记录。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-snN47EY4-1645609372957)(https://tfzcfxawmk.feishu.cn/space/api/box/stream/download/asynccode/?code=NTk4ZTJlNWRlODA2Zjk3YTlhYzI2MGQzOWE5NDhkZjlfM1NKQ1NuRURpa3E1V0VCbE1rcUhoOU10VXRqanBBTnVfVG9rZW46Ym94Y25QUlNBVWNwWUFxWWJyRzlnOTJmN2pnXzE2NDU2MDkyMTk6MTY0NTYxMjgxOV9WNA)]

jwt-auth插件介绍

jwt-auth 是一个认证插件,可以附加到任何 APISIX 路由上,在请求被转发到上游 URI 之前执行 JWT 认证。通常情况下,发行者使用私钥或文本密钥来签署 JWT。JWT 的接收者将验证签名,以确保令牌在被发行者签名后没有被改变。整个 JWT 机制的整体完整性取决于签名密钥(或 RSA 密钥对的文本密钥)。这使得未经认证的来源很难猜到签名密钥并试图改变 JWT 中的声明。

因此,在安全的环境中存储这些密钥是非常关键的。如果密钥落入坏人之手,可能会危及整个基础设施的安全。虽然 Apache APISIX采取了一切手段来遵循标准的 SecOps 实践,但在生产环境中有一个集中的密钥管理解决方案也是一件好事。例如 Vault,有详细的审计日志,定时的密钥轮换,密钥撤销等功能。如果每次在整个基础设施发生密钥轮换时,你都要更新 Apache APISIX 配置,这将是一个相当麻烦的问题。

如何集成 Vault 和 Apache APISIX

为了与 Vault 集成,Apache APISIX 需要在 config.yaml 文件中加载 Vault 的相关配置信息。

Apache APISIX 与 Vault server KV Secrets Engine v1 HTTP APIs 进行通信。由于大多数企业解决方案倾向于在生产环境中使用 KV Secrets Engine - Version 1,在APISIX-Vault 支持的初始阶段,我们只使用这个版本。在以后的版本中,我们将增加对 K/V - Version 2 的支持。

使用 Vault 而不是 APISIX etcd 后端的主要顾虑是在低信任度环境下的安全问题。因为 Vault 访问令牌是小范围的,可以授予 APISIX server 有限的权限。

配置 Vault

本节分享了在 Apache APISIX 生态系统中使用 Vault 的最佳实践。如果你已经有了一个具有必要权限的 Vault 实例在运行,请跳过本节。

第1步:启动 Vault server

在这里,你有多种选择,可以自由选择 docker、预编译二进制包或从源代码构建。至于与 Vault server 的通信,你需要一个 Vault CLI 客户端。请运行以下命令启动 server:

$ vault server -dev -dev-root-token-id=root
…
WARNING! dev mode is enabled! In this mode, Vault runs entirely in-memory
and starts unsealed with a single unseal key. The root token is already
authenticated to the CLI, so you can immediately begin using Vault.
You may need to set the following environment variable:
export VAULT_ADDR='http://127.0.0.1:8200'
The unseal key and root token are displayed below in case you want to
seal/unseal the Vault or re-authenticate.
Unseal Key: 12hURx2eDPKK1tzK+8TkgH9pPhPNJFpyfc/imCLgJKY=
Root Token: root
Development mode should NOT be used in production installations!

用正确的环境变量设置 Vault CLI 客户端。

$ export VAULT_ADDR='http://127.0.0.1:8200'
$ export VAULT_TOKEN='root'

用一个合适的path前缀启用 vault k/v version 1的密钥引擎后端。在这个演示中,我们要选择 kv 路径,这样就不会与 vault 默认的 kv 版本2的密钥路径发生冲突。

$ vault secrets enable -path=kv -version=1 kv
Success! Enabled the kv secrets engine at: kv/# To reconfirm the status, run
$ vault secrets list
Path          Type         Accessor              Description
----          ----         --------              -----------
cubbyhole/    cubbyhole    cubbyhole_4eeb394c    per-token private secret storage
identity/     identity     identity_5ca6201e     identity store
kv/           kv           kv_92cd6d37           n/a
secret/       kv           kv_6dd46a53           key/value secret storage
sys/          system       system_2045ddb1       system endpoints used for control, policy and debugging

第2步:为 Apache APISIX 生成一个 Vault 访问令牌

本文是关于在 jwt-auth 插件中使用 Vault 的观点。因此,对于一个APISIX 消费者jackjwt-auth插件会在<vault.prefix inside config.yaml>/consumer/<consumer.username>/jwt-auth中查找(如果启用了Vault 配置)secret/s 到 Vault 键值对 存储。在这种情况下,如果你将kv/apisix命名空间(Vault 路径)指定为config.yaml内的vault.prefix,用于所有 APISIX 相关数据的检索,我们建议你为路径kv/apisix/consumer/创建一个策略。最后的星号(*)确保策略允许读取任何具有kv/apisix/consumer前缀的路径。

用 HashiCorp 配置语言(HCL)创建一个策略文件。

$ tee apisix-policy.hcl << EOF
path "kv/apisix/consumer/*" {capabilities = ["read"]
}
EOF

将策略应用于 Vault 实例。

$ vault policy write apisix-policy apisix-policy.hclSuccess! Uploaded policy: apisix-policy

用新定义的策略生成一个令牌,该策略已被配置为很小的访问边界。

$ vault token create -policy="apisix-policy"Key                  Value
---                  -----
token                s.KUWFVhIXgoRuQbbp3j1eMVGa
token_accessor       nPXT3q0mfZkLmhshfioOyx8L
token_duration       768h
token_renewable      true
token_policies       ["apisix-policy" "default"]
identity_policies    []
policies             ["apisix-policy" "default"]

在这个演示中,s.KUWFVhIXgoRuQbbp3j1eMVGa 是你的访问令牌。

在 Apache APISIX 中添加 Vault 配置

Apache APISIX 通过 Vault HTTP APIs 与 Vault 实例进行通信。必要的配置必须被添加到 config.yaml 中。

下面是关于你可以使用的不同字段的简要信息。

  • host: 运行Vault服务器的主机地址。

  • timeout: 每次请求的HTTP超时。

  • token: 从金库实例生成的令牌,可以授予从金库读取数据的权限。

    • prefix:启用前缀可以更好地执行策略,生成有限范围的令牌,严格控制可以从APISIX访问的数据。有效的前缀是(kv/apisix,secret等)。
vault:host: 'http://0.0.0.0:8200'timeout: 10token: 's.KUWFVhIXgoRuQbbp3j1eMVGa'prefix: 'kv/apisix'

创建一个 APISIX Consumer

APISIX 有一个消费者层面的抽象,与认证方案并列。为了启用任何 APISIX 路由的认证,需要一个具有适合该特定类型认证服务的配置的消费者。然后,只有 APISIX 可以通过成功执行消费者配置方面的认证,将请求转发到上游 URI。APISIX 消费者有两个字段:一个是username(必填项),用于识别消费者,另一个是plugins,用于保存消费者所使用的特定插件配置。

在这里,在这篇文章中,我们将用 jwt-auth 插件创建一个消费者。它为各自的路由或服务执行 JWT认证。

运行以下命令,启用 Vault 配置的 jwt-auth。

$ curl http://127.0.0.1:9080/apisix/admin/consumers -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{"username": "jack","plugins": {"jwt-auth": {"key": "test-key","vault": {}}}
}'

在这个实例里面,插件在消费者配置中提到的消费者用户jack的 Vault 路径(<vault.prefix from conf.yaml>/consumer/jack/jwt-auth)中查找密钥secret,并将其用于后续的签名和 jwt 验证。如果在同一路径中没有找到密钥,该插件会记录错误,并且无法执行 jwt 验证。

设置一个测试的上游服务器

为了测试这个行为,你可以为一个上游创建一个路由(一个简单的 ping 处理程序,返回 pong)。你可以用一个普通的 go HTTP-Server 来设置它。

// simple upstream server
package mainimport "net/http"func ping(w http.ResponseWriter, req *http.Request) {w.Write([]byte("secure/pong\n"))
}func main() {http.HandleFunc("/secure/ping", ping)http.ListenAndServe(":9999", nil)
}

在这里,插件在消费者配置中提到的消费者jack的 Vault 路径(<vault.prefix from conf.yaml>/consumer/jack/jwt-auth)中查找密钥秘密,并使用它进行后续的签名和jwt验证。如果在同一路径中没有找到密钥,该插件会记录错误,并且无法执行jwt验证。

创建一个启用了认证的 APISIX 路由

用这个安全的 ping HTTP 服务器和启用了 jwt-auth 认证插件创建一个 APISIX 路由。

$ curl http://127.0.0.1:9080/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{"plugins": {"jwt-auth": {}},"upstream": {"nodes": {"127.0.0.1:9999": 1},"type": "roundrobin"},"uri": "/secure/ping"
}'

从 jwt-auth 插件生成令牌

现在从 APISIX 签署一个 jwt 密文,可以用于并通过向 APISIX 服务器的http://localhost:9080/secure/ping 代理路由发出请求。

$ curl http://127.0.0.1:9080/apisix/plugin/jwt/sign\?key\=test-key -i
HTTP/1.1 200 OK
Date: Tue, 18 Jan 2022 07:50:57 GMT
Content-Type: text/plain; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Server: APISIX/2.11.0eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJ0ZXN0LWtleSIsImV4cCI6MTY0MjU3ODY1N30.nkyev1_KUapVgY_QVYETsSApA6gEkDWS8tsHFV1EpD8

在上一步中,如果你看到类似签署 jwt 失败的信息,请确保你有一个私有密钥存储在vault kv/apisix/consumers/jack/jwt-auth路径中。

# example
$ vault kv put kv/apisix/consumer/jack/jwt-auth secret=$ecr3t-c0d3
Success! Data written to: kv/apisix/consumer/jack/jwt-auth

向 APISIX Server 发送请求

现在,向 APISIX 代理发出一个路由/secure/ping的请求。验证成功后,它将把请求转发给我们的 go HTTP 服务器。

$ curl http://127.0.0.1:9080/secure/ping -H 'Authorization: eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJrZXkiOiJ0ZXN0LWtleSIsImV4cCI6MTY0MjU3ODU5M30.IYudBr7FTgRme70u4rEBoYNtGmGByzgfGlt8hctI__Q' -i
HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Content-Length: 12
Connection: keep-alive
Date: Tue, 18 Jan 2022 08:00:04 GMT
Server: APISIX/2.11.0secure/pong

任何无效的 jwt 请求都会抛出 HTTP 401 未授权的错误。

$ curl http://127.0.0.1:9080/secure/ping -i
HTTP/1.1 401 Unauthorized
Date: Tue, 18 Jan 2022 08:00:33 GMT
Content-Type: text/plain; charset=utf-8
Transfer-Encoding: chunked
Connection: keep-alive
Server: APISIX/2.11.0{"message":"Missing JWT token in request"}

Vault可以与APISIX jwt-auth插件集成的不同用例

Apache APISIX jwt-auth 插件可以被配置为从 Vault 存储中获取简单的文本密钥以及 RS256 公私密钥对。

Note*:对于该集成支持的早期版本,该插件希望存储到金库路径中的密钥名称在[* *secret*, *public_key*, *private_key* ]之间,以成功使用该密钥。在未来的版本中,我们将增加对引用自定义命名的密钥的支持。

  1. 你在保险库内存储了 HS256 签名密钥,你想用它来进行 jwt 签名和验证。
$ curl http://127.0.0.1:9080/apisix/admin/consumers -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{"username": "jack","plugins": {"jwt-auth": {"key": "key-1","vault": {}}}
}'

在这里,插件在消费者配置中提到的消费者用户名jack的 Vault 路径(<vault.prefix from conf.yaml>/consumer/jack/jwt-auth)中查找密钥secret,并使用它进行后续的签名和 jwt 验证。如果在同一路径中没有找到密钥,该插件将记录一个错误,并且无法执行 jwt 验证。

  1. RS256 RSA 密钥对,公钥和私钥都存储在 Vault 中。
$ curl http://127.0.0.1:9080/apisix/admin/consumers -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{"username": "jim","plugins": {"jwt-auth": {"key": "rsa-keypair","algorithm": "RS256","vault": {}}}
}'

该插件在 Vault 键值对 路径(<vault.prefix from conf.yaml>/consumer/jim/jwt-auth)中为插件 vault 配置中提到的用户 jim 查找 public_keyprivate_key。如果没有找到,认证失败。

如果你不确定如何将公钥和私钥存储到 Vault 键值对 中,请使用这个命令

# provided, your current directory contains the files named "public.pem" and "private.pem"
$ vault kv put kv/apisix/consumer/jim/jwt-auth public_key=@public.pem private_key=@private.pem
Success! Data written to: kv/apisix/consumer/jim/jwt-auth
  1. 消费者配置中的公钥,而私钥在 Vault 中。
$ curl http://127.0.0.1:9080/apisix/admin/consumers -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{"username": "john","plugins": {"jwt-auth": {"key": "user-key","algorithm": "RS256","public_key": "-----BEGIN PUBLIC KEY-----\n……\n-----END PUBLIC KEY-----""vault": {}}}
}'

这个插件使用来自消费者配置的 RSA 公钥,并使用直接从 Vault 获取的私钥。

禁用 Vault 插件

现在,要禁用jwt-auth插件的 Vault 查询,只需从消费者插件配置中删除空的 Vault 对象(本例中是jack)。这将使 jwt 插件在随后对已启用 jwt-auth 配置的 URI 路由的请求中,将查找签名密钥(包括 HS256/HS512 或 RS512 密钥对)纳入插件配置。即使你在 APISIX config.yaml中启用了 Vault 配置,也不会有请求被发送到 Vault 服务器。

APISIX插件是热加载的,因此不需要重新启动APISIX。

$ curl http://127.0.0.1:9080/apisix/admin/consumers -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{"username": "jack","plugins": {"jwt-auth": {"key": "test-key","secret": "my-secret-key"}}
}'

Apache APISIX 集成 HashiCorp Vault,生态系统再添一员相关推荐

  1. 【资讯】K8S生态再添一员,Rancher发布开源HCI软件Harvester、及其安装教程

    原文出处: K8S生态再添一员,Rancher发布开源HCI软件Harvester https://gitee.com/mirrors/harvester https://github.com/ran ...

  2. 兼容低功耗MCU和SoC、超低电流消耗 特瑞仕转换器家族再添一员

    兼容低功耗MCU和SoC.超低电流消耗!特瑞仕转换器家族再添一员 唯样商城代理品牌特瑞仕XC9145系列的超低消耗电流电路将电流消耗降低至400nA,同时采用PWM/PFM控制方式使得产品在轻负载下显 ...

  3. 华为matepad 鸿蒙,鸿蒙阵营再添一员猛将!华为全新平板曝光

    原标题:鸿蒙阵营再添一员猛将!华为全新平板曝光 近日,有数码博主爆料称,华为确定将在6月2日召开智慧全场景新品发布会,带来数款新品.同时,被多次推迟发布的华为全新平板产品--华为MatePad Pro ...

  4. #今日论文推荐# 扩散模型家族再添一员,最新 Cold Diffusion 不再依赖高斯噪声

    #今日论文推荐# 扩散模型家族再添一员,最新 Cold Diffusion 不再依赖高斯噪声 目前业界出现的扩散模型变体层出不穷,但它们都有一个不变的核心:都是围绕随机噪声去除这个概念建立的. 扩散模 ...

  5. API 网关 Apache APISIX 集成 Eureka 作为服务发现

    微服务架构中,大型复杂的系统按功能或者业务需求垂直切分成更小的子系统,这些子系统以独立部署的子进程存在,它们之间通过网络调用进行通信.这些独立部署的服务如何发现对方成为了首先要解决的问题,所以在微服务 ...

  6. 阿里再添一员虎将!刚刚入职的80后硅谷科学家贾扬清到底有多牛?

    3月18日傍晚,阿里巴巴达摩院通过知乎账号宣布,原Facebook人工智能科学家贾扬清已正式加入阿里巴巴,担任技术副总裁岗位,领导大数据计算平台的研发工作.阿里巴巴达摩院在知乎问题"如何评价 ...

  7. 量子计算生态圈再添一员!德国半导体制造商英飞凌

    (图片来源:网络) 近期,德国半导体制造商英飞凌科技股份公司和英国离子阱量子计算公司Oxford Ionics宣布达成合作,依托Oxford Ionics独特的电子量子比特控制(EQC)技术和英飞凌的 ...

  8. 蔚来即将二次上市 车企跨界排头兵或将再添一员?

    数据智能产业创新服务媒体 --聚焦数智 · 改变商业 2月28日,蔚来汽车发布公告称,已通过香港交易所聆讯,获得在港交所主板二次上市的原则上批准.本次上市采用介绍上市的方式,不涉及新股发行及资金募集. ...

  9. linux操作系统_Linux操作系统生态再添一员猛将,腾讯视频推出Linux版本!

    原文链接:https://baijiahao.baidu.com/s?id=1654859883682113671&wfr=spider&for=pc 自2013年棱镜门事件之后,如何 ...

最新文章

  1. 智源论坛Live丨青年科学家线上报告会日程发布
  2. MyBatis的useGenerateKeys的使用方法
  3. VS2015 提示 无法启动 IIS Express Web 服务器
  4. Apache Lucene基础教程
  5. BJFU 质数相关
  6. 详解Python中的各种数字类型
  7. android sdk更新后出现please update ADT to the latest ve
  8. Google Android创赢路线与产品开发实战
  9. ubuntu安装 gcc 5.4.0
  10. Wso2 api manager 帮助文档
  11. 2019年8月8日 星期四 今日计划
  12. 灰度斜坡intensity ramp和灰度台阶intensity step的区别
  13. android 基带版本,手机基带是什么?手机的基带版本是什么意思?
  14. 个人GitHub地址
  15. WIN10开机显示被调用的对象已与其客户端断开连接解决方法之一
  16. gucci红包封面怎么抽 gucci红包封面怎么领取
  17. Ubuntu下阅读CHM格式的文档
  18. 搭建DVWA出现错误:DVWA System error - config file not found.
  19. 华中科技大学计算机专业排名2018,2018华中科技大学专业排名及分数线 王牌专业有哪些...
  20. AutoSAR系列讲解(实践篇)11.4-NvBlockSwComponents(上)

热门文章

  1. 光标切换键Insert
  2. selenium驱动IE常见问题解决
  3. GameFramework篇:StarForce全解读(总目录)
  4. 十一种值得珍惜的女生
  5. Photoshop:常用快捷键整理,提高工作效率,你也可以零基础成为PS高手
  6. Do Your Data Recovery(数据恢复软件)v7.1版本更新
  7. Python教程:self用法
  8. android过热自动关机,android实现自动关机的具体方法
  9. 基于JAVAVue网上书籍购买商城登录计算机毕业设计源码+数据库+lw文档+系统+部署
  10. 煽情的儿子552=随笔