From d9f311063616f11d4444bccfc47755c06b19f66b Mon Sep 17 00:00:00 2001 From: Jiawei Huang Date: Tue, 28 Jun 2022 13:31:40 -0700 Subject: [PATCH] Update UTs for SecurityContext changes --- pkg/render/apiserver_test.go | 8 +- pkg/render/aws-securitygroup-setup_test.go | 85 +++++++++++++++++++ pkg/render/dex_test.go | 9 ++ pkg/render/guardian_test.go | 7 ++ pkg/render/intrusion_detection_test.go | 9 ++ .../esmetrics/elasticsearch_metrics_test.go | 7 ++ pkg/render/logstorage_test.go | 7 ++ pkg/render/manager_test.go | 54 ++++++++---- pkg/render/monitor/monitor_test.go | 6 ++ 9 files changed, 175 insertions(+), 17 deletions(-) create mode 100644 pkg/render/aws-securitygroup-setup_test.go diff --git a/pkg/render/apiserver_test.go b/pkg/render/apiserver_test.go index 5437ce20fd..131b5f2a35 100644 --- a/pkg/render/apiserver_test.go +++ b/pkg/render/apiserver_test.go @@ -194,7 +194,7 @@ var _ = Describe("API server rendering tests (Calico Enterprise)", func() { Expect(d.Spec.Template.Spec.Tolerations).To(ConsistOf(rmeta.TolerateMaster)) Expect(d.Spec.Template.Spec.ImagePullSecrets).To(BeEmpty()) - Expect(len(d.Spec.Template.Spec.Containers)).To(Equal(2)) + Expect(d.Spec.Template.Spec.Containers).To(HaveLen(2)) Expect(d.Spec.Template.Spec.Containers[0].Name).To(Equal("tigera-apiserver")) Expect(d.Spec.Template.Spec.Containers[0].Image).To(Equal( fmt.Sprintf("testregistry.com/%s:%s", components.ComponentAPIServer.Image, components.ComponentAPIServer.Version), @@ -267,6 +267,12 @@ var _ = Describe("API server rendering tests (Calico Enterprise)", func() { Expect(d.Spec.Template.Spec.Containers[1].LivenessProbe.InitialDelaySeconds).To(BeEquivalentTo(90)) Expect(d.Spec.Template.Spec.Containers[1].LivenessProbe.PeriodSeconds).To(BeEquivalentTo(10)) + Expect(*d.Spec.Template.Spec.Containers[1].SecurityContext.AllowPrivilegeEscalation).To(BeFalse()) + Expect(*d.Spec.Template.Spec.Containers[1].SecurityContext.Privileged).To(BeFalse()) + Expect(*d.Spec.Template.Spec.Containers[1].SecurityContext.RunAsGroup).To(BeEquivalentTo(0)) + Expect(*d.Spec.Template.Spec.Containers[1].SecurityContext.RunAsNonRoot).To(BeTrue()) + Expect(*d.Spec.Template.Spec.Containers[1].SecurityContext.RunAsUser).To(BeEquivalentTo(1001)) + Expect(len(d.Spec.Template.Spec.Volumes)).To(Equal(3)) Expect(d.Spec.Template.Spec.Volumes[0].Name).To(Equal("tigera-apiserver-certs")) diff --git a/pkg/render/aws-securitygroup-setup_test.go b/pkg/render/aws-securitygroup-setup_test.go new file mode 100644 index 0000000000..5789b42362 --- /dev/null +++ b/pkg/render/aws-securitygroup-setup_test.go @@ -0,0 +1,85 @@ +// Copyright (c) 2022 Tigera, Inc. All rights reserved. + +// 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 render + +import ( + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + + batchv1 "k8s.io/api/batch/v1" + corev1 "k8s.io/api/core/v1" + + operatorv1 "github.com/tigera/operator/api/v1" + rtest "github.com/tigera/operator/pkg/render/common/test" +) + +var _ = Describe("AWS SecurityGroup Setup rendering tests", func() { + var cfg *AWSSGSetupConfiguration + + BeforeEach(func() { + cfg = &AWSSGSetupConfiguration{ + PullSecrets: []corev1.LocalObjectReference{}, + Installation: &operatorv1.InstallationSpec{}, + } + }) + + It("should render AWS SecurityGroup Setup resources", func() { + component, err := AWSSecurityGroupSetup(cfg) + Expect(err).NotTo(HaveOccurred()) + Expect(component.ResolveImages(nil)).NotTo(HaveOccurred()) + + toCreate, toDelete := component.Objects() + + expectedResources := []struct { + name string + ns string + group string + version string + kind string + }{ + {"tigera-aws-security-group-setup", "tigera-operator", "", "v1", "ServiceAccount"}, + {"tigera-aws-security-group-setup", "kube-system", "rbac.authorization.k8s.io", "v1", "Role"}, + {"tigera-aws-security-group-setup", "kube-system", "rbac.authorization.k8s.io", "v1", "RoleBinding"}, + {"aws-security-group-setup-1", "tigera-operator", "batch", "v1", "Job"}, + } + + Expect(len(toCreate)).To(Equal(len(expectedResources))) + + for i, expectedRes := range expectedResources { + obj := toCreate[i] + rtest.ExpectResource(obj, expectedRes.name, expectedRes.ns, expectedRes.group, expectedRes.version, expectedRes.kind) + } + + Expect(toDelete).To(BeNil()) + }) + + It("should render Setup Job specs correctly", func() { + component, err := AWSSecurityGroupSetup(cfg) + Expect(err).NotTo(HaveOccurred()) + Expect(component.ResolveImages(nil)).NotTo(HaveOccurred()) + toCreate, _ := component.Objects() + + job, ok := rtest.GetResource(toCreate, "aws-security-group-setup-1", "tigera-operator", "batch", "v1", "Job").(*batchv1.Job) + Expect(ok).To(BeTrue()) + + Expect(job.Spec.Template.Spec.Containers).To(HaveLen(1)) + + Expect(*job.Spec.Template.Spec.Containers[0].SecurityContext.AllowPrivilegeEscalation).To(BeFalse()) + Expect(*job.Spec.Template.Spec.Containers[0].SecurityContext.Privileged).To(BeFalse()) + Expect(*job.Spec.Template.Spec.Containers[0].SecurityContext.RunAsGroup).To(BeEquivalentTo(0)) + Expect(*job.Spec.Template.Spec.Containers[0].SecurityContext.RunAsNonRoot).To(BeTrue()) + Expect(*job.Spec.Template.Spec.Containers[0].SecurityContext.RunAsUser).To(BeEquivalentTo(1001)) + }) +}) diff --git a/pkg/render/dex_test.go b/pkg/render/dex_test.go index 767e655956..bbc8f97dca 100644 --- a/pkg/render/dex_test.go +++ b/pkg/render/dex_test.go @@ -146,6 +146,15 @@ var _ = Describe("dex rendering tests", func() { rtest.ExpectResource(resources[i], expectedRes.name, expectedRes.ns, expectedRes.group, expectedRes.version, expectedRes.kind) } Expect(len(resources)).To(Equal(len(expectedResources))) + + d := rtest.GetResource(resources, "tigera-dex", "tigera-dex", "apps", "v1", "Deployment").(*appsv1.Deployment) + + Expect(d.Spec.Template.Spec.Containers).To(HaveLen(1)) + Expect(*d.Spec.Template.Spec.Containers[0].SecurityContext.AllowPrivilegeEscalation).To(BeFalse()) + Expect(*d.Spec.Template.Spec.Containers[0].SecurityContext.Privileged).To(BeFalse()) + Expect(*d.Spec.Template.Spec.Containers[0].SecurityContext.RunAsGroup).To(BeEquivalentTo(1001)) + Expect(*d.Spec.Template.Spec.Containers[0].SecurityContext.RunAsNonRoot).To(BeTrue()) + Expect(*d.Spec.Template.Spec.Containers[0].SecurityContext.RunAsUser).To(BeEquivalentTo(1001)) }) DescribeTable("should render the cluster name properly in the validator", func(clusterDomain string) { diff --git a/pkg/render/guardian_test.go b/pkg/render/guardian_test.go index 748deb775f..77fa29dee2 100644 --- a/pkg/render/guardian_test.go +++ b/pkg/render/guardian_test.go @@ -113,7 +113,14 @@ var _ = Describe("Rendering tests", func() { } deployment := rtest.GetResource(resources, render.GuardianDeploymentName, render.GuardianNamespace, "apps", "v1", "Deployment").(*appsv1.Deployment) + Expect(deployment.Spec.Template.Spec.Containers).To(HaveLen(1)) Expect(deployment.Spec.Template.Spec.Containers[0].Image).Should(Equal("my-reg/tigera/guardian:" + components.ComponentGuardian.Version)) + + Expect(*deployment.Spec.Template.Spec.Containers[0].SecurityContext.AllowPrivilegeEscalation).To(BeFalse()) + Expect(*deployment.Spec.Template.Spec.Containers[0].SecurityContext.Privileged).To(BeFalse()) + Expect(*deployment.Spec.Template.Spec.Containers[0].SecurityContext.RunAsGroup).To(BeEquivalentTo(0)) + Expect(*deployment.Spec.Template.Spec.Containers[0].SecurityContext.RunAsNonRoot).To(BeTrue()) + Expect(*deployment.Spec.Template.Spec.Containers[0].SecurityContext.RunAsUser).To(BeEquivalentTo(1001)) }) It("should render controlPlaneTolerations", func() { diff --git a/pkg/render/intrusion_detection_test.go b/pkg/render/intrusion_detection_test.go index fb11d379b5..6a833fee66 100644 --- a/pkg/render/intrusion_detection_test.go +++ b/pkg/render/intrusion_detection_test.go @@ -143,17 +143,26 @@ var _ = Describe("Intrusion Detection rendering tests", func() { // Should mount ManagerTLSSecret for non-managed clusters idc := rtest.GetResource(resources, "intrusion-detection-controller", render.IntrusionDetectionNamespace, "apps", "v1", "Deployment").(*appsv1.Deployment) idji := rtest.GetResource(resources, "intrusion-detection-es-job-installer", render.IntrusionDetectionNamespace, "batch", "v1", "Job").(*batchv1.Job) + Expect(idc.Spec.Template.Spec.Containers).To(HaveLen(1)) Expect(idc.Spec.Template.Spec.Containers[0].Env).Should(ContainElements( corev1.EnvVar{Name: "ELASTIC_INDEX_SUFFIX", Value: "clusterTestName"}, )) + Expect(idji.Spec.Template.Spec.Containers).To(HaveLen(1)) Expect(idji.Spec.Template.Spec.Containers[0].Env).Should(ContainElements( corev1.EnvVar{Name: "ELASTIC_INDEX_SUFFIX", Value: "clusterTestName"}, )) Expect(idc.Spec.Template.Spec.Containers[0].VolumeMounts[0].Name).To(Equal(certificatemanagement.TrustedCertConfigMapName)) Expect(idc.Spec.Template.Spec.Containers[0].VolumeMounts[0].MountPath).To(Equal(certificatemanagement.TrustedCertVolumeMountPath)) + Expect(idc.Spec.Template.Spec.Volumes[0].Name).To(Equal(certificatemanagement.TrustedCertConfigMapName)) Expect(idc.Spec.Template.Spec.Volumes[0].ConfigMap.Name).To(Equal(certificatemanagement.TrustedCertConfigMapName)) + Expect(*idc.Spec.Template.Spec.Containers[0].SecurityContext.AllowPrivilegeEscalation).To(BeFalse()) + Expect(*idc.Spec.Template.Spec.Containers[0].SecurityContext.Privileged).To(BeFalse()) + Expect(*idc.Spec.Template.Spec.Containers[0].SecurityContext.RunAsGroup).To(BeEquivalentTo(10001)) + Expect(*idc.Spec.Template.Spec.Containers[0].SecurityContext.RunAsNonRoot).To(BeTrue()) + Expect(*idc.Spec.Template.Spec.Containers[0].SecurityContext.RunAsUser).To(BeEquivalentTo(10001)) + clusterRole := rtest.GetResource(resources, "intrusion-detection-controller", "", "rbac.authorization.k8s.io", "v1", "ClusterRole").(*rbacv1.ClusterRole) Expect(clusterRole.Rules).To(ContainElement(rbacv1.PolicyRule{ diff --git a/pkg/render/logstorage/esmetrics/elasticsearch_metrics_test.go b/pkg/render/logstorage/esmetrics/elasticsearch_metrics_test.go index 18ea79d64f..4d57247bb1 100644 --- a/pkg/render/logstorage/esmetrics/elasticsearch_metrics_test.go +++ b/pkg/render/logstorage/esmetrics/elasticsearch_metrics_test.go @@ -211,10 +211,17 @@ var _ = Describe("Elasticsearch metrics", func() { Expect(service.Spec).To(Equal(expectedService.Spec)) Expect(deploy.Annotations).To(Equal(expectedDeploy.Annotations)) Expect(deploy.Spec.Template.Spec.Volumes).To(Equal(expectedDeploy.Spec.Template.Spec.Volumes)) + Expect(deploy.Spec.Template.Spec.Containers).To(HaveLen(1)) Expect(deploy.Spec.Template.Spec.Containers[0].VolumeMounts).To(Equal(expectedDeploy.Spec.Template.Spec.Containers[0].VolumeMounts)) Expect(deploy.Spec.Template.Spec.Containers[0].Args).To(Equal(expectedDeploy.Spec.Template.Spec.Containers[0].Args)) Expect(deploy.Spec.Template.Spec.Containers[0].Env).To(Equal(expectedDeploy.Spec.Template.Spec.Containers[0].Env)) Expect(deploy.Spec.Template.Spec.Containers[0].Command).To(Equal(expectedDeploy.Spec.Template.Spec.Containers[0].Command)) + + Expect(*deploy.Spec.Template.Spec.Containers[0].SecurityContext.AllowPrivilegeEscalation).To(BeFalse()) + Expect(*deploy.Spec.Template.Spec.Containers[0].SecurityContext.Privileged).To(BeFalse()) + Expect(*deploy.Spec.Template.Spec.Containers[0].SecurityContext.RunAsGroup).To(BeEquivalentTo(10001)) + Expect(*deploy.Spec.Template.Spec.Containers[0].SecurityContext.RunAsNonRoot).To(BeTrue()) + Expect(*deploy.Spec.Template.Spec.Containers[0].SecurityContext.RunAsUser).To(BeEquivalentTo(10001)) }) It("should apply controlPlaneNodeSelector correctly", func() { diff --git a/pkg/render/logstorage_test.go b/pkg/render/logstorage_test.go index cca0c34b16..1a8dd021b1 100644 --- a/pkg/render/logstorage_test.go +++ b/pkg/render/logstorage_test.go @@ -222,6 +222,13 @@ var _ = Describe("Elasticsearch rendering tests", func() { "--enable-webhook=false", "--manage-webhook-certs=false", })) + + kb := rtest.GetResource(createResources, "tigera-secure", "tigera-kibana", "kibana.k8s.elastic.co", "v1", "Kibana") + Expect(kb).NotTo(BeNil()) + kibana := kb.(*kbv1.Kibana) + Expect(*kibana.Spec.PodTemplate.Spec.SecurityContext.RunAsGroup).To(BeEquivalentTo(10001)) + Expect(*kibana.Spec.PodTemplate.Spec.SecurityContext.RunAsNonRoot).To(BeTrue()) + Expect(*kibana.Spec.PodTemplate.Spec.SecurityContext.RunAsUser).To(BeEquivalentTo(10001)) }) It("should render an elasticsearchComponent and delete the Elasticsearch and Kibana ExternalService", func() { diff --git a/pkg/render/manager_test.go b/pkg/render/manager_test.go index cc66666c0d..e6fbd63436 100644 --- a/pkg/render/manager_test.go +++ b/pkg/render/manager_test.go @@ -85,7 +85,15 @@ var _ = Describe("Tigera Secure Manager rendering tests", func() { Expect(resources).To(HaveLen(expectedResourcesNumber)) deployment := rtest.GetResource(resources, "tigera-manager", render.ManagerNamespace, "apps", "v1", "Deployment").(*appsv1.Deployment) - Expect(len(deployment.Spec.Template.Spec.Containers)).Should(Equal(3)) + + // deployment + Expect(deployment.Spec.Template.Spec.Volumes).To(HaveLen(2)) + Expect(deployment.Spec.Template.Spec.Volumes[0].Name).To(Equal(render.ManagerTLSSecretName)) + Expect(deployment.Spec.Template.Spec.Volumes[0].Secret.SecretName).To(Equal(render.ManagerTLSSecretName)) + Expect(deployment.Spec.Template.Spec.Volumes[1].Name).To(Equal(certificatemanagement.TrustedCertConfigMapName)) + Expect(deployment.Spec.Template.Spec.Volumes[1].VolumeSource.ConfigMap.Name).To(Equal(certificatemanagement.TrustedCertConfigMapName)) + + Expect(deployment.Spec.Template.Spec.Containers).To(HaveLen(3)) manager := deployment.Spec.Template.Spec.Containers[0] esProxy := deployment.Spec.Template.Spec.Containers[1] voltron := deployment.Spec.Template.Spec.Containers[2] @@ -94,33 +102,47 @@ var _ = Describe("Tigera Secure Manager rendering tests", func() { Expect(esProxy.Image).Should(Equal(components.TigeraRegistry + "tigera/es-proxy:" + components.ComponentEsProxy.Version)) Expect(voltron.Image).Should(Equal(components.TigeraRegistry + "tigera/voltron:" + components.ComponentManagerProxy.Version)) - Expect(voltron.Env).Should(ContainElements([]corev1.EnvVar{ - {Name: "VOLTRON_QUERYSERVER_ENDPOINT", Value: "https://tigera-api.tigera-system.svc:8080"}, - {Name: "VOLTRON_QUERYSERVER_BASE_PATH", Value: "/api/v1/namespaces/tigera-system/services/https:tigera-api:8080/proxy/"}, - {Name: "VOLTRON_QUERYSERVER_CA_BUNDLE_PATH", Value: "/etc/pki/tls/certs/tigera-ca-bundle.crt"}, - }, - )) + // manager container + Expect(*manager.SecurityContext.AllowPrivilegeEscalation).To(BeFalse()) + Expect(*manager.SecurityContext.Privileged).To(BeFalse()) + Expect(*manager.SecurityContext.RunAsGroup).To(BeEquivalentTo(0)) + Expect(*manager.SecurityContext.RunAsNonRoot).To(BeTrue()) + Expect(*manager.SecurityContext.RunAsUser).To(BeEquivalentTo(999)) + // es-proxy container Expect(esProxy.Env).Should(ContainElements( corev1.EnvVar{Name: "ELASTIC_INDEX_SUFFIX", Value: "clusterTestName"}, )) - Expect(len(esProxy.VolumeMounts)).To(Equal(1)) + + Expect(esProxy.VolumeMounts).To(HaveLen(1)) Expect(esProxy.VolumeMounts[0].Name).To(Equal(certificatemanagement.TrustedCertConfigMapName)) Expect(esProxy.VolumeMounts[0].MountPath).To(Equal(certificatemanagement.TrustedCertVolumeMountPath)) - Expect(len(voltron.VolumeMounts)).To(Equal(2)) + Expect(*esProxy.SecurityContext.AllowPrivilegeEscalation).To(BeFalse()) + Expect(*esProxy.SecurityContext.Privileged).To(BeFalse()) + Expect(*esProxy.SecurityContext.RunAsGroup).To(BeEquivalentTo(0)) + Expect(*esProxy.SecurityContext.RunAsNonRoot).To(BeTrue()) + Expect(*esProxy.SecurityContext.RunAsUser).To(BeEquivalentTo(1001)) + + // voltron container + Expect(voltron.Env).To(ContainElements([]corev1.EnvVar{ + {Name: "VOLTRON_ENABLE_COMPLIANCE", Value: "true"}, + {Name: "VOLTRON_QUERYSERVER_ENDPOINT", Value: "https://tigera-api.tigera-system.svc:8080"}, + {Name: "VOLTRON_QUERYSERVER_BASE_PATH", Value: "/api/v1/namespaces/tigera-system/services/https:tigera-api:8080/proxy/"}, + {Name: "VOLTRON_QUERYSERVER_CA_BUNDLE_PATH", Value: "/etc/pki/tls/certs/tigera-ca-bundle.crt"}, + })) + + Expect(voltron.VolumeMounts).To(HaveLen(2)) Expect(voltron.VolumeMounts[0].Name).To(Equal(render.ManagerTLSSecretName)) Expect(voltron.VolumeMounts[0].MountPath).To(Equal("/manager-tls")) Expect(voltron.VolumeMounts[1].Name).To(Equal(certificatemanagement.TrustedCertConfigMapName)) Expect(voltron.VolumeMounts[1].MountPath).To(Equal(certificatemanagement.TrustedCertVolumeMountPath)) - Expect(voltron.Env).To(ContainElement(corev1.EnvVar{Name: "VOLTRON_ENABLE_COMPLIANCE", Value: "true"})) - - Expect(len(deployment.Spec.Template.Spec.Volumes)).To(Equal(2)) - Expect(deployment.Spec.Template.Spec.Volumes[0].Name).To(Equal(render.ManagerTLSSecretName)) - Expect(deployment.Spec.Template.Spec.Volumes[0].Secret.SecretName).To(Equal(render.ManagerTLSSecretName)) - Expect(deployment.Spec.Template.Spec.Volumes[1].Name).To(Equal(certificatemanagement.TrustedCertConfigMapName)) - Expect(deployment.Spec.Template.Spec.Volumes[1].VolumeSource.ConfigMap.Name).To(Equal(certificatemanagement.TrustedCertConfigMapName)) + Expect(*voltron.SecurityContext.AllowPrivilegeEscalation).To(BeFalse()) + Expect(*voltron.SecurityContext.Privileged).To(BeFalse()) + Expect(*voltron.SecurityContext.RunAsGroup).To(BeEquivalentTo(0)) + Expect(*voltron.SecurityContext.RunAsNonRoot).To(BeTrue()) + Expect(*voltron.SecurityContext.RunAsUser).To(BeEquivalentTo(1001)) }) It("should not proxy compliance if the feature is not active", func() { diff --git a/pkg/render/monitor/monitor_test.go b/pkg/render/monitor/monitor_test.go index 6d25f625c6..0828d1820b 100644 --- a/pkg/render/monitor/monitor_test.go +++ b/pkg/render/monitor/monitor_test.go @@ -141,6 +141,9 @@ var _ = Describe("monitor rendering tests", func() { Expect(*alertmanagerObj.Spec.Image).To(Equal(fmt.Sprintf("%s%s:%s", components.TigeraRegistry, alertmanagerCom.Image, alertmanagerCom.Version))) Expect(*alertmanagerObj.Spec.Replicas).To(Equal(int32(3))) Expect(alertmanagerObj.Spec.Version).To(Equal(components.ComponentCoreOSAlertmanager.Version)) + Expect(*alertmanagerObj.Spec.SecurityContext.RunAsGroup).To(BeEquivalentTo(10001)) + Expect(*alertmanagerObj.Spec.SecurityContext.RunAsNonRoot).To(BeTrue()) + Expect(*alertmanagerObj.Spec.SecurityContext.RunAsUser).To(BeEquivalentTo(10001)) // Alertmanager Service serviceObj, ok := rtest.GetResource(toCreate, "calico-node-alertmanager", common.TigeraPrometheusNamespace, "", "v1", "Service").(*corev1.Service) @@ -176,6 +179,9 @@ var _ = Describe("monitor rendering tests", func() { Expect(prometheusObj.Spec.Alerting.Alertmanagers[0].Namespace).To(Equal("tigera-prometheus")) Expect(prometheusObj.Spec.Alerting.Alertmanagers[0].Port).To(Equal(intstr.FromString("web"))) Expect(prometheusObj.Spec.Alerting.Alertmanagers[0].Scheme).To(Equal("HTTP")) + Expect(*prometheusObj.Spec.SecurityContext.RunAsGroup).To(BeEquivalentTo(10001)) + Expect(*prometheusObj.Spec.SecurityContext.RunAsNonRoot).To(BeTrue()) + Expect(*prometheusObj.Spec.SecurityContext.RunAsUser).To(BeEquivalentTo(10001)) // Prometheus ServiceAccount _, ok = rtest.GetResource(toCreate, "prometheus", common.TigeraPrometheusNamespace, "", "v1", "ServiceAccount").(*corev1.ServiceAccount)