Skip to content

Commit b5a8497

Browse files
committed
SecurityContextConstraints: pass effective selinux options to validate.
1 parent abd601c commit b5a8497

File tree

7 files changed

+26
-46
lines changed

7 files changed

+26
-46
lines changed

pkg/security/securitycontextconstraints/provider.go

+2-9
Original file line numberDiff line numberDiff line change
@@ -241,14 +241,7 @@ func (s *simpleProvider) ValidatePodSecurityContext(pod *api.Pod, fldPath *field
241241
allErrs = append(allErrs, s.supplementalGroupStrategy.Validate(pod, pod.Spec.SecurityContext.SupplementalGroups)...)
242242
allErrs = append(allErrs, s.seccompStrategy.ValidatePod(pod)...)
243243

244-
// make a dummy container context to reuse the selinux strategies
245-
container := &api.Container{
246-
Name: pod.Name,
247-
SecurityContext: &api.SecurityContext{
248-
SELinuxOptions: pod.Spec.SecurityContext.SELinuxOptions,
249-
},
250-
}
251-
allErrs = append(allErrs, s.seLinuxStrategy.Validate(pod, container)...)
244+
allErrs = append(allErrs, s.seLinuxStrategy.Validate(fldPath.Child("seLinuxOptions"), pod, nil, pod.Spec.SecurityContext.SELinuxOptions)...)
252245

253246
if !s.scc.AllowHostNetwork && pod.Spec.SecurityContext.HostNetwork {
254247
allErrs = append(allErrs, field.Invalid(fldPath.Child("hostNetwork"), pod.Spec.SecurityContext.HostNetwork, "Host network is not allowed to be used"))
@@ -317,7 +310,7 @@ func (s *simpleProvider) ValidateContainerSecurityContext(pod *api.Pod, containe
317310

318311
sc := container.SecurityContext
319312
allErrs = append(allErrs, s.runAsUserStrategy.Validate(pod, container)...)
320-
allErrs = append(allErrs, s.seLinuxStrategy.Validate(pod, container)...)
313+
allErrs = append(allErrs, s.seLinuxStrategy.Validate(fldPath.Child("seLinuxOptions"), pod, container, sc.SELinuxOptions)...)
321314
allErrs = append(allErrs, s.seccompStrategy.ValidateContainer(pod, container)...)
322315

323316
if !s.scc.AllowPrivilegedContainer && sc.Privileged != nil && *sc.Privileged {

pkg/security/securitycontextconstraints/provider_test.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -285,12 +285,12 @@ func TestValidatePodSecurityContextFailures(t *testing.T) {
285285
"failNilSELinux": {
286286
pod: failNilSELinuxPod,
287287
scc: failSELinuxSCC,
288-
expectedError: "unable to validate nil seLinuxOptions",
288+
expectedError: "seLinuxOptions: Required",
289289
},
290290
"failInvalidSELinux": {
291291
pod: failInvalidSELinuxPod,
292292
scc: failSELinuxSCC,
293-
expectedError: "does not match required level. Found bar, wanted foo",
293+
expectedError: "seLinuxOptions.level: Invalid value",
294294
},
295295
"failNoSeccomp": {
296296
pod: failNoSeccompAllowed,
@@ -421,7 +421,7 @@ func TestValidateContainerSecurityContextFailures(t *testing.T) {
421421
"failSELinuxSCC": {
422422
pod: failSELinuxPod,
423423
scc: failSELinuxSCC,
424-
expectedError: "does not match required level",
424+
expectedError: "seLinuxOptions.level: Invalid value",
425425
},
426426
"failPrivSCC": {
427427
pod: failPrivPod,

pkg/security/securitycontextconstraints/selinux/mustrunas.go

+12-20
Original file line numberDiff line numberDiff line change
@@ -28,41 +28,33 @@ func NewMustRunAs(options *securityapi.SELinuxContextStrategyOptions) (SELinuxSe
2828
}
2929

3030
// Generate creates the SELinuxOptions based on constraint rules.
31-
func (s *mustRunAs) Generate(pod *api.Pod, container *api.Container) (*api.SELinuxOptions, error) {
31+
func (s *mustRunAs) Generate(_ *api.Pod, _ *api.Container) (*api.SELinuxOptions, error) {
3232
return s.opts.SELinuxOptions, nil
3333
}
3434

3535
// Validate ensures that the specified values fall within the range of the strategy.
36-
func (s *mustRunAs) Validate(pod *api.Pod, container *api.Container) field.ErrorList {
36+
func (s *mustRunAs) Validate(fldPath *field.Path, _ *api.Pod, _ *api.Container, seLinux *api.SELinuxOptions) field.ErrorList {
3737
allErrs := field.ErrorList{}
3838

39-
if container.SecurityContext == nil {
40-
detail := fmt.Sprintf("unable to validate nil security context for %s", container.Name)
41-
allErrs = append(allErrs, field.Invalid(field.NewPath("securityContext"), container.SecurityContext, detail))
39+
if seLinux == nil {
40+
allErrs = append(allErrs, field.Required(fldPath, ""))
4241
return allErrs
4342
}
44-
if container.SecurityContext.SELinuxOptions == nil {
45-
detail := fmt.Sprintf("unable to validate nil seLinuxOptions for %s", container.Name)
46-
allErrs = append(allErrs, field.Invalid(field.NewPath("seLinuxOptions"), container.SecurityContext.SELinuxOptions, detail))
47-
return allErrs
48-
}
49-
seLinuxOptionsPath := field.NewPath("seLinuxOptions")
50-
seLinux := container.SecurityContext.SELinuxOptions
5143
if seLinux.Level != s.opts.SELinuxOptions.Level {
52-
detail := fmt.Sprintf("seLinuxOptions.level on %s does not match required level. Found %s, wanted %s", container.Name, seLinux.Level, s.opts.SELinuxOptions.Level)
53-
allErrs = append(allErrs, field.Invalid(seLinuxOptionsPath.Child("level"), seLinux.Level, detail))
44+
detail := fmt.Sprintf("must be %s", s.opts.SELinuxOptions.Level)
45+
allErrs = append(allErrs, field.Invalid(fldPath.Child("level"), seLinux.Level, detail))
5446
}
5547
if seLinux.Role != s.opts.SELinuxOptions.Role {
56-
detail := fmt.Sprintf("seLinuxOptions.role on %s does not match required role. Found %s, wanted %s", container.Name, seLinux.Role, s.opts.SELinuxOptions.Role)
57-
allErrs = append(allErrs, field.Invalid(seLinuxOptionsPath.Child("role"), seLinux.Role, detail))
48+
detail := fmt.Sprintf("must be %s", s.opts.SELinuxOptions.Role)
49+
allErrs = append(allErrs, field.Invalid(fldPath.Child("role"), seLinux.Role, detail))
5850
}
5951
if seLinux.Type != s.opts.SELinuxOptions.Type {
60-
detail := fmt.Sprintf("seLinuxOptions.type on %s does not match required type. Found %s, wanted %s", container.Name, seLinux.Type, s.opts.SELinuxOptions.Type)
61-
allErrs = append(allErrs, field.Invalid(seLinuxOptionsPath.Child("type"), seLinux.Type, detail))
52+
detail := fmt.Sprintf("must be %s", s.opts.SELinuxOptions.Type)
53+
allErrs = append(allErrs, field.Invalid(fldPath.Child("type"), seLinux.Type, detail))
6254
}
6355
if seLinux.User != s.opts.SELinuxOptions.User {
64-
detail := fmt.Sprintf("seLinuxOptions.user on %s does not match required user. Found %s, wanted %s", container.Name, seLinux.User, s.opts.SELinuxOptions.User)
65-
allErrs = append(allErrs, field.Invalid(seLinuxOptionsPath.Child("user"), seLinux.User, detail))
56+
detail := fmt.Sprintf("must be %s", s.opts.SELinuxOptions.User)
57+
allErrs = append(allErrs, field.Invalid(fldPath.Child("user"), seLinux.User, detail))
6658
}
6759

6860
return allErrs

pkg/security/securitycontextconstraints/selinux/mustrunas_test.go

+5-10
Original file line numberDiff line numberDiff line change
@@ -85,19 +85,19 @@ func TestMustRunAsValidate(t *testing.T) {
8585
}{
8686
"invalid role": {
8787
seLinux: role,
88-
expectedMsg: "does not match required role",
88+
expectedMsg: "role: Invalid value",
8989
},
9090
"invalid user": {
9191
seLinux: user,
92-
expectedMsg: "does not match required user",
92+
expectedMsg: "user: Invalid value",
9393
},
9494
"invalid level": {
9595
seLinux: level,
96-
expectedMsg: "does not match required level",
96+
expectedMsg: "level: Invalid value",
9797
},
9898
"invalid type": {
9999
seLinux: seType,
100-
expectedMsg: "does not match required type",
100+
expectedMsg: "type: Invalid value",
101101
},
102102
"valid": {
103103
seLinux: newValidOpts(),
@@ -115,13 +115,8 @@ func TestMustRunAsValidate(t *testing.T) {
115115
t.Errorf("unexpected error initializing NewMustRunAs for testcase %s: %#v", name, err)
116116
continue
117117
}
118-
container := &api.Container{
119-
SecurityContext: &api.SecurityContext{
120-
SELinuxOptions: tc.seLinux,
121-
},
122-
}
123118

124-
errs := mustRunAs.Validate(nil, container)
119+
errs := mustRunAs.Validate(nil, nil, nil, tc.seLinux)
125120
//should've passed but didn't
126121
if len(tc.expectedMsg) == 0 && len(errs) > 0 {
127122
t.Errorf("%s expected no errors but received %v", name, errs)

pkg/security/securitycontextconstraints/selinux/runasany.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,6 @@ func (s *runAsAny) Generate(pod *api.Pod, container *api.Container) (*api.SELinu
2323
}
2424

2525
// Validate ensures that the specified values fall within the range of the strategy.
26-
func (s *runAsAny) Validate(pod *api.Pod, container *api.Container) field.ErrorList {
26+
func (s *runAsAny) Validate(fldPath *field.Path, _ *api.Pod, _ *api.Container, options *api.SELinuxOptions) field.ErrorList {
2727
return field.ErrorList{}
2828
}

pkg/security/securitycontextconstraints/selinux/runasany_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,15 @@ func TestRunAsAnyValidate(t *testing.T) {
4343
if err != nil {
4444
t.Fatalf("unexpected error initializing NewRunAsAny %v", err)
4545
}
46-
errs := s.Validate(nil, nil)
46+
errs := s.Validate(nil, nil, nil, nil)
4747
if len(errs) != 0 {
4848
t.Errorf("unexpected errors validating with ")
4949
}
5050
s, err = NewRunAsAny(&securityapi.SELinuxContextStrategyOptions{})
5151
if err != nil {
5252
t.Fatalf("unexpected error initializing NewRunAsAny %v", err)
5353
}
54-
errs = s.Validate(nil, nil)
54+
errs = s.Validate(nil, nil, nil, nil)
5555
if len(errs) != 0 {
5656
t.Errorf("unexpected errors validating %v", errs)
5757
}

pkg/security/securitycontextconstraints/selinux/types.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -10,5 +10,5 @@ type SELinuxSecurityContextConstraintsStrategy interface {
1010
// Generate creates the SELinuxOptions based on constraint rules.
1111
Generate(pod *api.Pod, container *api.Container) (*api.SELinuxOptions, error)
1212
// Validate ensures that the specified values fall within the range of the strategy.
13-
Validate(pod *api.Pod, container *api.Container) field.ErrorList
13+
Validate(fldPath *field.Path, pod *api.Pod, container *api.Container, options *api.SELinuxOptions) field.ErrorList
1414
}

0 commit comments

Comments
 (0)