Skip to content

Commit e3b9d28

Browse files
Inconsistent User access behaviour - inside role groups (#436)
* update user api modified fixed auth inside role groups * role group level user auth fixed * fix for auth on role group * fix for auth on role group - role group query * review changes for user auth access control
1 parent 783eed9 commit e3b9d28

File tree

3 files changed

+117
-1
lines changed

3 files changed

+117
-1
lines changed

api/restHandler/UserRestHandler.go

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"github.com/devtron-labs/devtron/pkg/user"
2727
"github.com/devtron-labs/devtron/util/rbac"
2828
"github.com/devtron-labs/devtron/util/response"
29+
"github.com/go-pg/pg"
2930
"github.com/gorilla/mux"
3031
"go.uber.org/zap"
3132
"gopkg.in/go-playground/validator.v9"
@@ -108,6 +109,32 @@ func (handler UserRestHandlerImpl) CreateUser(w http.ResponseWriter, r *http.Req
108109
return
109110
}
110111
}
112+
113+
// auth check inside groups
114+
if len(userInfo.Groups) > 0 {
115+
groupRoles, err := handler.roleGroupService.FetchRolesForGroups(userInfo.Groups)
116+
if err != nil && err != pg.ErrNoRows {
117+
handler.logger.Errorw("service err, UpdateUser", "err", err, "payload", userInfo)
118+
writeJsonResp(w, err, "", http.StatusInternalServerError)
119+
return
120+
}
121+
122+
if groupRoles != nil && len(groupRoles) > 0 {
123+
for _, groupRole := range groupRoles {
124+
if len(groupRole.Team) > 0 {
125+
if ok := handler.enforcer.Enforce(token, rbac.ResourceUser, rbac.ActionCreate, groupRole.Team); !ok {
126+
response.WriteResponse(http.StatusForbidden, "FORBIDDEN", w, errors.New("unauthorized"))
127+
return
128+
}
129+
}
130+
}
131+
} else {
132+
if ok := handler.enforcer.Enforce(token, rbac.ResourceUser, rbac.ActionCreate, "*"); !ok {
133+
response.WriteResponse(http.StatusForbidden, "FORBIDDEN", w, errors.New("unauthorized"))
134+
return
135+
}
136+
}
137+
}
111138
//RBAC enforcer Ends
112139

113140
handler.logger.Infow("request payload, CreateUser ", "payload", userInfo)
@@ -167,6 +194,32 @@ func (handler UserRestHandlerImpl) UpdateUser(w http.ResponseWriter, r *http.Req
167194
return
168195
}
169196
}
197+
198+
// auth check inside groups
199+
if len(userInfo.Groups) > 0 {
200+
groupRoles, err := handler.roleGroupService.FetchRolesForGroups(userInfo.Groups)
201+
if err != nil && err != pg.ErrNoRows {
202+
handler.logger.Errorw("service err, UpdateUser", "err", err, "payload", userInfo)
203+
writeJsonResp(w, err, "", http.StatusInternalServerError)
204+
return
205+
}
206+
207+
if groupRoles != nil && len(groupRoles) > 0 {
208+
for _, groupRole := range groupRoles {
209+
if len(groupRole.Team) > 0 {
210+
if ok := handler.enforcer.Enforce(token, rbac.ResourceUser, rbac.ActionUpdate, groupRole.Team); !ok {
211+
response.WriteResponse(http.StatusForbidden, "FORBIDDEN", w, errors.New("unauthorized"))
212+
return
213+
}
214+
}
215+
}
216+
} else {
217+
if ok := handler.enforcer.Enforce(token, rbac.ResourceUser, rbac.ActionUpdate, "*"); !ok {
218+
response.WriteResponse(http.StatusForbidden, "FORBIDDEN", w, errors.New("unauthorized"))
219+
return
220+
}
221+
}
222+
}
170223
//RBAC enforcer Ends
171224

