Skip to content

Commit ee04368

Browse files
committed
Update unpack job pod security (operator-framework#2793)
* Update unpack job security Signed-off-by: perdasilva <[email protected]> * Refactor catsrc pod creation to use security package Signed-off-by: perdasilva <[email protected]>
1 parent 99b51e7 commit ee04368

File tree

5 files changed

+105
-27
lines changed

5 files changed

+105
-27
lines changed

pkg/controller/bundle/bundle_unpacker.go

+5
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ import (
2828
listersoperatorsv1alpha1 "github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/listers/operators/v1alpha1"
2929
"github.com/operator-framework/operator-lifecycle-manager/pkg/controller/install"
3030
"github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver/projection"
31+
"github.com/operator-framework/operator-lifecycle-manager/pkg/controller/security"
3132
)
3233

3334
const (
@@ -190,6 +191,10 @@ func (c *ConfigMapUnpacker) job(cmRef *corev1.ObjectReference, bundlePath string
190191
},
191192
},
192193
}
194+
195+
// Apply Pod security
196+
security.ApplyPodSpecSecurity(&job.Spec.Template.Spec)
197+
193198
job.SetNamespace(cmRef.Namespace)
194199
job.SetName(cmRef.Name)
195200
job.SetOwnerReferences([]metav1.OwnerReference{ownerRef(cmRef)})

pkg/controller/bundle/bundle_unpacker_test.go

+52-5
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,29 @@ func TestConfigMapUnpacker(t *testing.T) {
6868
roleBindings []*rbacv1.RoleBinding
6969
}
7070

