From ea32811cbdac352834002828b283ca154836e889 Mon Sep 17 00:00:00 2001 From: "m.nabokikh" Date: Tue, 31 Mar 2020 21:42:04 +0400 Subject: [PATCH] Fix service account names with a dot This fix provides the ability to mount service account tokens to pods. The core problem is the volumeName option can't contain any dots. --- .../pkg/admission/serviceaccount/admission.go | 5 +- .../serviceaccount/admission_test.go | 79 +++++++++++++++++++ 2 files changed, 82 insertions(+), 2 deletions(-) diff --git a/plugin/pkg/admission/serviceaccount/admission.go b/plugin/pkg/admission/serviceaccount/admission.go index 1a9448e7b94..4fd478cfd2e 100644 --- a/plugin/pkg/admission/serviceaccount/admission.go +++ b/plugin/pkg/admission/serviceaccount/admission.go @@ -467,9 +467,10 @@ func (s *Plugin) mountServiceAccountToken(serviceAccount *corev1.ServiceAccount, tokenVolumeName = s.generateName(ServiceAccountVolumeName + "-") } else { // Try naming the volume the same as the serviceAccountToken, and uniquify if needed - tokenVolumeName = serviceAccountToken + // Replace dots because volumeMountName can't contain it + tokenVolumeName = strings.Replace(serviceAccountToken, ".", "-", -1) if allVolumeNames.Has(tokenVolumeName) { - tokenVolumeName = s.generateName(fmt.Sprintf("%s-", serviceAccountToken)) + tokenVolumeName = s.generateName(fmt.Sprintf("%s-", tokenVolumeName)) } } } diff --git a/plugin/pkg/admission/serviceaccount/admission_test.go b/plugin/pkg/admission/serviceaccount/admission_test.go index a8e90b94089..6f8fb4a1dc0 100644 --- a/plugin/pkg/admission/serviceaccount/admission_test.go +++ b/plugin/pkg/admission/serviceaccount/admission_test.go @@ -1121,6 +1121,85 @@ func TestAutomountIsBackwardsCompatible(t *testing.T) { t.Fatalf("Expected\n\t%#v\ngot\n\t%#v", expectedVolumeMount, pod.Spec.Containers[0].VolumeMounts[0]) } } +func TestServiceAccountNameWithDotMount(t *testing.T) { + ns := "myns" + tokenName := "token.name-123" + serviceAccountName := "token.name" + serviceAccountUID := "12345" + + expectedVolume := api.Volume{ + Name: "token-name-123", + VolumeSource: api.VolumeSource{ + Secret: &api.SecretVolumeSource{ + SecretName: "token.name-123", + }, + }, + } + expectedVolumeMount := api.VolumeMount{ + Name: "token-name-123", + ReadOnly: true, + MountPath: DefaultAPITokenMountPath, + } + + admit := NewServiceAccount() + informerFactory := informers.NewSharedInformerFactory(nil, controller.NoResyncPeriodFunc()) + admit.SetExternalKubeInformerFactory(informerFactory) + admit.MountServiceAccountToken = true + admit.RequireAPIToken = true + + informerFactory.Core().V1().ServiceAccounts().Informer().GetStore().Add(&corev1.ServiceAccount{ + ObjectMeta: metav1.ObjectMeta{ + Name: serviceAccountName, + Namespace: ns, + UID: types.UID(serviceAccountUID), + }, + Secrets: []corev1.ObjectReference{ + {Name: tokenName}, + }, + }) + + informerFactory.Core().V1().Secrets().Informer().GetStore().Add(&corev1.Secret{ + ObjectMeta: metav1.ObjectMeta{ + Name: tokenName, + Namespace: ns, + Annotations: map[string]string{ + corev1.ServiceAccountNameKey: serviceAccountName, + corev1.ServiceAccountUIDKey: serviceAccountUID, + }, + }, + Type: corev1.SecretTypeServiceAccountToken, + Data: map[string][]byte{ + api.ServiceAccountTokenKey: []byte("token-data"), + }, + }) + + pod := &api.Pod{ + Spec: api.PodSpec{ + ServiceAccountName: serviceAccountName, + Containers: []api.Container{ + {Name: "container-1"}, + }, + }, + } + + attrs := admission.NewAttributesRecord(pod, nil, api.Kind("Pod").WithVersion("version"), ns, "myname", api.Resource("pods").WithVersion("version"), "", admission.Create, &metav1.CreateOptions{}, false, nil) + if err := admissiontesting.WithReinvocationTesting(t, admit).Admit(context.TODO(), attrs, nil); err != nil { + t.Fatal(err) + } + + if len(pod.Spec.Volumes) != 1 { + t.Fatalf("Expected 1 volume, got %d", len(pod.Spec.Volumes)) + } + if !reflect.DeepEqual(expectedVolume, pod.Spec.Volumes[0]) { + t.Fatalf("Expected\n\t%#v\ngot\n\t%#v", expectedVolume, pod.Spec.Volumes[0]) + } + if len(pod.Spec.Containers[0].VolumeMounts) != 1 { + t.Fatalf("Expected 1 volume mount, got %d", len(pod.Spec.Containers[0].VolumeMounts)) + } + if !reflect.DeepEqual(expectedVolumeMount, pod.Spec.Containers[0].VolumeMounts[0]) { + t.Fatalf("Expected\n\t%#v\ngot\n\t%#v", expectedVolumeMount, pod.Spec.Containers[0].VolumeMounts[0]) + } +} func testGenerateName(n string) string { return n + "abc123"