Skip to content

Commit 8976e36

Browse files
pjbgfsaschagrunert
andcommitted
Add seccomp enforcement and validation based on new GA fields
Adds seccomp validation. This ensures that field and annotation values must match when present. Co-authored-by: Sascha Grunert <[email protected]>
1 parent 865cbf0 commit 8976e36

File tree

93 files changed

+16268
-14099
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

93 files changed

+16268
-14099
lines changed

api/openapi-spec/swagger.json

Lines changed: 33 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/apis/core/annotation_key_constants.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,17 +39,20 @@ const (
3939

4040
// SeccompPodAnnotationKey represents the key of a seccomp profile applied
4141
// to all containers of a pod.
42+
// Deprecated: set a pod security context `seccompProfile` field.
4243
SeccompPodAnnotationKey string = "seccomp.security.alpha.kubernetes.io/pod"
4344

4445
// SeccompContainerAnnotationKeyPrefix represents the key of a seccomp profile applied
4546
// to one container of a pod.
47+
// Deprecated: set a container security context `seccompProfile` field.
4648
SeccompContainerAnnotationKeyPrefix string = "container.seccomp.security.alpha.kubernetes.io/"
4749

4850
// SeccompProfileRuntimeDefault represents the default seccomp profile used by container runtime.
51+
// Deprecated: set a pod or container security context `seccompProfile` of type "RuntimeDefault" instead.
4952
SeccompProfileRuntimeDefault string = "runtime/default"
5053

5154
// DeprecatedSeccompProfileDockerDefault represents the default seccomp profile used by docker.
52-
// This is now deprecated and should be replaced by SeccompProfileRuntimeDefault.
55+
// Deprecated: set a pod or container security context `seccompProfile` of type "RuntimeDefault" instead.
5356
DeprecatedSeccompProfileDockerDefault string = "docker/default"
5457

5558
// PreferAvoidPodsAnnotationKey represents the key of preferAvoidPods data (json serialized)

pkg/apis/core/pods/helpers.go

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -34,23 +34,23 @@ type ContainerVisitorWithPath func(container *api.Container, path *field.Path) b
3434
// of every container in the given pod spec and the field.Path to that container.
3535
// If visitor returns false, visiting is short-circuited. VisitContainersWithPath returns true if visiting completes,
3636
// false if visiting was short-circuited.
37-
func VisitContainersWithPath(podSpec *api.PodSpec, visitor ContainerVisitorWithPath) bool {
38-
path := field.NewPath("spec", "initContainers")
37+
func VisitContainersWithPath(podSpec *api.PodSpec, specPath *field.Path, visitor ContainerVisitorWithPath) bool {
38+
fldPath := specPath.Child("initContainers")
3939
for i := range podSpec.InitContainers {
40-
if !visitor(&podSpec.InitContainers[i], path.Index(i)) {
40+
if !visitor(&podSpec.InitContainers[i], fldPath.Index(i)) {
4141
return false
4242
}
4343
}
44-
path = field.NewPath("spec", "containers")
44+
fldPath = specPath.Child("containers")
4545
for i := range podSpec.Containers {
46-
if !visitor(&podSpec.Containers[i], path.Index(i)) {
46+
if !visitor(&podSpec.Containers[i], fldPath.Index(i)) {
4747
return false
4848
}
4949
}
5050
if utilfeature.DefaultFeatureGate.Enabled(features.EphemeralContainers) {
51-
path = field.NewPath("spec", "ephemeralContainers")
51+
fldPath = specPath.Child("ephemeralContainers")
5252
for i := range podSpec.EphemeralContainers {
53-
if !visitor((*api.Container)(&podSpec.EphemeralContainers[i].EphemeralContainerCommon), path.Index(i)) {
53+
if !visitor((*api.Container)(&podSpec.EphemeralContainers[i].EphemeralContainerCommon), fldPath.Index(i)) {
5454
return false
5555
}
5656
}

pkg/apis/core/pods/helpers_test.go

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,16 +32,19 @@ func TestVisitContainersWithPath(t *testing.T) {
3232

3333
testCases := []struct {
3434
description string
35+
path *field.Path
3536
haveSpec *api.PodSpec
3637
wantNames []string
3738
}{
3839
{
3940
"empty podspec",
41+
field.NewPath("spec"),
4042
&api.PodSpec{},
4143
[]string{},
4244
},
4345
{
4446
"regular containers",
47+
field.NewPath("spec"),
4548
&api.PodSpec{
4649
Containers: []api.Container{
4750
{Name: "c1"},
@@ -52,6 +55,7 @@ func TestVisitContainersWithPath(t *testing.T) {
5255
},
5356
{
5457
"init containers",
58+
field.NewPath("spec"),
5559
&api.PodSpec{
5660
InitContainers: []api.Container{
5761
{Name: "i1"},
@@ -62,6 +66,7 @@ func TestVisitContainersWithPath(t *testing.T) {
6266
},
6367
{
6468
"regular and init containers",
69+
field.NewPath("spec"),
6570
&api.PodSpec{
6671
Containers: []api.Container{
6772
{Name: "c1"},
@@ -76,6 +81,7 @@ func TestVisitContainersWithPath(t *testing.T) {
7681
},
7782
{
7883
"ephemeral containers",
84+
field.NewPath("spec"),
7985
&api.PodSpec{
8086
Containers: []api.Container{
8187
{Name: "c1"},
@@ -89,6 +95,7 @@ func TestVisitContainersWithPath(t *testing.T) {
8995
},
9096
{
9197
"all container types",
98+
field.NewPath("spec"),
9299
&api.PodSpec{
93100
Containers: []api.Container{
94101
{Name: "c1"},
@@ -105,11 +112,30 @@ func TestVisitContainersWithPath(t *testing.T) {
105112
},
106113
[]string{"spec.initContainers[0]", "spec.initContainers[1]", "spec.containers[0]", "spec.containers[1]", "spec.ephemeralContainers[0]", "spec.ephemeralContainers[1]"},
107114
},
115+
{
116+
"all container types with template pod path",
117+
field.NewPath("template", "spec"),
118+
&api.PodSpec{
119+
Containers: []api.Container{
120+
{Name: "c1"},
121+
{Name: "c2"},
122+
},
123+
InitContainers: []api.Container{
124+
{Name: "i1"},
125+
{Name: "i2"},
126+
},
127+
EphemeralContainers: []api.EphemeralContainer{
128+
{EphemeralContainerCommon: api.EphemeralContainerCommon{Name: "e1"}},
129+
{EphemeralContainerCommon: api.EphemeralContainerCommon{Name: "e2"}},
130+
},
131+
},
132+
[]string{"template.spec.initContainers[0]", "template.spec.initContainers[1]", "template.spec.containers[0]", "template.spec.containers[1]", "template.spec.ephemeralContainers[0]", "template.spec.ephemeralContainers[1]"},
133+
},
108134
}
109135

110136
for _, tc := range testCases {
111137
gotNames := []string{}
112-
VisitContainersWithPath(tc.haveSpec, func(c *api.Container, p *field.Path) bool {
138+
VisitContainersWithPath(tc.haveSpec, tc.path, func(c *api.Container, p *field.Path) bool {
113139
gotNames = append(gotNames, p.String())
114140
return true
115141
})

pkg/apis/core/types.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2897,8 +2897,36 @@ type PodSecurityContext struct {
28972897
// sysctls (by the container runtime) might fail to launch.
28982898
// +optional
28992899
Sysctls []Sysctl
2900+
// The seccomp options to use by the containers in this pod.
2901+
// +optional
2902+
SeccompProfile *SeccompProfile
29002903
}
29012904

2905+
// SeccompProfile defines a pod/container's seccomp profile settings.
2906+
// Only one profile source may be set.
2907+
// +union
2908+
type SeccompProfile struct {
2909+
// +unionDiscriminator
2910+
Type SeccompProfileType
2911+
// Load a profile defined in static file on the node.
2912+
// The profile must be preconfigured on the node to work.
2913+
// LocalhostProfile cannot be an absolute nor a descending path.
2914+
// +optional
2915+
LocalhostProfile *string
2916+
}
2917+
2918+
// SeccompProfileType defines the supported seccomp profile types.
2919+
type SeccompProfileType string
2920+
2921+
const (
2922+
// SeccompProfileTypeUnconfined is when no seccomp profile is applied (A.K.A. unconfined).
2923+
SeccompProfileTypeUnconfined SeccompProfileType = "Unconfined"
2924+
// SeccompProfileTypeRuntimeDefault represents the default container runtime seccomp profile.
2925+
SeccompProfileTypeRuntimeDefault SeccompProfileType = "RuntimeDefault"
2926+
// SeccompProfileTypeLocalhost represents custom made profiles stored on the node's disk.
2927+
SeccompProfileTypeLocalhost SeccompProfileType = "Localhost"
2928+
)
2929+
29022930
// PodQOSClass defines the supported qos classes of Pods.
29032931
type PodQOSClass string
29042932

@@ -5085,6 +5113,11 @@ type SecurityContext struct {
50855113
// readonly paths and masked paths.
50865114
// +optional
50875115
ProcMount *ProcMountType
5116+
// The seccomp options to use by this container. If seccomp options are
5117+
// provided at both the pod & container level, the container options
5118+
// override the pod options.
5119+
// +optional
5120+
SeccompProfile *SeccompProfile
50885121
}
50895122

50905123
// ProcMountType defines the type of proc mount

pkg/apis/core/v1/zz_generated.conversion.go

Lines changed: 36 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pkg/apis/core/validation/BUILD

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,8 @@ go_test(
6969
"//staging/src/k8s.io/apimachinery/pkg/util/validation/field:go_default_library",
7070
"//staging/src/k8s.io/apiserver/pkg/util/feature:go_default_library",
7171
"//staging/src/k8s.io/component-base/featuregate/testing:go_default_library",
72+
"//vendor/github.com/stretchr/testify/assert:go_default_library",
73+
"//vendor/github.com/stretchr/testify/require:go_default_library",
7274
"//vendor/k8s.io/utils/pointer:go_default_library",
7375
],
7476
)

0 commit comments

Comments
 (0)