Skip to content

AGENT-1448: Add IRI registry authentication support#10389

Open
rwsu wants to merge 1 commit intoopenshift:mainfrom
rwsu:AGENT-1448
Open

AGENT-1448: Add IRI registry authentication support#10389
rwsu wants to merge 1 commit intoopenshift:mainfrom
rwsu:AGENT-1448

Conversation

@rwsu
Copy link
Contributor

@rwsu rwsu commented Mar 12, 2026

Add authentication credentials for the Internal Release Image (IRI) registry.

New assets:

  • IRIRegistryAuth: In-memory-only asset that generates a random password and bcrypt htpasswd for the IRI registry. Not written to disk to avoid interfering with assisted-service's auth/ directory cleanup.
  • InternalReleaseImageRegistryAuthSecret: Bootkube manifest template that creates the openshift-machine-config-operator/internal-release- image-registry-auth Secret containing the htpasswd and password.

Pull secret integration:

  • Merge IRI registry credentials (openshift:) into the global pull secret during bootstrap ignition generation so that kubelet/CRI-O can authenticate to the IRI registry on master nodes at api-int.:22625.

Assisted-By: Claude Opus 4.6 noreply@anthropic.com

Summary by CodeRabbit

  • New Features

    • Adds generation of internal release-image registry credentials (username, password, htpasswd) and provides a registry-auth secret template.
    • When enabled, merges these credentials into the cluster pull secret used during bootstrap so nodes can authenticate to the internal registry.
  • Tests

    • Adds tests covering credential generation, encoding, htpasswd formatting, conditional (feature-gated) behavior, and merge handling during bootstrap.

@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Mar 12, 2026
@openshift-ci-robot
Copy link
Contributor

openshift-ci-robot commented Mar 12, 2026

@rwsu: This pull request references AGENT-1448 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "4.22.0" version, but no target version was set.

Details

In response to this:

Add authentication credentials for the Internal Release Image (IRI) registry.

New assets:

  • IRIRegistryAuth: In-memory-only asset that generates a random password and bcrypt htpasswd for the IRI registry. Not written to disk to avoid interfering with assisted-service's auth/ directory cleanup.
  • InternalReleaseImageRegistryAuthSecret: Bootkube manifest template that creates the openshift-machine-config-operator/internal-release- image-registry-auth Secret containing the htpasswd and password.

Pull secret integration:

  • Merge IRI registry credentials (openshift:) into the global pull secret during bootstrap ignition generation so that kubelet/CRI-O can authenticate to the IRI registry on master nodes at api-int.:22625.

Assisted-By: Claude Opus 4.6 noreply@anthropic.com

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@coderabbitai
Copy link

coderabbitai bot commented Mar 12, 2026

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

Walkthrough

Adds an in-memory IRI registry credential asset, a bootkube secret template asset, merges IRI credentials into the bootstrap pull secret, registers the new assets in manifests/targets, and updates tests to cover generation and absent-on-disk behavior.

Changes

Cohort / File(s) Summary
IRI Registry Credential Asset
pkg/asset/tls/iriregistryauth.go, pkg/asset/tls/iriregistryauth_test.go
New in-memory IRIRegistryAuth asset that generates Username, base64 Password, and htpasswd (bcrypt) when InternalReleaseImage exists and the feature gate allows; includes unit tests validating generation, formats, and Load/Name behavior.
Bootkube Secret Template Asset
data/data/manifests/bootkube/internal-release-image-registry-auth-secret.yaml.template, pkg/asset/templates/content/bootkube/internal-release-image-registry-auth-secret.go
Adds a bootkube secret template file and a WritableAsset (InternalReleaseImageRegistryAuthSecret) that loads and emits the template under content.TemplateDir when generation is enabled and InternalReleaseImage is present.
Bootstrap pull-secret merging
pkg/asset/ignition/bootstrap/common.go
Reads tls.IRIRegistryAuth credentials, constructs the IRI registry host, and merges base64(username:password) into the bootstrap pullSecret via new mergeIRIAuthIntoPullSecret helper; integrates merged pullSecret into template data and logs on merge failures.
Manifests & Targets registration
pkg/asset/manifests/operators.go, pkg/asset/targets/targets.go
Registers tls.IRIRegistryAuth and bootkube.InternalReleaseImageRegistryAuthSecret as dependencies; adds appendIRIRegistryAuth to render the registry-auth secret template and include it alongside IRI certs in generated bootkube manifests.
Tests / Asset store update
pkg/asset/store/assetcreate_test.go
Updates asset creation tests to mark InternalReleaseImageRegistryAuthSecret absent on disk under the same NoRegistryClusterInstall condition as the IRI TLS secret.

Sequence Diagram(s)

