Files
blinkagent[bot] 892b226837 fix(helm): allow overriding CODER_PPROF_ADDRESS and CODER_PROMETHEUS_ADDRESS (#21714)
## Summary

Previously, `CODER_PPROF_ADDRESS` and `CODER_PROMETHEUS_ADDRESS` were
hardcoded in the Helm chart template to `0.0.0.0:6060` and
`0.0.0.0:2112` respectively. These values could not be overridden via
`coder.env` values because the hardcoded values were set first in the
template, and Kubernetes uses the first occurrence of duplicate env
vars.

This was a security concern because binding to `0.0.0.0` exposes these
endpoints to any pod in the cluster:
- **pprof** can expose sensitive runtime information (goroutine stacks,
heap profiles, CPU profiles that may contain memory contents)
- **Prometheus metrics** may contain sensitive operational data

## Changes

1. **`helm/coder/templates/_coder.tpl`**: Added logic to check if the
user has set `CODER_PPROF_ADDRESS` or `CODER_PROMETHEUS_ADDRESS` in
`coder.env` before applying the default values. If the user provides a
value, the hardcoded default is skipped.

2. **`helm/coder/values.yaml`**: Updated documentation to:
   - Remove these vars from the "cannot be overridden" list
- Add them to a new "can be overridden" section with security
recommendations

3. **Tests**: Added test cases for both override scenarios with
corresponding golden files.

## Usage

Users can now restrict pprof and prometheus to localhost only:

```yaml
coder:
  env:
    - name: CODER_PPROF_ADDRESS
      value: "127.0.0.1:6060"
    - name: CODER_PROMETHEUS_ADDRESS  
      value: "127.0.0.1:2112"
```

## Local Testing

To verify the fix locally:

```bash
# Update helm dependencies
cd helm/coder && helm dependency update

# Test default behavior (should show 0.0.0.0)
helm template coder . -f tests/testdata/default_values.yaml --namespace default | grep -A1 'CODER_PPROF_ADDRESS\|CODER_PROMETHEUS_ADDRESS'

# Test pprof override (should show 127.0.0.1:6060)
helm template coder . -f tests/testdata/pprof_address_override.yaml --namespace default | grep -A1 'CODER_PPROF_ADDRESS'

# Test prometheus override (should show 127.0.0.1:2112)
helm template coder . -f tests/testdata/prometheus_address_override.yaml --namespace default | grep -A1 'CODER_PROMETHEUS_ADDRESS'

# Run Go tests
cd tests && go test . -v
```

Fixes #21713

---------
Co-authored-by: blink-so[bot] <211532188+blink-so[bot]@users.noreply.github.com>
Co-authored-by: uzair-coder07 <uzair@coder.com>
2026-02-02 19:03:06 -06:00

166 lines
4.7 KiB
Smarty

{{/*
Service account to merge into the libcoder template
*/}}
{{- define "coder.serviceaccount" -}}
{{- end -}}
{{/*
Component annotation for pod metadata.
*/}}
{{- define "coder.componentAnnotation" -}}
{{- if .Values.coder.workspaceProxy -}}
app.kubernetes.io/component: wsproxy
{{- else -}}
app.kubernetes.io/component: coderd
{{- end -}}
{{- end }}
{{/*
Deployment to merge into the libcoder template
*/}}
{{- define "coder.deployment" -}}
spec:
template:
spec:
containers:
-
{{ include "libcoder.containerspec" (list . "coder.containerspec") | indent 8}}
{{- end -}}
{{/*
ContainerSpec for the Coder container of the Coder deployment
*/}}
{{- define "coder.containerspec" -}}
args:
{{- if .Values.coder.commandArgs }}
{{- toYaml .Values.coder.commandArgs | nindent 12 }}
{{- else }}
{{- if .Values.coder.workspaceProxy }}
- wsproxy
{{- end }}
- server
{{- end }}
{{- if .Values.coder.envFrom }}
envFrom:
{{- with .Values.coder.envFrom }}
{{ toYaml . }}
{{- end }}
{{- end }}
env:
- name: CODER_HTTP_ADDRESS
value: "0.0.0.0:8080"
{{- $hasPrometheusAddress := false }}
{{- $hasPprofAddress := false }}
{{- range .Values.coder.env }}
{{- if eq .name "CODER_PROMETHEUS_ADDRESS" }}
{{- $hasPrometheusAddress = true }}
{{- end }}
{{- if eq .name "CODER_PPROF_ADDRESS" }}
{{- $hasPprofAddress = true }}
{{- end }}
{{- end }}
{{- if not $hasPrometheusAddress }}
- name: CODER_PROMETHEUS_ADDRESS
value: "0.0.0.0:2112"
{{- end }}
{{- if not $hasPprofAddress }}
- name: CODER_PPROF_ADDRESS
value: "0.0.0.0:6060"
{{- end }}
{{- if .Values.provisionerDaemon.pskSecretName }}
- name: CODER_PROVISIONER_DAEMON_PSK
valueFrom:
secretKeyRef:
name: {{ .Values.provisionerDaemon.pskSecretName | quote }}
key: psk
{{- end }}
# Set the default access URL so a `helm apply` works by default.
# See: https://github.com/coder/coder/issues/5024
{{- $hasAccessURL := false }}
{{- range .Values.coder.env }}
{{- if eq .name "CODER_ACCESS_URL" }}
{{- $hasAccessURL = true }}
{{- end }}
{{- end }}
{{- if and (not $hasAccessURL) .Values.coder.envUseClusterAccessURL }}
- name: CODER_ACCESS_URL
value: {{ include "coder.defaultAccessURL" . | quote }}
{{- end }}
# Used for inter-pod communication with high-availability.
- name: KUBE_POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP
- name: CODER_DERP_SERVER_RELAY_URL
value: "http://$(KUBE_POD_IP):8080"
{{- include "coder.tlsEnv" . }}
{{- with .Values.coder.env }}
{{ toYaml . }}
{{- end }}
ports:
- name: "http"
containerPort: 8080
protocol: TCP
{{- if eq (include "coder.tlsEnabled" .) "true" }}
- name: "https"
containerPort: 8443
protocol: TCP
{{- end }}
{{- range .Values.coder.env }}
{{- if eq .name "CODER_PROMETHEUS_ENABLE" }}
{{/*
This sadly has to be nested to avoid evaluating the second part
of the condition too early and potentially getting type errors if
the value is not a string (like a `valueFrom`). We do not support
`valueFrom` for this env var specifically.
*/}}
{{- if eq .value "true" }}
- name: "prometheus-http"
containerPort: 2112
protocol: TCP
{{- end }}
{{- end }}
{{- end }}
{{- if .Values.coder.readinessProbe.enabled }}
readinessProbe:
httpGet:
path: /healthz
port: "http"
scheme: "HTTP"
initialDelaySeconds: {{ .Values.coder.readinessProbe.initialDelaySeconds }}
{{- if hasKey .Values.coder.readinessProbe "periodSeconds" }}
periodSeconds: {{ .Values.coder.readinessProbe.periodSeconds }}
{{- end }}
{{- if hasKey .Values.coder.readinessProbe "timeoutSeconds" }}
timeoutSeconds: {{ .Values.coder.readinessProbe.timeoutSeconds }}
{{- end }}
{{- if hasKey .Values.coder.readinessProbe "successThreshold" }}
successThreshold: {{ .Values.coder.readinessProbe.successThreshold }}
{{- end }}
{{- if hasKey .Values.coder.readinessProbe "failureThreshold" }}
failureThreshold: {{ .Values.coder.readinessProbe.failureThreshold }}
{{- end }}
{{- end }}
{{- if .Values.coder.livenessProbe.enabled }}
livenessProbe:
httpGet:
path: /healthz
port: "http"
scheme: "HTTP"
initialDelaySeconds: {{ .Values.coder.livenessProbe.initialDelaySeconds }}
{{- if hasKey .Values.coder.livenessProbe "periodSeconds" }}
periodSeconds: {{ .Values.coder.livenessProbe.periodSeconds }}
{{- end }}
{{- if hasKey .Values.coder.livenessProbe "timeoutSeconds" }}
timeoutSeconds: {{ .Values.coder.livenessProbe.timeoutSeconds }}
{{- end }}
{{- if hasKey .Values.coder.livenessProbe "successThreshold" }}
successThreshold: {{ .Values.coder.livenessProbe.successThreshold }}
{{- end }}
{{- if hasKey .Values.coder.livenessProbe "failureThreshold" }}
failureThreshold: {{ .Values.coder.livenessProbe.failureThreshold }}
{{- end }}
{{- end }}
{{- end }}