Skip to content

Conversation

@mnencia
Copy link

@mnencia mnencia commented May 16, 2025

This pull request adds support for injecting the service CA bundle into Secrets to the existing functionality for ConfigMaps.

Closes #264.

@openshift-ci openshift-ci bot added the needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test. label May 16, 2025
@openshift-ci
Copy link
Contributor

openshift-ci bot commented May 16, 2025

Hi @mnencia. Thanks for your PR.

I'm waiting for a openshift member to verify that this patch is reasonable to test. If it is, they should reply with /ok-to-test on its own line. Until that is done, I will not automatically test new commits in this PR, but the usual testing commands by org members will still work. Regular contributors should join the org to skip this step.

Once the patch is verified, the new status will be reflected by the ok-to-test label.

I understand the commands that are listed here.

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.

@openshift-ci openshift-ci bot requested a review from deads2k May 16, 2025 15:09
@openshift-ci
Copy link
Contributor

openshift-ci bot commented May 16, 2025

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: mnencia
Once this PR has been reviewed and has the lgtm label, please assign deads2k 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-bot
Copy link
Contributor

Issues go stale after 90d of inactivity.

Mark the issue as fresh by commenting /remove-lifecycle stale.
Stale issues rot after an additional 30d of inactivity and eventually close.
Exclude this issue from closing by commenting /lifecycle frozen.

If this issue is safe to close now please do so with /close.

/lifecycle stale

@openshift-ci openshift-ci bot added the lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. label Aug 15, 2025
@openshift-ci openshift-ci bot removed the lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. label Sep 1, 2025
@openshift-bot
Copy link
Contributor

Issues go stale after 90d of inactivity.

Mark the issue as fresh by commenting /remove-lifecycle stale.
Stale issues rot after an additional 30d of inactivity and eventually close.
Exclude this issue from closing by commenting /lifecycle frozen.

If this issue is safe to close now please do so with /close.

/lifecycle stale

@openshift-ci openshift-ci bot added the lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. label Nov 30, 2025
@coderabbitai
Copy link

coderabbitai bot commented Nov 30, 2025

Walkthrough

Introduces Secret CA bundle injection support alongside existing ConfigMap injection. Implements a new Secret injector controller with idempotent update logic, integrates it into the startup pipeline, updates documentation to reflect both ConfigMap and Secret support, and adds comprehensive end-to-end tests validating injection and update semantics.

Changes

Cohort / File(s) Change Summary
Documentation updates
README.md
Updated nomenclature and sections to reference both ConfigMaps and Secrets for CA bundle injection, removing ConfigMap-specific language.
Secret injector implementation
pkg/controller/cabundleinjector/secret.go
New file introducing secretCABundleInjector struct, newSecretInjectorConfig function, and Sync logic that idempotently injects CA bundle data into Secrets, with filtering and annotation handling.
Controller integration
pkg/controller/cabundleinjector/starter.go
Registers the new Secret injector configuration in the controller startup sequence alongside existing injectors.
End-to-end tests
test/e2e/e2e_test.go
Adds helper functions for Secret creation, CA bundle injection polling, data editing, and validation; introduces two new test cases for Secret-based injection and update semantics.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

  • secret.go requires careful review of the injector logic, idempotency checks, and error handling paths
  • e2e_test.go should be verified for test coverage completeness and parity with ConfigMap injection tests
  • starter.go integration point should be confirmed for correct wiring and initialization order

Assessment against linked issues

