如何在 APISIX 使用 Vault 管理证书

更新时间 6/9/2023

API 网关是 API 全生命周期管理中的关键基础组件,是所有终端流量的入口,负责把下游客户端的 API 请求路由到正确的上游服务进行处理。因此,API 网关承担了上游服务和下游客户端之间的网络通信。

Apache APISIX 作为新一代的云原生 API 网关,提供了下游客户端与 APISIX、APISIX 与上游服务之间的 TLS/mTLS 通信机制,从而保证下游客户端与 API 网关之间、API 网关与上游服务之间的网络通信安全。APISIX 将SSL 证书保存为 SSL Certificate 对象,并通过支持 TLS 协议的扩展 SNI 实现 SSL 证书的动态加载。

为了更好地对 APISIX 中 SSL 证书安全存储,APISIX 实现了与 HashiCorp Vault 的集成,从而借助 Vault 的 secret 安全存储优势,实现对 SSL 证书的统一管理。本文以配置下游客户端与 APISIX 之间 HTTPS 通信为例,介绍 APISIX 如何集成 Vault 实现 SSL 证书管理。

Integrate APISIX with Vault

什么是 SSL 证书

SSL/TLS 是一种安全通信协议,它通过建立通信双方的加密网络连接,从而保护网络通信的安全性。SSL/TLS 协议通过认证用户和服务器,确保数据发送到正确的客户机和服务器。此外,SSL/TLS 协议可以加密通信数据,从而确保数据在传输过程中不被窃取、篡改或伪造。

SSL 证书是一种数字证书,用于认证网站的身份,并使用 SSL/TLS 协议对网络通信进行加密。SSL 证书通常由受信任的数字证书颁发机构 CA 颁发,其主要包含以下信息:

  • 证书颁发机构的域名
  • 证书颁发机构
  • 证书颁发机构的数字签名
  • 关联的子域
  • 证书颁发日期
  • 证书到期日期
  • 公钥(私钥为保密状态)

什么是 HashiCorp Vault

HashiCorp Vault(以下简称 Vault)是一款企业级 Secret 管理工具,可以存储和管理令牌、密码、证书等敏感数据。Vault 可以与整个IT系统中的技术进行集成,提供基于身份的安全自动化和加密服务,集中控制对敏感数据和系统的访问,帮助组织降低数据泄露和数据暴露的风险,从而提高云和应用程序的安全性。

HashiCorp Vault

如何在 Vault 中存储 APISIX SSL 证书

环境准备

部署并配置 Vault 服务

本节将使用 Docker 部署一个 Vault 容器服务。如果环境中已有可用的 Vault 服务实例,可跳过本节。

创建并部署一个 Dev 模式下的 Vault 容器,命名为 apisix-quickstart-vault。指定 Vault Token 为 apisix-quickstart-vault-token 并将端口 8200 映射至主机:

1docker run -d --cap-add=IPC_LOCK \
2  -e 'VAULT_DEV_LISTEN_ADDRESS=0.0.0.0:8200' \
3  -e 'VAULT_ADDR=http://0.0.0.0:8200' \
4  -e 'VAULT_DEV_ROOT_TOKEN_ID=apisix-quickstart-vault-token' \
5  -e 'VAULT_TOKEN=apisix-quickstart-vault-token' \
6  --network=apisix-quickstart-net \
7  --name apisix-quickstart-vault \
8  -p 8200:8200 vault:1.13.0

选择 kv 作为 APISIX 的 SSL 证书存储路径:

1docker exec apisix-quickstart-vault vault secrets enable -path=kv -version=1 kv

配置 APISIX

APISIX 需要从 Vault 读取 SSL 证书,因此 Vault 应授予 APISIX 指定路径的读权限。

创建一个名为 apisix-policy.hcl 的 Vault 策略文件,授予 APISIX 对路径 kv/apisix/ 的读权限:

1docker exec apisix-quickstart-vault /bin/sh -c "echo '
2path \"kv/apisix/*\" {
3    capabilities = [\"read\"]
4}
5' > /etc/apisix-policy.hcl"

将创建好的策略文件 apisix-policy.hcl 应用至 Vault:

1docker exec apisix-quickstart-vault vault policy write apisix-policy /etc/apisix-policy.hcl

创建一个 id 为 quickstart-secret-id 的 APISIX secret 对象,保存 Vault 连接信息和证书存储路径:

1curl -i "http://127.0.0.1:9180/apisix/admin/secrets/vault/quickstart-secret-id" -X PUT -d '
2{
3    "uri": "http://apisix-quickstart-vault:8200",
4    "prefix": "kv/apisix",
5    "token" : "apisix-quickstart-vault-token"
6}'

存储 SSL 证书至 Vault

创建自签 CA 证书 ca.crt 和密钥 ca.key

1openssl genrsa -out ca.key 2048 && \
2  openssl req -new -sha256 -key ca.key -out ca.csr -subj "/CN=ROOTCA" && \
3  openssl x509 -req -days 36500 -sha256 -extensions v3_ca -signkey ca.key -in ca.csr -out ca.crt

通过 CA 签发 SSL 证书 server.crt 及密钥 server.key,其 common name (CN) 为 test.com

