mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-27 13:37:30 +00:00
PodSecurityPolicy: pass effective selinux options to validate
This commit is contained in:
parent
5dc4da7c6a
commit
e34a00d14f
@ -209,14 +209,7 @@ func (s *simpleProvider) ValidatePodSecurityContext(pod *api.Pod, fldPath *field
|
|||||||
allErrs = append(allErrs, s.strategies.SupplementalGroupStrategy.Validate(pod, pod.Spec.SecurityContext.SupplementalGroups)...)
|
allErrs = append(allErrs, s.strategies.SupplementalGroupStrategy.Validate(pod, pod.Spec.SecurityContext.SupplementalGroups)...)
|
||||||
allErrs = append(allErrs, s.strategies.SeccompStrategy.ValidatePod(pod)...)
|
allErrs = append(allErrs, s.strategies.SeccompStrategy.ValidatePod(pod)...)
|
||||||
|
|
||||||
// make a dummy container context to reuse the selinux strategies
|
allErrs = append(allErrs, s.strategies.SELinuxStrategy.Validate(fldPath.Child("seLinuxOptions"), pod, nil, pod.Spec.SecurityContext.SELinuxOptions)...)
|
||||||
container := &api.Container{
|
|
||||||
Name: pod.Name,
|
|
||||||
SecurityContext: &api.SecurityContext{
|
|
||||||
SELinuxOptions: pod.Spec.SecurityContext.SELinuxOptions,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
allErrs = append(allErrs, s.strategies.SELinuxStrategy.Validate(pod, container)...)
|
|
||||||
|
|
||||||
if !s.psp.Spec.HostNetwork && pod.Spec.SecurityContext.HostNetwork {
|
if !s.psp.Spec.HostNetwork && pod.Spec.SecurityContext.HostNetwork {
|
||||||
allErrs = append(allErrs, field.Invalid(fldPath.Child("hostNetwork"), pod.Spec.SecurityContext.HostNetwork, "Host network is not allowed to be used"))
|
allErrs = append(allErrs, field.Invalid(fldPath.Child("hostNetwork"), pod.Spec.SecurityContext.HostNetwork, "Host network is not allowed to be used"))
|
||||||
@ -275,7 +268,7 @@ func (s *simpleProvider) ValidateContainerSecurityContext(pod *api.Pod, containe
|
|||||||
|
|
||||||
sc := container.SecurityContext
|
sc := container.SecurityContext
|
||||||
allErrs = append(allErrs, s.strategies.RunAsUserStrategy.Validate(pod, container)...)
|
allErrs = append(allErrs, s.strategies.RunAsUserStrategy.Validate(pod, container)...)
|
||||||
allErrs = append(allErrs, s.strategies.SELinuxStrategy.Validate(pod, container)...)
|
allErrs = append(allErrs, s.strategies.SELinuxStrategy.Validate(fldPath.Child("seLinuxOptions"), pod, container, sc.SELinuxOptions)...)
|
||||||
allErrs = append(allErrs, s.strategies.AppArmorStrategy.Validate(pod, container)...)
|
allErrs = append(allErrs, s.strategies.AppArmorStrategy.Validate(pod, container)...)
|
||||||
allErrs = append(allErrs, s.strategies.SeccompStrategy.ValidateContainer(pod, container)...)
|
allErrs = append(allErrs, s.strategies.SeccompStrategy.ValidateContainer(pod, container)...)
|
||||||
|
|
||||||
|
@ -323,12 +323,12 @@ func TestValidatePodSecurityContextFailures(t *testing.T) {
|
|||||||
"failNilSELinux": {
|
"failNilSELinux": {
|
||||||
pod: failNilSELinuxPod,
|
pod: failNilSELinuxPod,
|
||||||
psp: failSELinuxPSP,
|
psp: failSELinuxPSP,
|
||||||
expectedError: "unable to validate nil seLinuxOptions",
|
expectedError: "seLinuxOptions: Required",
|
||||||
},
|
},
|
||||||
"failInvalidSELinux": {
|
"failInvalidSELinux": {
|
||||||
pod: failInvalidSELinuxPod,
|
pod: failInvalidSELinuxPod,
|
||||||
psp: failSELinuxPSP,
|
psp: failSELinuxPSP,
|
||||||
expectedError: "does not match required level. Found bar, wanted foo",
|
expectedError: "seLinuxOptions.level: Invalid value",
|
||||||
},
|
},
|
||||||
"failHostDirPSP": {
|
"failHostDirPSP": {
|
||||||
pod: failHostDirPod,
|
pod: failHostDirPod,
|
||||||
@ -460,7 +460,7 @@ func TestValidateContainerSecurityContextFailures(t *testing.T) {
|
|||||||
"failSELinuxPSP": {
|
"failSELinuxPSP": {
|
||||||
pod: failSELinuxPod,
|
pod: failSELinuxPod,
|
||||||
psp: failSELinuxPSP,
|
psp: failSELinuxPSP,
|
||||||
expectedError: "does not match required level",
|
expectedError: "seLinuxOptions.level: Invalid value",
|
||||||
},
|
},
|
||||||
"failNilAppArmor": {
|
"failNilAppArmor": {
|
||||||
pod: failNilAppArmorPod,
|
pod: failNilAppArmorPod,
|
||||||
|
@ -43,41 +43,33 @@ func NewMustRunAs(options *extensions.SELinuxStrategyOptions) (SELinuxStrategy,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Generate creates the SELinuxOptions based on constraint rules.
|
// Generate creates the SELinuxOptions based on constraint rules.
|
||||||
func (s *mustRunAs) Generate(pod *api.Pod, container *api.Container) (*api.SELinuxOptions, error) {
|
func (s *mustRunAs) Generate(_ *api.Pod, _ *api.Container) (*api.SELinuxOptions, error) {
|
||||||
return s.opts.SELinuxOptions, nil
|
return s.opts.SELinuxOptions, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate ensures that the specified values fall within the range of the strategy.
|
// Validate ensures that the specified values fall within the range of the strategy.
|
||||||
func (s *mustRunAs) Validate(pod *api.Pod, container *api.Container) field.ErrorList {
|
func (s *mustRunAs) Validate(fldPath *field.Path, _ *api.Pod, _ *api.Container, seLinux *api.SELinuxOptions) field.ErrorList {
|
||||||
allErrs := field.ErrorList{}
|
allErrs := field.ErrorList{}
|
||||||
|
|
||||||
if container.SecurityContext == nil {
|
if seLinux == nil {
|
||||||
detail := fmt.Sprintf("unable to validate nil security context for %s", container.Name)
|
allErrs = append(allErrs, field.Required(fldPath, ""))
|
||||||
allErrs = append(allErrs, field.Invalid(field.NewPath("securityContext"), container.SecurityContext, detail))
|
|
||||||
return allErrs
|
return allErrs
|
||||||
}
|
}
|
||||||
if container.SecurityContext.SELinuxOptions == nil {
|
|
||||||
detail := fmt.Sprintf("unable to validate nil seLinuxOptions for %s", container.Name)
|
|
||||||
allErrs = append(allErrs, field.Invalid(field.NewPath("seLinuxOptions"), container.SecurityContext.SELinuxOptions, detail))
|
|
||||||
return allErrs
|
|
||||||
}
|
|
||||||
seLinuxOptionsPath := field.NewPath("seLinuxOptions")
|
|
||||||
seLinux := container.SecurityContext.SELinuxOptions
|
|
||||||
if seLinux.Level != s.opts.SELinuxOptions.Level {
|
if seLinux.Level != s.opts.SELinuxOptions.Level {
|
||||||
detail := fmt.Sprintf("seLinuxOptions.level on %s does not match required level. Found %s, wanted %s", container.Name, seLinux.Level, s.opts.SELinuxOptions.Level)
|
detail := fmt.Sprintf("must be %s", s.opts.SELinuxOptions.Level)
|
||||||
allErrs = append(allErrs, field.Invalid(seLinuxOptionsPath.Child("level"), seLinux.Level, detail))
|
allErrs = append(allErrs, field.Invalid(fldPath.Child("level"), seLinux.Level, detail))
|
||||||
}
|
}
|
||||||
if seLinux.Role != s.opts.SELinuxOptions.Role {
|
if seLinux.Role != s.opts.SELinuxOptions.Role {
|
||||||
detail := fmt.Sprintf("seLinuxOptions.role on %s does not match required role. Found %s, wanted %s", container.Name, seLinux.Role, s.opts.SELinuxOptions.Role)
|
detail := fmt.Sprintf("must be %s", s.opts.SELinuxOptions.Role)
|
||||||
allErrs = append(allErrs, field.Invalid(seLinuxOptionsPath.Child("role"), seLinux.Role, detail))
|
allErrs = append(allErrs, field.Invalid(fldPath.Child("role"), seLinux.Role, detail))
|
||||||
}
|
}
|
||||||
if seLinux.Type != s.opts.SELinuxOptions.Type {
|
if seLinux.Type != s.opts.SELinuxOptions.Type {
|
||||||
detail := fmt.Sprintf("seLinuxOptions.type on %s does not match required type. Found %s, wanted %s", container.Name, seLinux.Type, s.opts.SELinuxOptions.Type)
|
detail := fmt.Sprintf("must be %s", s.opts.SELinuxOptions.Type)
|
||||||
allErrs = append(allErrs, field.Invalid(seLinuxOptionsPath.Child("type"), seLinux.Type, detail))
|
allErrs = append(allErrs, field.Invalid(fldPath.Child("type"), seLinux.Type, detail))
|
||||||
}
|
}
|
||||||
if seLinux.User != s.opts.SELinuxOptions.User {
|
if seLinux.User != s.opts.SELinuxOptions.User {
|
||||||
detail := fmt.Sprintf("seLinuxOptions.user on %s does not match required user. Found %s, wanted %s", container.Name, seLinux.User, s.opts.SELinuxOptions.User)
|
detail := fmt.Sprintf("must be %s", s.opts.SELinuxOptions.User)
|
||||||
allErrs = append(allErrs, field.Invalid(seLinuxOptionsPath.Child("user"), seLinux.User, detail))
|
allErrs = append(allErrs, field.Invalid(fldPath.Child("user"), seLinux.User, detail))
|
||||||
}
|
}
|
||||||
|
|
||||||
return allErrs
|
return allErrs
|
||||||
|
@ -100,19 +100,19 @@ func TestMustRunAsValidate(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
"invalid role": {
|
"invalid role": {
|
||||||
seLinux: role,
|
seLinux: role,
|
||||||
expectedMsg: "does not match required role",
|
expectedMsg: "role: Invalid value",
|
||||||
},
|
},
|
||||||
"invalid user": {
|
"invalid user": {
|
||||||
seLinux: user,
|
seLinux: user,
|
||||||
expectedMsg: "does not match required user",
|
expectedMsg: "user: Invalid value",
|
||||||
},
|
},
|
||||||
"invalid level": {
|
"invalid level": {
|
||||||
seLinux: level,
|
seLinux: level,
|
||||||
expectedMsg: "does not match required level",
|
expectedMsg: "level: Invalid value",
|
||||||
},
|
},
|
||||||
"invalid type": {
|
"invalid type": {
|
||||||
seLinux: seType,
|
seLinux: seType,
|
||||||
expectedMsg: "does not match required type",
|
expectedMsg: "type: Invalid value",
|
||||||
},
|
},
|
||||||
"valid": {
|
"valid": {
|
||||||
seLinux: newValidOpts(),
|
seLinux: newValidOpts(),
|
||||||
@ -130,13 +130,8 @@ func TestMustRunAsValidate(t *testing.T) {
|
|||||||
t.Errorf("unexpected error initializing NewMustRunAs for testcase %s: %#v", name, err)
|
t.Errorf("unexpected error initializing NewMustRunAs for testcase %s: %#v", name, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
container := &api.Container{
|
|
||||||
SecurityContext: &api.SecurityContext{
|
|
||||||
SELinuxOptions: tc.seLinux,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
errs := mustRunAs.Validate(nil, container)
|
errs := mustRunAs.Validate(nil, nil, nil, tc.seLinux)
|
||||||
//should've passed but didn't
|
//should've passed but didn't
|
||||||
if len(tc.expectedMsg) == 0 && len(errs) > 0 {
|
if len(tc.expectedMsg) == 0 && len(errs) > 0 {
|
||||||
t.Errorf("%s expected no errors but received %v", name, errs)
|
t.Errorf("%s expected no errors but received %v", name, errs)
|
||||||
|
@ -38,6 +38,6 @@ func (s *runAsAny) Generate(pod *api.Pod, container *api.Container) (*api.SELinu
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Validate ensures that the specified values fall within the range of the strategy.
|
// Validate ensures that the specified values fall within the range of the strategy.
|
||||||
func (s *runAsAny) Validate(pod *api.Pod, container *api.Container) field.ErrorList {
|
func (s *runAsAny) Validate(fldPath *field.Path, _ *api.Pod, _ *api.Container, options *api.SELinuxOptions) field.ErrorList {
|
||||||
return field.ErrorList{}
|
return field.ErrorList{}
|
||||||
}
|
}
|
||||||
|
@ -58,7 +58,7 @@ func TestRunAsAnyValidate(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error initializing NewRunAsAny %v", err)
|
t.Fatalf("unexpected error initializing NewRunAsAny %v", err)
|
||||||
}
|
}
|
||||||
errs := s.Validate(nil, nil)
|
errs := s.Validate(nil, nil, nil, nil)
|
||||||
if len(errs) != 0 {
|
if len(errs) != 0 {
|
||||||
t.Errorf("unexpected errors validating with ")
|
t.Errorf("unexpected errors validating with ")
|
||||||
}
|
}
|
||||||
@ -66,7 +66,7 @@ func TestRunAsAnyValidate(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unexpected error initializing NewRunAsAny %v", err)
|
t.Fatalf("unexpected error initializing NewRunAsAny %v", err)
|
||||||
}
|
}
|
||||||
errs = s.Validate(nil, nil)
|
errs = s.Validate(nil, nil, nil, nil)
|
||||||
if len(errs) != 0 {
|
if len(errs) != 0 {
|
||||||
t.Errorf("unexpected errors validating %v", errs)
|
t.Errorf("unexpected errors validating %v", errs)
|
||||||
}
|
}
|
||||||
|
@ -26,5 +26,5 @@ type SELinuxStrategy interface {
|
|||||||
// Generate creates the SELinuxOptions based on constraint rules.
|
// Generate creates the SELinuxOptions based on constraint rules.
|
||||||
Generate(pod *api.Pod, container *api.Container) (*api.SELinuxOptions, error)
|
Generate(pod *api.Pod, container *api.Container) (*api.SELinuxOptions, error)
|
||||||
// Validate ensures that the specified values fall within the range of the strategy.
|
// Validate ensures that the specified values fall within the range of the strategy.
|
||||||
Validate(pod *api.Pod, container *api.Container) field.ErrorList
|
Validate(fldPath *field.Path, pod *api.Pod, container *api.Container, options *api.SELinuxOptions) field.ErrorList
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user