diff --git a/pkg/apis/core/validation/validation.go b/pkg/apis/core/validation/validation.go index ea8d0be34d3..74c09ad3d44 100644 --- a/pkg/apis/core/validation/validation.go +++ b/pkg/apis/core/validation/validation.go @@ -2913,6 +2913,20 @@ func ValidatePod(pod *core.Pod) field.ErrorList { // this was done to preserve backwards compatibility specPath := field.NewPath("spec") + if pod.Spec.ServiceAccountName == "" { + for vi, volume := range pod.Spec.Volumes { + path := specPath.Child("volumes").Index(vi).Child("projected") + if volume.Projected != nil { + for si, source := range volume.Projected.Sources { + saPath := path.Child("sources").Index(si).Child("serviceAccountToken") + if source.ServiceAccountToken != nil { + allErrs = append(allErrs, field.Forbidden(saPath, "must not be specified when serviceAccountName is not set")) + } + } + } + } + } + allErrs = append(allErrs, validateContainersOnlyForPod(pod.Spec.Containers, specPath.Child("containers"))...) allErrs = append(allErrs, validateContainersOnlyForPod(pod.Spec.InitContainers, specPath.Child("initContainers"))...) diff --git a/pkg/apis/core/validation/validation_test.go b/pkg/apis/core/validation/validation_test.go index 9b376426d4b..beeb77089ad 100644 --- a/pkg/apis/core/validation/validation_test.go +++ b/pkg/apis/core/validation/validation_test.go @@ -7670,6 +7670,35 @@ func TestValidatePod(t *testing.T) { }, }, }, + "serviceaccount token projected volume with no serviceaccount name specified": { + expectedError: "must not be specified when serviceAccountName is not set", + spec: core.Pod{ + ObjectMeta: metav1.ObjectMeta{Name: "123", Namespace: "ns"}, + Spec: core.PodSpec{ + Containers: []core.Container{{Name: "ctr", Image: "image", ImagePullPolicy: "IfNotPresent", TerminationMessagePolicy: "File"}}, + RestartPolicy: core.RestartPolicyAlways, + DNSPolicy: core.DNSClusterFirst, + Volumes: []core.Volume{ + { + Name: "projected-volume", + VolumeSource: core.VolumeSource{ + Projected: &core.ProjectedVolumeSource{ + Sources: []core.VolumeProjection{ + { + ServiceAccountToken: &core.ServiceAccountTokenProjection{ + Audience: "foo-audience", + ExpirationSeconds: 6000, + Path: "foo-path", + }, + }, + }, + }, + }, + }, + }, + }, + }, + }, } for k, v := range errorCases { if errs := ValidatePod(&v.spec); len(errs) == 0 {