mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 19:56:01 +00:00
PodSecurityPolicy: pass effective runAsNonRoot and runAsUser to user validation interface
This commit is contained in:
parent
e34a00d14f
commit
fef3b03188
@ -267,7 +267,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(fldPath.Child("securityContext"), pod, container, sc.RunAsNonRoot, sc.RunAsUser)...)
|
||||||
allErrs = append(allErrs, s.strategies.SELinuxStrategy.Validate(fldPath.Child("seLinuxOptions"), pod, container, sc.SELinuxOptions)...)
|
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)...)
|
||||||
|
@ -455,7 +455,7 @@ func TestValidateContainerSecurityContextFailures(t *testing.T) {
|
|||||||
"failUserPSP": {
|
"failUserPSP": {
|
||||||
pod: failUserPod,
|
pod: failUserPod,
|
||||||
psp: failUserPSP,
|
psp: failUserPSP,
|
||||||
expectedError: "does not match required range",
|
expectedError: "runAsUser: Invalid value",
|
||||||
},
|
},
|
||||||
"failSELinuxPSP": {
|
"failSELinuxPSP": {
|
||||||
pod: failSELinuxPod,
|
pod: failSELinuxPod,
|
||||||
|
@ -49,27 +49,17 @@ func (s *mustRunAs) Generate(pod *api.Pod, container *api.Container) (*int64, er
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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, runAsNonRoot *bool, runAsUser *int64) field.ErrorList {
|
||||||
allErrs := field.ErrorList{}
|
allErrs := field.ErrorList{}
|
||||||
|
|
||||||
securityContextPath := field.NewPath("securityContext")
|
if runAsUser == nil {
|
||||||
if container.SecurityContext == nil {
|
allErrs = append(allErrs, field.Required(fldPath.Child("runAsUser"), ""))
|
||||||
detail := fmt.Sprintf("unable to validate nil security context for container %s", container.Name)
|
|
||||||
allErrs = append(allErrs, field.Invalid(securityContextPath, container.SecurityContext, detail))
|
|
||||||
return allErrs
|
|
||||||
}
|
|
||||||
if container.SecurityContext.RunAsUser == nil {
|
|
||||||
detail := fmt.Sprintf("unable to validate nil RunAsUser for container %s", container.Name)
|
|
||||||
allErrs = append(allErrs, field.Invalid(securityContextPath.Child("runAsUser"), container.SecurityContext.RunAsUser, detail))
|
|
||||||
return allErrs
|
return allErrs
|
||||||
}
|
}
|
||||||
|
|
||||||
if !s.isValidUID(*container.SecurityContext.RunAsUser) {
|
if !s.isValidUID(*runAsUser) {
|
||||||
detail := fmt.Sprintf("UID on container %s does not match required range. Found %d, allowed: %v",
|
detail := fmt.Sprintf("must be in the ranges: %v", s.opts.Ranges)
|
||||||
container.Name,
|
allErrs = append(allErrs, field.Invalid(fldPath.Child("runAsUser"), *runAsUser, detail))
|
||||||
*container.SecurityContext.RunAsUser,
|
|
||||||
s.opts.Ranges)
|
|
||||||
allErrs = append(allErrs, field.Invalid(securityContextPath.Child("runAsUser"), *container.SecurityContext.RunAsUser, detail))
|
|
||||||
}
|
}
|
||||||
return allErrs
|
return allErrs
|
||||||
}
|
}
|
||||||
|
@ -98,19 +98,13 @@ func TestValidate(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"nil security context": {
|
|
||||||
container: &api.Container{
|
|
||||||
SecurityContext: nil,
|
|
||||||
},
|
|
||||||
expectedMsg: "unable to validate nil security context for container",
|
|
||||||
},
|
|
||||||
"nil run as user": {
|
"nil run as user": {
|
||||||
container: &api.Container{
|
container: &api.Container{
|
||||||
SecurityContext: &api.SecurityContext{
|
SecurityContext: &api.SecurityContext{
|
||||||
RunAsUser: nil,
|
RunAsUser: nil,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedMsg: "unable to validate nil RunAsUser for container",
|
expectedMsg: "runAsUser: Required",
|
||||||
},
|
},
|
||||||
"invalid id": {
|
"invalid id": {
|
||||||
container: &api.Container{
|
container: &api.Container{
|
||||||
@ -118,7 +112,7 @@ func TestValidate(t *testing.T) {
|
|||||||
RunAsUser: &invalidID,
|
RunAsUser: &invalidID,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedMsg: "does not match required range",
|
expectedMsg: "runAsUser: Invalid",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,7 +122,7 @@ func TestValidate(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
|
||||||
}
|
}
|
||||||
errs := mustRunAs.Validate(nil, tc.container)
|
errs := mustRunAs.Validate(nil, nil, nil, tc.container.SecurityContext.RunAsNonRoot, tc.container.SecurityContext.RunAsUser)
|
||||||
//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)
|
||||||
|
@ -17,8 +17,6 @@ limitations under the License.
|
|||||||
package user
|
package user
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||||
@ -43,22 +41,18 @@ func (s *nonRoot) Generate(pod *api.Pod, container *api.Container) (*int64, erro
|
|||||||
// or if the UID is set it is not root. Validation will fail if RunAsNonRoot is set to false.
|
// or if the UID is set it is not root. Validation will fail if RunAsNonRoot is set to false.
|
||||||
// In order to work properly this assumes that the kubelet performs a final check on runAsUser
|
// In order to work properly this assumes that the kubelet performs a final check on runAsUser
|
||||||
// or the image UID when runAsUser is nil.
|
// or the image UID when runAsUser is nil.
|
||||||
func (s *nonRoot) Validate(pod *api.Pod, container *api.Container) field.ErrorList {
|
func (s *nonRoot) Validate(fldPath *field.Path, _ *api.Pod, _ *api.Container, runAsNonRoot *bool, runAsUser *int64) field.ErrorList {
|
||||||
allErrs := field.ErrorList{}
|
allErrs := field.ErrorList{}
|
||||||
securityContextPath := field.NewPath("securityContext")
|
if runAsNonRoot == nil && runAsUser == nil {
|
||||||
if container.SecurityContext == nil {
|
allErrs = append(allErrs, field.Required(fldPath.Child("runAsNonRoot"), "must be true"))
|
||||||
detail := fmt.Sprintf("unable to validate nil security context for container %s", container.Name)
|
|
||||||
allErrs = append(allErrs, field.Invalid(securityContextPath, container.SecurityContext, detail))
|
|
||||||
return allErrs
|
return allErrs
|
||||||
}
|
}
|
||||||
if container.SecurityContext.RunAsNonRoot != nil && *container.SecurityContext.RunAsNonRoot == false {
|
if runAsNonRoot != nil && *runAsNonRoot == false {
|
||||||
detail := fmt.Sprintf("RunAsNonRoot must be true for container %s", container.Name)
|
allErrs = append(allErrs, field.Invalid(fldPath.Child("runAsNonRoot"), *runAsNonRoot, "must be true"))
|
||||||
allErrs = append(allErrs, field.Invalid(securityContextPath.Child("runAsNonRoot"), *container.SecurityContext.RunAsNonRoot, detail))
|
|
||||||
return allErrs
|
return allErrs
|
||||||
}
|
}
|
||||||
if container.SecurityContext.RunAsUser != nil && *container.SecurityContext.RunAsUser == 0 {
|
if runAsUser != nil && *runAsUser == 0 {
|
||||||
detail := fmt.Sprintf("running with the root UID is forbidden by the pod security policy for container %s", container.Name)
|
allErrs = append(allErrs, field.Invalid(fldPath.Child("runAsUser"), *runAsUser, "running with the root UID is forbidden"))
|
||||||
allErrs = append(allErrs, field.Invalid(securityContextPath.Child("runAsUser"), *container.SecurityContext.RunAsUser, detail))
|
|
||||||
return allErrs
|
return allErrs
|
||||||
}
|
}
|
||||||
return allErrs
|
return allErrs
|
||||||
|
@ -102,17 +102,17 @@ func TestNonRootValidate(t *testing.T) {
|
|||||||
{
|
{
|
||||||
container: &api.Container{
|
container: &api.Container{
|
||||||
SecurityContext: &api.SecurityContext{
|
SecurityContext: &api.SecurityContext{
|
||||||
RunAsNonRoot: &unfalse,
|
RunAsNonRoot: nil,
|
||||||
RunAsUser: &badUID,
|
RunAsUser: nil,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
expectedErr: true,
|
expectedErr: true,
|
||||||
msg: "in test case %d, expected errors from root uid but got %v",
|
msg: "in test case %d, expected errors from nil runAsNonRoot and nil runAsUser but got %v",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, tc := range tests {
|
for i, tc := range tests {
|
||||||
errs := s.Validate(nil, tc.container)
|
errs := s.Validate(nil, nil, nil, tc.container.SecurityContext.RunAsNonRoot, tc.container.SecurityContext.RunAsUser)
|
||||||
if (len(errs) == 0) == tc.expectedErr {
|
if (len(errs) == 0) == tc.expectedErr {
|
||||||
t.Errorf(tc.msg, i, errs)
|
t.Errorf(tc.msg, i, errs)
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,6 @@ func (s *runAsAny) Generate(pod *api.Pod, container *api.Container) (*int64, err
|
|||||||
}
|
}
|
||||||
|
|
||||||
// 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, runAsNonRoot *bool, runAsUser *int64) field.ErrorList {
|
||||||
return field.ErrorList{}
|
return field.ErrorList{}
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,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, nil)
|
||||||
if len(errs) != 0 {
|
if len(errs) != 0 {
|
||||||
t.Errorf("unexpected errors validating with ")
|
t.Errorf("unexpected errors validating with ")
|
||||||
}
|
}
|
||||||
|
@ -26,5 +26,5 @@ type RunAsUserStrategy interface {
|
|||||||
// Generate creates the uid based on policy rules.
|
// Generate creates the uid based on policy rules.
|
||||||
Generate(pod *api.Pod, container *api.Container) (*int64, error)
|
Generate(pod *api.Pod, container *api.Container) (*int64, 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, runAsNonRoot *bool, runAsUser *int64) field.ErrorList
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user