Mutual TLS Authentication

Protect Admin API

Why use it

Mutual TLS authentication provides a better way to prevent unauthorized access to APISIX.

The clients will provide their certificates to the server and the server will check whether the cert is signed by the supplied CA and decide whether to serve the request.

How to configure

  1. Generate self-signed key pairs, including ca, server, client key pairs.

  2. Modify configuration items in conf/config.yaml:

conf/config.yaml

  1. admin_listen:
  2. ip: 127.0.0.1
  3. port: 9180
  4. https_admin: true
  5. admin_api_mtls:
  6. admin_ssl_ca_cert: "/data/certs/mtls_ca.crt" # Path of your self-signed ca cert.
  7. admin_ssl_cert: "/data/certs/mtls_server.crt" # Path of your self-signed server side cert.
  8. admin_ssl_cert_key: "/data/certs/mtls_server.key" # Path of your self-signed server side key.
  1. Run command:
  1. apisix init
  2. apisix reload

How client calls

Please replace the following certificate paths and domain name with your real ones.

  • Note: The same CA certificate as the server needs to be used *
  1. curl --cacert /data/certs/mtls_ca.crt --key /data/certs/mtls_client.key --cert /data/certs/mtls_client.crt https://admin.apisix.dev:9180/apisix/admin/routes -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1'

etcd with mTLS

How to configure

You need to build APISIX-Base and configure etcd.tls section if you want APISIX to work on an etcd cluster with mTLS enabled.

conf/config.yaml

  1. deployment:
  2. role: traditional
  3. role_traditional:
  4. config_provider: etcd
  5. etcd:
  6. tls:
  7. cert: /data/certs/etcd_client.pem # path of certificate used by the etcd client
  8. key: /data/certs/etcd_client.key # path of key used by the etcd client

If APISIX does not trust the CA certificate that used by etcd server, we need to set up the CA certificate.

conf/config.yaml

  1. apisix:
  2. ssl:
  3. ssl_trusted_certificate: /path/to/certs/ca-certificates.crt # path of CA certificate used by the etcd server

Protect Route

Why use it

Using mTLS is a way to verify clients cryptographically. It is useful and important in cases where you want to have encrypted and secure traffic in both directions.

  • Note: the mTLS protection only happens in HTTPS. If your route can also be accessed via HTTP, you should add additional protection in HTTP or disable the access via HTTP.*

How to configure

We provide a tutorial that explains in detail how to configure mTLS between the client and APISIX.

When configuring ssl, use parameter client.ca and client.depth to configure the root CA that signing client certificates and the max length of certificate chain. Please refer to Admin API for details.

Here is an example Python script to create SSL with mTLS (id is 1, changes admin API url if needed):

create-ssl.py

  1. #!/usr/bin/env python
  2. # coding: utf-8
  3. import sys
  4. # sudo pip install requests
  5. import requests
  6. if len(sys.argv) < 4:
  7. print("bad argument")
  8. sys.exit(1)
  9. with open(sys.argv[1]) as f:
  10. cert = f.read()
  11. with open(sys.argv[2]) as f:
  12. key = f.read()
  13. sni = sys.argv[3]
  14. api_key = "edd1c9f034335f136f87ad84b625c8f1" # Change it
  15. reqParam = {
  16. "cert": cert,
  17. "key": key,
  18. "snis": [sni],
  19. }
  20. if len(sys.argv) >= 5:
  21. print("Setting mTLS")
  22. reqParam["client"] = {}
  23. with open(sys.argv[4]) as f:
  24. clientCert = f.read()
  25. reqParam["client"]["ca"] = clientCert
  26. if len(sys.argv) >= 6:
  27. reqParam["client"]["depth"] = int(sys.argv[5])
  28. resp = requests.put("http://127.0.0.1:9180/apisix/admin/ssls/1", json=reqParam, headers={
  29. "X-API-KEY": api_key,
  30. })
  31. print(resp.status_code)
  32. print(resp.text)

Create SSL:

  1. ./create-ssl.py ./server.pem ./server.key 'mtls.test.com' ./client_ca.pem 10
  2. # test it
  3. curl --resolve 'mtls.test.com:<APISIX_HTTPS_PORT>:<APISIX_URL>' "https://<APISIX_URL>:<APISIX_HTTPS_PORT>/hello" -k --cert ./client.pem --key ./client.key

Please make sure that the SNI fits the certificate domain.

mTLS Between APISIX and Upstream

Why use it

Sometimes the upstream requires mTLS. In this situation, the APISIX acts as the client, it needs to provide client certificate to communicate with upstream.

How to configure

When configuring upstreams, we could use parameter tls.client_cert and tls.client_key to configure the client certificate APISIX used to communicate with upstreams. Please refer to Admin API for details.

This feature requires APISIX to run on APISIX-Base.

Here is a similar Python script to patch a existed upstream with mTLS (changes admin API url if needed):

patch_upstream_mtls.py

  1. #!/usr/bin/env python
  2. # coding: utf-8
  3. import sys
  4. # sudo pip install requests
  5. import requests
  6. if len(sys.argv) < 4:
  7. print("bad argument")
  8. sys.exit(1)
  9. with open(sys.argv[2]) as f:
  10. cert = f.read()
  11. with open(sys.argv[3]) as f:
  12. key = f.read()
  13. id = sys.argv[1]
  14. api_key = "edd1c9f034335f136f87ad84b625c8f1" # Change it
  15. reqParam = {
  16. "tls": {
  17. "client_cert": cert,
  18. "client_key": key,
  19. },
  20. }
  21. resp = requests.patch("http://127.0.0.1:9180/apisix/admin/upstreams/"+id, json=reqParam, headers={
  22. "X-API-KEY": api_key,
  23. })
  24. print(resp.status_code)
  25. print(resp.text)

Patch existed upstream with id testmtls:

  1. ./patch_upstream_mtls.py testmtls ./client.pem ./client.key