Skip to content

Commit

Permalink
Add alpha annotations support to the PodSecurityPolicy provider
Browse files Browse the repository at this point in the history
  • Loading branch information
tallclair committed Aug 17, 2016
1 parent d4ea444 commit c99d7fd
Show file tree
Hide file tree
Showing 4 changed files with 32 additions and 20 deletions.
24 changes: 14 additions & 10 deletions pkg/security/podsecuritypolicy/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)

Expand Down Expand Up @@ -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
Expand All @@ -76,32 +77,33 @@ 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
}

if sc.FSGroup == nil {
fsGroup, err := s.strategies.FSGroupStrategy.GenerateSingle(pod)
if err != nil {
return nil, err
return nil, nil, err
}
sc.FSGroup = fsGroup
}

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
Expand All @@ -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
Expand All @@ -119,18 +121,20 @@ 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
}

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
}
Expand All @@ -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

Expand All @@ -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.
Expand Down
6 changes: 3 additions & 3 deletions pkg/security/podsecuritypolicy/provider_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
}
Expand Down Expand Up @@ -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)
}
Expand Down Expand Up @@ -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
Expand Down
10 changes: 6 additions & 4 deletions pkg/security/podsecuritypolicy/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
12 changes: 9 additions & 3 deletions plugin/pkg/admission/security/podsecuritypolicy/admission.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
)
Expand Down Expand Up @@ -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()))
}
Expand All @@ -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
Expand All @@ -211,14 +214,15 @@ 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
}
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"))...)
}

Expand All @@ -231,20 +235,22 @@ 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
}
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
}

Expand Down

0 comments on commit c99d7fd

Please sign in to comment.