Skip to content
You are viewing the documentation for Solo Enterprise for Istio, formerly known as Gloo Mesh (OSS APIs).

L7 waypoint egress

Page as Markdown

Deploy a waypoint proxy as an egress gateway and enforce L7 policies such as HTTP authorization, header manipulation, and TLS origination before traffic leaves your ambient mesh.

Set up L7 waypoint egress for your ambient mesh. This approach routes outbound traffic through an Envoy-based waypoint proxy, enabling HTTP-level authorization, header manipulation, rate limiting, and TLS origination. For a comparison of egress approaches, see the egress overview.

Before you begin

  1. Ensure that DNS capture and IP autoallocation are enabled in your ambient mesh, which are required for ServiceEntry resources to receive stable virtual IPs. If you followed the quickstart guide, these are already configured. For Helm installations, add the following flags to your Helm install or upgrade command for the istiod Helm chart.

    --set cni.ambient.dnsCapture=true --set pilot.env.PILOT_ENABLE_IP_AUTOALLOCATE=true
  2. Add services to the ambient mesh. The steps in this guide use the Bookinfo sample app services for example curl commands.

Step 1: Create an egress gateway

  1. Create the istio-egress namespace and add the following labels:

    • istio.io/dataplane-mode: ambient to add all pods in that namespace to the ambient mesh.
    • istio.io/use-waypoint: egress-waypoint to redirect all traffic through the egress waypoint proxy that you create in the next step.
    kubectl create namespace istio-egress
    kubectl label ns istio-egress istio.io/dataplane-mode=ambient
    kubectl label ns istio-egress istio.io/use-waypoint=egress-waypoint
  2. Create a waypoint proxy that serves as the egress gateway. Use the istio-waypoint GatewayClass so that Istio configures and manages the gateway. The Gateway serves routes from all namespaces.

    kubectl apply -f - <<EOF
    apiVersion: gateway.networking.k8s.io/v1
    kind: Gateway
    metadata:
      name: egress-waypoint
      namespace: istio-egress
    spec:
      gatewayClassName: istio-waypoint
      listeners:
      - name: mesh
        port: 15008
        protocol: HBONE
        allowedRoutes:
          namespaces:
            from: All
    EOF
  3. Wait for the Gateway to be fully deployed.

    kubectl -n istio-egress rollout status deployment/egress-waypoint

    Example output:

    deployment "egress-waypoint" successfully rolled out
  4. Verify that the egress gateway pod is running.

    kubectl get pods -n istio-egress

    Example output:

    NAME                               READY   STATUS    RESTARTS   AGE
    egress-waypoint-5cb48fc696-mq99j   1/1     Running   0          87m

Step 2: Route traffic through the egress gateway