sequenceDiagram
  participant Generator as IRIRegistryAuth
  participant TemplateAsset as InternalReleaseImageRegistryAuthSecret
  participant Bootstrap as Ignition Bootstrap
  participant Manifests as Operators Manifests
  participant Registry as IRI Registry

  Generator->>Generator: generate username, password, htpasswd
  Generator-->>TemplateAsset: expose Username, Password, HtpasswdContent (in-memory)
  TemplateAsset->>Manifests: emit secret template (template vars: htpasswd, password)
  Generator->>Bootstrap: provide Username & Password via asset dependency
  Bootstrap->>Bootstrap: merge base64(username:password) into pullSecret for Registry host
  Bootstrap->>Registry: bootstrap uses merged pullSecret to authenticate
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes


Important

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Stable And Deterministic Test Names ❓ Inconclusive Unable to directly access test file content to verify stable and deterministic test names in Ginkgo tests. Provide access to complete test file content including all Ginkgo It/Describe/Context calls to verify no dynamic values in test titles.
✅ Passed checks (6 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and directly summarizes the main change: adding authentication support for the Internal Release Image (IRI) registry, which is the central focus across all modified files.
Test Structure And Quality ✅ Passed PR uses standard Go testing, not Ginkgo. Tests follow Go conventions with mostly comprehensive assertion messages and single responsibilities.
Microshift Test Compatibility ✅ Passed This PR does not add any Ginkgo e2e tests; only standard Go unit tests for asset generation are included.
Single Node Openshift (Sno) Test Compatibility ✅ Passed No Ginkgo e2e tests present in PR; test files are standard Go unit tests incompatible with SNO checks.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed PR adds only standard Go unit tests, not Ginkgo e2e tests. Check does not apply to this PR.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
📝 Coding Plan
  • Generate coding plan for human review comments

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.11.3)

Error: can't load config: unsupported version of the configuration: "" See https://golangci-lint.run/docs/product/migration-guide for migration instructions
The command is terminated due to an error: can't load config: unsupported version of the configuration: "" See https://golangci-lint.run/docs/product/migration-guide for migration instructions


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

@openshift-ci openshift-ci bot requested review from bfournie and rna-afk March 12, 2026 19:45
@openshift-ci
Copy link
Contributor

openshift-ci bot commented Mar 12, 2026

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by:
Once this PR has been reviewed and has the lgtm label, please assign tthvo for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@openshift-ci-robot
Copy link
Contributor

openshift-ci-robot commented Mar 12, 2026

@rwsu: This pull request references AGENT-1448 which is a valid jira issue.

Details

In response to this:

Add authentication credentials for the Internal Release Image (IRI) registry.

New assets:

  • IRIRegistryAuth: In-memory-only asset that generates a random password and bcrypt htpasswd for the IRI registry. Not written to disk to avoid interfering with assisted-service's auth/ directory cleanup.
  • InternalReleaseImageRegistryAuthSecret: Bootkube manifest template that creates the openshift-machine-config-operator/internal-release- image-registry-auth Secret containing the htpasswd and password.

Pull secret integration:

  • Merge IRI registry credentials (openshift:) into the global pull secret during bootstrap ignition generation so that kubelet/CRI-O can authenticate to the IRI registry on master nodes at api-int.:22625.

Assisted-By: Claude Opus 4.6 noreply@anthropic.com

Summary by CodeRabbit

  • New Features

  • Added internal image registry authentication support, enabling secure credential management for internal release image registries used during cluster deployment.

  • Tests

  • Comprehensive test coverage for registry authentication functionality, including credential generation, encoding, and validation.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

Copy link

@coderabbitai coderabbitai bot left a comment

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 the current code and only fix it if needed.

Inline comments:
In `@pkg/asset/targets/targets.go`:
- Line 63: ManifestTemplates is missing the new bootkube asset for registry
auth; add the bootkube.InternalReleaseImageRegistryAuthSecret asset to the
ManifestTemplates slice (alongside &tls.IRIRegistryAuth{}) so the registry-auth
template is emitted by "openshift-install create manifest-templates"; locate the
ManifestTemplates declaration in targets.go and append
&bootkube.InternalReleaseImageRegistryAuthSecret{} to that slice.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 81c52f52-cdb5-4293-b8d8-6844615db77a

📥 Commits

Reviewing files that changed from the base of the PR and between b9c6f8e and d8649ac.

📒 Files selected for processing (7)
  • data/data/manifests/bootkube/internal-release-image-registry-auth-secret.yaml.template
  • pkg/asset/ignition/bootstrap/common.go
  • pkg/asset/manifests/operators.go
  • pkg/asset/targets/targets.go
  • pkg/asset/templates/content/bootkube/internal-release-image-registry-auth-secret.go
  • pkg/asset/tls/iriregistryauth.go
  • pkg/asset/tls/iriregistryauth_test.go

@openshift-ci-robot
Copy link
Contributor

openshift-ci-robot commented Mar 12, 2026

