mirror of https://github.com/k3s-io/k3s
Enforce pod security policy for CSI inline
parent
864e5e564a
commit
8e0cf65310
|
@ -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.
|
||||||
|
|
Loading…
Reference in New Issue