Skip to content

fix(preflight): validate pull access to rendered NICo image refs#3681

Open
shayan1995 wants to merge 1 commit into
NVIDIA:mainfrom
shayan1995:snamaghi/issue-3367-preflight-core-image-access
Open

fix(preflight): validate pull access to rendered NICo image refs#3681
shayan1995 wants to merge 1 commit into
NVIDIA:mainfrom
shayan1995:snamaghi/issue-3367-preflight-core-image-access

Conversation

@shayan1995

Copy link
Copy Markdown
Contributor

helm-prereqs/preflight.sh only probed https://<registry>/v2/ for reachability, so preflight passed even when the supplied credentials could not pull the exact NICo Core image setup.sh renders. Setup then installed the full prerequisite stack before failing much later in [6/6] with the nico-api-migrate pre-install job stuck in ImagePullBackOff (#3367).

Preflight now checks manifest access for the exact refs setup.sh will deploy, using the Docker Registry v2 API with the same conventions as setup.sh (${NICO_IMAGE_REGISTRY}/nvmetal-carbide:${NICO_CORE_IMAGE_TAG}, $oauthtoken + REGISTRY_PULL_SECRET), plus any literal registry-qualified image refs found in the core values file (unbound image/exporter, etc.):

  • HEAD /v2/<repo>/manifests/<tag-or-digest>, following the WWW-Authenticate bearer-token flow (authenticated when REGISTRY_PULL_SECRET is set, anonymous otherwise). HEAD does not count against registry pull rate limits.
  • Failures are distinguished as unauthorized/forbidden, tag not found, registry 5xx, and DNS/TLS/connect transport errors, as requested in the issue.
  • Credential and missing-tag failures are hard errors when REGISTRY_PULL_SECRET is set; without a secret they stay warnings, since images may be public, preloaded, or covered by existing imagePullSecrets.
  • If the registry host itself is unreachable, the existing warning is kept and per-image checks are skipped, so air-gapped/preloaded installs are not blocked.
  • Docker Hub shorthand refs (org/image:tag) in values files are skipped since they do not map to a probeable /v2 endpoint; digest-pinned refs are supported.

Related issues

Fixes #3367

Type of Change

  • Add - New feature or capability
  • Change - Changes in existing functionality
  • Fix - Bug fixes
  • Remove - Removed features or deprecated functionality
  • Internal - Internal changes (refactoring, tests, docs, etc.)

Breaking Changes

  • This PR contains breaking changes

Testing

  • Unit tests added/updated
  • Integration tests added/updated
  • Manual testing performed
  • No testing required (docs, internal refactor, etc.)

bash -n clean. Verified against live registries: public image passes via the anonymous bearer flow (ghcr.io, registry-1.docker.io), missing tag returns a 404 hard error, bad credentials on nvcr.io return a 401 hard error, DNS failure is a warning without a secret and an error with one, digest-pinned refs resolve, registry:5000/repo (port but no tag) is rejected, and the values-file collector keeps registry-hosted refs while dropping Hub shorthand, bare names, and comments.

@shayan1995
shayan1995 requested a review from a team as a code owner July 17, 2026 18:27
@copy-pr-bot

copy-pr-bot Bot commented Jul 17, 2026

Copy link
Copy Markdown

This pull request requires additional validation before any workflows can run on NVIDIA's runners.

Pull request vetters can view their responsibilities here.

Contributors can view more details about this message here.

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: e8629954-a31d-48f8-bef7-efebe768cdd9

📥 Commits

Reviewing files that changed from the base of the PR and between 079c679 and d04258c.

📒 Files selected for processing (2)
  • helm-prereqs/README.md
  • helm-prereqs/preflight.sh
🚧 Files skipped from review as they are similar to previous changes (2)
  • helm-prereqs/README.md
  • helm-prereqs/preflight.sh

Summary by CodeRabbit

  • New Features
    • Enhanced preflight checks validate pull access for the exact rendered NICo container image references from core values, including additional literal image references.
    • Registry probing now verifies manifest presence and supports Bearer-token authentication using pull credentials when applicable.
  • Bug Fixes
    • Improved reachability handling: unreachable registries warn and skip per-image validation when appropriate.
    • When core image validation is required and curl is missing, preflight now fails early with a clear error.
  • Documentation
    • Updated Helm prerequisites README to clarify REGISTRY_PULL_SECRET scope and the credential/validation behavior during preflight.

