Uh oh!
There was an error while loading. Please reload this page.
feat(egress-proxy): training-pod egress lockdown — squid gateway, gated rollout (client-runtime#102) - #247
Merged
Merged
Conversation
Step 0 of the training-pod egress lockdown (SECURITY §8.2 / tracebloc/client-runtime#102). Adds an in-cluster squid forward proxy that permits HTTPS CONNECT only to an FQDN allowlist (backend + App Insights), so a later step can drop the training pod's 0.0.0.0/0:443 egress rule. Additive and inert — no NetworkPolicy change yet, default behaviour unchanged. - egress-proxy Deployment/Service/ConfigMap: app=egress-proxy (deliberately outside the training netpol), ClusterIP egress-proxy-service:3128, PSA-restricted, read-only rootfs, pid_filename none, pinger disabled. - image pinned to ubuntu/squid 6.6-24.04_beta multi-arch index digest (amd64+arm64). - values: egressProxy.* + networkPolicy.training.allowExternalHttps (default true), both nil-guarded for `helm upgrade --reuse-values`; values.schema.json updated. - helm-unittest egress_proxy_test.yaml incl. a --reuse-values replay case. - Chart 1.6.1 -> 1.7.0 (version + appVersion lockstep). Verified: helm lint, full template render, helm unittest 207/207, and a docker smoke test under read-only rootfs as uid 13 (backend reachable, example.com denied). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…kloads Step 1 (chart side) of the §8.2 egress lockdown (tracebloc/client-runtime#102): - egressProxy.routeWorkloads flag (default false) — gateway ships inert. - jobs-manager gets EGRESS_PROXY_URL=http://egress-proxy-service:3128 only when egressProxy.enabled + routeWorkloads, so it injects HTTPS_PROXY into training pods. - network-policy-training: add an egress rule to the gateway (app=egress-proxy) whenever egressProxy.enabled, so the path is ready before rule 2 is dropped. - values.schema.json updated; new keys nil-guarded for `helm upgrade --reuse-values`. - helm-unittest: EGRESS_PROXY_URL gating, the netpol egress-proxy rule, and a training-podSelector-stability guard (auto-upgrade safety). 210/210. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…d allowExternalHttps Step 3 of the §8.2 lockdown (tracebloc/client-runtime#102) — THE guarantee. The training NetworkPolicy's external-HTTPS rule (egress to 0.0.0.0/0:443) is now wrapped in `dig "allowExternalHttps" true .Values.networkPolicy.training`: - default / absent key (helm upgrade --reuse-values from a pre-1.7.0 release) -> rule KEPT (no behaviour change, the safe direction). - explicit allowExternalHttps=false -> rule DROPPED; training pods then reach only DNS, in-cluster MySQL, the requests-proxy, and the egress gateway, so a pod running untrusted uploaded code can no longer exfiltrate the dataset to an arbitrary host. helm-unittest: rule present by default, absent (gateway path retained) when false. 212/212. Runtime G2 gate is a cluster e2e on a NetworkPolicy-enforcing CNI (see handoff). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
…ut (#102) Reflect the 1.7.0 egress gateway in SECURITY.md: - §4.2: external-443 egress is now conditional on networkPolicy.training.allowExternalHttps; document in-cluster egress to mysql / requests-proxy / egress gateway. - §8.2: rewritten from "not scheduled" to "mechanism shipped, gated rollout" with the per-fleet procedure (deploy -> routeWorkloads -> allowExternalHttps=false + verify G2) and the BACKEND_TOKEN residual (-> §8.1). - §8.1: interim mitigation now notes the lockdown hard-blocks direct SB when enabled. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
scripts/tests/e2e-auto-upgrade.sh: installs the last PUBLISHED chart from gh-pages on a real k3d cluster, then upgrades to the local working tree through both stored-values replay paths and asserts the fleet-safety contract: - `--reuse-values` (manual-operator habit): nil-guards hold, the #102 lockdown does NOT engage by accident. - `--reset-then-reuse-values` (the auto-upgrade cronjob's flags): new defaults flow in (egress gateway deploys, inert), image-refresh annotations survive. - flipping egressProxy.routeWorkloads + allowExternalHttps=false drops the external-443 rule and points jobs-manager at the gateway. - the NEXT plain auto-upgrade preserves the operator's flip. Pods are never waited on (published images need real credentials); the regression class this guards lives in Helm templating/values semantics. Wired as the `upgrade-e2e` job in helm-ci.yaml; script added to the shellcheck enumerations in installer-tests.yaml and standard-checks.yml. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
shujaatTracebloc
approved these changes
Jun 11, 2026
Uh oh!
There was an error while loading. Please reload this page.
saadqbal added a commit
that referenced
this pull request
Jun 12, 2026
feat(egress-proxy): training-pod egress lockdown — squid gateway, gated rollout (client-runtime#102)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Part of tracebloc/client-runtime#102 (SECURITY §8.2 — training-pod egress lockdown). Chart side; companion PR: tracebloc/client-runtime (jobs-manager
HTTPS_PROXYinjection).Why
A training pod runs untrusted, externally-uploaded ML code, may read the dataset from in-cluster MySQL, and can today open outbound HTTPS to
0.0.0.0/0:443(training NetworkPolicy rule 2) — a data-exfiltration path that undercuts the "data never leaves your infra" guarantee.What
Everything ships inert behind flags — no fleet behaviour changes on upgrade until an operator opts in per fleet:
egressProxy.*, default deployed but unused): squid forward proxy, HTTPS CONNECT only to an FQDN allowlist (backend per env + App Insights; fail-closed), chains to a corporate proxy viacache_peer(mirrorstracebloc.proxyEnvinputs).app=egress-proxy(deliberately outside the training netpol), ClusterIPegress-proxy-service:3128, PSA-restricted, read-only rootfs,pid_filename none, pinned to the multi-arch (amd64+arm64)ubuntu/squidindex digest.egressProxy.routeWorkloads, default false): jobs-manager getsEGRESS_PROXY_URLand injectsHTTPS_PROXYinto training pods (companion PR); netpol gains a training→gateway:3128 egress rule.networkPolicy.training.allowExternalHttps, default true): when explicitlyfalse, rule 2 (0.0.0.0/0:443) is dropped — training pods then reach only DNS, MySQL:3306, requests-proxy:8888, and the gateway:3128. Implemented withdig … true, so an absent key (stored-values replay) keeps the rule: the safe direction.BACKEND_TOKENresidual stays tracked under §8.1.upgrade-e2ejob — installs the last published chart on a real k3d cluster, upgrades to this tree via both--reuse-values(nil-guards hold, lockdown must not engage by accident) and--reset-then-reuse-values(the auto-upgrade cronjob's path: new defaults flow in inert, image-refresh annotations survive), then flips the lockdown flags and proves the next auto-upgrade preserves the flip.Auto-upgrade safety
--reset-then-reuse-values) carries the new defaults through and preserves operator overrides — flips are durable.helm upgrade --reuse-valuesfrom pre-1.7.0 stored values (regression-tested inegress_proxy_test.yaml+ the e2e gate).podSelectorto exactlytracebloc.io/workload: training, so the lockdown can never catch the auto-upgrade/image-refresh cronjobs.Rollout (per fleet, each step reversible)
egressProxy.routeWorkloads=true→ verify a training run completes via the gateway.networkPolicy.training.allowExternalHttps=false→ verify G2: in-podcurl https://example.comfails, run still completes. Requires a NetworkPolicy-enforcing CNI (Calico/Cilium/OVN — not flannel/kindnet).Tests
helm unittest: 212/212 (20 suites) — incl.--reuse-valuesreplay, flag gating both ways, podSelector stability.helm lint+ fullhelm templateclean; chart1.6.1 → 1.7.0(version+appVersion lockstep).200through the allowlist,example.comdenied.bash -n+shellcheck --severity=errorclean on the new e2e script.Remaining before fleet rollout
Cluster G2 e2e on a NetworkPolicy-enforcing CNI (tracked on tracebloc/client-runtime#102).
🤖 Generated with Claude Code
Note
High Risk
Changes training egress NetworkPolicy semantics and fleet upgrade paths; misconfiguration or broken nil-guards could break training or accidentally enable lockdown on upgrade.
Overview
Chart 1.6.1 → 1.7.0 adds a gated training-pod egress lockdown (SECURITY §8.2 / client-runtime#102): an optional in-cluster squid egress gateway (
egressProxy.*), training NetworkPolicy changes, and jobs-manager wiring forEGRESS_PROXY_URLwhen routing is enabled.Egress gateway (default on, inert until opted in): New ConfigMap/Deployment/Service render a fail-closed FQDN allowlist proxy (
app=egress-proxy, outside the training netpol).egressProxy.routeWorkloadsdefaults false; when true, jobs-manager getsEGRESS_PROXY_URLfor companion runtimeHTTPS_PROXYinjection.Network lockdown: Rule 2 (
0.0.0.0/0:443) is wrapped indig "allowExternalHttps" trueso missing keys on--reuse-valueskeep legacy behavior; explicitfalsedrops direct external HTTPS. When the gateway is enabled, training pods get an explicit egress rule toegress-proxyon the proxy port.Safety & CI:
values.yaml,values.schema.json, helm-unittest suiteegress_proxy_test.yaml, and SECURITY.md document the progressive rollout. Newupgrade-e2ejob runsscripts/tests/e2e-auto-upgrade.shon k3d (published chart → local tree via--reuse-valuesand--reset-then-reuse-values, then lockdown flag flip persistence). Shellcheck/bash gates include the new script.Reviewed by Cursor Bugbot for commit da57914. Bugbot is set up for automated code reviews on this repo. Configure here.