From d7028a8ed50a64a1867fa067526971ab9183df1d Mon Sep 17 00:00:00 2001 From: Jan Safranek Date: Tue, 6 Feb 2024 13:35:56 +0100 Subject: [PATCH] Add SELinuxMount feature gate The feature gate enables mounting with -o context=XYZ mount option for all volume types, not only ReadWriteOncePod. All SELinux label tracking & error reporting infrastructure is already in place from SELinuxMountReadWriteOncePod feature gate. This is just a trivial extension to all access modes. --- pkg/features/kube_features.go | 9 +++++ .../desired_state_of_world_populator_test.go | 33 +++++++++++++++++-- .../operationexecutor/operation_executor.go | 3 ++ pkg/volume/util/selinux.go | 4 +++ 4 files changed, 47 insertions(+), 2 deletions(-) diff --git a/pkg/features/kube_features.go b/pkg/features/kube_features.go index 11999e5d235..57e5e309076 100644 --- a/pkg/features/kube_features.go +++ b/pkg/features/kube_features.go @@ -905,6 +905,13 @@ const ( // // Allows namespace indexer for namespace scope resources in apiserver cache to accelerate list operations. StorageNamespaceIndex featuregate.Feature = "StorageNamespaceIndex" + + // owner: @jsafrane + // kep: https://kep.k8s.io/1710 + // alpha: v1.30 + // Speed up container startup by mounting volumes with the correct SELinux label + // instead of changing each file on the volumes recursively. + SELinuxMount featuregate.Feature = "SELinuxMount" ) func init() { @@ -1157,6 +1164,8 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS UserNamespacesPodSecurityStandards: {Default: false, PreRelease: featuregate.Alpha}, + SELinuxMount: {Default: false, PreRelease: featuregate.Alpha}, + // inherited features from generic apiserver, relisted here to get a conflict if it is changed // unintentionally on either side: diff --git a/pkg/kubelet/volumemanager/populator/desired_state_of_world_populator_test.go b/pkg/kubelet/volumemanager/populator/desired_state_of_world_populator_test.go index ecfe79c1646..c2953243440 100644 --- a/pkg/kubelet/volumemanager/populator/desired_state_of_world_populator_test.go +++ b/pkg/kubelet/volumemanager/populator/desired_state_of_world_populator_test.go @@ -1212,6 +1212,7 @@ func TestCheckVolumeSELinux(t *testing.T) { accessModes []v1.PersistentVolumeAccessMode existingContainerSELinuxOpts *v1.SELinuxOptions newContainerSELinuxOpts *v1.SELinuxOptions + seLinuxMountFeatureEnabled bool pluginSupportsSELinux bool expectError bool expectedContext string @@ -1231,14 +1232,22 @@ func TestCheckVolumeSELinux(t *testing.T) { expectedContext: "system_u:object_r:container_file_t:s0:c3,c4", }, { - name: "RWX with plugin with SELinux with fill context in pod", + name: "RWX with plugin with SELinux with full context in pod and SELinuxMount feature disabled", accessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteMany}, newContainerSELinuxOpts: fullOpts, pluginSupportsSELinux: true, expectedContext: "", // RWX volumes don't support SELinux }, { - name: "RWOP with plugin with no SELinux with fill context in pod", + name: "RWX with plugin with SELinux with full context in pod and SELinuxMount feature enabled", + accessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteMany}, + newContainerSELinuxOpts: fullOpts, + pluginSupportsSELinux: true, + seLinuxMountFeatureEnabled: true, + expectedContext: "system_u:object_r:container_file_t:s0:c1,c2", + }, + { + name: "RWOP with plugin with no SELinux with full context in pod", accessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOncePod}, newContainerSELinuxOpts: fullOpts, pluginSupportsSELinux: false, @@ -1267,6 +1276,25 @@ func TestCheckVolumeSELinux(t *testing.T) { pluginSupportsSELinux: true, expectedContext: "", }, + { + name: "mismatched SELinux with RWX and SELinuxMount feature disabled", + accessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteMany}, + existingContainerSELinuxOpts: fullOpts, + newContainerSELinuxOpts: differentFullOpts, + pluginSupportsSELinux: true, + expectedContext: "", + }, + { + name: "mismatched SELinux with RWX and SELinuxMount feature enabled", + accessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteMany}, + existingContainerSELinuxOpts: fullOpts, + newContainerSELinuxOpts: differentFullOpts, + pluginSupportsSELinux: true, + seLinuxMountFeatureEnabled: true, + expectError: true, + // The original seLinuxOpts are kept in DSW + expectedContext: "system_u:object_r:container_file_t:s0:c1,c2", + }, { name: "mismatched SELinux with RWOP - failure", accessModes: []v1.PersistentVolumeAccessMode{v1.ReadWriteOncePod}, @@ -1319,6 +1347,7 @@ func TestCheckVolumeSELinux(t *testing.T) { }, }, } + defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.SELinuxMount, tc.seLinuxMountFeatureEnabled)() fakeVolumePluginMgr, plugin := volumetesting.GetTestKubeletVolumePluginMgr(t) plugin.SupportsSELinux = tc.pluginSupportsSELinux diff --git a/pkg/volume/util/operationexecutor/operation_executor.go b/pkg/volume/util/operationexecutor/operation_executor.go index 0fa04e427e4..9d5aa77947c 100644 --- a/pkg/volume/util/operationexecutor/operation_executor.go +++ b/pkg/volume/util/operationexecutor/operation_executor.go @@ -449,6 +449,9 @@ type VolumeToMount struct { DesiredPersistentVolumeSize resource.Quantity // SELinux label that should be used to mount. + // The label is set when: + // * SELinuxMountReadWriteOncePod feature gate is enabled and the volume is RWOP and kubelet knows the SELinux label. + // * Or, SELinuxMount feature gate is enabled and kubelet knows the SELinux label. SELinuxLabel string } diff --git a/pkg/volume/util/selinux.go b/pkg/volume/util/selinux.go index 6150ab8dba2..d6ea382031e 100644 --- a/pkg/volume/util/selinux.go +++ b/pkg/volume/util/selinux.go @@ -177,6 +177,10 @@ func VolumeSupportsSELinuxMount(volumeSpec *volume.Spec) bool { if len(volumeSpec.PersistentVolume.Spec.AccessModes) != 1 { return false } + if utilfeature.DefaultFeatureGate.Enabled(features.SELinuxMount) { + return true + } + // Only SELinuxMountReadWriteOncePod feature enabled if !v1helper.ContainsAccessMode(volumeSpec.PersistentVolume.Spec.AccessModes, v1.ReadWriteOncePod) { return false }