Skip to content

Commit 628ceec

Browse files
Shivam-nagar23komalreddy3
authored andcommitted
feat: Introduction to feasibility in Deployment (#4862)
* introduction to feasibility * moved feasibility in trigger/devtronApps * feasibility refactorings * refactoring and feasibility manager * removing vulnerability changes * vulnerability checks retract * dry run removed * dry run checks removed * refactoring * removing unnecessary code * comments * trigger request
1 parent 0d8794b commit 628ceec

File tree

10 files changed

+110
-78
lines changed

10 files changed

+110
-78
lines changed

internal/constants/InternalErrorCode.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,10 @@ const (
8888

8989
GitHostCreateFailedAlreadyExists string = "9001"
9090
GitHostCreateFailedInDb string = "9002"
91+
92+
// feasibility errors
93+
OperationPerformError string = "10001"
94+
VulnerabilityFound string = "10002"
9195
)
9296

9397
var AppAlreadyExists = &ErrorCode{"4001", "application %s already exists"}

pkg/cluster/EnvironmentService.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ type EnvironmentService interface {
6565
GetCombinedEnvironmentListForDropDown(token string, isActionUserSuperAdmin bool, auth func(email string, object []string) map[string]bool) ([]*bean2.ClusterEnvDto, error)
6666
GetCombinedEnvironmentListForDropDownByClusterIds(token string, clusterIds []int, auth func(token string, object string) bool) ([]*bean2.ClusterEnvDto, error)
6767
HandleErrorInClusterConnections(clusters []*ClusterBean, respMap map[int]error, clusterExistInDb bool)
68+
GetDetailsById(envId int) (*repository.Environment, error)
6869
}
6970

7071
type EnvironmentServiceImpl struct {
@@ -743,3 +744,12 @@ func (impl EnvironmentServiceImpl) Delete(deleteReq *bean2.EnvironmentBean, user
743744
func (impl EnvironmentServiceImpl) HandleErrorInClusterConnections(clusters []*ClusterBean, respMap map[int]error, clusterExistInDb bool) {
744745
impl.clusterService.HandleErrorInClusterConnections(clusters, respMap, clusterExistInDb)
745746
}
747+
748+
func (impl EnvironmentServiceImpl) GetDetailsById(envId int) (*repository.Environment, error) {
749+
envDetails, err := impl.environmentRepository.FindById(envId)
750+
if err != nil {
751+
impl.logger.Errorw("error encountered in GetDetailsById", "envId", envId, "err", err)
752+
return nil, err
753+
}
754+
return envDetails, nil
755+
}

pkg/deployment/trigger/devtronApps/PreStageTriggerService.go

Lines changed: 3 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,10 @@ import (
99
gitSensorClient "github.com/devtron-labs/devtron/client/gitSensor"
1010
"github.com/devtron-labs/devtron/internal/sql/repository"
1111
"github.com/devtron-labs/devtron/internal/sql/repository/pipelineConfig"
12-
"github.com/devtron-labs/devtron/internal/sql/repository/security"
1312
"github.com/devtron-labs/devtron/internal/util"
1413
bean4 "github.com/devtron-labs/devtron/pkg/bean"
1514
repository2 "github.com/devtron-labs/devtron/pkg/cluster/repository"
15+
adapter2 "github.com/devtron-labs/devtron/pkg/deployment/trigger/devtronApps/adapter"
1616
"github.com/devtron-labs/devtron/pkg/deployment/trigger/devtronApps/bean"
1717
"github.com/devtron-labs/devtron/pkg/imageDigestPolicy"
1818
"github.com/devtron-labs/devtron/pkg/pipeline"
@@ -193,7 +193,8 @@ func (impl *TriggerServiceImpl) getEnvAndNsIfRunStageInEnv(ctx context.Context,
193193
func (impl *TriggerServiceImpl) checkVulnerabilityStatusAndFailWfIfNeeded(ctx context.Context, artifact *repository.CiArtifact,
194194
cdPipeline *pipelineConfig.Pipeline, runner *pipelineConfig.CdWorkflowRunner, triggeredBy int32) error {
195195
//checking vulnerability for the selected image
196-
isVulnerable, err := impl.GetArtifactVulnerabilityStatus(artifact, cdPipeline, ctx)
196+
vulnerabilityCheckRequest := adapter2.GetVulnerabilityCheckRequest(cdPipeline, artifact.ImageDigest)
197+
isVulnerable, err := impl.imageScanService.GetArtifactVulnerabilityStatus(ctx, vulnerabilityCheckRequest)
197198
if err != nil {
198199
impl.logger.Errorw("error in getting Artifact vulnerability status, TriggerPreStage", "err", err)
199200
return err
@@ -860,42 +861,6 @@ func (impl *TriggerServiceImpl) getSourceCiPipelineForArtifact(ciPipeline pipeli
860861
return sourceCiPipeline, nil
861862
}
862863

863-
func (impl *TriggerServiceImpl) GetArtifactVulnerabilityStatus(artifact *repository.CiArtifact, cdPipeline *pipelineConfig.Pipeline, ctx context.Context) (bool, error) {
864-
isVulnerable := false
865-
if len(artifact.ImageDigest) > 0 {
866-
var cveStores []*security.CveStore
867-
_, span := otel.Tracer("orchestrator").Start(ctx, "scanResultRepository.FindByImageDigest")
868-
imageScanResult, err := impl.scanResultRepository.FindByImageDigest(artifact.ImageDigest)
869-
span.End()
870-
if err != nil && err != pg.ErrNoRows {
871-
impl.logger.Errorw("error fetching image digest", "digest", artifact.ImageDigest, "err", err)
872-
return false, err
873-
}
874-
for _, item := range imageScanResult {
875-
cveStores = append(cveStores, &item.CveStore)
876-
}
877-
_, span = otel.Tracer("orchestrator").Start(ctx, "cvePolicyRepository.GetBlockedCVEList")
878-
if cdPipeline.Environment.ClusterId == 0 {
879-
envDetails, err := impl.envRepository.FindById(cdPipeline.EnvironmentId)
880-
if err != nil {
881-
impl.logger.Errorw("error fetching cluster details by env, GetArtifactVulnerabilityStatus", "envId", cdPipeline.EnvironmentId, "err", err)
882-
return false, err
883-
}
884-
cdPipeline.Environment = *envDetails
885-
}
886-
blockCveList, err := impl.cvePolicyRepository.GetBlockedCVEList(cveStores, cdPipeline.Environment.ClusterId, cdPipeline.EnvironmentId, cdPipeline.AppId, false)
887-
span.End()
888-
if err != nil {
889-
impl.logger.Errorw("error while fetching env", "err", err)
890-
return false, err
891-
}
892-
if len(blockCveList) > 0 {
893-
isVulnerable = true
894-
}
895-
}
896-
return isVulnerable, nil
897-
}
898-
899864
func (impl *TriggerServiceImpl) ReserveImagesGeneratedAtPlugin(customTagId int, registryImageMap map[string][]string) ([]int, error) {
900865
var imagePathReservationIds []int
901866
for _, images := range registryImageMap {

pkg/deployment/trigger/devtronApps/TriggerService.go

Lines changed: 14 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ import (
4848
"github.com/devtron-labs/devtron/pkg/pipeline/repository"
4949
"github.com/devtron-labs/devtron/pkg/pipeline/types"
5050
"github.com/devtron-labs/devtron/pkg/plugin"
51+
security2 "github.com/devtron-labs/devtron/pkg/security"
5152
"github.com/devtron-labs/devtron/pkg/sql"
5253
"github.com/devtron-labs/devtron/pkg/variables"
5354
"github.com/devtron-labs/devtron/pkg/workflow/cd"
@@ -114,13 +115,11 @@ type TriggerServiceImpl struct {
114115
gitSensorGrpcClient gitSensorClient.Client
115116
config *types.CdConfig
116117
helmAppService client2.HelmAppService
117-
118-
enforcerUtil rbac.EnforcerUtil
119-
helmAppClient gRPC.HelmAppClient //TODO refactoring: use helm app service instead
118+
imageScanService security2.ImageScanService
119+
enforcerUtil rbac.EnforcerUtil
120+
helmAppClient gRPC.HelmAppClient //TODO refactoring: use helm app service instead
120121

121122
appRepository appRepository.AppRepository
122-
scanResultRepository security.ImageScanResultRepository
123-
cvePolicyRepository security.CvePolicyRepository
124123
ciPipelineMaterialRepository pipelineConfig.CiPipelineMaterialRepository
125124
imageScanHistoryRepository security.ImageScanHistoryRepository
126125
imageScanDeployInfoRepository security.ImageScanDeployInfoRepository
@@ -170,8 +169,6 @@ func NewTriggerServiceImpl(logger *zap.SugaredLogger, cdWorkflowCommonService cd
170169
eventClient client.EventClient,
171170
envVariables *util3.EnvironmentVariables,
172171
appRepository appRepository.AppRepository,
173-
scanResultRepository security.ImageScanResultRepository,
174-
cvePolicyRepository security.CvePolicyRepository,
175172
ciPipelineMaterialRepository pipelineConfig.CiPipelineMaterialRepository,
176173
imageScanHistoryRepository security.ImageScanHistoryRepository,
177174
imageScanDeployInfoRepository security.ImageScanDeployInfoRepository,
@@ -188,7 +185,8 @@ func NewTriggerServiceImpl(logger *zap.SugaredLogger, cdWorkflowCommonService cd
188185
appLabelRepository pipelineConfig.AppLabelRepository,
189186
ciPipelineRepository pipelineConfig.CiPipelineRepository,
190187
appWorkflowRepository appWorkflow.AppWorkflowRepository,
191-
dockerArtifactStoreRepository repository4.DockerArtifactStoreRepository) (*TriggerServiceImpl, error) {
188+
dockerArtifactStoreRepository repository4.DockerArtifactStoreRepository,
189+
imageScanService security2.ImageScanService) (*TriggerServiceImpl, error) {
192190
impl := &TriggerServiceImpl{
193191
logger: logger,
194192
cdWorkflowCommonService: cdWorkflowCommonService,
@@ -221,8 +219,6 @@ func NewTriggerServiceImpl(logger *zap.SugaredLogger, cdWorkflowCommonService cd
221219
globalEnvVariables: envVariables.GlobalEnvVariables,
222220
helmAppClient: helmAppClient,
223221
appRepository: appRepository,
224-
scanResultRepository: scanResultRepository,
225-
cvePolicyRepository: cvePolicyRepository,
226222
ciPipelineMaterialRepository: ciPipelineMaterialRepository,
227223
imageScanHistoryRepository: imageScanHistoryRepository,
228224
imageScanDeployInfoRepository: imageScanDeployInfoRepository,
@@ -240,6 +236,7 @@ func NewTriggerServiceImpl(logger *zap.SugaredLogger, cdWorkflowCommonService cd
240236
ciPipelineRepository: ciPipelineRepository,
241237
appWorkflowRepository: appWorkflowRepository,
242238
dockerArtifactStoreRepository: dockerArtifactStoreRepository,
239+
imageScanService: imageScanService,
243240
}
244241
config, err := types.GetCdConfig()
245242
if err != nil {
@@ -400,7 +397,8 @@ func (impl *TriggerServiceImpl) ManualCdTrigger(triggerContext bean.TriggerConte
400397
impl.logger.Warnw("unable to migrate deprecated DataSource", "artifactId", artifact.Id)
401398
}
402399
}
403-
isVulnerable, err := impl.GetArtifactVulnerabilityStatus(artifact, cdPipeline, ctx)
400+
vulnerabilityCheckRequest := adapter.GetVulnerabilityCheckRequest(cdPipeline, artifact.ImageDigest)
401+
isVulnerable, err := impl.imageScanService.GetArtifactVulnerabilityStatus(ctx, vulnerabilityCheckRequest)
404402
if err != nil {
405403
impl.logger.Errorw("error in getting Artifact vulnerability status, ManualCdTrigger", "err", err)
406404
return 0, err
@@ -579,32 +577,12 @@ func (impl *TriggerServiceImpl) TriggerAutomaticDeployment(request bean.TriggerR
579577
return err
580578
}
581579
// custom GitOps repo url validation --> Ends
582-
580+
vulnerabilityCheckRequest := adapter.GetVulnerabilityCheckRequest(pipeline, artifact.ImageDigest)
583581
//checking vulnerability for deploying image
584-
isVulnerable := false
585-
if len(artifact.ImageDigest) > 0 {
586-
var cveStores []*security.CveStore
587-
imageScanResult, err := impl.scanResultRepository.FindByImageDigest(artifact.ImageDigest)
588-
if err != nil && err != pg.ErrNoRows {
589-
impl.logger.Errorw("error fetching image digest", "digest", artifact.ImageDigest, "err", err)
590-
return err
591-
}
592-
for _, item := range imageScanResult {
593-
cveStores = append(cveStores, &item.CveStore)
594-
}
595-
env, err := impl.envRepository.FindById(pipeline.EnvironmentId)
596-
if err != nil {
597-
impl.logger.Errorw("error while fetching env", "err", err)
598-
return err
599-
}
600-
blockCveList, err := impl.cvePolicyRepository.GetBlockedCVEList(cveStores, env.ClusterId, pipeline.EnvironmentId, pipeline.AppId, false)
601-
if err != nil {
602-
impl.logger.Errorw("error while fetching blocked cve list", "err", err)
603-
return err
604-
}
605-
if len(blockCveList) > 0 {
606-
isVulnerable = true
607-
}
582+
isVulnerable, err := impl.imageScanService.GetArtifactVulnerabilityStatus(request.TriggerContext.Context, vulnerabilityCheckRequest)
583+
if err != nil {
584+
impl.logger.Errorw("error in getting Artifact vulnerability status, ManualCdTrigger", "err", err)
585+
return err
608586
}
609587
if isVulnerable == true {
610588
if err = impl.cdWorkflowCommonService.MarkCurrentDeploymentFailed(runner, errors.New(pipelineConfig.FOUND_VULNERABILITY), triggeredBy); err != nil {

pkg/deployment/trigger/devtronApps/adapter/adapter.go

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package adapter
33
import (
44
bean3 "github.com/devtron-labs/devtron/api/bean"
55
"github.com/devtron-labs/devtron/internal/sql/repository/pipelineConfig"
6+
"github.com/devtron-labs/devtron/pkg/deployment/trigger/devtronApps/bean"
67
)
78

89
func SetPipelineFieldsInOverrideRequest(overrideRequest *bean3.ValuesOverrideRequest, pipeline *pipelineConfig.Pipeline) {
@@ -15,3 +16,10 @@ func SetPipelineFieldsInOverrideRequest(overrideRequest *bean3.ValuesOverrideReq
1516
overrideRequest.AppName = pipeline.App.AppName
1617
overrideRequest.DeploymentAppType = pipeline.DeploymentAppType
1718
}
19+
20+
func GetVulnerabilityCheckRequest(cdPipeline *pipelineConfig.Pipeline, imageDigest string) *bean.VulnerabilityCheckRequest {
21+
return &bean.VulnerabilityCheckRequest{
22+
CdPipeline: cdPipeline,
23+
ImageDigest: imageDigest,
24+
}
25+
}

pkg/deployment/trigger/devtronApps/bean/bean.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,3 +51,12 @@ const (
5151
ManifestDownload DeploymentType = "manifest_download"
5252
GitOpsWithoutDeployment DeploymentType = "git_ops_without_deployment"
5353
)
54+
55+
type TriggerRequirementRequestDto struct {
56+
TriggerRequest TriggerRequest
57+
}
58+
59+
type VulnerabilityCheckRequest struct {
60+
ImageDigest string
61+
CdPipeline *pipelineConfig.Pipeline
62+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package devtronApps
2+
3+
import (
4+
"github.com/devtron-labs/devtron/pkg/deployment/trigger/devtronApps/bean"
5+
)
6+
7+
type FeasibilityManager interface {
8+
CheckFeasibility(triggerRequirementRequest *bean.TriggerRequirementRequestDto) error
9+
}
10+
11+
func (impl *TriggerServiceImpl) CheckFeasibility(triggerRequirementRequest *bean.TriggerRequirementRequestDto) error {
12+
// have not implemented right now, will be implemented in future for security vulnerability
13+
return nil
14+
}

pkg/eventProcessor/in/WorkflowEventProcessorService.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -451,6 +451,7 @@ func (impl *WorkflowEventProcessorImpl) SubscribeCICompleteEvent() error {
451451
}
452452

453453
triggerContext := bean5.TriggerContext{
454+
Context: context.Background(),
454455
ReferenceId: pointer.String(msg.MsgId),
455456
}
456457

pkg/security/ImageScanService.go

Lines changed: 44 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,10 @@
1818
package security
1919

2020
import (
21+
"context"
2122
"github.com/devtron-labs/devtron/pkg/cluster/repository/bean"
23+
bean2 "github.com/devtron-labs/devtron/pkg/deployment/trigger/devtronApps/bean"
24+
"go.opentelemetry.io/otel"
2225
"time"
2326

2427
repository1 "github.com/devtron-labs/devtron/internal/sql/repository/app"
@@ -40,6 +43,7 @@ type ImageScanService interface {
4043
FetchExecutionDetailResult(request *ImageScanRequest) (*ImageScanExecutionDetail, error)
4144
FetchMinScanResultByAppIdAndEnvId(request *ImageScanRequest) (*ImageScanExecutionDetail, error)
4245
VulnerabilityExposure(request *security.VulnerabilityRequest) (*security.VulnerabilityExposureListingResponse, error)
46+
GetArtifactVulnerabilityStatus(ctx context.Context, request *bean2.VulnerabilityCheckRequest) (bool, error)
4347
}
4448

4549
type ImageScanServiceImpl struct {
@@ -59,6 +63,7 @@ type ImageScanServiceImpl struct {
5963
ciPipelineRepository pipelineConfig.CiPipelineRepository
6064
scanToolMetaDataRepository security.ScanToolMetadataRepository
6165
scanToolExecutionHistoryMappingRepository security.ScanToolExecutionHistoryMappingRepository
66+
cvePolicyRepository security.CvePolicyRepository
6267
}
6368

6469
type ImageScanRequest struct {
@@ -131,7 +136,8 @@ func NewImageScanServiceImpl(Logger *zap.SugaredLogger, scanHistoryRepository se
131136
userService user.UserService, teamRepository repository2.TeamRepository,
132137
appRepository repository1.AppRepository,
133138
envService cluster.EnvironmentService, ciArtifactRepository repository.CiArtifactRepository, policyService PolicyService,
134-
pipelineRepository pipelineConfig.PipelineRepository, ciPipelineRepository pipelineConfig.CiPipelineRepository, scanToolMetaDataRepository security.ScanToolMetadataRepository, scanToolExecutionHistoryMappingRepository security.ScanToolExecutionHistoryMappingRepository) *ImageScanServiceImpl {
139+
pipelineRepository pipelineConfig.PipelineRepository, ciPipelineRepository pipelineConfig.CiPipelineRepository, scanToolMetaDataRepository security.ScanToolMetadataRepository, scanToolExecutionHistoryMappingRepository security.ScanToolExecutionHistoryMappingRepository,
140+
cvePolicyRepository security.CvePolicyRepository) *ImageScanServiceImpl {
135141
return &ImageScanServiceImpl{Logger: Logger, scanHistoryRepository: scanHistoryRepository, scanResultRepository: scanResultRepository,
136142
scanObjectMetaRepository: scanObjectMetaRepository, cveStoreRepository: cveStoreRepository,
137143
imageScanDeployInfoRepository: imageScanDeployInfoRepository,
@@ -145,6 +151,7 @@ func NewImageScanServiceImpl(Logger *zap.SugaredLogger, scanHistoryRepository se
145151
ciPipelineRepository: ciPipelineRepository,
146152
scanToolMetaDataRepository: scanToolMetaDataRepository,
147153
scanToolExecutionHistoryMappingRepository: scanToolExecutionHistoryMappingRepository,
154+
cvePolicyRepository: cvePolicyRepository,
148155
}
149156
}
150157

@@ -605,3 +612,39 @@ func (impl ImageScanServiceImpl) VulnerabilityExposure(request *security.Vulnera
605612
vulnerabilityExposureListingResponse.VulnerabilityExposure = vulnerabilityExposureList
606613
return vulnerabilityExposureListingResponse, nil
607614
}
615+
616+
func (impl ImageScanServiceImpl) GetArtifactVulnerabilityStatus(ctx context.Context, request *bean2.VulnerabilityCheckRequest) (bool, error) {
617+
isVulnerable := false
618+
if len(request.ImageDigest) > 0 {
619+
var cveStores []*security.CveStore
620+
_, span := otel.Tracer("orchestrator").Start(ctx, "scanResultRepository.FindByImageDigest")
621+
imageScanResult, err := impl.scanResultRepository.FindByImageDigest(request.ImageDigest)
622+
span.End()
623+
if err != nil && err != pg.ErrNoRows {
624+
impl.Logger.Errorw("error fetching image digest", "digest", request.ImageDigest, "err", err)
625+
return false, err
626+
}
627+
for _, item := range imageScanResult {
628+
cveStores = append(cveStores, &item.CveStore)
629+
}
630+
_, span = otel.Tracer("orchestrator").Start(ctx, "cvePolicyRepository.GetBlockedCVEList")
631+
if request.CdPipeline.Environment.ClusterId == 0 {
632+
envDetails, err := impl.envService.GetDetailsById(request.CdPipeline.EnvironmentId)
633+
if err != nil {
634+
impl.Logger.Errorw("error fetching cluster details by env, GetArtifactVulnerabilityStatus", "envId", request.CdPipeline.EnvironmentId, "err", err)
635+
return false, err
636+
}
637+
request.CdPipeline.Environment = *envDetails
638+
}
639+
blockCveList, err := impl.cvePolicyRepository.GetBlockedCVEList(cveStores, request.CdPipeline.Environment.ClusterId, request.CdPipeline.EnvironmentId, request.CdPipeline.AppId, false)
640+
span.End()
641+
if err != nil {
642+
impl.Logger.Errorw("error encountered in GetArtifactVulnerabilityStatus", "clusterId", request.CdPipeline.Environment.ClusterId, "envId", request.CdPipeline.EnvironmentId, "appId", request.CdPipeline.AppId, "err", err)
643+
return false, err
644+
}
645+
if len(blockCveList) > 0 {
646+
isVulnerable = true
647+
}
648+
}
649+
return isVulnerable, nil
650+
}

0 commit comments

Comments
 (0)