security context initial implementation - squash
This commit is contained in:
@@ -776,15 +776,12 @@ func validateContainers(containers []api.Container, volumes util.StringSet) errs
|
||||
allNames := util.StringSet{}
|
||||
for i, ctr := range containers {
|
||||
cErrs := errs.ValidationErrorList{}
|
||||
capabilities := capabilities.Get()
|
||||
if len(ctr.Name) == 0 {
|
||||
cErrs = append(cErrs, errs.NewFieldRequired("name"))
|
||||
} else if !util.IsDNS1123Label(ctr.Name) {
|
||||
cErrs = append(cErrs, errs.NewFieldInvalid("name", ctr.Name, dns1123LabelErrorMsg))
|
||||
} else if allNames.Has(ctr.Name) {
|
||||
cErrs = append(cErrs, errs.NewFieldDuplicate("name", ctr.Name))
|
||||
} else if ctr.Privileged && !capabilities.AllowPrivileged {
|
||||
cErrs = append(cErrs, errs.NewFieldForbidden("privileged", ctr.Privileged))
|
||||
} else {
|
||||
allNames.Insert(ctr.Name)
|
||||
}
|
||||
@@ -801,6 +798,7 @@ func validateContainers(containers []api.Container, volumes util.StringSet) errs
|
||||
cErrs = append(cErrs, validateVolumeMounts(ctr.VolumeMounts, volumes).Prefix("volumeMounts")...)
|
||||
cErrs = append(cErrs, validatePullPolicy(&ctr).Prefix("pullPolicy")...)
|
||||
cErrs = append(cErrs, ValidateResourceRequirements(&ctr.Resources).Prefix("resources")...)
|
||||
cErrs = append(cErrs, ValidateSecurityContext(ctr.SecurityContext).Prefix("securityContext")...)
|
||||
allErrs = append(allErrs, cErrs.PrefixIndex(i)...)
|
||||
}
|
||||
// Check for colliding ports across all containers.
|
||||
@@ -1481,3 +1479,25 @@ func ValidateEndpointsUpdate(oldEndpoints, newEndpoints *api.Endpoints) errs.Val
|
||||
allErrs = append(allErrs, validateEndpointSubsets(newEndpoints.Subsets).Prefix("subsets")...)
|
||||
return allErrs
|
||||
}
|
||||
|
||||
// ValidateSecurityContext ensure the security context contains valid settings
|
||||
func ValidateSecurityContext(sc *api.SecurityContext) errs.ValidationErrorList {
|
||||
allErrs := errs.ValidationErrorList{}
|
||||
//this should only be true for testing since SecurityContext is defaulted by the api
|
||||
if sc == nil {
|
||||
return allErrs
|
||||
}
|
||||
|
||||
if sc.Privileged != nil {
|
||||
if *sc.Privileged && !capabilities.Get().AllowPrivileged {
|
||||
allErrs = append(allErrs, errs.NewFieldForbidden("privileged", sc.Privileged))
|
||||
}
|
||||
}
|
||||
|
||||
if sc.RunAsUser != nil {
|
||||
if *sc.RunAsUser < 0 {
|
||||
allErrs = append(allErrs, errs.NewFieldInvalid("runAsUser", *sc.RunAsUser, "runAsUser cannot be negative"))
|
||||
}
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
@@ -901,7 +901,7 @@ func TestValidateContainers(t *testing.T) {
|
||||
},
|
||||
ImagePullPolicy: "IfNotPresent",
|
||||
},
|
||||
{Name: "abc-1234", Image: "image", Privileged: true, ImagePullPolicy: "IfNotPresent"},
|
||||
{Name: "abc-1234", Image: "image", ImagePullPolicy: "IfNotPresent", SecurityContext: fakeValidSecurityContext(true)},
|
||||
}
|
||||
if errs := validateContainers(successCase, volumes); len(errs) != 0 {
|
||||
t.Errorf("expected success: %v", errs)
|
||||
@@ -1015,7 +1015,7 @@ func TestValidateContainers(t *testing.T) {
|
||||
},
|
||||
},
|
||||
"privilege disabled": {
|
||||
{Name: "abc", Image: "image", Privileged: true},
|
||||
{Name: "abc", Image: "image", SecurityContext: fakeValidSecurityContext(true)},
|
||||
},
|
||||
"invalid compute resource": {
|
||||
{
|
||||
@@ -3180,3 +3180,89 @@ func TestValidateEndpoints(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateSecurityContext(t *testing.T) {
|
||||
priv := false
|
||||
var runAsUser int64 = 1
|
||||
fullValidSC := func() *api.SecurityContext {
|
||||
return &api.SecurityContext{
|
||||
Privileged: &priv,
|
||||
Capabilities: &api.Capabilities{
|
||||
Add: []api.CapabilityType{"foo"},
|
||||
Drop: []api.CapabilityType{"bar"},
|
||||
},
|
||||
SELinuxOptions: &api.SELinuxOptions{
|
||||
User: "user",
|
||||
Role: "role",
|
||||
Type: "type",
|
||||
Level: "level",
|
||||
},
|
||||
RunAsUser: &runAsUser,
|
||||
}
|
||||
}
|
||||
|
||||
//setup data
|
||||
allSettings := fullValidSC()
|
||||
noCaps := fullValidSC()
|
||||
noCaps.Capabilities = nil
|
||||
|
||||
noSELinux := fullValidSC()
|
||||
noSELinux.SELinuxOptions = nil
|
||||
|
||||
noPrivRequest := fullValidSC()
|
||||
noPrivRequest.Privileged = nil
|
||||
|
||||
noRunAsUser := fullValidSC()
|
||||
noRunAsUser.RunAsUser = nil
|
||||
|
||||
successCases := map[string]struct {
|
||||
sc *api.SecurityContext
|
||||
}{
|
||||
"all settings": {allSettings},
|
||||
"no capabilities": {noCaps},
|
||||
"no selinux": {noSELinux},
|
||||
"no priv request": {noPrivRequest},
|
||||
"no run as user": {noRunAsUser},
|
||||
}
|
||||
for k, v := range successCases {
|
||||
if errs := ValidateSecurityContext(v.sc); len(errs) != 0 {
|
||||
t.Errorf("Expected success for %s, got %v", k, errs)
|
||||
}
|
||||
}
|
||||
|
||||
privRequestWithGlobalDeny := fullValidSC()
|
||||
requestPrivileged := true
|
||||
privRequestWithGlobalDeny.Privileged = &requestPrivileged
|
||||
|
||||
negativeRunAsUser := fullValidSC()
|
||||
var negativeUser int64 = -1
|
||||
negativeRunAsUser.RunAsUser = &negativeUser
|
||||
|
||||
errorCases := map[string]struct {
|
||||
sc *api.SecurityContext
|
||||
errorType fielderrors.ValidationErrorType
|
||||
errorDetail string
|
||||
}{
|
||||
"request privileged when capabilities forbids": {
|
||||
sc: privRequestWithGlobalDeny,
|
||||
errorType: "FieldValueForbidden",
|
||||
errorDetail: "",
|
||||
},
|
||||
"negative RunAsUser": {
|
||||
sc: negativeRunAsUser,
|
||||
errorType: "FieldValueInvalid",
|
||||
errorDetail: "runAsUser cannot be negative",
|
||||
},
|
||||
}
|
||||
for k, v := range errorCases {
|
||||
if errs := ValidateSecurityContext(v.sc); len(errs) == 0 || errs[0].(*errors.ValidationError).Type != v.errorType || errs[0].(*errors.ValidationError).Detail != v.errorDetail {
|
||||
t.Errorf("Expected error type %s with detail %s for %s, got %v", v.errorType, v.errorDetail, k, errs)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func fakeValidSecurityContext(priv bool) *api.SecurityContext {
|
||||
return &api.SecurityContext{
|
||||
Privileged: &priv,
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user