@@ -496,6 +496,52 @@ var _ = g.Describe("Authorization [RBAC] [Zalando]", func() {
496496 })
497497 })
498498
499+ // Test secret read permissions for CDP and deployment-service
500+ // =============================================================================
501+ // Validates the RBAC permissions granted to CDP and deployment-service for reading
502+ // secrets across all namespaces, including kube-system. These permissions enable
503+ // the workflow where users deploy cluster roles with secret read permissions that
504+ // are subsequently rewritten by the admission controller.
505+ g .When ("the service account is deployment-service-controller" , func () {
506+ g .BeforeEach (func () {
507+ tc .data .users = []string {"system:serviceaccount:kube-system:deployment-service-controller" }
508+ tc .data .groups = [][]string {{"system:serviceaccounts:kube-system" }}
509+ })
510+ g .It ("should allow to read secrets on user namespaces" , func () {
511+ tc .data .namespaces = []string {"teapot" }
512+ tc .data .resources = []string {"secrets" }
513+ tc .data .verbs = []string {"read" }
514+ tc .run (context .TODO (), cs , true )
515+ gomega .Expect (tc .output .passed ).To (gomega .BeTrue (), tc .output .String ())
516+ })
517+ g .It ("should allow to read secrets on system namespace" , func () {
518+ tc .data .namespaces = []string {"kube-system" }
519+ tc .data .resources = []string {"secrets" }
520+ tc .data .verbs = []string {"read" }
521+ tc .run (context .TODO (), cs , true )
522+ gomega .Expect (tc .output .passed ).To (gomega .BeTrue (), tc .output .String ())
523+ })
524+ })
525+ g .When ("the service account is CDP" , func () {
526+ g .BeforeEach (func () {
527+ tc .data .users = []string {"system:serviceaccount:default:cdp" }
528+ tc .data .groups = [][]string {{"system:serviceaccounts:default" }}
529+ })
530+ g .It ("should allow to read secrets on user namespaces" , func () {
531+ tc .data .namespaces = []string {"teapot" }
532+ tc .data .resources = []string {"secrets" }
533+ tc .data .verbs = []string {"read" }
534+ tc .run (context .TODO (), cs , true )
535+ gomega .Expect (tc .output .passed ).To (gomega .BeTrue (), tc .output .String ())
536+ })
537+ g .It ("should allow to read secrets on system namespace" , func () {
538+ tc .data .namespaces = []string {"kube-system" }
539+ tc .data .resources = []string {"secrets" }
540+ tc .data .verbs = []string {"read" }
541+ tc .run (context .TODO (), cs , true )
542+ gomega .Expect (tc .output .passed ).To (gomega .BeTrue (), tc .output .String ())
543+ })
544+ })
499545 })
500546
501547 g .Context ("For administrators" , func () {
@@ -885,6 +931,69 @@ var _ = g.Describe("Authorization via admission-controller [RBAC] [Zalando]", fu
885931 gomega .Expect (result .Error ()).To (gomega .MatchError (gomega .ContainSubstring ("write operations are forbidden" )))
886932 })
887933 })
934+ })
935+
936+ // Test secret read permissions for CDP and deployment-service
937+ // =============================================================================
938+ // Validates that the admission controller correctly rewrites ClusterRole
939+ // permissions related to secret access, ensuring that secret read permissions
940+ // granted to CDP and deployment-service are revoked.
941+ g .Context ("cdp and deployment-service" , func () {
942+ var (
943+ testSecret * corev1.Secret
944+ systemSecret * corev1.Secret
945+ )
946+
947+ g .BeforeEach (func () {
948+ var err error
949+ testSecret , err = createSecret (context .Background (), f .ClientSet , f .Namespace .Name , map [string ]string {"application" : "my-app" })
950+ framework .ExpectNoError (err )
951+
952+ systemSecret , err = createSecret (context .Background (), f .ClientSet , "kube-system" , map [string ]string {"application" : "my-app" })
953+ framework .ExpectNoError (err )
954+ })
955+
956+ g .Context ("cdp" , func () {
957+ var client * kubernetes.Clientset
958+
959+ g .BeforeEach (func () {
960+ var err error
961+
962+ client , err = getCDPClient (eksCluster , awsAccountID )
963+ framework .ExpectNoError (err )
964+ })
965+
966+ g .It ("should deny secret read access to user namespace" , func () {
967+ _ , err := client .CoreV1 ().Secrets (testSecret .Namespace ).Get (context .Background (), testSecret .Name , metav1.GetOptions {})
968+ gomega .Expect (err ).To (gomega .MatchError (gomega .ContainSubstring ("read operations are forbidden" )))
969+ })
970+
971+ g .It ("should deny secret read access to kube-system namespace" , func () {
972+ _ , err := client .CoreV1 ().Secrets (systemSecret .Namespace ).Get (context .Background (), systemSecret .Name , metav1.GetOptions {})
973+ gomega .Expect (err ).To (gomega .MatchError (gomega .ContainSubstring ("read operations are forbidden" )))
974+ })
975+ })
976+
977+ g .Context ("deployment-service" , func () {
978+ var client * kubernetes.Clientset
979+
980+ g .BeforeEach (func () {
981+ var err error
982+
983+ client , err = getDeploymentServiceClient (eksCluster , awsAccountID )
984+ framework .ExpectNoError (err )
985+ })
986+
987+ g .It ("should deny secret read access to user namespace" , func () {
988+ _ , err := client .CoreV1 ().Secrets (testSecret .Namespace ).Get (context .Background (), testSecret .Name , metav1.GetOptions {})
989+ gomega .Expect (err ).To (gomega .MatchError (gomega .ContainSubstring ("read operations are forbidden" )))
990+ })
991+
992+ g .It ("should deny secret read access to kube-system namespace" , func () {
993+ _ , err := client .CoreV1 ().Secrets (systemSecret .Namespace ).Get (context .Background (), systemSecret .Name , metav1.GetOptions {})
994+ gomega .Expect (err ).To (gomega .MatchError (gomega .ContainSubstring ("read operations are forbidden" )))
995+ })
996+ })
888997 })
889998})
890999
@@ -913,6 +1022,15 @@ func getPostgresAdministratorClient(cluster *types.Cluster, awsAccountID string)
9131022 return newClientWithRole (cluster , fmt .Sprintf ("arn:aws:iam::%s:role/%s-e2e-eks-iam-test-postgres-admin-role" , awsAccountID , aws .ToString (cluster .Name )))
9141023}
9151024
1025+ // getCDPClient returns a client with the `zalando:cdp` group.
1026+ func getCDPClient (cluster * types.Cluster , awsAccountID string ) (* kubernetes.Clientset , error ) {
1027+ return newClientWithRole (cluster , fmt .Sprintf ("arn:aws:iam::%s:role/%s-e2e-eks-iam-test-cdp-role" , awsAccountID , aws .ToString (cluster .Name )))
1028+ }
1029+ // getDeploymentServiceClient returns a client with the `zalando:deployment-service` group.
1030+ func getDeploymentServiceClient (cluster * types.Cluster , awsAccountID string ) (* kubernetes.Clientset , error ) {
1031+ return newClientWithRole (cluster , fmt .Sprintf ("arn:aws:iam::%s:role/%s-e2e-eks-iam-test-deployment-service-role" , awsAccountID , aws .ToString (cluster .Name )))
1032+ }
1033+
9161034// newClientWithRole returns a new Kubernetes client with the specified IAM role and its associated AccessEntries.
9171035func newClientWithRole (cluster * types.Cluster , assumeRole string ) (* kubernetes.Clientset , error ) {
9181036 gen , err := token .NewGenerator (true , false )
@@ -1013,6 +1131,18 @@ func createClusterRole(ctx context.Context, client kubernetes.Interface, labels
10131131 return client .RbacV1 ().ClusterRoles ().Create (ctx , clusterRole , metav1.CreateOptions {})
10141132}
10151133
1134+ // createSecret creates a Secret with the specified labels.
1135+ func createSecret (ctx context.Context , client kubernetes.Interface , namespace string , labels map [string ]string ) (* corev1.Secret , error ) {
1136+ secret := & corev1.Secret {
1137+ ObjectMeta : metav1.ObjectMeta {
1138+ GenerateName : "test-secret-" ,
1139+ Labels : labels ,
1140+ },
1141+ }
1142+
1143+ return client .CoreV1 ().Secrets (namespace ).Create (ctx , secret , metav1.CreateOptions {})
1144+ }
1145+
10161146// getAWSAccountID returns the current AWS account's ID.
10171147func getAWSAccountID (ctx context.Context , awsConfig aws.Config ) (string , error ) {
10181148 client := sts .NewFromConfig (awsConfig )
0 commit comments