Create an external service and configure your ambient mesh to route all traffic to that external service through the egress gateway that you set up earlier.

  1. Create a ServiceEntry that represents the external service httpbin.org. Label it with istio.io/use-waypoint to route all traffic for that host through the egress gateway.

    kubectl apply -f - <<EOF
    apiVersion: networking.istio.io/v1
    kind: ServiceEntry
    metadata:
      labels:
        istio.io/use-waypoint: egress-waypoint
      name: httpbin.org
      namespace: istio-egress
    spec:
      hosts:
      - httpbin.org
      ports:
      - name: http
        number: 80
        protocol: HTTP
      resolution: DNS
    EOF

    Tip

    Wildcard hostnames are not supported in ServiceEntry resources used with egress waypoints.

    To create the ServiceEntry in a different namespace, label it for cross-namespace use.

  2. Verify that the ServiceEntry is attached to the waypoint by checking its status.

    kubectl get serviceentry httpbin.org -n istio-egress -o yaml

    Example output:

    ...
    status:
      addresses:
      - host: httpbin.org
        value: 240.240.0.2
      - host: httpbin.org
        value: 2001:2::2
      conditions:
      - lastTransitionTime: "2025-01-31T19:59:45.435933727Z"
        message: Successfully attached to waypoint egress/egress-waypoint
        reason: WaypointAccepted
        status: "True"
        type: istio.io/WaypointBound
  3. Send a request from the productpage to the external service. Verify that the response contains the server: istio-envoy and x-envoy-upstream-service-time headers. The presence of these headers verifies that traffic is routed through the egress gateway.

    kubectl -n bookinfo exec deploy/productpage-v1 -c curl -- curl -vik "httpbin.org/get"

    Example output:

    ...
    HTTP/1.1 200 OK
    date: Fri, 31 Jan 2025 20:00:01 GMT
    content-type: application/json
    content-length: 257
    server: istio-envoy
    access-control-allow-origin: *
    access-control-allow-credentials: true
    x-envoy-upstream-service-time: 118
    
    {
      "args": {}, 
      "headers": {
        "Accept": "*/*", 
        "Host": "httpbin.org", 
       "User-Agent": "curl/7.83.1-DEV", 
        "X-Amzn-Trace-Id": "Root=1-679d2bc1-4cfac8b64db7791a6c8fc55a"
      }, 
      "origin": "18.XXX.XX.XX", 
      "url": "http://httpbin.org/get"
    }
  4. Review the ztunnel logs to confirm the request transited the egress gateway.

    1. Get the node that the egress gateway pod is deployed to. In the following example, the egress gateway is deployed on the ip-10-0-6-27.us-east-2.compute.internal node.

      kubectl get pods -n istio-egress -o wide

      Example output:

      NAME                               READY   STATUS    RESTARTS   AGE   IP           NODE                                      NOMINATED NODE   READINESS GATES
      egress-waypoint-5cb48fc696-mq99j   1/1     Running   0          95m   10.0.2.127   ip-10-0-6-27.us-east-2.compute.internal   <none>           <none>
    2. Get the ztunnel instance that is deployed on the same node as the egress gateway.

      kubectl get pods -n istio-system -o wide | grep ztunnel
    3. Review the logs of the ztunnel instance and verify that you can see a log entry for the request from the product page to the egress gateway. The presence of SPIFFE IDs for the source and destination confirms that traffic is secured via mutual TLS.

      kubectl logs <ztunnel-instance> -n istio-system

      Example output:

      2025-02-20T16:52:48.094361Z	info	http access	request complete	
      src.addr=10.0.74.45:58668 src.workload="productpage-v1-7654b4b6d5-7c4l5" 
      src.namespace="bookinfo" src.identity="spiffe://cluster1/ns/bookinfo/sa/bookinfo-productpage" 
      dst.addr=10.0.77.91:15008 dst.hbone_addr=240.240.0.4:80 dst.service="httpbin.org" 
      dst.workload="waypoint-865f5c9674-wfqwl" dst.namespace="egress" 
      dst.identity="spiffe://cluster1/ns/istio-egress/sa/egress-waypoint" 
      dst.cluster="cluster1" direction="outbound" method=GET path="/get"
      protocol=HTTP1 response_code=200 host="httpbin.org" user_agent="curl/7.83.1-dev" duration="13ms"
      
      2025-02-20T16:52:48.095517Z	info	access	connection complete	src.addr=10.0.74.45:58668 
      src.workload="productpage-v1-7654b4b6d5-7c4l5" src.namespace="bookinfo" src.identity="spiffe://cluster1/ns/bookinfo/sa/bookinfo-productpage" 
      dst.addr=10.0.77.91:15008 dst.hbone_addr=240.240.0.4:80 dst.service="httpbin.org" 
      dst.workload="egress-waypoint-865f5c9674-wfqwl" dst.namespace="istio-egress" 
      dst.identity="spiffe://cluster1/ns/istio-egress/sa/egress-waypoint" 
      dst.cluster="cluster1" direction="outbound" 
      bytes_sent=82 bytes_recv=493 duration="22ms"

Step 3: Apply an egress policy

Now that all traffic to the httpbin.org service is routed through the egress gateway, you can apply additional routing and security policies to it.

AuthorizationPolicy

Use an Istio AuthorizationPolicy to restrict access to the external service for specific HTTP methods.

  1. Create an AuthorizationPolicy that allows only GET requests to the httpbin.org service. Apply this policy to the egress gateway by using the targetRefs section.

    kubectl apply -f - <<EOF
    apiVersion: security.istio.io/v1
    kind: AuthorizationPolicy
    metadata:
      name: httpbin
      namespace: istio-egress
    spec:
      targetRefs:
      - kind: Gateway
        name: egress-waypoint
        group: gateway.networking.k8s.io
      action: ALLOW
      rules:
      - to:
        - operation:
            hosts: ["httpbin.org"]
            methods: ["GET"]
            paths: ["/get"]
    EOF
  2. Send a POST request to httpbin.org and verify that this request is denied with a 403 HTTP response code.

    kubectl -n bookinfo exec deploy/productpage-v1 -c curl -- curl -vik "httpbin.org/post"

    Example output:

    ...
    HTTP/1.1 403 Forbidden
    content-length: 19
    content-type: text/plain
    date: Thu, 20 Feb 2025 17:04:05 GMT
    server: istio-envoy
    
    RBAC: access denied
  3. Repeat the request. This time, use the GET HTTP method that is allowed by the AuthorizationPolicy. Verify that the request now succeeds.

    kubectl -n bookinfo exec deploy/productpage-v1 -c curl -- curl -vik "httpbin.org/get"

    Example output:

    < HTTP/1.1 200 OK
    < date: Thu, 20 Feb 2025 17:05:10 GMT
    < content-type: application/json
    < content-length: 257
    < server: istio-envoy
    < access-control-allow-origin: *
    < access-control-allow-credentials: true
    < x-envoy-upstream-service-time: 1070
    
    {
      "args": {}, 
      "headers": {
        "Accept": "*/*", 
        "Host": "httpbin.org", 
       "User-Agent": "curl/7.83.1-DEV", 
        "X-Amzn-Trace-Id": "Root=1-679d2bc1-4cfac8b64db7791a6c8fc55a"
      }, 
      "origin": "18.XXX.XX.XX", 
      "url": "http://httpbin.org/get"
    }

