From 1dea606c45a1e8ca76b9c7b5a9970bc2335a7f24 Mon Sep 17 00:00:00 2001 From: Lukas Wuttke Date: Mon, 8 Jun 2026 17:05:55 +0200 Subject: [PATCH 1/2] fix(proxy): make all egress workloads proxy-aware (wire the dead HTTP_PROXY_* values) The env.HTTP_PROXY_HOST/PORT/USERNAME/PASSWORD values were declared in values.yaml + values.schema.json but consumed by no template, and no workload pod received HTTP(S)_PROXY/NO_PROXY env. Behind a corporate proxy the installer's node-level proxy (scripts/lib/cluster.sh) handles image pulls, but the application pods make direct external calls (jobs-manager -> api.tracebloc.io) the network refuses -> CrashLoopBackOff. Add a tracebloc.proxyEnv helper that derives HTTP(S)_PROXY + an auto-augmented NO_PROXY (cluster-internal ranges always included, mirroring cluster.sh, so in-cluster + MySQL traffic never traverses the proxy) from the env.HTTP_PROXY_* values, and reference it on every external-egress workload: jobs-manager (api + pods-monitor), requests-proxy, image-refresh CronJob, auto-upgrade CronJob. Renders nothing when no proxy is set, so non-proxy installs are unchanged. Excludes mysql-client and resource-monitor (no external egress) and the ingestor sub-chart (talks only to jobs-manager..svc, in-cluster). Co-Authored-By: Claude Opus 4.8 --- client/templates/_helpers.tpl | 38 +++++++++++++++++++ client/templates/auto-upgrade-cronjob.yaml | 1 + client/templates/image-refresh-cronjob.yaml | 1 + client/templates/jobs-manager-deployment.yaml | 2 + .../templates/requests-proxy-deployment.yaml | 1 + 5 files changed, 43 insertions(+) diff --git a/client/templates/_helpers.tpl b/client/templates/_helpers.tpl index 574559b..5ffdb3e 100644 --- a/client/templates/_helpers.tpl +++ b/client/templates/_helpers.tpl @@ -207,3 +207,41 @@ Usage: {{ include "tracebloc.image" (dict "repository" "tracebloc/jobs-manager" {{ $registry }}/{{ .repository }}:{{ .tag | default "prod" }} {{- end -}} {{- end }} + +{{/* +tracebloc.proxyEnv — corporate-proxy env for egress-needing workloads. +Derives HTTP(S)_PROXY + an auto-augmented NO_PROXY from .Values.env.HTTP_PROXY_* +so workload pods can reach the backend / registries through a corporate proxy. +Renders nothing when HTTP_PROXY_HOST is unset (non-proxy installs unchanged). +NO_PROXY always carries the cluster-internal ranges so in-cluster + MySQL +traffic never traverses the proxy (mirrors scripts/lib/cluster.sh defaults). +Usage inside a container's env: list: + {{- include "tracebloc.proxyEnv" . | nindent 8 }} +*/}} +{{- define "tracebloc.proxyEnv" -}} +{{- if .Values.env.HTTP_PROXY_HOST }} +{{- $host := .Values.env.HTTP_PROXY_HOST -}} +{{- $port := .Values.env.HTTP_PROXY_PORT | default "" -}} +{{- $user := .Values.env.HTTP_PROXY_USERNAME | default "" -}} +{{- $pass := .Values.env.HTTP_PROXY_PASSWORD | default "" -}} +{{- $hostport := $host -}} +{{- if $port }}{{- $hostport = printf "%s:%v" $host $port -}}{{- end -}} +{{- $cred := "" -}} +{{- if $user }}{{- $cred = printf "%s:%s@" $user $pass -}}{{- end -}} +{{- $url := printf "http://%s%s" $cred $hostport -}} +{{- $noProxy := "localhost,127.0.0.1,0.0.0.0,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,.svc,.svc.cluster.local,.cluster.local,host.k3d.internal" -}} +{{- with .Values.env.NO_PROXY }}{{- $noProxy = printf "%s,%s" . $noProxy -}}{{- end }} +- name: HTTP_PROXY + value: {{ $url | quote }} +- name: HTTPS_PROXY + value: {{ $url | quote }} +- name: http_proxy + value: {{ $url | quote }} +- name: https_proxy + value: {{ $url | quote }} +- name: NO_PROXY + value: {{ $noProxy | quote }} +- name: no_proxy + value: {{ $noProxy | quote }} +{{- end }} +{{- end -}} diff --git a/client/templates/auto-upgrade-cronjob.yaml b/client/templates/auto-upgrade-cronjob.yaml index dc797ce..5cf652f 100644 --- a/client/templates/auto-upgrade-cronjob.yaml +++ b/client/templates/auto-upgrade-cronjob.yaml @@ -134,6 +134,7 @@ spec: # our script instead. command: ["/bin/sh", "/scripts/auto-upgrade.sh"] env: + {{- include "tracebloc.proxyEnv" . | nindent 16 }} - name: RELEASE_NAME value: {{ .Release.Name | quote }} - name: RELEASE_NAMESPACE diff --git a/client/templates/image-refresh-cronjob.yaml b/client/templates/image-refresh-cronjob.yaml index af4e2e3..3fe5e47 100644 --- a/client/templates/image-refresh-cronjob.yaml +++ b/client/templates/image-refresh-cronjob.yaml @@ -486,6 +486,7 @@ spec: # alpine/k8s entrypoint is kubectl; override to run our script. command: ["/bin/sh", "/scripts/image-refresh.sh"] env: + {{- include "tracebloc.proxyEnv" . | nindent 16 }} # alpine/k8s's kubectl writes a discovery cache under # $HOME/.kube. The pod runs uid 1000 with # readOnlyRootFilesystem, so point HOME at the writable diff --git a/client/templates/jobs-manager-deployment.yaml b/client/templates/jobs-manager-deployment.yaml index 9e67c3f..5b39f83 100644 --- a/client/templates/jobs-manager-deployment.yaml +++ b/client/templates/jobs-manager-deployment.yaml @@ -66,6 +66,7 @@ spec: subPath: ingestion-authz.yaml readOnly: true env: + {{- include "tracebloc.proxyEnv" . | nindent 8 }} - name: CLIENT_ID valueFrom: secretKeyRef: @@ -142,6 +143,7 @@ spec: - name: logs-volume mountPath: "/data/logs" env: + {{- include "tracebloc.proxyEnv" . | nindent 8 }} - name: CLIENT_ID valueFrom: secretKeyRef: diff --git a/client/templates/requests-proxy-deployment.yaml b/client/templates/requests-proxy-deployment.yaml index 8750d4b..640c172 100644 --- a/client/templates/requests-proxy-deployment.yaml +++ b/client/templates/requests-proxy-deployment.yaml @@ -71,6 +71,7 @@ spec: cpu: {{ $rpLim.cpu | default "1000m" | quote }} memory: {{ $rpLim.memory | default "512Mi" | quote }} env: + {{- include "tracebloc.proxyEnv" . | nindent 12 }} - name: MYSQL_HOST value: "mysql-client" - name: EXPERIMENTS_QUEUE_NAME From 6ffa9d6b61e49d7402fe71121eb9afed59cb15cb Mon Sep 17 00:00:00 2001 From: Lukas Wuttke Date: Mon, 8 Jun 2026 17:15:23 +0200 Subject: [PATCH 2/2] test(proxy): assert every egress workload gets proxy env when configured, none when not (backend#768) Co-Authored-By: Claude Opus 4.8 --- client/tests/proxy_env_test.yaml | 97 ++++++++++++++++++++++++++++++++ 1 file changed, 97 insertions(+) create mode 100644 client/tests/proxy_env_test.yaml diff --git a/client/tests/proxy_env_test.yaml b/client/tests/proxy_env_test.yaml new file mode 100644 index 0000000..d24e02b --- /dev/null +++ b/client/tests/proxy_env_test.yaml @@ -0,0 +1,97 @@ +suite: Corporate-proxy env injection (backend#768 — guards proxy-blind workloads) +templates: + - templates/jobs-manager-deployment.yaml + - templates/requests-proxy-deployment.yaml + - templates/image-refresh-cronjob.yaml + - templates/auto-upgrade-cronjob.yaml +set: + clientId: "test-id" + clientPassword: "test" +tests: + # ===== WITHOUT a proxy: non-proxy installs must be unchanged (no HTTP_PROXY env) ===== + - it: jobs-manager api has no HTTP_PROXY env by default + template: templates/jobs-manager-deployment.yaml + asserts: + - notContains: + path: spec.template.spec.containers[0].env + content: {name: HTTP_PROXY} + any: true + - it: jobs-manager pods-monitor has no HTTP_PROXY env by default + template: templates/jobs-manager-deployment.yaml + asserts: + - notContains: + path: spec.template.spec.containers[1].env + content: {name: HTTP_PROXY} + any: true + - it: requests-proxy has no HTTP_PROXY env by default + template: templates/requests-proxy-deployment.yaml + asserts: + - notContains: + path: spec.template.spec.containers[0].env + content: {name: HTTP_PROXY} + any: true + - it: image-refresh has no HTTP_PROXY env by default + template: templates/image-refresh-cronjob.yaml + documentSelector: {path: kind, value: CronJob} + asserts: + - notContains: + path: spec.jobTemplate.spec.template.spec.containers[0].env + content: {name: HTTP_PROXY} + any: true + - it: auto-upgrade has no HTTP_PROXY env by default + template: templates/auto-upgrade-cronjob.yaml + documentSelector: {path: kind, value: CronJob} + asserts: + - notContains: + path: spec.jobTemplate.spec.template.spec.containers[0].env + content: {name: HTTP_PROXY} + any: true + # ===== WITH a proxy: every egress workload carries HTTP_PROXY + cluster-safe NO_PROXY ===== + - it: jobs-manager api gets HTTP_PROXY + cluster-safe NO_PROXY when a proxy is set + template: templates/jobs-manager-deployment.yaml + set: {env.HTTP_PROXY_HOST: proxy.example.com, env.HTTP_PROXY_PORT: "8080"} + asserts: + - contains: + path: spec.template.spec.containers[0].env + content: {name: HTTP_PROXY, value: "http://proxy.example.com:8080"} + - contains: + path: spec.template.spec.containers[0].env + content: {name: NO_PROXY, value: "localhost,127.0.0.1,0.0.0.0,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16,.svc,.svc.cluster.local,.cluster.local,host.k3d.internal"} + - it: jobs-manager pods-monitor gets HTTP_PROXY when a proxy is set + template: templates/jobs-manager-deployment.yaml + set: {env.HTTP_PROXY_HOST: proxy.example.com, env.HTTP_PROXY_PORT: "8080"} + asserts: + - contains: + path: spec.template.spec.containers[1].env + content: {name: HTTP_PROXY, value: "http://proxy.example.com:8080"} + - it: requests-proxy gets HTTP_PROXY when a proxy is set + template: templates/requests-proxy-deployment.yaml + set: {env.HTTP_PROXY_HOST: proxy.example.com, env.HTTP_PROXY_PORT: "8080"} + asserts: + - contains: + path: spec.template.spec.containers[0].env + content: {name: HTTP_PROXY, value: "http://proxy.example.com:8080"} + - it: image-refresh gets HTTP_PROXY when a proxy is set + template: templates/image-refresh-cronjob.yaml + documentSelector: {path: kind, value: CronJob} + set: {env.HTTP_PROXY_HOST: proxy.example.com, env.HTTP_PROXY_PORT: "8080"} + asserts: + - contains: + path: spec.jobTemplate.spec.template.spec.containers[0].env + content: {name: HTTP_PROXY, value: "http://proxy.example.com:8080"} + - it: auto-upgrade gets HTTP_PROXY when a proxy is set + template: templates/auto-upgrade-cronjob.yaml + documentSelector: {path: kind, value: CronJob} + set: {env.HTTP_PROXY_HOST: proxy.example.com, env.HTTP_PROXY_PORT: "8080"} + asserts: + - contains: + path: spec.jobTemplate.spec.template.spec.containers[0].env + content: {name: HTTP_PROXY, value: "http://proxy.example.com:8080"} + # ===== authenticated proxy: credentials embed in the URL ===== + - it: an authenticated proxy embeds the credentials in the proxy URL + template: templates/jobs-manager-deployment.yaml + set: {env.HTTP_PROXY_HOST: proxy.example.com, env.HTTP_PROXY_PORT: "8080", env.HTTP_PROXY_USERNAME: bob, env.HTTP_PROXY_PASSWORD: pw} + asserts: + - contains: + path: spec.template.spec.containers[0].env + content: {name: HTTP_PROXY, value: "http://bob:pw@proxy.example.com:8080"}