github.com/verrazzano/verrazzano@v1.7.1/tests/e2e/security/rbac/rbac_test.go (about) 1 // Copyright (c) 2021, 2023, Oracle and/or its affiliates. 2 // Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl. 3 4 package rbac 5 6 import ( 7 "fmt" 8 "strconv" 9 "strings" 10 "time" 11 12 dump "github.com/verrazzano/verrazzano/tests/e2e/pkg/test/clusterdump" 13 14 . "github.com/onsi/ginkgo/v2" 15 . "github.com/onsi/gomega" 16 "github.com/verrazzano/verrazzano/pkg/k8sutil" 17 "github.com/verrazzano/verrazzano/tests/e2e/pkg" 18 "github.com/verrazzano/verrazzano/tests/e2e/pkg/test/framework" 19 corev1 "k8s.io/api/core/v1" 20 v1 "k8s.io/api/rbac/v1" 21 "k8s.io/apimachinery/pkg/api/errors" 22 "k8s.io/client-go/kubernetes" 23 ) 24 25 var ( 26 waitTimeout = 5 * time.Minute 27 pollingInterval = 10 * time.Second 28 ) 29 30 const ( 31 verrazzanoSystemNS = "verrazzano-system" 32 rbacTestNamespace = "rbactest" 33 v80ProjectAdmin = "ocid1.user.oc1..aaaaaaaallodotxfvg0g1antsyq3gonyyhblya66kiqjnp2kogonykvjwi19" 34 v80ProjectMonitor = "ocid1.user.oc1..aaaaaaaallodotxfvg0yank33sq3gonyghblya66kiqjnp2kogonykvjwi19" 35 verrazzanoAPI = "verrazzano-authproxy" 36 impersonateVerb = "impersonate" 37 ) 38 39 var t = framework.NewTestFramework("rbac") 40 41 var beforeSuite = t.BeforeSuiteFunc(func() { 42 t.Logs.Info("Create namespace") 43 Eventually(func() (*corev1.Namespace, error) { 44 return pkg.CreateNamespace(rbacTestNamespace, map[string]string{"verrazzano-managed": "true", "istio-injection": "enabled"}) 45 }, waitTimeout, pollingInterval).ShouldNot(BeNil()) 46 }) 47 48 var _ = BeforeSuite(beforeSuite) 49 50 var failed = false 51 var _ = t.AfterEach(func() { 52 failed = failed || CurrentSpecReport().Failed() 53 }) 54 55 var afterSuite = t.AfterSuiteFunc(func() { 56 if failed { 57 dump.ExecuteBugReport(rbacTestNamespace) 58 } 59 60 t.Logs.Info("Delete namespace") 61 Eventually(func() error { 62 return pkg.DeleteNamespace(rbacTestNamespace) 63 }, waitTimeout, pollingInterval).ShouldNot(HaveOccurred()) 64 65 Eventually(func() bool { 66 _, err := pkg.GetNamespace(rbacTestNamespace) 67 return err != nil && errors.IsNotFound(err) 68 }, waitTimeout, pollingInterval).Should(BeTrue()) 69 }) 70 71 var _ = AfterSuite(afterSuite) 72 73 var _ = t.Describe("Test RBAC Permission", Label("f:security.rbac"), func() { 74 t.Context("for verrazzano-project-admin.", func() { 75 76 t.It("Fail getting Pods in namespace rbactest", func() { 77 t.Logs.Info("Can User List Pods in NameSpace rbactest? No") 78 Eventually(func() (bool, error) { 79 allowed, reason, err := pkg.CanI(v80ProjectAdmin, rbacTestNamespace, "list", "pods") 80 t.Logs.Infof("Status: Should FAIL Authorization on user list pods: Allowed = %t, reason = %s", allowed, reason) 81 return allowed, err 82 }, waitTimeout, pollingInterval).Should(BeFalse(), "FAIL: Passed Authorization on user list pods. Timeout Expired") 83 }) 84 85 t.It("Create RoleBinding Admin for verrazzano-project-admin", func() { 86 t.Logs.Info("Create RoleBinding Admin for verrazzano-project-admin") 87 Eventually(func() error { 88 return pkg.CreateRoleBinding(v80ProjectAdmin, rbacTestNamespace, "admin-binding", "admin") 89 }, waitTimeout, pollingInterval).ShouldNot(HaveOccurred()) 90 }) 91 92 t.It("Verify RoleBinding Admin for verrazzano-project-admin", func() { 93 verifyRoleBindingExists("admin-binding") 94 }) 95 96 t.It("Succeed getting Pods in namespace rbactest", func() { 97 t.Logs.Info("Can User List Pods in NameSpace rbactest? Yes") 98 Eventually(func() (bool, error) { 99 allowed, reason, err := pkg.CanI(v80ProjectAdmin, rbacTestNamespace, "list", "pods") 100 t.Logs.Infof("Status: Should SUCCEED on user list pods in rbactest namespace: Allowed = %t, reason = %s", allowed, reason) 101 return allowed, err 102 }, waitTimeout, pollingInterval).Should(BeTrue(), "FAIL: Did Not Pass Authorization on user list pods. Timeout Expired") 103 }) 104 105 t.It("Fail getting Pods in namespace verrazzano-system", func() { 106 t.Logs.Info("Can User List Pods in NameSpace verrazzano-system? No") 107 Eventually(func() (bool, error) { 108 allowed, reason, err := pkg.CanI(v80ProjectAdmin, verrazzanoSystemNS, "list", "pods") 109 t.Logs.Infof("Status: Should FAIL on user list pods in verrazzano-system namespace: Allowed = %t, reason = %s", allowed, reason) 110 return allowed, err 111 }, waitTimeout, pollingInterval).Should(BeFalse(), "FAIL: Passed Authorization on user list pods. Timeout Expired") 112 }) 113 114 t.It("Fail create ApplicationConfiguration in namespace rbactest", func() { 115 t.Logs.Info("Can User create ApplicationConfiguration in NameSpace rbactest? No") 116 Eventually(func() (bool, error) { 117 allowed, reason, err := pkg.CanIForAPIGroup(v80ProjectAdmin, rbacTestNamespace, "create", "applicationconfigurations", "core.oam.dev") 118 t.Logs.Infof("Status: Should FAIL on user create ApplicationConfiguration: Allowed = %t, reason = %s", allowed, reason) 119 return allowed, err 120 }, waitTimeout, pollingInterval).Should(BeFalse(), "FAIL: Passed Authorization on user create ApplicationConfiguration. Timeout Expired") 121 }) 122 123 t.It("Fail list ApplicationConfiguration in namespace rbactest", func() { 124 t.Logs.Info("Can User list ApplicationConfiguration in NameSpace rbactest? No") 125 Eventually(func() (bool, error) { 126 allowed, reason, err := pkg.CanIForAPIGroup(v80ProjectAdmin, rbacTestNamespace, "list", "applicationconfigurations", "core.oam.dev") 127 t.Logs.Infof("Status: Should FAIL on user list ApplicationConfiguration: Allowed = %t, reason = %s", allowed, reason) 128 return allowed, err 129 }, waitTimeout, pollingInterval).Should(BeFalse(), "FAIL: Passed Authorization on user list ApplicationConfiguration. Timeout Expired") 130 }) 131 132 t.It("Fail create OAM Component in namespace rbactest", func() { 133 t.Logs.Info("Can User create OAM Components in NameSpace rbactest? No") 134 Eventually(func() (bool, error) { 135 allowed, reason, err := pkg.CanIForAPIGroup(v80ProjectAdmin, rbacTestNamespace, "create", "components", "core.oam.dev") 136 t.Logs.Infof("Status: Should FAIL on user create OAM Components: Allowed = %t, reason = %s", allowed, reason) 137 return allowed, err 138 }, waitTimeout, pollingInterval).Should(BeFalse(), "FAIL: Passed Authorization on user create OAM Components. Timeout Expired") 139 }) 140 141 t.It("Fail list OAM Component in namespace rbactest", func() { 142 t.Logs.Info("Can User list OAM Components in NameSpace rbactest? No") 143 Eventually(func() (bool, error) { 144 allowed, reason, err := pkg.CanIForAPIGroup(v80ProjectAdmin, rbacTestNamespace, "list", "components", "core.oam.dev") 145 t.Logs.Infof("Status: Should FAIL on user list OAM Components: Allowed = %t, reason = %s", allowed, reason) 146 return allowed, err 147 }, waitTimeout, pollingInterval).Should(BeFalse(), "FAIL: Passed Authorization on user list OAM Components. Timeout Expired") 148 }) 149 150 t.It("Create RoleBinding verrazzano-project-admin-binding for verrazzano-project-admin", func() { 151 t.Logs.Info("Create RoleBinding verrazzano-project-admin-binding for verrazzano-project-admin") 152 Eventually(func() error { 153 return pkg.CreateRoleBinding(v80ProjectAdmin, rbacTestNamespace, "verrazzano-project-admin-binding", "verrazzano-project-admin") 154 }, waitTimeout, pollingInterval).ShouldNot(HaveOccurred()) 155 }) 156 157 t.It("Verify RoleBinding verrazzano-project-admin-binding for verrazzano-project-admin", func() { 158 verifyRoleBindingExists("verrazzano-project-admin-binding") 159 }) 160 161 t.It("Succeed create ApplicationConfiguration in namespace rbactest", func() { 162 t.Logs.Info("Can User create ApplicationConfiguration in NameSpace rbactest? Yes") 163 Eventually(func() (bool, error) { 164 allowed, reason, err := pkg.CanIForAPIGroup(v80ProjectAdmin, rbacTestNamespace, "create", "applicationconfigurations", "core.oam.dev") 165 t.Logs.Infof("Status: Should SUCCEED on user create ApplicationConfiguration: Allowed = %t, reason = %s", allowed, reason) 166 return allowed, err 167 }, waitTimeout, pollingInterval).Should(BeTrue(), "FAIL: Did Not Pass Authorization on user create ApplicationConfiguration. Timeout Expired") 168 }) 169 170 t.It("Succeed list ApplicationConfiguration in namespace rbactest", func() { 171 t.Logs.Info("Can User list ApplicationConfiguration in NameSpace rbactest? Yes") 172 Eventually(func() (bool, error) { 173 allowed, reason, err := pkg.CanIForAPIGroup(v80ProjectAdmin, rbacTestNamespace, "list", "applicationconfigurations", "core.oam.dev") 174 t.Logs.Infof("Status: Should SUCCEED on user list ApplicationConfiguration: Allowed = %t, reason = %s", allowed, reason) 175 return allowed, err 176 }, waitTimeout, pollingInterval).Should(BeTrue(), "FAIL: Did Not Pass Authorization on user list ApplicationConfiguration. Timeout Expired") 177 }) 178 179 t.It("Succeed create OAM Components in namespace rbactest", func() { 180 t.Logs.Info("Can User create OAM Components in NameSpace rbactest? Yes") 181 Eventually(func() (bool, error) { 182 allowed, reason, err := pkg.CanIForAPIGroup(v80ProjectAdmin, rbacTestNamespace, "create", "components", "core.oam.dev") 183 t.Logs.Infof("Status: Should SUCCEED on user create OAM Components: Allowed = %t, reason = %s", allowed, reason) 184 return allowed, err 185 }, waitTimeout, pollingInterval).Should(BeTrue(), "FAIL: Did Not Pass Authorization on user create OAM Components. Timeout Expired") 186 }) 187 188 t.It("Succeed list OAM Components in namespace rbactest", func() { 189 t.Logs.Info("Can User list OAM Components in NameSpace rbactest? Yes") 190 Eventually(func() (bool, error) { 191 allowed, reason, err := pkg.CanIForAPIGroup(v80ProjectAdmin, rbacTestNamespace, "list", "components", "core.oam.dev") 192 t.Logs.Infof("Status: Should SUCCEED on user list OAM Components: Allowed = %t, reason = %s", allowed, reason) 193 return allowed, err 194 }, waitTimeout, pollingInterval).Should(BeTrue(), "FAIL: Did Not Pass Authorization on user list OAM Components. Timeout Expired") 195 }) 196 197 }) 198 }) 199 200 var _ = t.Describe("Test RBAC Permission", Label("f:security.rbac"), func() { 201 t.Context("for verrazzano-project-monitor.", func() { 202 203 t.It("Fail getting Pods in namespace rbactest", func() { 204 t.Logs.Info("Can User List Pods in NameSpace rbactest? No") 205 Eventually(func() (bool, error) { 206 allowed, reason, err := pkg.CanI(v80ProjectMonitor, rbacTestNamespace, "list", "pods") 207 t.Logs.Infof("Status: Should FAIL on user list pods in rbactest namespace: Allowed = %t, reason = %s", allowed, reason) 208 return allowed, err 209 }, waitTimeout, pollingInterval).Should(BeFalse(), "FAIL: Passed Authorization on user list pods. Timeout Expired") 210 }) 211 212 t.It("Create RoleBinding Admin for verrazzano-project-monitor", func() { 213 t.Logs.Info("Create RoleBinding Admin for verrazzano-project-monitor") 214 Eventually(func() error { 215 return pkg.CreateRoleBinding(v80ProjectMonitor, rbacTestNamespace, "monitor-binding", "admin") 216 }, waitTimeout, pollingInterval).ShouldNot(HaveOccurred()) 217 }) 218 219 t.It("Verify RoleBinding monitor-binding for verrazzano-project-monitor", func() { 220 verifyRoleBindingExists("monitor-binding") 221 }) 222 223 t.It("Succeed getting Pods in namespace rbactest", func() { 224 t.Logs.Info("Can User List Pods in NameSpace rbactest? Yes") 225 Eventually(func() (bool, error) { 226 allowed, reason, err := pkg.CanI(v80ProjectMonitor, rbacTestNamespace, "list", "pods") 227 t.Logs.Infof("Status: Should SUCCEED on user list pods in rbactest namespace: Allowed = %t, reason = %s", allowed, reason) 228 return allowed, err 229 }, waitTimeout, pollingInterval).Should(BeTrue(), "FAIL: Did Not Pass Authorization on user list pods. Timeout Expired") 230 }) 231 232 t.It("Fail getting Pods in namespace verrazzano-system", func() { 233 t.Logs.Info("Can User List Pods in NameSpace verrazzano-system? No") 234 Eventually(func() (bool, error) { 235 allowed, reason, err := pkg.CanI(v80ProjectMonitor, verrazzanoSystemNS, "list", "pods") 236 t.Logs.Infof("Status: Should FAIL on user list pods in verrazzano-system namespace: Allowed = %t, reason = %s", allowed, reason) 237 return allowed, err 238 }, waitTimeout, pollingInterval).Should(BeFalse(), "FAIL: Passed Authorization on user list pods. Timeout Expired") 239 }) 240 241 t.It("Fail create ApplicationConfiguration in namespace rbactest", func() { 242 t.Logs.Info("Can User create ApplicationConfiguration in NameSpace rbactest? No") 243 Eventually(func() (bool, error) { 244 allowed, reason, err := pkg.CanIForAPIGroup(v80ProjectMonitor, rbacTestNamespace, "create", "applicationconfigurations", "core.oam.dev") 245 t.Logs.Infof("Status: Should FAIL on user create ApplicationConfiguration. Allowed = %t, reason = %s", allowed, reason) 246 return allowed, err 247 }, waitTimeout, pollingInterval).Should(BeFalse(), "FAIL: Passed Authorization on user create ApplicationConfiguration. Timeout Expired") 248 }) 249 250 t.It("Fail list ApplicationConfiguration in namespace rbactest", func() { 251 t.Logs.Info("Can User list ApplicationConfiguration in NameSpace rbactest? No") 252 Eventually(func() (bool, error) { 253 allowed, reason, err := pkg.CanIForAPIGroup(v80ProjectMonitor, rbacTestNamespace, "list", "applicationconfigurations", "core.oam.dev") 254 t.Logs.Infof("Status: Should FAIL on user list ApplicationConfiguration. Allowed = %t, reason = %s", allowed, reason) 255 return allowed, err 256 }, waitTimeout, pollingInterval).Should(BeFalse(), "FAIL: Passed Authorization on user list ApplicationConfiguration. Timeout Expired") 257 }) 258 259 t.It("Fail create OAM Component in namespace rbactest", func() { 260 t.Logs.Info("Can User create OAM Components in NameSpace rbactest? No") 261 Eventually(func() (bool, error) { 262 allowed, reason, err := pkg.CanIForAPIGroup(v80ProjectMonitor, rbacTestNamespace, "create", "components", "core.oam.dev") 263 t.Logs.Infof("Status: Should FAIL on user create OAM Components. Allowed = %t, reason = %s", allowed, reason) 264 return allowed, err 265 }, waitTimeout, pollingInterval).Should(BeFalse(), "FAIL: Passed Authorization on user create OAM Components. Timeout Expired") 266 }) 267 268 t.It("Fail list OAM Component in namespace rbactest", func() { 269 t.Logs.Info("Can User list OAM Components in NameSpace rbactest? No") 270 Eventually(func() (bool, error) { 271 allowed, reason, err := pkg.CanIForAPIGroup(v80ProjectMonitor, rbacTestNamespace, "list", "components", "core.oam.dev") 272 t.Logs.Infof("Status: Should FAIL on user list OAM Components. Allowed = %t, reason = %s", allowed, reason) 273 return allowed, err 274 }, waitTimeout, pollingInterval).Should(BeFalse(), "FAIL: Passed Authorization on user list OAM Components. Timeout Expired") 275 }) 276 277 t.It("Create RoleBinding verrazzano-project-monitor-binding for cluster role verrazzano-project-monitor", func() { 278 t.Logs.Info("Create RoleBinding verrazzano-project-monitor-binding for verrazzano-project-monitor") 279 Eventually(func() error { 280 return pkg.CreateRoleBinding(v80ProjectMonitor, rbacTestNamespace, "verrazzano-project-monitor-binding", "verrazzano-project-monitor") 281 }, waitTimeout, pollingInterval).ShouldNot(HaveOccurred()) 282 }) 283 284 t.It("Verify RoleBinding verrazzano-project-monitor-binding for verrazzano-project-monitor", func() { 285 verifyRoleBindingExists("verrazzano-project-monitor-binding") 286 }) 287 288 t.It("Fail create ApplicationConfiguration in namespace rbactest", func() { 289 t.Logs.Info("Can User create ApplicationConfiguration in NameSpace rbactest? No") 290 Eventually(func() (bool, error) { 291 allowed, reason, err := pkg.CanIForAPIGroup(v80ProjectMonitor, rbacTestNamespace, "create", "applicationconfigurations", "core.oam.dev") 292 t.Logs.Infof("Status: Should FAIL on user create ApplicationConfiguration: Allowed = %t, reason = %s", allowed, reason) 293 return allowed, err 294 }, waitTimeout, pollingInterval).Should(BeFalse(), "FAIL: Passed Authorization on user create ApplicationConfiguration. Timeout Expired") 295 }) 296 297 t.It("Succeed list ApplicationConfiguration in namespace rbactest", func() { 298 t.Logs.Info("Can User list ApplicationConfiguration in NameSpace rbactest? Yes") 299 Eventually(func() (bool, error) { 300 allowed, reason, err := pkg.CanIForAPIGroup(v80ProjectMonitor, rbacTestNamespace, "list", "applicationconfigurations", "core.oam.dev") 301 t.Logs.Infof("Status: Should SUCCEED on user list ApplicationConfiguration: Allowed = %t, reason = %s", allowed, reason) 302 return allowed, err 303 }, waitTimeout, pollingInterval).Should(BeTrue(), "FAIL: Did Not Pass Authorization on user list ApplicationConfiguration. Timeout Expired") 304 }) 305 306 t.It("Fail create OAM Components in namespace rbactest", func() { 307 t.Logs.Info("Can User create OAM Components in NameSpace rbactest? No") 308 Eventually(func() (bool, error) { 309 allowed, reason, err := pkg.CanIForAPIGroup(v80ProjectMonitor, rbacTestNamespace, "create", "components", "core.oam.dev") 310 t.Logs.Infof("Status: Should FAIL on user create OAM Components: Allowed = %t, reason = %s", allowed, reason) 311 return allowed, err 312 }, waitTimeout, pollingInterval).Should(BeFalse(), "FAIL: Passed Authorization on user create OAM Components. Timeout Expired") 313 }) 314 315 t.It("Succeed list OAM Components in namespace rbactest", func() { 316 t.Logs.Info("Can User list OAM Components in NameSpace rbactest? Yes") 317 Eventually(func() (bool, error) { 318 allowed, reason, err := pkg.CanIForAPIGroup(v80ProjectMonitor, rbacTestNamespace, "list", "components", "core.oam.dev") 319 t.Logs.Infof("Status: Should SUCCEED on user list OAM Components: Allowed = %t, reason = %s", allowed, reason) 320 return allowed, err 321 }, waitTimeout, pollingInterval).Should(BeTrue(), "FAIL: Did Not Pass Authorization on user list OAM Components. Timeout Expired") 322 }) 323 324 }) 325 }) 326 327 var _ = t.Describe("Test Verrazzano API Service Account", func() { 328 t.Context("for serviceaccount verrazzano-authproxy", func() { 329 var serviceAccount *corev1.ServiceAccount 330 331 t.BeforeEach(func() { 332 Eventually(func() (*corev1.ServiceAccount, error) { 333 var err error 334 serviceAccount, err = pkg.GetServiceAccount(verrazzanoSystemNS, verrazzanoAPI) 335 return serviceAccount, err 336 }, waitTimeout, pollingInterval).ShouldNot(BeNil(), fmt.Sprintf("Failed to get service account %s in namespace %s", verrazzanoAPI, verrazzanoSystemNS)) 337 }) 338 339 t.It("Validate the secret of the Service Account of Verrazzano API", Label("f:security.apiproxy"), func() { 340 t.Logs.Info("DEBUG - This test fails on 1.21 - extra debugging added") 341 var pods *corev1.PodList 342 var clientset *kubernetes.Clientset 343 Eventually(func() (*kubernetes.Clientset, error) { 344 var err error 345 clientset, err = k8sutil.GetKubernetesClientset() 346 return clientset, err 347 }, waitTimeout, pollingInterval).ShouldNot(BeNil()) 348 Eventually(func() (*corev1.PodList, error) { 349 var err error 350 pods, err = pkg.ListPodsInCluster(verrazzanoSystemNS, clientset) 351 return pods, err 352 }, waitTimeout, pollingInterval).ShouldNot(BeNil()) 353 354 // get the kubernetes version 355 version, err := clientset.ServerVersion() 356 Expect(err).ShouldNot(HaveOccurred()) 357 Expect(version.Major).To(Equal("1"), "Kubernetes major version was not 1 - I don't know what to do!") 358 minor, err := strconv.Atoi(version.Minor) 359 Expect(err).ShouldNot(HaveOccurred()) 360 361 secretMatched := false 362 if minor <= 20 { 363 // Get secret for the SA. In k8s 1.24 and later, secret is not created for service accounts. 364 saSecret := serviceAccount.Secrets[0] 365 t.Logs.Info("SA SECRET: " + saSecret.String()) 366 // in k8s 1.20 and lower, the SA token is mounted as a regular volume mounted secret 367 for i := range pods.Items { 368 // Get the secret of the API proxy pod 369 t.Logs.Info("IN RANGE i=" + fmt.Sprint(i) + " POD=" + pods.Items[i].Name) 370 if strings.HasPrefix(pods.Items[i].Name, verrazzanoAPI) { 371 apiProxy := pods.Items[i] 372 for j := range apiProxy.Spec.Volumes { 373 if apiProxy.Spec.Volumes[j].Secret != nil { 374 t.Logs.Info("IN RANGE j=" + fmt.Sprint(j) + " VOLUME= " + apiProxy.Spec.Volumes[j].Name + " SECRET=" + apiProxy.Spec.Volumes[j].Secret.SecretName) 375 } else { 376 t.Logs.Info("IN RANGE j=" + fmt.Sprint(j) + " VOLUME= " + apiProxy.Spec.Volumes[j].Name + " SECRET=NIL") 377 } 378 if apiProxy.Spec.Volumes[j].Secret != nil && apiProxy.Spec.Volumes[j].Secret.SecretName == saSecret.Name { 379 secretMatched = true 380 break 381 } 382 } 383 break 384 } 385 } 386 } else { 387 // in k8s 1.21 and later, the SA token is mounted as a projected volume with a different name, 388 // so we just check that there is a volume of type service account token and ignore the name 389 for i := range pods.Items { 390 // Get the secret of the API proxy pod 391 t.Logs.Info("IN RANGE i=" + fmt.Sprint(i) + " POD=" + pods.Items[i].Name) 392 if strings.HasPrefix(pods.Items[i].Name, verrazzanoAPI) { 393 apiProxy := pods.Items[i] 394 inner: 395 for j := range apiProxy.Spec.Volumes { 396 t.Logs.Info("IN RANGE j=" + fmt.Sprint(j) + " VOLUME= " + apiProxy.Spec.Volumes[j].Name + " SOURCE=" + apiProxy.Spec.Volumes[j].VolumeSource.String()) 397 if apiProxy.Spec.Volumes[j].VolumeSource.Projected != nil { 398 if apiProxy.Spec.Volumes[j].VolumeSource.Projected.Sources != nil { 399 for k := range apiProxy.Spec.Volumes[j].VolumeSource.Projected.Sources { 400 if apiProxy.Spec.Volumes[j].VolumeSource.Projected.Sources[k].ServiceAccountToken != nil { 401 t.Logs.Info("Found a Service Account Token in the projected volume") 402 secretMatched = true 403 break inner 404 } 405 } 406 } 407 } 408 } 409 break 410 } 411 } 412 } 413 Expect(secretMatched).To(BeTrue(), fmt.Sprintf("FAIL: The secret name of ServiceAccount "+ 414 "%s differs from the secret obtained from the Verrazzano API pod.", verrazzanoAPI)) 415 }) 416 417 t.It("Validate the role binding of the Service Account of Verrazzano API", func() { 418 var bindings *v1.ClusterRoleBindingList 419 Eventually(func() (*v1.ClusterRoleBindingList, error) { 420 var err error 421 bindings, err = pkg.ListClusterRoleBindings() 422 return bindings, err 423 }, waitTimeout, pollingInterval).ShouldNot(BeNil()) 424 425 saName := serviceAccount.Name 426 bcount := 0 427 var rbinding v1.ClusterRoleBinding 428 for rb := range bindings.Items { 429 for sa := range bindings.Items[rb].Subjects { 430 // Get cluster role bindings for verrazzano-authproxy 431 if bindings.Items[rb].Subjects[sa].Name == saName { 432 rbinding = bindings.Items[rb] 433 bcount++ 434 } 435 } 436 } 437 // There should be a single cluster role binding, which references service account of Verrazzano API 438 Expect(bcount > 1).To(BeFalse()) 439 Expect(len(rbinding.Subjects) > 1).To(BeFalse(), 440 fmt.Sprintf("FAIL: There are more than one Subjects for the cluster role binding %s", rbinding.Subjects)) 441 442 // There should be a single subject of kind service account in verrazzano-system namespace 443 Expect(rbinding.Subjects[0].Kind == "ServiceAccount").To(BeTrue(), 444 fmt.Sprintf("FAIL: The KIND for service account %s is different than ServiceAccount.", rbinding.Subjects[0].Kind)) 445 Expect(rbinding.Subjects[0].Namespace == verrazzanoSystemNS).To(BeTrue(), 446 fmt.Sprintf("FAIL: The namespace for service account %s is different than %s.", 447 rbinding.Subjects[0].Namespace, verrazzanoSystemNS)) 448 449 // There should be a single rule with resources - users and groups, and verbs impersonate 450 var crole *v1.ClusterRole 451 Eventually(func() (*v1.ClusterRole, error) { 452 var err error 453 crole, err = pkg.GetClusterRole(rbinding.RoleRef.Name) 454 return crole, err 455 }, waitTimeout, pollingInterval).ShouldNot(BeNil()) 456 457 Expect(len(crole.Rules) == 3).To(BeTrue(), 458 fmt.Sprintf("FAIL: The cluster role %v expected to contain two rules, found %d.", crole, len(crole.Rules))) 459 460 crule := crole.Rules[0] 461 Expect(len(crule.Resources) == 2).To(BeTrue(), 462 fmt.Sprintf("FAIL: There are more resources than the expected users and groups %s", crule.Resources)) 463 res := make(map[string]bool) 464 res["users"] = true 465 res["groups"] = true 466 for r := range crule.Resources { 467 delete(res, crule.Resources[r]) 468 } 469 Expect(len(res) == 0).To(BeTrue(), 470 fmt.Sprintf("FAIL: The rule contains resource(s) other than expected users and groups - %s", crule.Resources)) 471 472 verbs := crule.Verbs 473 Expect(len(verbs) == 1).To(BeTrue(), 474 fmt.Sprintf("FAIL: The cluster role %s contains more than one verbs.", crole)) 475 Expect(verbs[0] == impersonateVerb).To(BeTrue(), 476 fmt.Sprintf("FAIL: The cluster role %s contains verb other than impersonate.", crole)) 477 }) 478 479 t.It("Fail impersonating any other service account", func() { 480 t.Logs.Info("Can verrazzano-authproxy service account impersonate any other service account? No") 481 allowed, reason, err := pkg.CanIForAPIGroupForServiceAccountOrUser("verrazzano-authproxy", "", "impersonate", "serviceaccounts", "core", true, verrazzanoSystemNS) 482 Expect(err).ShouldNot(HaveOccurred()) 483 Expect(allowed).To(BeFalse(), fmt.Sprintf("FAIL: Passed Authorization on impersonating service accounts: Allowed = %t, reason = %s", allowed, reason)) 484 }) 485 486 }) 487 }) 488 489 func verifyRoleBindingExists(name string) { 490 Eventually(func() (bool, error) { 491 return pkg.DoesRoleBindingExist(name, rbacTestNamespace) 492 }, waitTimeout, pollingInterval).Should(BeTrue()) 493 }