Header manipulation

Add headers to a request centrally at the egress gateway by using an Istio VirtualService.

  1. Create a VirtualService that adds the my-added-header: added-value header to all requests to httpbin.org.

    kubectl apply -f - <<EOF
    apiVersion: networking.istio.io/v1
    kind: VirtualService
    metadata:
      name: httpbin
      namespace: istio-egress
    spec:
      hosts:
      - httpbin.org
      http:
      - route:
        - destination:
            host: httpbin.org
        headers:
          request:
            add:
              my-added-header: added-value
    EOF
  2. Send a request to the httpbin.org external service and verify that you see the added request header.

    kubectl -n bookinfo exec deploy/productpage-v1 -c curl -- curl -vik "httpbin.org/get"

    Example output:

    < HTTP/1.1 200 OK
    ...
    content-type: application/json
    content-length: 296
    server: istio-envoy
    access-control-allow-origin: *
    access-control-allow-credentials: true
    x-envoy-upstream-service-time: 99
    
    {
     "args": {}, 
      "headers": {
        "Accept": "*/*", 
        "Host": "httpbin.org", 
        "My-Added-Header": "added-value", 
        "User-Agent": "curl/7.83.1-DEV", 
        "X-Amzn-Trace-Id": "Root=1-679d3bc5-1dd72be652986bb53d92b244"
      }, 
      "origin": "18.XXX.XX.XX", 
      "url": "http://httpbin.org/get"
    }

TLS origination

By default, all traffic within the ambient mesh is secured via mutual TLS. However, when routing traffic through an egress gateway, the egress gateway terminates the TLS connection and forwards the unencrypted request to the external service.

With TLS origination, you instruct the egress gateway to re-encrypt the request before it is forwarded to the external service.

  1. Add targetPort: 443 to the ServiceEntry to instruct the egress gateway to use port 443 when routing traffic to httpbin.org.

    kubectl apply -f - <<EOF
    apiVersion: networking.istio.io/v1
    kind: ServiceEntry
    metadata:
      name: httpbin.org
      namespace: istio-egress
    spec:
      hosts:
      - httpbin.org
      ports:
      - number: 80
        name: http
        protocol: HTTP
        targetPort: 443
      resolution: DNS
    EOF
  2. Create a DestinationRule to instruct the egress gateway to originate a TLS connection when routing traffic to httpbin.org.

    kubectl apply -f- <<EOF
    apiVersion: networking.istio.io/v1
    kind: DestinationRule
    metadata:
      name: httpbin.org-tls
      namespace: istio-egress
    spec:
      host: httpbin.org
      trafficPolicy:
        tls:
          mode: SIMPLE
    EOF
  3. Send a request to the httpbin.org external service and verify that traffic is sent to https://httpbin.org/get.

    kubectl -n bookinfo exec deploy/productpage-v1 -c curl -- curl -vik "httpbin.org/get"

    Example output:

    < HTTP/1.1 200 OK
    ...
    content-type: application/json
    content-length: 297
    server: istio-envoy
    access-control-allow-origin: *
    access-control-allow-credentials: true
    x-envoy-upstream-service-time: 303
    
    {
      "args": {}, 
      "headers": {
        "Accept": "*/*", 
        "Host": "httpbin.org", 
        "My-Added-Header": "added-value", 
        "User-Agent": "curl/7.83.1-DEV", 
        "X-Amzn-Trace-Id": "Root=1-679d4675-146cc1027fba135708ae3fef"
      }, 
      "origin": "18.XXX.XX.XX", 
      "url": "https://httpbin.org/get"
    }

Cleanup

You can optionally remove the resources that you created in this guide.

kubectl delete authorizationpolicy httpbin -n istio-egress
kubectl delete virtualservice httpbin -n istio-egress
kubectl delete serviceentry httpbin.org -n istio-egress
kubectl delete destinationrule httpbin.org-tls -n istio-egress
kubectl delete gateway egress-waypoint -n istio-egress
kubectl delete namespace istio-egress