Skip to content

Commit 58bd3e5

Browse files
committed
Include CSIDriver SupportsFsGroup
1 parent 70f68db commit 58bd3e5

File tree

13 files changed

+369
-38
lines changed

13 files changed

+369
-38
lines changed

api/openapi-spec/swagger.json

Lines changed: 8 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/apis/storage/types.go

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,14 @@ type CSIDriverSpec struct {
277277
// +optional
278278
AttachRequired *bool
279279

280+
// Defines if the underlying volume supports changing ownership and
281+
// permission of the volume before being mounted.
282+
// Refer to the specific FSGroupPolicy values for additional details.
283+
// This field is alpha-level, and is only honored by servers
284+
// that enable the CSIVolumeFSGroupPolicy feature gate.
285+
// +optional
286+
FSGroupPolicy *FSGroupPolicy
287+
280288
// If set to true, podInfoOnMount indicates this CSI volume driver
281289
// requires additional pod information (like podName, podUID, etc.) during
282290
// mount operations.
@@ -331,6 +339,37 @@ type CSIDriverSpec struct {
331339
StorageCapacity *bool
332340
}
333341

342+
// FSGroupPolicy specifies if a CSI Driver supports modifying
343+
// volume ownership and permissions of the volume to be mounted.
344+
// More modes may be added in the future.
345+
type FSGroupPolicy string
346+
347+
const (
348+
// ReadWriteOnceWithFSTypeFSGroupPolicy indicates that each volume will be examined
349+
// to determine if the volume ownership and permissions
350+
// should be modified. If a fstype is defined and the volume's access mode
351+
// contains ReadWriteOnce, then the defined fsGroup will be applied.
352+
// This mode should be defined if it's expected that the
353+
// fsGroup may need to be modified depending on the pod's SecurityPolicy.
354+
// This is the default behavior if no other FSGroupPolicy is defined.
355+
ReadWriteOnceWithFSTypeFSGroupPolicy FSGroupPolicy = "ReadWriteOnceWithFSType"
356+
357+
// FileFSGroupPolicy indicates that CSI driver supports volume ownership
358+
// and permission change via fsGroup, and Kubernetes may use fsGroup
359+
// to change permissions and ownership of the volume to match user requested fsGroup in
360+
// the pod's SecurityPolicy regardless of fstype or access mode.
361+
// This mode should be defined if the fsGroup is expected to always change on mount
362+
FileFSGroupPolicy FSGroupPolicy = "File"
363+
364+
// NoneFSGroupPolicy indicates that volumes will be mounted without performing
365+
// any ownership or permission modifications, as the CSIDriver does not support
366+
// these operations.
367+
// This mode should be selected if the CSIDriver does not support fsGroup modifications,
368+
// for example when Kubernetes cannot change ownership and permissions on a volume due
369+
// to root-squash settings on a NFS volume.
370+
NoneFSGroupPolicy FSGroupPolicy = "None"
371+
)
372+
334373
// VolumeLifecycleMode specifies how a CSI volume is used in Kubernetes.
335374
// More modes may be added in the future.
336375
type VolumeLifecycleMode string

pkg/apis/storage/v1/defaults.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,10 @@ func SetDefaults_CSIDriver(obj *storagev1.CSIDriver) {
5353
obj.Spec.StorageCapacity = new(bool)
5454
*(obj.Spec.StorageCapacity) = false
5555
}
56+
if obj.Spec.FSGroupPolicy == nil && utilfeature.DefaultFeatureGate.Enabled(features.CSIVolumeFSGroupPolicy) {
57+
obj.Spec.FSGroupPolicy = new(storagev1.FSGroupPolicy)
58+
*obj.Spec.FSGroupPolicy = storagev1.ReadWriteOnceWithFSTypeFSGroupPolicy
59+
}
5660
if len(obj.Spec.VolumeLifecycleModes) == 0 && utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume) {
5761
obj.Spec.VolumeLifecycleModes = append(obj.Spec.VolumeLifecycleModes, storagev1.VolumeLifecyclePersistent)
5862
}

pkg/apis/storage/v1beta1/defaults.go

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ limitations under the License.
1717
package v1beta1
1818

