Add SELinux mount support to CSI driver

With some minor refactoring to use common getCSIDriver function.
This commit is contained in:
Jan Safranek 2022-03-21 16:39:46 +01:00
parent de7f5b66ed
commit 5c90474f38
4 changed files with 75 additions and 53 deletions

View File

@ -26,9 +26,6 @@ import (
"strings" "strings"
"time" "time"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/klog/v2"
v1 "k8s.io/api/core/v1" v1 "k8s.io/api/core/v1"
storage "k8s.io/api/storage/v1" storage "k8s.io/api/storage/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors" apierrors "k8s.io/apimachinery/pkg/api/errors"
@ -36,9 +33,12 @@ import (
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/wait" "k8s.io/apimachinery/pkg/util/wait"
"k8s.io/apimachinery/pkg/watch" "k8s.io/apimachinery/pkg/watch"
utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes"
"k8s.io/klog/v2"
"k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume"
"k8s.io/kubernetes/pkg/volume/util"
volumetypes "k8s.io/kubernetes/pkg/volume/util/types" volumetypes "k8s.io/kubernetes/pkg/volume/util/types"
"k8s.io/utils/clock" "k8s.io/utils/clock"
) )
@ -333,6 +333,7 @@ func (c *csiAttacher) MountDevice(spec *volume.Spec, devicePath string, deviceMo
data := map[string]string{ data := map[string]string{
volDataKey.volHandle: csiSource.VolumeHandle, volDataKey.volHandle: csiSource.VolumeHandle,
volDataKey.driverName: csiSource.Driver, volDataKey.driverName: csiSource.Driver,
volDataKey.seLinuxMountContext: deviceMounterArgs.SELinuxLabel,
} }
err = saveVolumeData(dataDir, volDataFileName, data) err = saveVolumeData(dataDir, volDataFileName, data)
@ -371,6 +372,16 @@ func (c *csiAttacher) MountDevice(spec *volume.Spec, devicePath string, deviceMo
mountOptions = spec.PersistentVolume.Spec.MountOptions mountOptions = spec.PersistentVolume.Spec.MountOptions
} }
if utilfeature.DefaultFeatureGate.Enabled(features.SELinuxMountReadWriteOncePod) {
support, err := c.plugin.SupportsSELinuxContextMount(spec)
if err != nil {
return errors.New(log("failed to query for SELinuxMount support: %s", err))
}
if support {
mountOptions = util.AddSELinuxMountOption(mountOptions, deviceMounterArgs.SELinuxLabel)
}
}
var nodeStageFSGroupArg *int64 var nodeStageFSGroupArg *int64
if utilfeature.DefaultFeatureGate.Enabled(features.DelegateFSGroupToCSIDriver) { if utilfeature.DefaultFeatureGate.Enabled(features.DelegateFSGroupToCSIDriver) {
driverSupportsCSIVolumeMountGroup, err := csi.NodeSupportsVolumeMountGroup(ctx) driverSupportsCSIVolumeMountGroup, err := csi.NodeSupportsVolumeMountGroup(ctx)

View File

@ -24,8 +24,6 @@ import (
"os" "os"
"path/filepath" "path/filepath"
"k8s.io/klog/v2"
authenticationv1 "k8s.io/api/authentication/v1" authenticationv1 "k8s.io/api/authentication/v1"
api "k8s.io/api/core/v1" api "k8s.io/api/core/v1"
storage "k8s.io/api/storage/v1" storage "k8s.io/api/storage/v1"
@ -33,6 +31,7 @@ import (
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
utilfeature "k8s.io/apiserver/pkg/util/feature" utilfeature "k8s.io/apiserver/pkg/util/feature"
"k8s.io/client-go/kubernetes" "k8s.io/client-go/kubernetes"
"k8s.io/klog/v2"
"k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/features"
"k8s.io/kubernetes/pkg/volume" "k8s.io/kubernetes/pkg/volume"
"k8s.io/kubernetes/pkg/volume/util" "k8s.io/kubernetes/pkg/volume/util"
@ -49,7 +48,8 @@ var (
driverName, driverName,
nodeName, nodeName,
attachmentID, attachmentID,
volumeLifecycleMode string volumeLifecycleMode,
seLinuxMountContext string
}{ }{
"specVolID", "specVolID",
"volumeHandle", "volumeHandle",
@ -57,6 +57,7 @@ var (
"nodeName", "nodeName",
"attachmentID", "attachmentID",
"volumeLifecycleMode", "volumeLifecycleMode",
"seLinuxMountContext",
} }
) )
@ -70,7 +71,7 @@ type csiMountMgr struct {
volumeID string volumeID string
specVolumeID string specVolumeID string
readOnly bool readOnly bool
supportsSELinux bool needSELinuxRelabel bool
spec *volume.Spec spec *volume.Spec
pod *api.Pod pod *api.Pod
podUID types.UID podUID types.UID
@ -245,6 +246,18 @@ func (c *csiMountMgr) SetUpAt(dir string, mounterArgs volume.MounterArgs) error
} }
} }
var selinuxLabelMount bool
if utilfeature.DefaultFeatureGate.Enabled(features.SELinuxMountReadWriteOncePod) {
support, err := c.plugin.SupportsSELinuxContextMount(c.spec)
if err != nil {
return errors.New(log("failed to query for SELinuxMount support: %s", err))
}
if support {
mountOptions = util.AddSELinuxMountOption(mountOptions, mounterArgs.SELinuxLabel)
selinuxLabelMount = true
}
}
err = csi.NodePublishVolume( err = csi.NodePublishVolume(
ctx, ctx,
volumeHandle, volumeHandle,
@ -270,11 +283,13 @@ func (c *csiMountMgr) SetUpAt(dir string, mounterArgs volume.MounterArgs) error
return err return err
} }
c.supportsSELinux, err = c.kubeVolHost.GetHostUtil().GetSELinuxSupport(dir) if !selinuxLabelMount {
c.needSELinuxRelabel, err = c.kubeVolHost.GetHostUtil().GetSELinuxSupport(dir)
if err != nil { if err != nil {
// The volume is mounted. Return UncertainProgressError, so kubelet will unmount it when user deletes the pod. // The volume is mounted. Return UncertainProgressError, so kubelet will unmount it when user deletes the pod.
return volumetypes.NewUncertainProgressError(fmt.Sprintf("error checking for SELinux support: %s", err)) return volumetypes.NewUncertainProgressError(fmt.Sprintf("error checking for SELinux support: %s", err))
} }
}
if !driverSupportsCSIVolumeMountGroup && c.supportsFSGroup(fsType, mounterArgs.FsGroup, c.fsGroupPolicy) { if !driverSupportsCSIVolumeMountGroup && c.supportsFSGroup(fsType, mounterArgs.FsGroup, c.fsGroupPolicy) {
// Driver doesn't support applying FSGroup. Kubelet must apply it instead. // Driver doesn't support applying FSGroup. Kubelet must apply it instead.
@ -350,7 +365,7 @@ func (c *csiMountMgr) GetAttributes() volume.Attributes {
return volume.Attributes{ return volume.Attributes{
ReadOnly: c.readOnly, ReadOnly: c.readOnly,
Managed: !c.readOnly, Managed: !c.readOnly,
SELinuxRelabel: c.supportsSELinux, SELinuxRelabel: c.needSELinuxRelabel,
} }
} }

View File

@ -1235,7 +1235,7 @@ func Test_csiMountMgr_supportsFSGroup(t *testing.T) {
volumeID: tt.fields.volumeID, volumeID: tt.fields.volumeID,
specVolumeID: tt.fields.specVolumeID, specVolumeID: tt.fields.specVolumeID,
readOnly: tt.fields.readOnly, readOnly: tt.fields.readOnly,
supportsSELinux: tt.fields.supportsSELinux, needSELinuxRelabel: tt.fields.supportsSELinux,
spec: tt.fields.spec, spec: tt.fields.spec,
pod: tt.fields.pod, pod: tt.fields.pod,
podUID: tt.fields.podUID, podUID: tt.fields.podUID,

View File

@ -351,7 +351,7 @@ func (p *csiPlugin) RequiresRemount(spec *volume.Spec) bool {
klog.V(5).Info(log("Failed to mark %q as republish required, err: %v", spec.Name(), err)) klog.V(5).Info(log("Failed to mark %q as republish required, err: %v", spec.Name(), err))
return false return false
} }
csiDriver, err := p.csiDriverLister.Get(driverName) csiDriver, err := p.getCSIDriver(driverName)
if err != nil { if err != nil {
klog.V(5).Info(log("Failed to mark %q as republish required, err: %v", spec.Name(), err)) klog.V(5).Info(log("Failed to mark %q as republish required, err: %v", spec.Name(), err))
return false return false
@ -582,6 +582,20 @@ func (p *csiPlugin) SupportsBulkVolumeVerification() bool {
} }
func (p *csiPlugin) SupportsSELinuxContextMount(spec *volume.Spec) (bool, error) { func (p *csiPlugin) SupportsSELinuxContextMount(spec *volume.Spec) (bool, error) {
if utilfeature.DefaultFeatureGate.Enabled(features.SELinuxMountReadWriteOncePod) {
driver, err := GetCSIDriverName(spec)
if err != nil {
return false, err
}
csiDriver, err := p.getCSIDriver(driver)
if err != nil {
return false, err
}
if csiDriver.Spec.SELinuxMount != nil {
return *csiDriver.Spec.SELinuxMount, nil
}
return false, nil
}
return false, nil return false, nil
} }
@ -795,17 +809,7 @@ func (p *csiPlugin) ConstructBlockVolumeSpec(podUID types.UID, specVolName, mapP
// skipAttach looks up CSIDriver object associated with driver name // skipAttach looks up CSIDriver object associated with driver name
// to determine if driver requires attachment volume operation // to determine if driver requires attachment volume operation
func (p *csiPlugin) skipAttach(driver string) (bool, error) { func (p *csiPlugin) skipAttach(driver string) (bool, error) {
kletHost, ok := p.host.(volume.KubeletVolumeHost) csiDriver, err := p.getCSIDriver(driver)
if ok {
if err := kletHost.WaitForCacheSync(); err != nil {
return false, err
}
}
if p.csiDriverLister == nil {
return false, errors.New("CSIDriver lister does not exist")
}
csiDriver, err := p.csiDriverLister.Get(driver)
if err != nil { if err != nil {
if apierrors.IsNotFound(err) { if apierrors.IsNotFound(err) {
// Don't skip attach if CSIDriver does not exist // Don't skip attach if CSIDriver does not exist
@ -819,6 +823,21 @@ func (p *csiPlugin) skipAttach(driver string) (bool, error) {
return false, nil return false, nil
} }
func (p *csiPlugin) getCSIDriver(driver string) (*storage.CSIDriver, error) {
kletHost, ok := p.host.(volume.KubeletVolumeHost)
if ok {
if err := kletHost.WaitForCacheSync(); err != nil {
return nil, err
}
}
if p.csiDriverLister == nil {
return nil, errors.New("CSIDriver lister does not exist")
}
csiDriver, err := p.csiDriverLister.Get(driver)
return csiDriver, err
}
// supportsVolumeMode checks whether the CSI driver supports a volume in the given mode. // supportsVolumeMode checks whether the CSI driver supports a volume in the given mode.
// An error indicates that it isn't supported and explains why. // An error indicates that it isn't supported and explains why.
func (p *csiPlugin) supportsVolumeLifecycleMode(driver string, volumeMode storage.VolumeLifecycleMode) error { func (p *csiPlugin) supportsVolumeLifecycleMode(driver string, volumeMode storage.VolumeLifecycleMode) error {
@ -836,14 +855,7 @@ func (p *csiPlugin) supportsVolumeLifecycleMode(driver string, volumeMode storag
// optional), but then only persistent volumes are supported. // optional), but then only persistent volumes are supported.
var csiDriver *storage.CSIDriver var csiDriver *storage.CSIDriver
if p.csiDriverLister != nil { if p.csiDriverLister != nil {
kletHost, ok := p.host.(volume.KubeletVolumeHost) c, err := p.getCSIDriver(driver)
if ok {
if err := kletHost.WaitForCacheSync(); err != nil {
return err
}
}
c, err := p.csiDriverLister.Get(driver)
if err != nil && !apierrors.IsNotFound(err) { if err != nil && !apierrors.IsNotFound(err) {
// Some internal error. // Some internal error.
return err return err
@ -904,14 +916,7 @@ func (p *csiPlugin) getFSGroupPolicy(driver string) (storage.FSGroupPolicy, erro
// optional) // optional)
var csiDriver *storage.CSIDriver var csiDriver *storage.CSIDriver
if p.csiDriverLister != nil { if p.csiDriverLister != nil {
kletHost, ok := p.host.(volume.KubeletVolumeHost) c, err := p.getCSIDriver(driver)
if ok {
if err := kletHost.WaitForCacheSync(); err != nil {
return storage.ReadWriteOnceWithFSTypeFSGroupPolicy, err
}
}
c, err := p.csiDriverLister.Get(driver)
if err != nil && !apierrors.IsNotFound(err) { if err != nil && !apierrors.IsNotFound(err) {
// Some internal error. // Some internal error.
return storage.ReadWriteOnceWithFSTypeFSGroupPolicy, err return storage.ReadWriteOnceWithFSTypeFSGroupPolicy, err
@ -969,16 +974,7 @@ func (p *csiPlugin) newAttacherDetacher() (*csiAttacher, error) {
// podInfoEnabled check CSIDriver enabled pod info flag // podInfoEnabled check CSIDriver enabled pod info flag
func (p *csiPlugin) podInfoEnabled(driverName string) (bool, error) { func (p *csiPlugin) podInfoEnabled(driverName string) (bool, error) {
kletHost, ok := p.host.(volume.KubeletVolumeHost) csiDriver, err := p.getCSIDriver(driverName)
if ok {
kletHost.WaitForCacheSync()
}
if p.csiDriverLister == nil {
return false, fmt.Errorf("CSIDriverLister not found")
}
csiDriver, err := p.csiDriverLister.Get(driverName)
if err != nil { if err != nil {
if apierrors.IsNotFound(err) { if apierrors.IsNotFound(err) {
klog.V(4).Infof(log("CSIDriver %q not found, not adding pod information", driverName)) klog.V(4).Infof(log("CSIDriver %q not found, not adding pod information", driverName))