@@ -496,6 +496,52 @@ var _ = g.Describe("Authorization [RBAC] [Zalando]", func() {
496
496
})
497
497
})
498
498
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
+ })
499
545
})
500
546
501
547
g .Context ("For administrators" , func () {
@@ -885,6 +931,69 @@ var _ = g.Describe("Authorization via admission-controller [RBAC] [Zalando]", fu
885
931
gomega .Expect (result .Error ()).To (gomega .MatchError (gomega .ContainSubstring ("write operations are forbidden" )))
886
932
})
887
933
})
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
+ })
888
997
})
889
998
})
890
999
@@ -913,6 +1022,15 @@ func getPostgresAdministratorClient(cluster *types.Cluster, awsAccountID string)
913
1022
return newClientWithRole (cluster , fmt .Sprintf ("arn:aws:iam::%s:role/%s-e2e-eks-iam-test-postgres-admin-role" , awsAccountID , aws .ToString (cluster .Name )))
914
1023
}
915
1024
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
+
916
1034
// newClientWithRole returns a new Kubernetes client with the specified IAM role and its associated AccessEntries.
917
1035
func newClientWithRole (cluster * types.Cluster , assumeRole string ) (* kubernetes.Clientset , error ) {
918
1036
gen , err := token .NewGenerator (true , false )
@@ -1013,6 +1131,18 @@ func createClusterRole(ctx context.Context, client kubernetes.Interface, labels
1013
1131
return client .RbacV1 ().ClusterRoles ().Create (ctx , clusterRole , metav1.CreateOptions {})
1014
1132
}
1015
1133
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
+
1016
1146
// getAWSAccountID returns the current AWS account's ID.
1017
1147
func getAWSAccountID (ctx context.Context , awsConfig aws.Config ) (string , error ) {
1018
1148
client := sts .NewFromConfig (awsConfig )
0 commit comments