diff --git a/pkg/api/pod/warnings.go b/pkg/api/pod/warnings.go index 8958aa51a47..b72e515cd4d 100644 --- a/pkg/api/pod/warnings.go +++ b/pkg/api/pod/warnings.go @@ -170,6 +170,60 @@ func warningsForPodSpecAndMeta(fieldPath *field.Path, podSpec *api.PodSpec, meta } } + items := sets.NewString() + for _, v := range podSpec.Volumes { + if v.Projected != nil { + for _, k := range v.Projected.Sources { + if k.ServiceAccountToken != nil { + items.Insert(k.ServiceAccountToken.Path) + } + } + } + + } + + if items.Len() > 0 { + for i, item := range podSpec.Volumes { + if item.Projected != nil { + for _, k := range item.Projected.Sources { + if k.ConfigMap != nil { + if len(k.ConfigMap.Items) > 0 { + for j, item := range k.ConfigMap.Items { + if items.Has(item.Path) { + warnings = append(warnings, fmt.Sprintf("%s: has duplicated path with ServiceAccountToken %q", fieldPath.Child("spec", "volumes").Index(i).Child("projected", "sources", "configMap").Index(j), item.Path)) + } + } + } + } + + if k.Secret != nil { + if len(k.Secret.Items) > 0 { + for j, item := range k.Secret.Items { + if items.Has(item.Path) { + warnings = append(warnings, fmt.Sprintf("%s: has duplicated path with ServiceAccountToken %q", fieldPath.Child("spec", "volumes").Index(i).Child("projected", "sources", "secrets").Index(j), item.Path)) + } + } + } + } + + if k.DownwardAPI != nil { + for j, item := range k.DownwardAPI.Items { + if items.Has(item.Path) { + warnings = append(warnings, fmt.Sprintf("%s: has duplicated path with ServiceAccountToken %q", fieldPath.Child("spec", "volumes").Index(i).Child("projected", "sources", "downwardAPI").Index(j), item.Path)) + } + } + } + + if k.ClusterTrustBundle != nil { + if items.Has(k.ClusterTrustBundle.Path) { + warnings = append(warnings, fmt.Sprintf("%s: has duplicated path with ServiceAccountToken %q", fieldPath.Child("spec", "volumes").Index(i).Child("projected", "sources", "ClusterTrustBundle"), k.ClusterTrustBundle.Path)) + } + } + } + } + } + } + // duplicate hostAliases (#91670, #58477) if len(podSpec.HostAliases) > 1 { items := sets.New[string]() diff --git a/pkg/api/pod/warnings_test.go b/pkg/api/pod/warnings_test.go index 6405977b7cb..bea4dd18114 100644 --- a/pkg/api/pod/warnings_test.go +++ b/pkg/api/pod/warnings_test.go @@ -235,6 +235,86 @@ func TestWarnings(t *testing.T) { }, expected: []string{`spec.volumes[0].rbd: deprecated in v1.28, non-functional in v1.31+`}, }, + { + name: "duplicated path in projected volumes - secret and service account token", + template: &api.PodTemplateSpec{Spec: api.PodSpec{ + Volumes: []api.Volume{ + { + Name: "t", + VolumeSource: api.VolumeSource{ + Projected: &api.ProjectedVolumeSource{ + Sources: []api.VolumeProjection{ + {Secret: &api.SecretProjection{Items: []api.KeyToPath{{Path: "/test-path", Key: "test"}}}}, + {ServiceAccountToken: &api.ServiceAccountTokenProjection{Path: "/test-path"}}, + }}, + }, + }, + }, + }}, + expected: []string{ + "spec.volumes[0].projected.sources.secrets[0]: has duplicated path with ServiceAccountToken \"/test-path\"", + }, + }, + { + name: "duplicated path in projected volumes - configMap and service account token", + template: &api.PodTemplateSpec{Spec: api.PodSpec{ + Volumes: []api.Volume{ + { + Name: "t", + VolumeSource: api.VolumeSource{ + Projected: &api.ProjectedVolumeSource{ + Sources: []api.VolumeProjection{ + {ConfigMap: &api.ConfigMapProjection{Items: []api.KeyToPath{{Path: "/test-path", Key: "test"}}}}, + {ServiceAccountToken: &api.ServiceAccountTokenProjection{Path: "/test-path"}}, + }}, + }, + }, + }, + }}, + expected: []string{ + "spec.volumes[0].projected.sources.configMap[0]: has duplicated path with ServiceAccountToken \"/test-path\"", + }, + }, + { + name: "duplicated path in projected volumes - downwardAPI and service account token", + template: &api.PodTemplateSpec{Spec: api.PodSpec{ + Volumes: []api.Volume{ + { + Name: "t", + VolumeSource: api.VolumeSource{ + Projected: &api.ProjectedVolumeSource{ + Sources: []api.VolumeProjection{ + {DownwardAPI: &api.DownwardAPIProjection{Items: []api.DownwardAPIVolumeFile{{Path: "/test-path"}}}}, + {ServiceAccountToken: &api.ServiceAccountTokenProjection{Path: "/test-path"}}, + }}, + }, + }, + }, + }}, + expected: []string{ + "spec.volumes[0].projected.sources.downwardAPI[0]: has duplicated path with ServiceAccountToken \"/test-path\"", + }, + }, + { + name: "duplicated path in projected volumes - ClusterTrustBundle and service account token", + template: &api.PodTemplateSpec{Spec: api.PodSpec{ + Volumes: []api.Volume{ + { + Name: "t", + VolumeSource: api.VolumeSource{ + Projected: &api.ProjectedVolumeSource{ + Sources: []api.VolumeProjection{ + {ClusterTrustBundle: &api.ClusterTrustBundleProjection{Path: "/test-path"}}, + {ServiceAccountToken: &api.ServiceAccountTokenProjection{Path: "/test-path"}}, + }}, + }, + }, + }, + }}, + expected: []string{ + "spec.volumes[0].projected.sources.ClusterTrustBundle: has duplicated path with ServiceAccountToken \"/test-path\"", + }, + }, { name: "duplicate hostAlias", template: &api.PodTemplateSpec{Spec: api.PodSpec{