From c1d5b29f001495d6e6c2509178b6dea563e034aa Mon Sep 17 00:00:00 2001 From: Lior Lieberman Date: Mon, 14 Sep 2026 07:53:06 -0700 Subject: [PATCH] flip extproc order --- cmd/ate-setup/internal/steps/overlay_test.go | 72 +++++++++++++++++++ .../atenet-egress-with-sdsmint.yaml | 9 +-- 2 files changed, 77 insertions(+), 4 deletions(-) diff --git a/cmd/ate-setup/internal/steps/overlay_test.go b/cmd/ate-setup/internal/steps/overlay_test.go index 0523dcbbe..f2ef12a20 100644 --- a/cmd/ate-setup/internal/steps/overlay_test.go +++ b/cmd/ate-setup/internal/steps/overlay_test.go @@ -149,4 +149,76 @@ func TestPatchAtenetEgressManifest(t *testing.T) { t.Errorf("SDS resource %q is missing watched_directory; rotation would be silently broken", key) } } + + // The additional processor is spliced in below the policy ext_proc on + // both HTTP chains, so it sees only requests the policy allowed. + spliced := 0 + for _, filters := range httpFilterChains(t, envoyYaml) { + policyAt, additionalAt := -1, -1 + for i, f := range filters { + switch extProcCluster(f) { + case "ext_proc_server": + policyAt = i + case additionalEgressExtprocCluster: + additionalAt = i + } + } + if additionalAt < 0 { + continue + } + spliced++ + if policyAt < 0 || policyAt > additionalAt { + t.Errorf("additional ext_proc at http_filters[%d] runs before the policy ext_proc at [%d]", additionalAt, policyAt) + } + } + if spliced != 2 { + t.Errorf("additional ext_proc spliced into %d HTTP chains, want 2", spliced) + } +} + +// httpFilterChains returns the http_filters of every HTTP connection manager +// in the bootstrap's static listeners. +func httpFilterChains(t *testing.T, envoyYaml string) [][]map[string]any { + t.Helper() + var bootstrap struct { + StaticResources struct { + Listeners []struct { + FilterChains []struct { + Filters []struct { + Name string `json:"name"` + TypedConfig struct { + HTTPFilters []map[string]any `json:"http_filters"` + } `json:"typed_config"` + } `json:"filters"` + } `json:"filter_chains"` + } `json:"listeners"` + } `json:"static_resources"` + } + if err := yaml.Unmarshal([]byte(envoyYaml), &bootstrap); err != nil { + t.Fatalf("patched envoy.yaml does not parse as a bootstrap: %v", err) + } + var chains [][]map[string]any + for _, l := range bootstrap.StaticResources.Listeners { + for _, fc := range l.FilterChains { + for _, f := range fc.Filters { + if f.Name == "envoy.filters.network.http_connection_manager" { + chains = append(chains, f.TypedConfig.HTTPFilters) + } + } + } + } + return chains +} + +// extProcCluster returns the cluster an ext_proc filter dials, or "" for any +// other filter. +func extProcCluster(filter map[string]any) string { + if filter["name"] != "envoy.filters.http.ext_proc" { + return "" + } + typedConfig, _ := filter["typed_config"].(map[string]any) + grpcService, _ := typedConfig["grpc_service"].(map[string]any) + envoyGRPC, _ := grpcService["envoy_grpc"].(map[string]any) + name, _ := envoyGRPC["cluster_name"].(string) + return name } diff --git a/manifests/ate-install/atenet-egress-with-sdsmint.yaml b/manifests/ate-install/atenet-egress-with-sdsmint.yaml index 81846622c..c3103e7ee 100644 --- a/manifests/ate-install/atenet-egress-with-sdsmint.yaml +++ b/manifests/ate-install/atenet-egress-with-sdsmint.yaml @@ -265,8 +265,9 @@ data: # hack/install-ate.sh is run with # --experimental-additional-egress-extproc-service, which replaces each # with a generated block for an additional, external processor. The - # marker sits above the policy filter so that processor sees the request - # before anything is injected into it. + # marker sits below the policy filter, so that processor sees only + # requests the policy allowed, including any headers the policy added; a + # request the policy denies never reaches it. # # The passthrough chain is a tcp_proxy, so it has no HTTP filters of its # own, and it decides nothing: it dials the address the CONNECT leg @@ -420,7 +421,6 @@ data: cluster: egress_original_dst_tls timeout: 0s http_filters: - #ATE_MITM_EXTPROC_FILTER -- see the mitm_listener comment above. # Every request on this chain is authorized against the actor's # EgressPolicy by the same sidecar; the actor comes from the filter # state the CONNECT leg set, never from a header. @@ -461,6 +461,7 @@ data: receiving_namespaces: untyped: - dev.ate.egress + #ATE_MITM_EXTPROC_FILTER -- see the mitm_listener comment above. # Resolves the Host for the by-name route. It does nothing for a # route to any other kind of cluster. - name: envoy.filters.http.dynamic_forward_proxy @@ -582,7 +583,6 @@ data: cluster: egress_original_dst_cleartext timeout: 0s http_filters: - #ATE_MITM_EXTPROC_FILTER -- Don't modify this line. # Every request on this chain is authorized against the actor's # EgressPolicy by the same sidecar; the actor comes from the filter # state the CONNECT leg set, never from a header. @@ -623,6 +623,7 @@ data: receiving_namespaces: untyped: - dev.ate.egress + #ATE_MITM_EXTPROC_FILTER -- Don't modify this line. # Resolves the Host for the by-name route. It does nothing for a # route to any other kind of cluster. - name: envoy.filters.http.dynamic_forward_proxy