Skip to content

Commit a6ed598

Browse files
committed
(psa) make workloads compatible with psa:restricted profile
With the introduction of [Pod Security Admission](https://kubernetes.io/docs/concepts/security/pod-security-admission/#pod-security-admission-labels-for-namespaces), the reccomeneded best practice is to enforce the Restricted policy of admission (see [1] for more details). This PR *) Lables the olm namespace as `enforce:restricted` *) Labels the operators namespace as `enforce:baseline` (to allow existing CSV deployments without securityContext set to deploy in the namespace, which won't be possible with `enforce:resticted`) *) updates the securityContext of olm workload pods(olm-operator, catalog-operator, and CatalogSource registry pods) to adhere to the `Restricted` policy. *) updates the bundle unpacking job to create a pod that adheres to the `Restricted` policy, so that bundles can be unpacked in the `Restricted` namespace. Signed-off-by: Anik Bhattacharjee <[email protected]>
1 parent c652154 commit a6ed598

19 files changed

+303
-54
lines changed

Dockerfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ COPY --from=builder /build/bin/olm /bin/olm
3333
COPY --from=builder /build/bin/catalog /bin/catalog
3434
COPY --from=builder /build/bin/package-server /bin/package-server
3535
COPY --from=builder /build/bin/cpb /bin/cpb
36+
USER 1001
3637
EXPOSE 8080
3738
EXPOSE 5443
3839
CMD ["/bin/olm"]

Dockerfile.goreleaser

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,5 @@ COPY package-server /bin/package-server
1010
COPY cpb /bin/cpb
1111
EXPOSE 8080
1212
EXPOSE 5443
13+
USER 1001
1314
ENTRYPOINT ["/bin/olm"]

cmd/catalog/main.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ const (
3030
defaultOPMImage = "quay.io/operator-framework/upstream-opm-builder:latest"
3131
defaultUtilImage = "quay.io/operator-framework/olm:latest"
3232
defaultOperatorName = ""
33+
defaultWorkLoadUserID = int64(1001)
3334
)
3435

3536
// config flags defined globally so that they appear on the test binary as well
@@ -83,6 +84,10 @@ func (o *options) run(ctx context.Context, logger *logrus.Logger) error {
8384
return fmt.Errorf("error configuring client: %s", err.Error())
8485
}
8586

87+
workloadUserID := int64(-1)
88+
if o.setWorkloadUserID {
89+
workloadUserID = defaultWorkLoadUserID
90+
}
8691
// TODO(tflannag): Use options pattern for catalog operator
8792
// Create a new instance of the operator.
8893
op, err := catalog.NewOperator(
@@ -98,6 +103,7 @@ func (o *options) run(ctx context.Context, logger *logrus.Logger) error {
98103
k8sscheme.Scheme,
99104
o.installPlanTimeout,
100105
o.bundleUnpackTimeout,
106+
workloadUserID,
101107
)
102108
if err != nil {
103109
return fmt.Errorf("error configuring catalog operator: %s", err.Error())

cmd/catalog/start.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ type options struct {
2525
tlsKeyPath string
2626
tlsCertPath string
2727
clientCAPath string
28+
setWorkloadUserID bool
2829

2930
installPlanTimeout time.Duration
3031
bundleUnpackTimeout time.Duration
@@ -66,6 +67,7 @@ func newRootCmd() *cobra.Command {
6667
cmd.Flags().StringVar(&o.opmImage, "opmImage", defaultOPMImage, "the image to use for unpacking bundle content with opm")
6768
cmd.Flags().StringVar(&o.utilImage, "util-image", defaultUtilImage, "an image containing custom olm utilities")
6869
cmd.Flags().StringVar(&o.writeStatusName, "writeStatusName", defaultOperatorName, "ClusterOperator name in which to write status, set to \"\" to disable.")
70+
cmd.Flags().BoolVar(&o.setWorkloadUserID, "set-workload-user-id", false, "set user ID for all workloads (registry pods/bundle unpack jobs to default 1001")
6971

7072
cmd.Flags().BoolVar(&o.debug, "debug", false, "use debug log level")
7173
cmd.Flags().BoolVar(&o.version, "version", false, "displays the olm version")

deploy/chart/templates/0000_50_olm_00-namespace.yaml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,15 @@ apiVersion: v1
22
kind: Namespace
33
metadata:
44
name: {{ .Values.namespace }}
5+
labels:
6+
pod-security.kubernetes.io/enforce: restricted
7+
pod-security.kubernetes.io/enforce-version: latest
58

69
---
710
apiVersion: v1
811
kind: Namespace
912
metadata:
1013
name: {{ .Values.operator_namespace }}
14+
labels:
15+
pod-security.kubernetes.io/enforce: baseline
16+
pod-security.kubernetes.io/enforce-version: latest

deploy/chart/templates/0000_50_olm_07-olm-operator.deployment.yaml

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ spec:
1717
labels:
1818
app: olm-operator
1919
spec:
20+
securityContext:
21+
runAsNonRoot: true
22+
seccompProfile:
23+
type: RuntimeDefault
2024
serviceAccountName: olm-operator-serviceaccount
2125
{{- if or .Values.olm.tlsSecret .Values.olm.clientCASecret }}
2226
volumes:
@@ -33,6 +37,10 @@ spec:
3337
{{- end }}
3438
containers:
3539
- name: olm-operator
40+
securityContext:
41+
allowPrivilegeEscalation: false
42+
capabilities:
43+
drop: [ "ALL" ]
3644
{{- if or .Values.olm.tlsSecret .Values.olm.clientCASecret }}
3745
volumeMounts:
3846
{{- end }}

deploy/chart/templates/0000_50_olm_08-catalog-operator.deployment.yaml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ spec:
1717
labels:
1818
app: catalog-operator
1919
spec:
20+
securityContext:
21+
runAsNonRoot: true
22+
seccompProfile:
23+
type: RuntimeDefault
2024
serviceAccountName: olm-operator-serviceaccount
2125
{{- if or .Values.catalog.tlsSecret .Values.catalog.clientCASecret }}
2226
volumes:
@@ -33,6 +37,10 @@ spec:
3337
{{- end }}
3438
containers:
3539
- name: catalog-operator
40+
securityContext:
41+
allowPrivilegeEscalation: false
42+
capabilities:
43+
drop: [ "ALL" ]
3644
{{- if or .Values.catalog.tlsSecret .Values.catalog.clientCASecret }}
3745
volumeMounts:
3846
{{- end }}
@@ -76,6 +84,8 @@ spec:
7684
- --client-ca
7785
- /profile-collector-cert/tls.crt
7886
{{- end }}
87+
- --set-workload-user-id
88+
- "true"
7989
image: {{ .Values.catalog.image.ref }}
8090
imagePullPolicy: {{ .Values.catalog.image.pullPolicy }}
8191
ports:

deploy/chart/templates/_packageserver.deployment-spec.yaml

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ spec:
1414
labels:
1515
app: packageserver
1616
spec:
17+
securityContext:
18+
runAsNonRoot: true
19+
seccompProfile:
20+
type: RuntimeDefault
1721
serviceAccountName: olm-operator-serviceaccount
1822
{{- if .Values.package.nodeSelector }}
1923
nodeSelector:
@@ -25,6 +29,10 @@ spec:
2529
{{- end }}
2630
containers:
2731
- name: packageserver
32+
securityContext:
33+
allowPrivilegeEscalation: false
34+
capabilities:
35+
drop: [ "ALL" ]
2836
command:
2937
- /bin/package-server
3038
- -v=4
@@ -61,10 +69,6 @@ spec:
6169
resources:
6270
{{ toYaml .Values.package.resources | indent 10 }}
6371
{{- end }}
64-
{{- if .Values.package.securityContext }}
65-
securityContext:
66-
runAsUser: {{ .Values.package.securityContext.runAsUser }}
67-
{{- end }}
6872
volumeMounts:
6973
- name: tmpfs
7074
mountPath: /tmp

e2e.Dockerfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ FROM busybox
33
COPY olm catalog package-server wait cpb /bin/
44
EXPOSE 8080
55
EXPOSE 5443
6+
USER 1001
67
CMD ["/bin/olm"]

pkg/controller/bundle/bundle_unpacker.go

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
listersbatchv1 "k8s.io/client-go/listers/batch/v1"
2323
listerscorev1 "k8s.io/client-go/listers/core/v1"
2424
listersrbacv1 "k8s.io/client-go/listers/rbac/v1"
25+
"k8s.io/utils/pointer"
2526

2627
"github.com/operator-framework/api/pkg/operators/reference"
2728
operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1"
@@ -101,6 +102,11 @@ func (c *ConfigMapUnpacker) job(cmRef *corev1.ObjectReference, bundlePath string
101102
// See: https://kubernetes.io/docs/concepts/workloads/controllers/job/#pod-backoff-failure-policy
102103
RestartPolicy: corev1.RestartPolicyNever,
103104
ImagePullSecrets: secrets,
105+
SecurityContext: &corev1.PodSecurityContext{
106+
SeccompProfile: &corev1.SeccompProfile{
107+
Type: corev1.SeccompProfileTypeRuntimeDefault,
108+
},
109+
},
104110
Containers: []corev1.Container{
105111
{
106112
Name: "extract",
@@ -129,6 +135,12 @@ func (c *ConfigMapUnpacker) job(cmRef *corev1.ObjectReference, bundlePath string
129135
corev1.ResourceMemory: resource.MustParse("50Mi"),
130136
},
131137
},
138+
SecurityContext: &corev1.SecurityContext{
139+
AllowPrivilegeEscalation: pointer.Bool(false),
140+
Capabilities: &corev1.Capabilities{
141+
Drop: []corev1.Capability{"ALL"},
142+
},
143+
},
132144
},
133145
},
134146
InitContainers: []corev1.Container{
@@ -148,6 +160,12 @@ func (c *ConfigMapUnpacker) job(cmRef *corev1.ObjectReference, bundlePath string
148160
corev1.ResourceMemory: resource.MustParse("50Mi"),
149161
},
150162
},
163+
SecurityContext: &corev1.SecurityContext{
164+
AllowPrivilegeEscalation: pointer.Bool(false),
165+
Capabilities: &corev1.Capabilities{
166+
Drop: []corev1.Capability{"ALL"},
167+
},
168+
},
151169
},
152170
{
153171
Name: "pull",
@@ -170,6 +188,12 @@ func (c *ConfigMapUnpacker) job(cmRef *corev1.ObjectReference, bundlePath string
170188
corev1.ResourceMemory: resource.MustParse("50Mi"),
171189
},
172190
},
191+
SecurityContext: &corev1.SecurityContext{
192+
AllowPrivilegeEscalation: pointer.Bool(false),
193+
Capabilities: &corev1.Capabilities{
194+
Drop: []corev1.Capability{"ALL"},
195+
},
196+
},
173197
},
174198
},
175199
Volumes: []corev1.Volume{
@@ -193,7 +217,10 @@ func (c *ConfigMapUnpacker) job(cmRef *corev1.ObjectReference, bundlePath string
193217
job.SetNamespace(cmRef.Namespace)
194218
job.SetName(cmRef.Name)
195219
job.SetOwnerReferences([]metav1.OwnerReference{ownerRef(cmRef)})
196-
220+
if c.runAsUser > 0 {
221+
job.Spec.Template.Spec.SecurityContext.RunAsUser = &c.runAsUser
222+
job.Spec.Template.Spec.SecurityContext.RunAsNonRoot = pointer.Bool(true)
223+
}
197224
// By default the BackoffLimit is set to 6 which with exponential backoff 10s + 20s + 40s ...
198225
// translates to ~10m of waiting time.
199226
// We want to fail faster than that when we have repeated failures from the bundle unpack pod
@@ -246,6 +273,7 @@ type ConfigMapUnpacker struct {
246273
loader *configmap.BundleLoader
247274
now func() metav1.Time
248275
unpackTimeout time.Duration
276+
runAsUser int64
249277
}
250278

251279
type ConfigMapUnpackerOption func(*ConfigMapUnpacker)
@@ -335,6 +363,12 @@ func WithNow(now func() metav1.Time) ConfigMapUnpackerOption {
335363
}
336364
}
337365

366+
func WithUserID(id int64) ConfigMapUnpackerOption {
367+
return func(unpacker *ConfigMapUnpacker) {
368+
unpacker.runAsUser = id
369+
}
370+
}
371+
338372
func (c *ConfigMapUnpacker) apply(options ...ConfigMapUnpackerOption) {
339373
for _, option := range options {
340374
option(c)

0 commit comments

Comments
 (0)