Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 30 additions & 26 deletions api/auth/user/UserRestHandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -1190,7 +1190,7 @@ func (handler UserRestHandlerImpl) checkRBACForUserCreate(token string, requestS
}

func (handler UserRestHandlerImpl) checkRBACForUserUpdate(token string, userInfo *bean.UserInfo, isUserAlreadySuperAdmin bool, eliminatedRoleFilters,
eliminatedGroupRoles []*repository.RoleModel) (isAuthorised bool, err error) {
eliminatedGroupRoles []*repository.RoleModel, mapOfExistingUserRoleGroup map[string]bool) (isAuthorised bool, err error) {
isActionUserSuperAdmin := handler.enforcer.Enforce(token, casbin.ResourceGlobal, casbin.ActionGet, "*")
requestSuperAdmin := userInfo.SuperAdmin
if (requestSuperAdmin || isUserAlreadySuperAdmin) && !isActionUserSuperAdmin {
Expand Down Expand Up @@ -1241,33 +1241,37 @@ func (handler UserRestHandlerImpl) checkRBACForUserUpdate(token string, userInfo
}
}
if len(roleGroups) > 0 { // auth check inside groups
groupRoles, err := handler.roleGroupService.FetchRolesForUserRoleGroups(roleGroups)
if err != nil && err != pg.ErrNoRows {
handler.logger.Errorw("service err, UpdateUser", "err", err, "payload", roleGroups)
return false, err
}
if len(groupRoles) > 0 {
for _, groupRole := range groupRoles {
switch {
case groupRole.Action == bean.ACTION_SUPERADMIN:
isAuthorised = isActionUserSuperAdmin
case groupRole.AccessType == bean.APP_ACCESS_TYPE_HELM || groupRole.Entity == bean2.EntityJobs:
isAuthorised = isActionUserSuperAdmin
case len(groupRole.Team) > 0:
isAuthorised = handler.enforcer.Enforce(token, casbin.ResourceUser, casbin.ActionCreate, groupRole.Team)
case groupRole.Entity == bean.CLUSTER_ENTITIY:
isAuthorised = handler.userCommonService.CheckRbacForClusterEntity(groupRole.Cluster, groupRole.Namespace, groupRole.Group, groupRole.Kind, groupRole.Resource, token, handler.CheckManagerAuth)
case groupRole.Entity == bean.CHART_GROUP_ENTITY:
isAuthorised = true
default:
isAuthorised = false
}
if !isAuthorised {
return false, nil
//filter out roleGroups (existing has to be ignore while checking rbac)
filteredRoleGroups := util2.FilterRoleGroupIfAlreadyPresent(roleGroups, mapOfExistingUserRoleGroup)
if len(filteredRoleGroups) > 0 {
groupRoles, err := handler.roleGroupService.FetchRolesForUserRoleGroups(roleGroups)
if err != nil && err != pg.ErrNoRows {
handler.logger.Errorw("service err, UpdateUser", "err", err, "filteredRoleGroups", filteredRoleGroups)
return false, err
}
if len(groupRoles) > 0 {
for _, groupRole := range groupRoles {
switch {
case groupRole.Action == bean.ACTION_SUPERADMIN:
isAuthorised = isActionUserSuperAdmin
case groupRole.AccessType == bean.APP_ACCESS_TYPE_HELM || groupRole.Entity == bean2.EntityJobs:
isAuthorised = isActionUserSuperAdmin
case len(groupRole.Team) > 0:
isAuthorised = handler.enforcer.Enforce(token, casbin.ResourceUser, casbin.ActionCreate, groupRole.Team)
case groupRole.Entity == bean.CLUSTER_ENTITIY:
isAuthorised = handler.userCommonService.CheckRbacForClusterEntity(groupRole.Cluster, groupRole.Namespace, groupRole.Group, groupRole.Kind, groupRole.Resource, token, handler.CheckManagerAuth)
case groupRole.Entity == bean.CHART_GROUP_ENTITY:
isAuthorised = true
default:
isAuthorised = false
}
if !isAuthorised {
return false, nil
}
}
} else {
isAuthorised = false
}
} else {
isAuthorised = false
}
}
}
Expand Down
16 changes: 16 additions & 0 deletions api/auth/user/util/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,25 @@

package util

import (
"github.com/devtron-labs/devtron/api/bean"
"github.com/devtron-labs/devtron/pkg/auth/user/helper"
)

func IsGroupsPresent(groups []string) bool {
if len(groups) > 0 {
return true
}
return false
}

func FilterRoleGroupIfAlreadyPresent(roleGroups []bean.UserRoleGroup, mapOfExistingUserRoleGroup map[string]bool) []bean.UserRoleGroup {
finalRoleGroups := make([]bean.UserRoleGroup, 0, len(roleGroups))
for _, roleGrp := range roleGroups {
if _, ok := mapOfExistingUserRoleGroup[helper.GetCasbinNameFromRoleGroupName(roleGrp.RoleGroup.Name)]; !ok {
finalRoleGroups = append(finalRoleGroups, roleGrp)
}
}
return finalRoleGroups

}
18 changes: 14 additions & 4 deletions client/events/EventBuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package client
import (
"context"
"fmt"
repository4 "github.com/devtron-labs/devtron/pkg/cluster/repository"
"strings"
"time"

Expand All @@ -35,7 +36,7 @@ import (
)

type EventFactory interface {
Build(eventType util.EventType, sourceId *int, appId int, envId *int, pipelineType util.PipelineType) Event
Build(eventType util.EventType, sourceId *int, appId int, envId *int, pipelineType util.PipelineType) (Event, error)
BuildExtraCDData(event Event, wfr *pipelineConfig.CdWorkflowRunner, pipelineOverrideId int, stage bean2.WorkflowType) Event
BuildExtraCIData(event Event, material *MaterialTriggerInfo) Event
//BuildFinalData(event Event) *Payload
Expand All @@ -50,14 +51,15 @@ type EventSimpleFactoryImpl struct {
ciPipelineRepository pipelineConfig.CiPipelineRepository
pipelineRepository pipelineConfig.PipelineRepository
userRepository repository.UserRepository
envRepository repository4.EnvironmentRepository
ciArtifactRepository repository2.CiArtifactRepository
}

func NewEventSimpleFactoryImpl(logger *zap.SugaredLogger, cdWorkflowRepository pipelineConfig.CdWorkflowRepository,
pipelineOverrideRepository chartConfig.PipelineOverrideRepository, ciWorkflowRepository pipelineConfig.CiWorkflowRepository,
ciPipelineMaterialRepository pipelineConfig.CiPipelineMaterialRepository,
ciPipelineRepository pipelineConfig.CiPipelineRepository, pipelineRepository pipelineConfig.PipelineRepository,
userRepository repository.UserRepository, ciArtifactRepository repository2.CiArtifactRepository) *EventSimpleFactoryImpl {
userRepository repository.UserRepository, envRepository repository4.EnvironmentRepository, ciArtifactRepository repository2.CiArtifactRepository) *EventSimpleFactoryImpl {
return &EventSimpleFactoryImpl{
logger: logger,
cdWorkflowRepository: cdWorkflowRepository,
Expand All @@ -68,10 +70,11 @@ func NewEventSimpleFactoryImpl(logger *zap.SugaredLogger, cdWorkflowRepository p
pipelineRepository: pipelineRepository,
userRepository: userRepository,
ciArtifactRepository: ciArtifactRepository,
envRepository: envRepository,
}
}

func (impl *EventSimpleFactoryImpl) Build(eventType util.EventType, sourceId *int, appId int, envId *int, pipelineType util.PipelineType) Event {
func (impl *EventSimpleFactoryImpl) Build(eventType util.EventType, sourceId *int, appId int, envId *int, pipelineType util.PipelineType) (Event, error) {
correlationId := uuid.NewV4()
event := Event{}
event.EventTypeId = int(eventType)
Expand All @@ -80,12 +83,19 @@ func (impl *EventSimpleFactoryImpl) Build(eventType util.EventType, sourceId *in
}
event.AppId = appId
if envId != nil {
env, err := impl.envRepository.FindById(*envId)
if err != nil {
impl.logger.Errorw("error in getting env", "envId", *envId, "err", err)
return event, err
}
event.EnvId = *envId
event.ClusterId = env.ClusterId
event.IsProdEnv = env.Default
}
event.PipelineType = string(pipelineType)
event.CorrelationId = fmt.Sprintf("%s", correlationId)
event.EventTime = time.Now().Format(bean.LayoutRFC3339)
return event
return event, nil
}

func (impl *EventSimpleFactoryImpl) BuildExtraCDData(event Event, wfr *pipelineConfig.CdWorkflowRunner, pipelineOverrideId int, stage bean2.WorkflowType) Event {
Expand Down
2 changes: 2 additions & 0 deletions client/events/EventClient.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ type Event struct {
TeamId int `json:"teamId"`
AppId int `json:"appId"`
EnvId int `json:"envId"`
IsProdEnv bool `json:"isProdEnv"`
ClusterId int `json:"clusterId"`
CdWorkflowType bean.WorkflowType `json:"cdWorkflowType,omitempty"`
CdWorkflowRunnerId int `json:"cdWorkflowRunnerId"`
CiWorkflowRunnerId int `json:"ciWorkflowRunnerId"`
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ require gopkg.in/evanphx/json-patch.v4 v4.12.0 // indirect

replace (
github.com/argoproj/argo-workflows/v3 v3.5.10 => github.com/devtron-labs/argo-workflows/v3 v3.5.10
github.com/devtron-labs/common-lib => github.com/devtron-labs/devtron-services/common-lib v0.0.0-20241007082547-2dffd643a849
github.com/devtron-labs/common-lib => github.com/devtron-labs/devtron-services/common-lib v0.0.0-20241010131105-e2c23f9c80da
github.com/go-check/check => github.com/go-check/check v0.0.0-20180628173108-788fd7840127
github.com/googleapis/gnostic => github.com/googleapis/gnostic v0.5.5
k8s.io/api => k8s.io/api v0.29.7
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -794,8 +794,8 @@ github.com/devtron-labs/argo-workflows/v3 v3.5.10 h1:6rxQOesOzDz6SgQCMDQNHaehsKF
github.com/devtron-labs/argo-workflows/v3 v3.5.10/go.mod h1:/vqxcovDPT4zqr4DjR5v7CF8ggpY1l3TSa2CIG3jmjA=
github.com/devtron-labs/authenticator v0.4.35-0.20240809073103-6e11da8083f8 h1:2+Q7Jdhpo/uMiaQiZZzAh+ZX7wEJIFuMFG6DEiMuo64=
github.com/devtron-labs/authenticator v0.4.35-0.20240809073103-6e11da8083f8/go.mod h1:702R6WIf5y9UzKGoCGxQ+x3l5Ws+l0fXg2xlCpSGFZI=
github.com/devtron-labs/devtron-services/common-lib v0.0.0-20241007082547-2dffd643a849 h1:93zOd28I0n7FdidXYBPHtHJ2o2UKimTpPoMGfLAu4lY=
github.com/devtron-labs/devtron-services/common-lib v0.0.0-20241007082547-2dffd643a849/go.mod h1:KpKnF4OSpQNDJmb4wVZq3Za88ePBw4xec2GOAGRm5UQ=
github.com/devtron-labs/devtron-services/common-lib v0.0.0-20241010131105-e2c23f9c80da h1:vC6SMz6BM1doN+ZBGiDGyERJ/LphFQi5+Ab/YQkNJVo=
github.com/devtron-labs/devtron-services/common-lib v0.0.0-20241010131105-e2c23f9c80da/go.mod h1:KpKnF4OSpQNDJmb4wVZq3Za88ePBw4xec2GOAGRm5UQ=
github.com/devtron-labs/go-bitbucket v0.9.60-beta h1:VEx1jvDgdtDPS6A1uUFoaEi0l1/oLhbr+90xOwr6sDU=
github.com/devtron-labs/go-bitbucket v0.9.60-beta/go.mod h1:GnuiCesvh8xyHeMCb+twm8lBR/kQzJYSKL28ZfObp1Y=
github.com/devtron-labs/protos v0.0.3-0.20240802105333-92ee9bb85d80 h1:xwbTeijNTf4/j1v+tSfwVqwLVnReas/NqEKeQHvSTys=
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,8 @@ func (impl AppListingRepositoryQueryBuilder) BuildAppListingQueryLastDeploymentT
func (impl AppListingRepositoryQueryBuilder) GetAppIdsQueryWithPaginationForLastDeployedSearch(appListingFilter AppListingFilter) (string, []interface{}) {
join, queryParams := impl.CommonJoinSubQuery(appListingFilter)
countQuery := " (SELECT count(distinct(a.id)) as count FROM app a " + join + ") AS total_count "

// appending query params for count query as well
queryParams = append(queryParams, queryParams...)
query := "SELECT a.id as app_id,MAX(pco.id) as last_deployed_time, " + countQuery +
` FROM pipeline p
INNER JOIN pipeline_config_override pco ON pco.pipeline_id = p.id and p.deleted=false
Expand Down Expand Up @@ -259,7 +260,7 @@ func (impl AppListingRepositoryQueryBuilder) buildAppListingWhereCondition(appLi
}
if isNotDeployedFilterApplied {
deploymentAppType := "manifest_download"
whereCondition += " and (p.deployment_app_created=? and (p.deployment_app_type != ? || dc.deployment_app_type != ? ) or a.id NOT IN (SELECT app_id from pipeline) "
whereCondition += " and (p.deployment_app_created=? and (p.deployment_app_type != ? or dc.deployment_app_type != ? ) or a.id NOT IN (SELECT app_id from pipeline) "
queryParams = append(queryParams, false, deploymentAppType, deploymentAppType)
if len(appStatusExcludingNotDeployed) > 0 {
whereCondition += " or aps.status IN (?) "
Expand Down
4 changes: 2 additions & 2 deletions pkg/app/AppService.go
Original file line number Diff line number Diff line change
Expand Up @@ -811,7 +811,7 @@ func (impl *AppServiceImpl) UpdatePipelineStatusTimelineForApplicationChanges(ap
}

func (impl *AppServiceImpl) WriteCDSuccessEvent(appId int, envId int, override *chartConfig.PipelineOverride) {
event := impl.eventFactory.Build(util.Success, &override.PipelineId, appId, &envId, util.CD)
event, _ := impl.eventFactory.Build(util.Success, &override.PipelineId, appId, &envId, util.CD)
impl.logger.Debugw("event WriteCDSuccessEvent", "event", event, "override", override)
event = impl.eventFactory.BuildExtraCDData(event, nil, override.Id, bean.CD_WORKFLOW_TYPE_DEPLOY)
_, evtErr := impl.eventClient.WriteNotificationEvent(event)
Expand Down Expand Up @@ -1056,7 +1056,7 @@ type PipelineMaterialInfo struct {

func buildCDTriggerEvent(impl *AppServiceImpl, overrideRequest *bean.ValuesOverrideRequest, pipeline *pipelineConfig.Pipeline,
envOverride *chartConfig.EnvConfigOverride, materialInfo map[string]string, artifact *repository.CiArtifact) client.Event {
event := impl.eventFactory.Build(util.Trigger, &pipeline.Id, pipeline.AppId, &pipeline.EnvironmentId, util.CD)
event, _ := impl.eventFactory.Build(util.Trigger, &pipeline.Id, pipeline.AppId, &pipeline.EnvironmentId, util.CD)
return event
}

Expand Down
2 changes: 1 addition & 1 deletion pkg/app/DeploymentEventHandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func NewDeploymentEventHandlerImpl(logger *zap.SugaredLogger, appListingService
}

func (impl *DeploymentEventHandlerImpl) WriteCDDeploymentEvent(pipelineId, appId, envId int, eventType util.EventType) {
event := impl.eventFactory.Build(eventType, &pipelineId, appId, &envId, util.CD)
event, _ := impl.eventFactory.Build(eventType, &pipelineId, appId, &envId, util.CD)
impl.logger.Debugw("event WriteCDDeploymentEvent", "event", event)
event = impl.eventFactory.BuildExtraCDData(event, nil, 0, bean.CD_WORKFLOW_TYPE_DEPLOY)
_, evtErr := impl.eventClient.WriteNotificationEvent(event)
Expand Down
5 changes: 2 additions & 3 deletions pkg/auth/user/RoleGroupService.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package user
import (
"errors"
"fmt"
helper2 "github.com/devtron-labs/devtron/pkg/auth/user/helper"
"github.com/devtron-labs/devtron/pkg/auth/user/repository/helper"
"net/http"
"strings"
Expand Down Expand Up @@ -101,9 +102,7 @@ func (impl RoleGroupServiceImpl) CreateRoleGroup(request *bean.RoleGroup) (*bean
Name: request.Name,
Description: request.Description,
}
rgName := strings.ToLower(request.Name)
object := "group:" + strings.ReplaceAll(rgName, " ", "_")

object := helper2.GetCasbinNameFromRoleGroupName(request.Name)
exists, err := impl.roleGroupRepository.CheckRoleGroupExistByCasbinName(object)
if err != nil {
impl.logger.Errorw("error in getting role group by casbin name", "err", err, "casbinName", object)
Expand Down
8 changes: 5 additions & 3 deletions pkg/auth/user/UserService.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ type UserService interface {
CreateUser(userInfo *bean.UserInfo, token string, managerAuth func(resource, token string, object string) bool) ([]*bean.UserInfo, error)
SelfRegisterUserIfNotExists(userInfo *bean.UserInfo) ([]*bean.UserInfo, error)
UpdateUser(userInfo *bean.UserInfo, token string, checkRBACForUserUpdate func(token string, userInfo *bean.UserInfo, isUserAlreadySuperAdmin bool,
eliminatedRoleFilters, eliminatedGroupRoles []*repository.RoleModel) (isAuthorised bool, err error), managerAuth func(resource, token string, object string) bool) (*bean.UserInfo, error)
eliminatedRoleFilters, eliminatedGroupRoles []*repository.RoleModel, mapOfExistingUserRoleGroup map[string]bool) (isAuthorised bool, err error), managerAuth func(resource, token string, object string) bool) (*bean.UserInfo, error)
GetById(id int32) (*bean.UserInfo, error)
GetAll() ([]bean.UserInfo, error)
GetAllWithFilters(request *bean.ListingRequest) (*bean.UserListingResponse, error)
Expand Down Expand Up @@ -635,7 +635,7 @@ func (impl *UserServiceImpl) mergeUserRoleGroup(oldUserRoleGroups []bean.UserRol
}

func (impl *UserServiceImpl) UpdateUser(userInfo *bean.UserInfo, token string, checkRBACForUserUpdate func(token string, userInfo *bean.UserInfo,
isUserAlreadySuperAdmin bool, eliminatedRoleFilters, eliminatedGroupRoles []*repository.RoleModel) (isAuthorised bool, err error), managerAuth func(resource, token string, object string) bool) (*bean.UserInfo, error) {
isUserAlreadySuperAdmin bool, eliminatedRoleFilters, eliminatedGroupRoles []*repository.RoleModel, mapOfExistingUserRoleGroup map[string]bool) (isAuthorised bool, err error), managerAuth func(resource, token string, object string) bool) (*bean.UserInfo, error) {
//checking if request for same user is being processed
isLocked := impl.getUserReqLockStateById(userInfo.Id)
if isLocked {
Expand Down Expand Up @@ -684,6 +684,7 @@ func (impl *UserServiceImpl) UpdateUser(userInfo *bean.UserInfo, token string, c
//loading policy for safety
casbin2.LoadPolicy()
var eliminatedRoles, eliminatedGroupRoles []*repository.RoleModel
mapOfExistingUserRoleGroup := make(map[string]bool)
if userInfo.SuperAdmin == false {
//Starts Role and Mapping
userRoleModels, err := impl.userAuthRepository.GetUserRoleMappingByUserId(model.Id)
Expand Down Expand Up @@ -732,6 +733,7 @@ func (impl *UserServiceImpl) UpdateUser(userInfo *bean.UserInfo, token string, c
}
for _, oldItem := range userCasbinRoles {
oldGroupMap[oldItem] = oldItem
mapOfExistingUserRoleGroup[oldItem] = true
}
// START GROUP POLICY
for _, item := range userInfo.UserRoleGroup {
Expand Down Expand Up @@ -802,7 +804,7 @@ func (impl *UserServiceImpl) UpdateUser(userInfo *bean.UserInfo, token string, c
}

if checkRBACForUserUpdate != nil {
isAuthorised, err := checkRBACForUserUpdate(token, userInfo, isUserSuperAdmin, eliminatedRoles, eliminatedGroupRoles)
isAuthorised, err := checkRBACForUserUpdate(token, userInfo, isUserSuperAdmin, eliminatedRoles, eliminatedGroupRoles, mapOfExistingUserRoleGroup)
if err != nil {
impl.logger.Errorw("error in checking RBAC for user update", "err", err, "userInfo", userInfo)
return nil, err
Expand Down
4 changes: 4 additions & 0 deletions pkg/auth/user/helper/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,3 +93,7 @@ func CreateErrorMessageForUserRoleGroups(restrictedGroups []bean2.RestrictedGrou
}
return errorMessageForGroupsWithoutSuperAdmin, errorMessageForGroupsWithSuperAdmin
}

func GetCasbinNameFromRoleGroupName(name string) string {
return "group:" + strings.ReplaceAll(strings.ToLower(name), " ", "_")
}
Loading
Loading