Skip to content

Commit 5daef89

Browse files
kaovilaiclaude
andcommitted
Add restrictive security context to registry pod and init containers
Fixes #7039 Signed-off-by: Tiger Kaovilai <passawit.kaovilai@gmail.com> Add changelog fragment for init container security context fix Signed-off-by: Tiger Kaovilai <passawit.kaovilai@gmail.com> Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 3d5ab21 commit 5daef89

3 files changed

Lines changed: 93 additions & 2 deletions

File tree

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# entries is a list of entries to include in
2+
# release notes and/or the migration guide
3+
entries:
4+
- description: >
5+
Fixed `operator-sdk run bundle` with `--security-context-config=restricted` to apply
6+
the restricted security context to init containers (`registry-grpc-init`), not just
7+
the main container. This resolves PodSecurity violations on clusters with
8+
`restricted` policy enforcement.
9+
kind: bugfix
10+
breaking: false

internal/olm/operator/registry/fbcindex/fbc_registry_pod.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -148,15 +148,22 @@ func (f *FBCRegistryPod) Create(ctx context.Context, cfg *operator.Configuration
148148
},
149149
}
150150

151-
// Update the Registry Pod container security context to be restrictive
152-
f.pod.Spec.Containers[0].SecurityContext = &corev1.SecurityContext{
151+
restrictedSecurityContext := &corev1.SecurityContext{
153152
Privileged: pointer.To(false),
154153
ReadOnlyRootFilesystem: pointer.To(false),
155154
AllowPrivilegeEscalation: pointer.To(false),
156155
Capabilities: &corev1.Capabilities{
157156
Drop: []corev1.Capability{"ALL"},
158157
},
159158
}
159+
160+
// Update the Registry Pod container security context to be restrictive
161+
f.pod.Spec.Containers[0].SecurityContext = restrictedSecurityContext
162+
163+
// Update all init containers with the same restrictive security context
164+
for i := range f.pod.Spec.InitContainers {
165+
f.pod.Spec.InitContainers[i].SecurityContext = restrictedSecurityContext
166+
}
160167
}
161168

162169
if f.ImagePullPolicy == "" {

internal/olm/operator/registry/fbcindex/fbc_registry_pod_test.go

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ import (
3838
"k8s.io/apimachinery/pkg/util/wait"
3939
"sigs.k8s.io/controller-runtime/pkg/client"
4040
fakeclient "sigs.k8s.io/controller-runtime/pkg/client/fake"
41+
"sigs.k8s.io/controller-runtime/pkg/client/interceptor"
4142
)
4243

4344
const testIndexImageTag = "some-image:v1.2.3"
@@ -305,6 +306,79 @@ var _ = Describe("FBCRegistryPod", func() {
305306
Expect(rp.pod.Spec.InitContainers[0].VolumeMounts).Should(HaveLen(2))
306307
})
307308
})
309+
310+
Context("with SecurityContext set to restricted", func() {
311+
It("should apply restrictive security context to pod, containers, and init containers", func() {
312+
schm := runtime.NewScheme()
313+
Expect(v1alpha1.AddToScheme(schm)).ShouldNot(HaveOccurred())
314+
Expect(corev1.AddToScheme(schm)).ShouldNot(HaveOccurred())
315+
316+
// Use an interceptor to make the pod appear Running on Get calls
317+
fakeClient := fakeclient.NewClientBuilder().
318+
WithScheme(schm).
319+
WithInterceptorFuncs(interceptor.Funcs{
320+
Get: func(ctx context.Context, c client.WithWatch, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error {
321+
if err := c.Get(ctx, key, obj, opts...); err != nil {
322+
return err
323+
}
324+
if pod, ok := obj.(*corev1.Pod); ok {
325+
pod.Status.Phase = corev1.PodRunning
326+
}
327+
return nil
328+
},
329+
}).
330+
Build()
331+
332+
restrictedCfg := &operator.Configuration{
333+
Client: fakeClient,
334+
Namespace: "test-default",
335+
Scheme: schm,
336+
}
337+
338+
cs := &v1alpha1.CatalogSource{
339+
ObjectMeta: metav1.ObjectMeta{
340+
Name: "test-catalogsource",
341+
},
342+
}
343+
344+
restrictedRp := &FBCRegistryPod{
345+
BundleItems: defaultBundleItems,
346+
IndexImage: testIndexImageTag,
347+
SecurityContext: "restricted",
348+
}
349+
350+
pod, err := restrictedRp.Create(context.Background(), restrictedCfg, cs)
351+
Expect(err).NotTo(HaveOccurred())
352+
Expect(pod).NotTo(BeNil())
353+
354+
By("verifying pod-level security context")
355+
Expect(pod.Spec.SecurityContext).NotTo(BeNil())
356+
Expect(pod.Spec.SecurityContext.SeccompProfile).NotTo(BeNil())
357+
Expect(pod.Spec.SecurityContext.SeccompProfile.Type).To(Equal(corev1.SeccompProfileTypeRuntimeDefault))
358+
359+
By("verifying main container security context")
360+
Expect(pod.Spec.Containers).To(HaveLen(1))
361+
sc := pod.Spec.Containers[0].SecurityContext
362+
Expect(sc).NotTo(BeNil())
363+
Expect(*sc.Privileged).To(BeFalse())
364+
Expect(*sc.ReadOnlyRootFilesystem).To(BeFalse())
365+
Expect(*sc.AllowPrivilegeEscalation).To(BeFalse())
366+
Expect(sc.Capabilities).NotTo(BeNil())
367+
Expect(sc.Capabilities.Drop).To(ContainElement(corev1.Capability("ALL")))
368+
369+
By("verifying init container security contexts")
370+
Expect(pod.Spec.InitContainers).NotTo(BeEmpty())
371+
for i, initContainer := range pod.Spec.InitContainers {
372+
isc := initContainer.SecurityContext
373+
Expect(isc).NotTo(BeNil(), "init container %d (%s) should have security context", i, initContainer.Name)
374+
Expect(*isc.Privileged).To(BeFalse(), "init container %d should not be privileged", i)
375+
Expect(*isc.ReadOnlyRootFilesystem).To(BeFalse(), "init container %d ReadOnlyRootFilesystem", i)
376+
Expect(*isc.AllowPrivilegeEscalation).To(BeFalse(), "init container %d should not allow privilege escalation", i)
377+
Expect(isc.Capabilities).NotTo(BeNil(), "init container %d should have capabilities", i)
378+
Expect(isc.Capabilities.Drop).To(ContainElement(corev1.Capability("ALL")), "init container %d should drop ALL capabilities", i)
379+
}
380+
})
381+
})
308382
})
309383
})
310384

0 commit comments

Comments
 (0)