fix: drop the destination allowlist from the runner egress proxy #781

Merged
coilysiren merged 1 commit from chore/egress-proxy-open into main 2026-08-11 09:26:52 +00:00
Member

Follows the merged code.forgejo.org addition by removing the thing that made it necessary.

Why the allowlist went

It gated nothing. There is no NetworkPolicy anywhere in deploy/, so runner pods carry unrestricted direct egress right beside the proxy, and the docs already said so: the proxy "does not reroute unrelated CI" and "ordinary CI keeps its existing direct egress path." Anything wanting an arbitrary host took the direct route and always could.

What it cost was real and recurring. Adding a lint hook to a game-server repo needed an infrastructure PR and a Flux roll. That inverts the rule that a shipped repo never reaches up a layer for its own config, and the code.forgejo.org addition was that tax being paid one host at a time.

What still binds

Method and port remain the whole boundary: CONNECT only, 443 only, no TLS termination, no credentials, no caching, and a ClusterIP that only in-cluster pods can reach. http_access deny all stays the genuine terminal rule instead of dead text sitting under an allow all.

The guard in scripts/check-forgejo-runner-config.py restated the allowlist host by host, so it moves with the policy it encodes. It now asserts the method and port rules that still bind.

Verification

Against the digest-pinned image, not by reading:

  • squid -k parse clean, no warnings
  • code.forgejo.org tunnels 200, the exact host that blocked sirens-echo
  • crates.io and example.com tunnel, neither ever allowlisted
  • port 80 gets a Squid denial page, non-443 CONNECT refused

pre-commit run --all-files green.

One thing I tried and backed out

I wanted access logging on, since the destination set is no longer the record. stdio:/dev/stdout, stdio:/dev/fd/1, and daemon:/dev/stdout each crash this image at startup in a non-TTY container, which is exactly the Kubernetes condition. It only reproduces detached, so it would have passed a casual foreground check and taken both replicas down on rollout. Logging stays off and the doc records why. Worth a follow-up, not worth bundling here.

After merge

Flux rolls the new ConfigMap on the bumped config-revision. Re-running coilyco-gaming/sirens-echo#103 CI is the end-to-end check.

Follows the merged `code.forgejo.org` addition by removing the thing that made it necessary. ## Why the allowlist went It gated nothing. There is no NetworkPolicy anywhere in `deploy/`, so runner pods carry unrestricted direct egress right beside the proxy, and the docs already said so: the proxy "does not reroute unrelated CI" and "ordinary CI keeps its existing direct egress path." Anything wanting an arbitrary host took the direct route and always could. What it cost was real and recurring. Adding a lint hook to a game-server repo needed an infrastructure PR and a Flux roll. That inverts the rule that a shipped repo never reaches up a layer for its own config, and the `code.forgejo.org` addition was that tax being paid one host at a time. ## What still binds Method and port remain the whole boundary: CONNECT only, 443 only, no TLS termination, no credentials, no caching, and a ClusterIP that only in-cluster pods can reach. `http_access deny all` stays the genuine terminal rule instead of dead text sitting under an `allow all`. The guard in `scripts/check-forgejo-runner-config.py` restated the allowlist host by host, so it moves with the policy it encodes. It now asserts the method and port rules that still bind. ## Verification Against the digest-pinned image, not by reading: * `squid -k parse` clean, no warnings * `code.forgejo.org` tunnels 200, the exact host that blocked sirens-echo * `crates.io` and `example.com` tunnel, neither ever allowlisted * port 80 gets a Squid denial page, non-443 CONNECT refused `pre-commit run --all-files` green. ## One thing I tried and backed out I wanted access logging on, since the destination set is no longer the record. `stdio:/dev/stdout`, `stdio:/dev/fd/1`, and `daemon:/dev/stdout` each crash this image at startup in a non-TTY container, which is exactly the Kubernetes condition. It only reproduces detached, so it would have passed a casual foreground check and taken both replicas down on rollout. Logging stays off and the doc records why. Worth a follow-up, not worth bundling here. ## After merge Flux rolls the new ConfigMap on the bumped `config-revision`. Re-running https://forgejo.coilysiren.me/coilyco-gaming/sirens-echo/pulls/103 CI is the end-to-end check.
fix: drop the destination allowlist from the runner egress proxy
All checks were successful
TruffleHog / Scan for secrets (pull_request) Successful in 5s
CI / lint (pull_request) Successful in 1m14s
a2f88cf34b
The allowlist gated nothing. There is no NetworkPolicy anywhere in deploy/,
so runner pods carry unrestricted direct egress right beside the proxy, and
the docs say so outright: the proxy "does not reroute unrelated CI" and
"ordinary CI keeps its existing direct egress path." Anything wanting an
arbitrary host already took the direct route.

What it did cost was real and recurring. Adding a lint hook to a game-server
repo needed an infrastructure PR and a Flux roll, which inverts the rule that
a shipped repo never reaches up a layer for its own config. The code.forgejo.org
addition was that tax being paid one host at a time.

Method and port stay the boundary: CONNECT only, 443 only, no TLS
termination, no credentials, no caching, ClusterIP so only in-cluster pods
reach it. `http_access deny all` stays the real terminal rather than dead
text under an `allow all`.

The guard restated the old allowlist host by host, so it moves with the
policy it encodes. It now asserts the method and port rules that still bind.

Verified against the pinned image, not just by reading:

* `squid -k parse` clean, no warnings
* code.forgejo.org tunnels 200, the exact host that blocked sirens-echo
* crates.io and example.com tunnel, never allowlisted before
* port 80 gets a Squid denial page, non-443 CONNECT refused

Access logging stays off. `stdio:/dev/stdout`, `stdio:/dev/fd/1`, and
`daemon:/dev/stdout` each crash this image at startup in a non-TTY container,
which is the Kubernetes condition. Caught before shipping. Worth a follow-up,
not worth risking the proxy here.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Co-authored-by: Kai Siren <coilysiren@gmail.com>
Co-authored-by: Claude <noreply@anthropic.com>
Sign in to join this conversation.
No reviewers
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set

Reference
coilyco-flight-deck/infrastructure!781
No description provided.