mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-27 05:27:21 +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/cauldron
|
||||||
test/soak/serve_hostnames
|
test/soak/serve_hostnames
|
||||||
third_party/forked/golang/expansion
|
third_party/forked/golang/expansion
|
||||||
|
pkg/util/maps
|
||||||
|
@ -22,6 +22,7 @@ import (
|
|||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
"k8s.io/kubernetes/pkg/apis/extensions"
|
"k8s.io/kubernetes/pkg/apis/extensions"
|
||||||
psputil "k8s.io/kubernetes/pkg/security/podsecuritypolicy/util"
|
psputil "k8s.io/kubernetes/pkg/security/podsecuritypolicy/util"
|
||||||
|
"k8s.io/kubernetes/pkg/util/maps"
|
||||||
"k8s.io/kubernetes/pkg/util/validation/field"
|
"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
|
// NOTE: this method works on a copy of the PodSecurityContext. It is up to the caller to
|
||||||
// apply the PSC if validation passes.
|
// 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
|
var sc *api.PodSecurityContext = nil
|
||||||
if pod.Spec.SecurityContext != nil {
|
if pod.Spec.SecurityContext != nil {
|
||||||
// work with a copy
|
// work with a copy
|
||||||
@ -76,11 +77,12 @@ func (s *simpleProvider) CreatePodSecurityContext(pod *api.Pod) (*api.PodSecurit
|
|||||||
} else {
|
} else {
|
||||||
sc = &api.PodSecurityContext{}
|
sc = &api.PodSecurityContext{}
|
||||||
}
|
}
|
||||||
|
annotations := maps.CopySS(pod.Annotations)
|
||||||
|
|
||||||
if len(sc.SupplementalGroups) == 0 {
|
if len(sc.SupplementalGroups) == 0 {
|
||||||
supGroups, err := s.strategies.SupplementalGroupStrategy.Generate(pod)
|
supGroups, err := s.strategies.SupplementalGroupStrategy.Generate(pod)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
sc.SupplementalGroups = supGroups
|
sc.SupplementalGroups = supGroups
|
||||||
}
|
}
|
||||||
@ -88,7 +90,7 @@ func (s *simpleProvider) CreatePodSecurityContext(pod *api.Pod) (*api.PodSecurit
|
|||||||
if sc.FSGroup == nil {
|
if sc.FSGroup == nil {
|
||||||
fsGroup, err := s.strategies.FSGroupStrategy.GenerateSingle(pod)
|
fsGroup, err := s.strategies.FSGroupStrategy.GenerateSingle(pod)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
sc.FSGroup = fsGroup
|
sc.FSGroup = fsGroup
|
||||||
}
|
}
|
||||||
@ -96,12 +98,12 @@ func (s *simpleProvider) CreatePodSecurityContext(pod *api.Pod) (*api.PodSecurit
|
|||||||
if sc.SELinuxOptions == nil {
|
if sc.SELinuxOptions == nil {
|
||||||
seLinux, err := s.strategies.SELinuxStrategy.Generate(pod, nil)
|
seLinux, err := s.strategies.SELinuxStrategy.Generate(pod, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
sc.SELinuxOptions = seLinux
|
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
|
// 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
|
// 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.
|
// 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
|
var sc *api.SecurityContext = nil
|
||||||
if container.SecurityContext != nil {
|
if container.SecurityContext != nil {
|
||||||
// work with a copy of the original
|
// work with a copy of the original
|
||||||
@ -119,10 +121,12 @@ func (s *simpleProvider) CreateContainerSecurityContext(pod *api.Pod, container
|
|||||||
} else {
|
} else {
|
||||||
sc = &api.SecurityContext{}
|
sc = &api.SecurityContext{}
|
||||||
}
|
}
|
||||||
|
annotations := maps.CopySS(pod.Annotations)
|
||||||
|
|
||||||
if sc.RunAsUser == nil {
|
if sc.RunAsUser == nil {
|
||||||
uid, err := s.strategies.RunAsUserStrategy.Generate(pod, container)
|
uid, err := s.strategies.RunAsUserStrategy.Generate(pod, container)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
sc.RunAsUser = uid
|
sc.RunAsUser = uid
|
||||||
}
|
}
|
||||||
@ -130,7 +134,7 @@ func (s *simpleProvider) CreateContainerSecurityContext(pod *api.Pod, container
|
|||||||
if sc.SELinuxOptions == nil {
|
if sc.SELinuxOptions == nil {
|
||||||
seLinux, err := s.strategies.SELinuxStrategy.Generate(pod, container)
|
seLinux, err := s.strategies.SELinuxStrategy.Generate(pod, container)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
sc.SELinuxOptions = seLinux
|
sc.SELinuxOptions = seLinux
|
||||||
}
|
}
|
||||||
@ -150,7 +154,7 @@ func (s *simpleProvider) CreateContainerSecurityContext(pod *api.Pod, container
|
|||||||
|
|
||||||
caps, err := s.strategies.CapabilitiesStrategy.Generate(pod, container)
|
caps, err := s.strategies.CapabilitiesStrategy.Generate(pod, container)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
sc.Capabilities = caps
|
sc.Capabilities = caps
|
||||||
|
|
||||||
@ -161,7 +165,7 @@ func (s *simpleProvider) CreateContainerSecurityContext(pod *api.Pod, container
|
|||||||
sc.ReadOnlyRootFilesystem = &readOnlyRootFS
|
sc.ReadOnlyRootFilesystem = &readOnlyRootFS
|
||||||
}
|
}
|
||||||
|
|
||||||
return sc, nil
|
return sc, annotations, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure a pod's SecurityContext is in compliance with the given constraints.
|
// Ensure a pod's SecurityContext is in compliance with the given constraints.
|
||||||
|
@ -78,7 +78,7 @@ func TestCreatePodSecurityContextNonmutating(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create provider %v", err)
|
t.Fatalf("unable to create provider %v", err)
|
||||||
}
|
}
|
||||||
sc, err := provider.CreatePodSecurityContext(pod)
|
sc, _, err := provider.CreatePodSecurityContext(pod)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create psc %v", err)
|
t.Fatalf("unable to create psc %v", err)
|
||||||
}
|
}
|
||||||
@ -148,7 +148,7 @@ func TestCreateContainerSecurityContextNonmutating(t *testing.T) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("unable to create provider %v", err)
|
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 {
|
if err != nil {
|
||||||
t.Fatalf("unable to create container security context %v", err)
|
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)
|
t.Errorf("%s unable to create provider %v", k, err)
|
||||||
continue
|
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 {
|
if err != nil {
|
||||||
t.Errorf("%s unable to create container security context %v", k, err)
|
t.Errorf("%s unable to create container security context %v", k, err)
|
||||||
continue
|
continue
|
||||||
|
@ -29,10 +29,12 @@ import (
|
|||||||
// Provider provides the implementation to generate a new security
|
// Provider provides the implementation to generate a new security
|
||||||
// context based on constraints or validate an existing security context against constraints.
|
// context based on constraints or validate an existing security context against constraints.
|
||||||
type Provider interface {
|
type Provider interface {
|
||||||
// Create a PodSecurityContext based on the given constraints.
|
// Create a PodSecurityContext based on the given constraints. Also returns an updated set
|
||||||
CreatePodSecurityContext(pod *api.Pod) (*api.PodSecurityContext, error)
|
// of Pod annotations for alpha feature support.
|
||||||
// Create a container SecurityContext based on the given constraints
|
CreatePodSecurityContext(pod *api.Pod) (*api.PodSecurityContext, map[string]string, error)
|
||||||
CreateContainerSecurityContext(pod *api.Pod, container *api.Container) (*api.SecurityContext, 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.
|
// Ensure a pod's SecurityContext is in compliance with the given constraints.
|
||||||
ValidatePodSecurityContext(pod *api.Pod, fldPath *field.Path) field.ErrorList
|
ValidatePodSecurityContext(pod *api.Pod, fldPath *field.Path) field.ErrorList
|
||||||
// Ensure a container's SecurityContext is in compliance with the given constraints
|
// 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"
|
psputil "k8s.io/kubernetes/pkg/security/podsecuritypolicy/util"
|
||||||
sc "k8s.io/kubernetes/pkg/securitycontext"
|
sc "k8s.io/kubernetes/pkg/securitycontext"
|
||||||
"k8s.io/kubernetes/pkg/serviceaccount"
|
"k8s.io/kubernetes/pkg/serviceaccount"
|
||||||
|
"k8s.io/kubernetes/pkg/util/maps"
|
||||||
"k8s.io/kubernetes/pkg/util/validation/field"
|
"k8s.io/kubernetes/pkg/util/validation/field"
|
||||||
"k8s.io/kubernetes/pkg/watch"
|
"k8s.io/kubernetes/pkg/watch"
|
||||||
)
|
)
|
||||||
@ -190,7 +191,7 @@ func assignSecurityContext(provider psp.Provider, pod *api.Pod, fldPath *field.P
|
|||||||
|
|
||||||
errs := field.ErrorList{}
|
errs := field.ErrorList{}
|
||||||
|
|
||||||
psc, err := provider.CreatePodSecurityContext(pod)
|
psc, pscAnnotations, err := provider.CreatePodSecurityContext(pod)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errs = append(errs, field.Invalid(field.NewPath("spec", "securityContext"), pod.Spec.SecurityContext, err.Error()))
|
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.
|
// validation.
|
||||||
originalPSC := pod.Spec.SecurityContext
|
originalPSC := pod.Spec.SecurityContext
|
||||||
pod.Spec.SecurityContext = psc
|
pod.Spec.SecurityContext = psc
|
||||||
|
originalAnnotations := maps.CopySS(pod.Annotations)
|
||||||
|
pod.Annotations = pscAnnotations
|
||||||
errs = append(errs, provider.ValidatePodSecurityContext(pod, field.NewPath("spec", "securityContext"))...)
|
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
|
// 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.
|
// overriding pod level settings.
|
||||||
containerCopy.SecurityContext = sc.DetermineEffectiveSecurityContext(pod, &containerCopy)
|
containerCopy.SecurityContext = sc.DetermineEffectiveSecurityContext(pod, &containerCopy)
|
||||||
|
|
||||||
sc, err := provider.CreateContainerSecurityContext(pod, &containerCopy)
|
sc, scAnnotations, err := provider.CreateContainerSecurityContext(pod, &containerCopy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errs = append(errs, field.Invalid(field.NewPath("spec", "initContainers").Index(i).Child("securityContext"), "", err.Error()))
|
errs = append(errs, field.Invalid(field.NewPath("spec", "initContainers").Index(i).Child("securityContext"), "", err.Error()))
|
||||||
continue
|
continue
|
||||||
@ -219,6 +222,7 @@ func assignSecurityContext(provider psp.Provider, pod *api.Pod, fldPath *field.P
|
|||||||
generatedInitSCs = append(generatedInitSCs, sc)
|
generatedInitSCs = append(generatedInitSCs, sc)
|
||||||
|
|
||||||
containerCopy.SecurityContext = sc
|
containerCopy.SecurityContext = sc
|
||||||
|
pod.Annotations = scAnnotations
|
||||||
errs = append(errs, provider.ValidateContainerSecurityContext(pod, &containerCopy, field.NewPath("spec", "initContainers").Index(i).Child("securityContext"))...)
|
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.
|
// overriding pod level settings.
|
||||||
containerCopy.SecurityContext = sc.DetermineEffectiveSecurityContext(pod, &containerCopy)
|
containerCopy.SecurityContext = sc.DetermineEffectiveSecurityContext(pod, &containerCopy)
|
||||||
|
|
||||||
sc, err := provider.CreateContainerSecurityContext(pod, &containerCopy)
|
sc, scAnnotations, err := provider.CreateContainerSecurityContext(pod, &containerCopy)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
errs = append(errs, field.Invalid(field.NewPath("spec", "containers").Index(i).Child("securityContext"), "", err.Error()))
|
errs = append(errs, field.Invalid(field.NewPath("spec", "containers").Index(i).Child("securityContext"), "", err.Error()))
|
||||||
continue
|
continue
|
||||||
@ -239,12 +243,14 @@ func assignSecurityContext(provider psp.Provider, pod *api.Pod, fldPath *field.P
|
|||||||
generatedSCs[i] = sc
|
generatedSCs[i] = sc
|
||||||
|
|
||||||
containerCopy.SecurityContext = sc
|
containerCopy.SecurityContext = sc
|
||||||
|
pod.Annotations = scAnnotations
|
||||||
errs = append(errs, provider.ValidateContainerSecurityContext(pod, &containerCopy, field.NewPath("spec", "containers").Index(i).Child("securityContext"))...)
|
errs = append(errs, provider.ValidateContainerSecurityContext(pod, &containerCopy, field.NewPath("spec", "containers").Index(i).Child("securityContext"))...)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(errs) > 0 {
|
if len(errs) > 0 {
|
||||||
// ensure psc is not mutated if there are errors
|
// ensure psc is not mutated if there are errors
|
||||||
pod.Spec.SecurityContext = originalPSC
|
pod.Spec.SecurityContext = originalPSC
|
||||||
|
pod.Annotations = originalAnnotations
|
||||||
return errs
|
return errs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user