summaryrefslogtreecommitdiffstats
path: root/recipes-containers
diff options
context:
space:
mode:
authorSoumya Sambu <soumya.sambu@windriver.com>2023-11-13 04:16:41 +0000
committerBruce Ashfield <bruce.ashfield@gmail.com>2023-11-21 04:07:47 +0000
commit67b0ef4256a484851f3556d281ca4caa88374388 (patch)
tree8ebfe1a58794f434e87f9282824aecef32e69ca7 /recipes-containers
parent86126c9b348ffbe4156fbe489c74829efdb7fb43 (diff)
downloadmeta-virtualization-67b0ef4256a484851f3556d281ca4caa88374388.tar.gz
kubernetes: Fix CVE-2023-2727, CVE-2023-2728
Users may be able to launch containers using images that are restricted by ImagePolicyWebhook when using ephemeral containers, Kubernetes clusters are only affected if the ImagePolicyWebhook admission plugin is used together with ephemeral containers. Users may be able to launch containers that bypass the mountable secrets policy enforced by the ServiceAccount admission plugin when using ephemeral containers. The policy ensures pods running with a service account may only reference secrets specified in the service account's secrets field. Kuberenetes clusters are only affected if the ServiceAccount admission plugin and the `kubernetes.io/enforce-mountab'le-secrets` annotation are used teogether with ephemeralcontainers. CVE: CVE-2023-2727, CVE-2023-2728 Affected Versions 1.27.0 - v1.27.2 v1.26.0 - v1.26.5 v1.25.0 - v1.25.10 <= v1.24.14 master branch(kubernetes v1.28.2) is not impacted mickledore branch(kubernetes v1.27.5) is not impacted References: https://nvd.nist.gov/vuln/detail/CVE-2023-2727 https://nvd.nist.gov/vuln/detail/CVE-2023-2728 Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com> Signed-off-by: Bruce Ashfield <bruce.ashfield@gmail.com>
Diffstat (limited to 'recipes-containers')
-rw-r--r--recipes-containers/kubernetes/kubernetes/CVE-2023-2727-CVE-2023-2728.patch559
-rw-r--r--recipes-containers/kubernetes/kubernetes_git.bb1
2 files changed, 560 insertions, 0 deletions
diff --git a/recipes-containers/kubernetes/kubernetes/CVE-2023-2727-CVE-2023-2728.patch b/recipes-containers/kubernetes/kubernetes/CVE-2023-2727-CVE-2023-2728.patch
new file mode 100644
index 00000000..2a9e8489
--- /dev/null
+++ b/recipes-containers/kubernetes/kubernetes/CVE-2023-2727-CVE-2023-2728.patch
@@ -0,0 +1,559 @@
1From f754a4dee31455a0d7fc0f51cb85348af9ea5e1f Mon Sep 17 00:00:00 2001
2From: Rita Zhang <rita.z.zhang@gmail.com>
3Date: Tue, 30 May 2023 20:35:33 +0000
4Subject: [PATCH] Add ephemeralcontainer to imagepolicy securityaccount
5 admission plugin
6
7Signed-off-by: Rita Zhang <rita.z.zhang@gmail.com>
8
9CVE: CVE-2023-2727, CVE-2023-2728
10
11Upstream-Status: Backport [https://github.com/kubernetes/kubernetes/commit/f754a4dee31455a0d7fc0f51cb85348af9ea5e1f]
12
13Signed-off-by: Soumya Sambu <soumya.sambu@windriver.com>
14---
15 plugin/pkg/admission/imagepolicy/admission.go | 28 ++--
16 .../admission/imagepolicy/admission_test.go | 148 +++++++++++++++++-
17 .../pkg/admission/serviceaccount/admission.go | 57 ++++++-
18 .../serviceaccount/admission_test.go | 88 +++++++++++
19 4 files changed, 297 insertions(+), 24 deletions(-)
20
21diff --git a/plugin/pkg/admission/imagepolicy/admission.go b/plugin/pkg/admission/imagepolicy/admission.go
22index aea4f713eb5..3dfcbf95eef 100644
23--- a/plugin/pkg/admission/imagepolicy/admission.go
24+++ b/plugin/pkg/admission/imagepolicy/admission.go
25@@ -46,6 +46,7 @@ import (
26
27 // PluginName indicates name of admission plugin.
28 const PluginName = "ImagePolicyWebhook"
29+const ephemeralcontainers = "ephemeralcontainers"
30
31 // AuditKeyPrefix is used as the prefix for all audit keys handled by this
32 // pluggin. Some well known suffixes are listed below.
33@@ -132,8 +133,9 @@ func (a *Plugin) webhookError(pod *api.Pod, attributes admission.Attributes, err
34
35 // Validate makes an admission decision based on the request attributes
36 func (a *Plugin) Validate(ctx context.Context, attributes admission.Attributes, o admission.ObjectInterfaces) (err error) {
37- // Ignore all calls to subresources or resources other than pods.
38- if attributes.GetSubresource() != "" || attributes.GetResource().GroupResource() != api.Resource("pods") {
39+ // Ignore all calls to subresources other than ephemeralcontainers or calls to resources other than pods.
40+ subresource := attributes.GetSubresource()
41+ if (subresource != "" && subresource != ephemeralcontainers) || attributes.GetResource().GroupResource() != api.Resource("pods") {
42 return nil
43 }
44
45@@ -144,13 +146,21 @@ func (a *Plugin) Validate(ctx context.Context, attributes admission.Attributes,
46
47 // Build list of ImageReviewContainerSpec
48 var imageReviewContainerSpecs []v1alpha1.ImageReviewContainerSpec
49- containers := make([]api.Container, 0, len(pod.Spec.Containers)+len(pod.Spec.InitContainers))
50- containers = append(containers, pod.Spec.Containers...)
51- containers = append(containers, pod.Spec.InitContainers...)
52- for _, c := range containers {
53- imageReviewContainerSpecs = append(imageReviewContainerSpecs, v1alpha1.ImageReviewContainerSpec{
54- Image: c.Image,
55- })
56+ if subresource == "" {
57+ containers := make([]api.Container, 0, len(pod.Spec.Containers)+len(pod.Spec.InitContainers))
58+ containers = append(containers, pod.Spec.Containers...)
59+ containers = append(containers, pod.Spec.InitContainers...)
60+ for _, c := range containers {
61+ imageReviewContainerSpecs = append(imageReviewContainerSpecs, v1alpha1.ImageReviewContainerSpec{
62+ Image: c.Image,
63+ })
64+ }
65+ } else if subresource == ephemeralcontainers {
66+ for _, c := range pod.Spec.EphemeralContainers {
67+ imageReviewContainerSpecs = append(imageReviewContainerSpecs, v1alpha1.ImageReviewContainerSpec{
68+ Image: c.Image,
69+ })
70+ }
71 }
72 imageReview := v1alpha1.ImageReview{
73 Spec: v1alpha1.ImageReviewSpec{
74diff --git a/plugin/pkg/admission/imagepolicy/admission_test.go b/plugin/pkg/admission/imagepolicy/admission_test.go
75index d1f81d51950..a9188462fb9 100644
76--- a/plugin/pkg/admission/imagepolicy/admission_test.go
77+++ b/plugin/pkg/admission/imagepolicy/admission_test.go
78@@ -37,7 +37,6 @@ import (
79 api "k8s.io/kubernetes/pkg/apis/core"
80
81 "fmt"
82- "io/ioutil"
83 "os"
84 "path/filepath"
85 "text/template"
86@@ -67,7 +66,7 @@ imagePolicy:
87 `
88
89 func TestNewFromConfig(t *testing.T) {
90- dir, err := ioutil.TempDir("", "")
91+ dir, err := os.MkdirTemp("", "")
92 if err != nil {
93 t.Fatal(err)
94 }
95@@ -92,7 +91,7 @@ func TestNewFromConfig(t *testing.T) {
96 {data.Key, clientKey},
97 }
98 for _, file := range files {
99- if err := ioutil.WriteFile(file.name, file.data, 0400); err != nil {
100+ if err := os.WriteFile(file.name, file.data, 0400); err != nil {
101 t.Fatal(err)
102 }
103 }
104@@ -196,7 +195,7 @@ current-context: default
105 // Use a closure so defer statements trigger between loop iterations.
106 t.Run(tt.msg, func(t *testing.T) {
107 err := func() error {
108- tempfile, err := ioutil.TempFile("", "")
109+ tempfile, err := os.CreateTemp("", "")
110 if err != nil {
111 return err
112 }
113@@ -211,7 +210,7 @@ current-context: default
114 return fmt.Errorf("failed to execute test template: %v", err)
115 }
116
117- tempconfigfile, err := ioutil.TempFile("", "")
118+ tempconfigfile, err := os.CreateTemp("", "")
119 if err != nil {
120 return err
121 }
122@@ -359,7 +358,7 @@ func (m *mockService) HTTPStatusCode() int { return m.statusCode }
123 // newImagePolicyWebhook creates a temporary kubeconfig file from the provided arguments and attempts to load
124 // a new newImagePolicyWebhook from it.
125 func newImagePolicyWebhook(callbackURL string, clientCert, clientKey, ca []byte, cacheTime time.Duration, defaultAllow bool) (*Plugin, error) {
126- tempfile, err := ioutil.TempFile("", "")
127+ tempfile, err := os.CreateTemp("", "")
128 if err != nil {
129 return nil, err
130 }
131@@ -381,7 +380,7 @@ func newImagePolicyWebhook(callbackURL string, clientCert, clientKey, ca []byte,
132 return nil, err
133 }
134
135- tempconfigfile, err := ioutil.TempFile("", "")
136+ tempconfigfile, err := os.CreateTemp("", "")
137 if err != nil {
138 return nil, err
139 }
140@@ -595,17 +594,23 @@ func TestContainerCombinations(t *testing.T) {
141 test string
142 pod *api.Pod
143 wantAllowed, wantErr bool
144+ subresource string
145+ operation admission.Operation
146 }{
147 {
148 test: "Single container allowed",
149 pod: goodPod("good"),
150 wantAllowed: true,
151+ subresource: "",
152+ operation: admission.Create,
153 },
154 {
155 test: "Single container denied",
156 pod: goodPod("bad"),
157 wantAllowed: false,
158 wantErr: true,
159+ subresource: "",
160+ operation: admission.Create,
161 },
162 {
163 test: "One good container, one bad",
164@@ -627,6 +632,8 @@ func TestContainerCombinations(t *testing.T) {
165 },
166 wantAllowed: false,
167 wantErr: true,
168+ subresource: "",
169+ operation: admission.Create,
170 },
171 {
172 test: "Multiple good containers",
173@@ -648,6 +655,8 @@ func TestContainerCombinations(t *testing.T) {
174 },
175 wantAllowed: true,
176 wantErr: false,
177+ subresource: "",
178+ operation: admission.Create,
179 },
180 {
181 test: "Multiple bad containers",
182@@ -669,6 +678,8 @@ func TestContainerCombinations(t *testing.T) {
183 },
184 wantAllowed: false,
185 wantErr: true,
186+ subresource: "",
187+ operation: admission.Create,
188 },
189 {
190 test: "Good container, bad init container",
191@@ -692,6 +703,8 @@ func TestContainerCombinations(t *testing.T) {
192 },
193 wantAllowed: false,
194 wantErr: true,
195+ subresource: "",
196+ operation: admission.Create,
197 },
198 {
199 test: "Bad container, good init container",
200@@ -715,6 +728,8 @@ func TestContainerCombinations(t *testing.T) {
201 },
202 wantAllowed: false,
203 wantErr: true,
204+ subresource: "",
205+ operation: admission.Create,
206 },
207 {
208 test: "Good container, good init container",
209@@ -738,6 +753,123 @@ func TestContainerCombinations(t *testing.T) {
210 },
211 wantAllowed: true,
212 wantErr: false,
213+ subresource: "",
214+ operation: admission.Create,
215+ },
216+ {
217+ test: "Good container, good init container, bad ephemeral container when updating ephemeralcontainers subresource",
218+ pod: &api.Pod{
219+ Spec: api.PodSpec{
220+ ServiceAccountName: "default",
221+ SecurityContext: &api.PodSecurityContext{},
222+ Containers: []api.Container{
223+ {
224+ Image: "good",
225+ SecurityContext: &api.SecurityContext{},
226+ },
227+ },
228+ InitContainers: []api.Container{
229+ {
230+ Image: "good",
231+ SecurityContext: &api.SecurityContext{},
232+ },
233+ },
234+ EphemeralContainers: []api.EphemeralContainer{
235+ {
236+ EphemeralContainerCommon: api.EphemeralContainerCommon{
237+ Image: "bad",
238+ SecurityContext: &api.SecurityContext{},
239+ },
240+ },
241+ },
242+ },
243+ },
244+ wantAllowed: false,
245+ wantErr: true,
246+ subresource: "ephemeralcontainers",
247+ operation: admission.Update,
248+ },
249+ {
250+ test: "Good container, good init container, bad ephemeral container when updating subresource=='' which sets initContainer and container only",
251+ pod: &api.Pod{
252+ Spec: api.PodSpec{
253+ ServiceAccountName: "default",
254+ SecurityContext: &api.PodSecurityContext{},
255+ Containers: []api.Container{
256+ {
257+ Image: "good",
258+ SecurityContext: &api.SecurityContext{},
259+ },
260+ },
261+ InitContainers: []api.Container{
262+ {
263+ Image: "good",
264+ SecurityContext: &api.SecurityContext{},
265+ },
266+ },
267+ EphemeralContainers: []api.EphemeralContainer{
268+ {
269+ EphemeralContainerCommon: api.EphemeralContainerCommon{
270+ Image: "bad",
271+ SecurityContext: &api.SecurityContext{},
272+ },
273+ },
274+ },
275+ },
276+ },
277+ wantAllowed: true,
278+ wantErr: false,
279+ subresource: "",
280+ operation: admission.Update,
281+ },
282+
283+ {
284+ test: "Bad container, good ephemeral container when updating subresource=='ephemeralcontainers' which sets ephemeralcontainers only",
285+ pod: &api.Pod{
286+ Spec: api.PodSpec{
287+ ServiceAccountName: "default",
288+ SecurityContext: &api.PodSecurityContext{},
289+ Containers: []api.Container{
290+ {
291+ Image: "bad",
292+ SecurityContext: &api.SecurityContext{},
293+ },
294+ },
295+ EphemeralContainers: []api.EphemeralContainer{
296+ {
297+ EphemeralContainerCommon: api.EphemeralContainerCommon{
298+ Image: "good",
299+ SecurityContext: &api.SecurityContext{},
300+ },
301+ },
302+ },
303+ },
304+ },
305+ wantAllowed: true,
306+ wantErr: false,
307+ subresource: "ephemeralcontainers",
308+ operation: admission.Update,
309+ },
310+ {
311+ test: "Good ephemeral container",
312+ pod: &api.Pod{
313+ Spec: api.PodSpec{
314+ ServiceAccountName: "default",
315+ SecurityContext: &api.PodSecurityContext{},
316+ EphemeralContainers: []api.EphemeralContainer{
317+ {
318+ EphemeralContainerCommon: api.EphemeralContainerCommon{
319+ Image: "good",
320+ SecurityContext: &api.SecurityContext{},
321+ },
322+ },
323+ },
324+ },
325+ },
326+ wantAllowed: true,
327+ wantErr: false,
328+ subresource: "ephemeralcontainers",
329+ operation: admission.Update,
330 },
331 }
332 for _, tt := range tests {
333@@ -759,7 +891,7 @@ func TestContainerCombinations(t *testing.T) {
334 return
335 }
336
337- attr := admission.NewAttributesRecord(tt.pod, nil, api.Kind("Pod").WithVersion("version"), "namespace", "", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, &user.DefaultInfo{})
338+ attr := admission.NewAttributesRecord(tt.pod, nil, api.Kind("Pod").WithVersion("version"), "namespace", "", api.Resource("pods").WithVersion("version"), tt.subresource, tt.operation, &metav1.CreateOptions{}, false, &user.DefaultInfo{})
339
340 err = wh.Validate(context.TODO(), attr, nil)
341 if tt.wantAllowed {
342diff --git a/plugin/pkg/admission/serviceaccount/admission.go b/plugin/pkg/admission/serviceaccount/admission.go
343index 035d54ea8ea..f6e25f3c19d 100644
344--- a/plugin/pkg/admission/serviceaccount/admission.go
345+++ b/plugin/pkg/admission/serviceaccount/admission.go
346@@ -100,7 +100,7 @@ var _ = genericadmissioninitializer.WantsExternalKubeInformerFactory(&Plugin{})
347 // 5. If MountServiceAccountToken is true, it adds a VolumeMount with the pod's ServiceAccount's api token secret to containers
348 func NewServiceAccount() *Plugin {
349 return &Plugin{
350- Handler: admission.NewHandler(admission.Create),
351+ Handler: admission.NewHandler(admission.Create, admission.Update),
352 // TODO: enable this once we've swept secret usage to account for adding secret references to service accounts
353 LimitSecretReferences: false,
354 // Auto mount service account API token secrets
355@@ -140,7 +140,10 @@ func (s *Plugin) Admit(ctx context.Context, a admission.Attributes, o admission.
356 if shouldIgnore(a) {
357 return nil
358 }
359-
360+ if a.GetOperation() != admission.Create {
361+ // we only mutate pods during create requests
362+ return nil
363+ }
364 pod := a.GetObject().(*api.Pod)
365
366 // Don't modify the spec of mirror pods.
367@@ -157,7 +160,7 @@ func (s *Plugin) Admit(ctx context.Context, a admission.Attributes, o admission.
368
369 serviceAccount, err := s.getServiceAccount(a.GetNamespace(), pod.Spec.ServiceAccountName)
370 if err != nil {
371- return admission.NewForbidden(a, fmt.Errorf("error looking up service account %s/%s: %v", a.GetNamespace(), pod.Spec.ServiceAccountName, err))
372+ return admission.NewForbidden(a, fmt.Errorf("error looking up service account %s/%s: %w", a.GetNamespace(), pod.Spec.ServiceAccountName, err))
373 }
374 if s.MountServiceAccountToken && shouldAutomount(serviceAccount, pod) {
375 s.mountServiceAccountToken(serviceAccount, pod)
376@@ -180,6 +183,15 @@ func (s *Plugin) Validate(ctx context.Context, a admission.Attributes, o admissi
377
378 pod := a.GetObject().(*api.Pod)
379
380+ if a.GetOperation() == admission.Update && a.GetSubresource() == "ephemeralcontainers" {
381+ return s.limitEphemeralContainerSecretReferences(pod, a)
382+ }
383+
384+ if a.GetOperation() != admission.Create {
385+ // we only validate pod specs during create requests
386+ return nil
387+ }
388+
389 // Mirror pods have restrictions on what they can reference
390 if _, isMirrorPod := pod.Annotations[api.MirrorPodAnnotationKey]; isMirrorPod {
391 if len(pod.Spec.ServiceAccountName) != 0 {
392@@ -205,6 +217,10 @@ func (s *Plugin) Validate(ctx context.Context, a admission.Attributes, o admissi
393 return nil
394 }
395
396+ // Require container pods to have service accounts
397+ if len(pod.Spec.ServiceAccountName) == 0 {
398+ return admission.NewForbidden(a, fmt.Errorf("no service account specified for pod %s/%s", a.GetNamespace(), pod.Name))
399+ }
400 // Ensure the referenced service account exists
401 serviceAccount, err := s.getServiceAccount(a.GetNamespace(), pod.Spec.ServiceAccountName)
402 if err != nil {
403@@ -221,10 +237,7 @@ func (s *Plugin) Validate(ctx context.Context, a admission.Attributes, o admissi
404 }
405
406 func shouldIgnore(a admission.Attributes) bool {
407- if a.GetResource().GroupResource() != api.Resource("pods") {
408- return true
409- }
410- if a.GetSubresource() != "" {
411+ if a.GetResource().GroupResource() != api.Resource("pods") || (a.GetSubresource() != "" && a.GetSubresource() != "ephemeralcontainers") {
412 return true
413 }
414 obj := a.GetObject()
415@@ -350,6 +363,36 @@ func (s *Plugin) limitSecretReferences(serviceAccount *corev1.ServiceAccount, po
416 return nil
417 }
418
419+func (s *Plugin) limitEphemeralContainerSecretReferences(pod *api.Pod, a admission.Attributes) error {
420+ // Require ephemeral container pods to have service accounts
421+ if len(pod.Spec.ServiceAccountName) == 0 {
422+ return admission.NewForbidden(a, fmt.Errorf("no service account specified for pod %s/%s", a.GetNamespace(), pod.Name))
423+ }
424+ // Ensure the referenced service account exists
425+ serviceAccount, err := s.getServiceAccount(a.GetNamespace(), pod.Spec.ServiceAccountName)
426+ if err != nil {
427+ return admission.NewForbidden(a, fmt.Errorf("error looking up service account %s/%s: %w", a.GetNamespace(), pod.Spec.ServiceAccountName, err))
428+ }
429+ if !s.enforceMountableSecrets(serviceAccount) {
430+ return nil
431+ }
432+ // Ensure all secrets the ephemeral containers reference are allowed by the service account
433+ mountableSecrets := sets.NewString()
434+ for _, s := range serviceAccount.Secrets {
435+ mountableSecrets.Insert(s.Name)
436+ }
437+ for _, container := range pod.Spec.EphemeralContainers {
438+ for _, env := range container.Env {
439+ if env.ValueFrom != nil && env.ValueFrom.SecretKeyRef != nil {
440+ if !mountableSecrets.Has(env.ValueFrom.SecretKeyRef.Name) {
441+ return fmt.Errorf("ephemeral container %s with envVar %s referencing secret.secretName=\"%s\" is not allowed because service account %s does not reference that secret", container.Name, env.Name, env.ValueFrom.SecretKeyRef.Name, serviceAccount.Name)
442+ }
443+ }
444+ }
445+ }
446+ return nil
447+}
448+
449 func (s *Plugin) mountServiceAccountToken(serviceAccount *corev1.ServiceAccount, pod *api.Pod) {
450 // Find the volume and volume name for the ServiceAccountTokenSecret if it already exists
451 tokenVolumeName := ""
452diff --git a/plugin/pkg/admission/serviceaccount/admission_test.go b/plugin/pkg/admission/serviceaccount/admission_test.go
453index ca43abf9c3f..f5359253985 100644
454--- a/plugin/pkg/admission/serviceaccount/admission_test.go
455+++ b/plugin/pkg/admission/serviceaccount/admission_test.go
456@@ -545,6 +545,34 @@ func TestAllowsReferencedSecret(t *testing.T) {
457 if err := admissiontesting.WithReinvocationTesting(t, admit).Admit(context.TODO(), attrs, nil); err != nil {
458 t.Errorf("Unexpected error: %v", err)
459 }
460+
461+ pod2 = &api.Pod{
462+ Spec: api.PodSpec{
463+ ServiceAccountName: DefaultServiceAccountName,
464+ EphemeralContainers: []api.EphemeralContainer{
465+ {
466+ EphemeralContainerCommon: api.EphemeralContainerCommon{
467+ Name: "container-2",
468+ Env: []api.EnvVar{
469+ {
470+ Name: "env-1",
471+ ValueFrom: &api.EnvVarSource{
472+ SecretKeyRef: &api.SecretKeySelector{
473+ LocalObjectReference: api.LocalObjectReference{Name: "foo"},
474+ },
475+ },
476+ },
477+ },
478+ },
479+ },
480+ },
481+ },
482+ }
483+ // validate enforces restrictions on secret mounts when operation==create and subresource=='' or operation==update and subresource==ephemeralcontainers"
484+ attrs = admission.NewAttributesRecord(pod2, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "ephemeralcontainers", admission.Update, &metav1.UpdateOptions{}, false, nil)
485+ if err := admit.Validate(context.TODO(), attrs, nil); err != nil {
486+ t.Errorf("Unexpected error: %v", err)
487+ }
488 }
489
490 func TestRejectsUnreferencedSecretVolumes(t *testing.T) {
491@@ -622,6 +650,66 @@ func TestRejectsUnreferencedSecretVolumes(t *testing.T) {
492 if err := admissiontesting.WithReinvocationTesting(t, admit).Admit(context.TODO(), attrs, nil); err == nil || !strings.Contains(err.Error(), "with envVar") {
493 t.Errorf("Unexpected error: %v", err)
494 }
495+
496+ pod2 = &api.Pod{
497+ Spec: api.PodSpec{
498+ ServiceAccountName: DefaultServiceAccountName,
499+ InitContainers: []api.Container{
500+ {
501+ Name: "container-1",
502+ Env: []api.EnvVar{
503+ {
504+ Name: "env-1",
505+ ValueFrom: &api.EnvVarSource{
506+ SecretKeyRef: &api.SecretKeySelector{
507+ LocalObjectReference: api.LocalObjectReference{Name: "foo"},
508+ },
509+ },
510+ },
511+ },
512+ },
513+ },
514+ },
515+ }
516+ attrs = admission.NewAttributesRecord(pod2, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Update, &metav1.UpdateOptions{}, false, nil)
517+ if err := admissiontesting.WithReinvocationTesting(t, admit).Admit(context.TODO(), attrs, nil); err != nil {
518+ t.Errorf("admit only enforces restrictions on secret mounts when operation==create. Unexpected error: %v", err)
519+ }
520+ attrs = admission.NewAttributesRecord(pod2, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil)
521+ if err := admit.Validate(context.TODO(), attrs, nil); err == nil || !strings.Contains(err.Error(), "with envVar") {
522+ t.Errorf("validate only enforces restrictions on secret mounts when operation==create and subresource==''. Unexpected error: %v", err)
523+ }
524+
525+ pod2 = &api.Pod{
526+ Spec: api.PodSpec{
527+ ServiceAccountName: DefaultServiceAccountName,
528+ EphemeralContainers: []api.EphemeralContainer{
529+ {
530+ EphemeralContainerCommon: api.EphemeralContainerCommon{
531+ Name: "container-2",
532+ Env: []api.EnvVar{
533+ {
534+ Name: "env-1",
535+ ValueFrom: &api.EnvVarSource{
536+ SecretKeyRef: &api.SecretKeySelector{
537+ LocalObjectReference: api.LocalObjectReference{Name: "foo"},
538+ },
539+ },
540+ },
541+ },
542+ },
543+ },
544+ },
545+ },
546+ }
547+ attrs = admission.NewAttributesRecord(pod2, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Update, &metav1.UpdateOptions{}, false, nil)
548+ if err := admissiontesting.WithReinvocationTesting(t, admit).Admit(context.TODO(), attrs, nil); err != nil {
549+ t.Errorf("admit only enforces restrictions on secret mounts when operation==create and subresource==''. Unexpected error: %v", err)
550+ }
551+ attrs = admission.NewAttributesRecord(pod2, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "ephemeralcontainers", admission.Update, &metav1.UpdateOptions{}, false, nil)
552+ if err := admit.Validate(context.TODO(), attrs, nil); err == nil || !strings.Contains(err.Error(), "with envVar") {
553+ t.Errorf("validate enforces restrictions on secret mounts when operation==update and subresource==ephemeralcontainers. Unexpected error: %v", err)
554+ }
555 }
556
557 func TestAllowUnreferencedSecretVolumesForPermissiveSAs(t *testing.T) {
558--
5592.40.0
diff --git a/recipes-containers/kubernetes/kubernetes_git.bb b/recipes-containers/kubernetes/kubernetes_git.bb
index dc741bbf..b0c87c47 100644
--- a/recipes-containers/kubernetes/kubernetes_git.bb
+++ b/recipes-containers/kubernetes/kubernetes_git.bb
@@ -31,6 +31,7 @@ SRC_URI:append = " \
31 file://0001-build-golang.sh-convert-remaining-go-calls-to-use.patch;patchdir=src/import \ 31 file://0001-build-golang.sh-convert-remaining-go-calls-to-use.patch;patchdir=src/import \
32 file://0001-Makefile.generated_files-Fix-race-issue-for-installi.patch;patchdir=src/import \ 32 file://0001-Makefile.generated_files-Fix-race-issue-for-installi.patch;patchdir=src/import \
33 file://CVE-2023-2431.patch;patchdir=src/import \ 33 file://CVE-2023-2431.patch;patchdir=src/import \
34 file://CVE-2023-2727-CVE-2023-2728.patch;patchdir=src/import \
34 file://cni-containerd-net.conflist \ 35 file://cni-containerd-net.conflist \
35 file://k8s-init \ 36 file://k8s-init \
36 file://99-kubernetes.conf \ 37 file://99-kubernetes.conf \