Skip to content

Translate AllowPort into Envoy egress RBAC policy#5927

Open
ChrisJBurns wants to merge 4 commits into
cburns/envoy-readiness-fixfrom
cburns/envoy-allow-port
Open

Translate AllowPort into Envoy egress RBAC policy#5927
ChrisJBurns wants to merge 4 commits into
cburns/envoy-readiness-fixfrom
cburns/envoy-allow-port

Conversation

@ChrisJBurns

Copy link
Copy Markdown
Collaborator

Summary

Closes the AllowPort parity gap between the Envoy and Squid backends, and adds an e2e test that proves enforcement through a real Envoy container.

Closes #5915. Part of #5900.

The problem

With AllowHost: ["example.com"], AllowPort: [443], the intent is that only HTTPS traffic to example.com is permitted. Squid enforced this. Envoy ignored AllowPort entirely — plain HTTP to example.com (port 80) also got through.

The fix

AllowPort entries are translated into :authority suffix matchers (":443", ":80", …) in the RBAC ALLOW filter. In Envoy's RBAC, a policy fires when all its permissions match, so adding a port permission to the same policy as the host regex gives AND semantics — matching Squid's allowed_ports AND allowed_dsts ACL combination.

Profile Before After
AllowHost + AllowPort host only enforced (port ignored) host AND port both required
AllowPort only effectively allow-all any host on listed ports
AllowHost only any port any port (unchanged)
InsecureAllowAll everything everything (ignores port list, same as Squid)
Tests
  • TestBuildAllowlistPolicies_AllowPort — 4 unit table cases covering all combinations (config-shape level)
  • NetworkIsolationEnvoy / AllowPort enforcement — e2e test against a real Envoy container: allows https://example.com (port 443), blocks http://example.com (port 80)

Type of change

  • Bug fix / parity fix

Test plan

  • go build ./pkg/container/docker/... passes
  • golangci-lint clean
  • TestBuildAllowlistPolicies_AllowPort passes
  • go test -c ./test/e2e/ compiles
  • CI e2e proxy shard — AllowPort enforcement test runs against real Envoy

Generated with Claude Code

@github-actions github-actions Bot added the size/S Small PR: 100-299 lines changed label Jul 22, 2026
ChrisJBurns and others added 2 commits July 22, 2026 22:30
Creating the Envoy container in SetupEgress (before createMcpContainer)
caused the STRICT_DNS ingress cluster to probe the MCP hostname before
the container existed. On Linux Docker Engine this resulted in a cached
negative DNS response that prevented the ingress from ever connecting,
leaving the server stuck in "starting" past the readiness window.

Move all Envoy container creation to SetupIngress (after the MCP
container exists) so the STRICT_DNS cluster resolves the upstream
hostname on its first probe. SetupEgress now only computes and returns
the proxy env vars — the container name is deterministic, so no state
needs to be threaded through egressResult. Remove the now-unused
egressResult.ingressPort field and update the orchestration test.

Also remove the BeforeEach(Skip(...)) guard from the Envoy e2e suite so
the tests run now that the readiness issue is resolved.

Closes #5922.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The Envoy e2e tests were timing out on Linux CI because the Envoy
distroless image (~47MB) was being pulled cold inside the 120s readiness
window. Pre-pull it in the proxy shard's image setup step alongside the
other proxy-suite images. Raise the WaitForMCPServer timeout to 180s as
a safety margin for any remaining startup variability.

Closes #5922.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@ChrisJBurns
ChrisJBurns force-pushed the cburns/envoy-readiness-fix branch from 3f79384 to 8581a2d Compare July 22, 2026 21:30
@ChrisJBurns
ChrisJBurns force-pushed the cburns/envoy-allow-port branch from be9bc48 to 346d75d Compare July 22, 2026 21:30
ChrisJBurns and others added 2 commits July 22, 2026 22:30
Squid enforces AllowPort via the allowed_ports ACL, AND-d with AllowHost.
The Envoy backend previously ignored AllowPort, leaving allowlisted hosts
reachable on any port — a parity regression.

Translate AllowPort into :authority suffix matchers (":80", ":443", …) in
the RBAC ALLOW filter, mirroring Squid's AND semantics:
  - AllowHost + AllowPort  → host AND port must match in the same policy
  - AllowPort only         → any host on listed ports
  - AllowHost only         → any port (unchanged)
  - InsecureAllowAll       → ignores AllowPort (same as Squid)

Uses :authority suffix matching so plain HTTP ("host:port") and HTTPS
CONNECT ("host:port") are both covered. Remove the Known Limitation entry
and add a parity row to the comparison table.

Closes #5915.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Exercises the AllowPort fix end-to-end: starts an Envoy isolated server
with AllowHost:[example.com] + AllowPort:[443], then asserts that
https://example.com succeeds and http://example.com is blocked. This
closes the gap between unit tests (which verify the config shape) and
runtime behaviour through a real Envoy container.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@ChrisJBurns
ChrisJBurns force-pushed the cburns/envoy-allow-port branch from 346d75d to 1d45cc2 Compare July 22, 2026 21:30
@github-actions github-actions Bot added size/S Small PR: 100-299 lines changed and removed size/S Small PR: 100-299 lines changed labels Jul 22, 2026
@codecov

codecov Bot commented Jul 22, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 71.66%. Comparing base (8581a2d) to head (1d45cc2).

Additional details and impacted files
@@                      Coverage Diff                       @@
##           cburns/envoy-readiness-fix    #5927      +/-   ##
==============================================================
+ Coverage                       71.65%   71.66%   +0.01%     
==============================================================
  Files                             700      700              
  Lines                           71918    71940      +22     
==============================================================
+ Hits                            51532    51556      +24     
+ Misses                          16691    16690       -1     
+ Partials                         3695     3694       -1     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@ChrisJBurns
ChrisJBurns force-pushed the cburns/envoy-readiness-fix branch 2 times, most recently from ccf886b to 7d8fd98 Compare July 22, 2026 22:21
ChrisJBurns added a commit that referenced this pull request Jul 22, 2026
The transparent proxy rewrites the Host header to include the port
("127.0.0.1:22354"), but ingressDomains was returning bare hostnames from
Inbound.AllowHost (e.g. "127.0.0.1") without ports. Envoy's virtual host
matching failed, so every initialize request from waitForInitializeSuccess
was rejected — the server never reached running state.

Fix: always return wildcard for the ingress virtual host domain. The
Inbound.AllowHost restriction is already enforced by the 127.0.0.1
host-side port binding, which limits the ingress to local connections only.
The virtual host domain list adds no security value here and breaks the
health check.

Also removes the AllowPort e2e test from this branch (it belongs on #5927).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/S Small PR: 100-299 lines changed

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Envoy backend: translate AllowPort into egress policy

1 participant