BackendTLS
Originate a one-way TLS connection from the Gateway to a backend.
About one-way TLS
When you configure a TLS listener on your Gateway, the Gateway typically terminates incoming TLS traffic and forwards the unencrypted traffic to the backend service. However, you might have a service that only accepts TLS connections, or you want to forward traffic to a secured backend service that is external to the cluster.
You can use the Kubernetes Gateway API BackendTLSPolicy to configure TLS origination from the Gateway to a service in the cluster. This policy supports simple, one-way TLS use cases.
About this guide
In this guide, you learn how to use the BackendTLSPolicy resource to originate one-way TLS connections for the following services:
- In-cluster service: An NGINX server that is configured with a self-signed TLS certificate and deployed to the same cluster as the Gateway. You use a BackendTLSPolicy to originate TLS connections to NGINX.
- External service: The
httpbin.orghostname, which represents an external service that you want to originate a TLS connection to. You use a BackendTLSPolicy resource to originate TLS connections to that hostname.
Before you begin
Important: Install the experimental channel of the Kubernetes Gateway API to use this feature.
kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.5.0/experimental-install.yaml --server-sideUpgrade or install agentgateway with the
KGW_ENABLE_GATEWAY_API_EXPERIMENTAL_FEATURESenvironment variable. This setting defaults tofalseand must be explicitly enabled to use Gateway API experimental features.Example command:
helm upgrade -i agentgateway oci://cr.agentgateway.dev/charts/agentgateway \ --namespace agentgateway-system \ --version v1.0.0-alpha.3 \ --set controller.image.pullPolicy=Always \ --set controller.extraEnv.KGW_ENABLE_GATEWAY_API_EXPERIMENTAL_FEATURES=trueFollow the Get started guide to install the agentgateway control plane.
Follow the Sample app guide to deploy the httpbin sample app.
Get the external address of the gateway and save it in an environment variable.
export INGRESS_GW_ADDRESS=$(kubectl get svc -n agentgateway-system agentgateway-proxy -o jsonpath="{.status.loadBalancer.ingress[0]['hostname','ip']}") echo $INGRESS_GW_ADDRESSkubectl port-forward deployment/agentgateway-proxy -n agentgateway-system 8080:80
In-cluster service
Deploy an NGINX server in your cluster that is configured for TLS traffic. Then, instruct the gateway proxy to terminate TLS traffic at the gateway and originate a new TLS connection from the gateway proxy to the NGINX server.
Deploy the sample app
The following example uses an NGINX server with a self-signed TLS certificate.
Deploy the NGINX server with a self-signed TLS certificate.
kubectl apply -f https://raw.githubusercontent.com/solo-io/gloo-mesh-use-cases/refs/heads/main/agentgateway/nginx-tls.yamlVerify that the NGINX server is running.
kubectl get pods -l app.kubernetes.io/name=nginx -n agentgateway-systemExample output:
NAME READY STATUS RESTARTS AGE nginx 1/1 Running 0 9s
Originate TLS connections
Create a BackendTLSPolicy for the NGINX workload.
Create a Kubernetes ConfigMap that has the certificate the Gateway uses to verify the NGINX server. The NGINX deployment uses a self-signed certificate, so use that same certificate (the server cert) as the trust anchor in
ca.crt. This certificate must match the one in the nginx-tls.yaml deployment.kubectl apply -f- <<EOF apiVersion: v1 data: ca.crt: | -----BEGIN CERTIFICATE----- MIIDFTCCAf2gAwIBAgIUG9Mdv3nOQ2i7v68OgjArU4lhBikwDQYJKoZIhvcNAQEL BQAwFjEUMBIGA1UEAwwLZXhhbXBsZS5jb20wHhcNMjUwNzA3MTA0MDQwWhcNMjYw NzA3MTA0MDQwWjAWMRQwEgYDVQQDDAtleGFtcGxlLmNvbTCCASIwDQYJKoZIhvcN AQEBBQADggEPADCCAQoCggEBANueqwfAApjTfg+nxIoKVK4sK/YlNICvdoEq1UEL StE9wfTv0J27uNIsfpMqCx0Ni9Rjt1hzjunc8HUJDeobMNxGaZmryQofrdJWJ7Uu t5jeLW/w0MelPOfFLsDiM5REy4WuPm2X6v1Z1N3N5GR3UNDOtDtsbjS1momvooLO 9WxPIr2cfmPqr81fyyD2ReZsMC/8lVs0PkA9XBplMzpSU53DWl5/Nyh2d1W5ENK0 Zw1l5Ze4UGUeohQMa5cD5hmZcBjOeJF8MuSTi3167KSopoqfgHTvC5IsBeWXAyZF 81ihFYAq+SbhUZeUlsxc1wveuAdBRzafcYkK47gYmbq1K60CAwEAAaNbMFkwFgYD VR0RBA8wDYILZXhhbXBsZS5jb20wCwYDVR0PBAQDAgeAMBMGA1UdJQQMMAoGCCsG AQUFBwMBMB0GA1UdDgQWBBSoa1Zu2o+pQ6sq2HcOjAglZkp01zANBgkqhkiG9w0B AQsFAAOCAQEADZq1EMw/jMl0z2LpPh8cXbP09BnfXhoFbpL4cFrcBNEyig0oPO0j YN1e4bfURNduFVnC/FDnZhR3FlAt8a6ozJAwmJp+nQCYFoDQwotSx12y5Bc9IXwd BRZaLgHYy2NjGp2UgAya2z23BkUnwOJwJNMCzuGw3pOsmDQY0diR8ZWmEYYEPheW 6BVkrikzUNXv3tB8LmWzxV9V3eN71fnP5u39IM/UQsOZGRUow/8tvN2/d0W4dHky t/kdgLKhf4gU2wXq/WbeqxlDSpjo7q/emNl59v1FHeR3eITSSjESU+dQgRsYaGEn SWP+58ApfCcURLpMxUmxkO1ayfecNJbmSQ== -----END CERTIFICATE----- kind: ConfigMap metadata: name: ca namespace: agentgateway-system labels: app: nginx EOFCreate the TLS policy. Note that to use the BackendTLSPolicy, you must have the experimental channel of the Kubernetes Gateway API version 1.4 or later.
kubectl apply -f- <<EOF apiVersion: gateway.networking.k8s.io/v1 kind: BackendTLSPolicy metadata: name: tls-policy namespace: agentgateway-system labels: app: nginx spec: targetRefs: - group: "" kind: Service name: nginx validation: hostname: "example.com" caCertificateRefs: - group: "" kind: ConfigMap name: ca EOFReview the following table to understand this configuration. For more information, see the Kubernetes Gateway API docs.
Setting Description targetRefsThe service that you want the Gateway to originate a TLS connection to, such as the NGINX server.
Agentgateway proxies: Even if you use a Backend for selector-based destinations, you still need to target the backing Service and thesectionNameof the port that you want the policy to apply to.validation.hostnameThe hostname that matches the NGINX server certificate. validation.caCertificateRefsThe ConfigMap that has the certificate used to verify the backend. For the NGINX deployment in this guide, the server uses a self-signed certificate, so use that same certificate as the trust anchor. Create an HTTPRoute that routes traffic to the NGINX server on the
example.comhostname and HTTPS port 8443. Note that the parent Gateway is the samplehttpGateway resource that you created before you began.kubectl apply -f - <<EOF apiVersion: gateway.networking.k8s.io/v1beta1 kind: HTTPRoute metadata: name: nginx-route namespace: agentgateway-system labels: app: nginx spec: parentRefs: - name: agentgateway-proxy namespace: agentgateway-system hostnames: - "example.com" rules: - backendRefs: - name: nginx port: 8443 EOFSend a request to the NGINX server and verify that you get back a 200 HTTP response code.
curl -vi http://$INGRESS_GW_ADDRESS:80/ -H "host: example.com:80"curl -vi http://localhost:8080/ -H "host: example.com:8080"Example output:
* Host localhost:8080 was resolved. * IPv6: ::1 * IPv4: 127.0.0.1 * Trying [::1]:8080... * Connected to localhost (::1) port 8080 > GET / HTTP/1.1 > Host: example.com:8080 > User-Agent: curl/8.7.1 > Accept: */* > * Request completely sent off < HTTP/1.1 200 OK HTTP/1.1 200 OKThe HTTPRoute forwards the request to the NGINX server on port 8443, and the NGINX server accepts only TLS on that port. A 200 response means that the gateway proxy originated a TLS connection to the backend successfully. Without a valid BackendTLSPolicy and CA certificate, requests fail with
invalid peer certificate: UnknownIssuer.
External service
Set up an AgentgatewayBackend resource that represents your external service. Then, use a BackendTLSPolicy to instruct the gateway proxy to originate a TLS connection from the gateway proxy to the external service.
Create an AgentgatewayBackend resource that represents your external service. In this example, you use a static backend that routes traffic to the
httpbin.orgsite. Make sure to include the HTTPS port 443 so that traffic is routed to this port.kubectl apply -f- <<EOF apiVersion: agentgateway.dev/v1alpha1 kind: AgentgatewayBackend metadata: name: httpbin-org namespace: agentgateway-system spec: static: host: httpbin.org port: 443 EOFCreate a TLS policy that originates a TLS connection to the AgentgatewayBackend that you created in the previous step. To originate the TLS connection, you use known trusted CA certificates.
kubectl apply -f- <<EOF apiVersion: gateway.networking.k8s.io/v1 kind: BackendTLSPolicy metadata: name: httpbin-org namespace: agentgateway-system spec: targetRefs: - name: httpbin-org kind: AgentgatewayBackend group: agentgateway.dev validation: hostname: httpbin.org wellKnownCACertificates: System EOFCreate an HTTPRoute that rewrites traffic on the
httpbin-external.exampledomain to thehttpbin.orghostname and routes traffic to your Backend.kubectl apply -f- <<EOF apiVersion: gateway.networking.k8s.io/v1 kind: HTTPRoute metadata: name: httpbin-org namespace: agentgateway-system spec: parentRefs: - name: agentgateway-proxy namespace: agentgateway-system hostnames: - "httpbin-external.example" rules: - matches: - path: type: PathPrefix value: /anything backendRefs: - name: httpbin-org kind: AgentgatewayBackend group: agentgateway.dev filters: - type: URLRewrite urlRewrite: hostname: httpbin.org EOFSend a request to the
httpbin-external.exampledomain. Verify that the host is rewritten tohttps://httpbin.org/anythingand that you get back a 200 HTTP response code.curl -vi http://$INGRESS_GW_ADDRESS:80/anything -H "host: httpbin-external.example"curl -vi http://localhost:8080/anything -H "host: httpbin-external.example"Example output:
< HTTP/1.1 200 OK HTTP/1.1 200 OK ... { "args": {}, "data": "", "files": {}, "form": {}, "headers": { "Accept": "*/*", "Host": "httpbin.org", "User-Agent": "curl/8.7.1", "X-Amzn-Trace-Id": "Root=1-6881126a-03bfc90450805b9703e66e78", "X-Envoy-Expected-Rq-Timeout-Ms": "15000", "X-Envoy-External-Address": "10.0.X.XXX" }, "json": null, "method": "GET", "origin": "10.0.X.XXX, 3.XXX.XXX.XXX", "url": "https://httpbin.org/anything" }
Cleanup
You can remove the resources that you created in this guide.In-cluster service
kubectl delete -f https://raw.githubusercontent.com/solo-io/gloo-mesh-use-cases/refs/heads/main/agentgateway/nginx-tls.yaml
kubectl delete backendtlspolicy,configmap,httproute -A -l app=nginxExternal service
Delete the resources that you created.
kubectl delete httproute httpbin-org -n agentgateway-system
kubectl delete backendtlspolicy httpbin-org -n agentgateway-system
kubectl delete AgentgatewayBackend httpbin-org -n agentgateway-system