Skip to content

fix(webhook): reuse Helm-native serving cert on upgrade - #218

Open
giuliocalzo wants to merge 1 commit into
SlinkyProject:mainfrom
giuliocalzo:fix/webhook-cert-reuse-on-upgrade
Open

fix(webhook): reuse Helm-native serving cert on upgrade#218
giuliocalzo wants to merge 1 commit into
SlinkyProject:mainfrom
giuliocalzo:fix/webhook-cert-reuse-on-upgrade

Conversation

@giuliocalzo

@giuliocalzo giuliocalzo commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Summary

When certManager.enabled=false, the operator chart generates the webhook serving certificate in Helm using Sprig's genCA/genSignedCert. Because those functions produce fresh material on every render, each helm upgrade rotated the CA, the serving cert, and the injected caBundle. The running webhook pod is not restarted on upgrade (no checksum annotation), so it kept serving the old cert while the API server was updated to trust only the new CA — breaking admission until the pod was manually rolled.

This PR makes the Helm-native path reuse the existing certificate:

  • lookup the existing TLS Secret; if it has a complete cert (tls.crt/tls.key/ca.crt), reuse it verbatim for both the Secret and the injected caBundle.
  • Regenerate only when the Secret is missing/incomplete — i.e. first install, or helm template/--dry-run where lookup returns an empty map.
  • The CA stored in the Secret and the CA injected as caBundle come from the same source, so they stay consistent within a render.

cert-manager mode (certManager.enabled=true, the default) is unchanged.

Checklist

  • I have read CONTRIBUTING.md and the Code of Conduct.
  • New or existing tests cover these changes (where applicable).
  • Documentation is updated if user-visible behavior changes.

Breaking Changes

None. cert-manager mode (the default) is unchanged, and the Helm-native path now preserves existing certificate material across upgrades instead of rotating it.

Testing Notes

  • helm template with certManager.enabled=false: single TLS Secret, one unique caBundle, Secret.ca.crt == caBundle.
  • helm template with certManager.enabled=true: no native Secret/caBundle, cert-manager Issuer/Certificate + inject annotations present (default snapshot unchanged).
  • helm unittest ./helm/slurm-operator: 105 tests / 12 snapshots pass, including:
    • generation on first install (base64 PEM material, caBundle on every webhook, no cert-manager annotations),
    • verbatim reuse of an existing Secret mocked via kubernetesProvider,
    • cert-manager-enabled path renders no native Secret/caBundle.
  • helm lint passes with cert-manager both enabled and disabled.

Additional Context

Fixes broken admission after helm upgrade in the Helm-native (non cert-manager) certificate mode.

When cert-manager is disabled, the chart generates the webhook serving
certificate with genCA/genSignedCert. These regenerate on every render,
so each `helm upgrade` rotated the CA/cert and the injected caBundle
while the running webhook pod kept serving the old cert, breaking
admission until the pod was restarted.

Look up the existing TLS Secret and reuse its cert/CA when present,
regenerating only when the Secret is missing or incomplete (first
install, or `helm template`/`--dry-run` where lookup returns empty).

Add helm-unittest coverage for both branches: PEM generation on first
install, and verbatim reuse via a kubernetesProvider-mocked Secret.

Signed-off-by: Giulio Calzolari <gcalzolari@nvidia.com>
@vivian-hafener

Copy link
Copy Markdown
Contributor

Good afternoon @giuliocalzo,

I will look into this.

Best,
Vivian Hafener

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.

3 participants