71+
var expectedReadOnlyRootFilesystem = false
72+
var expectedAllowPrivilegeEscalation = false
73+
var expectedRunAsNonRoot = true
74+
var expectedRunAsUser int64 = 1001
75+
var expectedPrivileged = false
76+
77+
var expectedContainerSecurityContext = &corev1.SecurityContext{
78+
Privileged: &expectedPrivileged,
79+
ReadOnlyRootFilesystem: &expectedReadOnlyRootFilesystem,
80+
AllowPrivilegeEscalation: &expectedAllowPrivilegeEscalation,
81+
Capabilities: &corev1.Capabilities{
82+
Drop: []corev1.Capability{"ALL"},
83+
},
84+
}
85+
86+
var expectedPodSecurityContext = &corev1.PodSecurityContext{
87+
RunAsNonRoot: &expectedRunAsNonRoot,
88+
RunAsUser: &expectedRunAsUser,
89+
SeccompProfile: &corev1.SeccompProfile{
90+
Type: corev1.SeccompProfileTypeRuntimeDefault,
91+
},
92+
}
93+
7194
tests := []struct {
7295
description string
7396
fields fields
@@ -220,6 +243,7 @@ func TestConfigMapUnpacker(t *testing.T) {
220243
Spec: corev1.PodSpec{
221244
RestartPolicy: corev1.RestartPolicyNever,
222245
ImagePullSecrets: []corev1.LocalObjectReference{{Name: "my-secret"}},
246+
SecurityContext: expectedPodSecurityContext,
223247
Containers: []corev1.Container{
224248
{
225249
Name: "extract",
@@ -243,6 +267,7 @@ func TestConfigMapUnpacker(t *testing.T) {
243267
corev1.ResourceMemory: resource.MustParse("50Mi"),
244268
},
245269
},
270+
SecurityContext: expectedContainerSecurityContext,
246271
},
247272
},
248273
InitContainers: []corev1.Container{
@@ -262,6 +287,7 @@ func TestConfigMapUnpacker(t *testing.T) {
262287
corev1.ResourceMemory: resource.MustParse("50Mi"),
263288
},
264289
},
290+
SecurityContext: expectedContainerSecurityContext,
265291
},
266292
{
267293
Name: "pull",
@@ -284,6 +310,7 @@ func TestConfigMapUnpacker(t *testing.T) {
284310
corev1.ResourceMemory: resource.MustParse("50Mi"),
285311
},
286312
},
313+
SecurityContext: expectedContainerSecurityContext,
287314
},
288315
},
289316
Volumes: []corev1.Volume{
@@ -396,7 +423,8 @@ func TestConfigMapUnpacker(t *testing.T) {
396423
Name: pathHash,
397424
},
398425
Spec: corev1.PodSpec{
399-
RestartPolicy: corev1.RestartPolicyNever,
426+
RestartPolicy: corev1.RestartPolicyNever,
427+
SecurityContext: expectedPodSecurityContext,
400428
Containers: []corev1.Container{
401429
{
402430
Name: "extract",
@@ -420,6 +448,7 @@ func TestConfigMapUnpacker(t *testing.T) {
420448
corev1.ResourceMemory: resource.MustParse("50Mi"),
421449
},
422450
},
451+
SecurityContext: expectedContainerSecurityContext,
423452
},
424453
},
425454
InitContainers: []corev1.Container{
@@ -439,6 +468,7 @@ func TestConfigMapUnpacker(t *testing.T) {
439468
corev1.ResourceMemory: resource.MustParse("50Mi"),
440469
},
441470
},
471+
SecurityContext: expectedContainerSecurityContext,
442472
},
443473
{
444474
Name: "pull",
@@ -461,6 +491,7 @@ func TestConfigMapUnpacker(t *testing.T) {
461491
corev1.ResourceMemory: resource.MustParse("50Mi"),
462492
},
463493
},
494+
SecurityContext: expectedContainerSecurityContext,
464495
},
465496
},
466497
Volumes: []corev1.Volume{
@@ -614,7 +645,8 @@ func TestConfigMapUnpacker(t *testing.T) {
614645
Name: pathHash,
615646
},
616647
Spec: corev1.PodSpec{
617-
RestartPolicy: corev1.RestartPolicyNever,
648+
RestartPolicy: corev1.RestartPolicyNever,
649+
SecurityContext: expectedPodSecurityContext,
618650
Containers: []corev1.Container{
619651
{
620652
Name: "extract",
@@ -638,6 +670,7 @@ func TestConfigMapUnpacker(t *testing.T) {
638670
corev1.ResourceMemory: resource.MustParse("50Mi"),
639671
},
640672
},
673+
SecurityContext: expectedContainerSecurityContext,
641674
},
642675
},
643676
InitContainers: []corev1.Container{
@@ -657,6 +690,7 @@ func TestConfigMapUnpacker(t *testing.T) {
657690
corev1.ResourceMemory: resource.MustParse("50Mi"),
658691
},
659692
},
693+
SecurityContext: expectedContainerSecurityContext,
660694
},
661695
{
662696
Name: "pull",
@@ -679,6 +713,7 @@ func TestConfigMapUnpacker(t *testing.T) {
679713
corev1.ResourceMemory: resource.MustParse("50Mi"),
680714
},
681715
},
716+
SecurityContext: expectedContainerSecurityContext,
682717
},
683718
},
684719
Volumes: []corev1.Volume{
@@ -826,7 +861,8 @@ func TestConfigMapUnpacker(t *testing.T) {
826861
Name: pathHash,
827862
},
828863
Spec: corev1.PodSpec{
829-
RestartPolicy: corev1.RestartPolicyNever,
864+
RestartPolicy: corev1.RestartPolicyNever,
865+
SecurityContext: expectedPodSecurityContext,
830866
Containers: []corev1.Container{
831867
{
832868
Name: "extract",
@@ -850,6 +886,7 @@ func TestConfigMapUnpacker(t *testing.T) {
850886
corev1.ResourceMemory: resource.MustParse("50Mi"),
851887
},
852888
},
889+
SecurityContext: expectedContainerSecurityContext,
853890
},
854891
},
855892
InitContainers: []corev1.Container{
@@ -869,6 +906,7 @@ func TestConfigMapUnpacker(t *testing.T) {
869906
corev1.ResourceMemory: resource.MustParse("50Mi"),
870907
},
871908
},
909+
SecurityContext: expectedContainerSecurityContext,
872910
},
873911
{
874912
Name: "pull",
@@ -891,6 +929,7 @@ func TestConfigMapUnpacker(t *testing.T) {
891929
corev1.ResourceMemory: resource.MustParse("50Mi"),
892930
},
893931
},
932+
SecurityContext: expectedContainerSecurityContext,
894933
},
895934
},
896935
Volumes: []corev1.Volume{
@@ -1008,7 +1047,8 @@ func TestConfigMapUnpacker(t *testing.T) {
10081047
Name: pathHash,
10091048
},
10101049
Spec: corev1.PodSpec{
1011-
RestartPolicy: corev1.RestartPolicyNever,
1050+
RestartPolicy: corev1.RestartPolicyNever,
1051+
SecurityContext: expectedPodSecurityContext,
10121052
Containers: []corev1.Container{
10131053
{
10141054
Name: "extract",
@@ -1032,6 +1072,7 @@ func TestConfigMapUnpacker(t *testing.T) {
10321072
corev1.ResourceMemory: resource.MustParse("50Mi"),
10331073
},
10341074
},
1075+
SecurityContext: expectedContainerSecurityContext,
10351076
},
10361077
},
10371078
InitContainers: []corev1.Container{
@@ -1051,6 +1092,7 @@ func TestConfigMapUnpacker(t *testing.T) {
10511092
corev1.ResourceMemory: resource.MustParse("50Mi"),
10521093
},
10531094
},
1095+
SecurityContext: expectedContainerSecurityContext,
10541096
},
10551097
{
10561098
Name: "pull",
@@ -1073,6 +1115,7 @@ func TestConfigMapUnpacker(t *testing.T) {
10731115
corev1.ResourceMemory: resource.MustParse("50Mi"),
10741116
},
10751117
},
1118+
SecurityContext: expectedContainerSecurityContext,
10761119
},
10771120
},
10781121
Volumes: []corev1.Volume{
@@ -1201,7 +1244,8 @@ func TestConfigMapUnpacker(t *testing.T) {
12011244
Name: pathHash,
12021245
},
12031246
Spec: corev1.PodSpec{
1204-
RestartPolicy: corev1.RestartPolicyNever,
1247+
RestartPolicy: corev1.RestartPolicyNever,
1248+
SecurityContext: expectedPodSecurityContext,
12051249
Containers: []corev1.Container{
12061250
{
12071251
Name: "extract",
@@ -1225,6 +1269,7 @@ func TestConfigMapUnpacker(t *testing.T) {
12251269
corev1.ResourceMemory: resource.MustParse("50Mi"),
12261270
},
12271271
},
1272+
SecurityContext: expectedContainerSecurityContext,
12281273
},
12291274
},
12301275
InitContainers: []corev1.Container{
@@ -1244,6 +1289,7 @@ func TestConfigMapUnpacker(t *testing.T) {
12441289
corev1.ResourceMemory: resource.MustParse("50Mi"),
12451290
},
12461291
},
1292+
SecurityContext: expectedContainerSecurityContext,
12471293
},
12481294
{
12491295
Name: "pull",
@@ -1266,6 +1312,7 @@ func TestConfigMapUnpacker(t *testing.T) {
12661312
corev1.ResourceMemory: resource.MustParse("50Mi"),
12671313
},
12681314
},
1315+
SecurityContext: expectedContainerSecurityContext,
12691316
},
12701317
},
12711318
Volumes: []corev1.Volume{

pkg/controller/registry/reconciler/reconciler.go

+4-22
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"k8s.io/apimachinery/pkg/util/rand"
1313

1414
operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1"
15+
"github.com/operator-framework/operator-lifecycle-manager/pkg/controller/security"
1516
controllerclient "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/controller-runtime/client"
1617
hashutil "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/util/hash"
1718
"github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorclient"
@@ -113,14 +114,6 @@ func Pod(source *operatorsv1alpha1.CatalogSource, name string, image string, saN
113114
pullPolicy = corev1.PullAlways
114115
}
115116

116-
// Security context
117-
readOnlyRootFilesystem := false
118-
allowPrivilegeEscalation := false
119-
runAsNonRoot := true
120-
121-
// See: https://github.com/operator-framework/operator-registry/blob/master/Dockerfile#L27
122-
runAsUser := int64(1001)
123-
124117
pod := &corev1.Pod{
125118
ObjectMeta: metav1.ObjectMeta{
126119
GenerateName: source.GetName() + "-",
@@ -172,31 +165,20 @@ func Pod(source *operatorsv1alpha1.CatalogSource, name string, image string, saN
172165
corev1.ResourceMemory: resource.MustParse("50Mi"),
173166
},
174167
},
175-
SecurityContext: &corev1.SecurityContext{
176-
ReadOnlyRootFilesystem: &readOnlyRootFilesystem,
177-
AllowPrivilegeEscalation: &allowPrivilegeEscalation,
178-
Capabilities: &corev1.Capabilities{
179-
Drop: []corev1.Capability{"ALL"},
180-
},
181-
},
182168
ImagePullPolicy: pullPolicy,
183169
TerminationMessagePolicy: corev1.TerminationMessageFallbackToLogsOnError,
184170
},
185171
},
186-
SecurityContext: &corev1.PodSecurityContext{
187-
RunAsNonRoot: &runAsNonRoot,
188-
RunAsUser: &runAsUser,
189-
SeccompProfile: &corev1.SeccompProfile{
190-
Type: corev1.SeccompProfileTypeRuntimeDefault,
191-
},
192-
},
193172
NodeSelector: map[string]string{
194173
"kubernetes.io/os": "linux",
195174
},
196175
ServiceAccountName: saName,
197176
},
198177
}
199178

