From 21db5f8853435dba445cf21b7bd09360a9622302 Mon Sep 17 00:00:00 2001 From: Scott Seago Date: Thu, 20 Feb 2025 11:53:55 -0500 Subject: [PATCH] Copy SecurityContext from Containers[0] if present for PVR Signed-off-by: Scott Seago --- changelogs/unreleased/8712-sseago | 1 + .../actions/pod_volume_restore_action.go | 19 ++++++++--- .../actions/pod_volume_restore_action_test.go | 34 +++++++++++++++++++ 3 files changed, 49 insertions(+), 5 deletions(-) create mode 100644 changelogs/unreleased/8712-sseago diff --git a/changelogs/unreleased/8712-sseago b/changelogs/unreleased/8712-sseago new file mode 100644 index 000000000..2cddc00d2 --- /dev/null +++ b/changelogs/unreleased/8712-sseago @@ -0,0 +1 @@ +Copy SecurityContext from Containers[0] if present for PVR diff --git a/pkg/restore/actions/pod_volume_restore_action.go b/pkg/restore/actions/pod_volume_restore_action.go index 1970f54fa..55d6d73db 100644 --- a/pkg/restore/actions/pod_volume_restore_action.go +++ b/pkg/restore/actions/pod_volume_restore_action.go @@ -147,7 +147,7 @@ func (a *PodVolumeRestoreAction) Execute(input *velero.RestoreItemActionExecuteI resourceReqs, err := kube.ParseResourceRequirements(cpuRequest, memRequest, cpuLimit, memLimit) if err != nil { - log.Errorf("Using default resource values, couldn't parse resource requirements: %s.", err) + log.Errorf("couldn't parse resource requirements: %s.", err) resourceReqs, _ = kube.ParseResourceRequirements( defaultCPURequestLimit, defaultMemRequestLimit, // requests defaultCPURequestLimit, defaultMemRequestLimit, // limits @@ -157,15 +157,24 @@ func (a *PodVolumeRestoreAction) Execute(input *velero.RestoreItemActionExecuteI runAsUser, runAsGroup, allowPrivilegeEscalation, secCtx := getSecurityContext(log, config) var securityContext corev1.SecurityContext - if runAsUser == "" && runAsGroup == "" && allowPrivilegeEscalation == "" && secCtx == "" { - securityContext = defaultSecurityCtx() - } else { + securityContextSet := false + // Use securityContext settings from configmap if available + if runAsUser != "" || runAsGroup != "" || allowPrivilegeEscalation != "" || secCtx != "" { securityContext, err = kube.ParseSecurityContext(runAsUser, runAsGroup, allowPrivilegeEscalation, secCtx) if err != nil { log.Errorf("Using default securityContext values, couldn't parse securityContext requirements: %s.", err) - securityContext = defaultSecurityCtx() + } else { + securityContextSet = true } } + // if first container in pod has a SecurityContext set, then copy this security context + if len(pod.Spec.Containers) != 0 && pod.Spec.Containers[0].SecurityContext != nil { + securityContext = *pod.Spec.Containers[0].SecurityContext.DeepCopy() + securityContextSet = true + } + if !securityContextSet { + securityContext = defaultSecurityCtx() + } initContainerBuilder := newRestoreInitContainerBuilder(image, string(input.Restore.UID)) initContainerBuilder.Resources(&resourceReqs) diff --git a/pkg/restore/actions/pod_volume_restore_action_test.go b/pkg/restore/actions/pod_volume_restore_action_test.go index 08a85d188..cdbdf5399 100644 --- a/pkg/restore/actions/pod_volume_restore_action_test.go +++ b/pkg/restore/actions/pod_volume_restore_action_test.go @@ -128,6 +128,18 @@ func TestPodVolumeRestoreActionExecute(t *testing.T) { RunAsUser: &id, RunAsNonRoot: boolptr.True(), } + customID := int64(44444) + customSecurityContext := corev1api.SecurityContext{ + AllowPrivilegeEscalation: boolptr.False(), + Capabilities: &corev1api.Capabilities{ + Drop: []corev1api.Capability{"ALL"}, + }, + SeccompProfile: &corev1api.SeccompProfile{ + Type: corev1api.SeccompProfileTypeRuntimeDefault, + }, + RunAsUser: &customID, + RunAsNonRoot: boolptr.True(), + } var ( restoreName = "my-restore" @@ -264,6 +276,28 @@ func TestPodVolumeRestoreActionExecute(t *testing.T) { Command([]string{"/velero-restore-helper"}).Result()). Result(), }, + { + name: "Restoring pod with custom container SecurityContext uses this SecurityContext for the restore initContainer", + pod: builder.ForPod("ns-1", "my-pod"). + ObjectMeta( + builder.WithAnnotations("snapshot.velero.io/myvol", "")). + Containers( + builder.ForContainer("app-container", "app-image"). + SecurityContext(&customSecurityContext).Result()). + Result(), + want: builder.ForPod("ns-1", "my-pod"). + ObjectMeta( + builder.WithAnnotations("snapshot.velero.io/myvol", "")). + Containers( + builder.ForContainer("app-container", "app-image"). + SecurityContext(&customSecurityContext).Result()). + InitContainers( + newRestoreInitContainerBuilder(defaultRestoreHelperImage, ""). + Resources(&resourceReqs). + SecurityContext(&customSecurityContext). + VolumeMounts(builder.ForVolumeMount("myvol", "/restores/myvol").Result()). + Command([]string{"/velero-restore-helper"}).Result()).Result(), + }, } veleroDeployment := &appsv1.Deployment{