fix(bundler): redact the flag value when the CRD step rejects it - #2856
Conversation
Recipe evidence checkNo leaf overlays affected by this PR. This gate is warning-only and never blocks merge. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository: NVIDIA/aicr/.coderabbit.yaml Review profile: ASSERTIVE Plan: Enterprise Run ID: 📒 Files selected for processing (5)
Included review availability: Your plan provides up to 12 included reviews per hour; 10 remain after this review. 📝 WalkthroughWalkthroughThe CRD application template now reports only unsupported option names and omits option values from diagnostics. Tests cover joined and separated secret values and verify that sensitive values do not appear in generated output. Rendered scripts and Helm documentation describe support for only Priority: ➖ Normal Estimated code review effort: 2 (Simple) | ~10 minutes Change: Bug fix Suggested reviewers: 🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
|
@mchmarny this PR now has merge conflicts with |
The catch-all echoed the whole token. helm's --kube-token carries a
bearer token in its joined form, and deploy.sh runs install.sh with
output attached to the terminal and to CI logs, then retries it, so
`--kube-token=<bearer>` was printed verbatim and repeated.
kubectl reports an unknown flag by name alone, so the unpatched path
never disclosed the value. Translating the flags introduced this, which
makes it a regression of the change that added the parser rather than
anything inherited.
Print `${helm_conn[0]%%=*}`: the option, never its argument. The
separated form already stopped on the flag name, so only the joined
form leaked; both are covered now.
Correct the reason the message gives, in all three places it appears.
Several rejected flags do have kubectl equivalents -- --kube-token is
--token, --kube-apiserver is --server -- so "no known kubectl spelling"
was false in the message, in the block comment above the parser, and in
the generated README. Not translating them is a scope boundary, and an
error that misstates its own reason sends a reader looking for a flag
that exists.
Name the supported spellings in the error too. An operator reading it
in a CI log otherwise has to find the bundle README to learn what to
put in KUBECONFIG_FLAG instead. "Refuses to guess" is dropped with the
ambiguity framing it belonged to.
The rejection rows asserted exit status only, so nothing guarded the
output; they now also assert the argument is absent. Verified by
restoring the unredacted expansion, which fails the joined row. The
separated row guards a different future change: word-splitting already
keeps the value out of helm_conn[0], so it holds either way.
Signed-off-by: Mark Chmarny <mark@chmarny.com>
Coverage Report ✅
Coverage BadgeNo Go source files changed in this PR. |
e69aac2 to
4c9ce35
Compare
deploy.sh exported KUBECONFIG_FLAG for helm but passed no context to its own kubectl calls. With KUBECONFIG_FLAG="--kube-context prod-b" and an ambient context of prod-a, helm installed releases into prod-b while deploy.sh deleted Jobs, removed node taints and restarted DaemonSets on prod-a. Those call sites are 2>/dev/null || true, so nothing reported it. Callers now export KUBE_CONTEXT and KUBECONFIG, and each generated script renders the flag its own binary spells. The prologue lives once and is rendered into deploy.sh, both install.sh templates and apply-crds.sh, because each is a documented standalone entry point and cannot depend on a sibling file written by whichever deployer assembled the bundle. KUBECONFIG_FLAG is still accepted and translated, with a warning. An option it does not translate, a missing or option-shaped value, an empty joined value, or a context disagreeing with KUBE_CONTEXT all exit before the first cluster call: a dropped connection option is indistinguishable from one never set, and the fallback is the ambient context. Rejection messages name the option but never its argument, so a flag carrying a credential does not reach the log. Related: #2849, #2856 Signed-off-by: Brian Lockwood <lockwobr@gmail.com>
deploy.sh exported KUBECONFIG_FLAG for helm but passed no context to its own kubectl calls. With KUBECONFIG_FLAG="--kube-context prod-b" and an ambient context of prod-a, helm installed releases into prod-b while deploy.sh deleted Jobs, removed node taints and restarted DaemonSets on prod-a. Those call sites are 2>/dev/null || true, so nothing reported it. Callers now export KUBE_CONTEXT and KUBECONFIG, and each generated script renders the flag its own binary spells. The prologue lives once and is rendered into deploy.sh, both install.sh templates and apply-crds.sh, because each is a documented standalone entry point and cannot depend on a sibling file written by whichever deployer assembled the bundle. KUBECONFIG_FLAG is still accepted and translated, with a warning. An option it does not translate, a missing or option-shaped value, an empty joined value, or a context disagreeing with KUBE_CONTEXT all exit before the first cluster call: a dropped connection option is indistinguishable from one never set, and the fallback is the ambient context. Rejection messages name the option but never its argument, so a flag carrying a credential does not reach the log. Related: #2849, #2856 Signed-off-by: Brian Lockwood <lockwobr@gmail.com>
deploy.sh exported KUBECONFIG_FLAG for helm but passed no context to its own kubectl calls. With KUBECONFIG_FLAG="--kube-context prod-b" and an ambient context of prod-a, helm installed releases into prod-b while deploy.sh deleted Jobs, removed node taints and restarted DaemonSets on prod-a. Those call sites are 2>/dev/null || true, so nothing reported it. Callers now export KUBE_CONTEXT and KUBECONFIG, and each generated script renders the flag its own binary spells. The prologue lives once and is rendered into deploy.sh, both install.sh templates and apply-crds.sh, because each is a documented standalone entry point and cannot depend on a sibling file written by whichever deployer assembled the bundle. KUBECONFIG_FLAG is still accepted and translated, with a warning. An option it does not translate, a missing or option-shaped value, an empty joined value, or a context disagreeing with KUBE_CONTEXT all exit before the first cluster call: a dropped connection option is indistinguishable from one never set, and the fallback is the ambient context. Rejection messages name the option but never its argument, so a flag carrying a credential does not reach the log. Related: #2849, #2856 Signed-off-by: Brian Lockwood <lockwobr@gmail.com>
deploy.sh exported KUBECONFIG_FLAG for helm but passed no context to its own kubectl calls. With KUBECONFIG_FLAG="--kube-context prod-b" and an ambient context of prod-a, helm installed releases into prod-b while deploy.sh deleted Jobs, removed node taints and restarted DaemonSets on prod-a. Those call sites are 2>/dev/null || true, so nothing reported it. Callers now export KUBE_CONTEXT and KUBECONFIG, and each generated script renders the flag its own binary spells. The prologue lives once and is rendered into deploy.sh, both install.sh templates and apply-crds.sh, because each is a documented standalone entry point and cannot depend on a sibling file written by whichever deployer assembled the bundle. KUBECONFIG_FLAG is still accepted and translated, with a warning. An option it does not translate, a missing or option-shaped value, an empty joined value, or a context disagreeing with KUBE_CONTEXT all exit before the first cluster call: a dropped connection option is indistinguishable from one never set, and the fallback is the ambient context. Rejection messages name the option but never its argument, so a flag carrying a credential does not reach the log. Related: #2849, #2856 Signed-off-by: Brian Lockwood <lockwobr@gmail.com>
deploy.sh exported KUBECONFIG_FLAG for helm but passed no context to its own kubectl calls. With KUBECONFIG_FLAG="--kube-context prod-b" and an ambient context of prod-a, helm installed releases into prod-b while deploy.sh deleted Jobs, removed node taints and restarted DaemonSets on prod-a. Those call sites are 2>/dev/null || true, so nothing reported it. Callers now export KUBE_CONTEXT and KUBECONFIG, and each generated script renders the flag its own binary spells. The prologue lives once and is rendered into deploy.sh, both install.sh templates and apply-crds.sh, because each is a documented standalone entry point and cannot depend on a sibling file written by whichever deployer assembled the bundle. KUBECONFIG_FLAG is still accepted and translated, with a warning. An option it does not translate, a missing or option-shaped value, an empty joined value, or a context disagreeing with KUBE_CONTEXT all exit before the first cluster call: a dropped connection option is indistinguishable from one never set, and the fallback is the ambient context. Rejection messages name the option but never its argument, so a flag carrying a credential does not reach the log. Related: #2849, #2856 Signed-off-by: Brian Lockwood <lockwobr@gmail.com>
Summary
The CRD step's catch-all echoed the whole rejected token. helm's
--kube-tokencarries a bearer token in its joined form, so
--kube-token=<bearer>wasprinted verbatim. Print the option name only.
Motivation / Context
Follow-up to review feedback on #2849
(#2849 (review)), raised
as non-blocking and deferred to a separate PR.
deploy.shrunsinstall.shwith its output attached to the terminal and to CIlogs, inside a retry loop, so a disclosed token is both logged and repeated.
kubectl reports an unknown flag by name alone (
error: unknown flag: --kube-token), so the pre-#2849 path never disclosed the value — this is aregression #2849 introduced, not an inherited gap.
Fixes: N/A
Related: #2849
Type of Change
Component(s) Affected
cmd/aicr,pkg/cli)cmd/aicrd,pkg/server)pkg/recipe)pkg/bundler,pkg/component/*)pkg/collector,pkg/snapshotter)pkg/validator)pkg/errors,pkg/k8s)docs/,examples/)Implementation Notes
Only the joined form leaked. The separated form (
--kube-token SECRET)already stopped on the flag name, exiting before the value was reached. Both are
covered by tests regardless, since the asymmetry is not obvious from the code.
The message also misstated its own reason. "No known kubectl spelling" is
false:
--kube-tokenis--token,--kube-apiserveris--server,--kube-ca-fileis--certificate-authority. Not translating them is a scopedecision. An error that misstates its reason sends a reader looking for a flag
that exists, so it now says the step does not support them. The generated bundle
README matches.
The
GatesAndBoundspin was repointed, not dropped. The wording change brokeits old pin. It now pins
${helm_conn[0]%%=*}, so removing the redaction failsthe unit suite rather than only the new row.
Testing
make qualify # exit 0, 8m37s-race)Rendered script, all three shapes — no value in any:
KUBECONFIG_FLAG--kube-token=SUPERSECRETcarries '--kube-token'--kube-token SUPERSECRETcarries '--kube-token'--kube-apiserver=https://secret.internalcarries '--kube-apiserver'Two new rows in
TestApplyCRDsScript_TranslatesHelmConnectionFlagsassert themarker value is absent from captured output; the existing rejection rows checked
exit status only. Mutation-verified: restoring
${helm_conn[0]}fails thejoined row.
No production Go code changed — the only
.goedit is test assertions.Risk Assessment
Rollout notes: None. Operators who hit the old message see the same failure
with the argument removed.
Checklist
make testwith-race)make lint)git commit -S)