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  }