diff --git a/pipeline-runner/internal/tekton/tekton.go b/pipeline-runner/internal/tekton/tekton.go index 5c1e8a8eb..db6d90e64 100644 --- a/pipeline-runner/internal/tekton/tekton.go +++ b/pipeline-runner/internal/tekton/tekton.go @@ -109,7 +109,6 @@ func getJobVolumes() []corev1.Volume { }, }, } - return volumes } diff --git a/pipeline-runner/model/pipelineInfo.go b/pipeline-runner/model/pipelineInfo.go index e6cabe412..aa52adbb5 100644 --- a/pipeline-runner/model/pipelineInfo.go +++ b/pipeline-runner/model/pipelineInfo.go @@ -5,6 +5,7 @@ import ( "strings" "time" + "github.com/equinor/radix-common/utils/pointers" "github.com/equinor/radix-common/utils/slice" application "github.com/equinor/radix-operator/pkg/apis/applicationconfig" dnsaliasconfig "github.com/equinor/radix-operator/pkg/apis/config/dnsalias" @@ -129,7 +130,8 @@ func InitPipeline(pipelineType *pipeline.Definition, containerSecContext := securitycontext.Container(securitycontext.WithContainerDropAllCapabilities(), securitycontext.WithContainerSeccompProfileType(corev1.SeccompProfileTypeRuntimeDefault), securitycontext.WithContainerRunAsGroup(defaults.SecurityContextRunAsGroup), - securitycontext.WithContainerRunAsUser(defaults.SecurityContextRunAsUser)) + securitycontext.WithContainerRunAsUser(defaults.SecurityContextRunAsUser), + securitycontext.WithReadOnlyRootFileSystem(pointers.Ptr(true))) pipelineArguments.ContainerSecurityContext = *containerSecContext pipelineArguments.PodSecurityContext = *podSecContext diff --git a/pipeline-runner/steps/build_acr.go b/pipeline-runner/steps/build_acr.go index 4d5fcae0f..7dd0c2eeb 100644 --- a/pipeline-runner/steps/build_acr.go +++ b/pipeline-runner/steps/build_acr.go @@ -26,10 +26,12 @@ import ( ) const ( - buildSecretsMountPath = "/build-secrets" - privateImageHubMountPath = "/radix-private-image-hubs" - buildahRegistryAuthFile = "/home/build/auth.json" - azureServicePrincipleContext = "/radix-image-builder/.azure" + buildSecretsMountPath = "/build-secrets" + privateImageHubMountPath = "/radix-private-image-hubs" + buildahRegistryAuthFile = "/home/build/auth.json" + azureServicePrincipleContext = "/radix-image-builder/.azure" + RadixImageBuilderHomeVolumeName = "radix-image-builder-home" + RadixImageBuilderTmpVolumeName = "radix-image-builder-tmp" ) func (step *BuildStepImplementation) buildContainerImageBuildingJobs(pipelineInfo *model.PipelineInfo, buildSecrets []corev1.EnvVar) ([]*batchv1.Job, error) { @@ -159,6 +161,22 @@ func getContainerImageBuildingJobVolumes(defaultMode *int32, buildSecrets []core }, }, }, + { + Name: RadixImageBuilderTmpVolumeName, + VolumeSource: corev1.VolumeSource{ + EmptyDir: &corev1.EmptyDirVolumeSource{ + SizeLimit: resource.NewScaledQuantity(1, resource.Mega), + }, + }, + }, + { + Name: RadixImageBuilderHomeVolumeName, + VolumeSource: corev1.VolumeSource{ + EmptyDir: &corev1.EmptyDirVolumeSource{ + SizeLimit: resource.NewScaledQuantity(5, resource.Mega), + }, + }, + }, } if len(buildSecrets) > 0 { @@ -394,6 +412,16 @@ func getContainerImageBuildingJobVolumeMounts(buildSecrets []corev1.EnvVar, moun MountPath: azureServicePrincipleContext, ReadOnly: true, }, + { + Name: RadixImageBuilderTmpVolumeName, // image-builder creates a script there + MountPath: "/tmp", + ReadOnly: false, + }, + { + Name: RadixImageBuilderHomeVolumeName, // .azure folder is created in the user home folder + MountPath: "/home/radix-image-builder", + ReadOnly: false, + }, } if mountPrivateImageHubAuth { diff --git a/pipeline-runner/steps/build_test.go b/pipeline-runner/steps/build_test.go index 228c244b2..7533656de 100644 --- a/pipeline-runner/steps/build_test.go +++ b/pipeline-runner/steps/build_test.go @@ -28,6 +28,7 @@ import ( prometheusfake "github.com/prometheus-operator/prometheus-operator/pkg/client/versioned/fake" "github.com/stretchr/testify/suite" corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/api/resource" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" kubefake "k8s.io/client-go/kubernetes/fake" ) @@ -163,6 +164,8 @@ func (s *buildTestSuite) Test_BuildDeploy_JobSpecAndDeploymentConsistent() { {Name: git.GitSSHKeyVolumeName, VolumeSource: corev1.VolumeSource{Secret: &corev1.SecretVolumeSource{SecretName: git.GitSSHKeyVolumeName, DefaultMode: pointers.Ptr[int32](256)}}}, {Name: defaults.AzureACRServicePrincipleSecretName, VolumeSource: corev1.VolumeSource{Secret: &corev1.SecretVolumeSource{SecretName: defaults.AzureACRServicePrincipleSecretName}}}, {Name: defaults.PrivateImageHubSecretName, VolumeSource: corev1.VolumeSource{Secret: &corev1.SecretVolumeSource{SecretName: defaults.PrivateImageHubSecretName}}}, + {Name: steps.RadixImageBuilderTmpVolumeName, VolumeSource: corev1.VolumeSource{EmptyDir: &corev1.EmptyDirVolumeSource{SizeLimit: resource.NewScaledQuantity(1, resource.Mega)}}}, + {Name: steps.RadixImageBuilderHomeVolumeName, VolumeSource: corev1.VolumeSource{EmptyDir: &corev1.EmptyDirVolumeSource{SizeLimit: resource.NewScaledQuantity(5, resource.Mega)}}}, } s.ElementsMatch(expectedVolumes, job.Spec.Template.Spec.Volumes) @@ -187,6 +190,8 @@ func (s *buildTestSuite) Test_BuildDeploy_JobSpecAndDeploymentConsistent() { expectedBuildVolumeMounts := []corev1.VolumeMount{ {Name: git.BuildContextVolumeName, MountPath: git.Workspace}, {Name: defaults.AzureACRServicePrincipleSecretName, MountPath: "/radix-image-builder/.azure", ReadOnly: true}, + {Name: steps.RadixImageBuilderTmpVolumeName, MountPath: "/tmp", ReadOnly: false}, + {Name: steps.RadixImageBuilderHomeVolumeName, MountPath: "/home/radix-image-builder", ReadOnly: false}, } s.ElementsMatch(expectedBuildVolumeMounts, job.Spec.Template.Spec.Containers[0].VolumeMounts) expectedEnv := []corev1.EnvVar{ @@ -1339,13 +1344,13 @@ func (s *buildTestSuite) Test_BuildJobSpec_WithBuildSecrets() { jobs, _ := s.kubeClient.BatchV1().Jobs(utils.GetAppNamespace(appName)).List(context.Background(), metav1.ListOptions{}) s.Require().Len(jobs.Items, 1) job := jobs.Items[0] - s.Len(job.Spec.Template.Spec.Volumes, 5) + s.Len(job.Spec.Template.Spec.Volumes, 7) expectedVolumes := []corev1.Volume{ {Name: defaults.BuildSecretsName, VolumeSource: corev1.VolumeSource{Secret: &corev1.SecretVolumeSource{SecretName: defaults.BuildSecretsName}}}, } s.Subset(job.Spec.Template.Spec.Volumes, expectedVolumes) s.Require().Len(job.Spec.Template.Spec.Containers, 1) - s.Len(job.Spec.Template.Spec.Containers[0].VolumeMounts, 3) + s.Len(job.Spec.Template.Spec.Containers[0].VolumeMounts, 5) expectedVolumeMounts := []corev1.VolumeMount{ {Name: defaults.BuildSecretsName, MountPath: "/build-secrets", ReadOnly: true}, } @@ -1565,13 +1570,13 @@ func (s *buildTestSuite) Test_BuildJobSpec_BuildKit_WithBuildSecrets() { jobs, _ := s.kubeClient.BatchV1().Jobs(utils.GetAppNamespace(appName)).List(context.Background(), metav1.ListOptions{}) s.Require().Len(jobs.Items, 1) job := jobs.Items[0] - s.Len(job.Spec.Template.Spec.Volumes, 5) + s.Len(job.Spec.Template.Spec.Volumes, 7) expectedVolumes := []corev1.Volume{ {Name: defaults.BuildSecretsName, VolumeSource: corev1.VolumeSource{Secret: &corev1.SecretVolumeSource{SecretName: defaults.BuildSecretsName}}}, } s.Subset(job.Spec.Template.Spec.Volumes, expectedVolumes) s.Require().Len(job.Spec.Template.Spec.Containers, 1) - s.Len(job.Spec.Template.Spec.Containers[0].VolumeMounts, 4) + s.Len(job.Spec.Template.Spec.Containers[0].VolumeMounts, 6) expectedVolumeMounts := []corev1.VolumeMount{ {Name: defaults.BuildSecretsName, MountPath: "/build-secrets", ReadOnly: true}, } diff --git a/pkg/apis/job/job_test.go b/pkg/apis/job/job_test.go index 68eefb8b0..d9b93bff8 100644 --- a/pkg/apis/job/job_test.go +++ b/pkg/apis/job/job_test.go @@ -233,6 +233,7 @@ func (s *RadixJobTestSuite) TestObjectSynced_PipelineJobCreated() { Privileged: pointers.Ptr(false), AllowPrivilegeEscalation: pointers.Ptr(false), RunAsNonRoot: pointers.Ptr(true), + ReadOnlyRootFilesystem: pointers.Ptr(true), RunAsUser: pointers.Ptr[int64](1000), RunAsGroup: pointers.Ptr[int64](1000), Capabilities: &corev1.Capabilities{Drop: []corev1.Capability{"ALL"}}, diff --git a/pkg/apis/job/kubejob.go b/pkg/apis/job/kubejob.go index 749732d21..86c0f7fd6 100644 --- a/pkg/apis/job/kubejob.go +++ b/pkg/apis/job/kubejob.go @@ -7,6 +7,7 @@ import ( "strings" "github.com/equinor/radix-common/utils/maps" + "github.com/equinor/radix-common/utils/pointers" "github.com/equinor/radix-operator/pkg/apis/defaults" "github.com/equinor/radix-operator/pkg/apis/kube" pipelineJob "github.com/equinor/radix-operator/pkg/apis/pipeline" @@ -103,7 +104,8 @@ func (job *Job) getPipelineJobConfig() (*batchv1.Job, error) { securitycontext.WithContainerDropAllCapabilities(), securitycontext.WithContainerSeccompProfileType(corev1.SeccompProfileTypeRuntimeDefault), securitycontext.WithContainerRunAsGroup(runAsGroup), - securitycontext.WithContainerRunAsUser(runAsUser)), + securitycontext.WithContainerRunAsUser(runAsUser), + securitycontext.WithReadOnlyRootFileSystem(pointers.Ptr(true))), }, }, RestartPolicy: "Never", diff --git a/pkg/apis/utils/git/clone.go b/pkg/apis/utils/git/clone.go index 4f984d348..dce18e928 100644 --- a/pkg/apis/utils/git/clone.go +++ b/pkg/apis/utils/git/clone.go @@ -2,6 +2,7 @@ package git import ( "fmt" + corev1 "k8s.io/api/core/v1" )