From eabed57335a6a1171f4e16a4d543c02517a6c895 Mon Sep 17 00:00:00 2001 From: Ash-exp Date: Tue, 29 Aug 2023 11:36:26 +0530 Subject: [PATCH 1/9] feat: added validation for create app workflow --- api/appbean/AppDetail.go | 22 +-- api/restHandler/CoreAppRestHandler.go | 135 ++++++++++++++---- .../pipelineConfig/MaterialRepository.go | 12 ++ wire_gen.go | 2 +- 4 files changed, 135 insertions(+), 36 deletions(-) diff --git a/api/appbean/AppDetail.go b/api/appbean/AppDetail.go index d44108eff81..701aa64e667 100644 --- a/api/appbean/AppDetail.go +++ b/api/appbean/AppDetail.go @@ -20,9 +20,9 @@ type AppDetail struct { type AppWorkflowCloneDto struct { AppId int `json:"appId"` - AppName string `json:"appName"` - AppWorkflows []*AppWorkflow `json:"workflows"` - EnvironmentOverrides map[string]*EnvironmentOverride `json:"environmentOverride"` + AppName string `json:"appName" validate:"required"` + AppWorkflows []*AppWorkflow `json:"workflows,omitempty" validate:"dive"` + EnvironmentOverrides map[string]*EnvironmentOverride `json:"environmentOverride,omitempty" validate:"dive"` } type AppMetadata struct { @@ -71,15 +71,15 @@ type DeploymentTemplate struct { } type AppWorkflow struct { - Name string `json:"name"` - CiPipeline *CiPipelineDetails `json:"ciPipeline"` - CdPipelines []*CdPipelineDetails `json:"cdPipelines"` + Name string `json:"name" validate:"required"` + CiPipeline *CiPipelineDetails `json:"ciPipeline" validate:"dive,required"` + CdPipelines []*CdPipelineDetails `json:"cdPipelines,omitempty" validate:"dive"` } type CiPipelineDetails struct { Name string `json:"name" validate:"required"` //name suffix of corresponding pipeline IsManual bool `json:"isManual" validate:"required"` - CiPipelineMaterialsConfig []*CiPipelineMaterialConfig `json:"ciPipelineMaterialsConfig"` + CiPipelineMaterialsConfig []*CiPipelineMaterialConfig `json:"ciPipelineMaterialsConfig" validate:"dive,min=1"` DockerBuildArgs map[string]string `json:"dockerBuildArgs"` BeforeDockerBuildScripts []*BuildScript `json:"beforeDockerBuildScripts"` AfterDockerBuildScripts []*BuildScript `json:"afterDockerBuildScripts"` @@ -93,7 +93,7 @@ type CiPipelineDetails struct { } type CiPipelineMaterialConfig struct { - Type pipelineConfig.SourceType `json:"type,omitempty" validate:"oneof=SOURCE_TYPE_BRANCH_FIXED WEBHOOK"` + Type pipelineConfig.SourceType `json:"type,omitempty" validate:"oneof=SOURCE_TYPE_BRANCH_FIXED SOURCE_TYPE_BRANCH_REGEX SOURCE_TYPE_TAG_ANY WEBHOOK"` Value string `json:"value,omitempty" ` CheckoutPath string `json:"checkoutPath"` GitMaterialId int `json:"gitMaterialId"` @@ -107,9 +107,9 @@ type BuildScript struct { } type CdPipelineDetails struct { - Name string `json:"name"` //pipelineName - EnvironmentName string `json:"environmentName" ` - TriggerType pipelineConfig.TriggerType `json:"triggerType" validate:"required"` + Name string `json:"name" validate:"required"` //pipelineName + EnvironmentName string `json:"environmentName" validate:"required"` + TriggerType pipelineConfig.TriggerType `json:"triggerType" validate:"oneof=AUTOMATIC MANUAL"` DeploymentAppType string `json:"deploymentAppType"` DeploymentStrategyType chartRepoRepository.DeploymentStrategy `json:"deploymentType,omitempty"` // DeploymentStrategies []*DeploymentStrategy `json:"deploymentStrategies"` diff --git a/api/restHandler/CoreAppRestHandler.go b/api/restHandler/CoreAppRestHandler.go index d2f90dd0661..294e417125f 100644 --- a/api/restHandler/CoreAppRestHandler.go +++ b/api/restHandler/CoreAppRestHandler.go @@ -96,6 +96,7 @@ type CoreAppRestHandlerImpl struct { teamService team.TeamService argoUserService argo.ArgoUserService pipelineStageService pipeline.PipelineStageService + ciPipelineRepository pipelineConfig.CiPipelineRepository } func NewCoreAppRestHandlerImpl(logger *zap.SugaredLogger, userAuthService user.UserService, validator *validator.Validate, enforcerUtil rbac.EnforcerUtil, @@ -105,7 +106,7 @@ func NewCoreAppRestHandlerImpl(logger *zap.SugaredLogger, userAuthService user.U materialRepository pipelineConfig.MaterialRepository, gitProviderRepo repository.GitProviderRepository, appWorkflowRepository appWorkflow2.AppWorkflowRepository, environmentRepository repository2.EnvironmentRepository, configMapRepository chartConfig.ConfigMapRepository, envConfigRepo chartConfig.EnvConfigOverrideRepository, chartRepo chartRepoRepository.ChartRepository, teamService team.TeamService, - argoUserService argo.ArgoUserService, pipelineStageService pipeline.PipelineStageService) *CoreAppRestHandlerImpl { + argoUserService argo.ArgoUserService, pipelineStageService pipeline.PipelineStageService, ciPipelineRepository pipelineConfig.CiPipelineRepository) *CoreAppRestHandlerImpl { handler := &CoreAppRestHandlerImpl{ logger: logger, userAuthService: userAuthService, @@ -130,6 +131,7 @@ func NewCoreAppRestHandlerImpl(logger *zap.SugaredLogger, userAuthService user.U teamService: teamService, argoUserService: argoUserService, pipelineStageService: pipelineStageService, + ciPipelineRepository: ciPipelineRepository, } return handler } @@ -297,6 +299,19 @@ func (handler CoreAppRestHandlerImpl) CreateApp(w http.ResponseWriter, r *http.R handler.logger.Infow("creating app v2", "createAppRequest", createAppRequest) + // validate payload starts + createAppWorkflowReq := appBean.AppWorkflowCloneDto{ + AppName: createAppRequest.Metadata.AppName, + AppWorkflows: createAppRequest.AppWorkflows, + EnvironmentOverrides: createAppRequest.EnvironmentOverrides, + } + err, statusCode := handler.ValidateAppWorkflowRequest(&createAppWorkflowReq, token) + if err != nil { + common.WriteJsonResp(w, err, nil, statusCode) + return + } + // validate payload ends + //creating blank app starts createBlankAppResp, err, statusCode := handler.createBlankApp(createAppRequest.Metadata, userId) if err != nil { @@ -387,7 +402,7 @@ func (handler CoreAppRestHandlerImpl) CreateApp(w http.ResponseWriter, r *http.R //creating workflow starts if createAppRequest.AppWorkflows != nil { - err, statusCode = handler.createWorkflows(ctx, appId, userId, createAppRequest.AppWorkflows, token, createAppRequest.Metadata.AppName) + err, statusCode = handler.createWorkflows(ctx, appId, userId, createAppRequest.AppWorkflows) if err != nil { errResp = multierror.Append(errResp, err) errInAppDelete := handler.deleteApp(ctx, appId, userId) @@ -402,7 +417,7 @@ func (handler CoreAppRestHandlerImpl) CreateApp(w http.ResponseWriter, r *http.R //creating environment override starts if createAppRequest.EnvironmentOverrides != nil { - err, statusCode = handler.createEnvOverrides(ctx, appId, userId, createAppRequest.EnvironmentOverrides, token) + err, statusCode = handler.createEnvOverrides(ctx, appId, userId, createAppRequest.EnvironmentOverrides) if err != nil { errResp = multierror.Append(errResp, err) errInAppDelete := handler.deleteApp(ctx, appId, userId) @@ -1522,7 +1537,7 @@ func (handler CoreAppRestHandlerImpl) createGlobalSecrets(appId int, userId int3 } // create app workflows -func (handler CoreAppRestHandlerImpl) createWorkflows(ctx context.Context, appId int, userId int32, workflows []*appBean.AppWorkflow, token string, appName string) (error, int) { +func (handler CoreAppRestHandlerImpl) createWorkflows(ctx context.Context, appId int, userId int32, workflows []*appBean.AppWorkflow) (error, int) { handler.logger.Infow("Create App - creating workflows", "appId", appId, "workflows size", len(workflows)) for _, workflow := range workflows { //Create workflow starts (we need to create workflow with given name) @@ -1542,7 +1557,7 @@ func (handler CoreAppRestHandlerImpl) createWorkflows(ctx context.Context, appId //Creating CI pipeline ends //Creating CD pipeline starts - err = handler.createCdPipelines(ctx, appId, userId, workflowId, ciPipelineId, workflow.CdPipelines, token, appName) + err = handler.createCdPipelines(ctx, appId, userId, workflowId, ciPipelineId, workflow.CdPipelines) if err != nil { handler.logger.Errorw("err in saving cd pipelines", err, "appId", appId) return err, http.StatusInternalServerError @@ -1591,8 +1606,8 @@ func (handler CoreAppRestHandlerImpl) createCiPipeline(appId int, userId int32, //finding gitMaterial by appId and checkoutPath gitMaterial, err = handler.materialRepository.FindByAppIdAndCheckoutPath(appId, ciMaterial.CheckoutPath) } else { - //if linkedci find git material by it's id - gitMaterial, err = handler.materialRepository.FindById(ciMaterial.GitMaterialId) + //if linked CI find git material by it's parentAppId and Id + gitMaterial, err = handler.materialRepository.FindByAppIdAndId(ciPipelineData.ParentAppId, ciMaterial.GitMaterialId) } if err != nil { handler.logger.Errorw("service err, FindByAppIdAndCheckoutPath in CreateWorkflows", "err", err, "appId", appId) @@ -1652,7 +1667,7 @@ func (handler CoreAppRestHandlerImpl) createCiPipeline(appId int, userId int32, return res.CiPipelines[0].Id, nil } -func (handler CoreAppRestHandlerImpl) createCdPipelines(ctx context.Context, appId int, userId int32, workflowId int, ciPipelineId int, cdPipelines []*appBean.CdPipelineDetails, token string, appName string) error { +func (handler CoreAppRestHandlerImpl) createCdPipelines(ctx context.Context, appId int, userId int32, workflowId int, ciPipelineId int, cdPipelines []*appBean.CdPipelineDetails) error { var cdPipelineRequestConfigs []*bean.CDPipelineConfigObject for _, cdPipeline := range cdPipelines { @@ -1670,12 +1685,7 @@ func (handler CoreAppRestHandlerImpl) createCdPipelines(ctx context.Context, app return err } - // RBAC starts - object := handler.enforcerUtil.GetAppRBACByAppNameAndEnvId(appName, envModel.Id) - if ok := handler.enforcer.Enforce(token, casbin.ResourceEnvironment, casbin.ActionCreate, object); !ok { - return errors.New("unauthorized User") - } - // RBAC ends + // RBAC has already been verified in Validation function // build model cdPipelineRequestConfig := &bean.CDPipelineConfigObject{ @@ -1722,7 +1732,7 @@ func (handler CoreAppRestHandlerImpl) createCdPipelines(ctx context.Context, app } // create environment overrides -func (handler CoreAppRestHandlerImpl) createEnvOverrides(ctx context.Context, appId int, userId int32, environmentOverrides map[string]*appBean.EnvironmentOverride, token string) (error, int) { +func (handler CoreAppRestHandlerImpl) createEnvOverrides(ctx context.Context, appId int, userId int32, environmentOverrides map[string]*appBean.EnvironmentOverride) (error, int) { handler.logger.Infow("Create App - creating env overrides", "appId", appId) for envName, envOverrideValues := range environmentOverrides { @@ -1739,12 +1749,7 @@ func (handler CoreAppRestHandlerImpl) createEnvOverrides(ctx context.Context, ap return err, http.StatusInternalServerError } - // RBAC starts - object := handler.enforcerUtil.GetEnvRBACNameByAppId(appId, envModel.Id) - if ok := handler.enforcer.Enforce(token, casbin.ResourceEnvironment, casbin.ActionUpdate, object); !ok { - return fmt.Errorf("unauthorized user"), http.StatusForbidden - } - // RBAC ends + // RBAC has already been verified in Validation function envId := envModel.Id @@ -2088,6 +2093,81 @@ func ExtractErrorType(err error) int { } } +func (handler CoreAppRestHandlerImpl) validateCdPipelines(cdPipelines []*appBean.CdPipelineDetails, appName, token string) (error, int) { + for _, cdPipeline := range cdPipelines { + envName := cdPipeline.EnvironmentName + envModel, err := handler.environmentRepository.FindByName(envName) + if err != nil || envModel == nil { + return fmt.Errorf("invalid environment name %s for cd pipeline", envName), http.StatusBadRequest + } + + // validation RBAC starts + object := handler.enforcerUtil.GetAppRBACByAppNameAndEnvId(appName, envModel.Id) + if ok := handler.enforcer.Enforce(token, casbin.ResourceEnvironment, casbin.ActionCreate, object); !ok { + return fmt.Errorf("unauthorized user for the environment %s", envName), http.StatusForbidden + } + // validation RBAC ends + + // validate deploymentStrategy for each cd pipeline + for _, deploymentStrategy := range cdPipeline.DeploymentStrategies { + _, err = json.Marshal(deploymentStrategy.Config) + if err != nil { + return fmt.Errorf("err in converting deployment strategies for creating the cd pipeline %s", cdPipeline.Name), http.StatusBadRequest + } + } + } + return nil, http.StatusOK +} + +func (handler CoreAppRestHandlerImpl) ValidateAppWorkflowRequest(createAppWorkflowRequest *appBean.AppWorkflowCloneDto, token string) (error, int) { + // validation for app workflow request + if createAppWorkflowRequest.AppWorkflows != nil { + for _, workflow := range createAppWorkflowRequest.AppWorkflows { + // if ci pipeline is of external type, then throw error as we are not supporting it as of now + if workflow.CiPipeline.ParentCiPipeline == 0 && workflow.CiPipeline.ParentAppId == 0 && workflow.CiPipeline.IsExternal { + return fmt.Errorf("external ci pipeline creation is not supported yet"), http.StatusUnprocessableEntity + } + // for linked CI, parentCiPipeline should be a valid ciPipelineId and the given ParentAppId should be matched + if workflow.CiPipeline.ParentCiPipeline != 0 && workflow.CiPipeline.ParentAppId != 0 { + ciPipeline, err := handler.ciPipelineRepository.FindById(workflow.CiPipeline.ParentCiPipeline) + if err != nil { + return fmt.Errorf("error in finding ci pipeline with the given parentCiPipeline '%v'", workflow.CiPipeline.ParentCiPipeline), http.StatusBadRequest + } + if ciPipeline.AppId != workflow.CiPipeline.ParentAppId { + return fmt.Errorf("invalid parentAppId '%v' for the given parentCiPipeline '%v'", workflow.CiPipeline.ParentAppId, workflow.CiPipeline.ParentCiPipeline), http.StatusBadRequest + } + } + // validate environment name and rbac object of payload + if workflow.CdPipelines != nil { + err, statusCode := handler.validateCdPipelines(workflow.CdPipelines, createAppWorkflowRequest.AppName, token) + if err != nil { + return err, statusCode + } + } + } + } + // validation for environment override request + if createAppWorkflowRequest.EnvironmentOverrides != nil { + for envName, _ := range createAppWorkflowRequest.EnvironmentOverrides { + envModel, err := handler.environmentRepository.FindByName(envName) + + if err != nil || envModel == nil { + return fmt.Errorf("invalid environment name '%s' for environment override", envName), http.StatusBadRequest + } + if envModel.IsVirtualEnvironment { + return fmt.Errorf("virtual environment '%s' for cd pipeline is not supported yet", envName), http.StatusUnprocessableEntity + } + // validate RBAC starts + object := handler.enforcerUtil.GetAppRBACByAppNameAndEnvId(createAppWorkflowRequest.AppName, envModel.Id) + if ok := handler.enforcer.Enforce(token, casbin.ResourceEnvironment, casbin.ActionUpdate, object); !ok { + return fmt.Errorf("unauthorized user for the environment '%s'", envName), http.StatusForbidden + } + // validate RBAC ends + } + } + return nil, http.StatusOK +} + func (handler CoreAppRestHandlerImpl) CreateAppWorkflow(w http.ResponseWriter, r *http.Request) { decoder := json.NewDecoder(r.Body) userId, err := handler.userAuthService.GetLoggedInUser(r) @@ -2134,8 +2214,15 @@ func (handler CoreAppRestHandlerImpl) CreateAppWorkflow(w http.ResponseWriter, r } //rbac ends + // validate payload starts + err, statusCode := handler.ValidateAppWorkflowRequest(&createAppRequest, token) + if err != nil { + common.WriteJsonResp(w, err, nil, statusCode) + return + } + // validate payload ends + handler.logger.Infow("creating app workflow created ", "createAppRequest", createAppRequest) - var statusCode int //creating workflow starts if createAppRequest.AppWorkflows != nil { @@ -2143,7 +2230,7 @@ func (handler CoreAppRestHandlerImpl) CreateAppWorkflow(w http.ResponseWriter, r common.WriteJsonResp(w, err, "please provide only one workflow at one time", http.StatusBadRequest) return } - err, statusCode = handler.createWorkflows(ctx, createAppRequest.AppId, userId, createAppRequest.AppWorkflows, token, app.AppName) + err, statusCode = handler.createWorkflows(ctx, createAppRequest.AppId, userId, createAppRequest.AppWorkflows) if err != nil { common.WriteJsonResp(w, err, nil, statusCode) return @@ -2153,7 +2240,7 @@ func (handler CoreAppRestHandlerImpl) CreateAppWorkflow(w http.ResponseWriter, r //creating environment override starts if createAppRequest.EnvironmentOverrides != nil && len(createAppRequest.EnvironmentOverrides) > 0 { - err, statusCode = handler.createEnvOverrides(ctx, createAppRequest.AppId, userId, createAppRequest.EnvironmentOverrides, token) + err, statusCode = handler.createEnvOverrides(ctx, createAppRequest.AppId, userId, createAppRequest.EnvironmentOverrides) if err != nil { common.WriteJsonResp(w, err, nil, statusCode) return diff --git a/internal/sql/repository/pipelineConfig/MaterialRepository.go b/internal/sql/repository/pipelineConfig/MaterialRepository.go index eb1e4ed152c..eb7349e530f 100644 --- a/internal/sql/repository/pipelineConfig/MaterialRepository.go +++ b/internal/sql/repository/pipelineConfig/MaterialRepository.go @@ -57,6 +57,7 @@ type MaterialRepository interface { Update(materials []*GitMaterial) error FindByAppId(appId int) ([]*GitMaterial, error) FindById(Id int) (*GitMaterial, error) + FindByAppIdAndId(appId, id int) (*GitMaterial, error) UpdateMaterialScmId(material *GitMaterial) error FindByAppIdAndCheckoutPath(appId int, checkoutPath string) (*GitMaterial, error) FindByGitProviderId(gitProviderId int) (materials []*GitMaterial, err error) @@ -92,6 +93,17 @@ func (repo MaterialRepositoryImpl) FindById(Id int) (*GitMaterial, error) { return material, err } +func (repo MaterialRepositoryImpl) FindByAppIdAndId(appId, id int) (*GitMaterial, error) { + material := &GitMaterial{} + err := repo.dbConnection.Model(material). + Column("git_material.*", "GitProvider"). + Where("app_id = ? ", appId). + Where("git_material.id =? ", id). + Where("git_material.active =? ", true). + Select() + return material, err +} + func (repo MaterialRepositoryImpl) MaterialExists(url string) (bool, error) { material := &GitMaterial{} exists, err := repo.dbConnection. diff --git a/wire_gen.go b/wire_gen.go index 7663ccf8c17..0caf1f934cd 100644 --- a/wire_gen.go +++ b/wire_gen.go @@ -677,7 +677,7 @@ func InitializeApp() (*App, error) { webhookListenerRouterImpl := router.NewWebhookListenerRouterImpl(webhookEventHandlerImpl) appRestHandlerImpl := restHandler.NewAppRestHandlerImpl(sugaredLogger, appCrudOperationServiceImpl, userServiceImpl, validate, enforcerUtilImpl, enforcerImpl, helmAppServiceImpl, enforcerUtilHelmImpl, genericNoteServiceImpl) appRouterImpl := router.NewAppRouterImpl(sugaredLogger, appRestHandlerImpl) - coreAppRestHandlerImpl := restHandler.NewCoreAppRestHandlerImpl(sugaredLogger, userServiceImpl, validate, enforcerUtilImpl, enforcerImpl, appCrudOperationServiceImpl, pipelineBuilderImpl, gitRegistryConfigImpl, chartServiceImpl, configMapServiceImpl, appListingServiceImpl, propertiesConfigServiceImpl, appWorkflowServiceImpl, materialRepositoryImpl, gitProviderRepositoryImpl, appWorkflowRepositoryImpl, environmentRepositoryImpl, configMapRepositoryImpl, envConfigOverrideRepositoryImpl, chartRepositoryImpl, teamServiceImpl, argoUserServiceImpl, pipelineStageServiceImpl) + coreAppRestHandlerImpl := restHandler.NewCoreAppRestHandlerImpl(sugaredLogger, userServiceImpl, validate, enforcerUtilImpl, enforcerImpl, appCrudOperationServiceImpl, pipelineBuilderImpl, gitRegistryConfigImpl, chartServiceImpl, configMapServiceImpl, appListingServiceImpl, propertiesConfigServiceImpl, appWorkflowServiceImpl, materialRepositoryImpl, gitProviderRepositoryImpl, appWorkflowRepositoryImpl, environmentRepositoryImpl, configMapRepositoryImpl, envConfigOverrideRepositoryImpl, chartRepositoryImpl, teamServiceImpl, argoUserServiceImpl, pipelineStageServiceImpl, ciPipelineRepositoryImpl) coreAppRouterImpl := router.NewCoreAppRouterImpl(coreAppRestHandlerImpl) helmAppRestHandlerImpl := client3.NewHelmAppRestHandlerImpl(sugaredLogger, helmAppServiceImpl, enforcerImpl, clusterServiceImplExtended, enforcerUtilHelmImpl, appStoreDeploymentCommonServiceImpl, userServiceImpl, attributesServiceImpl, serverEnvConfigServerEnvConfig) helmAppRouterImpl := client3.NewHelmAppRouterImpl(helmAppRestHandlerImpl) From e8792eb46127efef61264075c223e9bb81435983 Mon Sep 17 00:00:00 2001 From: Ash-exp Date: Tue, 29 Aug 2023 13:16:15 +0530 Subject: [PATCH 2/9] fixed: CiPipelineDetails validation --- api/appbean/AppDetail.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/appbean/AppDetail.go b/api/appbean/AppDetail.go index 701aa64e667..ce1edccca7f 100644 --- a/api/appbean/AppDetail.go +++ b/api/appbean/AppDetail.go @@ -78,7 +78,7 @@ type AppWorkflow struct { type CiPipelineDetails struct { Name string `json:"name" validate:"required"` //name suffix of corresponding pipeline - IsManual bool `json:"isManual" validate:"required"` + IsManual bool `json:"isManual"` CiPipelineMaterialsConfig []*CiPipelineMaterialConfig `json:"ciPipelineMaterialsConfig" validate:"dive,min=1"` DockerBuildArgs map[string]string `json:"dockerBuildArgs"` BeforeDockerBuildScripts []*BuildScript `json:"beforeDockerBuildScripts"` From 0ab63685633d50952123adf2406a19396c48216b Mon Sep 17 00:00:00 2001 From: Ash-exp Date: Tue, 29 Aug 2023 13:48:46 +0530 Subject: [PATCH 3/9] fixed: virtual env validation --- api/restHandler/CoreAppRestHandler.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/api/restHandler/CoreAppRestHandler.go b/api/restHandler/CoreAppRestHandler.go index 294e417125f..a890f652502 100644 --- a/api/restHandler/CoreAppRestHandler.go +++ b/api/restHandler/CoreAppRestHandler.go @@ -2100,7 +2100,9 @@ func (handler CoreAppRestHandlerImpl) validateCdPipelines(cdPipelines []*appBean if err != nil || envModel == nil { return fmt.Errorf("invalid environment name %s for cd pipeline", envName), http.StatusBadRequest } - + if envModel.IsVirtualEnvironment { + return fmt.Errorf("virtual environment '%s' for cd pipeline is not supported yet", envName), http.StatusUnprocessableEntity + } // validation RBAC starts object := handler.enforcerUtil.GetAppRBACByAppNameAndEnvId(appName, envModel.Id) if ok := handler.enforcer.Enforce(token, casbin.ResourceEnvironment, casbin.ActionCreate, object); !ok { From ab250351cc59bbb2d0b4f02e7de24ca5edde4215 Mon Sep 17 00:00:00 2001 From: Ash-exp Date: Tue, 29 Aug 2023 15:12:02 +0530 Subject: [PATCH 4/9] fixed: validation struct --- api/appbean/AppDetail.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/api/appbean/AppDetail.go b/api/appbean/AppDetail.go index ce1edccca7f..974d369195d 100644 --- a/api/appbean/AppDetail.go +++ b/api/appbean/AppDetail.go @@ -8,14 +8,14 @@ import ( ) type AppDetail struct { - Metadata *AppMetadata `json:"metadata,notnull" validate:"required"` + Metadata *AppMetadata `json:"metadata,notnull" validate:"dive,required"` GitMaterials []*GitMaterial `json:"gitMaterials,notnull"` DockerConfig *DockerConfig `json:"dockerConfig"` GlobalDeploymentTemplate *DeploymentTemplate `json:"globalDeploymentTemplate,notnull"` - AppWorkflows []*AppWorkflow `json:"workflows"` + AppWorkflows []*AppWorkflow `json:"workflows,omitempty" validate:"dive"` GlobalConfigMaps []*ConfigMap `json:"globalConfigMaps"` GlobalSecrets []*Secret `json:"globalSecrets"` - EnvironmentOverrides map[string]*EnvironmentOverride `json:"environmentOverride"` + EnvironmentOverrides map[string]*EnvironmentOverride `json:"environmentOverride,omitempty" validate:"dive"` } type AppWorkflowCloneDto struct { From ee12a963c9f099a6cf74c5716e06edbcee26c920 Mon Sep 17 00:00:00 2001 From: Ash-exp Date: Tue, 29 Aug 2023 15:14:54 +0530 Subject: [PATCH 5/9] fixed: validation struct --- api/appbean/AppDetail.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/api/appbean/AppDetail.go b/api/appbean/AppDetail.go index 974d369195d..eec8d743b13 100644 --- a/api/appbean/AppDetail.go +++ b/api/appbean/AppDetail.go @@ -9,12 +9,12 @@ import ( type AppDetail struct { Metadata *AppMetadata `json:"metadata,notnull" validate:"dive,required"` - GitMaterials []*GitMaterial `json:"gitMaterials,notnull"` - DockerConfig *DockerConfig `json:"dockerConfig"` - GlobalDeploymentTemplate *DeploymentTemplate `json:"globalDeploymentTemplate,notnull"` + GitMaterials []*GitMaterial `json:"gitMaterials,notnull" validate:"dive"` + DockerConfig *DockerConfig `json:"dockerConfig" validate:"dive"` + GlobalDeploymentTemplate *DeploymentTemplate `json:"globalDeploymentTemplate,notnull" validate:"dive"` AppWorkflows []*AppWorkflow `json:"workflows,omitempty" validate:"dive"` - GlobalConfigMaps []*ConfigMap `json:"globalConfigMaps"` - GlobalSecrets []*Secret `json:"globalSecrets"` + GlobalConfigMaps []*ConfigMap `json:"globalConfigMaps,omitempty" validate:"dive"` + GlobalSecrets []*Secret `json:"globalSecrets,omitempty" validate:"dive"` EnvironmentOverrides map[string]*EnvironmentOverride `json:"environmentOverride,omitempty" validate:"dive"` } From 978848117b9b1d9d03e81ce26b96bf3c1203e878 Mon Sep 17 00:00:00 2001 From: Ash-exp Date: Tue, 29 Aug 2023 15:16:50 +0530 Subject: [PATCH 6/9] fixed: validation struct --- api/appbean/AppDetail.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/appbean/AppDetail.go b/api/appbean/AppDetail.go index eec8d743b13..ba6a101f575 100644 --- a/api/appbean/AppDetail.go +++ b/api/appbean/AppDetail.go @@ -9,7 +9,7 @@ import ( type AppDetail struct { Metadata *AppMetadata `json:"metadata,notnull" validate:"dive,required"` - GitMaterials []*GitMaterial `json:"gitMaterials,notnull" validate:"dive"` + GitMaterials []*GitMaterial `json:"gitMaterials,notnull" validate:"dive,min=1"` DockerConfig *DockerConfig `json:"dockerConfig" validate:"dive"` GlobalDeploymentTemplate *DeploymentTemplate `json:"globalDeploymentTemplate,notnull" validate:"dive"` AppWorkflows []*AppWorkflow `json:"workflows,omitempty" validate:"dive"` From fafbda3eb58970bb28b3f5a3e9e9048121e5794f Mon Sep 17 00:00:00 2001 From: Ash-exp Date: Wed, 30 Aug 2023 13:22:08 +0530 Subject: [PATCH 7/9] chore: renamed a function --- api/restHandler/CoreAppRestHandler.go | 2 +- internal/sql/repository/pipelineConfig/MaterialRepository.go | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/api/restHandler/CoreAppRestHandler.go b/api/restHandler/CoreAppRestHandler.go index a890f652502..bac54915d6e 100644 --- a/api/restHandler/CoreAppRestHandler.go +++ b/api/restHandler/CoreAppRestHandler.go @@ -1607,7 +1607,7 @@ func (handler CoreAppRestHandlerImpl) createCiPipeline(appId int, userId int32, gitMaterial, err = handler.materialRepository.FindByAppIdAndCheckoutPath(appId, ciMaterial.CheckoutPath) } else { //if linked CI find git material by it's parentAppId and Id - gitMaterial, err = handler.materialRepository.FindByAppIdAndId(ciPipelineData.ParentAppId, ciMaterial.GitMaterialId) + gitMaterial, err = handler.materialRepository.FindByAppIdAndGitMaterialId(ciPipelineData.ParentAppId, ciMaterial.GitMaterialId) } if err != nil { handler.logger.Errorw("service err, FindByAppIdAndCheckoutPath in CreateWorkflows", "err", err, "appId", appId) diff --git a/internal/sql/repository/pipelineConfig/MaterialRepository.go b/internal/sql/repository/pipelineConfig/MaterialRepository.go index eb7349e530f..5dc8b4456e2 100644 --- a/internal/sql/repository/pipelineConfig/MaterialRepository.go +++ b/internal/sql/repository/pipelineConfig/MaterialRepository.go @@ -57,7 +57,7 @@ type MaterialRepository interface { Update(materials []*GitMaterial) error FindByAppId(appId int) ([]*GitMaterial, error) FindById(Id int) (*GitMaterial, error) - FindByAppIdAndId(appId, id int) (*GitMaterial, error) + FindByAppIdAndGitMaterialId(appId, id int) (*GitMaterial, error) UpdateMaterialScmId(material *GitMaterial) error FindByAppIdAndCheckoutPath(appId int, checkoutPath string) (*GitMaterial, error) FindByGitProviderId(gitProviderId int) (materials []*GitMaterial, err error) @@ -93,7 +93,7 @@ func (repo MaterialRepositoryImpl) FindById(Id int) (*GitMaterial, error) { return material, err } -func (repo MaterialRepositoryImpl) FindByAppIdAndId(appId, id int) (*GitMaterial, error) { +func (repo MaterialRepositoryImpl) FindByAppIdAndGitMaterialId(appId, id int) (*GitMaterial, error) { material := &GitMaterial{} err := repo.dbConnection.Model(material). Column("git_material.*", "GitProvider"). From d57a18702363a22d17574e9a8332891bef10f475 Mon Sep 17 00:00:00 2001 From: Ash-exp Date: Mon, 4 Sep 2023 10:21:54 +0530 Subject: [PATCH 8/9] fixed: updated validation --- api/restHandler/CoreAppRestHandler.go | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/api/restHandler/CoreAppRestHandler.go b/api/restHandler/CoreAppRestHandler.go index bac54915d6e..2bc859c9f98 100644 --- a/api/restHandler/CoreAppRestHandler.go +++ b/api/restHandler/CoreAppRestHandler.go @@ -51,6 +51,7 @@ import ( "github.com/hashicorp/go-multierror" "go.uber.org/zap" "gopkg.in/go-playground/validator.v9" + "k8s.io/utils/strings/slices" "net/http" "strconv" "strings" @@ -2139,6 +2140,29 @@ func (handler CoreAppRestHandlerImpl) ValidateAppWorkflowRequest(createAppWorkfl return fmt.Errorf("invalid parentAppId '%v' for the given parentCiPipeline '%v'", workflow.CiPipeline.ParentAppId, workflow.CiPipeline.ParentCiPipeline), http.StatusBadRequest } } + ciMaterialCheckoutPaths := make([]string, 0) + for _, ciPipelineMaterialConfig := range workflow.CiPipeline.CiPipelineMaterialsConfig { + // value for webhook type CiPipelineMaterial should be a valid json string + if ciPipelineMaterialConfig.Type == pipelineConfig.SOURCE_TYPE_WEBHOOK { + var jsonValueMap map[string]interface{} + err := json.Unmarshal([]byte(ciPipelineMaterialConfig.Value), &jsonValueMap) + if err != nil { + return fmt.Errorf("invalid value for the ciPipelineMaterialsConfig type %s", string(ciPipelineMaterialConfig.Type)), http.StatusBadRequest + } + if _, ok := jsonValueMap["eventId"]; !ok { + return fmt.Errorf("invalid value for the ciPipelineMaterialsConfig type %s, eventId not found", string(ciPipelineMaterialConfig.Type)), http.StatusBadRequest + } + + if _, ok := jsonValueMap["condition"]; !ok { + return fmt.Errorf("invalid value for the ciPipelineMaterialsConfig type %s, condition not found", string(ciPipelineMaterialConfig.Type)), http.StatusBadRequest + } + } + // CiPipelineMaterial checkout paths should be unique + if slices.Contains(ciMaterialCheckoutPaths, ciPipelineMaterialConfig.CheckoutPath) { + return fmt.Errorf(""), http.StatusBadRequest + } + ciMaterialCheckoutPaths = append(ciMaterialCheckoutPaths, ciPipelineMaterialConfig.CheckoutPath) + } // validate environment name and rbac object of payload if workflow.CdPipelines != nil { err, statusCode := handler.validateCdPipelines(workflow.CdPipelines, createAppWorkflowRequest.AppName, token) From 0ff251db66cc796d1b3c9d9ef297707d7efba8e2 Mon Sep 17 00:00:00 2001 From: Ash-exp Date: Mon, 4 Sep 2023 11:30:27 +0530 Subject: [PATCH 9/9] updated: validation for linked CI --- api/restHandler/CoreAppRestHandler.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/api/restHandler/CoreAppRestHandler.go b/api/restHandler/CoreAppRestHandler.go index 2bc859c9f98..2b7ec9edaf0 100644 --- a/api/restHandler/CoreAppRestHandler.go +++ b/api/restHandler/CoreAppRestHandler.go @@ -2132,6 +2132,9 @@ func (handler CoreAppRestHandlerImpl) ValidateAppWorkflowRequest(createAppWorkfl } // for linked CI, parentCiPipeline should be a valid ciPipelineId and the given ParentAppId should be matched if workflow.CiPipeline.ParentCiPipeline != 0 && workflow.CiPipeline.ParentAppId != 0 { + if !workflow.CiPipeline.IsExternal { + return fmt.Errorf("invalid value of isExternal '%v', for linked CI isExternal must be TRUE", workflow.CiPipeline.IsExternal), http.StatusBadRequest + } ciPipeline, err := handler.ciPipelineRepository.FindById(workflow.CiPipeline.ParentCiPipeline) if err != nil { return fmt.Errorf("error in finding ci pipeline with the given parentCiPipeline '%v'", workflow.CiPipeline.ParentCiPipeline), http.StatusBadRequest