Apache APISIX 集成 HashiCorp Vault,生态系统再添一员
随着微服务架构的兴起,保持服务安全变得比以前更有挑战性。多个后端 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 消费者jack
,jwt-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*
]之间,以成功使用该密钥。在未来的版本中,我们将增加对引用自定义命名的密钥的支持。
- 你在保险库内存储了 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 验证。
- 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_key
和 private_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
- 消费者配置中的公钥,而私钥在 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,生态系统再添一员相关推荐
- 【资讯】K8S生态再添一员,Rancher发布开源HCI软件Harvester、及其安装教程
原文出处: K8S生态再添一员,Rancher发布开源HCI软件Harvester https://gitee.com/mirrors/harvester https://github.com/ran ...
- 兼容低功耗MCU和SoC、超低电流消耗 特瑞仕转换器家族再添一员
兼容低功耗MCU和SoC.超低电流消耗!特瑞仕转换器家族再添一员 唯样商城代理品牌特瑞仕XC9145系列的超低消耗电流电路将电流消耗降低至400nA,同时采用PWM/PFM控制方式使得产品在轻负载下显 ...
- 华为matepad 鸿蒙,鸿蒙阵营再添一员猛将!华为全新平板曝光
原标题:鸿蒙阵营再添一员猛将!华为全新平板曝光 近日,有数码博主爆料称,华为确定将在6月2日召开智慧全场景新品发布会,带来数款新品.同时,被多次推迟发布的华为全新平板产品--华为MatePad Pro ...
- #今日论文推荐# 扩散模型家族再添一员,最新 Cold Diffusion 不再依赖高斯噪声
#今日论文推荐# 扩散模型家族再添一员,最新 Cold Diffusion 不再依赖高斯噪声 目前业界出现的扩散模型变体层出不穷,但它们都有一个不变的核心:都是围绕随机噪声去除这个概念建立的. 扩散模 ...
- API 网关 Apache APISIX 集成 Eureka 作为服务发现
微服务架构中,大型复杂的系统按功能或者业务需求垂直切分成更小的子系统,这些子系统以独立部署的子进程存在,它们之间通过网络调用进行通信.这些独立部署的服务如何发现对方成为了首先要解决的问题,所以在微服务 ...
- 阿里再添一员虎将!刚刚入职的80后硅谷科学家贾扬清到底有多牛?
3月18日傍晚,阿里巴巴达摩院通过知乎账号宣布,原Facebook人工智能科学家贾扬清已正式加入阿里巴巴,担任技术副总裁岗位,领导大数据计算平台的研发工作.阿里巴巴达摩院在知乎问题"如何评价 ...
- 量子计算生态圈再添一员!德国半导体制造商英飞凌
(图片来源:网络) 近期,德国半导体制造商英飞凌科技股份公司和英国离子阱量子计算公司Oxford Ionics宣布达成合作,依托Oxford Ionics独特的电子量子比特控制(EQC)技术和英飞凌的 ...
- 蔚来即将二次上市 车企跨界排头兵或将再添一员?
数据智能产业创新服务媒体 --聚焦数智 · 改变商业 2月28日,蔚来汽车发布公告称,已通过香港交易所聆讯,获得在港交所主板二次上市的原则上批准.本次上市采用介绍上市的方式,不涉及新股发行及资金募集. ...
- linux操作系统_Linux操作系统生态再添一员猛将,腾讯视频推出Linux版本!
原文链接:https://baijiahao.baidu.com/s?id=1654859883682113671&wfr=spider&for=pc 自2013年棱镜门事件之后,如何 ...
最新文章
- 智源论坛Live丨青年科学家线上报告会日程发布
- MyBatis的useGenerateKeys的使用方法
- VS2015 提示 无法启动 IIS Express Web 服务器
- Apache Lucene基础教程
- BJFU 质数相关
- 详解Python中的各种数字类型
- android sdk更新后出现please update ADT to the latest ve
- Google Android创赢路线与产品开发实战
- ubuntu安装 gcc 5.4.0
- Wso2 api manager 帮助文档
- 2019年8月8日 星期四 今日计划
- 灰度斜坡intensity ramp和灰度台阶intensity step的区别
- android 基带版本,手机基带是什么?手机的基带版本是什么意思?
- 个人GitHub地址
- WIN10开机显示被调用的对象已与其客户端断开连接解决方法之一
- gucci红包封面怎么抽 gucci红包封面怎么领取
- Ubuntu下阅读CHM格式的文档
- 搭建DVWA出现错误:DVWA System error - config file not found.
- 华中科技大学计算机专业排名2018,2018华中科技大学专业排名及分数线 王牌专业有哪些...
- AutoSAR系列讲解(实践篇)11.4-NvBlockSwComponents(上)
热门文章
- 光标切换键Insert
- selenium驱动IE常见问题解决
- GameFramework篇:StarForce全解读(总目录)
- 十一种值得珍惜的女生
- Photoshop:常用快捷键整理,提高工作效率,你也可以零基础成为PS高手
- Do Your Data Recovery(数据恢复软件)v7.1版本更新
- Python教程:self用法
- android过热自动关机,android实现自动关机的具体方法
- 基于JAVAVue网上书籍购买商城登录计算机毕业设计源码+数据库+lw文档+系统+部署
- 煽情的儿子552=随笔