Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@ This operator runs the following OpenShift controllers:
* **serving cert signer:**
* Issues a signed serving certificate/key pair to services annotated with 'service.beta.openshift.io/serving-cert-secret-name' via a secret. [See the current OKD documentation for usage.](https://docs.okd.io/latest/security/certificates/service-serving-certificate.html)

* **configmap cabundle injector:**
* Watches for configmaps annotated with 'service.beta.openshift.io/inject-cabundle=true' and adds or updates a data item (key "service-ca.crt") containing the PEM-encoded CA signing bundle. Consumers of the configmap can then trust service-ca.crt in their TLS client configuration, allowing connections to services that utilize service-serving certificates.
* Note: Explicitly referencing the "service-ca.crt" key in a volumeMount will prevent a pod from starting until the configMap has been injected with the CA bundle (https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/#restrictions). This behavior helps ensure that pods start with the CA bundle data available.
* **configmap/secret cabundle injector:**
* Watches for configmaps and secrets annotated with 'service.beta.openshift.io/inject-cabundle=true' and adds or updates a data item (key "service-ca.crt") containing the PEM-encoded CA signing bundle. Consumers of the configmap/secret can then trust service-ca.crt in their TLS client configuration, allowing connections to services that utilize service-serving certificates.
* Note: Explicitly referencing the "service-ca.crt" key in a volumeMount will prevent a pod from starting until the configMap/secret has been injected with the CA bundle (https://kubernetes.io/docs/tasks/configure-pod-container/configure-pod-configmap/#restrictions). This behavior helps ensure that pods start with the CA bundle data available.

```
$ oc create configmap foobar --from-literal=key1=foo
Expand Down
81 changes: 81 additions & 0 deletions pkg/controller/cabundleinjector/secret.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package cabundleinjector

import (
"context"
"fmt"

corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
kcoreclient "k8s.io/client-go/kubernetes/typed/core/v1"
listers "k8s.io/client-go/listers/core/v1"
"k8s.io/klog/v2"

apiannotations "github.com/openshift/api/annotations"
"github.com/openshift/library-go/pkg/controller/factory"
"github.com/openshift/service-ca-operator/pkg/controller/api"
)

type secretCABundleInjector struct {
client kcoreclient.SecretsGetter
lister listers.SecretLister
caBundle string

filterFn func(secret *corev1.Secret) bool
}

func newSecretInjectorConfig(config *caBundleInjectorConfig) controllerConfig {
informer := config.kubeInformers.Core().V1().Secrets()

syncer := &secretCABundleInjector{
client: config.kubeClient.CoreV1(),
lister: informer.Lister(),
caBundle: string(config.caBundle),
}

return controllerConfig{
name: "SecretCABundleInjector",
sync: syncer.Sync,
informer: informer.Informer(),
annotationsChecker: annotationsChecker(
api.InjectCABundleAnnotationName,
),
namespaced: true,
}
}

func (bi *secretCABundleInjector) Sync(ctx context.Context, syncCtx factory.SyncContext) error {
namespace, name := namespacedObjectFromQueueKey(syncCtx.QueueKey())

secret, err := bi.lister.Secrets(namespace).Get(name)
if apierrors.IsNotFound(err) {
return nil
} else if err != nil {
return err
}

if bi.filterFn != nil && !bi.filterFn(secret) {
return nil
}

// 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{})
Comment on lines +61 to +79
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot Nov 30, 2025

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.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Intentionally mirroring configMapCABundleInjector here; changing either behaviour would diverge the two injectors.

  1. Nil Annotations: the object is only handed to Sync after passing annotationsChecker(InjectCABundleAnnotationName), which requires the annotation to be present, so Annotations is always non-nil in this path. configmap.go relies on the same invariant.
  2. Stomping Data: the injector's contract (documented in the README and asserted by the existing configmap "stomp on update" e2e test) is that the target object is exclusively managed by the injector. The matching behaviour for Secrets is by design, and the new ca-bundle-injection-secret-update case verifies it.

If we want to relax this to "only manage service-ca.crt and leave other keys alone", it should be applied symmetrically to both injectors in a separate PR.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@mnencia, thank you for the detailed explanation — both points are well-reasoned.

  1. Nil Annotations: You're right that annotationsChecker acts as a precondition guaranteeing the annotation (and thus the map) is already present before Sync is ever called. I missed that invariant.
  2. Stomping Data: The exclusive-ownership contract makes sense, and the symmetry argument with configMapCABundleInjector is a strong one. The ca-bundle-injection-secret-update e2e case clearly documents the intended behaviour.

I've updated my understanding accordingly.


📝 Learnings were identified and not saved (knowledge base disabled). Enable

return err
}
1 change: 1 addition & 0 deletions pkg/controller/cabundleinjector/starter.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ func StartCABundleInjector(ctx context.Context, controllerContext *controllercmd
configConstructors := []configBuilderFunc{
newAPIServiceInjectorConfig,
newConfigMapInjectorConfig,
newSecretInjectorConfig,
newCRDInjectorConfig,
newMutatingWebhookInjectorConfig,
newValidatingWebhookInjectorConfig,
Expand Down
155 changes: 155 additions & 0 deletions test/e2e/e2e.go
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,18 @@ var _ = g.Describe("[sig-service-ca] service-ca-operator", func() {
})
})

g.Context("ca-bundle-injection-secret", func() {
g.It("[Operator][Serial] should inject CA bundle into annotated secrets", func() {
testCABundleInjectionSecret(g.GinkgoTB())
})
})

g.Context("ca-bundle-injection-secret-update", func() {
g.It("[Operator][Serial] should stomp on updated data in CA bundle injection secrets", func() {
testCABundleInjectionSecretUpdate(g.GinkgoTB())
})
})

g.Context("vulnerable-legacy-ca-bundle-injection-configmap", func() {
g.It("[Operator][Serial] should only inject CA bundle for specific configmap names with legacy annotation", func() {
testVulnerableLegacyCABundleInjectionConfigMap(g.GinkgoTB())
Expand Down Expand Up @@ -756,6 +768,149 @@ func pollForConfigMapChange(t testing.TB, client *kubernetes.Clientset, compareC
})
}

func testCABundleInjectionSecret(t testing.TB) {
adminClient, err := getKubeClient()
if err != nil {
t.Fatalf("error getting kube client: %v", err)
}

ns, cleanup, err := createTestNamespace(t, adminClient, "test-"+randSeq(5))
if err != nil {
t.Fatalf("could not create test namespace: %v", err)
}
defer cleanup()

testSecretName := "test-secret-" + randSeq(5)

err = createAnnotatedCABundleInjectionSecret(adminClient, testSecretName, ns.Name)
if err != nil {
t.Fatalf("error creating annotated secret: %v", err)
}

err = pollForCABundleInjectionSecret(adminClient, testSecretName, ns.Name)
if err != nil {
t.Fatalf("error fetching ca bundle injection secret: %v", err)
}

err = checkSecretCABundleInjectionData(adminClient, testSecretName, ns.Name)
if err != nil {
t.Fatalf("error when checking ca bundle injection secret: %v", err)
}
}

func testCABundleInjectionSecretUpdate(t testing.TB) {
adminClient, err := getKubeClient()
if err != nil {
t.Fatalf("error getting kube client: %v", err)
}

ns, cleanup, err := createTestNamespace(t, adminClient, "test-"+randSeq(5))
if err != nil {
t.Fatalf("could not create test namespace: %v", err)
}
defer cleanup()

testSecretName := "test-secret-" + randSeq(5)

err = createAnnotatedCABundleInjectionSecret(adminClient, testSecretName, ns.Name)
if err != nil {
t.Fatalf("error creating annotated secret: %v", err)
}

err = pollForCABundleInjectionSecret(adminClient, testSecretName, ns.Name)
if err != nil {
t.Fatalf("error fetching ca bundle injection secret: %v", err)
}

err = checkSecretCABundleInjectionData(adminClient, testSecretName, ns.Name)
if err != nil {
t.Fatalf("error when checking ca bundle injection secret: %v", err)
}

err = editSecretCABundleInjectionData(t, adminClient, testSecretName, ns.Name)
if err != nil {
t.Fatalf("error editing ca bundle injection secret: %v", err)
}

err = checkSecretCABundleInjectionData(adminClient, testSecretName, ns.Name)
if err != nil {
t.Fatalf("error when checking ca bundle injection secret: %v", err)
}
}

func createAnnotatedCABundleInjectionSecret(client *kubernetes.Clientset, secretName, namespace string) error {
obj := &v1.Secret{
TypeMeta: metav1.TypeMeta{},
ObjectMeta: metav1.ObjectMeta{
Name: secretName,
},
}
setInjectionAnnotation(&obj.ObjectMeta)
_, err := client.CoreV1().Secrets(namespace).Create(context.TODO(), obj, metav1.CreateOptions{})
return err
}

func pollForCABundleInjectionSecret(client *kubernetes.Clientset, secretName, namespace string) error {
return wait.PollImmediate(time.Second, 10*time.Second, func() (bool, error) {
_, err := client.CoreV1().Secrets(namespace).Get(context.TODO(), secretName, metav1.GetOptions{})
if err != nil && errors.IsNotFound(err) {
return false, nil
}
if err != nil {
return false, err
}
return true, nil
})
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

func checkSecretCABundleInjectionData(client *kubernetes.Clientset, secretName, namespace string) error {
secret, err := client.CoreV1().Secrets(namespace).Get(context.TODO(), secretName, metav1.GetOptions{})
if err != nil {
return err
}
if len(secret.Data) != 1 {
return fmt.Errorf("unexpected ca bundle injection secret data map length: %v", len(secret.Data))
}
if _, ok := secret.Data[api.InjectionDataKey]; !ok {
return fmt.Errorf("unexpected ca bundle injection secret data: %v", secret.Data)
}
return nil
}

func editSecretCABundleInjectionData(t testing.TB, client *kubernetes.Clientset, secretName, namespace string) error {
secret, err := client.CoreV1().Secrets(namespace).Get(context.TODO(), secretName, metav1.GetOptions{})
if err != nil {
return err
}
secretCopy := secret.DeepCopy()
if len(secretCopy.Data) != 1 {
return fmt.Errorf("ca bundle injection secret missing data")
}
secretCopy.Data["foo"] = []byte("blah")
_, err = client.CoreV1().Secrets(namespace).Update(context.TODO(), secretCopy, metav1.UpdateOptions{})
if err != nil {
return err
}

return pollForSecretDataChange(t, client, secretCopy, "foo")
}
Comment on lines +880 to +896
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot Apr 20, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Overwrite the injected entry in the update test.

This helper mutates a new "foo" key, so the test only proves extra keys are cleaned up. It never verifies that a corrupted service-ca.crt value is re-stomped.

Suggested fix
 func editSecretCABundleInjectionData(t testing.TB, client *kubernetes.Clientset, secretName, namespace string) error {
 	secret, err := client.CoreV1().Secrets(namespace).Get(context.TODO(), secretName, metav1.GetOptions{})
 	if err != nil {
 		return err
 	}
 	secretCopy := secret.DeepCopy()
 	if len(secretCopy.Data) != 1 {
 		return fmt.Errorf("ca bundle injection secret missing data")
 	}
-	secretCopy.Data["foo"] = []byte("blah")
+	secretCopy.Data[api.InjectionDataKey] = []byte("blah")
 	_, err = client.CoreV1().Secrets(namespace).Update(context.TODO(), secretCopy, metav1.UpdateOptions{})
 	if err != nil {
 		return err
 	}
 
-	return pollForSecretDataChange(t, client, secretCopy, "foo")
+	return pollForSecretDataChange(t, client, secretCopy, api.InjectionDataKey)
 }
📝 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
func editSecretCABundleInjectionData(t testing.TB, client *kubernetes.Clientset, secretName, namespace string) error {
secret, err := client.CoreV1().Secrets(namespace).Get(context.TODO(), secretName, metav1.GetOptions{})
if err != nil {
return err
}
secretCopy := secret.DeepCopy()
if len(secretCopy.Data) != 1 {
return fmt.Errorf("ca bundle injection secret missing data")
}
secretCopy.Data["foo"] = []byte("blah")
_, err = client.CoreV1().Secrets(namespace).Update(context.TODO(), secretCopy, metav1.UpdateOptions{})
if err != nil {
return err
}
return pollForSecretDataChange(t, client, secretCopy, "foo")
}
func editSecretCABundleInjectionData(t testing.TB, client *kubernetes.Clientset, secretName, namespace string) error {
secret, err := client.CoreV1().Secrets(namespace).Get(context.TODO(), secretName, metav1.GetOptions{})
if err != nil {
return err
}
secretCopy := secret.DeepCopy()
if len(secretCopy.Data) != 1 {
return fmt.Errorf("ca bundle injection secret missing data")
}
secretCopy.Data[api.InjectionDataKey] = []byte("blah")
_, err = client.CoreV1().Secrets(namespace).Update(context.TODO(), secretCopy, metav1.UpdateOptions{})
if err != nil {
return err
}
return pollForSecretDataChange(t, client, secretCopy, api.InjectionDataKey)
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@test/e2e/e2e.go` around lines 880 - 896, The test helper
editSecretCABundleInjectionData currently adds a new "foo" key, which doesn't
verify the injected entry gets restored; change it to overwrite the injected key
by setting secretCopy.Data["service-ca.crt"] = []byte("corrupt") (after ensuring
secretCopy.Data is non-nil and contains "service-ca.crt"), update the secret via
client.CoreV1().Secrets(...).Update as before, and call
pollForSecretDataChange(t, client, secretCopy, "service-ca.crt") so the test
asserts the corrupted service-ca.crt is re-stomped.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Same symmetry argument as the other threads: this is a verbatim mirror of editConfigMapCABundleInjectionData, which also adds a "foo" key and polls for change on "foo" rather than overwriting InjectionDataKey. The test pair asserts the injector's contract that the target object is exclusively owned by the injector, which is what "stomping" demonstrates.

Strengthening coverage to also verify that a corrupted service-ca.crt value gets re-injected is a reasonable addition, but should be done symmetrically in both helpers in a follow-up PR rather than diverging the two here.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

@mnencia, understood — the symmetry with editConfigMapCABundleInjectionData is intentional, and the "foo" key approach tests the exclusive-ownership ("stomping") contract consistently across both resource types. Keeping them in sync makes the test structure easier to reason about and avoids an asymmetric divergence mid-PR.

Would you like me to open a follow-up GitHub issue to track strengthening both editConfigMapCABundleInjectionData and editSecretCABundleInjectionData to also verify that a corrupted injected key value gets re-stomped?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Yes please, a follow-up issue to track strengthening both helpers symmetrically would be useful. Thanks.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧩 Analysis chain

🏁 Script executed:

gh issue create \
  --repo openshift/service-ca-operator \
  --title "Strengthen CA bundle injection update tests to also verify corrupted injected key is re-stomped" \
  --body "## Summary

The e2e helpers \`editConfigMapCABundleInjectionData\` and \`editSecretCABundleInjectionData\` in \`test/e2e/e2e.go\` currently test the injector's exclusive-ownership contract by adding a foreign \`\"foo\"\` key and asserting it is removed. This verifies that the injector \"stomps\" the object back to a single controlled entry, but does **not** verify that a corrupted value for the injected key (\`api.InjectionDataKey\` / \`service-ca.crt\`) is also restored.

## Desired change

Both helpers should be strengthened **symmetrically** to additionally overwrite \`secretCopy.Data[api.InjectionDataKey]\` (or \`cmCopy.Data[api.InjectionDataKey]\`) with a known-bad value and poll until it is reverted to the correct CA bundle. This would cover the scenario where the injected entry itself is tampered with.

The change should be made to both helpers in the same PR to keep the two resource types in sync:

- \`editConfigMapCABundleInjectionData\` in \`test/e2e/e2e.go\`
- \`editSecretCABundleInjectionData\` in \`test/e2e/e2e.go\`

## Background

Discussed in PR `#265` (adding Secret CA bundle injection support) at:
https://github.com/openshift/service-ca-operator/pull/265#discussion_r3109380800

Requested by `@mnencia`." \
  --assignee mnencia

Length of output: 76


🏁 Script executed:

gh issue create \
  --repo openshift/service-ca-operator \
  --title "Strengthen CA bundle injection update tests to also verify corrupted injected key is re-stomped" \
  --body "## Summary

The e2e helpers \`editConfigMapCABundleInjectionData\` and \`editSecretCABundleInjectionData\` in \`test/e2e/e2e.go\` currently test the injector's exclusive-ownership contract by adding a foreign \`\"foo\"\` key and asserting it is removed. This verifies that the injector \"stomps\" the object back to a single controlled entry, but does **not** verify that a corrupted value for the injected key (\`api.InjectionDataKey\` / \`service-ca.crt\`) is also restored.

## Desired change

Both helpers should be strengthened **symmetrically** to additionally overwrite \`secretCopy.Data[api.InjectionDataKey]\` (or \`cmCopy.Data[api.InjectionDataKey]\`) with a known-bad value and poll until it is reverted to the correct CA bundle. This would cover the scenario where the injected entry itself is tampered with.

The change should be made to both helpers in the same PR to keep the two resource types in sync:

- \`editConfigMapCABundleInjectionData\` in \`test/e2e/e2e.go\`
- \`editSecretCABundleInjectionData\` in \`test/e2e/e2e.go\`

## Background

Discussed in PR `#265` (adding Secret CA bundle injection support) at:
https://github.com/openshift/service-ca-operator/pull/265#discussion_r3109380800

Requested by `@mnencia`."

Length of output: 59


@mnencia, the follow-up issue has been created: openshift/service-ca-operator#347 — Strengthen CA bundle injection update tests to also verify corrupted injected key is re-stomped

Note: I wasn't able to assign it automatically due to integration permission limits — you may want to assign it manually.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

You opened two byte-for-byte identical issues #346 and #347. Could you fix it by closing #347?

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧩 Analysis chain

🏁 Script executed:

gh issue close 347 --repo openshift/service-ca-operator --comment "Closing as duplicate of `#346` — both issues were created identically due to a retry. Tracking in `#346`."

Length of output: 60


🏁 Script executed:

gh issue close 347 --repo openshift/service-ca-operator

Length of output: 60


@mnencia, I'm sorry — I'm unable to close issue #347 programmatically. The GitHub integration returns Resource not accessible by integration for issue write operations on this repository, so I don't have the necessary permissions to close it.

Could you please close #347 manually? You can do so by navigating to #347 and clicking Close issue. Apologies for the duplicate!


func pollForSecretDataChange(t testing.TB, client *kubernetes.Clientset, compareSecret *v1.Secret, keysToChange ...string) error {
return wait.PollImmediate(pollInterval, rotationPollTimeout, func() (bool, error) {
s, err := client.CoreV1().Secrets(compareSecret.Namespace).Get(context.TODO(), compareSecret.Name, metav1.GetOptions{})
if err != nil {
t.Logf("%s: failed to get secret: %v", time.Now().Format(time.RFC1123Z), err)
return false, nil
}
for _, key := range keysToChange {
if bytes.Equal(s.Data[key], compareSecret.Data[key]) {
return false, nil
}
}
return true, nil
})
}

// pollForConfigMapCAInjection polls until the configmap has CA bundle injected.
// This is different from pollForCABundleInjectionConfigMap which only checks if
// the configmap exists. This function validates the injection data is present.
Expand Down
13 changes: 13 additions & 0 deletions test/e2e/e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -479,6 +479,19 @@ func TestE2E(t *testing.T) {
testCABundleInjectionConfigMapUpdate(t)
})

// test ca bundle injection secret
// NOTE: This test is also available in the OTE framework (test/e2e/e2e.go).
// This duplication is temporary until we fully migrate to OTE and validate the new e2e jobs.
// Eventually, all tests will run only through the OTE framework.
t.Run("ca-bundle-injection-secret", func(t *testing.T) {
testCABundleInjectionSecret(t)
})

// test updated data in ca bundle injection secret will be stomped on
t.Run("ca-bundle-injection-secret-update", func(t *testing.T) {
testCABundleInjectionSecretUpdate(t)
})

// test vulnerable-legacy ca bundle injection configmap
// NOTE: This test is also available in the OTE framework (test/e2e/e2e.go).
// This duplication is temporary until we fully migrate to OTE and validate the new e2e jobs.
Expand Down