// assignSecurityContext creates a security context for each container in the pod // and validates that the sc falls within the scc constraints. All containers must validate against // the same scc or is not considered valid. func assignSecurityContext(provider scc.SecurityContextConstraintsProvider, pod *kapi.Pod) fielderrors.ValidationErrorList { generatedSCs := make([]*kapi.SecurityContext, len(pod.Spec.Containers)) errs := fielderrors.ValidationErrorList{} for i, c := range pod.Spec.Containers { sc, err := provider.CreateSecurityContext(pod, &c) if err != nil { errs = append(errs, fielderrors.NewFieldInvalid(fmt.Sprintf("spec.containers[%d].securityContext", i), "", err.Error())) continue } generatedSCs[i] = sc c.SecurityContext = sc errs = append(errs, provider.ValidateSecurityContext(pod, &c).Prefix(fmt.Sprintf("spec.containers[%d].securityContext", i))...) } if len(errs) > 0 { return errs } // if we've reached this code then we've generated and validated an SC for every container in the // pod so let's apply what we generated for i, sc := range generatedSCs { pod.Spec.Containers[i].SecurityContext = sc } return nil }
// assignSecurityContext creates a security context for each container in the pod // and validates that the sc falls within the scc constraints. All containers must validate against // the same scc or is not considered valid. func assignSecurityContext(provider scc.SecurityContextConstraintsProvider, pod *kapi.Pod, fldPath *field.Path) field.ErrorList { generatedSCs := make([]*kapi.SecurityContext, len(pod.Spec.InitContainers)+len(pod.Spec.Containers)) errs := field.ErrorList{} psc, err := provider.CreatePodSecurityContext(pod) if err != nil { errs = append(errs, field.Invalid(field.NewPath("spec", "securityContext"), pod.Spec.SecurityContext, err.Error())) } // save the original PSC and validate the generated PSC. Leave the generated PSC // set for container generation/validation. We will reset to original post container // validation. originalPSC := pod.Spec.SecurityContext pod.Spec.SecurityContext = psc errs = append(errs, provider.ValidatePodSecurityContext(pod, field.NewPath("spec", "securityContext"))...) // Note: this is not changing the original container, we will set container SCs later so long // as all containers validated under the same SCC. containerPath := field.NewPath("spec", "initContainers") for i, containerCopy := range pod.Spec.InitContainers { csc, resolutionErrs := resolveContainerSecurityContext(provider, pod, &containerCopy, containerPath.Index(i)) errs = append(errs, resolutionErrs...) if len(resolutionErrs) > 0 { continue } generatedSCs[i] = csc } base := len(pod.Spec.InitContainers) // Note: this is not changing the original container, we will set container SCs later so long // as all containers validated under the same SCC. containerPath = field.NewPath("spec", "containers") for i, containerCopy := range pod.Spec.Containers { csc, resolutionErrs := resolveContainerSecurityContext(provider, pod, &containerCopy, containerPath.Index(i)) errs = append(errs, resolutionErrs...) if len(resolutionErrs) > 0 { continue } generatedSCs[i+base] = csc } if len(errs) > 0 { // ensure psc is not mutated if there are errors pod.Spec.SecurityContext = originalPSC return errs } // if we've reached this code then we've generated and validated an SC for every container in the // pod so let's apply what we generated. Note: the psc is already applied. for i := range pod.Spec.InitContainers { pod.Spec.InitContainers[i].SecurityContext = generatedSCs[i] } for i := range pod.Spec.Containers { pod.Spec.Containers[i].SecurityContext = generatedSCs[i+base] } return nil }
// resolveContainerSecurityContext checks the provided container against the provider, returning any // validation errors encountered on the resulting security context, or the security context that was // resolved. The SecurityContext field of the container is updated, so ensure that a copy of the original // container is passed here if you wish to preserve the original input. func resolveContainerSecurityContext(provider scc.SecurityContextConstraintsProvider, pod *kapi.Pod, container *kapi.Container, path *field.Path) (*kapi.SecurityContext, field.ErrorList) { // We will determine the effective security context for the container and validate against that // since that is how the sc provider will eventually apply settings in the runtime. // This results in an SC that is based on the Pod's PSC with the set fields from the container // overriding pod level settings. container.SecurityContext = sc.DetermineEffectiveSecurityContext(pod, container) csc, err := provider.CreateContainerSecurityContext(pod, container) if err != nil { return nil, field.ErrorList{field.Invalid(path.Child("securityContext"), "", err.Error())} } container.SecurityContext = csc return csc, provider.ValidateContainerSecurityContext(pod, container, path.Child("securityContext")) }
// assignSecurityContext creates a security context for each container in the pod // and validates that the sc falls within the scc constraints. All containers must validate against // the same scc or is not considered valid. func assignSecurityContext(provider scc.SecurityContextConstraintsProvider, pod *kapi.Pod, fldPath *field.Path) field.ErrorList { generatedSCs := make([]*kapi.SecurityContext, len(pod.Spec.Containers)) errs := field.ErrorList{} psc, err := provider.CreatePodSecurityContext(pod) if err != nil { errs = append(errs, field.Invalid(field.NewPath("spec", "securityContext"), pod.Spec.SecurityContext, err.Error())) } // save the original PSC and validate the generated PSC. Leave the generated PSC // set for container generation/validation. We will reset to original post container // validation. originalPSC := pod.Spec.SecurityContext pod.Spec.SecurityContext = psc errs = append(errs, provider.ValidatePodSecurityContext(pod, field.NewPath("spec", "securityContext"))...) // Note: this is not changing the original container, we will set container SCs later so long // as all containers validated under the same SCC. for i, containerCopy := range pod.Spec.Containers { // We will determine the effective security context for the container and validate against that // since that is how the sc provider will eventually apply settings in the runtime. // This results in an SC that is based on the Pod's PSC with the set fields from the container // overriding pod level settings. containerCopy.SecurityContext = sc.DetermineEffectiveSecurityContext(pod, &containerCopy) sc, err := provider.CreateContainerSecurityContext(pod, &containerCopy) if err != nil { errs = append(errs, field.Invalid(field.NewPath("spec", "containers").Index(i).Child("securityContext"), "", err.Error())) continue } generatedSCs[i] = sc containerCopy.SecurityContext = sc errs = append(errs, provider.ValidateContainerSecurityContext(pod, &containerCopy, field.NewPath("spec", "containers").Index(i).Child("securityContext"))...) } if len(errs) > 0 { // ensure psc is not mutated if there are errors pod.Spec.SecurityContext = originalPSC return errs } // if we've reached this code then we've generated and validated an SC for every container in the // pod so let's apply what we generated. Note: the psc is already applied. for i, sc := range generatedSCs { pod.Spec.Containers[i].SecurityContext = sc } return nil }
// FillPodSecurityPolicySubjectReviewStatus fills PodSecurityPolicySubjectReviewStatus assigning SecurityContectConstraint to the PodSpec func FillPodSecurityPolicySubjectReviewStatus(s *securityapi.PodSecurityPolicySubjectReviewStatus, provider kscc.SecurityContextConstraintsProvider, spec kapi.PodSpec, constraint *kapi.SecurityContextConstraints) (bool, error) { pod := &kapi.Pod{ Spec: spec, } if errs := oscc.AssignSecurityContext(provider, pod, field.NewPath(fmt.Sprintf("provider %s: ", provider.GetSCCName()))); len(errs) > 0 { glog.Errorf("unable to assign SecurityContextConstraints provider: %v", errs) s.Reason = "CantAssignSecurityContextConstraintProvider" return false, fmt.Errorf("unable to assign SecurityContextConstraints provider: %v", errs.ToAggregate()) } ref, err := kapi.GetReference(constraint) if err != nil { s.Reason = "CantObtainReference" return false, fmt.Errorf("unable to get SecurityContextConstraints reference: %v", err) } s.AllowedBy = ref if len(spec.ServiceAccountName) > 0 { s.Template.Spec = pod.Spec } return true, nil }