1openssl genrsa -out server.key 2048 && \
2  openssl req -new -sha256 -key server.key -out server.csr -subj "/CN=test.com" && \
3  openssl x509 -req -days 36500 -sha256 -extensions v3_req \
4  -CA ca.crt -CAkey ca.key -CAserial ca.srl -CAcreateserial \
5  -in server.csr -out server.crt

将签发的 SSL 证书及密钥拷贝至 Vault 容器中:

1docker cp server.key apisix-quickstart-vault:/root/
2docker cp server.crt apisix-quickstart-vault:/root/

使用 vault kv put 命令,将 SSL证书及密钥存储为 secret,其 key 为 ssl,存储路径为 kv/apisix

1docker exec apisix-quickstart-vault vault kv put kv/apisix/ssl test.com.crt=@/root/server.crt test.com.key=@/root/server.key

通过上述命令,我们在 Vault 中存储了一个名为 ssl 的 secret,其包含 2 个键值对:证书及私钥。

如何使用 Vault 中存储的 APISIX SSL 证书

APISIX 支持下游客户端与 APISIX、APISIX 与上游服务之间的 TLS/mTLS 网络通信加密,Vault 存储的 SSL 证书均可使用。本文以配置客户端与 APISIX 之间 HTTPS 通信为例,演示如何在 APISIX 中使用 Vault 存储的 SSL 证书。

配置客户端与 APISIX 之间 HTTPS 通信

创建一个 SSL certificate 对象来保存 SSL 证书:

1curl -i "http://127.0.0.1:9180/apisix/admin/ssls" -X PUT -d '
2{
3  "id": "quickstart-tls-client-ssl",
4  "sni": "test.com",
5  "cert": "$secret://vault/quickstart-secret-id/ssl/test.com.crt",
6  "key": "$secret://vault/quickstart-secret-id/ssl/test.com.key"
7}'

该对象的 sni 为 test.com,与签发证书的 CN 保持一致。cert 和 key 对应为签发的证书及私钥,通过既定的 secret 资源定位符从 Vault 中自动获取,其资源定位规则为:

1$secret://$manager/$id/$secret_name/$key
  • manager: 密钥管理服务 Vault
  • id: APISIX secret 资源 ID
  • secret_name: Vault 中的 secret 名称
  • key:名为 secret_name 的 secret 中键值对的 key

验证客户端与 APISIX 之间 HTTPS 通信

创建一个路由,将所有发送至 /ip 的请求转发至上游 httpbin.org

1curl -i "http://127.0.0.1:9180/apisix/admin/routes" -X PUT -d '
2{
3  "id": "quickstart-client-ip",
4  "uri": "/ip",
5  "upstream": {
6    "nodes": {
7      "httpbin.org:80":1
8    },
9    "type": "roundrobin"
10  }
11}'

使用 cURL 发送请求至 https://test.com:9443/iptest.com 可解析为 127.0.0.1:

1curl -ikv --resolve "test.com:9443:127.0.0.1" "https://test.com:9443/ip"

如果配置成功,cURL 返回的客户端与 APISIX TLS 握手过程将与以下结果相同:

1* Added test.com:9443:127.0.0.1 to DNS cache
2* Hostname test.com was found in DNS cache
3*   Trying 127.0.0.1:9443...
4* Connected to test.com (127.0.0.1) port 9443 (#0)
5* ALPN, offering h2
6* ALPN, offering http/1.1
7* successfully set certificate verify locations:
8*  CAfile: /etc/ssl/certs/ca-certificates.crt
9*  CApath: /etc/ssl/certs
10* TLSv1.3 (OUT), TLS handshake, Client hello (1):
11* TLSv1.3 (IN), TLS handshake, Server hello (2):
12* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
13* TLSv1.3 (IN), TLS handshake, Certificate (11):
14* TLSv1.3 (IN), TLS handshake, CERT verify (15):
15* TLSv1.3 (IN), TLS handshake, Finished (20):
16* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
17* TLSv1.3 (OUT), TLS handshake, Finished (20):
18* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
19* ALPN, server accepted to use h2
20* Server certificate:
21*  subject: CN=test.com
22*  start date: Apr 21 07:47:54 2023 GMT
23*  expire date: Mar 28 07:47:54 2123 GMT
24*  issuer: CN=ROOTCA
25*  SSL certificate verify result: unable to get local issuer certificate (20), continuing anyway.
26* Using HTTP2, server supports multi-use
27* Connection state changed (HTTP/2 confirmed)
28* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
29* Using Stream ID: 1 (easy handle 0x556274d632e0)
30> GET /ip HTTP/2
31> Host: test.com:9443
32> user-agent: curl/7.74.0
33> accept: */*
34>
35* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
36* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
37* old SSL session ID is stale, removing
38* Connection state changed (MAX_CONCURRENT_STREAMS == 128)!
39< HTTP/2 200
40HTTP/2 200
41...

总结

本文介绍了 APISIX 如何集成 Vault 实现 SSL 证书管理,并以配置下游客户端与 APISIX 之间 HTTPS 通信为例,详细展示了配置与集成步骤。关于 APISIX 中 SSL 证书的相关概念及使用场景,可进一步参考以下文章:

微信咨询

获取方案