From c0674fb0d670f20be419bb27b1a5471f6289b535 Mon Sep 17 00:00:00 2001 From: Francesco Pantano Date: Mon, 9 Sep 2024 13:02:56 +0200 Subject: [PATCH] Run glance-api as privileged container when image cache is enabled ImageCache currently uses two different cronJobs associated to each glance-api instance (-cleaner and -pruner cronJobs). They mount /var/lib/glance/image-cache, a RWO Pvc, and execute a glance utility on the filestem owned by glance kolla user/group. Without glance-api being privileged, after the cronJob execution the Glance Pod is not able to access the image-cache path anymore, resulting in a Permission denied error. This patch defines a FSGroup that should be set at Pod level to make sure we always have the right privileges on the container fs, and, in addition, it runs glance-api as a privileged container when Cache is enabled. Jira: https://issues.redhat.com/browse/OSPRH-9842 Signed-off-by: Francesco Pantano --- controllers/glanceapi_controller.go | 2 ++ pkg/glance/funcs.go | 14 +++++++++----- pkg/glanceapi/cachejob.go | 13 +++++++------ pkg/glanceapi/statefulset.go | 3 +++ 4 files changed, 21 insertions(+), 11 deletions(-) diff --git a/controllers/glanceapi_controller.go b/controllers/glanceapi_controller.go index 2ddd41e2..e6b72a71 100644 --- a/controllers/glanceapi_controller.go +++ b/controllers/glanceapi_controller.go @@ -802,6 +802,8 @@ func (r *GlanceAPIReconciler) reconcileNormal( // This is currently required because cleaner and pruner cronJobs // mount the same pvc to clean data present in /var/lib/glance/image-cache + // TODO (fpantano) reference a Glance spec/proposal to move to a different + // approach if len(instance.Spec.ImageCache.Size) > 0 { privileged = true } diff --git a/pkg/glance/funcs.go b/pkg/glance/funcs.go index 78767150..aabcbb56 100644 --- a/pkg/glance/funcs.go +++ b/pkg/glance/funcs.go @@ -65,6 +65,7 @@ func BaseSecurityContext() *corev1.SecurityContext { func APISecurityContext(userID int64, privileged bool) *corev1.SecurityContext { runAsUser := int64(userID) trueVal := true + return &corev1.SecurityContext{ AllowPrivilegeEscalation: &trueVal, RunAsUser: &runAsUser, @@ -77,16 +78,19 @@ func APISecurityContext(userID int64, privileged bool) *corev1.SecurityContext { // HttpdSecurityContext - func HttpdSecurityContext() *corev1.SecurityContext { - runAsUser := int64(0) - falseVal := false + runAsUser := int64(GlanceUID) + runAsGroup := int64(GlanceGID) + trueVal := true + return &corev1.SecurityContext{ - AllowPrivilegeEscalation: &falseVal, + AllowPrivilegeEscalation: &trueVal, Capabilities: &corev1.Capabilities{ Drop: []corev1.Capability{ - "ALL", + "MKNOD", }, }, - RunAsUser: &runAsUser, + RunAsUser: &runAsUser, + RunAsGroup: &runAsGroup, SeccompProfile: &corev1.SeccompProfile{ Type: corev1.SeccompProfileTypeRuntimeDefault, }, diff --git a/pkg/glanceapi/cachejob.go b/pkg/glanceapi/cachejob.go index 2f421d83..eee87b85 100644 --- a/pkg/glanceapi/cachejob.go +++ b/pkg/glanceapi/cachejob.go @@ -31,7 +31,7 @@ func ImageCacheJob( instance *glancev1.GlanceAPI, cronSpec glance.CronJobSpec, ) *batchv1.CronJob { - runAsUser := int64(0) + userID := glance.GlanceUID var config0644AccessMode int32 = 0644 cronCommand := fmt.Sprintf( @@ -100,6 +100,9 @@ func ImageCacheJob( Completions: &completions, Template: corev1.PodTemplateSpec{ Spec: corev1.PodSpec{ + SecurityContext: &corev1.PodSecurityContext{ + FSGroup: &userID, + }, Affinity: GetGlanceAPIPodAffinity(instance), Containers: []corev1.Container{ { @@ -108,11 +111,9 @@ func ImageCacheJob( Command: []string{ "/bin/bash", }, - Args: args, - VolumeMounts: cronJobVolumeMounts, - SecurityContext: &corev1.SecurityContext{ - RunAsUser: &runAsUser, - }, + Args: args, + VolumeMounts: cronJobVolumeMounts, + SecurityContext: glance.BaseSecurityContext(), }, }, Volumes: cronJobVolume, diff --git a/pkg/glanceapi/statefulset.go b/pkg/glanceapi/statefulset.go index 63f00063..e050b3e2 100644 --- a/pkg/glanceapi/statefulset.go +++ b/pkg/glanceapi/statefulset.go @@ -179,6 +179,9 @@ func StatefulSet( Labels: labels, }, Spec: corev1.PodSpec{ + SecurityContext: &corev1.PodSecurityContext{ + FSGroup: &userID, + }, ServiceAccountName: instance.Spec.ServiceAccount, // When using Cinder we run as privileged, but also some // commands need to be run on the host using nsenter (eg: