From d8b6f48ae7ace61c85ed593b7482ebf09ee68744 Mon Sep 17 00:00:00 2001 From: Paolo Dettori Date: Mon, 8 Jun 2026 14:37:56 -0400 Subject: [PATCH] fix(driver): bypass Istio ambient inbound capture for sandbox pods On OpenShift with Istio ambient mesh (HBONE mode), ztunnel intercepts inbound TCP to the pod and re-originates connections from the pod's main IP instead of preserving the sandbox veth source address. This breaks the proxy's /proc/net/tcp-based identity resolution because peer_addr() returns ztunnel's address, not the sandbox's 10.200.0.2. Always annotate sandbox pods with: ambient.istio.io/bypass-inbound-capture: "true" This tells Istio ambient to skip inbound interception, preserving the original source address on the veth pair so identity resolution can correlate sockets to sandbox processes. The sidecar-mode annotation (traffic.sidecar.istio.io/excludeInboundPorts) has no effect in ambient mode. Fixes: kagenti/kagenti#1855 Assisted-By: Claude (Anthropic AI) Signed-off-by: Paolo Dettori --- internal/driver/provisioner.go | 7 ++++++- internal/driver/provisioner_test.go | 3 +++ 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/internal/driver/provisioner.go b/internal/driver/provisioner.go index b08eef0..11b7a2f 100644 --- a/internal/driver/provisioner.go +++ b/internal/driver/provisioner.go @@ -28,7 +28,8 @@ const ( labelKagentiInject = "kagenti.io/inject" labelTenant = "openshell.ai/tenant" labelKagentiTeam = "kagenti.io/team" - annotationSandboxID = "openshell.io/sandbox-id" + annotationSandboxID = "openshell.io/sandbox-id" + annotationBypassInboundCapture = "ambient.istio.io/bypass-inbound-capture" ) // K8sProvisioner implements SandboxProvisioner using the Kubernetes API. It @@ -383,6 +384,10 @@ func (p *K8sProvisioner) buildSandboxSpec(sb *pb.DriverSandbox) map[string]inter podAnnotations := map[string]interface{}{ annotationSandboxID: sb.GetId(), + // Bypass Istio ambient inbound capture so ztunnel (HBONE mode) does not + // re-originate veth-pair connections from the pod's main IP, which breaks + // the proxy's /proc/net/tcp identity resolution. + annotationBypassInboundCapture: "true", } return map[string]interface{}{ diff --git a/internal/driver/provisioner_test.go b/internal/driver/provisioner_test.go index 6ecabc6..9d92bde 100644 --- a/internal/driver/provisioner_test.go +++ b/internal/driver/provisioner_test.go @@ -365,6 +365,9 @@ func TestBuildSandboxSpec_Annotations(t *testing.T) { if annotations[annotationSandboxID] != "sb-anno-123" { t.Errorf("expected annotation %s=sb-anno-123, got %v", annotationSandboxID, annotations[annotationSandboxID]) } + if annotations[annotationBypassInboundCapture] != "true" { + t.Errorf("expected annotation %s=true, got %v", annotationBypassInboundCapture, annotations[annotationBypassInboundCapture]) + } } func TestBuildSandboxSpec_TenantLabels(t *testing.T) {