Certificate
It is most common for an SSL certificate to contain only one domain. We can create an ssl
object. Here is a simple case, creates a ssl
object and route
object.
cert
: PEM-encoded public certificate of the SSL key pair.key
: PEM-encoded private key of the SSL key pair.snis
: Hostname(s) to associate with this certificate as SNIs. To set this attribute this certificate must have a valid private key associated with it.
We will use the Python script below to simplify the example:
# create SSL object
./ssl.py t.crt t.key test.com
# create Router object
curl http://127.0.0.1:9180/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -i -d '
{
"uri": "/hello",
"hosts": ["test.com"],
"methods": ["GET"],
"upstream": {
"type": "roundrobin",
"nodes": {
"127.0.0.1:1980": 1
}
}
}'
# make a test
curl --resolve 'test.com:9443:127.0.0.1' https://test.com:9443/hello -vvv
* Added test.com:9443:127.0.0.1 to DNS cache
* About to connect() to test.com port 9443 (#0)
* Trying 127.0.0.1...
* Connected to test.com (127.0.0.1) port 9443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* skipping SSL peer certificate verification
* SSL connection using TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
* Server certificate:
* subject: CN=test.com,O=iresty,L=ZhuHai,ST=GuangDong,C=CN
* start date: Jun 24 22:18:05 2019 GMT
* expire date: May 31 22:18:05 2119 GMT
* common name: test.com
* issuer: CN=test.com,O=iresty,L=ZhuHai,ST=GuangDong,C=CN
> GET /hello HTTP/1.1
> User-Agent: curl/7.29.0
> Host: test.com:9443
> Accept: */*
Sometimes, one SSL certificate may contain a wildcard domain like *.test.com
, that means it can accept more than one domain, eg: www.test.com
or mail.test.com
.
Here is an example, note that the value we pass as sni
is *.test.com
.
./ssl.py t.crt t.key '*.test.com'
curl http://127.0.0.1:9180/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -i -d '
{
"hosts": ["*.test.com"],
"methods": ["GET"],
"upstream": {
"type": "roundrobin",
"nodes": {
"127.0.0.1:1980": 1
}
}
}'
# make a test
curl --resolve 'www.test.com:9443:127.0.0.1' https://www.test.com:9443/hello -vvv
* Added test.com:9443:127.0.0.1 to DNS cache
* About to connect() to test.com port 9443 (#0)
* Trying 127.0.0.1...
* Connected to test.com (127.0.0.1) port 9443 (#0)
* Initializing NSS with certpath: sql:/etc/pki/nssdb
* skipping SSL peer certificate verification
* SSL connection using TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
* Server certificate:
* subject: CN=test.com,O=iresty,L=ZhuHai,ST=GuangDong,C=CN
* start date: Jun 24 22:18:05 2019 GMT
* expire date: May 31 22:18:05 2119 GMT
* common name: test.com
* issuer: CN=test.com,O=iresty,L=ZhuHai,ST=GuangDong,C=CN
> GET /hello HTTP/1.1
> User-Agent: curl/7.29.0
> Host: test.com:9443
> Accept: */*
If your SSL certificate may contain more than one domain, like www.test.com
and mail.test.com
, then you can add them into the snis
array. For example:
certs
: PEM-encoded certificate array.keys
: PEM-encoded private key array.
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.
APISIX currently uses CA certificates in several places, such as , etcd with mTLS, and .
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 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.
The following table details the configurations involved in this example and what they do:
- Create CA bundle files
cat /path/to/foo_ca.crt /path/to/bar_ca.crt > apisix.ca-bundle
- Start the ETCD cluster and enable client authentication
Start by writing a goreman
configuration named Procfile-single-enable-mtls
, the content as:
# 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-file /path/to/apisix.ca-bundle
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-file /path/to/apisix.ca-bundle
Use goreman
to start the ETCD cluster:
- Update
config.yaml
deployment:
admin:
admin_key
- name: admin
key: edd1c9f034335f136f87ad84b625c8f1
role: admin
admin_listen:
ip: 127.0.0.1
port: 9180
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
apisix:
ssl:
ssl_trusted_certificate: /path/to/apisix.ca-bundle
deployment:
role: traditional
role_traditional:
config_provider: etcd
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
- 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:
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
}
}
}'
- Verify APISIX proxy
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 . The whole process is working fine using CA bundle instead of CA certificate.