Enable Upstream Mutual TLS
Mutual TLS (aka mTLS) asks the client to provide a certificate as its identifier so the server can verify it in a TLS handshake. It can be enforced between the clients and Apache APISIX, and between Apache APISIX and the backend services.
This guide will show you how to configure mTLS between Apache APISIX and your backend services.
Please read What is SSL before you go ahead.
Prepare the Environment
Deploy Apache APISIX
Please refer to How to Deploy Apache APISIX to learn how to deploy Apache APISIX and connect it to API7 Cloud. In this guide, we'll deploy an Apache APISIX instance on Docker.
Sign Certificates
To show the mTLS feature, we use openssl
to generate three key pairs:
- The CA certificate and private key
- The server certificate and private key (used by backend service)
- The client certificate and private key (used by Apache APISIX)
# Generate the CA certificate and private key
openssl req -x509 -nodes -new -keyout ca.key -out ca.crt -days 3650 -subj "/C=/ST=/L=/O=/OU=web/CN=private_ca"
# Generate the server certificate sign request and its private key
openssl req -newkey rsa:2048 -nodes -days 3650 -keyout server.key -out server.req
# Generate the server certificate
openssl x509 -req -days 3650 -set_serial 01 -in server.req -out server.crt -CA ca.crt -CAkey ca.key
# Generate the client certificate sign request and its private key
openssl req -newkey rsa:2048 -nodes -days 3650 -keyout client.key -out client.req -subj "/C=/ST=/L=/O=/OU=web/CN=mtls.httpbin.org"
# Generate the client certificate
openssl x509 -req -days 3650 -set_serial 01 -in client.req -out client.crt -CA ca.crt -CAkey ca.key
You can skip the above steps if you already have these certificates.
Create SSL Object
Follow the tips in How to Create SSL Object and upload the server certificate, private key, CA certificate, API7 Cloud creates an SSL object.
Deploy Backend Service
For demonstration, in this guide, we create a Nginx container. It'll return a simple
string "mtls upstream"
. If you have an existing backend service that enables mTLS, you can use it and
skip to creating the Nginx container.
# mtls.conf
server {
listen 8443 ssl;
ssl_certificate conf.d/server.crt;
ssl_certificate_key conf.d/server.key;
ssl_trusted_certificate conf.d/ca.crt;
location / {
return 200 "mtls upstream";
}
}
Then run the container.
docker run --name mtls-upstream-server --detach --rm -v /path/to/mtls.conf:/etc/nginx/conf.d/httpbin.conf -v /path/to/server.crt:/etc/nginx/conf.d/server.crt -v /path/to/server.key:/etc/nginx/conf.d/server.key -v /path/to/ca.crt:/etc/nginx/conf.d/ca.crt --network <Apache APISIX Container Network ID> nginx:latest
You need to use the absolute paths for the mtls.conf
and the certificates.
We deploy this container with the same network as the Apache APISIX container. You can run the command below to get the network id of the Apache APISIX container.
docker inspect <Apache APISIX Container Name/ID> -f '{{ .NetworkSettings.Networks.bridge.NetworkID }}'
Create Service
We'll create a Service with the following details in this guide.
- The Service name is
upstream-mtls-app
. - The path prefix is
/v1
. - The HTTP Host is
umtls.httpbin.org
. - Set the upstream URL to the IP address of Nginx container (in our case, it's
http://172.17.0.4
). Please use the below command to get the correct IP address in your run. - We enable the upstream mutual TLS and fill in the SSL object ID.
You can run the command below to fetch the container address of the nginx services.
docker inspect mtls-upstream-server --format '{{ .NetworkSettings.Networks.bridge.IPAddress }}'
When you create the Service or when you add a new Upstream version:
- Click on the View Hide Advanced Upstream Options to unfold advanced upstream options.
- Select the Mutual TLS checkbox, and an API7 Cloud will show an input box to fill in the SSL object ID
Besides, we'll create a route inside the mtls-auth-app Service.
- The route name is
anything
. - The path is
/anything
(exact match). - Accepted HTTP method is
GET
.
If you don't know how to configure a service and route, please refer to the Getting Started guides first
Test mTLS
Let's send a request to the anything
route via curl.
curl http://127.0.0.1:9080/v1/anything -H 'Host: umtls.httpbin.org' -i
HTTP/1.1 200 OK
Content-Type: application/octet-stream
Content-Length: 13
Connection: keep-alive
Date: Thu, 09 Jun 2022 09:15:25 GMT
Server: APISIX/2.15.0
mtls upstream
Apache APISIX forwards the request to the backend Nginx service correctly.