Objective Addressed Explanation
Add support for injecting CA certificates into Secrets (#264)

Out-of-scope changes

No out-of-scope changes detected. All modifications directly support the objective of enabling CA certificate injection into Secrets.

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

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

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

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Cache: Disabled due to data retention organization setting

Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting

📥 Commits

Reviewing files that changed from the base of the PR and between 4dfa691 and f588f82.

📒 Files selected for processing (4)
  • README.md (1 hunks)
  • pkg/controller/cabundleinjector/secret.go (1 hunks)
  • pkg/controller/cabundleinjector/starter.go (1 hunks)
  • test/e2e/e2e_test.go (5 hunks)
🧰 Additional context used
📓 Path-based instructions (1)
**

⚙️ CodeRabbit configuration file

-Focus on major issues impacting performance, readability, maintainability and security. Avoid nitpicks and avoid verbosity.

Files:

  • README.md
  • pkg/controller/cabundleinjector/secret.go
  • pkg/controller/cabundleinjector/starter.go
  • test/e2e/e2e_test.go
🧬 Code graph analysis (2)
pkg/controller/cabundleinjector/secret.go (1)
pkg/controller/api/api.go (3)
  • InjectCABundleAnnotationName (27-27)
  • InjectionDataKey (29-29)
  • OwningJiraComponent (22-22)
test/e2e/e2e_test.go (1)
pkg/controller/api/api.go (1)
  • InjectionDataKey (29-29)
🪛 markdownlint-cli2 (0.18.1)
README.md

9-9: Bare URL used

(MD034, no-bare-urls)

🔇 Additional comments (3)
pkg/controller/cabundleinjector/starter.go (1)

89-97: Wiring the Secret injector into the startup pipeline looks correct

Adding newSecretInjectorConfig to configConstructors matches the existing pattern for other injectors and ensures the Secret injector runs with the shared informer factory and annotations filter.

README.md (1)

7-9: Updated docs correctly mention Secret-based CA bundle injection

The README text for the “configmap/secret cabundle injector” accurately reflects that both ConfigMaps and Secrets annotated with inject-cabundle=true are now handled, and explains the service-ca.crt data item usage clearly.

test/e2e/e2e_test.go (1)

213-223: Secret CA-bundle e2e helpers and tests mirror existing ConfigMap coverage

The new helpers for creating annotated Secrets, polling for injection, editing data, and validating contents closely follow the existing ConfigMap patterns and exercise both initial injection and “stomp-on-change” behavior for dedicated injection Secrets. Timeouts and polling are consistent with the rest of the suite, so this should give good end-to-end coverage of the new Secret injector without introducing obvious flakiness.

Also applies to: 251-262, 297-313, 358-372, 1498-1558

Comment on lines +61 to +79
// skip updating when the CA bundle is already there
if data, ok := secret.Data[api.InjectionDataKey]; ok &&
string(data) == bi.caBundle && len(secret.Data) == 1 {

return nil
}

klog.Infof("updating secret %s/%s with the service signing CA bundle", secret.Namespace, secret.Name)

// make a copy to avoid mutating cache state
secretCopy := secret.DeepCopy()
secretCopy.Data = map[string][]byte{api.InjectionDataKey: []byte(bi.caBundle)}
// set the owning-component unless someone else has claimed it.
if len(secretCopy.Annotations[apiannotations.OpenShiftComponent]) == 0 {
secretCopy.Annotations[apiannotations.OpenShiftComponent] = api.OwningJiraComponent
secretCopy.Annotations[apiannotations.OpenShiftDescription] = fmt.Sprintf("Secret is added/updated with a data item containing the CA signing bundle that can be used to verify service-serving certificates")
}

_, err = bi.client.Secrets(secretCopy.Namespace).Update(ctx, secretCopy, metav1.UpdateOptions{})
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Fix nil Annotations panic and reconsider overwriting all Secret data

Two things to flag here:

  1. Potential panic on nil annotations (must fix):
    secretCopy.Annotations may be nil for a freshly-created Secret. Writing to a nil map will panic:
if len(secretCopy.Annotations[apiannotations.OpenShiftComponent]) == 0 {
    secretCopy.Annotations[apiannotations.OpenShiftComponent] = api.OwningJiraComponent
    secretCopy.Annotations[apiannotations.OpenShiftDescription] = fmt.Sprintf("Secret is added/updated with a data item containing the CA signing bundle that can be used to verify service-serving certificates")
}

Initialize the map before writing:

-	secretCopy := secret.DeepCopy()
-	secretCopy.Data = map[string][]byte{api.InjectionDataKey: []byte(bi.caBundle)}
-	// set the owning-component unless someone else has claimed it.
-	if len(secretCopy.Annotations[apiannotations.OpenShiftComponent]) == 0 {
+	secretCopy := secret.DeepCopy()
+	secretCopy.Data = map[string][]byte{api.InjectionDataKey: []byte(bi.caBundle)}
+	// ensure annotations map is initialized before writing to it
+	if secretCopy.Annotations == nil {
+		secretCopy.Annotations = map[string]string{}
+	}
+	// set the owning-component unless someone else has claimed it.
+	if len(secretCopy.Annotations[apiannotations.OpenShiftComponent]) == 0 {
 		secretCopy.Annotations[apiannotations.OpenShiftComponent] = api.OwningJiraComponent
 		secretCopy.Annotations[apiannotations.OpenShiftDescription] = fmt.Sprintf("Secret is added/updated with a data item containing the CA signing bundle that can be used to verify service-serving certificates")
 	}
  1. Secret Data is fully overwritten (design/semantics):
    secretCopy.Data = map[string][]byte{...} drops all existing keys and, together with the len(secret.Data) == 1 skip condition, forces injected Secrets to contain only service-ca.crt. That’s consistent with the new e2e tests (which assert len(Data)==1 and that extra keys get “stomped”), but it is stricter than the README wording (“adds or updates a data item”) and prevents co-locating other material in the same Secret.

If you want parity with a more typical “only manage InjectionDataKey” pattern (and to better match the README text), consider instead:

-	secretCopy := secret.DeepCopy()
-	secretCopy.Data = map[string][]byte{api.InjectionDataKey: []byte(bi.caBundle)}
+	secretCopy := secret.DeepCopy()
+	if secretCopy.Data == nil {
+		secretCopy.Data = map[string][]byte{}
+	}
+	secretCopy.Data[api.InjectionDataKey] = []byte(bi.caBundle)

and relaxing the len(secret.Data) == 1 checks in Sync/tests to only care that InjectionDataKey matches the operator’s bundle.

🤖 Prompt for AI Agents
In pkg/controller/cabundleinjector/secret.go around lines 61 to 79, initialize
secretCopy.Annotations if nil before writing to it to avoid a nil-map panic, and
stop overwriting the entire Secret.Data: instead of assigning a new map, set or
update only the api.InjectionDataKey entry on secretCopy.Data (ensuring
secretCopy.Data is non-nil first) and adjust the earlier skip condition so it
checks only that the InjectionDataKey value matches bi.caBundle rather than
relying on len(secret.Data)==1.

@mnencia
Copy link
Author

mnencia commented Dec 9, 2025

/remove-lifecycle stale

@openshift-ci openshift-ci bot removed the lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. label Dec 9, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

needs-ok-to-test Indicates a PR that requires an org member to verify it is safe to test.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add support for injecting CA certificates into Secrets

2 participants