mirror of https://github.com/k3s-io/k3s
support flexvlome in psp
parent
84b3dcca08
commit
98faf6b39c
|
@ -860,6 +860,11 @@ type PodSecurityPolicySpec struct {
|
|||
// AllowedHostPaths is a white list of allowed host paths. Empty indicates that all host paths may be used.
|
||||
// +optional
|
||||
AllowedHostPaths []AllowedHostPath
|
||||
// AllowedFlexVolumes is a whitelist of allowed Flexvolumes. Empty or nil indicates that all
|
||||
// Flexvolumes may be used. This parameter is effective only when the usage of the Flexvolumes
|
||||
// is allowed in the "Volumes" field.
|
||||
// +optional
|
||||
AllowedFlexVolumes []AllowedFlexVolume
|
||||
}
|
||||
|
||||
// AllowedHostPath defines the host volume conditions that will be enabled by a policy
|
||||
|
@ -923,6 +928,12 @@ var (
|
|||
All FSType = "*"
|
||||
)
|
||||
|
||||
// AllowedFlexVolume represents a single Flexvolume that is allowed to be used.
|
||||
type AllowedFlexVolume struct {
|
||||
// Driver is the name of the Flexvolume driver.
|
||||
Driver string
|
||||
}
|
||||
|
||||
// SELinuxStrategyOptions defines the strategy type and any options used to create the strategy.
|
||||
type SELinuxStrategyOptions struct {
|
||||
// Rule is the strategy that will dictate the allowable labels that may be set.
|
||||
|
|
|
@ -655,6 +655,7 @@ func ValidatePodSecurityPolicySpec(spec *extensions.PodSecurityPolicySpec, fldPa
|
|||
allErrs = append(allErrs, validatePSPCapsAgainstDrops(spec.RequiredDropCapabilities, spec.AllowedCapabilities, field.NewPath("allowedCapabilities"))...)
|
||||
allErrs = append(allErrs, validatePSPDefaultAllowPrivilegeEscalation(fldPath.Child("defaultAllowPrivilegeEscalation"), spec.DefaultAllowPrivilegeEscalation, spec.AllowPrivilegeEscalation)...)
|
||||
allErrs = append(allErrs, validatePSPAllowedHostPaths(fldPath.Child("allowedHostPaths"), spec.AllowedHostPaths)...)
|
||||
allErrs = append(allErrs, validatePSPAllowedFlexVolumes(fldPath.Child("allowedFlexVolumes"), spec.AllowedFlexVolumes)...)
|
||||
|
||||
return allErrs
|
||||
}
|
||||
|
@ -721,6 +722,20 @@ func validatePSPAllowedHostPaths(fldPath *field.Path, allowedHostPaths []extensi
|
|||
return allErrs
|
||||
}
|
||||
|
||||
// validatePSPAllowedFlexVolumes
|
||||
func validatePSPAllowedFlexVolumes(fldPath *field.Path, flexVolumes []extensions.AllowedFlexVolume) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
if len(flexVolumes) > 0 {
|
||||
for idx, fv := range flexVolumes {
|
||||
if len(fv.Driver) == 0 {
|
||||
allErrs = append(allErrs, field.Required(fldPath.Child("allowedFlexVolumes").Index(idx).Child("driver"),
|
||||
"must specify a driver"))
|
||||
}
|
||||
}
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// validatePSPSELinux validates the SELinux fields of PodSecurityPolicy.
|
||||
func validatePSPSELinux(fldPath *field.Path, seLinux *extensions.SELinuxStrategyOptions) field.ErrorList {
|
||||
allErrs := field.ErrorList{}
|
||||
|
@ -802,7 +817,6 @@ func validatePodSecurityPolicyVolumes(fldPath *field.Path, volumes []extensions.
|
|||
allErrs = append(allErrs, field.NotSupported(fldPath.Child("volumes"), v, allowed.List()))
|
||||
}
|
||||
}
|
||||
|
||||
return allErrs
|
||||
}
|
||||
|
||||
|
|
|
@ -2450,6 +2450,13 @@ func TestValidatePodSecurityPolicy(t *testing.T) {
|
|||
pe := true
|
||||
invalidDefaultAllowPrivilegeEscalation.Spec.DefaultAllowPrivilegeEscalation = &pe
|
||||
|
||||
emptyFlexDriver := validPSP()
|
||||
emptyFlexDriver.Spec.Volumes = []extensions.FSType{extensions.FlexVolume}
|
||||
emptyFlexDriver.Spec.AllowedFlexVolumes = []extensions.AllowedFlexVolume{{}}
|
||||
|
||||
nonEmptyFlexVolumes := validPSP()
|
||||
nonEmptyFlexVolumes.Spec.AllowedFlexVolumes = []extensions.AllowedFlexVolume{{Driver: "example/driver"}}
|
||||
|
||||
type testCase struct {
|
||||
psp *extensions.PodSecurityPolicy
|
||||
errorType field.ErrorType
|
||||
|
@ -2581,6 +2588,11 @@ func TestValidatePodSecurityPolicy(t *testing.T) {
|
|||
errorType: field.ErrorTypeInvalid,
|
||||
errorDetail: "must not contain '..'",
|
||||
},
|
||||
"empty flex volume driver": {
|
||||
psp: emptyFlexDriver,
|
||||
errorType: field.ErrorTypeRequired,
|
||||
errorDetail: "must specify a driver",
|
||||
},
|
||||
}
|
||||
|
||||
for k, v := range errorCases {
|
||||
|
@ -2660,6 +2672,17 @@ func TestValidatePodSecurityPolicy(t *testing.T) {
|
|||
validDefaultAllowPrivilegeEscalation.Spec.DefaultAllowPrivilegeEscalation = &pe
|
||||
validDefaultAllowPrivilegeEscalation.Spec.AllowPrivilegeEscalation = true
|
||||
|
||||
flexvolumeWhenFlexVolumesAllowed := validPSP()
|
||||
flexvolumeWhenFlexVolumesAllowed.Spec.Volumes = []extensions.FSType{extensions.FlexVolume}
|
||||
flexvolumeWhenFlexVolumesAllowed.Spec.AllowedFlexVolumes = []extensions.AllowedFlexVolume{
|
||||
{Driver: "example/driver1"},
|
||||
}
|
||||
|
||||
flexvolumeWhenAllVolumesAllowed := validPSP()
|
||||
flexvolumeWhenAllVolumesAllowed.Spec.Volumes = []extensions.FSType{extensions.All}
|
||||
flexvolumeWhenAllVolumesAllowed.Spec.AllowedFlexVolumes = []extensions.AllowedFlexVolume{
|
||||
{Driver: "example/driver2"},
|
||||
}
|
||||
successCases := map[string]struct {
|
||||
psp *extensions.PodSecurityPolicy
|
||||
}{
|
||||
|
@ -2690,6 +2713,12 @@ func TestValidatePodSecurityPolicy(t *testing.T) {
|
|||
"valid defaultAllowPrivilegeEscalation as true": {
|
||||
psp: validDefaultAllowPrivilegeEscalation,
|
||||
},
|
||||
"allow white-listed flexVolume when flex volumes are allowed": {
|
||||
psp: flexvolumeWhenFlexVolumesAllowed,
|
||||
},
|
||||
"allow white-listed flexVolume when all volumes are allowed": {
|
||||
psp: flexvolumeWhenAllVolumesAllowed,
|
||||
},
|
||||
}
|
||||
|
||||
for k, v := range successCases {
|
||||
|
|
|
@ -3386,6 +3386,9 @@ func describePodSecurityPolicy(psp *extensions.PodSecurityPolicy) (string, error
|
|||
w.Write(LEVEL_1, "Allowed Capabilities:\t%s\n", capsToString(psp.Spec.AllowedCapabilities))
|
||||
w.Write(LEVEL_1, "Allowed Volume Types:\t%s\n", fsTypeToString(psp.Spec.Volumes))
|
||||
|
||||
if len(psp.Spec.AllowedFlexVolumes) > 0 {
|
||||
w.Write(LEVEL_1, "Allowed FlexVolume Types:\t%s\n", flexVolumesToString(psp.Spec.AllowedFlexVolumes))
|
||||
}
|
||||
w.Write(LEVEL_1, "Allow Host Network:\t%t\n", psp.Spec.HostNetwork)
|
||||
w.Write(LEVEL_1, "Allow Host Ports:\t%s\n", hostPortRangeToString(psp.Spec.HostPorts))
|
||||
w.Write(LEVEL_1, "Allow Host PID:\t%t\n", psp.Spec.HostPID)
|
||||
|
@ -3419,10 +3422,14 @@ func describePodSecurityPolicy(psp *extensions.PodSecurityPolicy) (string, error
|
|||
}
|
||||
|
||||
func stringOrNone(s string) string {
|
||||
return stringOrDefaultValue(s, "<none>")
|
||||
}
|
||||
|
||||
func stringOrDefaultValue(s, defaultValue string) string {
|
||||
if len(s) > 0 {
|
||||
return s
|
||||
}
|
||||
return "<none>"
|
||||
return defaultValue
|
||||
}
|
||||
|
||||
func fsTypeToString(volumes []extensions.FSType) string {
|
||||
|
@ -3433,6 +3440,14 @@ func fsTypeToString(volumes []extensions.FSType) string {
|
|||
return stringOrNone(strings.Join(strVolumes, ","))
|
||||
}
|
||||
|
||||
func flexVolumesToString(flexVolumes []extensions.AllowedFlexVolume) string {
|
||||
volumes := []string{}
|
||||
for _, flexVolume := range flexVolumes {
|
||||
volumes = append(volumes, "driver="+flexVolume.Driver)
|
||||
}
|
||||
return stringOrDefaultValue(strings.Join(volumes, ","), "<all>")
|
||||
}
|
||||
|
||||
func hostPortRangeToString(ranges []extensions.HostPortRange) string {
|
||||
formattedString := ""
|
||||
if ranges != nil {
|
||||
|
|
|
@ -233,9 +233,24 @@ func (s *simpleProvider) ValidatePodSecurityContext(pod *api.Pod, fldPath *field
|
|||
fmt.Sprintf("is not allowed to be used")))
|
||||
}
|
||||
}
|
||||
|
||||
if fsType == extensions.FlexVolume && len(s.psp.Spec.AllowedFlexVolumes) > 0 {
|
||||
found := false
|
||||
driver := v.FlexVolume.Driver
|
||||
for _, allowedFlexVolume := range s.psp.Spec.AllowedFlexVolumes {
|
||||
if driver == allowedFlexVolume.Driver {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
allErrs = append(allErrs,
|
||||
field.Invalid(fldPath.Child("volumes").Index(i).Child("driver"), driver,
|
||||
"Flexvolume driver is not allowed to be used"))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return allErrs
|
||||
}
|
||||
|
||||
|
|
|
@ -256,6 +256,18 @@ func TestValidatePodSecurityContextFailures(t *testing.T) {
|
|||
failSeccompProfilePod := defaultPod()
|
||||
failSeccompProfilePod.Annotations = map[string]string{api.SeccompPodAnnotationKey: "foo"}
|
||||
|
||||
podWithInvalidFlexVolumeDriver := defaultPod()
|
||||
podWithInvalidFlexVolumeDriver.Spec.Volumes = []api.Volume{
|
||||
{
|
||||
Name: "flex-volume",
|
||||
VolumeSource: api.VolumeSource{
|
||||
FlexVolume: &api.FlexVolumeSource{
|
||||
Driver: "example/unknown",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
errorCases := map[string]struct {
|
||||
pod *api.Pod
|
||||
psp *extensions.PodSecurityPolicy
|
||||
|
@ -341,6 +353,16 @@ func TestValidatePodSecurityContextFailures(t *testing.T) {
|
|||
psp: defaultPSP(),
|
||||
expectedError: "Forbidden: seccomp may not be set",
|
||||
},
|
||||
"fail pod with disallowed flexVolume when flex volumes are allowed": {
|
||||
pod: podWithInvalidFlexVolumeDriver,
|
||||
psp: allowFlexVolumesPSP(false, false),
|
||||
expectedError: "Flexvolume driver is not allowed to be used",
|
||||
},
|
||||
"fail pod with disallowed flexVolume when all volumes are allowed": {
|
||||
pod: podWithInvalidFlexVolumeDriver,
|
||||
psp: allowFlexVolumesPSP(false, true),
|
||||
expectedError: "Flexvolume driver is not allowed to be used",
|
||||
},
|
||||
}
|
||||
for k, v := range errorCases {
|
||||
provider, err := NewSimpleProvider(v.psp, "namespace", NewSimpleStrategyFactory())
|
||||
|
@ -358,6 +380,28 @@ func TestValidatePodSecurityContextFailures(t *testing.T) {
|
|||
}
|
||||
}
|
||||
|
||||
func allowFlexVolumesPSP(allowAllFlexVolumes, allowAllVolumes bool) *extensions.PodSecurityPolicy {
|
||||
psp := defaultPSP()
|
||||
|
||||
allowedVolumes := []extensions.AllowedFlexVolume{
|
||||
{Driver: "example/foo"},
|
||||
{Driver: "example/bar"},
|
||||
}
|
||||
if allowAllFlexVolumes {
|
||||
allowedVolumes = []extensions.AllowedFlexVolume{}
|
||||
}
|
||||
|
||||
allowedVolumeType := extensions.FlexVolume
|
||||
if allowAllVolumes {
|
||||
allowedVolumeType = extensions.All
|
||||
}
|
||||
|
||||
psp.Spec.AllowedFlexVolumes = allowedVolumes
|
||||
psp.Spec.Volumes = []extensions.FSType{allowedVolumeType}
|
||||
|
||||
return psp
|
||||
}
|
||||
|
||||
func TestValidateContainerSecurityContextFailures(t *testing.T) {
|
||||
// fail user strat
|
||||
failUserPSP := defaultPSP()
|
||||
|
@ -597,6 +641,18 @@ func TestValidatePodSecurityContextSuccess(t *testing.T) {
|
|||
api.SeccompPodAnnotationKey: "foo",
|
||||
}
|
||||
|
||||
flexVolumePod := defaultPod()
|
||||
flexVolumePod.Spec.Volumes = []api.Volume{
|
||||
{
|
||||
Name: "flex-volume",
|
||||
VolumeSource: api.VolumeSource{
|
||||
FlexVolume: &api.FlexVolumeSource{
|
||||
Driver: "example/bar",
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
successCases := map[string]struct {
|
||||
pod *api.Pod
|
||||
psp *extensions.PodSecurityPolicy
|
||||
|
@ -653,6 +709,22 @@ func TestValidatePodSecurityContextSuccess(t *testing.T) {
|
|||
pod: seccompPod,
|
||||
psp: seccompPSP,
|
||||
},
|
||||
"flex volume driver in a whitelist (all volumes are allowed)": {
|
||||
pod: flexVolumePod,
|
||||
psp: allowFlexVolumesPSP(false, true),
|
||||
},
|
||||
"flex volume driver with empty whitelist (all volumes are allowed)": {
|
||||
pod: flexVolumePod,
|
||||
psp: allowFlexVolumesPSP(true, true),
|
||||
},
|
||||
"flex volume driver in a whitelist (only flex volumes are allowed)": {
|
||||
pod: flexVolumePod,
|
||||
psp: allowFlexVolumesPSP(false, false),
|
||||
},
|
||||
"flex volume driver with empty whitelist (only flex volumes volumes are allowed)": {
|
||||
pod: flexVolumePod,
|
||||
psp: allowFlexVolumesPSP(true, false),
|
||||
},
|
||||
}
|
||||
|
||||
for k, v := range successCases {
|
||||
|
|
|
@ -938,6 +938,11 @@ type PodSecurityPolicySpec struct {
|
|||
// is a white list of allowed host paths. Empty indicates that all host paths may be used.
|
||||
// +optional
|
||||
AllowedHostPaths []AllowedHostPath `json:"allowedHostPaths,omitempty" protobuf:"bytes,17,rep,name=allowedHostPaths"`
|
||||
// AllowedFlexVolumes is a whitelist of allowed Flexvolumes. Empty or nil indicates that all
|
||||
// Flexvolumes may be used. This parameter is effective only when the usage of the Flexvolumes
|
||||
// is allowed in the "Volumes" field.
|
||||
// +optional
|
||||
AllowedFlexVolumes []AllowedFlexVolume `json:"allowedFlexVolumes,omitempty" protobuf:"bytes,18,rep,name=allowedFlexVolumes"`
|
||||
}
|
||||
|
||||
// defines the host volume conditions that will be enabled by a policy
|
||||
|
@ -981,6 +986,12 @@ var (
|
|||
All FSType = "*"
|
||||
)
|
||||
|
||||
// AllowedFlexVolume represents a single Flexvolume that is allowed to be used.
|
||||
type AllowedFlexVolume struct {
|
||||
// Driver is the name of the Flexvolume driver.
|
||||
Driver string `json:"driver" protobuf:"bytes,1,opt,name=driver"`
|
||||
}
|
||||
|
||||
// Host Port Range defines a range of host ports that will be enabled by a policy
|
||||
// for pods to use. It requires both the start and end to be defined.
|
||||
type HostPortRange struct {
|
||||
|
|
Loading…
Reference in New Issue