172225
if userInfo.EmailId == "admin" {

internal/sql/repository/RoleGroupRepository.go

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,8 @@ type RoleGroupRepository interface {
3737
GetRoleGroupRoleMappingByRoleGroupId(roleGroupId int32) ([]*RoleGroupRoleMapping, error)
3838
DeleteRoleGroupRoleMapping(model *RoleGroupRoleMapping, tx *pg.Tx) (bool, error)
3939
GetConnection() (dbConnection *pg.DB)
40+
GetRoleGroupListByNames(groupNames []string) ([]*RoleGroup, error)
41+
GetRoleGroupRoleMappingByRoleGroupIds(roleGroupIds []int32) ([]*RoleModel, error)
4042
}
4143

4244
type RoleGroupRepositoryImpl struct {
@@ -63,7 +65,7 @@ type RoleGroupRoleMapping struct {
6365
Id int `sql:"id,pk"`
6466
RoleGroupId int32 `sql:"role_group_id,notnull"`
6567
RoleId int `sql:"role_id,notnull"`
66-
//User UserModel
68+
RoleModel *RoleModel
6769
models.AuditLog
6870
}
6971

@@ -154,3 +156,21 @@ func (impl RoleGroupRepositoryImpl) DeleteRoleGroupRoleMapping(model *RoleGroupR
154156
}
155157
return true, nil
156158
}
159+
160+
func (impl RoleGroupRepositoryImpl) GetRoleGroupListByNames(groupNames []string) ([]*RoleGroup, error) {
161+
var model []*RoleGroup
162+
err := impl.dbConnection.Model(&model).Where("name in (?)", pg.In(groupNames)).Where("active = ?", true).Order("updated_on desc").Select()
163+
return model, err
164+
}
165+
166+
func (impl RoleGroupRepositoryImpl) GetRoleGroupRoleMappingByRoleGroupIds(roleGroupIds []int32) ([]*RoleModel, error) {
167+
var roleModels []*RoleModel
168+
query := "SELECT r.* from roles r" +
169+
" INNER JOIN role_group_role_mapping rgm on rgm.role_id=r.id" +
170+
" WHERE rgm.role_group_id in (?);"
171+
_, err := impl.dbConnection.Query(&roleModels, query, pg.In(roleGroupIds))
172+
if err != nil {
173+
return roleModels, err
174+
}
175+
return roleModels, nil
176+
}

pkg/user/RoleGroupService.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import (
2626
"github.com/devtron-labs/devtron/internal/constants"
2727
"github.com/devtron-labs/devtron/internal/sql/repository"
2828
"github.com/devtron-labs/devtron/internal/util"
29+
"github.com/go-pg/pg"
2930
"github.com/gorilla/sessions"
3031
"go.uber.org/zap"
3132
"strings"
@@ -40,6 +41,7 @@ type RoleGroupService interface {
4041
FetchRoleGroups() ([]*bean.RoleGroup, error)
4142
FetchRoleGroupsByName(name string) ([]*bean.RoleGroup, error)
4243
DeleteRoleGroup(model *bean.RoleGroup) (bool, error)
44+
FetchRolesForGroups(groupNames []string) ([]*bean.RoleFilter, error)
4345
}
4446

4547
type RoleGroupServiceImpl struct {
@@ -525,3 +527,44 @@ func (impl RoleGroupServiceImpl) DeleteRoleGroup(bean *bean.RoleGroup) (bool, er
525527

526528
return true, nil
527529
}
530+
531+
func (impl RoleGroupServiceImpl) FetchRolesForGroups(groupNames []string) ([]*bean.RoleFilter, error) {
532+
if len(groupNames) == 0 {
533+
return nil, nil
534+
}
535+
roleGroups, err := impl.roleGroupRepository.GetRoleGroupListByNames(groupNames)
536+
if err != nil && err != pg.ErrNoRows {
537+
impl.logger.Errorw("error while fetching user from db", "error", err)
538+
return nil, err
539+
}
540+
if err == pg.ErrNoRows {
541+
impl.logger.Warnw("no result found for role groups", "groups", groupNames)
542+
return nil, nil
543+
}
544+
545+
var roleGroupIds []int32
546+
for _, roleGroup := range roleGroups {
547+
roleGroupIds = append(roleGroupIds, roleGroup.Id)
548+
}
549+
550+
roles, err := impl.roleGroupRepository.GetRoleGroupRoleMappingByRoleGroupIds(roleGroupIds)
551+
if err != nil && err != pg.ErrNoRows {
552+
impl.logger.Errorw("error while fetching user from db", "error", err)
553+
return nil, err
554+
}
555+
list := make([]*bean.RoleFilter, 0)
556+
if roles == nil {
557+
return list, nil
558+
}
559+
for _, role := range roles {
560+
bean := &bean.RoleFilter{
561+
EntityName: role.EntityName,
562+
Entity: role.Entity,
563+
Action: role.Action,
564+
Environment: role.Environment,
565+
Team: role.Team,
566+
}
567+
list = append(list, bean)
568+
}
569+
return list, nil
570+
}

0 commit comments

Comments
 (0)