diff --git a/api/openapi-spec/swagger.json b/api/openapi-spec/swagger.json index 823e0a31de6..459b0069c48 100644 --- a/api/openapi-spec/swagger.json +++ b/api/openapi-spec/swagger.json @@ -11303,7 +11303,7 @@ "description": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata" }, "secrets": { - "description": "Secrets is a list of the secrets in the same namespace that pods running using this ServiceAccount are allowed to use. Pods are only limited to this list if this service account has a \"kubernetes.io/enforce-mountable-secrets\" annotation set to \"true\". This field should not be used to find auto-generated service account token secrets for use outside of pods. Instead, tokens can be requested directly using the TokenRequest API, or service account token secrets can be manually created. More info: https://kubernetes.io/docs/concepts/configuration/secret", + "description": "Secrets is a list of the secrets in the same namespace that pods running using this ServiceAccount are allowed to use. Pods are only limited to this list if this service account has a \"kubernetes.io/enforce-mountable-secrets\" annotation set to \"true\". The \"kubernetes.io/enforce-mountable-secrets\" annotation is deprecated since v1.32. Prefer separate namespaces to isolate access to mounted secrets. This field should not be used to find auto-generated service account token secrets for use outside of pods. Instead, tokens can be requested directly using the TokenRequest API, or service account token secrets can be manually created. More info: https://kubernetes.io/docs/concepts/configuration/secret", "items": { "$ref": "#/definitions/io.k8s.api.core.v1.ObjectReference" }, diff --git a/api/openapi-spec/v3/api__v1_openapi.json b/api/openapi-spec/v3/api__v1_openapi.json index a2bbed968e0..d97ff9864ab 100644 --- a/api/openapi-spec/v3/api__v1_openapi.json +++ b/api/openapi-spec/v3/api__v1_openapi.json @@ -7436,7 +7436,7 @@ "description": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata" }, "secrets": { - "description": "Secrets is a list of the secrets in the same namespace that pods running using this ServiceAccount are allowed to use. Pods are only limited to this list if this service account has a \"kubernetes.io/enforce-mountable-secrets\" annotation set to \"true\". This field should not be used to find auto-generated service account token secrets for use outside of pods. Instead, tokens can be requested directly using the TokenRequest API, or service account token secrets can be manually created. More info: https://kubernetes.io/docs/concepts/configuration/secret", + "description": "Secrets is a list of the secrets in the same namespace that pods running using this ServiceAccount are allowed to use. Pods are only limited to this list if this service account has a \"kubernetes.io/enforce-mountable-secrets\" annotation set to \"true\". The \"kubernetes.io/enforce-mountable-secrets\" annotation is deprecated since v1.32. Prefer separate namespaces to isolate access to mounted secrets. This field should not be used to find auto-generated service account token secrets for use outside of pods. Instead, tokens can be requested directly using the TokenRequest API, or service account token secrets can be manually created. More info: https://kubernetes.io/docs/concepts/configuration/secret", "items": { "allOf": [ { diff --git a/pkg/apis/core/types.go b/pkg/apis/core/types.go index bfad02c78f8..b624561c0d9 100644 --- a/pkg/apis/core/types.go +++ b/pkg/apis/core/types.go @@ -4822,6 +4822,8 @@ type ServiceAccount struct { // Secrets is a list of the secrets in the same namespace that pods running using this ServiceAccount are allowed to use. // Pods are only limited to this list if this service account has a "kubernetes.io/enforce-mountable-secrets" annotation set to "true". + // The "kubernetes.io/enforce-mountable-secrets" annotation is deprecated since v1.32. + // Prefer separate namespaces to isolate access to mounted secrets. // This field should not be used to find auto-generated service account token secrets for use outside of pods. // Instead, tokens can be requested directly using the TokenRequest API, or service account token secrets can be manually created. Secrets []ObjectReference diff --git a/pkg/generated/openapi/zz_generated.openapi.go b/pkg/generated/openapi/zz_generated.openapi.go index 590abdc1981..cc80465dd43 100644 --- a/pkg/generated/openapi/zz_generated.openapi.go +++ b/pkg/generated/openapi/zz_generated.openapi.go @@ -30736,7 +30736,7 @@ func schema_k8sio_api_core_v1_ServiceAccount(ref common.ReferenceCallback) commo }, }, SchemaProps: spec.SchemaProps{ - Description: "Secrets is a list of the secrets in the same namespace that pods running using this ServiceAccount are allowed to use. Pods are only limited to this list if this service account has a \"kubernetes.io/enforce-mountable-secrets\" annotation set to \"true\". This field should not be used to find auto-generated service account token secrets for use outside of pods. Instead, tokens can be requested directly using the TokenRequest API, or service account token secrets can be manually created. More info: https://kubernetes.io/docs/concepts/configuration/secret", + Description: "Secrets is a list of the secrets in the same namespace that pods running using this ServiceAccount are allowed to use. Pods are only limited to this list if this service account has a \"kubernetes.io/enforce-mountable-secrets\" annotation set to \"true\". The \"kubernetes.io/enforce-mountable-secrets\" annotation is deprecated since v1.32. Prefer separate namespaces to isolate access to mounted secrets. This field should not be used to find auto-generated service account token secrets for use outside of pods. Instead, tokens can be requested directly using the TokenRequest API, or service account token secrets can be manually created. More info: https://kubernetes.io/docs/concepts/configuration/secret", Type: []string{"array"}, Items: &spec.SchemaOrArray{ Schema: &spec.Schema{ diff --git a/pkg/registry/core/serviceaccount/strategy.go b/pkg/registry/core/serviceaccount/strategy.go index cad6da26fb1..5f28ae74994 100644 --- a/pkg/registry/core/serviceaccount/strategy.go +++ b/pkg/registry/core/serviceaccount/strategy.go @@ -18,6 +18,7 @@ package serviceaccount import ( "context" + "fmt" "k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/util/validation/field" @@ -25,6 +26,7 @@ import ( "k8s.io/kubernetes/pkg/api/legacyscheme" api "k8s.io/kubernetes/pkg/apis/core" "k8s.io/kubernetes/pkg/apis/core/validation" + sa "k8s.io/kubernetes/plugin/pkg/admission/serviceaccount" ) // strategy implements behavior for ServiceAccount objects @@ -50,7 +52,9 @@ func (strategy) Validate(ctx context.Context, obj runtime.Object) field.ErrorLis } // WarningsOnCreate returns warnings for the creation of the given object. -func (strategy) WarningsOnCreate(ctx context.Context, obj runtime.Object) []string { return nil } +func (strategy) WarningsOnCreate(ctx context.Context, obj runtime.Object) []string { + return warnIfHasEnforceMountableSecretsAnnotation(obj.(*api.ServiceAccount), nil) +} // Canonicalize normalizes the object after validation. func (strategy) Canonicalize(obj runtime.Object) { @@ -76,9 +80,24 @@ func (strategy) ValidateUpdate(ctx context.Context, obj, old runtime.Object) fie // WarningsOnUpdate returns warnings for the given update. func (strategy) WarningsOnUpdate(ctx context.Context, obj, old runtime.Object) []string { - return nil + return warnIfHasEnforceMountableSecretsAnnotation(obj.(*api.ServiceAccount), old.(*api.ServiceAccount)) } func (strategy) AllowUnconditionalUpdate() bool { return true } + +func warnIfHasEnforceMountableSecretsAnnotation(serviceAccount, oldServiceAccount *api.ServiceAccount) []string { + if oldServiceAccount != nil { + _, ok := oldServiceAccount.Annotations[sa.EnforceMountableSecretsAnnotation] + if ok { + // skip warning if request isn't newly setting the annotation + return nil + } + } + _, ok := serviceAccount.Annotations[sa.EnforceMountableSecretsAnnotation] + if ok { + return []string{fmt.Sprintf("metadata.annotations[%s]: deprecated in v1.32+; prefer separate namespaces to isolate access to mounted secrets", sa.EnforceMountableSecretsAnnotation)} + } + return nil +} diff --git a/pkg/registry/core/serviceaccount/strategy_test.go b/pkg/registry/core/serviceaccount/strategy_test.go new file mode 100644 index 00000000000..5089eae6ca8 --- /dev/null +++ b/pkg/registry/core/serviceaccount/strategy_test.go @@ -0,0 +1,63 @@ +/* +Copyright 2024 The Kubernetes Authors. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package serviceaccount + +import ( + "context" + "fmt" + "testing" + + api "k8s.io/kubernetes/pkg/apis/core" + sa "k8s.io/kubernetes/plugin/pkg/admission/serviceaccount" +) + +func TestWarningsOnCreate(t *testing.T) { + ctx := context.TODO() + serviceAccount := &api.ServiceAccount{} + + warnings := Strategy.WarningsOnCreate(ctx, serviceAccount) + if len(warnings) != 0 { + t.Errorf("expected no warnings, got %v", warnings) + } + serviceAccount.Annotations = map[string]string{sa.EnforceMountableSecretsAnnotation: "true"} + warnings = Strategy.WarningsOnCreate(ctx, serviceAccount) + if len(warnings) != 1 || warnings[0] != fmt.Sprintf("metadata.annotations[%s]: deprecated in v1.32+; prefer separate namespaces to isolate access to mounted secrets", sa.EnforceMountableSecretsAnnotation) { + t.Errorf("expected warnings, got %v", warnings) + } +} + +func TestWarningsOnUpdate(t *testing.T) { + ctx := context.TODO() + serviceAccount := &api.ServiceAccount{} + oldServiceAccount := &api.ServiceAccount{} + + warnings := Strategy.WarningsOnUpdate(ctx, serviceAccount, oldServiceAccount) + if len(warnings) != 0 { + t.Errorf("expected no warnings, got %v", warnings) + } + serviceAccount.Annotations = map[string]string{sa.EnforceMountableSecretsAnnotation: "true"} + warnings = Strategy.WarningsOnUpdate(ctx, serviceAccount, oldServiceAccount) + if len(warnings) != 1 || warnings[0] != fmt.Sprintf("metadata.annotations[%s]: deprecated in v1.32+; prefer separate namespaces to isolate access to mounted secrets", sa.EnforceMountableSecretsAnnotation) { + t.Errorf("expected warnings, got %v", warnings) + } + + oldServiceAccount.Annotations = map[string]string{sa.EnforceMountableSecretsAnnotation: "true"} + warnings = Strategy.WarningsOnUpdate(ctx, serviceAccount, oldServiceAccount) + if len(warnings) != 0 { + t.Errorf("expected no warnings if request isn't newly setting the annotation, got %v", warnings) + } +} diff --git a/staging/src/k8s.io/api/core/v1/generated.proto b/staging/src/k8s.io/api/core/v1/generated.proto index 268ac96f7d4..b3f3ffbda11 100644 --- a/staging/src/k8s.io/api/core/v1/generated.proto +++ b/staging/src/k8s.io/api/core/v1/generated.proto @@ -5649,6 +5649,8 @@ message ServiceAccount { // Secrets is a list of the secrets in the same namespace that pods running using this ServiceAccount are allowed to use. // Pods are only limited to this list if this service account has a "kubernetes.io/enforce-mountable-secrets" annotation set to "true". + // The "kubernetes.io/enforce-mountable-secrets" annotation is deprecated since v1.32. + // Prefer separate namespaces to isolate access to mounted secrets. // This field should not be used to find auto-generated service account token secrets for use outside of pods. // Instead, tokens can be requested directly using the TokenRequest API, or service account token secrets can be manually created. // More info: https://kubernetes.io/docs/concepts/configuration/secret diff --git a/staging/src/k8s.io/api/core/v1/types.go b/staging/src/k8s.io/api/core/v1/types.go index 36bc2692614..492b49b3911 100644 --- a/staging/src/k8s.io/api/core/v1/types.go +++ b/staging/src/k8s.io/api/core/v1/types.go @@ -5736,6 +5736,8 @@ type ServiceAccount struct { // Secrets is a list of the secrets in the same namespace that pods running using this ServiceAccount are allowed to use. // Pods are only limited to this list if this service account has a "kubernetes.io/enforce-mountable-secrets" annotation set to "true". + // The "kubernetes.io/enforce-mountable-secrets" annotation is deprecated since v1.32. + // Prefer separate namespaces to isolate access to mounted secrets. // This field should not be used to find auto-generated service account token secrets for use outside of pods. // Instead, tokens can be requested directly using the TokenRequest API, or service account token secrets can be manually created. // More info: https://kubernetes.io/docs/concepts/configuration/secret diff --git a/staging/src/k8s.io/api/core/v1/types_swagger_doc_generated.go b/staging/src/k8s.io/api/core/v1/types_swagger_doc_generated.go index 6134e5dc7ee..5aa15255db7 100644 --- a/staging/src/k8s.io/api/core/v1/types_swagger_doc_generated.go +++ b/staging/src/k8s.io/api/core/v1/types_swagger_doc_generated.go @@ -2392,7 +2392,7 @@ func (Service) SwaggerDoc() map[string]string { var map_ServiceAccount = map[string]string{ "": "ServiceAccount binds together: * a name, understood by users, and perhaps by peripheral systems, for an identity * a principal that can be authenticated and authorized * a set of secrets", "metadata": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata", - "secrets": "Secrets is a list of the secrets in the same namespace that pods running using this ServiceAccount are allowed to use. Pods are only limited to this list if this service account has a \"kubernetes.io/enforce-mountable-secrets\" annotation set to \"true\". This field should not be used to find auto-generated service account token secrets for use outside of pods. Instead, tokens can be requested directly using the TokenRequest API, or service account token secrets can be manually created. More info: https://kubernetes.io/docs/concepts/configuration/secret", + "secrets": "Secrets is a list of the secrets in the same namespace that pods running using this ServiceAccount are allowed to use. Pods are only limited to this list if this service account has a \"kubernetes.io/enforce-mountable-secrets\" annotation set to \"true\". The \"kubernetes.io/enforce-mountable-secrets\" annotation is deprecated since v1.32. Prefer separate namespaces to isolate access to mounted secrets. This field should not be used to find auto-generated service account token secrets for use outside of pods. Instead, tokens can be requested directly using the TokenRequest API, or service account token secrets can be manually created. More info: https://kubernetes.io/docs/concepts/configuration/secret", "imagePullSecrets": "ImagePullSecrets is a list of references to secrets in the same namespace to use for pulling any images in pods that reference this ServiceAccount. ImagePullSecrets are distinct from Secrets because Secrets can be mounted in the pod, but ImagePullSecrets are only accessed by the kubelet. More info: https://kubernetes.io/docs/concepts/containers/images/#specifying-imagepullsecrets-on-a-pod", "automountServiceAccountToken": "AutomountServiceAccountToken indicates whether pods running as this service account should have an API token automatically mounted. Can be overridden at the pod level.", } diff --git a/staging/src/k8s.io/cli-runtime/artifacts/openapi/swagger-with-shared-parameters.json b/staging/src/k8s.io/cli-runtime/artifacts/openapi/swagger-with-shared-parameters.json index 15d819bccdb..13877fb7a3c 100644 --- a/staging/src/k8s.io/cli-runtime/artifacts/openapi/swagger-with-shared-parameters.json +++ b/staging/src/k8s.io/cli-runtime/artifacts/openapi/swagger-with-shared-parameters.json @@ -9630,7 +9630,7 @@ "description": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata" }, "secrets": { - "description": "Secrets is a list of the secrets in the same namespace that pods running using this ServiceAccount are allowed to use. Pods are only limited to this list if this service account has a \"kubernetes.io/enforce-mountable-secrets\" annotation set to \"true\". This field should not be used to find auto-generated service account token secrets for use outside of pods. Instead, tokens can be requested directly using the TokenRequest API, or service account token secrets can be manually created. More info: https://kubernetes.io/docs/concepts/configuration/secret", + "description": "Secrets is a list of the secrets in the same namespace that pods running using this ServiceAccount are allowed to use. Pods are only limited to this list if this service account has a \"kubernetes.io/enforce-mountable-secrets\" annotation set to \"true\". The \"kubernetes.io/enforce-mountable-secrets\" annotation is deprecated since v1.32. Prefer separate namespaces to isolate access to mounted secrets. This field should not be used to find auto-generated service account token secrets for use outside of pods. Instead, tokens can be requested directly using the TokenRequest API, or service account token secrets can be manually created. More info: https://kubernetes.io/docs/concepts/configuration/secret", "items": { "$ref": "#/definitions/io.k8s.api.core.v1.ObjectReference" }, diff --git a/staging/src/k8s.io/cli-runtime/artifacts/openapi/swagger.json b/staging/src/k8s.io/cli-runtime/artifacts/openapi/swagger.json index 9ad11fe1f75..eb286e2cd2c 100644 --- a/staging/src/k8s.io/cli-runtime/artifacts/openapi/swagger.json +++ b/staging/src/k8s.io/cli-runtime/artifacts/openapi/swagger.json @@ -10019,7 +10019,7 @@ "description": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata" }, "secrets": { - "description": "Secrets is a list of the secrets in the same namespace that pods running using this ServiceAccount are allowed to use. Pods are only limited to this list if this service account has a \"kubernetes.io/enforce-mountable-secrets\" annotation set to \"true\". This field should not be used to find auto-generated service account token secrets for use outside of pods. Instead, tokens can be requested directly using the TokenRequest API, or service account token secrets can be manually created. More info: https://kubernetes.io/docs/concepts/configuration/secret", + "description": "Secrets is a list of the secrets in the same namespace that pods running using this ServiceAccount are allowed to use. Pods are only limited to this list if this service account has a \"kubernetes.io/enforce-mountable-secrets\" annotation set to \"true\". The \"kubernetes.io/enforce-mountable-secrets\" annotation is deprecated since v1.32. Prefer separate namespaces to isolate access to mounted secrets. This field should not be used to find auto-generated service account token secrets for use outside of pods. Instead, tokens can be requested directly using the TokenRequest API, or service account token secrets can be manually created. More info: https://kubernetes.io/docs/concepts/configuration/secret", "items": { "$ref": "#/definitions/io.k8s.api.core.v1.ObjectReference" }, diff --git a/staging/src/k8s.io/client-go/openapi/openapitest/testdata/api__v1_openapi.json b/staging/src/k8s.io/client-go/openapi/openapitest/testdata/api__v1_openapi.json index 4637e313d99..c71267015b8 100644 --- a/staging/src/k8s.io/client-go/openapi/openapitest/testdata/api__v1_openapi.json +++ b/staging/src/k8s.io/client-go/openapi/openapitest/testdata/api__v1_openapi.json @@ -6851,7 +6851,7 @@ "description": "Standard object's metadata. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata" }, "secrets": { - "description": "Secrets is a list of the secrets in the same namespace that pods running using this ServiceAccount are allowed to use. Pods are only limited to this list if this service account has a \"kubernetes.io/enforce-mountable-secrets\" annotation set to \"true\". This field should not be used to find auto-generated service account token secrets for use outside of pods. Instead, tokens can be requested directly using the TokenRequest API, or service account token secrets can be manually created. More info: https://kubernetes.io/docs/concepts/configuration/secret", + "description": "Secrets is a list of the secrets in the same namespace that pods running using this ServiceAccount are allowed to use. Pods are only limited to this list if this service account has a \"kubernetes.io/enforce-mountable-secrets\" annotation set to \"true\". The \"kubernetes.io/enforce-mountable-secrets\" annotation is deprecated since v1.32. Prefer separate namespaces to isolate access to mounted secrets. This field should not be used to find auto-generated service account token secrets for use outside of pods. Instead, tokens can be requested directly using the TokenRequest API, or service account token secrets can be manually created. More info: https://kubernetes.io/docs/concepts/configuration/secret", "items": { "allOf": [ { diff --git a/staging/src/k8s.io/kubectl/testdata/openapi/v3/api/v1.json b/staging/src/k8s.io/kubectl/testdata/openapi/v3/api/v1.json index 4c5f13d8d9f..5ec9adf5da0 100644 --- a/staging/src/k8s.io/kubectl/testdata/openapi/v3/api/v1.json +++ b/staging/src/k8s.io/kubectl/testdata/openapi/v3/api/v1.json @@ -26671,7 +26671,7 @@ ] }, "secrets": { - "description": "Secrets is a list of the secrets in the same namespace that pods running using this ServiceAccount are allowed to use. Pods are only limited to this list if this service account has a \"kubernetes.io/enforce-mountable-secrets\" annotation set to \"true\". This field should not be used to find auto-generated service account token secrets for use outside of pods. Instead, tokens can be requested directly using the TokenRequest API, or service account token secrets can be manually created. More info: https://kubernetes.io/docs/concepts/configuration/secret", + "description": "Secrets is a list of the secrets in the same namespace that pods running using this ServiceAccount are allowed to use. Pods are only limited to this list if this service account has a \"kubernetes.io/enforce-mountable-secrets\" annotation set to \"true\". The \"kubernetes.io/enforce-mountable-secrets\" annotation is deprecated since v1.32. Prefer separate namespaces to isolate access to mounted secrets. This field should not be used to find auto-generated service account token secrets for use outside of pods. Instead, tokens can be requested directly using the TokenRequest API, or service account token secrets can be manually created. More info: https://kubernetes.io/docs/concepts/configuration/secret", "type": "array", "items": { "default": {}, diff --git a/test/integration/auth/svcaccttoken_test.go b/test/integration/auth/svcaccttoken_test.go index 0c31f285a60..ab8a6438549 100644 --- a/test/integration/auth/svcaccttoken_test.go +++ b/test/integration/auth/svcaccttoken_test.go @@ -22,6 +22,7 @@ import ( "encoding/base64" "encoding/json" "fmt" + "io" "net/http" "net/url" @@ -52,6 +53,7 @@ import ( "k8s.io/kubernetes/pkg/controlplane" "k8s.io/kubernetes/pkg/features" "k8s.io/kubernetes/pkg/serviceaccount" + svcacct "k8s.io/kubernetes/plugin/pkg/admission/serviceaccount" "k8s.io/kubernetes/test/integration/framework" "k8s.io/kubernetes/test/utils/ktesting" "k8s.io/utils/ptr" @@ -68,6 +70,58 @@ AwEHoUQDQgAEH6cuzP8XuD5wal6wf9M6xDljTOPLX2i8uIp/C/ASqiIGUeeKQtX0 tokenExpirationSeconds = 60*60 + 7 ) +func TestServiceAccountAnnotationDeprecation(t *testing.T) { + tCtx := ktesting.Init(t) + // Start the server + kubeClient, kubeConfig, tearDownFn := framework.StartTestServer(tCtx, t, framework.TestServerSetup{}) + defer tearDownFn() + + ns := framework.CreateNamespaceOrDie(kubeClient, "myns", t) + defer framework.DeleteNamespaceOrDie(kubeClient, ns, t) + + warningHandler := &recordingWarningHandler{} + + configWithWarningHandler := rest.CopyConfig(kubeConfig) + configWithWarningHandler.WarningHandler = warningHandler + cs, err := clientset.NewForConfig(configWithWarningHandler) + if err != nil { + t.Fatalf("err: %v", err) + } + var ( + saWithAnnotation = &v1.ServiceAccount{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-svcacct", + Namespace: ns.Name, + }, + } + pod = &v1.Pod{ + ObjectMeta: metav1.ObjectMeta{ + Name: "test-pod", + Namespace: saWithAnnotation.Namespace, + }, + Spec: v1.PodSpec{ + ServiceAccountName: saWithAnnotation.Name, + Containers: []v1.Container{{Name: "test-container", Image: "nginx"}}, + }, + } + ) + + t.Run("service account with deprecated annotation", func(t *testing.T) { + warningHandler.clear() + // test warning is emitted when the service account has this deprecated annotation + saWithAnnotation.Annotations = map[string]string{svcacct.EnforceMountableSecretsAnnotation: "true"} + _, delSvcAcct := createDeleteSvcAcct(t, cs, saWithAnnotation) + defer delSvcAcct() + warningHandler.assertEqual(t, []string{fmt.Sprintf("metadata.annotations[%s]: deprecated in v1.32+; prefer separate namespaces to isolate access to mounted secrets", svcacct.EnforceMountableSecretsAnnotation)}) + + warningHandler.clear() + // no warning when a pod is created with a service account that has this deprecated annotation + _, delPod := createDeletePod(t, cs, pod) + defer delPod() + warningHandler.assertEqual(t, nil) + }) +} + func TestServiceAccountTokenCreate(t *testing.T) { const iss = "https://foo.bar.example.com" aud := authenticator.Audiences{"api"}