diff --git a/go.mod b/go.mod index 05ae49f275..be50ba2b44 100644 --- a/go.mod +++ b/go.mod @@ -13,7 +13,7 @@ require ( github.com/mikefarah/yq/v3 v3.0.0-20201202084205-8846255d1c37 github.com/onsi/ginkgo/v2 v2.1.3 github.com/openshift/api v0.0.0-20220525145417-ee5b62754c68 - github.com/operator-framework/api v0.16.0 + github.com/operator-framework/api v0.17.1 github.com/operator-framework/operator-lifecycle-manager v0.0.0-00010101000000-000000000000 github.com/operator-framework/operator-registry v1.17.5 github.com/sirupsen/logrus v1.8.1 diff --git a/staging/operator-lifecycle-manager/deploy/chart/crds/0000_50_olm_00-catalogsources.crd.yaml b/staging/operator-lifecycle-manager/deploy/chart/crds/0000_50_olm_00-catalogsources.crd.yaml index 318393f814..5da15cc938 100644 --- a/staging/operator-lifecycle-manager/deploy/chart/crds/0000_50_olm_00-catalogsources.crd.yaml +++ b/staging/operator-lifecycle-manager/deploy/chart/crds/0000_50_olm_00-catalogsources.crd.yaml @@ -79,6 +79,13 @@ spec: priorityClassName: description: If specified, indicates the pod's priority. If not specified, the pod priority will be default or zero if there is no default. type: string + securityContextConfig: + description: 'SecurityContextConfig can be one of `legacy` or `restricted`. The CatalogSource''s pod is either injected with the right pod.spec.securityContext and pod.spec.container[*].securityContext values to allow the pod to run in Pod Security Admission(PSA) controller''s `restricted` mode, or doesn''t set these values at all, in which case the pod can only be run in PSA `baseline` or `privileged` namespaces. By default, SecurityContextConfig is set to `restricted`. If the value is unspecified, the default value of `restricted` is used. Specifying any other value will result in a validation error. When using older catalog images, which could not be run in `restricted` mode, the SecurityContextConfig should be set to `legacy`. More information about PSA can be found here: https://kubernetes.io/docs/concepts/security/pod-security-admission/''' + type: string + default: restricted + enum: + - legacy + - restricted tolerations: description: Tolerations are the catalog source's pod's tolerations. type: array diff --git a/staging/operator-lifecycle-manager/go.mod b/staging/operator-lifecycle-manager/go.mod index 87fc82abb2..b1802e4368 100644 --- a/staging/operator-lifecycle-manager/go.mod +++ b/staging/operator-lifecycle-manager/go.mod @@ -24,7 +24,7 @@ require ( github.com/onsi/gomega v1.18.1 github.com/openshift/api v0.0.0-20220525145417-ee5b62754c68 github.com/openshift/client-go v0.0.0-20220525160904-9e1acff93e4a - github.com/operator-framework/api v0.16.0 + github.com/operator-framework/api v0.17.1 github.com/operator-framework/operator-registry v1.17.5 github.com/otiai10/copy v1.2.0 github.com/pkg/errors v0.9.1 diff --git a/staging/operator-lifecycle-manager/go.sum b/staging/operator-lifecycle-manager/go.sum index fb2a952e86..9a15c91e15 100644 --- a/staging/operator-lifecycle-manager/go.sum +++ b/staging/operator-lifecycle-manager/go.sum @@ -1080,8 +1080,8 @@ github.com/openshift/cluster-policy-controller v0.0.0-20220825134653-523e4104074 github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= github.com/operator-framework/api v0.7.1/go.mod h1:L7IvLd/ckxJEJg/t4oTTlnHKAJIP/p51AvEslW3wYdY= -github.com/operator-framework/api v0.16.0 h1:swUOhVv7QDszxBTwYM8QAtyeqI4EQHNVAiKMS+xjakY= -github.com/operator-framework/api v0.16.0/go.mod h1:kk8xJahHJR3bKqrA+A+1VIrhOTmyV76k+ARv+iV+u1Q= +github.com/operator-framework/api v0.17.1 h1:J/6+Xj4IEV8C7hcirqUFwOiZAU3PbnJhWvB0/bB51c4= +github.com/operator-framework/api v0.17.1/go.mod h1:kk8xJahHJR3bKqrA+A+1VIrhOTmyV76k+ARv+iV+u1Q= github.com/operator-framework/operator-registry v1.17.5 h1:LR8m1rFz5Gcyje8WK6iYt+gIhtzqo52zMRALdmTYHT0= github.com/operator-framework/operator-registry v1.17.5/go.mod h1:sRQIgDMZZdUcmHltzyCnM6RUoDF+WS8Arj1BQIARDS8= github.com/otiai10/copy v1.2.0 h1:HvG945u96iNadPoG2/Ja2+AUJeW5YuFQMixq9yirC+k= diff --git a/staging/operator-lifecycle-manager/pkg/controller/registry/reconciler/reconciler.go b/staging/operator-lifecycle-manager/pkg/controller/registry/reconciler/reconciler.go index 45bf8dcba4..eada0099fe 100644 --- a/staging/operator-lifecycle-manager/pkg/controller/registry/reconciler/reconciler.go +++ b/staging/operator-lifecycle-manager/pkg/controller/registry/reconciler/reconciler.go @@ -182,11 +182,7 @@ func Pod(source *operatorsv1alpha1.CatalogSource, name string, image string, saN }, }, SecurityContext: &corev1.SecurityContext{ - ReadOnlyRootFilesystem: pointer.Bool(false), - AllowPrivilegeEscalation: pointer.Bool(false), - Capabilities: &corev1.Capabilities{ - Drop: []corev1.Capability{"ALL"}, - }, + ReadOnlyRootFilesystem: pointer.Bool(false), }, ImagePullPolicy: pullPolicy, TerminationMessagePolicy: corev1.TerminationMessageFallbackToLogsOnError, @@ -195,19 +191,18 @@ func Pod(source *operatorsv1alpha1.CatalogSource, name string, image string, saN NodeSelector: map[string]string{ "kubernetes.io/os": "linux", }, - SecurityContext: &corev1.PodSecurityContext{ - SeccompProfile: &corev1.SeccompProfile{ - Type: corev1.SeccompProfileTypeRuntimeDefault, - }, - }, ServiceAccountName: saName, }, } - if runAsUser > 0 { - pod.Spec.SecurityContext.RunAsUser = &runAsUser - pod.Spec.SecurityContext.RunAsNonRoot = pointer.Bool(true) + if source.Spec.GrpcPodConfig != nil { + if source.Spec.GrpcPodConfig.SecurityContextConfig == operatorsv1alpha1.Restricted { + addSecurityContext(pod, runAsUser) + } + } else { + addSecurityContext(pod, runAsUser) } + // Override scheduling options if specified if source.Spec.GrpcPodConfig != nil { grpcPodConfig := source.Spec.GrpcPodConfig @@ -256,3 +251,19 @@ func hashPodSpec(spec corev1.PodSpec) string { hashutil.DeepHashObject(hasher, &spec) return rand.SafeEncodeString(fmt.Sprint(hasher.Sum32())) } + +func addSecurityContext(pod *corev1.Pod, runAsUser int64) { + pod.Spec.Containers[0].SecurityContext.AllowPrivilegeEscalation = pointer.Bool(false) + pod.Spec.Containers[0].SecurityContext.Capabilities = &corev1.Capabilities{ + Drop: []corev1.Capability{"ALL"}, + } + pod.Spec.SecurityContext = &corev1.PodSecurityContext{ + SeccompProfile: &corev1.SeccompProfile{ + Type: corev1.SeccompProfileTypeRuntimeDefault, + }, + } + if runAsUser > 0 { + pod.Spec.SecurityContext.RunAsUser = &runAsUser + pod.Spec.SecurityContext.RunAsNonRoot = pointer.Bool(true) + } +} diff --git a/staging/operator-lifecycle-manager/test/e2e/catalog_e2e_test.go b/staging/operator-lifecycle-manager/test/e2e/catalog_e2e_test.go index e02436d375..007ccc75ea 100644 --- a/staging/operator-lifecycle-manager/test/e2e/catalog_e2e_test.go +++ b/staging/operator-lifecycle-manager/test/e2e/catalog_e2e_test.go @@ -53,7 +53,11 @@ var _ = Describe("Starting CatalogSource e2e tests", func() { ) BeforeEach(func() { - namespaceName := genName("catsrc-e2e-") + // In OPC, PSA labels for any namespace created that is not prefixed with "openshift-" is overriden to enforce + // PSA restricted. This test namespace needs to prefixed with openshift- so that baseline/privileged enforcement + // for the PSA specific tests are not overridden, + // Change it only after https://github.com/operator-framework/operator-lifecycle-manager/issues/2859 is closed. + namespaceName := genName("openshift-catsrc-e2e-") og := operatorsv1.OperatorGroup{ ObjectMeta: metav1.ObjectMeta{ Name: fmt.Sprintf("%s-operatorgroup", namespaceName), @@ -1396,7 +1400,147 @@ var _ = Describe("Starting CatalogSource e2e tests", func() { }) }) }) + When("The namespace is labled as Pod Security Admission policy enforce:restricted", func() { + BeforeEach(func() { + var err error + testNS := &corev1.Namespace{} + Eventually(func() error { + testNS, err = c.KubernetesInterface().CoreV1().Namespaces().Get(context.TODO(), ns.GetName(), metav1.GetOptions{}) + if err != nil { + return err + } + return nil + }).Should(BeNil()) + + testNS.ObjectMeta.Labels = map[string]string{ + "pod-security.kubernetes.io/enforce": "restricted", + "pod-security.kubernetes.io/enforce-version": "latest", + } + + Eventually(func() error { + _, err := c.KubernetesInterface().CoreV1().Namespaces().Update(context.TODO(), testNS, metav1.UpdateOptions{}) + if err != nil { + return err + } + return nil + }).Should(BeNil()) + }) + When("A CatalogSource built with opm v1.21.0 ( 0 { - pod.Spec.SecurityContext.RunAsUser = &runAsUser - pod.Spec.SecurityContext.RunAsNonRoot = pointer.Bool(true) + if source.Spec.GrpcPodConfig != nil { + if source.Spec.GrpcPodConfig.SecurityContextConfig == operatorsv1alpha1.Restricted { + addSecurityContext(pod, runAsUser) + } + } else { + addSecurityContext(pod, runAsUser) } + // Override scheduling options if specified if source.Spec.GrpcPodConfig != nil { grpcPodConfig := source.Spec.GrpcPodConfig @@ -256,3 +251,19 @@ func hashPodSpec(spec corev1.PodSpec) string { hashutil.DeepHashObject(hasher, &spec) return rand.SafeEncodeString(fmt.Sprint(hasher.Sum32())) } + +func addSecurityContext(pod *corev1.Pod, runAsUser int64) { + pod.Spec.Containers[0].SecurityContext.AllowPrivilegeEscalation = pointer.Bool(false) + pod.Spec.Containers[0].SecurityContext.Capabilities = &corev1.Capabilities{ + Drop: []corev1.Capability{"ALL"}, + } + pod.Spec.SecurityContext = &corev1.PodSecurityContext{ + SeccompProfile: &corev1.SeccompProfile{ + Type: corev1.SeccompProfileTypeRuntimeDefault, + }, + } + if runAsUser > 0 { + pod.Spec.SecurityContext.RunAsUser = &runAsUser + pod.Spec.SecurityContext.RunAsNonRoot = pointer.Bool(true) + } +} diff --git a/vendor/modules.txt b/vendor/modules.txt index c8fa7f6cb3..c5a67dc4ae 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -636,7 +636,7 @@ github.com/openshift/client-go/config/listers/config/v1 # github.com/openshift/cluster-policy-controller v0.0.0-20220825134653-523e4104074f ## explicit; go 1.18 github.com/openshift/cluster-policy-controller/pkg/psalabelsyncer/nsexemptions -# github.com/operator-framework/api v0.16.0 => ./staging/api +# github.com/operator-framework/api v0.17.1 => ./staging/api ## explicit; go 1.18 github.com/operator-framework/api/crds github.com/operator-framework/api/pkg/constraints