mirror of
				https://github.com/optim-enterprises-bv/kubernetes.git
				synced 2025-11-04 04:08:16 +00:00 
			
		
		
		
	Enforce pod security policy for CSI inline
This commit is contained in:
		@@ -209,7 +209,8 @@ type PodSecurityPolicySpec struct {
 | 
				
			|||||||
	// +optional
 | 
						// +optional
 | 
				
			||||||
	AllowedFlexVolumes []AllowedFlexVolume
 | 
						AllowedFlexVolumes []AllowedFlexVolume
 | 
				
			||||||
	// AllowedCSIDrivers is a whitelist of inline CSI drivers that must be explicitly set to be embedded within a pod spec.
 | 
						// AllowedCSIDrivers is a whitelist of inline CSI drivers that must be explicitly set to be embedded within a pod spec.
 | 
				
			||||||
	// An empty value means no CSI drivers can run inline within a pod spec.
 | 
						// An empty value indicates that any CSI driver can be used for inline ephemeral volumes.
 | 
				
			||||||
 | 
						// This is an alpha field, and is only honored if the API server enables the CSIInlineVolume feature gate.
 | 
				
			||||||
	// +optional
 | 
						// +optional
 | 
				
			||||||
	AllowedCSIDrivers []AllowedCSIDriver
 | 
						AllowedCSIDrivers []AllowedCSIDriver
 | 
				
			||||||
	// AllowedUnsafeSysctls is a list of explicitly allowed unsafe sysctls, defaults to none.
 | 
						// AllowedUnsafeSysctls is a list of explicitly allowed unsafe sysctls, defaults to none.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -281,6 +281,10 @@ func TestValidatePodSecurityPolicy(t *testing.T) {
 | 
				
			|||||||
	invalidProcMount := validPSP()
 | 
						invalidProcMount := validPSP()
 | 
				
			||||||
	invalidProcMount.Spec.AllowedProcMountTypes = []api.ProcMountType{api.ProcMountType("bogus")}
 | 
						invalidProcMount.Spec.AllowedProcMountTypes = []api.ProcMountType{api.ProcMountType("bogus")}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						allowedCSIDriverPSP := validPSP()
 | 
				
			||||||
 | 
						allowedCSIDriverPSP.Spec.Volumes = []policy.FSType{policy.CSI}
 | 
				
			||||||
 | 
						allowedCSIDriverPSP.Spec.AllowedCSIDrivers = []policy.AllowedCSIDriver{{}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	type testCase struct {
 | 
						type testCase struct {
 | 
				
			||||||
		psp         *policy.PodSecurityPolicy
 | 
							psp         *policy.PodSecurityPolicy
 | 
				
			||||||
		errorType   field.ErrorType
 | 
							errorType   field.ErrorType
 | 
				
			||||||
@@ -447,6 +451,10 @@ func TestValidatePodSecurityPolicy(t *testing.T) {
 | 
				
			|||||||
			errorType:   field.ErrorTypeRequired,
 | 
								errorType:   field.ErrorTypeRequired,
 | 
				
			||||||
			errorDetail: "must specify a driver",
 | 
								errorDetail: "must specify a driver",
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
							"CSI policy with empty allowed driver list": {
 | 
				
			||||||
 | 
								psp:       allowedCSIDriverPSP,
 | 
				
			||||||
 | 
								errorType: field.ErrorTypeRequired,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
		"invalid allowedProcMountTypes": {
 | 
							"invalid allowedProcMountTypes": {
 | 
				
			||||||
			psp:         invalidProcMount,
 | 
								psp:         invalidProcMount,
 | 
				
			||||||
			errorType:   field.ErrorTypeNotSupported,
 | 
								errorType:   field.ErrorTypeNotSupported,
 | 
				
			||||||
@@ -549,6 +557,14 @@ func TestValidatePodSecurityPolicy(t *testing.T) {
 | 
				
			|||||||
	validProcMount := validPSP()
 | 
						validProcMount := validPSP()
 | 
				
			||||||
	validProcMount.Spec.AllowedProcMountTypes = []api.ProcMountType{api.DefaultProcMount, api.UnmaskedProcMount}
 | 
						validProcMount.Spec.AllowedProcMountTypes = []api.ProcMountType{api.DefaultProcMount, api.UnmaskedProcMount}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						allowedCSIDriversWithCSIFsType := validPSP()
 | 
				
			||||||
 | 
						allowedCSIDriversWithCSIFsType.Spec.Volumes = []policy.FSType{policy.CSI}
 | 
				
			||||||
 | 
						allowedCSIDriversWithCSIFsType.Spec.AllowedCSIDrivers = []policy.AllowedCSIDriver{{Name: "foo"}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						allowedCSIDriversWithAllFsTypes := validPSP()
 | 
				
			||||||
 | 
						allowedCSIDriversWithAllFsTypes.Spec.Volumes = []policy.FSType{policy.All}
 | 
				
			||||||
 | 
						allowedCSIDriversWithAllFsTypes.Spec.AllowedCSIDrivers = []policy.AllowedCSIDriver{{Name: "bar"}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	successCases := map[string]struct {
 | 
						successCases := map[string]struct {
 | 
				
			||||||
		psp *policy.PodSecurityPolicy
 | 
							psp *policy.PodSecurityPolicy
 | 
				
			||||||
	}{
 | 
						}{
 | 
				
			||||||
@@ -591,6 +607,12 @@ func TestValidatePodSecurityPolicy(t *testing.T) {
 | 
				
			|||||||
		"valid allowedProcMountTypes": {
 | 
							"valid allowedProcMountTypes": {
 | 
				
			||||||
			psp: validProcMount,
 | 
								psp: validProcMount,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
							"allowed CSI drivers when FSType policy is set to CSI": {
 | 
				
			||||||
 | 
								psp: allowedCSIDriversWithCSIFsType,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"allowed CSI drivers when FSType policy is set to All": {
 | 
				
			||||||
 | 
								psp: allowedCSIDriversWithAllFsTypes,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for k, v := range successCases {
 | 
						for k, v := range successCases {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -3856,6 +3856,11 @@ func describePodSecurityPolicy(psp *policyv1beta1.PodSecurityPolicy) (string, er
 | 
				
			|||||||
		if len(psp.Spec.AllowedFlexVolumes) > 0 {
 | 
							if len(psp.Spec.AllowedFlexVolumes) > 0 {
 | 
				
			||||||
			w.Write(LEVEL_1, "Allowed FlexVolume Types:\t%s\n", flexVolumesToString(psp.Spec.AllowedFlexVolumes))
 | 
								w.Write(LEVEL_1, "Allowed FlexVolume Types:\t%s\n", flexVolumesToString(psp.Spec.AllowedFlexVolumes))
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if len(psp.Spec.AllowedCSIDrivers) > 0 {
 | 
				
			||||||
 | 
								w.Write(LEVEL_1, "Allowed CSI Drivers:\t%s\n", csiDriversToString(psp.Spec.AllowedCSIDrivers))
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if len(psp.Spec.AllowedUnsafeSysctls) > 0 {
 | 
							if len(psp.Spec.AllowedUnsafeSysctls) > 0 {
 | 
				
			||||||
			w.Write(LEVEL_1, "Allowed Unsafe Sysctls:\t%s\n", sysctlsToString(psp.Spec.AllowedUnsafeSysctls))
 | 
								w.Write(LEVEL_1, "Allowed Unsafe Sysctls:\t%s\n", sysctlsToString(psp.Spec.AllowedUnsafeSysctls))
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
@@ -3921,6 +3926,14 @@ func flexVolumesToString(flexVolumes []policyv1beta1.AllowedFlexVolume) string {
 | 
				
			|||||||
	return stringOrDefaultValue(strings.Join(volumes, ","), "<all>")
 | 
						return stringOrDefaultValue(strings.Join(volumes, ","), "<all>")
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func csiDriversToString(csiDrivers []policyv1beta1.AllowedCSIDriver) string {
 | 
				
			||||||
 | 
						drivers := []string{}
 | 
				
			||||||
 | 
						for _, csiDriver := range csiDrivers {
 | 
				
			||||||
 | 
							drivers = append(drivers, "driver="+csiDriver.Name)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return stringOrDefaultValue(strings.Join(drivers, ","), "<all>")
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func sysctlsToString(sysctls []string) string {
 | 
					func sysctlsToString(sysctls []string) string {
 | 
				
			||||||
	return stringOrNone(strings.Join(sysctls, ","))
 | 
						return stringOrNone(strings.Join(sysctls, ","))
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -42,6 +42,7 @@ go_test(
 | 
				
			|||||||
    deps = [
 | 
					    deps = [
 | 
				
			||||||
        "//pkg/apis/core:go_default_library",
 | 
					        "//pkg/apis/core:go_default_library",
 | 
				
			||||||
        "//pkg/apis/core/v1:go_default_library",
 | 
					        "//pkg/apis/core/v1:go_default_library",
 | 
				
			||||||
 | 
					        "//pkg/features:go_default_library",
 | 
				
			||||||
        "//pkg/security/apparmor:go_default_library",
 | 
					        "//pkg/security/apparmor:go_default_library",
 | 
				
			||||||
        "//pkg/security/podsecuritypolicy/seccomp:go_default_library",
 | 
					        "//pkg/security/podsecuritypolicy/seccomp:go_default_library",
 | 
				
			||||||
        "//pkg/security/podsecuritypolicy/util:go_default_library",
 | 
					        "//pkg/security/podsecuritypolicy/util:go_default_library",
 | 
				
			||||||
@@ -49,6 +50,8 @@ go_test(
 | 
				
			|||||||
        "//staging/src/k8s.io/api/policy/v1beta1:go_default_library",
 | 
					        "//staging/src/k8s.io/api/policy/v1beta1:go_default_library",
 | 
				
			||||||
        "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
 | 
					        "//staging/src/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
 | 
				
			||||||
        "//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library",
 | 
					        "//staging/src/k8s.io/apimachinery/pkg/util/diff:go_default_library",
 | 
				
			||||||
 | 
					        "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
 | 
				
			||||||
 | 
					        "//staging/src/k8s.io/component-base/featuregate/testing:go_default_library",
 | 
				
			||||||
        "//vendor/github.com/stretchr/testify/assert:go_default_library",
 | 
					        "//vendor/github.com/stretchr/testify/assert:go_default_library",
 | 
				
			||||||
        "//vendor/github.com/stretchr/testify/require:go_default_library",
 | 
					        "//vendor/github.com/stretchr/testify/require:go_default_library",
 | 
				
			||||||
        "//vendor/k8s.io/utils/pointer:go_default_library",
 | 
					        "//vendor/k8s.io/utils/pointer:go_default_library",
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -233,6 +233,28 @@ func (s *simpleProvider) ValidatePod(pod *api.Pod) field.ErrorList {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
	allErrs = append(allErrs, s.strategies.SysctlsStrategy.Validate(pod)...)
 | 
						allErrs = append(allErrs, s.strategies.SysctlsStrategy.Validate(pod)...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						allErrs = append(allErrs, s.validatePodVolumes(pod)...)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if s.psp.Spec.RuntimeClass != nil {
 | 
				
			||||||
 | 
							allErrs = append(allErrs, validateRuntimeClassName(pod.Spec.RuntimeClassName, s.psp.Spec.RuntimeClass.AllowedRuntimeClassNames)...)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fldPath := field.NewPath("spec", "initContainers")
 | 
				
			||||||
 | 
						for i := range pod.Spec.InitContainers {
 | 
				
			||||||
 | 
							allErrs = append(allErrs, s.validateContainer(pod, &pod.Spec.InitContainers[i], fldPath.Index(i))...)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fldPath = field.NewPath("spec", "containers")
 | 
				
			||||||
 | 
						for i := range pod.Spec.Containers {
 | 
				
			||||||
 | 
							allErrs = append(allErrs, s.validateContainer(pod, &pod.Spec.Containers[i], fldPath.Index(i))...)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return allErrs
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *simpleProvider) validatePodVolumes(pod *api.Pod) field.ErrorList {
 | 
				
			||||||
 | 
						allErrs := field.ErrorList{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if len(pod.Spec.Volumes) > 0 {
 | 
						if len(pod.Spec.Volumes) > 0 {
 | 
				
			||||||
		allowsAllVolumeTypes := psputil.PSPAllowsAllVolumes(s.psp)
 | 
							allowsAllVolumeTypes := psputil.PSPAllowsAllVolumes(s.psp)
 | 
				
			||||||
		allowedVolumes := psputil.FSTypeToStringSet(s.psp.Spec.Volumes)
 | 
							allowedVolumes := psputil.FSTypeToStringSet(s.psp.Spec.Volumes)
 | 
				
			||||||
@@ -250,7 +272,8 @@ func (s *simpleProvider) ValidatePod(pod *api.Pod) field.ErrorList {
 | 
				
			|||||||
				continue
 | 
									continue
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if fsType == policy.HostPath {
 | 
								switch fsType {
 | 
				
			||||||
 | 
								case policy.HostPath:
 | 
				
			||||||
				allows, mustBeReadOnly := psputil.AllowsHostVolumePath(s.psp, v.HostPath.Path)
 | 
									allows, mustBeReadOnly := psputil.AllowsHostVolumePath(s.psp, v.HostPath.Path)
 | 
				
			||||||
				if !allows {
 | 
									if !allows {
 | 
				
			||||||
					allErrs = append(allErrs, field.Invalid(
 | 
										allErrs = append(allErrs, field.Invalid(
 | 
				
			||||||
@@ -279,40 +302,46 @@ func (s *simpleProvider) ValidatePod(pod *api.Pod) field.ErrorList {
 | 
				
			|||||||
						}
 | 
											}
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if fsType == policy.FlexVolume && len(s.psp.Spec.AllowedFlexVolumes) > 0 {
 | 
								case policy.FlexVolume:
 | 
				
			||||||
				found := false
 | 
									if len(s.psp.Spec.AllowedFlexVolumes) > 0 {
 | 
				
			||||||
				driver := v.FlexVolume.Driver
 | 
										found := false
 | 
				
			||||||
				for _, allowedFlexVolume := range s.psp.Spec.AllowedFlexVolumes {
 | 
										driver := v.FlexVolume.Driver
 | 
				
			||||||
					if driver == allowedFlexVolume.Driver {
 | 
										for _, allowedFlexVolume := range s.psp.Spec.AllowedFlexVolumes {
 | 
				
			||||||
						found = true
 | 
											if driver == allowedFlexVolume.Driver {
 | 
				
			||||||
						break
 | 
												found = true
 | 
				
			||||||
 | 
												break
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										if !found {
 | 
				
			||||||
 | 
											allErrs = append(allErrs,
 | 
				
			||||||
 | 
												field.Invalid(field.NewPath("spec", "volumes").Index(i).Child("driver"), driver,
 | 
				
			||||||
 | 
													"Flexvolume driver is not allowed to be used"))
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				if !found {
 | 
					
 | 
				
			||||||
					allErrs = append(allErrs,
 | 
								case policy.CSI:
 | 
				
			||||||
						field.Invalid(field.NewPath("spec", "volumes").Index(i).Child("driver"), driver,
 | 
									if utilfeature.DefaultFeatureGate.Enabled(features.CSIInlineVolume) {
 | 
				
			||||||
							"Flexvolume driver is not allowed to be used"))
 | 
										if len(s.psp.Spec.AllowedCSIDrivers) > 0 {
 | 
				
			||||||
 | 
											found := false
 | 
				
			||||||
 | 
											driver := v.CSI.Driver
 | 
				
			||||||
 | 
											for _, allowedCSIDriver := range s.psp.Spec.AllowedCSIDrivers {
 | 
				
			||||||
 | 
												if driver == allowedCSIDriver.Name {
 | 
				
			||||||
 | 
													found = true
 | 
				
			||||||
 | 
													break
 | 
				
			||||||
 | 
												}
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
											if !found {
 | 
				
			||||||
 | 
												allErrs = append(allErrs,
 | 
				
			||||||
 | 
													field.Invalid(field.NewPath("spec", "volumes").Index(i).Child("csi", "driver"), driver,
 | 
				
			||||||
 | 
														"Inline CSI driver is not allowed to be used"))
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if s.psp.Spec.RuntimeClass != nil {
 | 
					 | 
				
			||||||
		allErrs = append(allErrs, validateRuntimeClassName(pod.Spec.RuntimeClassName, s.psp.Spec.RuntimeClass.AllowedRuntimeClassNames)...)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	fldPath := field.NewPath("spec", "initContainers")
 | 
					 | 
				
			||||||
	for i := range pod.Spec.InitContainers {
 | 
					 | 
				
			||||||
		allErrs = append(allErrs, s.validateContainer(pod, &pod.Spec.InitContainers[i], fldPath.Index(i))...)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	fldPath = field.NewPath("spec", "containers")
 | 
					 | 
				
			||||||
	for i := range pod.Spec.Containers {
 | 
					 | 
				
			||||||
		allErrs = append(allErrs, s.validateContainer(pod, &pod.Spec.Containers[i], fldPath.Index(i))...)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	return allErrs
 | 
						return allErrs
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -25,12 +25,15 @@ import (
 | 
				
			|||||||
	"github.com/stretchr/testify/assert"
 | 
						"github.com/stretchr/testify/assert"
 | 
				
			||||||
	"github.com/stretchr/testify/require"
 | 
						"github.com/stretchr/testify/require"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"k8s.io/api/core/v1"
 | 
						v1 "k8s.io/api/core/v1"
 | 
				
			||||||
	policy "k8s.io/api/policy/v1beta1"
 | 
						policy "k8s.io/api/policy/v1beta1"
 | 
				
			||||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
						metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/util/diff"
 | 
						"k8s.io/apimachinery/pkg/util/diff"
 | 
				
			||||||
 | 
						utilfeature "k8s.io/apiserver/pkg/util/feature"
 | 
				
			||||||
 | 
						featuregatetesting "k8s.io/component-base/featuregate/testing"
 | 
				
			||||||
	api "k8s.io/kubernetes/pkg/apis/core"
 | 
						api "k8s.io/kubernetes/pkg/apis/core"
 | 
				
			||||||
	k8s_api_v1 "k8s.io/kubernetes/pkg/apis/core/v1"
 | 
						k8s_api_v1 "k8s.io/kubernetes/pkg/apis/core/v1"
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/pkg/features"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/security/apparmor"
 | 
						"k8s.io/kubernetes/pkg/security/apparmor"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/security/podsecuritypolicy/seccomp"
 | 
						"k8s.io/kubernetes/pkg/security/podsecuritypolicy/seccomp"
 | 
				
			||||||
	psputil "k8s.io/kubernetes/pkg/security/podsecuritypolicy/util"
 | 
						psputil "k8s.io/kubernetes/pkg/security/podsecuritypolicy/util"
 | 
				
			||||||
@@ -172,6 +175,8 @@ func TestMutateContainerNonmutating(t *testing.T) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestValidatePodFailures(t *testing.T) {
 | 
					func TestValidatePodFailures(t *testing.T) {
 | 
				
			||||||
 | 
						defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, true)()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	failHostNetworkPod := defaultPod()
 | 
						failHostNetworkPod := defaultPod()
 | 
				
			||||||
	failHostNetworkPod.Spec.SecurityContext.HostNetwork = true
 | 
						failHostNetworkPod.Spec.SecurityContext.HostNetwork = true
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -328,6 +333,18 @@ func TestValidatePodFailures(t *testing.T) {
 | 
				
			|||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						failCSIDriverPod := defaultPod()
 | 
				
			||||||
 | 
						failCSIDriverPod.Spec.Volumes = []api.Volume{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								Name: "csi volume pod",
 | 
				
			||||||
 | 
								VolumeSource: api.VolumeSource{
 | 
				
			||||||
 | 
									CSI: &api.CSIVolumeSource{
 | 
				
			||||||
 | 
										Driver: "csi.driver.foo",
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	errorCases := map[string]struct {
 | 
						errorCases := map[string]struct {
 | 
				
			||||||
		pod           *api.Pod
 | 
							pod           *api.Pod
 | 
				
			||||||
		psp           *policy.PodSecurityPolicy
 | 
							psp           *policy.PodSecurityPolicy
 | 
				
			||||||
@@ -433,6 +450,40 @@ func TestValidatePodFailures(t *testing.T) {
 | 
				
			|||||||
			psp:           allowFlexVolumesPSP(false, true),
 | 
								psp:           allowFlexVolumesPSP(false, true),
 | 
				
			||||||
			expectedError: "Flexvolume driver is not allowed to be used",
 | 
								expectedError: "Flexvolume driver is not allowed to be used",
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
							"CSI policy using disallowed CDI driver": {
 | 
				
			||||||
 | 
								pod: failCSIDriverPod,
 | 
				
			||||||
 | 
								psp: func() *policy.PodSecurityPolicy {
 | 
				
			||||||
 | 
									psp := defaultPSP()
 | 
				
			||||||
 | 
									psp.Spec.Volumes = []policy.FSType{policy.CSI}
 | 
				
			||||||
 | 
									psp.Spec.AllowedCSIDrivers = []policy.AllowedCSIDriver{{Name: "csi.driver.disallowed"}}
 | 
				
			||||||
 | 
									return psp
 | 
				
			||||||
 | 
								}(),
 | 
				
			||||||
 | 
								expectedError: "Inline CSI driver is not allowed to be used",
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"Using inline CSI driver with no policy specified": {
 | 
				
			||||||
 | 
								pod: failCSIDriverPod,
 | 
				
			||||||
 | 
								psp: func() *policy.PodSecurityPolicy {
 | 
				
			||||||
 | 
									psp := defaultPSP()
 | 
				
			||||||
 | 
									psp.Spec.AllowedCSIDrivers = []policy.AllowedCSIDriver{{Name: "csi.driver.foo"}}
 | 
				
			||||||
 | 
									return psp
 | 
				
			||||||
 | 
								}(),
 | 
				
			||||||
 | 
								expectedError: "csi volumes are not allowed to be used",
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"policy.All using disallowed CDI driver": {
 | 
				
			||||||
 | 
								pod: failCSIDriverPod,
 | 
				
			||||||
 | 
								psp: func() *policy.PodSecurityPolicy {
 | 
				
			||||||
 | 
									psp := defaultPSP()
 | 
				
			||||||
 | 
									psp.Spec.Volumes = []policy.FSType{policy.All}
 | 
				
			||||||
 | 
									psp.Spec.AllowedCSIDrivers = []policy.AllowedCSIDriver{{Name: "csi.driver.disallowed"}}
 | 
				
			||||||
 | 
									return psp
 | 
				
			||||||
 | 
								}(),
 | 
				
			||||||
 | 
								expectedError: "Inline CSI driver is not allowed to be used",
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"CSI inline volumes without proper policy set": {
 | 
				
			||||||
 | 
								pod:           failCSIDriverPod,
 | 
				
			||||||
 | 
								psp:           defaultPSP(),
 | 
				
			||||||
 | 
								expectedError: "csi volumes are not allowed to be used",
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	for name, test := range errorCases {
 | 
						for name, test := range errorCases {
 | 
				
			||||||
		t.Run(name, func(t *testing.T) {
 | 
							t.Run(name, func(t *testing.T) {
 | 
				
			||||||
@@ -616,6 +667,8 @@ func TestValidateContainerFailures(t *testing.T) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestValidatePodSuccess(t *testing.T) {
 | 
					func TestValidatePodSuccess(t *testing.T) {
 | 
				
			||||||
 | 
						defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, true)()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	hostNetworkPSP := defaultPSP()
 | 
						hostNetworkPSP := defaultPSP()
 | 
				
			||||||
	hostNetworkPSP.Spec.HostNetwork = true
 | 
						hostNetworkPSP.Spec.HostNetwork = true
 | 
				
			||||||
	hostNetworkPod := defaultPod()
 | 
						hostNetworkPod := defaultPod()
 | 
				
			||||||
@@ -806,6 +859,34 @@ func TestValidatePodSuccess(t *testing.T) {
 | 
				
			|||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						csiDriverPod := defaultPod()
 | 
				
			||||||
 | 
						csiDriverPod.Spec.Volumes = []api.Volume{
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								Name: "csi inline driver",
 | 
				
			||||||
 | 
								VolumeSource: api.VolumeSource{
 | 
				
			||||||
 | 
									CSI: &api.CSIVolumeSource{
 | 
				
			||||||
 | 
										Driver: "foo",
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								Name: "csi inline driver 2",
 | 
				
			||||||
 | 
								VolumeSource: api.VolumeSource{
 | 
				
			||||||
 | 
									CSI: &api.CSIVolumeSource{
 | 
				
			||||||
 | 
										Driver: "bar",
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							{
 | 
				
			||||||
 | 
								Name: "csi inline driver 3",
 | 
				
			||||||
 | 
								VolumeSource: api.VolumeSource{
 | 
				
			||||||
 | 
									CSI: &api.CSIVolumeSource{
 | 
				
			||||||
 | 
										Driver: "baz",
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	successCases := map[string]struct {
 | 
						successCases := map[string]struct {
 | 
				
			||||||
		pod *api.Pod
 | 
							pod *api.Pod
 | 
				
			||||||
		psp *policy.PodSecurityPolicy
 | 
							psp *policy.PodSecurityPolicy
 | 
				
			||||||
@@ -886,6 +967,33 @@ func TestValidatePodSuccess(t *testing.T) {
 | 
				
			|||||||
			pod: flexVolumePod,
 | 
								pod: flexVolumePod,
 | 
				
			||||||
			psp: allowFlexVolumesPSP(true, false),
 | 
								psp: allowFlexVolumesPSP(true, false),
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
							"CSI policy with no CSI volumes used": {
 | 
				
			||||||
 | 
								pod: defaultPod(),
 | 
				
			||||||
 | 
								psp: func() *policy.PodSecurityPolicy {
 | 
				
			||||||
 | 
									psp := defaultPSP()
 | 
				
			||||||
 | 
									psp.Spec.Volumes = []policy.FSType{policy.CSI}
 | 
				
			||||||
 | 
									psp.Spec.AllowedCSIDrivers = []policy.AllowedCSIDriver{{Name: "foo"}, {Name: "bar"}, {Name: "baz"}}
 | 
				
			||||||
 | 
									return psp
 | 
				
			||||||
 | 
								}(),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"CSI policy with CSI inline volumes used": {
 | 
				
			||||||
 | 
								pod: csiDriverPod,
 | 
				
			||||||
 | 
								psp: func() *policy.PodSecurityPolicy {
 | 
				
			||||||
 | 
									psp := defaultPSP()
 | 
				
			||||||
 | 
									psp.Spec.Volumes = []policy.FSType{policy.CSI}
 | 
				
			||||||
 | 
									psp.Spec.AllowedCSIDrivers = []policy.AllowedCSIDriver{{Name: "foo"}, {Name: "bar"}, {Name: "baz"}}
 | 
				
			||||||
 | 
									return psp
 | 
				
			||||||
 | 
								}(),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"policy.All with CSI inline volumes used": {
 | 
				
			||||||
 | 
								pod: csiDriverPod,
 | 
				
			||||||
 | 
								psp: func() *policy.PodSecurityPolicy {
 | 
				
			||||||
 | 
									psp := defaultPSP()
 | 
				
			||||||
 | 
									psp.Spec.Volumes = []policy.FSType{policy.All}
 | 
				
			||||||
 | 
									psp.Spec.AllowedCSIDrivers = []policy.AllowedCSIDriver{{Name: "foo"}, {Name: "bar"}, {Name: "baz"}}
 | 
				
			||||||
 | 
									return psp
 | 
				
			||||||
 | 
								}(),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for name, test := range successCases {
 | 
						for name, test := range successCases {
 | 
				
			||||||
@@ -1218,6 +1326,8 @@ func defaultV1Pod() *v1.Pod {
 | 
				
			|||||||
// a pod with that type of volume and deny it, accept it explicitly, or accept it with
 | 
					// a pod with that type of volume and deny it, accept it explicitly, or accept it with
 | 
				
			||||||
// the FSTypeAll wildcard.
 | 
					// the FSTypeAll wildcard.
 | 
				
			||||||
func TestValidateAllowedVolumes(t *testing.T) {
 | 
					func TestValidateAllowedVolumes(t *testing.T) {
 | 
				
			||||||
 | 
						defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, true)()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	val := reflect.ValueOf(api.VolumeSource{})
 | 
						val := reflect.ValueOf(api.VolumeSource{})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for i := 0; i < val.NumField(); i++ {
 | 
						for i := 0; i < val.NumField(); i++ {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -41,6 +41,7 @@ go_test(
 | 
				
			|||||||
        "//pkg/apis/core:go_default_library",
 | 
					        "//pkg/apis/core:go_default_library",
 | 
				
			||||||
        "//pkg/apis/core/v1:go_default_library",
 | 
					        "//pkg/apis/core/v1:go_default_library",
 | 
				
			||||||
        "//pkg/controller:go_default_library",
 | 
					        "//pkg/controller:go_default_library",
 | 
				
			||||||
 | 
					        "//pkg/features:go_default_library",
 | 
				
			||||||
        "//pkg/security/apparmor:go_default_library",
 | 
					        "//pkg/security/apparmor:go_default_library",
 | 
				
			||||||
        "//pkg/security/podsecuritypolicy:go_default_library",
 | 
					        "//pkg/security/podsecuritypolicy:go_default_library",
 | 
				
			||||||
        "//pkg/security/podsecuritypolicy/seccomp:go_default_library",
 | 
					        "//pkg/security/podsecuritypolicy/seccomp:go_default_library",
 | 
				
			||||||
@@ -56,7 +57,9 @@ go_test(
 | 
				
			|||||||
        "//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library",
 | 
					        "//staging/src/k8s.io/apiserver/pkg/authentication/user:go_default_library",
 | 
				
			||||||
        "//staging/src/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
 | 
					        "//staging/src/k8s.io/apiserver/pkg/authorization/authorizer:go_default_library",
 | 
				
			||||||
        "//staging/src/k8s.io/apiserver/pkg/authorization/authorizerfactory:go_default_library",
 | 
					        "//staging/src/k8s.io/apiserver/pkg/authorization/authorizerfactory:go_default_library",
 | 
				
			||||||
 | 
					        "//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
 | 
				
			||||||
        "//staging/src/k8s.io/client-go/informers:go_default_library",
 | 
					        "//staging/src/k8s.io/client-go/informers:go_default_library",
 | 
				
			||||||
 | 
					        "//staging/src/k8s.io/component-base/featuregate/testing:go_default_library",
 | 
				
			||||||
        "//vendor/github.com/stretchr/testify/assert:go_default_library",
 | 
					        "//vendor/github.com/stretchr/testify/assert:go_default_library",
 | 
				
			||||||
        "//vendor/k8s.io/utils/pointer:go_default_library",
 | 
					        "//vendor/k8s.io/utils/pointer:go_default_library",
 | 
				
			||||||
    ],
 | 
					    ],
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -35,11 +35,14 @@ import (
 | 
				
			|||||||
	"k8s.io/apiserver/pkg/authentication/user"
 | 
						"k8s.io/apiserver/pkg/authentication/user"
 | 
				
			||||||
	"k8s.io/apiserver/pkg/authorization/authorizer"
 | 
						"k8s.io/apiserver/pkg/authorization/authorizer"
 | 
				
			||||||
	"k8s.io/apiserver/pkg/authorization/authorizerfactory"
 | 
						"k8s.io/apiserver/pkg/authorization/authorizerfactory"
 | 
				
			||||||
 | 
						utilfeature "k8s.io/apiserver/pkg/util/feature"
 | 
				
			||||||
	"k8s.io/client-go/informers"
 | 
						"k8s.io/client-go/informers"
 | 
				
			||||||
 | 
						featuregatetesting "k8s.io/component-base/featuregate/testing"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/api/legacyscheme"
 | 
						"k8s.io/kubernetes/pkg/api/legacyscheme"
 | 
				
			||||||
	kapi "k8s.io/kubernetes/pkg/apis/core"
 | 
						kapi "k8s.io/kubernetes/pkg/apis/core"
 | 
				
			||||||
	k8s_api_v1 "k8s.io/kubernetes/pkg/apis/core/v1"
 | 
						k8s_api_v1 "k8s.io/kubernetes/pkg/apis/core/v1"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/controller"
 | 
						"k8s.io/kubernetes/pkg/controller"
 | 
				
			||||||
 | 
						"k8s.io/kubernetes/pkg/features"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/security/apparmor"
 | 
						"k8s.io/kubernetes/pkg/security/apparmor"
 | 
				
			||||||
	kpsp "k8s.io/kubernetes/pkg/security/podsecuritypolicy"
 | 
						kpsp "k8s.io/kubernetes/pkg/security/podsecuritypolicy"
 | 
				
			||||||
	"k8s.io/kubernetes/pkg/security/podsecuritypolicy/seccomp"
 | 
						"k8s.io/kubernetes/pkg/security/podsecuritypolicy/seccomp"
 | 
				
			||||||
@@ -625,6 +628,8 @@ func TestAdmitCaps(t *testing.T) {
 | 
				
			|||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TestAdmitVolumes(t *testing.T) {
 | 
					func TestAdmitVolumes(t *testing.T) {
 | 
				
			||||||
 | 
						defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.CSIInlineVolume, true)()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	val := reflect.ValueOf(kapi.VolumeSource{})
 | 
						val := reflect.ValueOf(kapi.VolumeSource{})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for i := 0; i < val.NumField(); i++ {
 | 
						for i := 0; i < val.NumField(); i++ {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -929,7 +929,8 @@ type PodSecurityPolicySpec struct {
 | 
				
			|||||||
	// +optional
 | 
						// +optional
 | 
				
			||||||
	AllowedFlexVolumes []AllowedFlexVolume `json:"allowedFlexVolumes,omitempty" protobuf:"bytes,18,rep,name=allowedFlexVolumes"`
 | 
						AllowedFlexVolumes []AllowedFlexVolume `json:"allowedFlexVolumes,omitempty" protobuf:"bytes,18,rep,name=allowedFlexVolumes"`
 | 
				
			||||||
	// AllowedCSIDrivers is a whitelist of inline CSI drivers that must be explicitly set to be embedded within a pod spec.
 | 
						// AllowedCSIDrivers is a whitelist of inline CSI drivers that must be explicitly set to be embedded within a pod spec.
 | 
				
			||||||
	// An empty value means no CSI drivers can run inline within a pod spec.
 | 
						// An empty value indicates that any CSI driver can be used for inline ephemeral volumes.
 | 
				
			||||||
 | 
						// This is an alpha field, and is only honored if the API server enables the CSIInlineVolume feature gate.
 | 
				
			||||||
	// +optional
 | 
						// +optional
 | 
				
			||||||
	AllowedCSIDrivers []AllowedCSIDriver `json:"allowedCSIDrivers,omitempty" protobuf:"bytes,23,rep,name=allowedCSIDrivers"`
 | 
						AllowedCSIDrivers []AllowedCSIDriver `json:"allowedCSIDrivers,omitempty" protobuf:"bytes,23,rep,name=allowedCSIDrivers"`
 | 
				
			||||||
	// allowedUnsafeSysctls is a list of explicitly allowed unsafe sysctls, defaults to none.
 | 
						// allowedUnsafeSysctls is a list of explicitly allowed unsafe sysctls, defaults to none.
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -17,7 +17,7 @@ limitations under the License.
 | 
				
			|||||||
package v1beta1
 | 
					package v1beta1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"k8s.io/api/core/v1"
 | 
						v1 "k8s.io/api/core/v1"
 | 
				
			||||||
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
						metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 | 
				
			||||||
	"k8s.io/apimachinery/pkg/util/intstr"
 | 
						"k8s.io/apimachinery/pkg/util/intstr"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
@@ -217,7 +217,8 @@ type PodSecurityPolicySpec struct {
 | 
				
			|||||||
	// +optional
 | 
						// +optional
 | 
				
			||||||
	AllowedFlexVolumes []AllowedFlexVolume `json:"allowedFlexVolumes,omitempty" protobuf:"bytes,18,rep,name=allowedFlexVolumes"`
 | 
						AllowedFlexVolumes []AllowedFlexVolume `json:"allowedFlexVolumes,omitempty" protobuf:"bytes,18,rep,name=allowedFlexVolumes"`
 | 
				
			||||||
	// AllowedCSIDrivers is a whitelist of inline CSI drivers that must be explicitly set to be embedded within a pod spec.
 | 
						// AllowedCSIDrivers is a whitelist of inline CSI drivers that must be explicitly set to be embedded within a pod spec.
 | 
				
			||||||
	// An empty value means no CSI drivers can run inline within a pod spec.
 | 
						// An empty value indicates that any CSI driver can be used for inline ephemeral volumes.
 | 
				
			||||||
 | 
						// This is an alpha field, and is only honored if the API server enables the CSIInlineVolume feature gate.
 | 
				
			||||||
	// +optional
 | 
						// +optional
 | 
				
			||||||
	AllowedCSIDrivers []AllowedCSIDriver `json:"allowedCSIDrivers,omitempty" protobuf:"bytes,23,rep,name=allowedCSIDrivers"`
 | 
						AllowedCSIDrivers []AllowedCSIDriver `json:"allowedCSIDrivers,omitempty" protobuf:"bytes,23,rep,name=allowedCSIDrivers"`
 | 
				
			||||||
	// allowedUnsafeSysctls is a list of explicitly allowed unsafe sysctls, defaults to none.
 | 
						// allowedUnsafeSysctls is a list of explicitly allowed unsafe sysctls, defaults to none.
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user