diff options
Diffstat (limited to 'recipes-containers')
| -rw-r--r-- | recipes-containers/kubernetes/kubernetes/CVE-2024-3177.patch | 237 | ||||
| -rw-r--r-- | recipes-containers/kubernetes/kubernetes_git.bb | 1 |
2 files changed, 238 insertions, 0 deletions
diff --git a/recipes-containers/kubernetes/kubernetes/CVE-2024-3177.patch b/recipes-containers/kubernetes/kubernetes/CVE-2024-3177.patch new file mode 100644 index 00000000..20b2ea8a --- /dev/null +++ b/recipes-containers/kubernetes/kubernetes/CVE-2024-3177.patch | |||
| @@ -0,0 +1,237 @@ | |||
| 1 | From 3f0922513d235d8bdebe79f0d07da769c04211b8 Mon Sep 17 00:00:00 2001 | ||
| 2 | From: Rita Zhang <rita.z.zhang@gmail.com> | ||
| 3 | Date: Mon, 25 Mar 2024 10:33:41 -0700 | ||
| 4 | Subject: [PATCH] Add envFrom to serviceaccount admission plugin | ||
| 5 | |||
| 6 | Signed-off-by: Rita Zhang <rita.z.zhang@gmail.com> | ||
| 7 | |||
| 8 | Upstream-Status: Backport [https://github.com/kubernetes/kubernetes/pull/124325/commits/3f0922513d235d8bdebe79f0d07da769c04211b8] | ||
| 9 | CVE: CVE-2024-3177 | ||
| 10 | Signed-off-by: Ashish Sharma <asharma@mvista.com> | ||
| 11 | |||
| 12 | .../pkg/admission/serviceaccount/admission.go | 21 +++ | ||
| 13 | .../serviceaccount/admission_test.go | 122 ++++++++++++++++-- | ||
| 14 | 2 files changed, 132 insertions(+), 11 deletions(-) | ||
| 15 | |||
| 16 | diff --git a/plugin/pkg/admission/serviceaccount/admission.go b/plugin/pkg/admission/serviceaccount/admission.go | ||
| 17 | index c844a051c24b..3f4338128e53 100644 | ||
| 18 | --- a/plugin/pkg/admission/serviceaccount/admission.go | ||
| 19 | +++ b/plugin/pkg/admission/serviceaccount/admission.go | ||
| 20 | @@ -337,6 +337,13 @@ func (s *Plugin) limitSecretReferences(serviceAccount *corev1.ServiceAccount, po | ||
| 21 | } | ||
| 22 | } | ||
| 23 | } | ||
| 24 | + for _, envFrom := range container.EnvFrom { | ||
| 25 | + if envFrom.SecretRef != nil { | ||
| 26 | + if !mountableSecrets.Has(envFrom.SecretRef.Name) { | ||
| 27 | + return fmt.Errorf("init container %s with envFrom referencing secret.secretName=\"%s\" is not allowed because service account %s does not reference that secret", container.Name, envFrom.SecretRef.Name, serviceAccount.Name) | ||
| 28 | + } | ||
| 29 | + } | ||
| 30 | + } | ||
| 31 | } | ||
| 32 | |||
| 33 | for _, container := range pod.Spec.Containers { | ||
| 34 | @@ -347,6 +354,13 @@ func (s *Plugin) limitSecretReferences(serviceAccount *corev1.ServiceAccount, po | ||
| 35 | } | ||
| 36 | } | ||
| 37 | } | ||
| 38 | + for _, envFrom := range container.EnvFrom { | ||
| 39 | + if envFrom.SecretRef != nil { | ||
| 40 | + if !mountableSecrets.Has(envFrom.SecretRef.Name) { | ||
| 41 | + return fmt.Errorf("container %s with envFrom referencing secret.secretName=\"%s\" is not allowed because service account %s does not reference that secret", container.Name, envFrom.SecretRef.Name, serviceAccount.Name) | ||
| 42 | + } | ||
| 43 | + } | ||
| 44 | + } | ||
| 45 | } | ||
| 46 | |||
| 47 | // limit pull secret references as well | ||
| 48 | @@ -388,6 +402,13 @@ func (s *Plugin) limitEphemeralContainerSecretReferences(pod *api.Pod, a admissi | ||
| 49 | } | ||
| 50 | } | ||
| 51 | } | ||
| 52 | + for _, envFrom := range container.EnvFrom { | ||
| 53 | + if envFrom.SecretRef != nil { | ||
| 54 | + if !mountableSecrets.Has(envFrom.SecretRef.Name) { | ||
| 55 | + return fmt.Errorf("ephemeral container %s with envFrom referencing secret.secretName=\"%s\" is not allowed because service account %s does not reference that secret", container.Name, envFrom.SecretRef.Name, serviceAccount.Name) | ||
| 56 | + } | ||
| 57 | + } | ||
| 58 | + } | ||
| 59 | } | ||
| 60 | return nil | ||
| 61 | } | ||
| 62 | diff --git a/plugin/pkg/admission/serviceaccount/admission_test.go b/plugin/pkg/admission/serviceaccount/admission_test.go | ||
| 63 | index bf15f870d75a..4dba6cd8b13e 100644 | ||
| 64 | --- a/plugin/pkg/admission/serviceaccount/admission_test.go | ||
| 65 | +++ b/plugin/pkg/admission/serviceaccount/admission_test.go | ||
| 66 | @@ -521,6 +521,25 @@ func TestAllowsReferencedSecret(t *testing.T) { | ||
| 67 | t.Errorf("Unexpected error: %v", err) | ||
| 68 | } | ||
| 69 | |||
| 70 | + pod2 = &api.Pod{ | ||
| 71 | + Spec: api.PodSpec{ | ||
| 72 | + Containers: []api.Container{ | ||
| 73 | + { | ||
| 74 | + Name: "container-1", | ||
| 75 | + EnvFrom: []api.EnvFromSource{ | ||
| 76 | + { | ||
| 77 | + SecretRef: &api.SecretEnvSource{ | ||
| 78 | + LocalObjectReference: api.LocalObjectReference{ | ||
| 79 | + Name: "foo"}}}}, | ||
| 80 | + }, | ||
| 81 | + }, | ||
| 82 | + }, | ||
| 83 | + } | ||
| 84 | + attrs = admission.NewAttributesRecord(pod2, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil) | ||
| 85 | + if err := admissiontesting.WithReinvocationTesting(t, admit).Admit(context.TODO(), attrs, nil); err != nil { | ||
| 86 | + t.Errorf("Unexpected error: %v", err) | ||
| 87 | + } | ||
| 88 | + | ||
| 89 | pod2 = &api.Pod{ | ||
| 90 | Spec: api.PodSpec{ | ||
| 91 | InitContainers: []api.Container{ | ||
| 92 | @@ -545,6 +564,25 @@ func TestAllowsReferencedSecret(t *testing.T) { | ||
| 93 | t.Errorf("Unexpected error: %v", err) | ||
| 94 | } | ||
| 95 | |||
| 96 | + pod2 = &api.Pod{ | ||
| 97 | + Spec: api.PodSpec{ | ||
| 98 | + InitContainers: []api.Container{ | ||
| 99 | + { | ||
| 100 | + Name: "container-1", | ||
| 101 | + EnvFrom: []api.EnvFromSource{ | ||
| 102 | + { | ||
| 103 | + SecretRef: &api.SecretEnvSource{ | ||
| 104 | + LocalObjectReference: api.LocalObjectReference{ | ||
| 105 | + Name: "foo"}}}}, | ||
| 106 | + }, | ||
| 107 | + }, | ||
| 108 | + }, | ||
| 109 | + } | ||
| 110 | + attrs = admission.NewAttributesRecord(pod2, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil) | ||
| 111 | + if err := admissiontesting.WithReinvocationTesting(t, admit).Admit(context.TODO(), attrs, nil); err != nil { | ||
| 112 | + t.Errorf("Unexpected error: %v", err) | ||
| 113 | + } | ||
| 114 | + | ||
| 115 | pod2 = &api.Pod{ | ||
| 116 | Spec: api.PodSpec{ | ||
| 117 | ServiceAccountName: DefaultServiceAccountName, | ||
| 118 | @@ -572,6 +610,28 @@ func TestAllowsReferencedSecret(t *testing.T) { | ||
| 119 | if err := admit.Validate(context.TODO(), attrs, nil); err != nil { | ||
| 120 | t.Errorf("Unexpected error: %v", err) | ||
| 121 | } | ||
| 122 | + | ||
| 123 | + pod2 = &api.Pod{ | ||
| 124 | + Spec: api.PodSpec{ | ||
| 125 | + ServiceAccountName: DefaultServiceAccountName, | ||
| 126 | + EphemeralContainers: []api.EphemeralContainer{ | ||
| 127 | + { | ||
| 128 | + EphemeralContainerCommon: api.EphemeralContainerCommon{ | ||
| 129 | + Name: "container-2", | ||
| 130 | + EnvFrom: []api.EnvFromSource{{ | ||
| 131 | + SecretRef: &api.SecretEnvSource{ | ||
| 132 | + LocalObjectReference: api.LocalObjectReference{ | ||
| 133 | + Name: "foo"}}}}, | ||
| 134 | + }, | ||
| 135 | + }, | ||
| 136 | + }, | ||
| 137 | + }, | ||
| 138 | + } | ||
| 139 | + // validate enforces restrictions on secret mounts when operation==update and subresource==ephemeralcontainers" | ||
| 140 | + attrs = admission.NewAttributesRecord(pod2, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "ephemeralcontainers", admission.Update, &metav1.UpdateOptions{}, false, nil) | ||
| 141 | + if err := admit.Validate(context.TODO(), attrs, nil); err != nil { | ||
| 142 | + t.Errorf("Unexpected error: %v", err) | ||
| 143 | + } | ||
| 144 | } | ||
| 145 | |||
| 146 | func TestRejectsUnreferencedSecretVolumes(t *testing.T) { | ||
| 147 | @@ -628,25 +688,20 @@ func TestRejectsUnreferencedSecretVolumes(t *testing.T) { | ||
| 148 | |||
| 149 | pod2 = &api.Pod{ | ||
| 150 | Spec: api.PodSpec{ | ||
| 151 | - InitContainers: []api.Container{ | ||
| 152 | + Containers: []api.Container{ | ||
| 153 | { | ||
| 154 | Name: "container-1", | ||
| 155 | - Env: []api.EnvVar{ | ||
| 156 | + EnvFrom: []api.EnvFromSource{ | ||
| 157 | { | ||
| 158 | - Name: "env-1", | ||
| 159 | - ValueFrom: &api.EnvVarSource{ | ||
| 160 | - SecretKeyRef: &api.SecretKeySelector{ | ||
| 161 | - LocalObjectReference: api.LocalObjectReference{Name: "foo"}, | ||
| 162 | - }, | ||
| 163 | - }, | ||
| 164 | - }, | ||
| 165 | - }, | ||
| 166 | + SecretRef: &api.SecretEnvSource{ | ||
| 167 | + LocalObjectReference: api.LocalObjectReference{ | ||
| 168 | + Name: "foo"}}}}, | ||
| 169 | }, | ||
| 170 | }, | ||
| 171 | }, | ||
| 172 | } | ||
| 173 | attrs = admission.NewAttributesRecord(pod2, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil) | ||
| 174 | - if err := admissiontesting.WithReinvocationTesting(t, admit).Admit(context.TODO(), attrs, nil); err == nil || !strings.Contains(err.Error(), "with envVar") { | ||
| 175 | + if err := admissiontesting.WithReinvocationTesting(t, admit).Admit(context.TODO(), attrs, nil); err == nil || !strings.Contains(err.Error(), "with envFrom") { | ||
| 176 | t.Errorf("Unexpected error: %v", err) | ||
| 177 | } | ||
| 178 | |||
| 179 | @@ -679,6 +734,30 @@ func TestRejectsUnreferencedSecretVolumes(t *testing.T) { | ||
| 180 | t.Errorf("validate only enforces restrictions on secret mounts when operation==create and subresource==''. Unexpected error: %v", err) | ||
| 181 | } | ||
| 182 | |||
| 183 | + pod2 = &api.Pod{ | ||
| 184 | + Spec: api.PodSpec{ | ||
| 185 | + ServiceAccountName: DefaultServiceAccountName, | ||
| 186 | + InitContainers: []api.Container{ | ||
| 187 | + { | ||
| 188 | + Name: "container-1", | ||
| 189 | + EnvFrom: []api.EnvFromSource{ | ||
| 190 | + { | ||
| 191 | + SecretRef: &api.SecretEnvSource{ | ||
| 192 | + LocalObjectReference: api.LocalObjectReference{ | ||
| 193 | + Name: "foo"}}}}, | ||
| 194 | + }, | ||
| 195 | + }, | ||
| 196 | + }, | ||
| 197 | + } | ||
| 198 | + attrs = admission.NewAttributesRecord(pod2, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Update, &metav1.UpdateOptions{}, false, nil) | ||
| 199 | + if err := admissiontesting.WithReinvocationTesting(t, admit).Admit(context.TODO(), attrs, nil); err != nil { | ||
| 200 | + t.Errorf("admit only enforces restrictions on secret mounts when operation==create. Unexpected error: %v", err) | ||
| 201 | + } | ||
| 202 | + attrs = admission.NewAttributesRecord(pod2, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil) | ||
| 203 | + if err := admit.Validate(context.TODO(), attrs, nil); err == nil || !strings.Contains(err.Error(), "with envFrom") { | ||
| 204 | + t.Errorf("validate only enforces restrictions on secret mounts when operation==create and subresource==''. Unexpected error: %v", err) | ||
| 205 | + } | ||
| 206 | + | ||
| 207 | pod2 = &api.Pod{ | ||
| 208 | Spec: api.PodSpec{ | ||
| 209 | ServiceAccountName: DefaultServiceAccountName, | ||
| 210 | @@ -709,6 +788,27 @@ func TestRejectsUnreferencedSecretVolumes(t *testing.T) { | ||
| 211 | if err := admit.Validate(context.TODO(), attrs, nil); err == nil || !strings.Contains(err.Error(), "with envVar") { | ||
| 212 | t.Errorf("validate enforces restrictions on secret mounts when operation==update and subresource==ephemeralcontainers. Unexpected error: %v", err) | ||
| 213 | } | ||
| 214 | + | ||
| 215 | + pod2 = &api.Pod{ | ||
| 216 | + Spec: api.PodSpec{ | ||
| 217 | + ServiceAccountName: DefaultServiceAccountName, | ||
| 218 | + EphemeralContainers: []api.EphemeralContainer{ | ||
| 219 | + { | ||
| 220 | + EphemeralContainerCommon: api.EphemeralContainerCommon{ | ||
| 221 | + Name: "container-2", | ||
| 222 | + EnvFrom: []api.EnvFromSource{{ | ||
| 223 | + SecretRef: &api.SecretEnvSource{ | ||
| 224 | + LocalObjectReference: api.LocalObjectReference{ | ||
| 225 | + Name: "foo"}}}}, | ||
| 226 | + }, | ||
| 227 | + }, | ||
| 228 | + }, | ||
| 229 | + }, | ||
| 230 | + } | ||
| 231 | + attrs = admission.NewAttributesRecord(pod2, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "ephemeralcontainers", admission.Update, &metav1.UpdateOptions{}, false, nil) | ||
| 232 | + if err := admit.Validate(context.TODO(), attrs, nil); err == nil || !strings.Contains(err.Error(), "with envFrom") { | ||
| 233 | + t.Errorf("validate enforces restrictions on secret mounts when operation==update and subresource==ephemeralcontainers. Unexpected error: %v", err) | ||
| 234 | + } | ||
| 235 | } | ||
| 236 | |||
| 237 | func TestAllowUnreferencedSecretVolumesForPermissiveSAs(t *testing.T) { | ||
diff --git a/recipes-containers/kubernetes/kubernetes_git.bb b/recipes-containers/kubernetes/kubernetes_git.bb index b0c87c47..78d1cd2a 100644 --- a/recipes-containers/kubernetes/kubernetes_git.bb +++ b/recipes-containers/kubernetes/kubernetes_git.bb | |||
| @@ -35,6 +35,7 @@ SRC_URI:append = " \ | |||
| 35 | file://cni-containerd-net.conflist \ | 35 | file://cni-containerd-net.conflist \ |
| 36 | file://k8s-init \ | 36 | file://k8s-init \ |
| 37 | file://99-kubernetes.conf \ | 37 | file://99-kubernetes.conf \ |
| 38 | file://CVE-2024-3177.patch \ | ||
| 38 | " | 39 | " |
| 39 | 40 | ||
| 40 | DEPENDS += "rsync-native \ | 41 | DEPENDS += "rsync-native \ |
