Add alpha annotations support to the PodSecurityPolicy provider

This commit is contained in:
Tim St. Clair 2016-08-17 10:14:23 -07:00
parent d4ea444277
commit c99d7fddc1
No known key found for this signature in database
GPG Key ID: 434D16BCEF479EAB
4 changed files with 32 additions and 20 deletions

View File

@ -22,6 +22,7 @@ import (
"k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/apis/extensions"
psputil "k8s.io/kubernetes/pkg/security/podsecuritypolicy/util"
"k8s.io/kubernetes/pkg/util/maps"
"k8s.io/kubernetes/pkg/util/validation/field"
)
@ -67,7 +68,7 @@ func NewSimpleProvider(psp *extensions.PodSecurityPolicy, namespace string, stra
//
// NOTE: this method works on a copy of the PodSecurityContext. It is up to the caller to
// apply the PSC if validation passes.
func (s *simpleProvider) CreatePodSecurityContext(pod *api.Pod) (*api.PodSecurityContext, error) {
func (s *simpleProvider) CreatePodSecurityContext(pod *api.Pod) (*api.PodSecurityContext, map[string]string, error) {
var sc *api.PodSecurityContext = nil
if pod.Spec.SecurityContext != nil {
// work with a copy
@ -76,11 +77,12 @@ func (s *simpleProvider) CreatePodSecurityContext(pod *api.Pod) (*api.PodSecurit
} else {
sc = &api.PodSecurityContext{}
}
annotations := maps.CopySS(pod.Annotations)
if len(sc.SupplementalGroups) == 0 {
supGroups, err := s.strategies.SupplementalGroupStrategy.Generate(pod)
if err != nil {
return nil, err
return nil, nil, err
}
sc.SupplementalGroups = supGroups
}
@ -88,7 +90,7 @@ func (s *simpleProvider) CreatePodSecurityContext(pod *api.Pod) (*api.PodSecurit
if sc.FSGroup == nil {
fsGroup, err := s.strategies.FSGroupStrategy.GenerateSingle(pod)
if err != nil {
return nil, err
return nil, nil, err
}
sc.FSGroup = fsGroup
}
@ -96,12 +98,12 @@ func (s *simpleProvider) CreatePodSecurityContext(pod *api.Pod) (*api.PodSecurit
if sc.SELinuxOptions == nil {
seLinux, err := s.strategies.SELinuxStrategy.Generate(pod, nil)
if err != nil {
return nil, err
return nil, nil, err
}
sc.SELinuxOptions = seLinux
}
return sc, nil
return sc, annotations, nil
}
// Create a SecurityContext based on the given constraints. If a setting is already set on the
@ -110,7 +112,7 @@ func (s *simpleProvider) CreatePodSecurityContext(pod *api.Pod) (*api.PodSecurit
//
// NOTE: this method works on a copy of the SC of the container. It is up to the caller to apply
// the SC if validation passes.
func (s *simpleProvider) CreateContainerSecurityContext(pod *api.Pod, container *api.Container) (*api.SecurityContext, error) {
func (s *simpleProvider) CreateContainerSecurityContext(pod *api.Pod, container *api.Container) (*api.SecurityContext, map[string]string, error) {
var sc *api.SecurityContext = nil
if container.SecurityContext != nil {
// work with a copy of the original
@ -119,10 +121,12 @@ func (s *simpleProvider) CreateContainerSecurityContext(pod *api.Pod, container
} else {
sc = &api.SecurityContext{}
}
annotations := maps.CopySS(pod.Annotations)
if sc.RunAsUser == nil {
uid, err := s.strategies.RunAsUserStrategy.Generate(pod, container)
if err != nil {
return nil, err
return nil, nil, err
}
sc.RunAsUser = uid
}
@ -130,7 +134,7 @@ func (s *simpleProvider) CreateContainerSecurityContext(pod *api.Pod, container
if sc.SELinuxOptions == nil {
seLinux, err := s.strategies.SELinuxStrategy.Generate(pod, container)
if err != nil {
return nil, err
return nil, nil, err
}
sc.SELinuxOptions = seLinux
}
@ -150,7 +154,7 @@ func (s *simpleProvider) CreateContainerSecurityContext(pod *api.Pod, container
caps, err := s.strategies.CapabilitiesStrategy.Generate(pod, container)
if err != nil {
return nil, err
return nil, nil, err
}
sc.Capabilities = caps
@ -161,7 +165,7 @@ func (s *simpleProvider) CreateContainerSecurityContext(pod *api.Pod, container
sc.ReadOnlyRootFilesystem = &readOnlyRootFS
}
return sc, nil
return sc, annotations, nil
}
// Ensure a pod's SecurityContext is in compliance with the given constraints.

View File

@ -78,7 +78,7 @@ func TestCreatePodSecurityContextNonmutating(t *testing.T) {
if err != nil {
t.Fatalf("unable to create provider %v", err)
}
sc, err := provider.CreatePodSecurityContext(pod)
sc, _, err := provider.CreatePodSecurityContext(pod)
if err != nil {
t.Fatalf("unable to create psc %v", err)
}
@ -148,7 +148,7 @@ func TestCreateContainerSecurityContextNonmutating(t *testing.T) {
if err != nil {
t.Fatalf("unable to create provider %v", err)
}
sc, err := provider.CreateContainerSecurityContext(pod, &pod.Spec.Containers[0])
sc, _, err := provider.CreateContainerSecurityContext(pod, &pod.Spec.Containers[0])
if err != nil {
t.Fatalf("unable to create container security context %v", err)
}
@ -698,7 +698,7 @@ func TestGenerateContainerSecurityContextReadOnlyRootFS(t *testing.T) {
t.Errorf("%s unable to create provider %v", k, err)
continue
}
sc, err := provider.CreateContainerSecurityContext(v.pod, &v.pod.Spec.Containers[0])
sc, _, err := provider.CreateContainerSecurityContext(v.pod, &v.pod.Spec.Containers[0])
if err != nil {
t.Errorf("%s unable to create container security context %v", k, err)
continue

View File

@ -29,10 +29,12 @@ import (
// Provider provides the implementation to generate a new security
// context based on constraints or validate an existing security context against constraints.
type Provider interface {
// Create a PodSecurityContext based on the given constraints.
CreatePodSecurityContext(pod *api.Pod) (*api.PodSecurityContext, error)
// Create a container SecurityContext based on the given constraints
CreateContainerSecurityContext(pod *api.Pod, container *api.Container) (*api.SecurityContext, error)
// Create a PodSecurityContext based on the given constraints. Also returns an updated set
// of Pod annotations for alpha feature support.
CreatePodSecurityContext(pod *api.Pod) (*api.PodSecurityContext, map[string]string, error)
// Create a container SecurityContext based on the given constraints. Also returns an updated set
// of Pod annotations for alpha feature support.
CreateContainerSecurityContext(pod *api.Pod, container *api.Container) (*api.SecurityContext, map[string]string, error)
// Ensure a pod's SecurityContext is in compliance with the given constraints.
ValidatePodSecurityContext(pod *api.Pod, fldPath *field.Path) field.ErrorList
// Ensure a container's SecurityContext is in compliance with the given constraints

View File

@ -35,6 +35,7 @@ import (
psputil "k8s.io/kubernetes/pkg/security/podsecuritypolicy/util"
sc "k8s.io/kubernetes/pkg/securitycontext"
"k8s.io/kubernetes/pkg/serviceaccount"
"k8s.io/kubernetes/pkg/util/maps"
"k8s.io/kubernetes/pkg/util/validation/field"
"k8s.io/kubernetes/pkg/watch"
)
@ -190,7 +191,7 @@ func assignSecurityContext(provider psp.Provider, pod *api.Pod, fldPath *field.P
errs := field.ErrorList{}
psc, err := provider.CreatePodSecurityContext(pod)
psc, pscAnnotations, err := provider.CreatePodSecurityContext(pod)
if err != nil {
errs = append(errs, field.Invalid(field.NewPath("spec", "securityContext"), pod.Spec.SecurityContext, err.Error()))
}
@ -200,6 +201,8 @@ func assignSecurityContext(provider psp.Provider, pod *api.Pod, fldPath *field.P
// validation.
originalPSC := pod.Spec.SecurityContext
pod.Spec.SecurityContext = psc
originalAnnotations := maps.CopySS(pod.Annotations)
pod.Annotations = pscAnnotations
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
@ -211,7 +214,7 @@ func assignSecurityContext(provider psp.Provider, pod *api.Pod, fldPath *field.P
// overriding pod level settings.
containerCopy.SecurityContext = sc.DetermineEffectiveSecurityContext(pod, &containerCopy)
sc, err := provider.CreateContainerSecurityContext(pod, &containerCopy)
sc, scAnnotations, err := provider.CreateContainerSecurityContext(pod, &containerCopy)
if err != nil {
errs = append(errs, field.Invalid(field.NewPath("spec", "initContainers").Index(i).Child("securityContext"), "", err.Error()))
continue
@ -219,6 +222,7 @@ func assignSecurityContext(provider psp.Provider, pod *api.Pod, fldPath *field.P
generatedInitSCs = append(generatedInitSCs, sc)
containerCopy.SecurityContext = sc
pod.Annotations = scAnnotations
errs = append(errs, provider.ValidateContainerSecurityContext(pod, &containerCopy, field.NewPath("spec", "initContainers").Index(i).Child("securityContext"))...)
}
@ -231,7 +235,7 @@ func assignSecurityContext(provider psp.Provider, pod *api.Pod, fldPath *field.P
// overriding pod level settings.
containerCopy.SecurityContext = sc.DetermineEffectiveSecurityContext(pod, &containerCopy)
sc, err := provider.CreateContainerSecurityContext(pod, &containerCopy)
sc, scAnnotations, err := provider.CreateContainerSecurityContext(pod, &containerCopy)
if err != nil {
errs = append(errs, field.Invalid(field.NewPath("spec", "containers").Index(i).Child("securityContext"), "", err.Error()))
continue
@ -239,12 +243,14 @@ func assignSecurityContext(provider psp.Provider, pod *api.Pod, fldPath *field.P
generatedSCs[i] = sc
containerCopy.SecurityContext = sc
pod.Annotations = scAnnotations
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
pod.Annotations = originalAnnotations
return errs
}