Client TLS
Enable TLS origination on your ingress gateway.
Configure your ingress gateway to perform TLS origination for traffic that is sent to services in or outside your cluster. When TLS origination is enabled, the ingress gateway encrypts incoming HTTP or HTTPS requests by using TLS certificates before forwarding the request to an HTTPS server or service in the cluster. Therefore, TLS origination is the opposite of TLS termination where incoming HTTPS requests are decrypted by the ingress gateway before they are forwarded to a service in the cluster.
For more information, see the following resources:
If you import or export resources across workspaces, your policies might not apply. For more information, see Import and export policies.
Before you begin
To follow the example that is outlined on this page, Gloo Gateway must be set up in a single cluster as described in the getting started guide. You do not need to deploy sample apps as you create an NGINX server and configure it for HTTPS traffic as part of this example.
Deploy an NGINX server that is configured for HTTPS traffic
The following steps show how to deploy a sample NGINX server and configure the server for HTTPS traffic. You use this server to try out the client TLS policy later.
Create a namespaces for the NGINX server that you deploy as part of this example.
kubectl create namespace nginx
Create a root certificate for the
example.com
domain. You use this certificate to sign the certificate for your NGINX service later.openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=example Inc./CN=example.com' -keyout example.com.key -out example.com.crt
Create a server certificate and private key for the
my-nginx.nginx.svc.cluster.local
service.openssl req -out my-nginx.nginx.svc.cluster.local.csr -newkey rsa:2048 -nodes -keyout my-nginx.nginx.svc.cluster.local.key -subj "/CN=my-nginx.nginx.svc.cluster.local/O=some organization" openssl x509 -req -sha256 -days 365 -CA example.com.crt -CAkey example.com.key -set_serial 0 -in my-nginx.nginx.svc.cluster.local.csr -out my-nginx.nginx.svc.cluster.local.crt
Generate the client certificate and private key.
openssl req -out client.example.com.csr -newkey rsa:2048 -nodes -keyout client.example.com.key -subj "/CN=client.example.com/O=client organization" openssl x509 -req -sha256 -days 365 -CA example.com.crt -CAkey example.com.key -set_serial 1 -in client.example.com.csr -out client.example.com.crt
Create a secret that stores the server and CA certificate that you created.
kubectl create -n nginx secret tls nginx-server-certs --key my-nginx.nginx.svc.cluster.local.key --cert my-nginx.nginx.svc.cluster.local.crt kubectl create -n nginx secret generic nginx-ca-certs --from-file=example.com.crt
Prepare your NGINX configuration. The following example configures NGINX for HTTPS traffic with the server and client certificates that you created earlier.
cat <<EOF > ./nginx.conf events { } http { log_format main '$remote_addr - $remote_user [$time_local] $status ' '"$request" $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; error_log /var/log/nginx/error.log; server { listen 443 ssl; root /usr/share/nginx/html; index index.html; server_name my-nginx.nginx.svc.cluster.local; ssl_certificate /etc/nginx-server-certs/tls.crt; ssl_certificate_key /etc/nginx-server-certs/tls.key; ssl_client_certificate /etc/nginx-ca-certs/example.com.crt; ssl_verify_client on; } } EOF
Store the NGINX configuration in a configmap.
kubectl create configmap nginx-configmap -n nginx --from-file=nginx.conf=./nginx.conf
Deploy the NGINX server.
kubectl apply -f https://raw.githubusercontent.com/solo-io/gloo-mesh-use-cases/main/policy-demo/nginx.yaml
Store the client certificate and key in another secret that the ingress gateway later uses to authenticate with the NGINX server.
kubectl create secret -n gloo-mesh-gateways generic client-credential --from-file=tls.key=client.example.com.key \ --from-file=tls.crt=client.example.com.crt --from-file=ca.crt=example.com.crt
Configure and verify client TLS policies
Now that you configured your NGINX server for HTTPS traffic, you must enable TLS origination for the ingress gateway.
Configure an HTTP listener on your ingress gateway. This listener enables the ingress gateway to accept incoming HTTP requests.
kubectl apply -f- <<EOF apiVersion: networking.gloo.solo.io/v2 kind: VirtualGateway metadata: name: mtls-gateway namespace: gloo-mesh-gateways spec: listeners: - port: number: 80 http: {} workloads: - selector: labels: istio: ingressgateway EOF
Create a route table that routes incoming HTTP traffic to the NGINX server that is configured for HTTPS traffic.
kubectl apply -f- <<EOF apiVersion: networking.gloo.solo.io/v2 kind: RouteTable metadata: name: mtls-routetable namespace: gloo-mesh-gateways spec: virtualGateways: - name: mtls-gateway namespace: gloo-mesh-gateways hosts: - '*' http: - matchers: - uri: prefix: / forwardTo: destinations: - ref: name: my-nginx namespace: nginx cluster: $CLUSTER_NAME port: number: 443 EOF
Verify that your NGINX server does not accept incoming HTTP requests.
In a new terminal, port-forward the ingress gateway on your local machine.
kubectl port-forward deploy/ingressgateway -n gloo-mesh-gateways 8080
Send an HTTP request to your local host. Because the ingress gateway is not yet configured for TLS origination, the HTTP request is forwarded to the NGINX server without encryption. However, the NGINX server is configured to only accept HTTPS traffic so you see an error stating that you tried to send plain HTTP traffic to an HTTPS port.
curl localhost:8080
Example output:
<html> <head><title>400 The plain HTTP request was sent to HTTPS port</title></head> <body> <center><h1>400 Bad Request</h1></center> <center>The plain HTTP request was sent to HTTPS port</center> <hr><center>nginx/1.23.3</center> </body> </html>
Create the client TLS policy. This policy configures the ingress gateway to encrypt all incoming HTTP traffic for the NGINX deployment by using the client certificates that are stored in the secret.
kubectl apply -f- <<EOF apiVersion: security.policy.gloo.solo.io/v2 kind: ClientTLSPolicy metadata: name: mtls namespace: gloo-mesh-gateways spec: applyToDestinations: - selector: namespace: nginx labels: run: my-nginx mutual: config: credentialName: client-credential EOF
Send another HTTP request to your local host. Because the ingress gateway is now configured to encrypt HTTP requests before forwarding them to the NGINX server, the request now succeeds.
curl localhost:8080
Example output:
<!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> <style> html { color-scheme: light dark; } body { width: 35em; margin: 0 auto; font-family: Tahoma, Verdana, Arial, sans-serif; } </style> </head> <body> <h1>Welcome to nginx!</h1> <p>If you see this page, the nginx web server is successfully installed and working. Further configuration is required.</p> <p>For online documentation and support please refer to <a href="http://nginx.org/">nginx.org</a>.<br/> Commercial support is available at <a href="http://nginx.com/">nginx.com</a>.</p> <p><em>Thank you for using nginx.</em></p> </body> </html>
Cleanup
You can optionally remove the resources that you set up as part of this guide.
kubectl delete namespace nginx
kubectl delete virtualgateway mtls-gateway -n gloo-mesh-gateways
kubectl delete routetable mtls-routetable -n gloo-mesh-gateways
kubectl delete clienttlspolicy mtls -n gloo-mesh-gateways