@rwsu: This pull request references AGENT-1448 which is a valid jira issue.

Details

In response to this:

Add authentication credentials for the Internal Release Image (IRI) registry.

New assets:

  • IRIRegistryAuth: In-memory-only asset that generates a random password and bcrypt htpasswd for the IRI registry. Not written to disk to avoid interfering with assisted-service's auth/ directory cleanup.
  • InternalReleaseImageRegistryAuthSecret: Bootkube manifest template that creates the openshift-machine-config-operator/internal-release- image-registry-auth Secret containing the htpasswd and password.

Pull secret integration:

  • Merge IRI registry credentials (openshift:) into the global pull secret during bootstrap ignition generation so that kubelet/CRI-O can authenticate to the IRI registry on master nodes at api-int.:22625.

Assisted-By: Claude Opus 4.6 noreply@anthropic.com

Summary by CodeRabbit

  • New Features

  • Adds internal release-image registry authentication: generates and provides htpasswd and password credentials, and optionally merges them into the cluster pull secret for bootstrap.

  • Tests

  • Adds comprehensive tests covering credential generation, encoding, htpasswd formatting, validation, and conditional generation behavior.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

♻️ Duplicate comments (1)
pkg/asset/tls/iriregistryauth.go (1)

50-82: ⚠️ Potential issue | 🔴 Critical

These credentials still rotate between installer invocations.

Generate() always creates a fresh password and Load() never restores the previous one. In the standard create manifestscreate ignition-configs flow, pkg/asset/manifests/operators.go persists one password into manifests/internal-release-image-registry-auth-secret.yaml, while pkg/asset/ignition/bootstrap/common.go later merges a different password into the pull secret. That leaves the Secret and pull secret out of sync and breaks registry auth. Please reload the existing credential here, or derive it from the persisted manifest, and add a regression test for that two-step workflow.

