fix(dpf): start without the site-wide BMC root credential - #4172
Conversation
Operators set the site-wide BMC root credential through the API, so on a fresh site it does not exist when nico-api first boots. DPF SDK init read it unconditionally and propagated the failure out of setup, aborting the boot before the listener started -- leaving no way to set the credential that would let the next boot succeed. Make the initial read best-effort when a BMC password refresh interval is configured: initialization continues without the Secret and the existing 60s refresh task writes it as soon as the credential appears, so no restart is needed. With no refresh task nothing would ever retry, so there the failure stays fatal. The refresh task could not have recovered as written: create_secret returned early when the Secret already existed, so a rotated password was never propagated to the cluster. Rename it to apply_secret and implement it as a server-side apply, matching apply_configmap. Backport of 2d2eaea onto release/v2.0. The documentation changes from that commit are omitted; release branches do not carry docs. Fixes NVIDIA#4130 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Important Review skippedAuto reviews are disabled on base/target branches other than the default branch. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Enterprise Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
🔐 TruffleHog Secret Scan✅ No secrets or credentials found! Your code has been scanned for 700+ types of secrets and credentials. All clear! 🎉 🕐 Last updated: 2026-07-26 16:44:38 UTC | Commit: b6ef000 |
🔍 Container Scan Summary
Per-CVE detail lives in the per-service |
Backport of #4167 onto
release/v2.0.Operators set the site-wide BMC root credential through the API, so on a fresh
site it does not exist when nico-api first boots. DPF SDK initialization read
that credential unconditionally and propagated the failure out of setup,
aborting the boot before the listener started — which left no way to set the
credential that would have let the next boot succeed. A fresh site with DPF
enabled could not be brought up at all.
This makes the initial read best-effort when a BMC password refresh interval is
configured: initialization continues without the Secret, and the existing 60s
refresh task writes it as soon as the credential appears, so no restart is
needed. With no refresh task configured nothing would ever retry, so there the
failure stays fatal.
The refresh task could not have recovered as written:
create_secretreturnedearly when the Secret already existed, so a rotated password was never
propagated to the cluster. It is renamed to
apply_secretand implemented as aserver-side apply, matching
apply_configmap.All ten source files cherry-picked onto the
release/v2.0base with noconflicts. The documentation changes carried by #4167 are omitted here, as
release branches do not carry docs.
Related issues
#4130
Type of Change
Breaking Changes
Testing
cargo test -p carbide-dpfon this branch: 98 passed, 0 failed. That includesthe four new tests, each confirmed by name — the refresh task writing the Secret
once the password appears, staying unwritten while it is unavailable, and build
succeeding vs. failing when the password is unset with and without a refresh
interval configured.
The equivalent change on
mainwas additionally verified against a local kindcluster running the DPF operator, with nico-api pointed at a Vault mount holding
the UEFI site defaults but no
machines/bmc/site/root. Startup reached DPF SDKinitialization instead of aborting at the credential read:
That verification was performed on the
main-based branch, not on thisrelease/v2.0backport.Additional Notes
The repository pre-commit hook and
pre-commit-verify-workspaceboth invokecargo xtask lint-error-messages, which does not exist onrelease/v2.0, soneither could run against this branch. CI is the first lint signal here.
🤖 Generated with Claude Code