diff --git a/lib/resourcemerge/core.go b/lib/resourcemerge/core.go index 8793f6c89..a13208eb1 100644 --- a/lib/resourcemerge/core.go +++ b/lib/resourcemerge/core.go @@ -487,6 +487,7 @@ func ensureSecurityContext(modified *bool, existing *corev1.SecurityContext, req setBoolPtr(modified, &existing.RunAsNonRoot, required.RunAsNonRoot) setBoolPtr(modified, &existing.ReadOnlyRootFilesystem, required.ReadOnlyRootFilesystem) setBoolPtr(modified, &existing.AllowPrivilegeEscalation, required.AllowPrivilegeEscalation) + ensureSeccompProfilePtr(modified, &existing.SeccompProfile, required.SeccompProfile) } func ensureCapabilitiesPtr(modified *bool, existing **corev1.Capabilities, required *corev1.Capabilities) { @@ -535,6 +536,30 @@ func ensureCapabilities(modified *bool, existing *corev1.Capabilities, required } } +func ensureSeccompProfilePtr(modified *bool, existing **corev1.SeccompProfile, required *corev1.SeccompProfile) { + if *existing == nil && required == nil { + return + } + + // Check if we can simply set to required. This can be done if existing is not set or it is set + // but required is not set. + if *existing == nil || (required == nil && *existing != nil) { + *modified = true + *existing = required + return + } + ensureSeccompProfile(modified, *existing, *required) +} + +func ensureSeccompProfile(modified *bool, existing *corev1.SeccompProfile, required corev1.SeccompProfile) { + if equality.Semantic.DeepEqual(existing, required) { + return + } + + *modified = true + *existing = required +} + func setStringSlice(modified *bool, existing *[]string, required []string) { if !reflect.DeepEqual(required, *existing) { *existing = required @@ -637,6 +662,7 @@ func ensurePodSecurityContext(modified *bool, existing *corev1.PodSecurityContex setInt64Ptr(modified, &existing.RunAsUser, required.RunAsUser) setInt64Ptr(modified, &existing.RunAsGroup, required.RunAsGroup) setBoolPtr(modified, &existing.RunAsNonRoot, required.RunAsNonRoot) + ensureSeccompProfilePtr(modified, &existing.SeccompProfile, required.SeccompProfile) // any SupplementalGroups we specify, we require. for _, required := range required.SupplementalGroups { diff --git a/lib/resourcemerge/core_test.go b/lib/resourcemerge/core_test.go index b7686c3ad..8e578f792 100644 --- a/lib/resourcemerge/core_test.go +++ b/lib/resourcemerge/core_test.go @@ -44,6 +44,82 @@ func TestEnsurePodSpec(t *testing.T) { Containers: []corev1.Container{ {Name: "test"}}}, }, + { + name: "PodSecurityContext empty input wont overwrite existing", + existing: corev1.PodSpec{ + SecurityContext: &corev1.PodSecurityContext{RunAsNonRoot: pointer.BoolPtr(false), + RunAsUser: pointer.Int64Ptr(int64(1234)), + RunAsGroup: pointer.Int64Ptr(int64(1234)), + FSGroup: pointer.Int64Ptr(int64(1234)), + SELinuxOptions: &corev1.SELinuxOptions{User: "foo"}, + }}, + input: corev1.PodSpec{ + SecurityContext: &corev1.PodSecurityContext{}}, + + expected: corev1.PodSpec{ + SecurityContext: &corev1.PodSecurityContext{RunAsNonRoot: pointer.BoolPtr(false), + RunAsUser: pointer.Int64Ptr(int64(1234)), + RunAsGroup: pointer.Int64Ptr(int64(1234)), + FSGroup: pointer.Int64Ptr(int64(1234)), + SELinuxOptions: &corev1.SELinuxOptions{User: "foo"}, + }}, + }, + { + name: "PodSecurityContext changes", + existing: corev1.PodSpec{ + SecurityContext: &corev1.PodSecurityContext{RunAsNonRoot: pointer.BoolPtr(true), + RunAsUser: pointer.Int64Ptr(int64(1234)), + RunAsGroup: pointer.Int64Ptr(int64(1234))}}, + input: corev1.PodSpec{ + SecurityContext: &corev1.PodSecurityContext{RunAsNonRoot: pointer.BoolPtr(false), + RunAsGroup: pointer.Int64Ptr(int64(5)), + SeccompProfile: &corev1.SeccompProfile{Type: corev1.SeccompProfileTypeRuntimeDefault}}}, + + expectedModified: true, + expected: corev1.PodSpec{ + SecurityContext: &corev1.PodSecurityContext{RunAsNonRoot: pointer.BoolPtr(false), + RunAsUser: pointer.Int64Ptr(int64(1234)), + RunAsGroup: pointer.Int64Ptr(int64(5)), + SeccompProfile: &corev1.SeccompProfile{Type: corev1.SeccompProfileTypeRuntimeDefault}}}, + }, + { + name: "container SecurityContext none", + existing: corev1.PodSpec{ + Containers: []corev1.Container{ + {SecurityContext: &corev1.SecurityContext{RunAsNonRoot: pointer.BoolPtr(false), + RunAsUser: pointer.Int64Ptr(int64(1234)), + Capabilities: &corev1.Capabilities{ + Add: []corev1.Capability{"bar"}}, + SELinuxOptions: &corev1.SELinuxOptions{User: "foo"}, + }}}}, + input: corev1.PodSpec{}, + + expectedModified: true, + expected: corev1.PodSpec{}, + }, + { + name: "container SecurityContext empty wont overwrite existing", + existing: corev1.PodSpec{ + Containers: []corev1.Container{ + {SecurityContext: &corev1.SecurityContext{RunAsNonRoot: pointer.BoolPtr(false), + RunAsUser: pointer.Int64Ptr(int64(1234)), + Capabilities: &corev1.Capabilities{ + Add: []corev1.Capability{"bar"}}, + SELinuxOptions: &corev1.SELinuxOptions{User: "foo"}, + }}}}, + input: corev1.PodSpec{ + Containers: []corev1.Container{ + {SecurityContext: &corev1.SecurityContext{}}}}, + + expected: corev1.PodSpec{ + Containers: []corev1.Container{ + {SecurityContext: &corev1.SecurityContext{RunAsNonRoot: pointer.BoolPtr(false), + RunAsUser: pointer.Int64Ptr(int64(1234)), + Capabilities: &corev1.Capabilities{ + Add: []corev1.Capability{"bar"}}, + SELinuxOptions: &corev1.SELinuxOptions{User: "foo"}, + }}}}, + }, { name: "remove regular and init containers from existing", existing: corev1.PodSpec{