Walkthrough

Preflight check #8 validates pull access to the rendered NICo Core image and additional literal image references. It performs authenticated manifest probes, classifies failures, and handles unreachable registries or missing curl.

Changes

Registry Image Validation

Layer / File(s) Summary
Image reference and issue helpers
helm-prereqs/preflight.sh
Updates check #8 documentation and adds helpers for collecting literal image references, extracting registry credentials, translating curl errors, and recording warnings or errors.
Manifest probing and authentication
helm-prereqs/preflight.sh
Adds HEAD manifest probes, HTTP and transport-status classification, and Bearer-token retrieval with authenticated retries.
Core image access integration
helm-prereqs/preflight.sh, helm-prereqs/README.md
Validates the rendered core image and additional literal references, skips per-image checks for unreachable registries, errors when required validation cannot run without curl, and documents credential and warning behavior.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Preflight as preflight.sh
  participant Curl as curl
  participant Registry
  participant TokenEndpoint
  Preflight->>Curl: HEAD manifest request
  Curl->>Registry: Probe rendered image manifest
  Registry-->>Curl: Status or WWW-Authenticate challenge
  Preflight->>TokenEndpoint: Request Bearer token
  TokenEndpoint-->>Preflight: Return token
  Preflight->>Curl: Retry manifest request with token
  Curl->>Registry: Authenticated manifest probe
  Registry-->>Preflight: Final status
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely summarizes the main change: validating pull access for rendered NICo image refs.
Description check ✅ Passed The description is directly aligned with the patch and explains the preflight pull-access validation changes.
Linked Issues check ✅ Passed The changes satisfy #3367 by checking exact rendered NICo image refs and classifying pull, tag, and network failures.
Out of Scope Changes check ✅ Passed The README update and validation refinements stay within the stated preflight pull-access objective.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 4

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@helm-prereqs/preflight.sh`:
- Around line 286-304: Update the token-response handling in the registry
preflight flow before the `_curl_registry_manifest` retry: explicitly classify
successful 2xx responses with a usable token, 401/403 credential responses, 5xx
transport/service failures, other non-2xx statuses, malformed JSON, and
empty-token responses. Only retry the manifest with `_token` when the token
response is valid; otherwise record the appropriate token-endpoint issue instead
of reusing the manifest’s original 401.
- Around line 322-324: Update the HTTP 404 handling in the preflight image-check
logic to remain non-blocking when REGISTRY_PULL_SECRET is not configured,
emitting the existing warning behavior instead of appending to ERRORS. Preserve
the hard-error behavior for 404 responses when a pull secret is configured.
- Around line 899-902: Update the curl assignment in the registry probe to avoid
appending a second fallback value when curl already outputs HTTP status 000 on
transport failure. Preserve a single 000 result so the existing conditional
warning path is reached.
- Around line 163-175: Update the registry probe flow around
_record_registry_transport_issue and its callers to apply REGISTRY_PULL_SECRET
only when the image reference’s registry host matches the configured target
registry; otherwise probe without that secret or require explicit credentials
for the foreign host. Ensure auth failures and warning/error messages remain
scoped to the specific registry host, including all referenced probe paths.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: cfa84eb5-12f0-4c18-9639-225c79a9395b

📥 Commits

Reviewing files that changed from the base of the PR and between 0cd8acb and 4ffb5bf.

📒 Files selected for processing (1)
  • helm-prereqs/preflight.sh

Comment thread helm-prereqs/preflight.sh
Comment thread helm-prereqs/preflight.sh Outdated
Comment thread helm-prereqs/preflight.sh
Comment thread helm-prereqs/preflight.sh Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@helm-prereqs/README.md`:
- Around line 200-201: Update the secret-handling documentation near the
NICO_IMAGE_REGISTRY probing behavior to state that REGISTRY_PULL_SECRET is sent
only to the configured registry and its trusted WWW-Authenticate Bearer token
service, which may be hosted separately. Remove the stronger host-only wording,
without changing implementation behavior.
- Around line 201-203: Update the image-access behavior description in the
README to limit warning-only findings without a secret to authentication, 404,
server, and transport failures. Explicitly preserve hard errors for malformed
image references, unexpected HTTP responses, and missing curl when validation is
required, while retaining the unreachable-registry behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 0f49bd49-a806-4004-a87b-afb1a27b7c72

