Egress gateway
Use agentgateway as an egress waypoint to enforce Layer 7 policies on traffic leaving your ambient mesh.
You can deploy Solo Enterprise for agentgateway as an egress waypoint to apply L7 policies to traffic leaving your ambient mesh. This guide covers cases in which your application manages its own credentials and you want to control which service accounts are allowed to make outbound calls to an external API. The agentgateway waypoint enforces allow/deny policy on the traffic, but does not inject credentials or perform provider-aware routing.
If you want agentgateway to manage API credentials and perform provider-aware routing to LLM backends (the east-west equivalent of the standalone Solo Enterprise for agentgateway LLM provider guides), see the AI provider backends with agentgateway waypoint guide instead.
The pattern mirrors the community egress with a waypoint proxy method, with two differences:
- Uses the
enterprise-agentgateway-waypointGatewayClass instead ofistio-waypoint - Always uses
istio.io/waypoint-for: allbecause ServiceEntries are not Kubernetes-native services
Before you begin
Install the Solo Enterprise for agentgateway control plane and GatewayClass by following the Install guide. Complete the Install Solo Enterprise for agentgateway section only. You do not need to complete the Deploy the waypoint section, because this guide creates a separate egress waypoint Gateway.
Deploy an egress waypoint
Set the workload namespace where your workloads run. All resources in this guide are created in this namespace.
export NAMESPACE=<ns>Create a Gateway resource for the egress waypoint. Because egress targets are represented as ServiceEntries rather than Kubernetes Services, you must use
istio.io/waypoint-for: all.kubectl apply -f - <<EOF apiVersion: gateway.networking.k8s.io/v1 kind: Gateway metadata: name: egress-waypoint namespace: ${NAMESPACE} labels: istio.io/waypoint-for: all spec: gatewayClassName: enterprise-agentgateway-waypoint listeners: - name: mesh port: 15008 protocol: HBONE EOFVerify that the egress waypoint pod is running and the Gateway is programmed.
kubectl get pods -n ${NAMESPACE} -l gateway.networking.k8s.io/gateway-name=egress-waypoint kubectl get gateway egress-waypoint -n ${NAMESPACE}Example output:
NAME READY STATUS RESTARTS AGE egress-waypoint-757fdbb564-44nz2 1/1 Running 0 11s NAME CLASS ADDRESS PROGRAMMED AGE egress-waypoint enterprise-agentgateway-waypoint 172.20.235.25 True 23s
Register the external AI API
Create a ServiceEntry for the external AI API, such as the OpenAI API.
kubectl apply -f - <<EOF apiVersion: networking.istio.io/v1 kind: ServiceEntry metadata: name: openai-api namespace: ${NAMESPACE} spec: hosts: - api.openai.com ports: - number: 443 name: https protocol: HTTPS resolution: DNS location: MESH_EXTERNAL EOFLabel the ServiceEntry to route traffic through the egress waypoint.
kubectl label serviceentry openai-api \ -n ${NAMESPACE} \ istio.io/use-waypoint=egress-waypoint
Restrict which agents can call the API
Apply an EnterpriseAgentgatewayPolicy to allow only specific service accounts to make calls to the external AI API. The policy denies all traffic by default, so any workload not listed in matchExpressions receives a 403 directly from the waypoint — before the request reaches OpenAI. This 403 (rather than a 401 from the upstream API) confirms the waypoint is intercepting and enforcing policy on the traffic.
Set the service account of your agent workload.
export AGENT_SERVICE_ACCOUNT=<your_agent_sa>Apply an EnterpriseAgentgatewayPolicy. The following example allows POST requests from a single agent service account.
kubectl apply -f - <<EOF apiVersion: enterpriseagentgateway.solo.io/v1alpha1 kind: EnterpriseAgentgatewayPolicy metadata: name: openai-allow-agent-only namespace: ${NAMESPACE} spec: targetRefs: - kind: ServiceEntry group: "networking.istio.io" name: openai-api traffic: authorization: action: Allow policy: matchExpressions: - 'source.identity.namespace == "${NAMESPACE}" && source.identity.serviceAccount == "${AGENT_SERVICE_ACCOUNT}" && request.method == "POST"' EOFTo allow multiple agents, add an expression for each service account.
matchExpressions: - 'source.identity.namespace == "${NAMESPACE}" && source.identity.serviceAccount == "agent-a" && request.method == "POST"' - 'source.identity.namespace == "${NAMESPACE}" && source.identity.serviceAccount == "agent-b" && request.method == "POST"'Deploy an unauthorized test pod that runs under the default service account.
kubectl run curl-unauth -n ${NAMESPACE} --image=curlimages/curl --restart=Never -- sleep 3600Deploy an authorized test pod that runs under the agent service account.
kubectl run curl-auth -n ${NAMESPACE} --image=curlimages/curl \ --restart=Never --overrides="{\"spec\":{\"serviceAccountName\":\"${AGENT_SERVICE_ACCOUNT}\"}}" \ -- sleep 3600Verify that the waypoint enforces the policy by sending a request from the unauthorized pod. The waypoint returns a
403before the request reaches OpenAI.kubectl exec -n ${NAMESPACE} curl-unauth -- \ curl -s -o /dev/null -w "%{http_code}" https://api.openai.com/v1/modelsConfirm that the authorized pod can reach OpenAI.
kubectl exec -n ${NAMESPACE} curl-auth -- \ curl -s -o /dev/null -w "%{http_code}" https://api.openai.com/v1/modelsVerify that the in-mesh segment of the traffic (from your workload to the egress waypoint) uses mTLS. For more information about this command, see the CLI reference.
istioctl ztunnel-config connections --namespace ${NAMESPACE}The
PROTOCOLcolumn showsHBONEfor inbound connections to the egress waypoint pod, confirming that workload-to-waypoint traffic is mutually authenticated over HBONE.Example output:
WORKLOAD DIRECTION LOCAL REMOTE REMOTE TARGET PROTOCOL CONN ID egress-waypoint-757fdbb564-44nz2.<ns> Inbound 10.0.0.10:15008 10.0.0.3:54210 api.openai.com:443 HBONE 1a2b3c4d
Cleanup
If you no longer need them, you can remove all resources that you created in this guide.
kubectl delete pod curl-unauth curl-auth -n ${NAMESPACE}
kubectl delete enterpriseagentgatewaypolicy openai-allow-agent-only -n ${NAMESPACE}
kubectl delete serviceentry openai-api -n ${NAMESPACE}
kubectl delete gateway egress-waypoint -n ${NAMESPACE}Authenticate to the AI API using workload identity
Rather than embedding API credentials in your workload, agentgateway can forward the source workload’s WIMSE WIT to the external API. Use backend.workloadIdentity.mode: SourceDelegation in an EnterpriseAgentgatewayPolicy to attach the inbound Workload-Identity-Token header to the outbound request. The external API can then verify the token directly.
apiVersion: enterpriseagentgateway.solo.io/v1alpha1
kind: EnterpriseAgentgatewayPolicy
metadata:
name: openai-wit-forward
namespace: ${NAMESPACE}
spec:
targetRefs:
- kind: ServiceEntry
group: "networking.istio.io"
name: openai-api
backend:
workloadIdentity:
mode: SourceDelegationFor full WIT configuration details, including inbound policy with workload claims and the SelfIdentification mode, see Workload identity tokens (WIMSE).