@@ -20,8 +20,12 @@ import (
2020 "context"
2121 "encoding/json"
2222 "errors"
23+ bean2 "github.com/devtron-labs/devtron/pkg/cluster/bean"
24+ "github.com/devtron-labs/devtron/pkg/cluster/environment"
25+ "github.com/devtron-labs/devtron/pkg/cluster/rbac"
2326 "net/http"
2427 "strconv"
28+ "strings"
2529 "time"
2630
2731 "github.com/devtron-labs/devtron/pkg/auth/authorisation/casbin"
@@ -69,8 +73,8 @@ type ClusterRestHandlerImpl struct {
6973 enforcer casbin.Enforcer
7074 deleteService delete2.DeleteService
7175 argoUserService argo.ArgoUserService
72- environmentService cluster .EnvironmentService
73- clusterRbacService cluster .ClusterRbacService
76+ environmentService environment .EnvironmentService
77+ clusterRbacService rbac .ClusterRbacService
7478}
7579
7680func NewClusterRestHandlerImpl (clusterService cluster.ClusterService ,
@@ -82,8 +86,8 @@ func NewClusterRestHandlerImpl(clusterService cluster.ClusterService,
8286 enforcer casbin.Enforcer ,
8387 deleteService delete2.DeleteService ,
8488 argoUserService argo.ArgoUserService ,
85- environmentService cluster .EnvironmentService ,
86- clusterRbacService cluster .ClusterRbacService ) * ClusterRestHandlerImpl {
89+ environmentService environment .EnvironmentService ,
90+ clusterRbacService rbac .ClusterRbacService ) * ClusterRestHandlerImpl {
8791 return & ClusterRestHandlerImpl {
8892 clusterService : clusterService ,
8993 clusterNoteService : clusterNoteService ,
@@ -107,7 +111,7 @@ func (impl ClusterRestHandlerImpl) SaveClusters(w http.ResponseWriter, r *http.R
107111 common .WriteJsonResp (w , err , "Unauthorized User" , http .StatusUnauthorized )
108112 return
109113 }
110- beans := []* cluster .ClusterBean {}
114+ beans := []* bean2 .ClusterBean {}
111115 err = decoder .Decode (& beans )
112116 if err != nil {
113117 impl .logger .Errorw ("request err, Save" , "error" , err , "payload" , beans )
@@ -178,7 +182,7 @@ func (impl ClusterRestHandlerImpl) Save(w http.ResponseWriter, r *http.Request)
178182 common .WriteJsonResp (w , err , "Unauthorized User" , http .StatusUnauthorized )
179183 return
180184 }
181- bean := new (cluster .ClusterBean )
185+ bean := new (bean2 .ClusterBean )
182186 err = decoder .Decode (bean )
183187 if err != nil {
184188 impl .logger .Errorw ("request err, Save" , "error" , err , "payload" , bean )
@@ -247,7 +251,7 @@ func (impl ClusterRestHandlerImpl) ValidateKubeconfig(w http.ResponseWriter, r *
247251 common .WriteJsonResp (w , err , "Unauthorized User" , http .StatusUnauthorized )
248252 return
249253 }
250- bean := & cluster .Kubeconfig {}
254+ bean := & bean2 .Kubeconfig {}
251255 err = decoder .Decode (bean )
252256 if err != nil {
253257 impl .logger .Errorw ("request err, Validate" , "error" , err , "payload" , bean )
@@ -309,7 +313,7 @@ func (impl ClusterRestHandlerImpl) FindAll(w http.ResponseWriter, r *http.Reques
309313 }
310314
311315 // RBAC enforcer applying
312- var result []* cluster .ClusterBean
316+ var result []* bean2 .ClusterBean
313317 for _ , item := range clusterList {
314318 if ok := impl .enforcer .Enforce (token , casbin .ResourceCluster , casbin .ActionGet , item .ClusterName ); ok {
315319 result = append (result , item )
@@ -374,7 +378,7 @@ func (impl ClusterRestHandlerImpl) FindNoteByClusterId(w http.ResponseWriter, r
374378 }
375379 // RBAC enforcer applying
376380 token := r .Header .Get ("token" )
377- authenticated , err := impl .clusterRbacService .CheckAuthorization (bean .ClusterName , bean .ClusterId , token , userId , false )
381+ authenticated , err := impl .clusterRbacService .CheckAuthorization (bean .ClusterName , bean .ClusterId , token , userId , true )
378382 if err != nil {
379383 impl .logger .Errorw ("error in checking rbac for cluster" , "err" , err , "clusterId" , bean .ClusterId )
380384 common .WriteJsonResp (w , err , nil , http .StatusInternalServerError )
@@ -397,7 +401,7 @@ func (impl ClusterRestHandlerImpl) Update(w http.ResponseWriter, r *http.Request
397401 common .WriteJsonResp (w , err , "Unauthorized User" , http .StatusUnauthorized )
398402 return
399403 }
400- var bean cluster .ClusterBean
404+ var bean bean2 .ClusterBean
401405 err = decoder .Decode (& bean )
402406 if err != nil {
403407 impl .logger .Errorw ("request err, Update" , "error" , err , "payload" , bean )
@@ -458,7 +462,7 @@ func (impl ClusterRestHandlerImpl) UpdateClusterDescription(w http.ResponseWrite
458462 common .WriteJsonResp (w , err , "Unauthorized User" , http .StatusUnauthorized )
459463 return
460464 }
461- var bean cluster .ClusterBean
465+ var bean bean2 .ClusterBean
462466 err = decoder .Decode (& bean )
463467 if err != nil {
464468 impl .logger .Errorw ("request err, UpdateClusterDescription" , "error" , err , "payload" , bean )
@@ -474,7 +478,8 @@ func (impl ClusterRestHandlerImpl) UpdateClusterDescription(w http.ResponseWrite
474478 return
475479 }
476480 // RBAC enforcer applying
477- if ok := impl .enforcer .Enforce (token , casbin .ResourceCluster , casbin .ActionUpdate , clusterDescription .ClusterName ); ! ok {
481+ authenticated := impl .clusterRbacService .CheckAuthorisationForAllK8sPermissions (token , clusterDescription .ClusterName , casbin .ActionUpdate )
482+ if ! authenticated {
478483 common .WriteJsonResp (w , errors .New ("unauthorized" ), nil , http .StatusForbidden )
479484 return
480485 }
@@ -518,7 +523,8 @@ func (impl ClusterRestHandlerImpl) UpdateClusterNote(w http.ResponseWriter, r *h
518523 return
519524 }
520525 // RBAC enforcer applying
521- if ok := impl .enforcer .Enforce (token , casbin .ResourceCluster , casbin .ActionUpdate , clusterDescription .ClusterName ); ! ok {
526+ authenticated := impl .clusterRbacService .CheckAuthorisationForAllK8sPermissions (token , clusterDescription .ClusterName , casbin .ActionUpdate )
527+ if ! authenticated {
522528 common .WriteJsonResp (w , errors .New ("unauthorized" ), nil , http .StatusForbidden )
523529 return
524530 }
@@ -544,7 +550,7 @@ func (impl ClusterRestHandlerImpl) FindAllForAutoComplete(w http.ResponseWriter,
544550 common .WriteJsonResp (w , err , nil , http .StatusInternalServerError )
545551 return
546552 }
547- var result []cluster .ClusterBean
553+ var result []bean2 .ClusterBean
548554 v := r .URL .Query ()
549555 authEnabled := true
550556 auth := v .Get ("auth" )
@@ -573,7 +579,7 @@ func (impl ClusterRestHandlerImpl) FindAllForAutoComplete(w http.ResponseWriter,
573579 //RBAC enforcer Ends
574580
575581 if len (result ) == 0 {
576- result = make ([]cluster .ClusterBean , 0 )
582+ result = make ([]bean2 .ClusterBean , 0 )
577583 }
578584 common .WriteJsonResp (w , err , result , http .StatusOK )
579585}
@@ -586,7 +592,7 @@ func (impl ClusterRestHandlerImpl) DeleteCluster(w http.ResponseWriter, r *http.
586592 common .WriteJsonResp (w , err , "Unauthorized User" , http .StatusUnauthorized )
587593 return
588594 }
589- var bean cluster .ClusterBean
595+ var bean bean2 .ClusterBean
590596 err = decoder .Decode (& bean )
591597 if err != nil {
592598 impl .logger .Errorw ("request err, Delete" , "error" , err , "payload" , bean )
@@ -619,17 +625,61 @@ func (impl ClusterRestHandlerImpl) DeleteCluster(w http.ResponseWriter, r *http.
619625
620626func (impl ClusterRestHandlerImpl ) GetAllClusterNamespaces (w http.ResponseWriter , r * http.Request ) {
621627 token := r .Header .Get ("token" )
628+ userId , err := impl .userService .GetLoggedInUser (r )
629+ if userId == 0 || err != nil {
630+ impl .logger .Errorw ("err, GetAllClusterNamespaces" , "error" , err , "userId" , userId )
631+ common .WriteJsonResp (w , err , "Unauthorized User" , http .StatusUnauthorized )
632+ return
633+ }
622634 clusterNamespaces := impl .clusterService .GetAllClusterNamespaces ()
623635
624636 // RBAC enforcer applying
625- for clusterName , _ := range clusterNamespaces {
626- if ok := impl .enforcer .Enforce (token , casbin .ResourceCluster , casbin .ActionGet , clusterName ); ! ok {
627- delete (clusterNamespaces , clusterName )
628- }
637+ filteredClusterNamespaces , err := impl .HandleRbacForClusterNamespace (userId , token , clusterNamespaces )
638+ if err != nil {
639+ impl .logger .Errorw ("error in GetAllClusterNamespaces" , "err" , err )
640+ common .WriteJsonResp (w , err , nil , http .StatusInternalServerError )
641+ return
629642 }
630643 //RBAC enforcer Ends
631644
632- common .WriteJsonResp (w , nil , clusterNamespaces , http .StatusOK )
645+ common .WriteJsonResp (w , nil , filteredClusterNamespaces , http .StatusOK )
646+ }
647+
648+ func (impl ClusterRestHandlerImpl ) HandleRbacForClusterNamespace (userId int32 , token string , clusterNamespaces map [string ][]string ) (map [string ][]string , error ) {
649+ filteredClusterNamespaces := make (map [string ][]string )
650+ if ok := impl .enforcer .Enforce (token , casbin .ResourceGlobal , casbin .ActionGet , "*" ); ok {
651+ return clusterNamespaces , nil
652+ }
653+ roles , err := impl .clusterService .FetchRolesFromGroup (userId )
654+ if err != nil {
655+ impl .logger .Errorw ("error on fetching user roles for cluster list" , "err" , err )
656+ return nil , err
657+ }
658+
659+ clusterAndNameSpaceVsAllowedMap := make (map [string ]bool , len (roles ))
660+ clusterNameVsAllAllowedMap := make (map [string ]bool , len (roles ))
661+ for _ , role := range roles {
662+ clusterAndNameSpaceVsAllowedMap [strings .ToLower (role .Cluster + "_" + role .Namespace )] = true
663+ if role .Namespace == "" {
664+ clusterNameVsAllAllowedMap [role .Cluster ] = true
665+ } else {
666+ clusterNameVsAllAllowedMap [role .Cluster ] = false
667+ }
668+ }
669+
670+ for clusterName , allNamespaces := range clusterNamespaces {
671+ if val , exist := clusterNameVsAllAllowedMap [clusterName ]; val {
672+ filteredClusterNamespaces [clusterName ] = allNamespaces
673+ } else if exist {
674+ for _ , namespace := range allNamespaces {
675+ if val2 , exist2 := clusterAndNameSpaceVsAllowedMap [strings .ToLower (clusterName + "_" + namespace )]; exist2 && val2 {
676+ filteredClusterNamespaces [clusterName ] = append (filteredClusterNamespaces [clusterName ], namespace )
677+ }
678+ }
679+ }
680+ }
681+ return filteredClusterNamespaces , nil
682+
633683}
634684
635685func (impl ClusterRestHandlerImpl ) GetClusterNamespaces (w http.ResponseWriter , r * http.Request ) {
@@ -688,7 +738,7 @@ func (impl ClusterRestHandlerImpl) FindAllForClusterPermission(w http.ResponseWr
688738 if len (clusterList ) == 0 {
689739 // assumption is that if list is empty, then it can happen only in case of Unauthorized (but not sending Unauthorized for super-admin user)
690740 if isActionUserSuperAdmin {
691- clusterList = make ([]cluster .ClusterBean , 0 )
741+ clusterList = make ([]bean2 .ClusterBean , 0 )
692742 } else {
693743 common .WriteJsonResp (w , errors .New ("unauthorized" ), nil , http .StatusForbidden )
694744 return
0 commit comments