179+
// Update pod security
180+
security.ApplyPodSpecSecurity(&pod.Spec)
181+
200182
// Override scheduling options if specified
201183
if source.Spec.GrpcPodConfig != nil {
202184
grpcPodConfig := source.Spec.GrpcPodConfig

pkg/controller/registry/reconciler/reconciler_test.go

+2
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,10 @@ func TestPodContainerSecurityContext(t *testing.T) {
8282
expectedAllowPrivilegeEscalation := false
8383
expectedRunAsNonRoot := true
8484
expectedRunAsUser := int64(1001)
85+
expectedPrivileged := false
8586

8687
expectedContainerSecCtx := &corev1.SecurityContext{
88+
Privileged: &expectedPrivileged,
8789
ReadOnlyRootFilesystem: &expectedReadOnlyRootFilesystem,
8890
AllowPrivilegeEscalation: &expectedAllowPrivilegeEscalation,
8991
Capabilities: &corev1.Capabilities{

pkg/controller/security/security.go

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
package security
2+
3+
import (
4+
corev1 "k8s.io/api/core/v1"
5+
"k8s.io/utils/pointer"
6+
)
7+
8+
const readOnlyRootFilesystem = false
9+
const allowPrivilegeEscalation = false
10+
const privileged = false
11+
const runAsNonRoot = true
12+
13+
// See: https://github.com/operator-framework/operator-registry/blob/master/Dockerfile#L27
14+
const runAsUser int64 = 1001
15+
16+
// ApplyPodSpecSecurity applies the standard security profile to a pod spec
17+
func ApplyPodSpecSecurity(spec *corev1.PodSpec) {
18+
var containerSecurityContext = &corev1.SecurityContext{
19+
Privileged: pointer.Bool(privileged),
20+
ReadOnlyRootFilesystem: pointer.Bool(readOnlyRootFilesystem),
21+
AllowPrivilegeEscalation: pointer.Bool(allowPrivilegeEscalation),
22+
Capabilities: &corev1.Capabilities{
23+
Drop: []corev1.Capability{"ALL"},
24+
},
25+
}
26+
27+
var podSecurityContext = &corev1.PodSecurityContext{
28+
RunAsNonRoot: pointer.Bool(runAsNonRoot),
29+
RunAsUser: pointer.Int64(runAsUser),
30+
SeccompProfile: &corev1.SeccompProfile{
31+
Type: corev1.SeccompProfileTypeRuntimeDefault,
32+
},
33+
}
34+
35+
spec.SecurityContext = podSecurityContext
36+
for idx := 0; idx < len(spec.Containers); idx++ {
37+
spec.Containers[idx].SecurityContext = containerSecurityContext
38+
}
39+
for idx := 0; idx < len(spec.InitContainers); idx++ {
40+
spec.InitContainers[idx].SecurityContext = containerSecurityContext
41+
}
42+
}

0 commit comments

Comments
 (0)