From 90e86cf169699dacc8858d3845b8a8e3e2870103 Mon Sep 17 00:00:00 2001 From: Matt Moore Date: Thu, 14 Apr 2022 14:15:21 -0700 Subject: [PATCH] Switch to `ghcr.io/distroless/busybox` for `shell-image` This is very similar to #4758 and #4717 but for `shell-image`. This switches the default user of the `shell-image` to `nonroot`, which forces Tekton to be explicit about all of the places it needs a shell as `root` using `runAsUser: 0`. This also switches things over to a much leaner `busybox` image (no `glibc`), which is the main thing we use `base:debug` for with the OG distroless images. Fixes: #4761 Related: #4752 --- config/controller.yaml | 8 ++- .../resource/v1alpha1/storage/artifact_pvc.go | 19 +++++-- .../v1alpha1/storage/artifact_pvc_test.go | 15 +++-- .../taskrun/resources/output_resource_test.go | 57 +++++++++++++------ 4 files changed, 72 insertions(+), 27 deletions(-) diff --git a/config/controller.yaml b/config/controller.yaml index 20df625538d..4e174f15a14 100644 --- a/config/controller.yaml +++ b/config/controller.yaml @@ -75,10 +75,12 @@ spec: # This is gcr.io/google.com/cloudsdktool/cloud-sdk:302.0.0-slim "-gsutil-image", "gcr.io/google.com/cloudsdktool/cloud-sdk@sha256:27b2c22bf259d9bc1a291e99c63791ba0c27a04d2db0a43241ba0f1f20f4067f", - # The shell image must be root in order to create directories and copy files to PVCs. - # gcr.io/distroless/base:debug as of February 17, 2022 + + # The shell image must allow root in order to create directories and copy files to PVCs. + # ghcr.io/distroless/busybox as of April 14 2022 # image shall not contains tag, so it will be supported on a runtime like cri-o - "-shell-image", "gcr.io/distroless/base@sha256:3cebc059e7e52a4f5a389aa6788ac2b582227d7953933194764ea434f4d70d64", + "-shell-image", "ghcr.io/distroless/busybox@sha256:19f02276bf8dbdd62f069b922f10c65262cc34b710eea26ff928129a736be791", + # for script mode to work with windows we need a powershell image # pinning to nanoserver tag as of July 15 2021 "-shell-image-win", "mcr.microsoft.com/powershell:nanoserver@sha256:b6d5ff841b78bdf2dfed7550000fd4f3437385b8fa686ec0f010be24777654d6", diff --git a/pkg/apis/resource/v1alpha1/storage/artifact_pvc.go b/pkg/apis/resource/v1alpha1/storage/artifact_pvc.go index 27560dfec55..80c882ad3d6 100644 --- a/pkg/apis/resource/v1alpha1/storage/artifact_pvc.go +++ b/pkg/apis/resource/v1alpha1/storage/artifact_pvc.go @@ -23,6 +23,7 @@ import ( "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1beta1" "github.com/tektoncd/pipeline/pkg/names" corev1 "k8s.io/api/core/v1" + "knative.dev/pkg/ptr" ) var ( @@ -64,13 +65,23 @@ func (p *ArtifactPVC) GetCopyFromStorageToSteps(name, sourcePath, destinationPat // GetCopyToStorageFromSteps returns a container used to upload artifacts for temporary storage. func (p *ArtifactPVC) GetCopyToStorageFromSteps(name, sourcePath, destinationPath string) []v1beta1.Step { return []v1beta1.Step{{Container: corev1.Container{ - Name: names.SimpleNameGenerator.RestrictLengthWithRandomSuffix(fmt.Sprintf("source-mkdir-%s", name)), - Image: p.ShellImage, + Name: names.SimpleNameGenerator.RestrictLengthWithRandomSuffix(fmt.Sprintf("source-mkdir-%s", name)), + Image: p.ShellImage, + // This requires us to run as root, and the ShellImage is nonroot + // by default. + SecurityContext: &corev1.SecurityContext{ + RunAsUser: ptr.Int64(0), + }, Command: []string{"mkdir", "-p", destinationPath}, VolumeMounts: []corev1.VolumeMount{GetPvcMount(p.Name)}, }}, {Container: corev1.Container{ - Name: names.SimpleNameGenerator.RestrictLengthWithRandomSuffix(fmt.Sprintf("source-copy-%s", name)), - Image: p.ShellImage, + Name: names.SimpleNameGenerator.RestrictLengthWithRandomSuffix(fmt.Sprintf("source-copy-%s", name)), + Image: p.ShellImage, + // This requires us to run as root, and the ShellImage is nonroot + // by default. + SecurityContext: &corev1.SecurityContext{ + RunAsUser: ptr.Int64(0), + }, Command: []string{"cp", "-r", fmt.Sprintf("%s/.", sourcePath), destinationPath}, VolumeMounts: []corev1.VolumeMount{GetPvcMount(p.Name)}, Env: []corev1.EnvVar{{ diff --git a/pkg/apis/resource/v1alpha1/storage/artifact_pvc_test.go b/pkg/apis/resource/v1alpha1/storage/artifact_pvc_test.go index 53f104af884..011c79e8c5c 100644 --- a/pkg/apis/resource/v1alpha1/storage/artifact_pvc_test.go +++ b/pkg/apis/resource/v1alpha1/storage/artifact_pvc_test.go @@ -26,6 +26,7 @@ import ( "github.com/tektoncd/pipeline/test/names" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "knative.dev/pkg/ptr" ) func TestPVCGetCopyFromContainerSpec(t *testing.T) { @@ -57,13 +58,19 @@ func TestPVCGetCopyToContainerSpec(t *testing.T) { ShellImage: "busybox", } want := []v1beta1.Step{{Container: corev1.Container{ - Name: "source-mkdir-workspace-9l9zj", - Image: "busybox", + Name: "source-mkdir-workspace-9l9zj", + Image: "busybox", + SecurityContext: &corev1.SecurityContext{ + RunAsUser: ptr.Int64(0), + }, Command: []string{"mkdir", "-p", "/workspace/destination"}, VolumeMounts: []corev1.VolumeMount{{MountPath: "/pvc", Name: "pipelinerun-pvc"}}, }}, {Container: corev1.Container{ - Name: "source-copy-workspace-mz4c7", - Image: "busybox", + Name: "source-copy-workspace-mz4c7", + Image: "busybox", + SecurityContext: &corev1.SecurityContext{ + RunAsUser: ptr.Int64(0), + }, Command: []string{"cp", "-r", "src-path/.", "/workspace/destination"}, VolumeMounts: []corev1.VolumeMount{{MountPath: "/pvc", Name: "pipelinerun-pvc"}}, Env: []corev1.EnvVar{{Name: "TEKTON_RESOURCE_NAME", Value: "workspace"}}, diff --git a/pkg/reconciler/taskrun/resources/output_resource_test.go b/pkg/reconciler/taskrun/resources/output_resource_test.go index 85e52e3d5bb..165fa7da7d4 100644 --- a/pkg/reconciler/taskrun/resources/output_resource_test.go +++ b/pkg/reconciler/taskrun/resources/output_resource_test.go @@ -31,6 +31,7 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" fakek8s "k8s.io/client-go/kubernetes/fake" + "knative.dev/pkg/ptr" ) var ( @@ -224,16 +225,22 @@ func TestValidOutputResources(t *testing.T) { Image: "busybox", Command: []string{"mkdir", "-p", "/workspace/output/source-workspace"}, }}, {Container: corev1.Container{ - Name: "source-mkdir-source-git-mz4c7", - Image: "busybox", + Name: "source-mkdir-source-git-mz4c7", + Image: "busybox", + SecurityContext: &corev1.SecurityContext{ + RunAsUser: ptr.Int64(0), + }, Command: []string{"mkdir", "-p", "pipeline-task-name"}, VolumeMounts: []corev1.VolumeMount{{ Name: "pipelinerun-pvc", MountPath: "/pvc", }}, }}, {Container: corev1.Container{ - Name: "source-copy-source-git-mssqb", - Image: "busybox", + Name: "source-copy-source-git-mssqb", + Image: "busybox", + SecurityContext: &corev1.SecurityContext{ + RunAsUser: ptr.Int64(0), + }, Command: []string{"cp", "-r", "/workspace/output/source-workspace/.", "pipeline-task-name"}, VolumeMounts: []corev1.VolumeMount{{ Name: "pipelinerun-pvc", @@ -298,16 +305,22 @@ func TestValidOutputResources(t *testing.T) { Image: "busybox", Command: []string{"mkdir", "-p", "/workspace/output/source-workspace"}, }}, {Container: corev1.Container{ - Name: "source-mkdir-source-git-mz4c7", - Image: "busybox", + Name: "source-mkdir-source-git-mz4c7", + Image: "busybox", + SecurityContext: &corev1.SecurityContext{ + RunAsUser: ptr.Int64(0), + }, Command: []string{"mkdir", "-p", "pipeline-task-name"}, VolumeMounts: []corev1.VolumeMount{{ Name: "pipelinerun-pvc", MountPath: "/pvc", }}, }}, {Container: corev1.Container{ - Name: "source-copy-source-git-mssqb", - Image: "busybox", + Name: "source-copy-source-git-mssqb", + Image: "busybox", + SecurityContext: &corev1.SecurityContext{ + RunAsUser: ptr.Int64(0), + }, Command: []string{"cp", "-r", "/workspace/output/source-workspace/.", "pipeline-task-name"}, VolumeMounts: []corev1.VolumeMount{{ Name: "pipelinerun-pvc", @@ -476,14 +489,20 @@ func TestValidOutputResources(t *testing.T) { Command: []string{"mkdir", "-p", "/workspace/output/source-workspace"}, }}, {Container: corev1.Container{ - Name: "source-mkdir-source-gcs-mz4c7", - Image: "busybox", + Name: "source-mkdir-source-gcs-mz4c7", + Image: "busybox", + SecurityContext: &corev1.SecurityContext{ + RunAsUser: ptr.Int64(0), + }, Command: []string{"mkdir", "-p", "pipeline-task-path"}, VolumeMounts: []corev1.VolumeMount{{Name: "pipelinerun-parent-pvc", MountPath: "/pvc"}}, }}, {Container: corev1.Container{ - Name: "source-copy-source-gcs-mssqb", - Image: "busybox", + Name: "source-copy-source-gcs-mssqb", + Image: "busybox", + SecurityContext: &corev1.SecurityContext{ + RunAsUser: ptr.Int64(0), + }, Command: []string{"cp", "-r", "/workspace/output/source-workspace/.", "pipeline-task-path"}, VolumeMounts: []corev1.VolumeMount{{Name: "pipelinerun-parent-pvc", MountPath: "/pvc"}}, Env: []corev1.EnvVar{ @@ -570,14 +589,20 @@ func TestValidOutputResources(t *testing.T) { Command: []string{"mkdir", "-p", "/workspace/output/source-workspace"}, }}, {Container: corev1.Container{ - Name: "source-mkdir-source-gcs-mz4c7", - Image: "busybox", + Name: "source-mkdir-source-gcs-mz4c7", + Image: "busybox", + SecurityContext: &corev1.SecurityContext{ + RunAsUser: ptr.Int64(0), + }, Command: []string{"mkdir", "-p", "pipeline-task-path"}, VolumeMounts: []corev1.VolumeMount{{Name: "pipelinerun-pvc", MountPath: "/pvc"}}, }}, {Container: corev1.Container{ - Name: "source-copy-source-gcs-mssqb", - Image: "busybox", + Name: "source-copy-source-gcs-mssqb", + Image: "busybox", + SecurityContext: &corev1.SecurityContext{ + RunAsUser: ptr.Int64(0), + }, Command: []string{"cp", "-r", "/workspace/output/source-workspace/.", "pipeline-task-path"}, VolumeMounts: []corev1.VolumeMount{{Name: "pipelinerun-pvc", MountPath: "/pvc"}}, Env: []corev1.EnvVar{