Skip to content

Commit 96c057a

Browse files
authored
Merge pull request kubernetes#92001 from huffmanca/include-csidriver-fsgroup
Include CSIDriver capability to indicate fsGroup support
2 parents 75b5552 + ade2f83 commit 96c057a

31 files changed

+711
-231
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/fuzzer/fuzzer.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package fuzzer
1818

1919
import (
2020
"fmt"
21+
2122
fuzz "github.com/google/gofuzz"
2223

2324
runtimeserializer "k8s.io/apimachinery/pkg/runtime/serializer"
@@ -82,6 +83,10 @@ var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} {
8283
obj.Spec.StorageCapacity = new(bool)
8384
*(obj.Spec.StorageCapacity) = false
8485
}
86+
if obj.Spec.FSGroupPolicy == nil {
87+
obj.Spec.FSGroupPolicy = new(storage.FSGroupPolicy)
88+
*obj.Spec.FSGroupPolicy = storage.ReadWriteOnceWithFSTypeFSGroupPolicy
89+
}
8590
if len(obj.Spec.VolumeLifecycleModes) == 0 {
8691
obj.Spec.VolumeLifecycleModes = []storage.VolumeLifecycleMode{
8792
storage.VolumeLifecyclePersistent,

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/v1/zz_generated.conversion.go

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

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/v1beta1/zz_generated.conversion.go

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

pkg/apis/storage/validation/validation.go

Lines changed: 18 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
}
@@ -455,6 +456,23 @@ func validateStorageCapacity(storageCapacity *bool, fldPath *field.Path) field.E
455456
return allErrs
456457
}
457458

459+
var supportedFSGroupPolicy = sets.NewString(string(storage.ReadWriteOnceWithFSTypeFSGroupPolicy), string(storage.FileFSGroupPolicy), string(storage.NoneFSGroupPolicy))
460+
461+
// validateFSGroupPolicy tests if FSGroupPolicy contains an appropriate value.
462+
func validateFSGroupPolicy(fsGroupPolicy *storage.FSGroupPolicy, fldPath *field.Path) field.ErrorList {
463+
allErrs := field.ErrorList{}
464+
if fsGroupPolicy == nil {
465+
// This is not a required field, so if nothing is provided simply return
466+
return allErrs
467+
}
468+
469+
if !supportedFSGroupPolicy.Has(string(*fsGroupPolicy)) {
470+
allErrs = append(allErrs, field.NotSupported(fldPath, fsGroupPolicy, supportedFSGroupPolicy.List()))
471+
}
472+
473+
return allErrs
474+
}
475+
458476
// validateVolumeLifecycleModes tests if mode has one of the allowed values.
459477
func validateVolumeLifecycleModes(modes []storage.VolumeLifecycleMode, fldPath *field.Path) field.ErrorList {
460478
allErrs := field.ErrorList{}

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/apis/storage/zz_generated.deepcopy.go

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

0 commit comments

Comments
 (0)