From dc160baab59d49e9b5e88e84d925d6241fd52261 Mon Sep 17 00:00:00 2001 From: Per Goncalves da Silva Date: Mon, 13 Jun 2022 20:11:54 +0200 Subject: [PATCH] Update unpack job pod security (#2793) * Update unpack job security Signed-off-by: perdasilva * Refactor catsrc pod creation to use security package Signed-off-by: perdasilva Upstream-repository: operator-lifecycle-manager Upstream-commit: eedad287de8d2326e2ad1f701737df1fb8d38756 --- .../pkg/controller/bundle/bundle_unpacker.go | 5 ++ .../controller/bundle/bundle_unpacker_test.go | 57 +++++++++++++++++-- .../registry/reconciler/reconciler.go | 26 ++------- .../registry/reconciler/reconciler_test.go | 2 + .../pkg/controller/security/security.go | 42 ++++++++++++++ .../pkg/controller/bundle/bundle_unpacker.go | 5 ++ .../registry/reconciler/reconciler.go | 26 ++------- .../pkg/controller/security/security.go | 42 ++++++++++++++ vendor/modules.txt | 1 + 9 files changed, 157 insertions(+), 49 deletions(-) create mode 100644 staging/operator-lifecycle-manager/pkg/controller/security/security.go create mode 100644 vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/controller/security/security.go diff --git a/staging/operator-lifecycle-manager/pkg/controller/bundle/bundle_unpacker.go b/staging/operator-lifecycle-manager/pkg/controller/bundle/bundle_unpacker.go index 55665aada6..f97a6a27d9 100644 --- a/staging/operator-lifecycle-manager/pkg/controller/bundle/bundle_unpacker.go +++ b/staging/operator-lifecycle-manager/pkg/controller/bundle/bundle_unpacker.go @@ -28,6 +28,7 @@ import ( listersoperatorsv1alpha1 "github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/listers/operators/v1alpha1" "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/install" "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver/projection" + "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/security" ) const ( @@ -190,6 +191,10 @@ func (c *ConfigMapUnpacker) job(cmRef *corev1.ObjectReference, bundlePath string }, }, } + + // Apply Pod security + security.ApplyPodSpecSecurity(&job.Spec.Template.Spec) + job.SetNamespace(cmRef.Namespace) job.SetName(cmRef.Name) job.SetOwnerReferences([]metav1.OwnerReference{ownerRef(cmRef)}) diff --git a/staging/operator-lifecycle-manager/pkg/controller/bundle/bundle_unpacker_test.go b/staging/operator-lifecycle-manager/pkg/controller/bundle/bundle_unpacker_test.go index 4e580ffc36..878c739f0a 100644 --- a/staging/operator-lifecycle-manager/pkg/controller/bundle/bundle_unpacker_test.go +++ b/staging/operator-lifecycle-manager/pkg/controller/bundle/bundle_unpacker_test.go @@ -68,6 +68,29 @@ func TestConfigMapUnpacker(t *testing.T) { roleBindings []*rbacv1.RoleBinding } + var expectedReadOnlyRootFilesystem = false + var expectedAllowPrivilegeEscalation = false + var expectedRunAsNonRoot = true + var expectedRunAsUser int64 = 1001 + var expectedPrivileged = false + + var expectedContainerSecurityContext = &corev1.SecurityContext{ + Privileged: &expectedPrivileged, + ReadOnlyRootFilesystem: &expectedReadOnlyRootFilesystem, + AllowPrivilegeEscalation: &expectedAllowPrivilegeEscalation, + Capabilities: &corev1.Capabilities{ + Drop: []corev1.Capability{"ALL"}, + }, + } + + var expectedPodSecurityContext = &corev1.PodSecurityContext{ + RunAsNonRoot: &expectedRunAsNonRoot, + RunAsUser: &expectedRunAsUser, + SeccompProfile: &corev1.SeccompProfile{ + Type: corev1.SeccompProfileTypeRuntimeDefault, + }, + } + tests := []struct { description string fields fields @@ -220,6 +243,7 @@ func TestConfigMapUnpacker(t *testing.T) { Spec: corev1.PodSpec{ RestartPolicy: corev1.RestartPolicyNever, ImagePullSecrets: []corev1.LocalObjectReference{{Name: "my-secret"}}, + SecurityContext: expectedPodSecurityContext, Containers: []corev1.Container{ { Name: "extract", @@ -243,6 +267,7 @@ func TestConfigMapUnpacker(t *testing.T) { corev1.ResourceMemory: resource.MustParse("50Mi"), }, }, + SecurityContext: expectedContainerSecurityContext, }, }, InitContainers: []corev1.Container{ @@ -262,6 +287,7 @@ func TestConfigMapUnpacker(t *testing.T) { corev1.ResourceMemory: resource.MustParse("50Mi"), }, }, + SecurityContext: expectedContainerSecurityContext, }, { Name: "pull", @@ -284,6 +310,7 @@ func TestConfigMapUnpacker(t *testing.T) { corev1.ResourceMemory: resource.MustParse("50Mi"), }, }, + SecurityContext: expectedContainerSecurityContext, }, }, Volumes: []corev1.Volume{ @@ -396,7 +423,8 @@ func TestConfigMapUnpacker(t *testing.T) { Name: pathHash, }, Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyNever, + RestartPolicy: corev1.RestartPolicyNever, + SecurityContext: expectedPodSecurityContext, Containers: []corev1.Container{ { Name: "extract", @@ -420,6 +448,7 @@ func TestConfigMapUnpacker(t *testing.T) { corev1.ResourceMemory: resource.MustParse("50Mi"), }, }, + SecurityContext: expectedContainerSecurityContext, }, }, InitContainers: []corev1.Container{ @@ -439,6 +468,7 @@ func TestConfigMapUnpacker(t *testing.T) { corev1.ResourceMemory: resource.MustParse("50Mi"), }, }, + SecurityContext: expectedContainerSecurityContext, }, { Name: "pull", @@ -461,6 +491,7 @@ func TestConfigMapUnpacker(t *testing.T) { corev1.ResourceMemory: resource.MustParse("50Mi"), }, }, + SecurityContext: expectedContainerSecurityContext, }, }, Volumes: []corev1.Volume{ @@ -614,7 +645,8 @@ func TestConfigMapUnpacker(t *testing.T) { Name: pathHash, }, Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyNever, + RestartPolicy: corev1.RestartPolicyNever, + SecurityContext: expectedPodSecurityContext, Containers: []corev1.Container{ { Name: "extract", @@ -638,6 +670,7 @@ func TestConfigMapUnpacker(t *testing.T) { corev1.ResourceMemory: resource.MustParse("50Mi"), }, }, + SecurityContext: expectedContainerSecurityContext, }, }, InitContainers: []corev1.Container{ @@ -657,6 +690,7 @@ func TestConfigMapUnpacker(t *testing.T) { corev1.ResourceMemory: resource.MustParse("50Mi"), }, }, + SecurityContext: expectedContainerSecurityContext, }, { Name: "pull", @@ -679,6 +713,7 @@ func TestConfigMapUnpacker(t *testing.T) { corev1.ResourceMemory: resource.MustParse("50Mi"), }, }, + SecurityContext: expectedContainerSecurityContext, }, }, Volumes: []corev1.Volume{ @@ -826,7 +861,8 @@ func TestConfigMapUnpacker(t *testing.T) { Name: pathHash, }, Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyNever, + RestartPolicy: corev1.RestartPolicyNever, + SecurityContext: expectedPodSecurityContext, Containers: []corev1.Container{ { Name: "extract", @@ -850,6 +886,7 @@ func TestConfigMapUnpacker(t *testing.T) { corev1.ResourceMemory: resource.MustParse("50Mi"), }, }, + SecurityContext: expectedContainerSecurityContext, }, }, InitContainers: []corev1.Container{ @@ -869,6 +906,7 @@ func TestConfigMapUnpacker(t *testing.T) { corev1.ResourceMemory: resource.MustParse("50Mi"), }, }, + SecurityContext: expectedContainerSecurityContext, }, { Name: "pull", @@ -891,6 +929,7 @@ func TestConfigMapUnpacker(t *testing.T) { corev1.ResourceMemory: resource.MustParse("50Mi"), }, }, + SecurityContext: expectedContainerSecurityContext, }, }, Volumes: []corev1.Volume{ @@ -1008,7 +1047,8 @@ func TestConfigMapUnpacker(t *testing.T) { Name: pathHash, }, Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyNever, + RestartPolicy: corev1.RestartPolicyNever, + SecurityContext: expectedPodSecurityContext, Containers: []corev1.Container{ { Name: "extract", @@ -1032,6 +1072,7 @@ func TestConfigMapUnpacker(t *testing.T) { corev1.ResourceMemory: resource.MustParse("50Mi"), }, }, + SecurityContext: expectedContainerSecurityContext, }, }, InitContainers: []corev1.Container{ @@ -1051,6 +1092,7 @@ func TestConfigMapUnpacker(t *testing.T) { corev1.ResourceMemory: resource.MustParse("50Mi"), }, }, + SecurityContext: expectedContainerSecurityContext, }, { Name: "pull", @@ -1073,6 +1115,7 @@ func TestConfigMapUnpacker(t *testing.T) { corev1.ResourceMemory: resource.MustParse("50Mi"), }, }, + SecurityContext: expectedContainerSecurityContext, }, }, Volumes: []corev1.Volume{ @@ -1201,7 +1244,8 @@ func TestConfigMapUnpacker(t *testing.T) { Name: pathHash, }, Spec: corev1.PodSpec{ - RestartPolicy: corev1.RestartPolicyNever, + RestartPolicy: corev1.RestartPolicyNever, + SecurityContext: expectedPodSecurityContext, Containers: []corev1.Container{ { Name: "extract", @@ -1225,6 +1269,7 @@ func TestConfigMapUnpacker(t *testing.T) { corev1.ResourceMemory: resource.MustParse("50Mi"), }, }, + SecurityContext: expectedContainerSecurityContext, }, }, InitContainers: []corev1.Container{ @@ -1244,6 +1289,7 @@ func TestConfigMapUnpacker(t *testing.T) { corev1.ResourceMemory: resource.MustParse("50Mi"), }, }, + SecurityContext: expectedContainerSecurityContext, }, { Name: "pull", @@ -1266,6 +1312,7 @@ func TestConfigMapUnpacker(t *testing.T) { corev1.ResourceMemory: resource.MustParse("50Mi"), }, }, + SecurityContext: expectedContainerSecurityContext, }, }, Volumes: []corev1.Volume{ 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 b9f51194b1..1d8d51f5f9 100644 --- a/staging/operator-lifecycle-manager/pkg/controller/registry/reconciler/reconciler.go +++ b/staging/operator-lifecycle-manager/pkg/controller/registry/reconciler/reconciler.go @@ -12,6 +12,7 @@ import ( "k8s.io/apimachinery/pkg/util/rand" operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1" + "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/security" controllerclient "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/controller-runtime/client" hashutil "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/util/hash" "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorclient" @@ -113,14 +114,6 @@ func Pod(source *operatorsv1alpha1.CatalogSource, name string, image string, saN pullPolicy = corev1.PullAlways } - // Security context - readOnlyRootFilesystem := false - allowPrivilegeEscalation := false - runAsNonRoot := true - - // See: https://github.com/operator-framework/operator-registry/blob/master/Dockerfile#L27 - runAsUser := int64(1001) - pod := &corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ GenerateName: source.GetName() + "-", @@ -163,24 +156,10 @@ func Pod(source *operatorsv1alpha1.CatalogSource, name string, image string, saN corev1.ResourceMemory: resource.MustParse("50Mi"), }, }, - SecurityContext: &corev1.SecurityContext{ - ReadOnlyRootFilesystem: &readOnlyRootFilesystem, - AllowPrivilegeEscalation: &allowPrivilegeEscalation, - Capabilities: &corev1.Capabilities{ - Drop: []corev1.Capability{"ALL"}, - }, - }, ImagePullPolicy: pullPolicy, TerminationMessagePolicy: corev1.TerminationMessageFallbackToLogsOnError, }, }, - SecurityContext: &corev1.PodSecurityContext{ - RunAsNonRoot: &runAsNonRoot, - RunAsUser: &runAsUser, - SeccompProfile: &corev1.SeccompProfile{ - Type: corev1.SeccompProfileTypeRuntimeDefault, - }, - }, NodeSelector: map[string]string{ "kubernetes.io/os": "linux", }, @@ -188,6 +167,9 @@ func Pod(source *operatorsv1alpha1.CatalogSource, name string, image string, saN }, } + // Update pod security + security.ApplyPodSpecSecurity(&pod.Spec) + // Override scheduling options if specified if source.Spec.GrpcPodConfig != nil { grpcPodConfig := source.Spec.GrpcPodConfig diff --git a/staging/operator-lifecycle-manager/pkg/controller/registry/reconciler/reconciler_test.go b/staging/operator-lifecycle-manager/pkg/controller/registry/reconciler/reconciler_test.go index c5be126087..9177b251d8 100644 --- a/staging/operator-lifecycle-manager/pkg/controller/registry/reconciler/reconciler_test.go +++ b/staging/operator-lifecycle-manager/pkg/controller/registry/reconciler/reconciler_test.go @@ -82,8 +82,10 @@ func TestPodContainerSecurityContext(t *testing.T) { expectedAllowPrivilegeEscalation := false expectedRunAsNonRoot := true expectedRunAsUser := int64(1001) + expectedPrivileged := false expectedContainerSecCtx := &corev1.SecurityContext{ + Privileged: &expectedPrivileged, ReadOnlyRootFilesystem: &expectedReadOnlyRootFilesystem, AllowPrivilegeEscalation: &expectedAllowPrivilegeEscalation, Capabilities: &corev1.Capabilities{ diff --git a/staging/operator-lifecycle-manager/pkg/controller/security/security.go b/staging/operator-lifecycle-manager/pkg/controller/security/security.go new file mode 100644 index 0000000000..f53bab01d5 --- /dev/null +++ b/staging/operator-lifecycle-manager/pkg/controller/security/security.go @@ -0,0 +1,42 @@ +package security + +import ( + corev1 "k8s.io/api/core/v1" + "k8s.io/utils/pointer" +) + +const readOnlyRootFilesystem = false +const allowPrivilegeEscalation = false +const privileged = false +const runAsNonRoot = true + +// See: https://github.com/operator-framework/operator-registry/blob/master/Dockerfile#L27 +const runAsUser int64 = 1001 + +// ApplyPodSpecSecurity applies the standard security profile to a pod spec +func ApplyPodSpecSecurity(spec *corev1.PodSpec) { + var containerSecurityContext = &corev1.SecurityContext{ + Privileged: pointer.Bool(privileged), + ReadOnlyRootFilesystem: pointer.Bool(readOnlyRootFilesystem), + AllowPrivilegeEscalation: pointer.Bool(allowPrivilegeEscalation), + Capabilities: &corev1.Capabilities{ + Drop: []corev1.Capability{"ALL"}, + }, + } + + var podSecurityContext = &corev1.PodSecurityContext{ + RunAsNonRoot: pointer.Bool(runAsNonRoot), + RunAsUser: pointer.Int64(runAsUser), + SeccompProfile: &corev1.SeccompProfile{ + Type: corev1.SeccompProfileTypeRuntimeDefault, + }, + } + + spec.SecurityContext = podSecurityContext + for idx := 0; idx < len(spec.Containers); idx++ { + spec.Containers[idx].SecurityContext = containerSecurityContext + } + for idx := 0; idx < len(spec.InitContainers); idx++ { + spec.InitContainers[idx].SecurityContext = containerSecurityContext + } +} diff --git a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/controller/bundle/bundle_unpacker.go b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/controller/bundle/bundle_unpacker.go index 55665aada6..f97a6a27d9 100644 --- a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/controller/bundle/bundle_unpacker.go +++ b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/controller/bundle/bundle_unpacker.go @@ -28,6 +28,7 @@ import ( listersoperatorsv1alpha1 "github.com/operator-framework/operator-lifecycle-manager/pkg/api/client/listers/operators/v1alpha1" "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/install" "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver/projection" + "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/security" ) const ( @@ -190,6 +191,10 @@ func (c *ConfigMapUnpacker) job(cmRef *corev1.ObjectReference, bundlePath string }, }, } + + // Apply Pod security + security.ApplyPodSpecSecurity(&job.Spec.Template.Spec) + job.SetNamespace(cmRef.Namespace) job.SetName(cmRef.Name) job.SetOwnerReferences([]metav1.OwnerReference{ownerRef(cmRef)}) diff --git a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/reconciler/reconciler.go b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/reconciler/reconciler.go index b9f51194b1..1d8d51f5f9 100644 --- a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/reconciler/reconciler.go +++ b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/reconciler/reconciler.go @@ -12,6 +12,7 @@ import ( "k8s.io/apimachinery/pkg/util/rand" operatorsv1alpha1 "github.com/operator-framework/api/pkg/operators/v1alpha1" + "github.com/operator-framework/operator-lifecycle-manager/pkg/controller/security" controllerclient "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/controller-runtime/client" hashutil "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/kubernetes/pkg/util/hash" "github.com/operator-framework/operator-lifecycle-manager/pkg/lib/operatorclient" @@ -113,14 +114,6 @@ func Pod(source *operatorsv1alpha1.CatalogSource, name string, image string, saN pullPolicy = corev1.PullAlways } - // Security context - readOnlyRootFilesystem := false - allowPrivilegeEscalation := false - runAsNonRoot := true - - // See: https://github.com/operator-framework/operator-registry/blob/master/Dockerfile#L27 - runAsUser := int64(1001) - pod := &corev1.Pod{ ObjectMeta: metav1.ObjectMeta{ GenerateName: source.GetName() + "-", @@ -163,24 +156,10 @@ func Pod(source *operatorsv1alpha1.CatalogSource, name string, image string, saN corev1.ResourceMemory: resource.MustParse("50Mi"), }, }, - SecurityContext: &corev1.SecurityContext{ - ReadOnlyRootFilesystem: &readOnlyRootFilesystem, - AllowPrivilegeEscalation: &allowPrivilegeEscalation, - Capabilities: &corev1.Capabilities{ - Drop: []corev1.Capability{"ALL"}, - }, - }, ImagePullPolicy: pullPolicy, TerminationMessagePolicy: corev1.TerminationMessageFallbackToLogsOnError, }, }, - SecurityContext: &corev1.PodSecurityContext{ - RunAsNonRoot: &runAsNonRoot, - RunAsUser: &runAsUser, - SeccompProfile: &corev1.SeccompProfile{ - Type: corev1.SeccompProfileTypeRuntimeDefault, - }, - }, NodeSelector: map[string]string{ "kubernetes.io/os": "linux", }, @@ -188,6 +167,9 @@ func Pod(source *operatorsv1alpha1.CatalogSource, name string, image string, saN }, } + // Update pod security + security.ApplyPodSpecSecurity(&pod.Spec) + // Override scheduling options if specified if source.Spec.GrpcPodConfig != nil { grpcPodConfig := source.Spec.GrpcPodConfig diff --git a/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/controller/security/security.go b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/controller/security/security.go new file mode 100644 index 0000000000..f53bab01d5 --- /dev/null +++ b/vendor/github.com/operator-framework/operator-lifecycle-manager/pkg/controller/security/security.go @@ -0,0 +1,42 @@ +package security + +import ( + corev1 "k8s.io/api/core/v1" + "k8s.io/utils/pointer" +) + +const readOnlyRootFilesystem = false +const allowPrivilegeEscalation = false +const privileged = false +const runAsNonRoot = true + +// See: https://github.com/operator-framework/operator-registry/blob/master/Dockerfile#L27 +const runAsUser int64 = 1001 + +// ApplyPodSpecSecurity applies the standard security profile to a pod spec +func ApplyPodSpecSecurity(spec *corev1.PodSpec) { + var containerSecurityContext = &corev1.SecurityContext{ + Privileged: pointer.Bool(privileged), + ReadOnlyRootFilesystem: pointer.Bool(readOnlyRootFilesystem), + AllowPrivilegeEscalation: pointer.Bool(allowPrivilegeEscalation), + Capabilities: &corev1.Capabilities{ + Drop: []corev1.Capability{"ALL"}, + }, + } + + var podSecurityContext = &corev1.PodSecurityContext{ + RunAsNonRoot: pointer.Bool(runAsNonRoot), + RunAsUser: pointer.Int64(runAsUser), + SeccompProfile: &corev1.SeccompProfile{ + Type: corev1.SeccompProfileTypeRuntimeDefault, + }, + } + + spec.SecurityContext = podSecurityContext + for idx := 0; idx < len(spec.Containers); idx++ { + spec.Containers[idx].SecurityContext = containerSecurityContext + } + for idx := 0; idx < len(spec.InitContainers); idx++ { + spec.InitContainers[idx].SecurityContext = containerSecurityContext + } +} diff --git a/vendor/modules.txt b/vendor/modules.txt index 13652ec944..457ab034d9 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -698,6 +698,7 @@ github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver/cache github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver/projection github.com/operator-framework/operator-lifecycle-manager/pkg/controller/registry/resolver/solver +github.com/operator-framework/operator-lifecycle-manager/pkg/controller/security github.com/operator-framework/operator-lifecycle-manager/pkg/feature github.com/operator-framework/operator-lifecycle-manager/pkg/lib/catalogsource github.com/operator-framework/operator-lifecycle-manager/pkg/lib/clients