Configure mTLS between API7 Enterprise and Upstream
Mutual TLS (mTLS) is a two-way TLS where the client and the server authenticate each other. It is typically implemented in high-security environments to prevent unauthorized access and harden security.
This guide will walk you through how to configure mTLS between API7 Gateway and an upstream service, using NGINX as a sample upstream service.
Prerequisites
- Install API7 Enterprise.
- Create a token on API7 Enterprise.
Generate Certificates and Keys
-
Generate the certificate authority (CA) key and certificate.
openssl genrsa -out ca.key 2048
openssl req -x509 -new -nodes -key ca.key -sha256 -days 36500 -out ca.crt \
-subj "/CN=ROOTCA" -
Generate the server key and certificate with the common name
test.com
for the upstream service (NGINX), and sign with the CA certificate.openssl genrsa -out server.key 2048 && \
openssl req -new -key server.key -out server.csr -subj "/CN=test.com" && \
cat > server.ext << EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = test.com
EOF
openssl x509 -req -in server.csr -CA ca.crt -CAkey ca.key \
-CAcreateserial -out server.crt -days 36500 \
-sha256 -extfile server.ext -
Generate the key and certificate with the common name
client
for API7 Gateway (as the client), and sign with the CA certificate.openssl genrsa -out client.key 2048 && \
openssl req -new -key client.key -out client.csr -subj "/CN=client" && \
cat > client.ext << EOF
authorityKeyIdentifier=keyid,issuer
basicConstraints=CA:FALSE
keyUsage = digitalSignature, nonRepudiation, keyEncipherment, dataEncipherment
extendedKeyUsage = clientAuth
EOF
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days 36500 -sha256 -extfile client.ext -
After generating certificates and keys, check your directory to locate
client.crt
,client.key
, andca.crt
.
Configure Upstream Service
- Docker
- Kubernetes
Start an NGINX server as a sample upstream service:
docker run -d \
--name quickstart-nginx \
--network=host \
nginx
Copy CA certificate, server certificate public and private keys into NGINX:
docker cp ca.crt quickstart-nginx:/var/ca.crt
docker cp server.crt quickstart-nginx:/var/server.crt
docker cp server.key quickstart-nginx:/var/server.key
Configure an HTTPs server listening on /hello
and port 8443
in NGINX configuration file:
http {
# ...
server {
listen 8443 ssl;
server_name test.com;
ssl_certificate /var/server.crt;
ssl_certificate_key /var/server.key;
ssl_client_certificate /var/ca.crt;
ssl_verify_client on;
location /hello {
return 200 "Hello API7!";
}
}
}
❶ server_name
: set to test.com
to be consistent with the server certificate CN value.
❷ ssl_certificate
: configure the path to the server certificate public key server.crt
.
❸ ssl_certificate_key
: configure the path to the server certificate private key server.key
.
❹ ssl_client_certificate
: configure the path to the CA certificate public key ca.crt
.
❺ ssl_verify_client
: set to on
to verify the client certificate.
Reload the NGINX server to apply the configuration changes:
docker exec quickstart-nginx nginx -s reload
Create a Kubernetes secret for the NGINX sample upstream service:
kubectl create secret generic nginx-certs \
--from-file=server.crt=server.crt \
--from-file=server.key=server.key \
--from-file=ca.crt=ca.crt \
--namespace=api7
Create a ConfigMap for the NGINX sample upstream service:
apiVersion: v1
kind: ConfigMap
metadata:
name: nginx-config
namespace: api7
data:
default.conf: |
server {
listen 8443 ssl;
server_name test.com;
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
ssl_client_certificate /etc/nginx/ssl/ca.crt;
ssl_verify_client on;
location /hello {
return 200 "Hello API7!";
}
}
❶ server_name
: set to test.com
to be consistent with the server certificate CN value.
❷ ssl_certificate
: configure the path to the server certificate public key server.crt
.
❸ ssl_certificate_key
: configure the path to the server certificate private key server.key
.
❹ ssl_client_certificate
: configure the path to the CA certificate public key ca.crt
.
❺ ssl_verify_client
: set to on
to verify the client certificate.
Create a Kubernetes manifest file for the NGINX sample upstream service deployment and service:
apiVersion: v1
kind: Service
metadata:
name: quickstart-nginx
namespace: api7
spec:
type: NodePort
selector:
app: quickstart-nginx
ports:
- name: https
port: 8443
targetPort: 8443
---
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: api7
name: quickstart-nginx
spec:
replicas: 1
selector:
matchLabels:
app: quickstart-nginx
template:
metadata:
labels:
app: quickstart-nginx
spec:
containers:
- name: nginx
image: nginx
ports:
- containerPort: 8443
volumeMounts:
- name: config
mountPath: /etc/nginx/conf.d
- name: certs
mountPath: /etc/nginx/ssl
volumes:
- name: config
configMap:
name: nginx-config
- name: certs
secret:
secretName: nginx-certs
Apply the configuration to your cluster:
kubectl apply -f nginx-cm.yaml -f nginx.yaml
Port forward the NGINX service port to your local machine's port for verification:
kubectl port-forward service/quickstart-nginx 8443:8443 &
To verify that the NGINX instance is properly configured, send a request to the route with client certificate and key:
curl -ik "https://127.0.0.1:8443/hello" --cert client.crt --key client.key
You should receive an HTTP/1.1 200 OK
response.
Configure mTLS for API7 Enterprise
Create a Route to the NGINX Server
- Dashboard
- Ingress Controller
- Select Published Services under your gateway group from the side navigation bar and then click Add Service.
- Select Add Manually.
- From the dialog box, do the following:
- In the Name field of Service Basics, enter
mtls-nginx
. - In the Service Type field, choose
HTTP (Layer 7 Proxy)
. - In the Name field of Upstream Basics, enter
default
. - In the How to find the upstream field, choose
Use Nodes
. - Click Add Node.
- From the Add Node dialog box, do the following:
- In the Host field, enter the IP address of your API7 dashboard.
- In the Port field, enter
8443
. - In the Weight field, enter
100
.
- In the Upstream Scheme field, choose
HTTPs
. Leave the Client Certificate and CA Certificates fields for future steps. - Open the Add First Route switch, then create a route
/hello
with theGET
method. - Click Add.
- In the Name field of Service Basics, enter
- Gateway API
- APISIX CRD
Gateway API currently does not support the configuration of upstream mTLS.
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
namespace: api7
name: mtls-nginx
spec:
ingressClassName: apisix
http:
- name: mtls-nginx
match:
paths:
- /hello
methods:
- GET
backends:
- serviceName: quickstart-nginx
servicePort: 8443
Apply the configuration to your cluster:
kubectl apply -f mtls-route.yaml
Configure Certificates
If you would like to reference SSL certificate from secret providers, see Reference Secrets in HashiCorp Vault, Reference Secrets in AWS Secrets Manager, or Reference Secrets in Kubernetes Secret.
- Dashboard
- Ingress Controller
Upload Certificates
- Select Certificates of your gateway group from the side navigation bar, enter the SSL Certificates tab.
- Click Add SSL Certificate.
- From the dialog box, do the following:
- In the Name field, enter
Upstream SSL Certificate
. - In the Certificate field, upload the
client.crt
file. - In the Private Key field, upload the
client.key
file. - Click Add.
- Select Certificates of your gateway group from the side navigation bar, then click CA Certificates tab.
- Click Add CA Certificate.
- From the dialog box, do the following:
- In the Name field, enter
Upstream CA Certificate
. - In the Certificate field, upload the
ca.crt
file. - Click Add.
Configure Certificates
- Select Published Services of your gateway group from the side navigation bar, enter the
mtls-nginx
service you created before. - Select the Upstreams from the side navigation bar.
- Click the edit button of the Connection Configuration fields.
- From the dialog box, do the following:
- In the Client Certificate field, select
Upstream SSL Certificate
. - In the Ca Certificates field, select
Upstream CA Certificate
. - Click Save.
- Gateway API
- APISIX CRD
Gateway API currently does not support the configuration of upstream mTLS.
Create a Kubernetes secret for API7:
kubectl create secret tls test-mtls-secret \
--cert=client.crt \
--key=client.key \
--namespace=api7
Create a Kubernetes manifest file to configure the upstream of the previously created route:
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
namespace: api7
name: quickstart-nginx # should match the service name
spec:
ingressClassName: apisix
scheme: https
tlsSecret:
namespace: api7
name: test-mtls-secret
Apply the configuration to your cluster:
kubectl apply -f mtls-upstream.yaml
Verify mTLS between API7 Enterprise and Upstream Service
Send a request to the route:
curl -ik "http://127.0.0.1:9080/hello"
You should receive an HTTP/1.1 200 OK
response, verifying that the mTLS between API7 Enterprise and upstream has been set up successfully.
Additional Resources
- Key Concepts