PSP: conditional support for generic volume type

When introducing the new "generic" volume type for generic ephemeral
inline volumes, the storage policy for PodSecurityPolicy objects
should have been extended so that this new type is valid only
if the generic ephemeral volume feature is enabled or an
existing object already has it.

Adding the new type to the internal API was also missed.
This commit is contained in:
Patrick Ohly 2021-02-09 12:15:42 +01:00
parent 90851a0fb5
commit 38384d5c13
4 changed files with 106 additions and 0 deletions

View File

@ -31,6 +31,16 @@ func DropDisabledFields(pspSpec, oldPSPSpec *policy.PodSecurityPolicySpec) {
if !utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume) {
pspSpec.AllowedCSIDrivers = nil
}
var volumes []policy.FSType
for _, volume := range pspSpec.Volumes {
if volume != policy.Ephemeral ||
utilfeature.DefaultFeatureGate.Enabled(features.GenericEphemeralVolume) ||
volumeInUse(oldPSPSpec, volume) {
// Keep it.
volumes = append(volumes, volume)
}
}
pspSpec.Volumes = volumes
}
func allowedProcMountTypesInUse(oldPSPSpec *policy.PodSecurityPolicySpec) bool {
@ -45,3 +55,15 @@ func allowedProcMountTypesInUse(oldPSPSpec *policy.PodSecurityPolicySpec) bool {
return false
}
func volumeInUse(oldPSPSpec *policy.PodSecurityPolicySpec, volume policy.FSType) bool {
if oldPSPSpec == nil {
return false
}
for _, v := range oldPSPSpec.Volumes {
if v == volume {
return true
}
}
return false
}

View File

@ -107,3 +107,82 @@ func TestDropAllowedProcMountTypes(t *testing.T) {
}
}
}
func TestDropEphemeralVolumeType(t *testing.T) {
allowedVolumeTypes := []policy.FSType{policy.Ephemeral}
pspWithoutGenericVolume := func() *policy.PodSecurityPolicySpec {
return &policy.PodSecurityPolicySpec{}
}
pspWithGenericVolume := func() *policy.PodSecurityPolicySpec {
return &policy.PodSecurityPolicySpec{
Volumes: allowedVolumeTypes,
}
}
pspInfo := []struct {
description string
hasGenericVolume bool
psp func() *policy.PodSecurityPolicySpec
}{
{
description: "PodSecurityPolicySpec Without GenericVolume",
hasGenericVolume: false,
psp: pspWithoutGenericVolume,
},
{
description: "PodSecurityPolicySpec With GenericVolume",
hasGenericVolume: true,
psp: pspWithGenericVolume,
},
{
description: "is nil",
hasGenericVolume: false,
psp: func() *policy.PodSecurityPolicySpec { return nil },
},
}
for _, enabled := range []bool{true, false} {
for _, oldPSPSpecInfo := range pspInfo {
for _, newPSPSpecInfo := range pspInfo {
oldPSPSpecHasGenericVolume, oldPSPSpec := oldPSPSpecInfo.hasGenericVolume, oldPSPSpecInfo.psp()
newPSPSpecHasGenericVolume, newPSPSpec := newPSPSpecInfo.hasGenericVolume, newPSPSpecInfo.psp()
if newPSPSpec == nil {
continue
}
t.Run(fmt.Sprintf("feature enabled=%v, old PodSecurityPolicySpec %v, new PodSecurityPolicySpec %v", enabled, oldPSPSpecInfo.description, newPSPSpecInfo.description), func(t *testing.T) {
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.GenericEphemeralVolume, enabled)()
DropDisabledFields(newPSPSpec, oldPSPSpec)
// old PodSecurityPolicySpec should never be changed
if !reflect.DeepEqual(oldPSPSpec, oldPSPSpecInfo.psp()) {
t.Errorf("old PodSecurityPolicySpec changed: %v", diff.ObjectReflectDiff(oldPSPSpec, oldPSPSpecInfo.psp()))
}
switch {
case enabled || oldPSPSpecHasGenericVolume:
// new PodSecurityPolicySpec should not be changed if the feature is enabled, or if the old PodSecurityPolicySpec had GenericVolume
if !reflect.DeepEqual(newPSPSpec, newPSPSpecInfo.psp()) {
t.Errorf("new PodSecurityPolicySpec changed: %v", diff.ObjectReflectDiff(newPSPSpec, newPSPSpecInfo.psp()))
}
case newPSPSpecHasGenericVolume:
// new PodSecurityPolicySpec should be changed
if reflect.DeepEqual(newPSPSpec, newPSPSpecInfo.psp()) {
t.Errorf("new PodSecurityPolicySpec was not changed")
}
// new PodSecurityPolicySpec should not have GenericVolume
if !reflect.DeepEqual(newPSPSpec, pspWithoutGenericVolume()) {
t.Errorf("new PodSecurityPolicySpec had PodSecurityPolicySpecGenericVolume: %v", diff.ObjectReflectDiff(newPSPSpec, pspWithoutGenericVolume()))
}
default:
// new PodSecurityPolicySpec should not need to be changed
if !reflect.DeepEqual(newPSPSpec, newPSPSpecInfo.psp()) {
t.Errorf("new PodSecurityPolicySpec changed: %v", diff.ObjectReflectDiff(newPSPSpec, newPSPSpecInfo.psp()))
}
}
})
}
}
}
}

View File

@ -309,6 +309,7 @@ const (
PortworxVolume FSType = "portworxVolume"
ScaleIO FSType = "scaleIO"
CSI FSType = "csi"
Ephemeral FSType = "ephemeral"
All FSType = "*"
)

View File

@ -29,6 +29,8 @@ const (
ValidatedPSPAnnotation = "kubernetes.io/psp"
)
// GetAllFSTypesExcept returns the result of GetAllFSTypesAsSet minus
// the given exceptions.
func GetAllFSTypesExcept(exceptions ...string) sets.String {
fstypes := GetAllFSTypesAsSet()
for _, e := range exceptions {
@ -37,6 +39,8 @@ func GetAllFSTypesExcept(exceptions ...string) sets.String {
return fstypes
}
// GetAllFSTypesAsSet returns all actual volume types, regardless
// of feature gates. The special policy.All pseudo type is not included.
func GetAllFSTypesAsSet() sets.String {
fstypes := sets.NewString()
fstypes.Insert(