diff --git a/api/helm-app/HelmAppRestHandler.go b/api/helm-app/HelmAppRestHandler.go index 49c2da7c14..ea77634234 100644 --- a/api/helm-app/HelmAppRestHandler.go +++ b/api/helm-app/HelmAppRestHandler.go @@ -231,6 +231,13 @@ func (handler *HelmAppRestHandlerImpl) handleFluxApplicationHibernate(r *http.Re return nil, err } + // Validate confirmation name if provided + if hibernateRequest.ConfirmationName != nil { + if *hibernateRequest.ConfirmationName != appIdentifier.AppName { + return nil, errors.New("confirmation name does not match application name") + } + } + if !handler.enforcer.Enforce(token, casbin.ResourceGlobal, casbin.ActionUpdate, "*") { return nil, errors.New("unauthorized") } @@ -243,6 +250,13 @@ func (handler *HelmAppRestHandlerImpl) handleArgoApplicationHibernate(r *http.Re return nil, err } + // Validate confirmation name if provided + if hibernateRequest.ConfirmationName != nil { + if *hibernateRequest.ConfirmationName != appIdentifier.AppName { + return nil, errors.New("confirmation name does not match application name") + } + } + if !handler.enforcer.Enforce(token, casbin.ResourceGlobal, casbin.ActionUpdate, "*") { return nil, errors.New("unauthorized") } @@ -255,6 +269,14 @@ func (handler *HelmAppRestHandlerImpl) handleHelmApplicationHibernate(r *http.Re if err != nil { return nil, err } + + // Validate confirmation name if provided + if hibernateRequest.ConfirmationName != nil { + if *hibernateRequest.ConfirmationName != appIdentifier.ReleaseName { + return nil, errors.New("confirmation name does not match application name") + } + } + rbacObject, rbacObject2 := handler.enforcerUtil.GetHelmObjectByClusterIdNamespaceAndAppName( appIdentifier.ClusterId, appIdentifier.Namespace, @@ -317,6 +339,14 @@ func (handler *HelmAppRestHandlerImpl) handleFluxApplicationUnHibernate(r *http. if err != nil { return nil, err } + + // Validate confirmation name if provided + if hibernateRequest.ConfirmationName != nil { + if *hibernateRequest.ConfirmationName != appIdentifier.AppName { + return nil, errors.New("confirmation name does not match application name") + } + } + if !handler.enforcer.Enforce(token, casbin.ResourceGlobal, casbin.ActionUpdate, "*") { return nil, errors.New("unauthorized") } @@ -327,6 +357,14 @@ func (handler *HelmAppRestHandlerImpl) handleArgoApplicationUnHibernate(r *http. if err != nil { return nil, err } + + // Validate confirmation name if provided + if hibernateRequest.ConfirmationName != nil { + if *hibernateRequest.ConfirmationName != appIdentifier.AppName { + return nil, errors.New("confirmation name does not match application name") + } + } + if !handler.enforcer.Enforce(token, casbin.ResourceGlobal, casbin.ActionUpdate, "*") { return nil, errors.New("unauthorized") } @@ -339,6 +377,13 @@ func (handler *HelmAppRestHandlerImpl) handleHelmApplicationUnHibernate(r *http. return nil, err } + // Validate confirmation name if provided + if hibernateRequest.ConfirmationName != nil { + if *hibernateRequest.ConfirmationName != appIdentifier.ReleaseName { + return nil, errors.New("confirmation name does not match application name") + } + } + rbacObject, rbacObject2 := handler.enforcerUtil.GetHelmObjectByClusterIdNamespaceAndAppName( appIdentifier.ClusterId, appIdentifier.Namespace, diff --git a/api/helm-app/openapiClient/model_hibernate_request.go b/api/helm-app/openapiClient/model_hibernate_request.go index 869a78f398..073c245f9c 100644 --- a/api/helm-app/openapiClient/model_hibernate_request.go +++ b/api/helm-app/openapiClient/model_hibernate_request.go @@ -19,6 +19,8 @@ type HibernateRequest struct { // helm app id AppId *string `json:"appId,omitempty"` Resources *[]HibernateTargetObject `json:"resources,omitempty"` + // confirmation name - should match app name for additional confirmation + ConfirmationName *string `json:"confirmationName,omitempty"` } // NewHibernateRequest instantiates a new HibernateRequest object @@ -102,6 +104,38 @@ func (o *HibernateRequest) SetResources(v []HibernateTargetObject) { o.Resources = &v } +// GetConfirmationName returns the ConfirmationName field value if set, zero value otherwise. +func (o *HibernateRequest) GetConfirmationName() string { + if o == nil || o.ConfirmationName == nil { + var ret string + return ret + } + return *o.ConfirmationName +} + +// GetConfirmationNameOk returns a tuple with the ConfirmationName field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *HibernateRequest) GetConfirmationNameOk() (*string, bool) { + if o == nil || o.ConfirmationName == nil { + return nil, false + } + return o.ConfirmationName, true +} + +// HasConfirmationName returns a boolean if a field has been set. +func (o *HibernateRequest) HasConfirmationName() bool { + if o != nil && o.ConfirmationName != nil { + return true + } + + return false +} + +// SetConfirmationName gets a reference to the given string and assigns it to the ConfirmationName field. +func (o *HibernateRequest) SetConfirmationName(v string) { + o.ConfirmationName = &v +} + func (o HibernateRequest) MarshalJSON() ([]byte, error) { toSerialize := map[string]interface{}{} if o.AppId != nil { @@ -110,6 +144,9 @@ func (o HibernateRequest) MarshalJSON() ([]byte, error) { if o.Resources != nil { toSerialize["resources"] = o.Resources } + if o.ConfirmationName != nil { + toSerialize["confirmationName"] = o.ConfirmationName + } return json.Marshal(toSerialize) } diff --git a/pkg/bulkAction/bean/bean.go b/pkg/bulkAction/bean/bean.go index 6a777834b2..add27fbd17 100644 --- a/pkg/bulkAction/bean/bean.go +++ b/pkg/bulkAction/bean/bean.go @@ -106,6 +106,8 @@ type BulkApplicationForEnvironmentPayload struct { AppNamesExcludes []string `json:"appNamesExcludes,omitempty"` UserId int32 `json:"-"` InvalidateCache bool `json:"invalidateCache"` + // confirmation name - should match environment name for additional confirmation + ConfirmationName *string `json:"confirmationName,omitempty"` } type BulkApplicationForEnvironmentResponse struct { diff --git a/pkg/bulkAction/service/BulkUpdateService.go b/pkg/bulkAction/service/BulkUpdateService.go index 817ebfb1cb..9648233ba8 100644 --- a/pkg/bulkAction/service/BulkUpdateService.go +++ b/pkg/bulkAction/service/BulkUpdateService.go @@ -1108,6 +1108,26 @@ type stopAppFunc func(ctx context.Context, req *bean5.StopAppRequest, userMetada // bulkHibernateCommon contains the common bulk-hibernate logic. func (impl BulkUpdateServiceImpl) bulkHibernateCommon(request *bean4.BulkApplicationForEnvironmentPayload, ctx context.Context, token string, checkAuthForBulkActions func(token, appObject, envObject string) bool, stopApp stopAppFunc, userMetadata *bean6.UserMetadata) (*bean4.BulkApplicationHibernateUnhibernateForEnvironmentResponse, error) { + // Validate confirmation name if provided + if request.ConfirmationName != nil { + var envName string + if len(request.EnvName) > 0 { + envName = request.EnvName + } else if request.EnvId != 0 { + // Fetch environment name by ID + env, err := impl.environmentRepository.FindById(request.EnvId) + if err != nil { + impl.logger.Errorw("error in fetching environment by id", "envId", request.EnvId, "err", err) + return nil, fmt.Errorf("error fetching environment details: %v", err) + } + envName = env.Name + } + + if envName != "" && *request.ConfirmationName != envName { + return nil, fmt.Errorf("confirmation name does not match environment name") + } + } + // Fetch pipelines based on filters. var pipelines []*pipelineConfig.Pipeline var err error @@ -1279,6 +1299,26 @@ func (impl BulkUpdateServiceImpl) buildHibernateUnHibernateRequestForHelmPipelin func (impl BulkUpdateServiceImpl) BulkUnHibernate(ctx context.Context, request *bean4.BulkApplicationForEnvironmentPayload, checkAuthForBulkActions func(token string, appObject string, envObject string) bool, userMetadata *bean6.UserMetadata) (*bean4.BulkApplicationHibernateUnhibernateForEnvironmentResponse, error) { + // Validate confirmation name if provided + if request.ConfirmationName != nil { + var envName string + if len(request.EnvName) > 0 { + envName = request.EnvName + } else if request.EnvId != 0 { + // Fetch environment name by ID + env, err := impl.environmentRepository.FindById(request.EnvId) + if err != nil { + impl.logger.Errorw("error in fetching environment by id", "envId", request.EnvId, "err", err) + return nil, fmt.Errorf("error fetching environment details: %v", err) + } + envName = env.Name + } + + if envName != "" && *request.ConfirmationName != envName { + return nil, fmt.Errorf("confirmation name does not match environment name") + } + } + var pipelines []*pipelineConfig.Pipeline var err error if len(request.AppIdIncludes) > 0 {