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:

    1. # create SSL object
    2. ./ssl.py t.crt t.key test.com
    3. # create Router object
    4. curl http://127.0.0.1:9180/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -i -d '
    5. {
    6. "uri": "/hello",
    7. "hosts": ["test.com"],
    8. "methods": ["GET"],
    9. "upstream": {
    10. "type": "roundrobin",
    11. "nodes": {
    12. "127.0.0.1:1980": 1
    13. }
    14. }
    15. }'
    16. # make a test
    17. curl --resolve 'test.com:9443:127.0.0.1' https://test.com:9443/hello -vvv
    18. * Added test.com:9443:127.0.0.1 to DNS cache
    19. * About to connect() to test.com port 9443 (#0)
    20. * Trying 127.0.0.1...
    21. * Connected to test.com (127.0.0.1) port 9443 (#0)
    22. * Initializing NSS with certpath: sql:/etc/pki/nssdb
    23. * skipping SSL peer certificate verification
    24. * SSL connection using TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
    25. * Server certificate:
    26. * subject: CN=test.com,O=iresty,L=ZhuHai,ST=GuangDong,C=CN
    27. * start date: Jun 24 22:18:05 2019 GMT
    28. * expire date: May 31 22:18:05 2119 GMT
    29. * common name: test.com
    30. * issuer: CN=test.com,O=iresty,L=ZhuHai,ST=GuangDong,C=CN
    31. > GET /hello HTTP/1.1
    32. > User-Agent: curl/7.29.0
    33. > Host: test.com:9443
    34. > 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.

    1. ./ssl.py t.crt t.key '*.test.com'
    2. curl http://127.0.0.1:9180/apisix/admin/routes/1 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -i -d '
    3. {
    4. "hosts": ["*.test.com"],
    5. "methods": ["GET"],
    6. "upstream": {
    7. "type": "roundrobin",
    8. "nodes": {
    9. "127.0.0.1:1980": 1
    10. }
    11. }
    12. }'
    13. # make a test
    14. curl --resolve 'www.test.com:9443:127.0.0.1' https://www.test.com:9443/hello -vvv
    15. * Added test.com:9443:127.0.0.1 to DNS cache
    16. * About to connect() to test.com port 9443 (#0)
    17. * Trying 127.0.0.1...
    18. * Connected to test.com (127.0.0.1) port 9443 (#0)
    19. * Initializing NSS with certpath: sql:/etc/pki/nssdb
    20. * skipping SSL peer certificate verification
    21. * SSL connection using TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
    22. * Server certificate:
    23. * subject: CN=test.com,O=iresty,L=ZhuHai,ST=GuangDong,C=CN
    24. * start date: Jun 24 22:18:05 2019 GMT
    25. * expire date: May 31 22:18:05 2119 GMT
    26. * common name: test.com
    27. * issuer: CN=test.com,O=iresty,L=ZhuHai,ST=GuangDong,C=CN
    28. > GET /hello HTTP/1.1
    29. > User-Agent: curl/7.29.0
    30. > Host: test.com:9443
    31. > 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:

    1. Create CA bundle files
    1. cat /path/to/foo_ca.crt /path/to/bar_ca.crt > apisix.ca-bundle
    1. Start the ETCD cluster and enable client authentication

    Start by writing a goreman configuration named Procfile-single-enable-mtls, the content as:

    1. # Use goreman to run `go get github.com/mattn/goreman`
    2. 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
    3. 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:

    1. Update config.yaml
    1. deployment:
    2. admin:
    3. admin_key
    4. - name: admin
    5. key: edd1c9f034335f136f87ad84b625c8f1
    6. role: admin
    7. admin_listen:
    8. ip: 127.0.0.1
    9. port: 9180
    10. admin_api_mtls:
    11. admin_ssl_ca_cert: /path/to/apisix.ca-bundle
    12. admin_ssl_cert: /path/to/foo_server.crt
    13. admin_ssl_cert_key: /path/to/foo_server.key
    14. apisix:
    15. ssl:
    16. ssl_trusted_certificate: /path/to/apisix.ca-bundle
    17. deployment:
    18. role: traditional
    19. role_traditional:
    20. config_provider: etcd
    21. etcd:
    22. host:
    23. - "https://127.0.0.1:12379"
    24. - "https://127.0.0.1:22379"
    25. - "https://127.0.0.1:32379"
    26. tls:
    27. cert: /path/to/bar_apisix.crt
    28. key: /path/to/bar_apisix.key
    29. sni: etcd.cluster.dev
    1. 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:

    1. curl -vvv \
    2. --resolve 'admin.apisix.dev:9180:127.0.0.1' https://admin.apisix.dev:9180/apisix/admin/routes/1 \
    3. --cert /path/to/foo_client.crt \
    4. --key /path/to/foo_client.key \
    5. --cacert /path/to/apisix.ca-bundle \
    6. -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -i -d '
    7. {
    8. "uri": "/get",
    9. "upstream": {
    10. "type": "roundrobin",
    11. "nodes": {
    12. "httpbin.org:80": 1
    13. }
    14. }
    15. }'
    1. Verify APISIX proxy
    1. curl http://127.0.0.1:9080/get -i
    2. HTTP/1.1 200 OK
    3. Content-Type: application/json
    4. Content-Length: 298
    5. Connection: keep-alive
    6. Date: Tue, 26 Jul 2022 16:31:00 GMT
    7. Access-Control-Allow-Origin: *
    8. Access-Control-Allow-Credentials: true
    9. Server: APISIX/2.14.1
    10. ...

    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.