1919
import (
20-
"k8s.io/api/core/v1"
20+
v1 "k8s.io/api/core/v1"
2121
storagev1beta1 "k8s.io/api/storage/v1beta1"
2222
"k8s.io/apimachinery/pkg/runtime"
2323
utilfeature "k8s.io/apiserver/pkg/util/feature"
@@ -53,6 +53,10 @@ func SetDefaults_CSIDriver(obj *storagev1beta1.CSIDriver) {
5353
obj.Spec.StorageCapacity = new(bool)
5454
*(obj.Spec.StorageCapacity) = false
5555
}
56+
if obj.Spec.FSGroupPolicy == nil && utilfeature.DefaultFeatureGate.Enabled(features.CSIVolumeFSGroupPolicy) {
57+
obj.Spec.FSGroupPolicy = new(storagev1beta1.FSGroupPolicy)
58+
*obj.Spec.FSGroupPolicy = storagev1beta1.ReadWriteOnceWithFSTypeFSGroupPolicy
59+
}
5660
if len(obj.Spec.VolumeLifecycleModes) == 0 && utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume) {
5761
obj.Spec.VolumeLifecycleModes = append(obj.Spec.VolumeLifecycleModes, storagev1beta1.VolumeLifecyclePersistent)
5862
}

pkg/apis/storage/validation/validation.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,6 +421,7 @@ func validateCSIDriverSpec(
421421
allErrs = append(allErrs, validateAttachRequired(spec.AttachRequired, fldPath.Child("attachedRequired"))...)
422422
allErrs = append(allErrs, validatePodInfoOnMount(spec.PodInfoOnMount, fldPath.Child("podInfoOnMount"))...)
423423
allErrs = append(allErrs, validateStorageCapacity(spec.StorageCapacity, fldPath.Child("storageCapacity"))...)
424+
allErrs = append(allErrs, validateFSGroupPolicy(spec.FSGroupPolicy, fldPath.Child("fsGroupPolicy"))...)
424425
allErrs = append(allErrs, validateVolumeLifecycleModes(spec.VolumeLifecycleModes, fldPath.Child("volumeLifecycleModes"))...)
425426
return allErrs
426427
}
@@ -451,6 +452,21 @@ func validateStorageCapacity(storageCapacity *bool, fldPath *field.Path) field.E
451452
if storageCapacity == nil && utilfeature.DefaultFeatureGate.Enabled(features.CSIStorageCapacity) {
452453
allErrs = append(allErrs, field.Required(fldPath, ""))
453454
}
455+
}
456+
457+
var supportedFSGroupPolicy = sets.NewString(string(storage.ReadWriteOnceWithFSTypeFSGroupPolicy), string(storage.FileFSGroupPolicy), string(storage.NoneFSGroupPolicy))
458+
459+
// validateFSGroupPolicy tests if FSGroupPolicy contains an appropriate value.
460+
func validateFSGroupPolicy(fsGroupPolicy *storage.FSGroupPolicy, fldPath *field.Path) field.ErrorList {
461+
allErrs := field.ErrorList{}
462+
if fsGroupPolicy == nil {
463+
// This is not a required field, so if nothing is provided simply return
464+
return allErrs
465+
}
466+
467+
if !supportedFSGroupPolicy.Has(string(*fsGroupPolicy)) {
468+
allErrs = append(allErrs, field.NotSupported(fldPath, fsGroupPolicy, supportedFSGroupPolicy.List()))
469+
}
454470

455471
return allErrs
456472
}

pkg/apis/storage/validation/validation_test.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1665,6 +1665,9 @@ func TestCSIDriverValidation(t *testing.T) {
16651665
attachNotRequired := false
16661666
podInfoOnMount := true
16671667
notPodInfoOnMount := false
1668+
supportedFSGroupPolicy := storage.FileFSGroupPolicy
1669+
invalidFSGroupPolicy := storage.ReadWriteOnceWithFSTypeFSGroupPolicy
1670+
invalidFSGroupPolicy = "invalid-mode"
16681671
successCases := []storage.CSIDriver{
16691672
{
16701673
ObjectMeta: metav1.ObjectMeta{Name: driverName},
@@ -1769,6 +1772,14 @@ func TestCSIDriverValidation(t *testing.T) {
17691772
},
17701773
},
17711774
},
1775+
{
1776+
ObjectMeta: metav1.ObjectMeta{Name: driverName},
1777+
Spec: storage.CSIDriverSpec{
1778+
AttachRequired: &attachNotRequired,
1779+
PodInfoOnMount: &notPodInfoOnMount,
1780+
FSGroupPolicy: &supportedFSGroupPolicy,
1781+
},
1782+
},
17721783
}
17731784