📥 Commits

Reviewing files that changed from the base of the PR and between 96a2b7d and 4e56346.

📒 Files selected for processing (2)
  • helm-prereqs/README.md
  • helm-prereqs/preflight.sh
🚧 Files skipped from review as they are similar to previous changes (1)
  • helm-prereqs/preflight.sh

Comment thread helm-prereqs/README.md Outdated
Comment thread helm-prereqs/README.md Outdated
@shayan1995

Copy link
Copy Markdown
Contributor Author

/ok to test 079c679

preflight.sh only probed https://<registry>/v2/ for reachability, so it
passed even when the supplied credentials could not pull the exact NICo
Core image setup.sh renders. Setup then installed the full prereq stack
before failing an hour in with nico-api-migrate stuck in
ImagePullBackOff (NVIDIA#3367).

Preflight now checks manifest access for the exact refs setup.sh will
deploy, using the Docker Registry v2 API with the same conventions as
setup.sh (${NICO_IMAGE_REGISTRY}/nvmetal-carbide:${NICO_CORE_IMAGE_TAG},
$oauthtoken + REGISTRY_PULL_SECRET), plus any literal
registry-qualified image refs found in the core values file:

- HEAD /v2/<repo>/manifests/<tag-or-digest>, following the
  WWW-Authenticate bearer-token flow. HEAD does not count against
  registry pull rate limits. Token-endpoint responses are classified
  (2xx without a usable token, 401/403, other) so a broken token
  service is not misreported as bad credentials.
- REGISTRY_PULL_SECRET is sent only to the NICO_IMAGE_REGISTRY host
  and the Bearer token endpoint it advertises; refs on other hosts
  are probed anonymously so the secret never leaks to unrelated
  registries and no-auth registries simply answer 200.
- Failures are distinguished as unauthorized/forbidden, tag not found,
  registry 5xx, and DNS/TLS/connect transport errors. They are hard
  errors only when credentials apply to the host; otherwise warnings,
  since images may be public, preloaded, or covered by existing
  imagePullSecrets.
- If the registry host itself is unreachable, the existing warning is
  kept and per-image checks are skipped so air-gapped/preloaded
  installs are not blocked. Also fixes the pre-existing host probe:
  curl already prints 000 on transport failure, so '|| echo 000'
  corrupted the value and the unreachable path never triggered.
- Docker Hub shorthand refs (org/image:tag) in values files are
  skipped since they do not map to a probeable /v2 endpoint;
  digest-pinned refs are supported.
- Documented in the script header and helm-prereqs/README.md.

Verified against live registries (anonymous bearer flow, 404, 401
with bad credentials, digest refs, DNS failure, values-file collector
filter) and end-to-end on a fresh 3-node cluster where preflight
validated the exact rendered core image with real credentials.

Fixes NVIDIA#3367

Signed-off-by: Shayan Namaghi <snamaghi@nvidia.com>
@shayan1995
shayan1995 force-pushed the snamaghi/issue-3367-preflight-core-image-access branch from 079c679 to d04258c Compare July 17, 2026 20:52
@github-actions

Copy link
Copy Markdown

🔍 Container Scan Summary

Service Total Critical High Medium Low Other
boot-artifacts-aarch64 3 0 0 3 0 0
boot-artifacts-x86_64 3 0 0 3 0 0
forge-admin-cli-x86_64 259 16 29 79 7 128
machine-validation-runner 532 39 113 184 15 181
machine_validation 532 39 113 184 15 181
machine_validation-aarch64 532 39 113 184 15 181
nvmetal-carbide 532 39 113 184 15 181
TOTAL 2393 172 481 821 67 852

Per-CVE detail lives in the per-service grype-* artifacts (JSON + SARIF). Severity counts only — no CVE IDs published here.

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.

bug: Preflight should validate pull permissions for rendered NICo images

1 participant