Skip to content

Commit 67177c0

Browse files
authored
(psa) make workloads compatible with psa:restricted profile (#2820)
* (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]> * (flaky text fix): GC CSV with wrong namespace annotation The test was modifying the `olm.operatornamespace` to an incorrect value, and checking to make sure that the CSV was garbage collected as a result. However, the olm-controller was copying a fresh copy back into the namespace, so whenever the test was able to get a yes reply to the question "is the CSV gone", in the brief window before it was copied back again, the test was passing. This commit fixes that by making sure that if find a CSV that we expected to be garbage collected, it passes if it determines that the CSV is a fresh copy, and not the one modified before. Signed-off-by: Anik Bhattacharjee <[email protected]>
1 parent b2086bd commit 67177c0

20 files changed

+331
-69
lines changed

Diff for: Dockerfile

+1
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"]

Diff for: Dockerfile.goreleaser

+1
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"]

Diff for: cmd/catalog/main.go

+6
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())

Diff for: cmd/catalog/start.go

+2
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")

Diff for: deploy/chart/templates/0000_50_olm_00-namespace.yaml

+6
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

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

+8
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 }}

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

+10
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:

Diff for: deploy/chart/templates/_packageserver.deployment-spec.yaml

+8-4
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

Diff for: e2e.Dockerfile

+1
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"]

Diff for: pkg/controller/bundle/bundle_unpacker.go

+35-1
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)