Skip to content

feat: expose orgCABundle.configMapName for TLS trust injection#38

Merged
pmeier merged 1 commit into
nebari-dev:mainfrom
oren-openteams:feat/org-ca-bundle
Jul 2, 2026
Merged

feat: expose orgCABundle.configMapName for TLS trust injection#38
pmeier merged 1 commit into
nebari-dev:mainfrom
oren-openteams:feat/org-ca-bundle

Conversation

@oren-openteams

Copy link
Copy Markdown
Contributor

Closes #36.

Summary

Adds an optional orgCABundle.configMapName value. When set, the chart mounts the named ConfigMap into the nebi pod at /etc/ssl/certs/org-ca.crt (via subPath) and sets SSL_CERT_FILE to point at it.

Required on clusters with a TLS-intercepting egress proxy whose CA isn't in the container's default trust store — otherwise pixi/rattler outbound HTTPS to conda-forge / pypi / github fails with unknown CA.

Mirrors the shape already shipped in nebari-rayserve-pack#16. Same pattern I've been driving through kubectl patch + Argo ignoreDifferences on real deployments for weeks — this puts the config surface where it belongs (a helm value) so those out-of-band patches can retire.

Why both the bind mount AND SSL_CERT_FILE

Rust's rustls-native-certs (used by pixi/rattler under the hood) honors SSL_CERT_FILE but does NOT iterate /etc/ssl/certs/. So a bare subPath mount at /etc/ssl/certs/org-ca.crt is invisible to pixi without the env var. This is a subtle difference from Go and Python tooling, both of which pick up the directory entry. The chart sets both automatically when the value is non-empty.

Changes

  • values.yaml — new top-level orgCABundle.configMapName value defaulted to "", with a docstring covering the intercepting-proxy use case, the SSL_CERT_FILE reasoning, the ConfigMap key requirement (ca-bundle.crt), and the byte-identity guarantee when unset.
  • templates/deployment.yaml — three changes:
    1. Conditional SSL_CERT_FILE env var appended to the existing env block.
    2. Refactored volumeMounts to compose the existing environments mount and the new org-ca-bundle mount independently (guarded on either being enabled).
    3. Refactored volumes to compose the existing environments PVC and the new org-ca-bundle ConfigMap independently.

The refactor of volumeMounts and volumes from {{- if .Values.persistence.enabled }} to {{- if or .Values.persistence.enabled .Values.orgCABundle.configMapName }} preserves the existing behavior exactly (both defaults evaluate to the same output) while allowing either or both to render independently.

Verification

Rendered both trees with helm template test . --set nebariapp.hostname=nebi.example.com:

  • Default values (orgCABundle.configMapName=\"\") — 418 lines, byte-identical vs main:
    $ diff /tmp/rendered-main.yaml /tmp/rendered-mychanges.yaml
    (no output)
    
  • With orgCABundle.configMapName=my-ca-bundle — exactly the expected additions in the right places (env var, volumeMount, volume), no unrelated diffs:
    > - name: SSL_CERT_FILE
    >   value: /etc/ssl/certs/org-ca.crt
    > - name: org-ca-bundle
    >   mountPath: /etc/ssl/certs/org-ca.crt
    >   subPath: org-ca.crt
    >   readOnly: true
    > - name: org-ca-bundle
    >   configMap:
    >     name: my-ca-bundle
    >     items:
    >       - key: ca-bundle.crt
    >         path: org-ca.crt
    
  • helm lint — clean (the pre-existing missing required value: nebariapp.hostname warning is unrelated).

Not included in this PR

  • postgres-statefulset.yaml: the issue mentions propagating the mount there as optional. The postgres pod doesn't currently make outbound HTTPS calls (it just serves the local nebi container), so I skipped it to keep the PR focused. Easy follow-up if it turns out to be needed.
  • Auto-creating the ConfigMap from a helm value: intentionally out of scope per the issue. The ConfigMap should come from whatever the operator uses for secrets/configs (sealed-secrets, external-secrets, gitops, kubectl create). The chart only consumes a reference.
  • README example: happy to add if desired, but the docstring in values.yaml is fairly comprehensive already, and the README is currently thin on configuration reference (values.yaml is de facto the docs).

Rollout risk

Zero for existing users: the value defaults to "" and the render is byte-identical, so no diff would land on any current deployment.

Adds an optional `orgCABundle.configMapName` value. When set, the chart
mounts the named ConfigMap into the nebi pod at
`/etc/ssl/certs/org-ca.crt` (via subPath) and sets `SSL_CERT_FILE` to
point at it.

Required on clusters with a TLS-intercepting egress proxy whose CA
isn't in the container's default trust store — otherwise pixi/rattler
outbound HTTPS to conda-forge / pypi / github fails with "unknown CA".

Rust's rustls-native-certs (used by pixi/rattler under the hood)
honours `SSL_CERT_FILE` but does NOT iterate `/etc/ssl/certs/`, so
both the bind mount AND the env var are required — the env var is
set automatically when the value is non-empty.

The named ConfigMap must already exist in the release namespace with
key `ca-bundle.crt` containing PEM-encoded CA certs. Creation is out
of scope for the chart: use gitops / sealed-secrets / external-secrets /
whatever the operator already runs. Mirrors the shape already shipped
in nebari-rayserve-pack#16.

When `orgCABundle.configMapName` is empty (default), `helm template`
output is byte-identical to before this change. Verified by rendering
both trees with `--set nebariapp.hostname=nebi.example.com` and
diffing — 418 lines vs 418 lines, no diff.

Closes nebari-dev#36.
@oren-openteams oren-openteams requested a review from pmeier July 2, 2026 03:42
@pmeier pmeier merged commit 02bcdbf into nebari-dev:main Jul 2, 2026
4 of 5 checks passed
@oren-openteams oren-openteams deleted the feat/org-ca-bundle branch July 2, 2026 13:42
pmeier pushed a commit that referenced this pull request Jul 2, 2026
Triggers the release workflow to publish nebari-nebi-pack-0.1.1.

Changes since 0.1.0 (one merged PR):

- #38 — expose `orgCABundle.configMapName` for TLS trust injection.
  Adds an optional value that, when set, mounts a pre-provisioned
  ConfigMap of PEM CA certs into the nebi pod at
  `/etc/ssl/certs/org-ca.crt` and sets `SSL_CERT_FILE`. Backwards-
  compatible: `helm template` output is byte-identical when the value
  is left at its empty default. Required on clusters with a TLS-
  intercepting egress proxy (pixi/rattler fail with "unknown CA"
  otherwise). Mirrors the pattern in nebari-rayserve-pack#16.

Versioning note: this is a single backwards-compatible feature add.
Strict semver would call for a minor bump (0.2.0); using a patch bump
here matches the project's pre-1.0 convention where the 0.1.0-alpha.N
line rolled feature additions through patch-level increments. Bump to
0.2.0 instead if the maintainer prefers strict semver — the release
workflow keys off whatever is in Chart.yaml.

`appVersion` stays at "0.13" — the nebi image hasn't changed, only
the chart's rendering does.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Expose orgCABundle.configMapName for TLS trust injection

2 participants