This is an automated email from the ASF dual-hosted git repository.
spacewander pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix.git
The following commit(s) were added to refs/heads/master by this push:
new 7945e6d98 docs: set up multiple CA certificates (#7540)
7945e6d98 is described below
commit 7945e6d98b4f03576af92c2255b52e367952d5f7
Author: tzssangglass <[email protected]>
AuthorDate: Fri Jul 29 17:15:38 2022 +0800
docs: set up multiple CA certificates (#7540)
---
docs/en/latest/certificate.md | 143 ++++++++++++++++++++++++++++++++++++++++++
docs/zh/latest/certificate.md | 143 ++++++++++++++++++++++++++++++++++++++++++
2 files changed, 286 insertions(+)
diff --git a/docs/en/latest/certificate.md b/docs/en/latest/certificate.md
index 5507e5ee3..38140f36c 100644
--- a/docs/en/latest/certificate.md
+++ b/docs/en/latest/certificate.md
@@ -171,3 +171,146 @@ private keys by `certs` and `keys`.
`APISIX` will pair certificate and private key with the same indice as a SSL
key
pair. So the length of `certs` and `keys` must be same.
+
+### set up multiple CA certificates
+
+APISIX currently uses CA certificates in several places, such as [Protect
Admin API](./mtls.md#protect-admin-api), [etcd with
mTLS](./mtls.md#etcd-with-mtls), and [Deployment
Modes](./architecture-design/deployment-role.md).
+
+In these places, `ssl_trusted_certificate` or `trusted_ca_cert` will be used
to set up the CA certificate, but these configurations will eventually be
translated into
[lua_ssl_trusted_certificate](https://github.com/openresty/lua-nginx-module#lua_ssl_trusted_certificate)
directive in OpenResty.
+
+If you need to set up different CA certificates in different places, then you
can package these CA certificates into a CA bundle file and point to this file
when you need to set up CAs. This will avoid the problem that the generated
`lua_ssl_trusted_certificate` has multiple locations and overwrites each other.
+
+The following is a complete example to show how to set up multiple CA
certificates in APISIX.
+
+Suppose we let client and APISIX Admin API, APISIX and ETCD communicate with
each other using mTLS protocol, and currently there are two CA certificates,
`foo_ca.crt` and `bar_ca.crt`, and use each of these two CA certificates to
issue client and server certificate pairs, `foo_ca.crt` and its issued
certificate pair are used to protect Admin API, and `bar_ca.crt` and its issued
certificate pair are used to protect ETCD.
+
+The following table details the configurations involved in this example and
what they do:
+
+| Configuration | Type | Description
|
+| ------------- | ------- |
-------------------------------------------------------------------------------------------------------------------------------------------------------------
|
+| foo_ca.crt | CA cert | Issues the secondary certificate required for
the client to communicate with the APISIX Admin API over mTLS.
|
+| foo_client.crt | cert | A certificate issued by `foo_ca.crt` and used
by the client to prove its identity when accessing the APISIX Admin API.
|
+| foo_client.key | key | Issued by `foo_ca.crt`, used by the client,
the key file required to access the APISIX Admin API.
|
+| foo_server.crt | cert | Issued by `foo_ca.crt`, used by APISIX,
corresponding to the `apisix.admin_api_mtls.admin_ssl_cert` configuration
entry. |
+| foo_server.key | key | Issued by `foo_ca.crt`, used by APISIX,
corresponding to the `apisix.admin_api_mtls.admin_ssl_cert_key` configuration
entry. |
+| admin.apisix.dev | doname | Common Name used in issuing `foo_server.crt`
certificate, through which the client accesses APISIX Admin API
|
+| bar_ca.crt | CA cert | Issues the secondary certificate required for
APISIX to communicate with ETCD over mTLS.
|
+| bar_etcd.crt | cert | Issued by `bar_ca.crt` and used by ETCD,
corresponding to the `-cert-file` option in the ETCD startup command.
|
+| bar_etcd.key | key | Issued by `bar_ca.crt` and used by ETCD,
corresponding to the `--key-file` option in the ETCD startup command.
|
+| bar_apisix.crt | cert | Issued by `bar_ca.crt`, used by APISIX,
corresponding to the `etcd.tls.cert` configuration entry.
|
+| bar_apisix.key | key | Issued by `bar_ca.crt`, used by APISIX,
corresponding to the `etcd.tls.key` configuration entry.
|
+| etcd.cluster.dev | key | Common Name used in issuing `bar_etcd.crt`
certificate, which is used as SNI when APISIX communicates with ETCD over mTLS.
corresponds to `etcd.tls.sni` configuration item. |
+| apisix.ca-bundle | CA bundle | Merged from `foo_ca.crt` and `bar_ca.crt`,
replacing `foo_ca.crt` and `bar_ca.crt`.
|
+
+1. Create CA bundle files
+
+```
+cat /path/to/foo_ca.crt /path/to/bar_ca.crt > apisix.ca-bundle
+```
+
+2. Start the ETCD cluster and enable client authentication
+
+Start by writing a `goreman` configuration named
`Procfile-single-enable-mtls`, the content as:
+
+```text
+# Use goreman to run `go get github.com/mattn/goreman`
+etcd1: etcd --name infra1 --listen-client-urls https://127.0.0.1:12379
--advertise-client-urls https://127.0.0.1:12379 --listen-peer-urls
http://127.0.0.1:12380 --initial-advertise-peer-urls http://127.0.0.1:12380
--initial-cluster-token etcd-cluster-1 --initial-cluster
'infra1=http://127.0.0.1:12380,infra2=http://127.0.0.1:22380,infra3=http://127.0.0.1:32380'
--initial-cluster-state new --cert-file /path/to/bar_etcd.crt --key-file
/path/to/bar_etcd.key --client-cert-auth --trusted-ca-fi [...]
+etcd2: etcd --name infra2 --listen-client-urls https://127.0.0.1:22379
--advertise-client-urls https://127.0.0.1:22379 --listen-peer-urls
http://127.0.0.1:22380 --initial-advertise-peer-urls http://127.0.0.1:22380
--initial-cluster-token etcd-cluster-1 --initial-cluster
'infra1=http://127.0.0.1:12380,infra2=http://127.0.0.1:22380,infra3=http://127.0.0.1:32380'
--initial-cluster-state new --cert-file /path/to/bar_etcd.crt --key-file
/path/to/bar_etcd.key --client-cert-auth --trusted-ca-fi [...]
+etcd3: etcd --name infra3 --listen-client-urls https://127.0.0.1:32379
--advertise-client-urls https://127.0.0.1:32379 --listen-peer-urls
http://127.0.0.1:32380 --initial-advertise-peer-urls http://127.0.0.1:32380
--initial-cluster-token etcd-cluster-1 --initial-cluster
'infra1=http://127.0.0.1:12380,infra2=http://127.0.0.1:22380,infra3=http://127.0.0.1:32380'
--initial-cluster-state new --cert-file /path/to/bar_etcd.crt --key-file
/path/to/bar_etcd.key --client-cert-auth --trusted-ca-fi [...]
+```
+
+Use `goreman` to start the ETCD cluster:
+
+```shell
+goreman -f Procfile-single-enable-mtls start > goreman.log 2>&1 &
+```
+
+3. Update `config.yaml`
+
+```yaml
+apisix:
+ admin_key:
+ - name: admin
+ key: edd1c9f034335f136f87ad84b625c8f1
+ role: admin
+ port_admin: 9180
+ https_admin: true
+
+ admin_api_mtls:
+ admin_ssl_ca_cert: /path/to/apisix.ca-bundle
+ admin_ssl_cert: /path/to/foo_server.crt
+ admin_ssl_cert_key: /path/to/foo_server.key
+
+ ssl:
+ ssl_trusted_certificate: /path/to/apisix.ca-bundle
+
+etcd:
+ host:
+ - "https://127.0.0.1:12379"
+ - "https://127.0.0.1:22379"
+ - "https://127.0.0.1:32379"
+ tls:
+ cert: /path/to/bar_apisix.crt
+ key: /path/to/bar_apisix.key
+ sni: etcd.cluster.dev
+```
+
+4. Test APISIX Admin API
+
+Start APISIX, if APISIX starts successfully and there is no abnormal output in
`logs/error.log`, it means that mTLS communication between APISIX and ETCD is
normal.
+
+Use curl to simulate a client, communicate with APISIX Admin API with mTLS,
and create a route:
+
+```shell
+curl -vvv \
+ --resolve 'admin.apisix.dev:9180:127.0.0.1'
https://admin.apisix.dev:9180/apisix/admin/routes/1 \
+ --cert /path/to/foo_client.crt \
+ --key /path/to/foo_client.key \
+ --cacert /path/to/apisix.ca-bundle \
+ -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -i -d '
+{
+ "uri": "/get",
+ "upstream": {
+ "type": "roundrobin",
+ "nodes": {
+ "httpbin.org:80": 1
+ }
+ }
+}'
+```
+
+A successful mTLS communication between curl and the APISIX Admin API is
indicated if the following SSL handshake process is output:
+
+```shell
+* TLSv1.3 (OUT), TLS handshake, Client hello (1):
+* TLSv1.3 (IN), TLS handshake, Server hello (2):
+* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
+* TLSv1.3 (IN), TLS handshake, Request CERT (13):
+* TLSv1.3 (IN), TLS handshake, Certificate (11):
+* TLSv1.3 (IN), TLS handshake, CERT verify (15):
+* TLSv1.3 (IN), TLS handshake, Finished (20):
+* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
+* TLSv1.3 (OUT), TLS handshake, Certificate (11):
+* TLSv1.3 (OUT), TLS handshake, CERT verify (15):
+* TLSv1.3 (OUT), TLS handshake, Finished (20):
+* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
+```
+
+5. Verify APISIX proxy
+
+```shell
+curl http://127.0.0.1:9080/get -i
+
+HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 298
+Connection: keep-alive
+Date: Tue, 26 Jul 2022 16:31:00 GMT
+Access-Control-Allow-Origin: *
+Access-Control-Allow-Credentials: true
+Server: APISIX/2.14.1
+
+...
+```
+
+APISIX proxied the request to the `/get` path of the upstream `httpbin.org`
and returned `HTTP/1.1 200 OK`. The whole process is working fine using CA
bundle instead of CA certificate.
diff --git a/docs/zh/latest/certificate.md b/docs/zh/latest/certificate.md
index e6c433e2f..8b89d6f6c 100644
--- a/docs/zh/latest/certificate.md
+++ b/docs/zh/latest/certificate.md
@@ -168,3 +168,146 @@ curl --resolve 'www.test.com:9443:127.0.0.1'
https://www.test.com:9443/hello -v
* `keys`:PEM 格式的 SSL 证书私钥列表
`APISIX` 会将相同下标的证书和私钥配对使用,因此 `certs` 和 `keys` 列表的长度必须一致。
+
+### 设置多个 CA 证书
+
+APISIX 目前支持在多处设置 CA 证书,比如 [保护 Admin API](./mtls.md#保护-admin-api),[保护
ETCD](./mtls.md#保护-etcd),以及
[部署模式](../../en/latest/architecture-design/deployment-role.md) 等。
+
+在这些地方,使用 `ssl_trusted_certificate` 或 `trusted_ca_cert` 来配置 CA 证书,但是这些配置最终将转化为
OpenResty 的
[lua_ssl_trusted_certificate](https://github.com/openresty/lua-nginx-module#lua_ssl_trusted_certificate)
指令。
+
+如果你需要在不同的地方指定不同的 CA 证书,你可以将这些 CA 证书制作成一个 CA bundle 文件,在需要用到 CA
证书的地方将配置指向这个文件。这样可以避免生成的 `lua_ssl_trusted_certificate` 存在多处并且互相覆盖的问题。
+
+下面用一个完整的例子来展示如何在 APISIX 设置多个 CA 证书。
+
+假设让 client 与 APISIX Admin API,APISIX 与 ETCD 之间都使用 mTLS 协议进行通信,目前有两张 CA 证书,分别是
`foo_ca.crt` 和 `bar_ca.crt`,用这两张 CA 证书各自签发 client 与 server 证书对,`foo_ca.crt`
及其签发的证书对用于保护 Admin API,`bar_ca.crt` 及其签发的证书对用于保护 ETCD。
+
+下表详细列出这个示例所涉及到的配置及其作用:
+
+| 配置 | 类型 | 用途
|
+| ------------- | ------- |
-----------------------------------------------------------------------------------------------------------
|
+| foo_ca.crt | CA 证书 | 签发客户端与 APISIX Admin API 进行 mTLS 通信所需的次级证书。
|
+| foo_client.crt | 证书 | 由 `foo_ca.crt` 签发,客户端使用,访问 APISIX Admin API
时证明自身身份的证书。 |
+| foo_client.key | 密钥文件 | 由 `foo_ca.crt` 签发,客户端使用,访问 APISIX Admin API
所需的密钥文件。 |
+| foo_server.crt | 证书 | 由 `foo_ca.crt` 签发,APISIX 使用,对应
`apisix.admin_api_mtls.admin_ssl_cert` 配置项。 |
+| foo_server.key | 密钥文件 | 由 `foo_ca.crt` 签发,APISIX 使用,对应
`apisix.admin_api_mtls.admin_ssl_cert_key` 配置项。 |
+| admin.apisix.dev | 域名 | 签发 `foo_server.crt` 证书时使用的 Common
Name,客户端通过该域名访问 APISIX Admin API |
+| bar_ca.crt | CA 证书 | 签发 APISIX 与 ETCD 进行 mTLS 通信所需的次级证书。
|
+| bar_etcd.crt | 证书 | 由 `bar_ca.crt` 签发,ETCD 使用,对应 ETCD 启动命令中的
`--cert-file` 选项。 |
+| bar_etcd.key | 密钥文件 | 由 `bar_ca.crt` 签发,ETCD 使用,对应 ETCD 启动命令中的
`--key-file` 选项。 |
+| bar_apisix.crt | 证书 | 由 `bar_ca.crt` 签发,APISIX 使用,对应 `etcd.tls.cert`
配置项。 |
+| bar_apisix.key | 密钥文件 | 由 `bar_ca.crt` 签发,APISIX 使用,对应 `etcd.tls.key`
配置项。 |
+| etcd.cluster.dev | 域名 | 签发 `bar_etcd.crt` 证书时使用的 Common Name,APISIX 与
ETCD 进行 mTLS 通信时,使用该域名作为 SNI。对应 `etcd.tls.sni` 配置项。|
+| apisix.ca-bundle | CA bundle | 由 `foo_ca.crt` 与 `bar_ca.crt` 合并而成,替代
`foo_ca.crt` 与 `bar_ca.crt`。 |
+
+1. 制作 CA bundle 文件
+
+```
+cat /path/to/foo_ca.crt /path/to/bar_ca.crt > apisix.ca-bundle
+```
+
+2. 启动 ETCD 集群,并开启客户端验证
+
+先编写 `goreman` 配置,命名为 `Procfile-single-enable-mtls`,内容如下:
+
+```text
+# 运行 `go get github.com/mattn/goreman` 安装 goreman,用 goreman 执行以下命令:
+etcd1: etcd --name infra1 --listen-client-urls https://127.0.0.1:12379
--advertise-client-urls https://127.0.0.1:12379 --listen-peer-urls
http://127.0.0.1:12380 --initial-advertise-peer-urls http://127.0.0.1:12380
--initial-cluster-token etcd-cluster-1 --initial-cluster
'infra1=http://127.0.0.1:12380,infra2=http://127.0.0.1:22380,infra3=http://127.0.0.1:32380'
--initial-cluster-state new --cert-file /path/to/bar_etcd.crt --key-file
/path/to/bar_etcd.key --client-cert-auth --trusted-ca-fi [...]
+etcd2: etcd --name infra2 --listen-client-urls https://127.0.0.1:22379
--advertise-client-urls https://127.0.0.1:22379 --listen-peer-urls
http://127.0.0.1:22380 --initial-advertise-peer-urls http://127.0.0.1:22380
--initial-cluster-token etcd-cluster-1 --initial-cluster
'infra1=http://127.0.0.1:12380,infra2=http://127.0.0.1:22380,infra3=http://127.0.0.1:32380'
--initial-cluster-state new --cert-file /path/to/bar_etcd.crt --key-file
/path/to/bar_etcd.key --client-cert-auth --trusted-ca-fi [...]
+etcd3: etcd --name infra3 --listen-client-urls https://127.0.0.1:32379
--advertise-client-urls https://127.0.0.1:32379 --listen-peer-urls
http://127.0.0.1:32380 --initial-advertise-peer-urls http://127.0.0.1:32380
--initial-cluster-token etcd-cluster-1 --initial-cluster
'infra1=http://127.0.0.1:12380,infra2=http://127.0.0.1:22380,infra3=http://127.0.0.1:32380'
--initial-cluster-state new --cert-file /path/to/bar_etcd.crt --key-file
/path/to/bar_etcd.key --client-cert-auth --trusted-ca-fi [...]
+```
+
+使用 `goreman` 来启动 ETCD 集群:
+
+```shell
+goreman -f Procfile-single-enable-mtls start > goreman.log 2>&1 &
+```
+
+3. 更新 `config.yaml`
+
+```yaml
+apisix:
+ admin_key:
+ - name: admin
+ key: edd1c9f034335f136f87ad84b625c8f1
+ role: admin
+ port_admin: 9180
+ https_admin: true
+
+ admin_api_mtls:
+ admin_ssl_ca_cert: /path/to/apisix.ca-bundle
+ admin_ssl_cert: /path/to/foo_server.crt
+ admin_ssl_cert_key: /path/to/foo_server.key
+
+ ssl:
+ ssl_trusted_certificate: /path/to/apisix.ca-bundle
+
+etcd:
+ host:
+ - "https://127.0.0.1:12379"
+ - "https://127.0.0.1:22379"
+ - "https://127.0.0.1:32379"
+ tls:
+ cert: /path/to/bar_apisix.crt
+ key: /path/to/bar_apisix.key
+ sni: etcd.cluster.dev
+```
+
+4. 测试 Admin API
+
+启动 APISIX,如果 APISIX 启动成功,`logs/error.log` 中没有异常输出,表示 APISIX 与 ETCD 之间进行 mTLS
通信正常。
+
+用 curl 模拟客户端,与 APISIX Admin API 进行 mTLS 通信,并创建一条路由:
+
+```shell
+curl -vvv \
+ --resolve 'admin.apisix.dev:9180:127.0.0.1'
https://admin.apisix.dev:9180/apisix/admin/routes/1 \
+ --cert /path/to/foo_client.crt \
+ --key /path/to/foo_client.key \
+ --cacert /path/to/apisix.ca-bundle \
+ -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -i -d '
+{
+ "uri": "/get",
+ "upstream": {
+ "type": "roundrobin",
+ "nodes": {
+ "httpbin.org:80": 1
+ }
+ }
+}'
+```
+
+如果输出以下 SSL 握手过程,表示 curl 与 APISIX Admin API 之间 mTLS 通信成功:
+
+```shell
+* TLSv1.3 (OUT), TLS handshake, Client hello (1):
+* TLSv1.3 (IN), TLS handshake, Server hello (2):
+* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
+* TLSv1.3 (IN), TLS handshake, Request CERT (13):
+* TLSv1.3 (IN), TLS handshake, Certificate (11):
+* TLSv1.3 (IN), TLS handshake, CERT verify (15):
+* TLSv1.3 (IN), TLS handshake, Finished (20):
+* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
+* TLSv1.3 (OUT), TLS handshake, Certificate (11):
+* TLSv1.3 (OUT), TLS handshake, CERT verify (15):
+* TLSv1.3 (OUT), TLS handshake, Finished (20):
+* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
+```
+
+5. 验证 APISIX 代理
+
+```shell
+curl http://127.0.0.1:9080/get -i
+
+HTTP/1.1 200 OK
+Content-Type: application/json
+Content-Length: 298
+Connection: keep-alive
+Date: Tue, 26 Jul 2022 16:31:00 GMT
+Access-Control-Allow-Origin: *
+Access-Control-Allow-Credentials: true
+Server: APISIX/2.14.1
+
+……
+```
+
+APISIX 将请求代理到了上游 `httpbin.org` 的 `/get` 路径,并返回了 `HTTP/1.1 200 OK`。整个过程使用 CA
bundle 替代 CA 证书是正常可用的。