mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 19:56:01 +00:00
Merge pull request #30257 from timstclair/aa-psp-annotations
Automatic merge from submit-queue Add annotations to the PodSecurityPolicy Provider interface @pweil- is this what you were thinking in terms of API changes? I really like to avoid functions with more than 2 return values, but couldn't think of a cleaner approach in this case.
This commit is contained in:
commit
dc588e4451
@ -197,3 +197,4 @@ test/integration/openshift
|
||||
test/soak/cauldron
|
||||
test/soak/serve_hostnames
|
||||
third_party/forked/golang/expansion
|
||||
pkg/util/maps
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
18
pkg/util/maps/doc.go
Normal file
18
pkg/util/maps/doc.go
Normal file
@ -0,0 +1,18 @@
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
// Package maps has common methods for dealing with common map types.
|
||||
package maps
|
29
pkg/util/maps/string.go
Normal file
29
pkg/util/maps/string.go
Normal file
@ -0,0 +1,29 @@
|
||||
/*
|
||||
Copyright 2016 The Kubernetes Authors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package maps
|
||||
|
||||
// CopySS makes a shallow copy of a map.
|
||||
func CopySS(m map[string]string) map[string]string {
|
||||
if m == nil {
|
||||
return nil
|
||||
}
|
||||
copy := make(map[string]string, len(m))
|
||||
for k, v := range m {
|
||||
copy[k] = v
|
||||
}
|
||||
return copy
|
||||
}
|
@ -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
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user