Also applies to: 90-97

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/asset/tls/iriregistryauth.go` around lines 50 - 82, The Generate method
in IRIRegistryAuth (Generate) always creates a new password, causing creds to
rotate because Load never restores persisted values; change Generate to first
attempt to load an existing credential (via the asset Load method or by reading
the persisted InternalReleaseImage registry auth secret manifest used by
manifests/internal-release-image-registry-auth-secret.yaml) and only generate a
new password if none exists, or alternatively derive the password from the
persisted manifest, and ensure Load restores a.Password/HtpasswdContent when
present; also add a regression test that runs the two-step flow (create
manifests -> create ignition-configs) to confirm the same credential is used
across both steps.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Duplicate comments:
In `@pkg/asset/tls/iriregistryauth.go`:
- Around line 50-82: The Generate method in IRIRegistryAuth (Generate) always
creates a new password, causing creds to rotate because Load never restores
persisted values; change Generate to first attempt to load an existing
credential (via the asset Load method or by reading the persisted
InternalReleaseImage registry auth secret manifest used by
manifests/internal-release-image-registry-auth-secret.yaml) and only generate a
new password if none exists, or alternatively derive the password from the
persisted manifest, and ensure Load restores a.Password/HtpasswdContent when
present; also add a regression test that runs the two-step flow (create
manifests -> create ignition-configs) to confirm the same credential is used
across both steps.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 451bd7d6-2968-41a3-b1a0-3c2b26a37d52

📥 Commits

Reviewing files that changed from the base of the PR and between d8649ac and b252ebb.

📒 Files selected for processing (7)
  • data/data/manifests/bootkube/internal-release-image-registry-auth-secret.yaml.template
  • pkg/asset/ignition/bootstrap/common.go
  • pkg/asset/manifests/operators.go
  • pkg/asset/targets/targets.go
  • pkg/asset/templates/content/bootkube/internal-release-image-registry-auth-secret.go
  • pkg/asset/tls/iriregistryauth.go
  • pkg/asset/tls/iriregistryauth_test.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • pkg/asset/tls/iriregistryauth_test.go
  • data/data/manifests/bootkube/internal-release-image-registry-auth-secret.yaml.template

@openshift-ci-robot
Copy link
Contributor

openshift-ci-robot commented Mar 12, 2026

@rwsu: This pull request references AGENT-1448 which is a valid jira issue.

Details

In response to this:

Add authentication credentials for the Internal Release Image (IRI) registry.

New assets:

  • IRIRegistryAuth: In-memory-only asset that generates a random password and bcrypt htpasswd for the IRI registry. Not written to disk to avoid interfering with assisted-service's auth/ directory cleanup.
  • InternalReleaseImageRegistryAuthSecret: Bootkube manifest template that creates the openshift-machine-config-operator/internal-release- image-registry-auth Secret containing the htpasswd and password.

Pull secret integration:

  • Merge IRI registry credentials (openshift:) into the global pull secret during bootstrap ignition generation so that kubelet/CRI-O can authenticate to the IRI registry on master nodes at api-int.:22625.

Assisted-By: Claude Opus 4.6 noreply@anthropic.com

Summary by CodeRabbit

  • New Features

  • Adds internal release-image registry authentication: generates htpasswd and password credentials for the internal registry and, when applicable, merges them into the cluster pull secret used during bootstrap.

  • Tests

  • Adds tests validating credential generation, encoding, htpasswd formatting, and conditional generation/merge behavior.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
pkg/asset/manifests/operators.go (1)

234-241: ⚠️ Potential issue | 🟠 Major

Propagate the merged pull secret into the bootkube pull-secret manifest too.

This branch adds the registry-auth Secret, but the bootkube template data is still built from the unmodified install-config pull secret. The generated openshift-config-secret-pull-secret manifest therefore goes out without the api-int.<clusterDomain>:22625 auth entry, so the IRI credentials never reach the cluster-wide pull secret. Please merge the IRI auth before populating PullSecretBase64 as well, ideally via a shared helper instead of keeping the merge logic only in pkg/asset/ignition/bootstrap/common.go.

Also applies to: 270-291

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/asset/manifests/operators.go` around lines 234 - 241, The bootkube
pull-secret manifest is still built from the original install-config pull secret
so IRI credentials never make it into the cluster pull secret; update
operators.go to merge the InternalReleaseImage registry auth into the
install-config pull secret before creating the bootkube template data (the value
used for PullSecretBase64) by reusing the same merge helper used in
pkg/asset/ignition/bootstrap/common.go (or extract that merge into a shared
helper), and ensure this merged secret is used when producing the
bootkube/openshift-config-secret-pull-secret manifest (references:
InternalReleaseImage, appendIRIRegistryAuth, appendIRIcerts, PullSecretBase64).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@pkg/asset/manifests/operators.go`:
- Around line 234-241: The bootkube pull-secret manifest is still built from the
original install-config pull secret so IRI credentials never make it into the
cluster pull secret; update operators.go to merge the InternalReleaseImage
registry auth into the install-config pull secret before creating the bootkube
template data (the value used for PullSecretBase64) by reusing the same merge
helper used in pkg/asset/ignition/bootstrap/common.go (or extract that merge
into a shared helper), and ensure this merged secret is used when producing the
bootkube/openshift-config-secret-pull-secret manifest (references:
InternalReleaseImage, appendIRIRegistryAuth, appendIRIcerts, PullSecretBase64).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 88a78d10-6306-4e0b-80aa-ebdb801f3997

📥 Commits

Reviewing files that changed from the base of the PR and between b252ebb and e884fa1.

📒 Files selected for processing (8)
  • data/data/manifests/bootkube/internal-release-image-registry-auth-secret.yaml.template
  • pkg/asset/ignition/bootstrap/common.go
  • pkg/asset/manifests/operators.go
  • pkg/asset/store/assetcreate_test.go
  • pkg/asset/targets/targets.go
  • pkg/asset/templates/content/bootkube/internal-release-image-registry-auth-secret.go
  • pkg/asset/tls/iriregistryauth.go
  • pkg/asset/tls/iriregistryauth_test.go
🚧 Files skipped from review as they are similar to previous changes (2)
  • pkg/asset/tls/iriregistryauth_test.go
  • data/data/manifests/bootkube/internal-release-image-registry-auth-secret.yaml.template

@openshift-ci-robot
Copy link
Contributor

openshift-ci-robot commented Mar 12, 2026

@rwsu: This pull request references AGENT-1448 which is a valid jira issue.

Details

In response to this:

Add authentication credentials for the Internal Release Image (IRI) registry.

New assets:

  • IRIRegistryAuth: In-memory-only asset that generates a random password and bcrypt htpasswd for the IRI registry. Not written to disk to avoid interfering with assisted-service's auth/ directory cleanup.
  • InternalReleaseImageRegistryAuthSecret: Bootkube manifest template that creates the openshift-machine-config-operator/internal-release- image-registry-auth Secret containing the htpasswd and password.

Pull secret integration:

  • Merge IRI registry credentials (openshift:) into the global pull secret during bootstrap ignition generation so that kubelet/CRI-O can authenticate to the IRI registry on master nodes at api-int.:22625.

Assisted-By: Claude Opus 4.6 noreply@anthropic.com

Summary by CodeRabbit

  • New Features

  • Adds internal release-image registry authentication: generates a username, password, and htpasswd entry, exposes a template for the registry auth secret, and (when enabled) merges credentials into the cluster pull secret used during bootstrap.

  • Tests

  • Adds tests verifying credential generation, encoding, htpasswd formatting, conditional generation, and merge behavior.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (4)
pkg/asset/ignition/bootstrap/common.go (2)

719-719: Remove unnecessary entry - IRIRegistryAuth.Files() returns empty.

Since IRIRegistryAuth is an in-memory-only asset that returns an empty Files() slice, including it in addParentFiles has no effect. The asset is already fetched in getTemplateData (line 389) where its credentials are used. This entry adds confusion about what files are being embedded.

♻️ Suggested removal
 		&tls.MCSCertKey{},
 		&tls.IRICertKey{},
-		&tls.IRIRegistryAuth{},
 		&tls.ServiceAccountKeyPair{},
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/asset/ignition/bootstrap/common.go` at line 719, Remove the unnecessary
&tls.IRIRegistryAuth{} entry from the addParentFiles call:
IRIRegistryAuth.Files() returns an empty slice and the asset is already accessed
in getTemplateData for credentials, so deleting this entry clarifies intent and
avoids embedding a no-op asset; update any nearby comments if present that imply
this asset is being embedded and ensure references to IRIRegistryAuth remain
only where credentials are read (getTemplateData).

