helm: drop fromToml dependency in security-configmap.yaml (fixes #11611) (#11614)

* helm: drop fromToml dependency in security-configmap.yaml (fixes #11611)

fromToml was added to Helm in v3.17.0 (helm/helm#12026, merged
2024-09-12, one day after v3.16.0 was cut). This chart declares no
minimum Helm version (no Chart.yaml kubeVersion, nothing in the
README), and the call in security-configmap.yaml:21 is an
unconditional *parse*-time failure on Helm < v3.17.0 - Go's
text/template parses a file's entire body before evaluating any
{{if}}, so this breaks the chart (any topology, any values) even when
securityConfigEnabled is false and the ConfigMap would render nothing.

Replaces the fromToml-based dig lookup with a small regex-based helper
(seaweedfs.existingTomlKey) that reads the same four "key = ..." JWT
signing-key values out of a previously-rendered security.toml,
preserving the existing fallback-to-random behavior exactly.

Verified:
- helm lint (v3.16.3 and v4.3.0): clean
- helm template with chart defaults: byte-identical output to the
  unpatched chart rendered via Helm v4 (which has fromToml) - the
  disabled/default path is untouched
- helm template with security enabled, no prior ConfigMap: identical
  structure to the unpatched chart (helm v4), modulo the expected
  random key
- Real helm install + helm upgrade round trip (live lookup, since
  "helm template" never evaluates lookup, even under the original
  fromToml code): the JWT signing key is identical across both
  releases - confirms key persistence across upgrades is preserved,
  not just "renders without erroring"
- helm template with chart defaults, Helm v3.16.3: previously failed
  with a parse error naming fromToml as undefined; now renders
  successfully

Fixes #11611.

* helm: harden existingTomlKey against commented key lines and CRLF

Addresses two review findings from greptile-apps on PR #11614:

- The key-line regex matched the first "key = ..." anywhere in the
  section block, including a commented-out "# key = ..." line, which
  would shadow a real active key on a hand-edited or otherwise
  non-chart-generated ConfigMap. Anchored to line start with the
  Go regexp multiline flag ((?m)^key...), which a line starting with
  "#" cannot match.
- The section-header match required an exact "]\n", so a ConfigMap
  with CRLF line endings would fail to match the block at all and
  regenerate the key instead of reusing it. Changed to "]\r?\n".

Also adds a CI test ("Verify JWT signing key persistence across
upgrades") exercising all of this end to end with a real
helm install -> edit the live ConfigMap -> helm upgrade cycle,
matching the existing "Verify SFTP host key secret lifecycle" test's
shape: both edge cases are reproduced against a real ConfigMap and
asserted on the post-upgrade rendered security.toml.

Verified locally (same commands as the new CI step) against a real
cluster before pushing.

* helm: preserve JWT keys across supported TOML layouts

* ci: use setup-python interpreter for JWT upgrade checks

* helm: preserve keys under quoted TOML section headers

* helm: ignore unrelated quoted TOML section headers
This commit is contained in:
Upayan authored and GitHub committed 2026-10-06 12:56:08 +08:00
1 parent 3a65365f6e
commit b14dd1cee4
5 files changed
+329 -7

No files matched your search

+31 -2
View File
@@ -3,10 +3,10 @@ name: "helm: lint and test charts"
on:
push:
branches: [ master ]
paths: ['k8s/**', '.github/workflows/helm_ci.yml']
paths: ['k8s/**', '.github/workflows/helm_ci.yml', '.github/scripts/helm_jwt_keys.py']
pull_request:
branches: [ master ]
paths: ['k8s/**', '.github/workflows/helm_ci.yml']
paths: ['k8s/**', '.github/workflows/helm_ci.yml', '.github/scripts/helm_jwt_keys.py']
permissions:
contents: read
@@ -20,6 +20,14 @@ jobs:
with:
fetch-depth: 0
- name: Set up Helm before fromToml was available
uses: azure/setup-helm@v5
with:
version: v3.16.3
- name: Record legacy Helm binary
run: echo "HELM_LEGACY=$(command -v helm)" >> "$GITHUB_ENV"
- name: Set up Helm
uses: azure/setup-helm@v5
with:
@@ -44,6 +52,17 @@ jobs:
- name: Run chart-testing (lint)
run: ct lint --target-branch ${{ github.event.repository.default_branch }} --all --validate-maintainers=false --chart-dirs k8s/charts
- name: Verify legacy Helm rendering
run: |
"$HELM_LEGACY" lint k8s/charts/seaweedfs
"$HELM_LEGACY" template test k8s/charts/seaweedfs > "$RUNNER_TEMP/legacy-default.yaml"
"$HELM_LEGACY" template test k8s/charts/seaweedfs \
--set global.seaweedfs.securityConfig.jwtSigning.volumeRead=true \
--set global.seaweedfs.securityConfig.jwtSigning.filerWrite=true \
--set global.seaweedfs.securityConfig.jwtSigning.filerRead=true \
> "$RUNNER_TEMP/legacy-jwt.yaml"
- name: Verify template rendering
run: |
set -e
@@ -1922,6 +1941,16 @@ jobs:
kubectl delete namespace "$NS"
echo "SFTP host key lifecycle tests passed"
- name: Verify JWT signing key persistence across upgrades
run: |
# chart-testing puts its pip-less venv first on PATH; use setup-python.
PYTHON="$pythonLocation/bin/python3"
"$PYTHON" -m pip install tomli==2.2.1
CONTEXT=$(kubectl config current-context)
"$PYTHON" .github/scripts/helm_jwt_keys.py --context "$CONTEXT"
"$PYTHON" .github/scripts/helm_jwt_keys.py --helm "$HELM_LEGACY" \
--reference-helm helm --context "$CONTEXT"
- name: Verify install into a default-deny namespace
run: |
set -e