17741785
for _, csiDriver := range successCases {
@@ -1818,6 +1829,15 @@ func TestCSIDriverValidation(t *testing.T) {
18181829
},
18191830
},
18201831
},
1832+
{
1833+
// invalid fsGroupPolicy
1834+
ObjectMeta: metav1.ObjectMeta{Name: driverName},
1835+
Spec: storage.CSIDriverSpec{
1836+
AttachRequired: &attachNotRequired,
1837+
PodInfoOnMount: &notPodInfoOnMount,
1838+
FSGroupPolicy: &invalidFSGroupPolicy,
1839+
},
1840+
},
18211841
}
18221842

18231843
for _, csiDriver := range errorCases {

pkg/features/kube_features.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -435,6 +435,12 @@ const (
435435
// Expects vSphere CSI Driver to be installed and configured on all nodes.
436436
CSIMigrationvSphereComplete featuregate.Feature = "CSIMigrationvSphereComplete"
437437

438+
// owner: @huffmanca
439+
// alpha: v1.19
440+
//
441+
// Determines if a CSI Driver supports applying fsGroup.
442+
CSIVolumeFSGroupPolicy featuregate.Feature = "CSIVolumeFSGroupPolicy"
443+
438444
// owner: @gnufied
439445
// alpha: v1.18
440446
// Allows user to configure volume permission change policy for fsGroups when mounting
@@ -685,6 +691,7 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS
685691
CSIInlineVolume: {Default: true, PreRelease: featuregate.Beta},
686692
CSIStorageCapacity: {Default: false, PreRelease: featuregate.Alpha},
687693
GenericEphemeralVolume: {Default: false, PreRelease: featuregate.Alpha},
694+
CSIVolumeFSGroupPolicy: {Default: false, PreRelease: featuregate.Alpha},
688695
RuntimeClass: {Default: true, PreRelease: featuregate.Beta},
689696
NodeLease: {Default: true, PreRelease: featuregate.GA, LockToDefault: true},
690697
SCTPSupport: {Default: true, PreRelease: featuregate.Beta},

pkg/registry/storage/csidriver/strategy.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,14 +45,16 @@ func (csiDriverStrategy) NamespaceScoped() bool {
4545

4646
// PrepareForCreate clears the fields for which the corresponding feature is disabled.
4747
func (csiDriverStrategy) PrepareForCreate(ctx context.Context, obj runtime.Object) {
48+
csiDriver := obj.(*storage.CSIDriver)
4849
if !utilfeature.DefaultFeatureGate.Enabled(features.CSIStorageCapacity) {
49-
csiDriver := obj.(*storage.CSIDriver)
5050
csiDriver.Spec.StorageCapacity = nil
5151
}
5252
if !utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume) {
53-
csiDriver := obj.(*storage.CSIDriver)
5453
csiDriver.Spec.VolumeLifecycleModes = nil
5554
}
55+
if !utilfeature.DefaultFeatureGate.Enabled(features.CSIVolumeFSGroupPolicy) {
56+
csiDriver.Spec.FSGroupPolicy = nil
57+
}
5658
}
5759

5860
func (csiDriverStrategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorList {
@@ -86,6 +88,11 @@ func (csiDriverStrategy) PrepareForUpdate(ctx context.Context, obj, old runtime.
8688
newCSIDriver := obj.(*storage.CSIDriver)
8789
newCSIDriver.Spec.VolumeLifecycleModes = nil
8890
}
91+
if old.(*storage.CSIDriver).Spec.FSGroupPolicy == nil &&
92+
!utilfeature.DefaultFeatureGate.Enabled(features.CSIVolumeFSGroupPolicy) {
93+
newCSIDriver := obj.(*storage.CSIDriver)
94+
newCSIDriver.Spec.FSGroupPolicy = nil
95+
}
8996
}
9097

9198
func (csiDriverStrategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) field.ErrorList {

0 commit comments

Comments
 (0)