426-449: Consider handling missing auths field more gracefully.

If the pull secret has a null or missing auths field (edge case with malformed input), the function returns an error. Consider initializing an empty auths map instead, which would make the merge more robust.

♻️ Suggested defensive handling
 	auths, ok := pullSecretMap["auths"].(map[string]interface{})
 	if !ok {
-		return "", fmt.Errorf("pull secret missing 'auths' field")
+		auths = make(map[string]interface{})
+		pullSecretMap["auths"] = auths
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/asset/ignition/bootstrap/common.go` around lines 426 - 449, The function
mergeIRIAuthIntoPullSecret currently errors if pullSecretMap["auths"] is missing
or not a map; instead, detect when "auths" is absent or nil and initialize auths
as an empty map[string]interface{} before inserting the registry entry (operate
on the local variable auths and assign it back to pullSecretMap["auths"] if you
create it), so the function accepts pull secrets without an existing auths block
while preserving existing auths and still returning the merged JSON or errors on
marshal/unmarshal failures.
pkg/asset/tls/iriregistryauth_test.go (1)

159-162: Consider using k8s.io/utils/ptr.To for consistency.

The codebase already imports k8s.io/utils/ptr in other files (e.g., common.go uses ptr.To). Using the standard utility would align with the rest of the codebase.

♻️ Suggested refactor
+import "k8s.io/utils/ptr"
+
 // In test setup:
-Replicas: pointer(int64(3)),
+Replicas: ptr.To(int64(3)),
-
-// pointer returns a pointer to the given value
-func pointer(i int64) *int64 {
-	return &i
-}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/asset/tls/iriregistryauth_test.go` around lines 159 - 162, The test
defines a local helper function pointer(i int64) *int64; replace usages of this
helper with the standard k8s utility ptr.To to be consistent with the codebase:
remove the pointer function, add/import "k8s.io/utils/ptr" if not already
imported in pkg/asset/tls/iriregistryauth_test.go, and change calls like
pointer(x) to ptr.To(x) (refers to the pointer helper function name "pointer"
and test code usages).
pkg/asset/manifests/operators.go (1)

239-242: Implicit coupling between IRI assets - consider adding a defensive check.

The guard len(iri.FileList) > 0 ensures InternalReleaseImage exists, but appendIRIRegistryAuth assumes iriAuthSecret.Files() is non-empty (line 276). While this holds because InternalReleaseImageRegistryAuthSecret.Generate uses the same guard, the coupling is implicit.

Consider adding a defensive check for robustness:

♻️ Optional defensive check
 		if len(iri.FileList) > 0 {
 			files = append(files, appendIRIcerts(dependencies))
-			files = append(files, appendIRIRegistryAuth(dependencies))
+			if authFile := appendIRIRegistryAuth(dependencies); authFile != nil {
+				files = append(files, authFile)
+			}
 		}

And in appendIRIRegistryAuth:

 func appendIRIRegistryAuth(dependencies asset.Parents) *asset.File {
 	iriAuth := &tls.IRIRegistryAuth{}
 	iriAuthSecret := &bootkube.InternalReleaseImageRegistryAuthSecret{}
 	dependencies.Get(iriAuth, iriAuthSecret)
 
+	if len(iriAuthSecret.Files()) == 0 {
+		return nil
+	}
 	f := iriAuthSecret.Files()[0]
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/asset/manifests/operators.go` around lines 239 - 242, The code implicitly
assumes that when len(iri.FileList) > 0 (i.e. an InternalReleaseImage exists)
then the registry auth secret also has files, creating coupling between the
caller and appendIRIRegistryAuth; update the caller and appendIRIRegistryAuth to
be defensive: in the caller (where appendIRIcerts and appendIRIRegistryAuth are
invoked) only call appendIRIRegistryAuth if iriAuthSecret.Files() (or the
equivalent InternalReleaseImageRegistryAuthSecret) is non-empty, and inside
appendIRIRegistryAuth add a guard that returns early if the provided
secret/files list is empty; reference appendIRIRegistryAuth, appendIRIcerts,
InternalReleaseImage, iriAuthSecret.Files(), and
InternalReleaseImageRegistryAuthSecret.Generate to locate the relevant code
paths to change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@pkg/asset/ignition/bootstrap/common.go`:
- Line 719: Remove the unnecessary &tls.IRIRegistryAuth{} entry from the
addParentFiles call: IRIRegistryAuth.Files() returns an empty slice and the
asset is already accessed in getTemplateData for credentials, so deleting this
entry clarifies intent and avoids embedding a no-op asset; update any nearby
comments if present that imply this asset is being embedded and ensure
references to IRIRegistryAuth remain only where credentials are read
(getTemplateData).
- Around line 426-449: The function mergeIRIAuthIntoPullSecret currently errors
if pullSecretMap["auths"] is missing or not a map; instead, detect when "auths"
is absent or nil and initialize auths as an empty map[string]interface{} before
inserting the registry entry (operate on the local variable auths and assign it
back to pullSecretMap["auths"] if you create it), so the function accepts pull
secrets without an existing auths block while preserving existing auths and
still returning the merged JSON or errors on marshal/unmarshal failures.

In `@pkg/asset/manifests/operators.go`:
- Around line 239-242: The code implicitly assumes that when len(iri.FileList) >
0 (i.e. an InternalReleaseImage exists) then the registry auth secret also has
files, creating coupling between the caller and appendIRIRegistryAuth; update
the caller and appendIRIRegistryAuth to be defensive: in the caller (where
appendIRIcerts and appendIRIRegistryAuth are invoked) only call
appendIRIRegistryAuth if iriAuthSecret.Files() (or the equivalent
InternalReleaseImageRegistryAuthSecret) is non-empty, and inside
appendIRIRegistryAuth add a guard that returns early if the provided
secret/files list is empty; reference appendIRIRegistryAuth, appendIRIcerts,
InternalReleaseImage, iriAuthSecret.Files(), and
InternalReleaseImageRegistryAuthSecret.Generate to locate the relevant code
paths to change.

In `@pkg/asset/tls/iriregistryauth_test.go`:
- Around line 159-162: The test defines a local helper function pointer(i int64)
*int64; replace usages of this helper with the standard k8s utility ptr.To to be
consistent with the codebase: remove the pointer function, add/import
"k8s.io/utils/ptr" if not already imported in
pkg/asset/tls/iriregistryauth_test.go, and change calls like pointer(x) to
ptr.To(x) (refers to the pointer helper function name "pointer" and test code
usages).

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 744b58fe-0a6a-4ce5-80dc-431e5fefe435

📥 Commits

Reviewing files that changed from the base of the PR and between e884fa1 and 2b66c1b.

📒 Files selected for processing (8)
  • data/data/manifests/bootkube/internal-release-image-registry-auth-secret.yaml.template
  • pkg/asset/ignition/bootstrap/common.go
  • pkg/asset/manifests/operators.go
  • pkg/asset/store/assetcreate_test.go
  • pkg/asset/targets/targets.go
  • pkg/asset/templates/content/bootkube/internal-release-image-registry-auth-secret.go
  • pkg/asset/tls/iriregistryauth.go
  • pkg/asset/tls/iriregistryauth_test.go
🚧 Files skipped from review as they are similar to previous changes (1)
  • pkg/asset/store/assetcreate_test.go

Add authentication credentials for the Internal Release Image (IRI)
registry.

New assets:
- IRIRegistryAuth: In-memory-only asset that generates a random password
  and bcrypt htpasswd for the IRI registry. Not written to disk to avoid
  interfering with assisted-service's auth/ directory cleanup.
- InternalReleaseImageRegistryAuthSecret: Bootkube manifest template
  that creates the openshift-machine-config-operator/internal-release-
  image-registry-auth Secret containing the htpasswd and password.

Pull secret integration:
- Merge IRI registry credentials (openshift:<password>) into the global
  pull secret during bootstrap ignition generation so that kubelet/CRI-O
  can authenticate to the IRI registry on master nodes at
  api-int.<baseDomain>:22625.

Assisted-By: Claude Opus 4.6 <noreply@anthropic.com>
@openshift-ci-robot
Copy link
Contributor

openshift-ci-robot commented Mar 13, 2026

@rwsu: This pull request references AGENT-1448 which is a valid jira issue.

Details

In response to this:

Add authentication credentials for the Internal Release Image (IRI) registry.

New assets:

  • IRIRegistryAuth: In-memory-only asset that generates a random password and bcrypt htpasswd for the IRI registry. Not written to disk to avoid interfering with assisted-service's auth/ directory cleanup.
  • InternalReleaseImageRegistryAuthSecret: Bootkube manifest template that creates the openshift-machine-config-operator/internal-release- image-registry-auth Secret containing the htpasswd and password.

Pull secret integration:

  • Merge IRI registry credentials (openshift:) into the global pull secret during bootstrap ignition generation so that kubelet/CRI-O can authenticate to the IRI registry on master nodes at api-int.:22625.

Assisted-By: Claude Opus 4.6 noreply@anthropic.com

Summary by CodeRabbit

  • New Features

  • Adds generation of internal release-image registry credentials (username, password, htpasswd) and provides a registry-auth secret template.

  • When enabled, merges these credentials into the cluster pull secret used during bootstrap so nodes can authenticate to the internal registry.

  • Tests

  • Adds tests covering credential generation, encoding, htpasswd formatting, conditional (feature-gated) behavior, and merge handling during bootstrap.

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
pkg/asset/ignition/bootstrap/common.go (1)

426-449: Consider handling missing auths field more gracefully.

The function returns an error if the auths field is missing or not a map. However, while rare, a valid but minimal pull secret might not have an auths field. Consider initializing it if missing rather than returning an error.

♻️ Proposed fix to handle missing auths field
 func mergeIRIAuthIntoPullSecret(pullSecret, username, password, registryHost string) (string, error) {
 	var pullSecretMap map[string]interface{}
 	if err := json.Unmarshal([]byte(pullSecret), &pullSecretMap); err != nil {
 		return "", fmt.Errorf("failed to parse pull secret: %w", err)
 	}
 
-	auths, ok := pullSecretMap["auths"].(map[string]interface{})
-	if !ok {
-		return "", fmt.Errorf("pull secret missing 'auths' field")
+	auths, ok := pullSecretMap["auths"].(map[string]interface{})
+	if !ok {
+		auths = make(map[string]interface{})
+		pullSecretMap["auths"] = auths
 	}
 
 	authValue := base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%s:%s", username, password)))
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/asset/ignition/bootstrap/common.go` around lines 426 - 449, The function
mergeIRIAuthIntoPullSecret currently errors when pullSecretMap["auths"] is
missing or not a map; instead, modify it to initialize a new
map[string]interface{} for auths when the assertion fails and assign it back to
pullSecretMap["auths"], then proceed to add the registryHost entry; keep the
existing base64 auth creation and JSON marshal logic, and ensure you handle both
the case where "auths" exists as a map and where it must be created before
setting auths[registryHost] — change the auths handling in
mergeIRIAuthIntoPullSecret accordingly.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@pkg/asset/manifests/operators.go`:
- Around line 270-291: The function appendIRIRegistryAuth dereferences
iriAuthSecret.Files()[0] which can panic if
InternalReleaseImageRegistryAuthSecret.Files() returns an empty slice; add a
defensive check in appendIRIRegistryAuth to return nil immediately when
iriAuthSecret is nil or len(iriAuthSecret.Files()) == 0 before using Files()[0],
and ensure the caller that consumes appendIRIRegistryAuth handles a nil
*asset.File return (so callers of appendIRIRegistryAuth can skip adding when
nil).

---

Nitpick comments:
In `@pkg/asset/ignition/bootstrap/common.go`:
- Around line 426-449: The function mergeIRIAuthIntoPullSecret currently errors
when pullSecretMap["auths"] is missing or not a map; instead, modify it to
initialize a new map[string]interface{} for auths when the assertion fails and
assign it back to pullSecretMap["auths"], then proceed to add the registryHost
entry; keep the existing base64 auth creation and JSON marshal logic, and ensure
you handle both the case where "auths" exists as a map and where it must be
created before setting auths[registryHost] — change the auths handling in
mergeIRIAuthIntoPullSecret accordingly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository: openshift/coderabbit/.coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 138702e6-e09b-4744-a137-32872d94427f

📥 Commits

Reviewing files that changed from the base of the PR and between 2b66c1b and 6ed844a.

📒 Files selected for processing (8)
  • data/data/manifests/bootkube/internal-release-image-registry-auth-secret.yaml.template
  • pkg/asset/ignition/bootstrap/common.go
  • pkg/asset/manifests/operators.go
  • pkg/asset/store/assetcreate_test.go
  • pkg/asset/targets/targets.go
  • pkg/asset/templates/content/bootkube/internal-release-image-registry-auth-secret.go
  • pkg/asset/tls/iriregistryauth.go
  • pkg/asset/tls/iriregistryauth_test.go
🚧 Files skipped from review as they are similar to previous changes (3)
  • pkg/asset/store/assetcreate_test.go
  • data/data/manifests/bootkube/internal-release-image-registry-auth-secret.yaml.template
  • pkg/asset/targets/targets.go

Comment on lines +270 to +291
// appendIRIRegistryAuth renders the IRI registry auth secret template with the generated credentials.
func appendIRIRegistryAuth(dependencies asset.Parents) *asset.File {
iriAuth := &tls.IRIRegistryAuth{}
iriAuthSecret := &bootkube.InternalReleaseImageRegistryAuthSecret{}
dependencies.Get(iriAuth, iriAuthSecret)

f := iriAuthSecret.Files()[0]

templateData := struct {
IriRegistryHtpasswd string
IriRegistryPassword string
}{
IriRegistryHtpasswd: base64.StdEncoding.EncodeToString([]byte(iriAuth.HtpasswdContent)),
IriRegistryPassword: base64.StdEncoding.EncodeToString([]byte(iriAuth.Password)),
}
fileData := applyTemplateData(f.Data, templateData)

return &asset.File{
Filename: path.Join(manifestDir, strings.TrimSuffix(filepath.Base(f.Filename), ".template")),
Data: fileData,
}
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Add nil/empty check before accessing Files()[0].

If InternalReleaseImageRegistryAuthSecret.Generate() returns early (e.g., feature gate disabled or IRI manifest missing), Files() will return an empty slice. Accessing Files()[0] would cause a panic. Although the caller checks len(iri.FileList) > 0, this function should defensively validate its own input.

🛡️ Proposed fix to add defensive check
 func appendIRIRegistryAuth(dependencies asset.Parents) *asset.File {
 	iriAuth := &tls.IRIRegistryAuth{}
 	iriAuthSecret := &bootkube.InternalReleaseImageRegistryAuthSecret{}
 	dependencies.Get(iriAuth, iriAuthSecret)
 
+	files := iriAuthSecret.Files()
+	if len(files) == 0 {
+		return nil
+	}
+	f := files[0]
-	f := iriAuthSecret.Files()[0]
 
 	templateData := struct {

Then update the caller to handle nil:

 		if len(iri.FileList) > 0 {
 			files = append(files, appendIRIcerts(dependencies))
-			files = append(files, appendIRIRegistryAuth(dependencies))
+			if authFile := appendIRIRegistryAuth(dependencies); authFile != nil {
+				files = append(files, authFile)
+			}
 		}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// appendIRIRegistryAuth renders the IRI registry auth secret template with the generated credentials.
func appendIRIRegistryAuth(dependencies asset.Parents) *asset.File {
iriAuth := &tls.IRIRegistryAuth{}
iriAuthSecret := &bootkube.InternalReleaseImageRegistryAuthSecret{}
dependencies.Get(iriAuth, iriAuthSecret)
f := iriAuthSecret.Files()[0]
templateData := struct {
IriRegistryHtpasswd string
IriRegistryPassword string
}{
IriRegistryHtpasswd: base64.StdEncoding.EncodeToString([]byte(iriAuth.HtpasswdContent)),
IriRegistryPassword: base64.StdEncoding.EncodeToString([]byte(iriAuth.Password)),
}
fileData := applyTemplateData(f.Data, templateData)
return &asset.File{
Filename: path.Join(manifestDir, strings.TrimSuffix(filepath.Base(f.Filename), ".template")),
Data: fileData,
}
}
// appendIRIRegistryAuth renders the IRI registry auth secret template with the generated credentials.
func appendIRIRegistryAuth(dependencies asset.Parents) *asset.File {
iriAuth := &tls.IRIRegistryAuth{}
iriAuthSecret := &bootkube.InternalReleaseImageRegistryAuthSecret{}
dependencies.Get(iriAuth, iriAuthSecret)
files := iriAuthSecret.Files()
if len(files) == 0 {
return nil
}
f := files[0]
templateData := struct {
IriRegistryHtpasswd string
IriRegistryPassword string
}{
IriRegistryHtpasswd: base64.StdEncoding.EncodeToString([]byte(iriAuth.HtpasswdContent)),
IriRegistryPassword: base64.StdEncoding.EncodeToString([]byte(iriAuth.Password)),
}
fileData := applyTemplateData(f.Data, templateData)
return &asset.File{
Filename: path.Join(manifestDir, strings.TrimSuffix(filepath.Base(f.Filename), ".template")),
Data: fileData,
}
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@pkg/asset/manifests/operators.go` around lines 270 - 291, The function
appendIRIRegistryAuth dereferences iriAuthSecret.Files()[0] which can panic if
InternalReleaseImageRegistryAuthSecret.Files() returns an empty slice; add a
defensive check in appendIRIRegistryAuth to return nil immediately when
iriAuthSecret is nil or len(iriAuthSecret.Files()) == 0 before using Files()[0],
and ensure the caller that consumes appendIRIRegistryAuth handles a nil
*asset.File return (so callers of appendIRIRegistryAuth can skip adding when
nil).

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Mar 13, 2026

@rwsu: all tests passed!

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

jira/valid-reference Indicates that this PR references a valid Jira ticket of any type.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants