diff --git a/.github/workflows/helm_ci.yml b/.github/workflows/helm_ci.yml index 9873e736c..a7d9e9541 100644 --- a/.github/workflows/helm_ci.yml +++ b/.github/workflows/helm_ci.yml @@ -116,6 +116,23 @@ jobs: grep -q "security-config" /tmp/security.yaml echo "Security configuration renders correctly" + echo "" + echo "=== Testing admin.allowInsecureBind satisfies the admin auth render guard ===" + # admin.ip defaults to 0.0.0.0 (non-loopback), which weed admin 4.46 + # refuses to bind without authentication (see PR #11228 for the + # -allowInsecureBind opt-out this flag maps to). + helm template test $CHART_DIR --set admin.enabled=true --set admin.allowInsecureBind=true \ + > /tmp/admin-allow-insecure-bind.yaml + grep -q -- "-allowInsecureBind" /tmp/admin-allow-insecure-bind.yaml + echo "admin.allowInsecureBind renders -allowInsecureBind and passes the render guard" + + if helm template test $CHART_DIR --set admin.enabled=true > /tmp/admin-no-auth.yaml 2>/tmp/admin-no-auth.err; then + echo "FAIL: admin.enabled=true with no auth configured should fail to render" + exit 1 + fi + grep -q "admin.allowInsecureBind" /tmp/admin-no-auth.err + echo "admin with no auth configured still fails the render guard, and the guard mentions admin.allowInsecureBind" + echo "" echo "=== Testing JWT expiration overrides ===" helm template test $CHART_DIR \ diff --git a/k8s/charts/seaweedfs/templates/admin/admin-statefulset.yaml b/k8s/charts/seaweedfs/templates/admin/admin-statefulset.yaml index d6b2e79ca..2bab36fe2 100644 --- a/k8s/charts/seaweedfs/templates/admin/admin-statefulset.yaml +++ b/k8s/charts/seaweedfs/templates/admin/admin-statefulset.yaml @@ -9,7 +9,7 @@ {{- $adminAuthEnabled := include "seaweedfs.admin.authEnabled" . }} {{- $adminIp := .Values.admin.ip | default "0.0.0.0" }} {{- if and (not (include "seaweedfs.admin.isLoopbackIp" $adminIp)) (ne $adminAuthEnabled "true") }} -{{- fail (printf "admin.ip is set to %q (non-loopback) but admin authentication is not configured. Since `weed admin` 4.46 refuses to bind a non-loopback address without authentication, the admin container would exit on startup. Set admin.secret.adminPassword or admin.secret.existingSecret, or supply WEED_ADMIN_PASSWORD via admin.extraEnvironmentVars / admin.secretExtraEnvironmentVars, or set admin.ip to a loopback address such as 127.0.0.1 (note: a loopback bind makes the chart's httpGet readiness/liveness probes fail)." $adminIp) -}} +{{- fail (printf "admin.ip is set to %q (non-loopback) but admin authentication is not configured. Since `weed admin` 4.46 refuses to bind a non-loopback address without authentication, the admin container would exit on startup. Set admin.secret.adminPassword or admin.secret.existingSecret, or supply WEED_ADMIN_PASSWORD via admin.extraEnvironmentVars / admin.secretExtraEnvironmentVars, or set admin.ip to a loopback address such as 127.0.0.1 (note: a loopback bind makes the chart's httpGet readiness/liveness probes fail), or set admin.allowInsecureBind to true to opt out via -allowInsecureBind (INSECURE: exposes the admin API unauthenticated on the network)." $adminIp) -}} {{- end }} apiVersion: apps/v1 kind: StatefulSet @@ -176,14 +176,17 @@ spec: -dataDir={{ .Values.admin.dataDir }} \ {{- end }} {{- if .Values.admin.masters }} - -masters={{ .Values.admin.masters }}{{- if or $urlPrefix .Values.admin.extraArgs }} \{{ end }} + -masters={{ .Values.admin.masters }} \ {{- else if .Values.global.seaweedfs.masterServer }} - -masters={{ .Values.global.seaweedfs.masterServer }}{{- if or $urlPrefix .Values.admin.extraArgs }} \{{ end }} + -masters={{ .Values.global.seaweedfs.masterServer }} \ {{- else }} - -masters={{ range $index := until (.Values.master.replicas | int) }}${SEAWEEDFS_FULLNAME}-master-{{ $index }}.${SEAWEEDFS_FULLNAME}-master.{{ $.Release.Namespace }}:{{ $.Values.master.port }}{{ if lt $index (sub ($.Values.master.replicas | int) 1) }},{{ end }}{{ end }}{{- if or $urlPrefix .Values.admin.extraArgs }} \{{ end }} + -masters={{ range $index := until (.Values.master.replicas | int) }}${SEAWEEDFS_FULLNAME}-master-{{ $index }}.${SEAWEEDFS_FULLNAME}-master.{{ $.Release.Namespace }}:{{ $.Values.master.port }}{{ if lt $index (sub ($.Values.master.replicas | int) 1) }},{{ end }}{{ end }} \ {{- end }} {{- if $urlPrefix }} - -urlPrefix={{ $urlPrefix }}{{- if .Values.admin.extraArgs }} \{{ end }} + -urlPrefix={{ $urlPrefix }} \ + {{- end }} + {{- if .Values.admin.allowInsecureBind }} + -allowInsecureBind \ {{- end }} {{- range $index, $arg := .Values.admin.extraArgs }} {{ $arg }}{{- if lt $index (sub (len $.Values.admin.extraArgs) 1) }} \{{ end }} diff --git a/k8s/charts/seaweedfs/templates/shared/_helpers.tpl b/k8s/charts/seaweedfs/templates/shared/_helpers.tpl index 3836e9cff..8ac0085a3 100644 --- a/k8s/charts/seaweedfs/templates/shared/_helpers.tpl +++ b/k8s/charts/seaweedfs/templates/shared/_helpers.tpl @@ -105,13 +105,15 @@ true {{- end -}} {{- end -}} -{{/* Whether admin authentication is enabled from any supported source: - admin.secret (adminPassword or existingSecret), or WEED_ADMIN_PASSWORD - supplied via extraEnvironmentVars / secretExtraEnvironmentVars (which - weed admin picks up through viper's AutomaticEnv). A secret-backed - entry counts as enabled even though the chart cannot read its value. */}} +{{/* Whether the admin server's non-loopback bind guard is satisfied, from + any supported source: admin.secret (adminPassword or existingSecret), + WEED_ADMIN_PASSWORD supplied via extraEnvironmentVars / + secretExtraEnvironmentVars (which weed admin picks up through viper's + AutomaticEnv), or admin.allowInsecureBind (renders -allowInsecureBind, + the binary's own explicit opt-out). A secret-backed entry counts as + enabled even though the chart cannot read its value. */}} {{- define "seaweedfs.admin.authEnabled" -}} -{{- if or .Values.admin.secret.existingSecret .Values.admin.secret.adminPassword -}} +{{- if or .Values.admin.secret.existingSecret .Values.admin.secret.adminPassword .Values.admin.allowInsecureBind -}} true {{- else -}} {{- $merged := dict -}} diff --git a/k8s/charts/seaweedfs/values.yaml b/k8s/charts/seaweedfs/values.yaml index 40d77e897..d1435eb5f 100644 --- a/k8s/charts/seaweedfs/values.yaml +++ b/k8s/charts/seaweedfs/values.yaml @@ -1350,6 +1350,10 @@ admin: ip: "0.0.0.0" loggingOverrideLevel: null + # Let the admin server bind a non-loopback ip without adminPassword + # or mTLS configured. + allowInsecureBind: false + # Admin authentication secret: # Name of an existing secret containing admin credentials. If set, adminUser and adminPassword below are ignored.