@@ -44,12 +44,17 @@ import (
44
44
"github.com/devtron-labs/devtron/pkg/deployment/trigger/devtronApps/userDeploymentRequest/service"
45
45
eventProcessorBean "github.com/devtron-labs/devtron/pkg/eventProcessor/bean"
46
46
"github.com/devtron-labs/devtron/pkg/pipeline"
47
+ constants2 "github.com/devtron-labs/devtron/pkg/pipeline/constants"
47
48
"github.com/devtron-labs/devtron/pkg/pipeline/executors"
48
49
repository2 "github.com/devtron-labs/devtron/pkg/plugin/repository"
50
+ "github.com/devtron-labs/devtron/pkg/policyGovernance/security/imageScanning"
51
+ repository3 "github.com/devtron-labs/devtron/pkg/policyGovernance/security/imageScanning/repository"
49
52
"github.com/devtron-labs/devtron/pkg/sql"
50
53
"github.com/devtron-labs/devtron/pkg/workflow/cd"
51
54
bean4 "github.com/devtron-labs/devtron/pkg/workflow/cd/bean"
55
+ "github.com/devtron-labs/devtron/pkg/workflow/dag/adaptor"
52
56
bean2 "github.com/devtron-labs/devtron/pkg/workflow/dag/bean"
57
+ "github.com/devtron-labs/devtron/pkg/workflow/dag/helper"
53
58
error2 "github.com/devtron-labs/devtron/util/error"
54
59
util2 "github.com/devtron-labs/devtron/util/event"
55
60
"strings"
@@ -124,6 +129,8 @@ type WorkflowDagExecutorImpl struct {
124
129
commonArtifactService artifacts.CommonArtifactService
125
130
deploymentConfigService common2.DeploymentConfigService
126
131
asyncRunnable * async.Runnable
132
+ scanHistoryRepository repository3.ImageScanHistoryRepository
133
+ imageScanService imageScanning.ImageScanService
127
134
}
128
135
129
136
func NewWorkflowDagExecutorImpl (Logger * zap.SugaredLogger , pipelineRepository pipelineConfig.PipelineRepository ,
@@ -147,7 +154,10 @@ func NewWorkflowDagExecutorImpl(Logger *zap.SugaredLogger, pipelineRepository pi
147
154
manifestCreationService manifest.ManifestCreationService ,
148
155
commonArtifactService artifacts.CommonArtifactService ,
149
156
deploymentConfigService common2.DeploymentConfigService ,
150
- asyncRunnable * async.Runnable ) * WorkflowDagExecutorImpl {
157
+ asyncRunnable * async.Runnable ,
158
+ scanHistoryRepository repository3.ImageScanHistoryRepository ,
159
+ imageScanService imageScanning.ImageScanService ,
160
+ ) * WorkflowDagExecutorImpl {
151
161
wde := & WorkflowDagExecutorImpl {logger : Logger ,
152
162
pipelineRepository : pipelineRepository ,
153
163
cdWorkflowRepository : cdWorkflowRepository ,
@@ -171,6 +181,8 @@ func NewWorkflowDagExecutorImpl(Logger *zap.SugaredLogger, pipelineRepository pi
171
181
commonArtifactService : commonArtifactService ,
172
182
deploymentConfigService : deploymentConfigService ,
173
183
asyncRunnable : asyncRunnable ,
184
+ scanHistoryRepository : scanHistoryRepository ,
185
+ imageScanService : imageScanService ,
174
186
}
175
187
config , err := types .GetCdConfig ()
176
188
if err != nil {
@@ -558,6 +570,22 @@ func (impl *WorkflowDagExecutorImpl) HandlePreStageSuccessEvent(triggerContext t
558
570
if err != nil {
559
571
return err
560
572
}
573
+ scanEnabled , scanned := ciArtifact .ScanEnabled , ciArtifact .Scanned
574
+ isScanPluginConfigured , isScanningDoneViaPlugin , err := impl .isArtifactScannedByPluginForPipeline (ciArtifact , cdStageCompleteEvent .CdPipelineId , repository4 .PIPELINE_STAGE_TYPE_PRE_CD , bean2 .ImageScanningPluginToCheckInPipelineStageStep )
575
+ if err != nil {
576
+ impl .logger .Errorw ("error in checking if artifact scanned by plugin for a pipeline or not" , "ciArtifact" , ciArtifact , "err" , err )
577
+ return err
578
+ }
579
+ helper .UpdateScanStatusInCiArtifact (ciArtifact , isScanPluginConfigured , isScanningDoneViaPlugin )
580
+
581
+ // if ciArtifact scanEnabled and scanned state changed from above func then update ciArtifact
582
+ if scanEnabled != ciArtifact .ScanEnabled || scanned != ciArtifact .Scanned {
583
+ err = impl .ciArtifactRepository .Update (ciArtifact )
584
+ if err != nil {
585
+ impl .logger .Errorw ("error in updating ci artifact after handling scan event for this artifact" , "ciArtifact" , ciArtifact , "err" , err )
586
+ return err
587
+ }
588
+ }
561
589
// Migration of deprecated DataSource Type
562
590
if ciArtifact .IsMigrationRequired () {
563
591
migrationErr := impl .ciArtifactRepository .MigrateToWebHookDataSourceType (ciArtifact .Id )
@@ -651,6 +679,22 @@ func (impl *WorkflowDagExecutorImpl) HandlePostStageSuccessEvent(triggerContext
651
679
impl .logger .Errorw ("error in finding artifact by cd workflow id" , "err" , err , "cdWorkflowId" , cdWorkflowId )
652
680
return err
653
681
}
682
+ scanEnabled , scanned := ciArtifact .ScanEnabled , ciArtifact .Scanned
683
+ isScanPluginConfigured , isScanningDoneViaPlugin , err := impl .isArtifactScannedByPluginForPipeline (ciArtifact , cdPipelineId , repository4 .PIPELINE_STAGE_TYPE_POST_CD , bean2 .ImageScanningPluginToCheckInPipelineStageStep )
684
+ if err != nil {
685
+ impl .logger .Errorw ("error in checking if artifact scanned by plugin for a pipeline or not" , "ciArtifact" , ciArtifact , "err" , err )
686
+ return err
687
+ }
688
+ helper .UpdateScanStatusInCiArtifact (ciArtifact , isScanPluginConfigured , isScanningDoneViaPlugin )
689
+
690
+ // if ciArtifact scanEnabled and scanned state changed from above func then update ciArtifact
691
+ if scanEnabled != ciArtifact .ScanEnabled || scanned != ciArtifact .Scanned {
692
+ err = impl .ciArtifactRepository .Update (ciArtifact )
693
+ if err != nil {
694
+ impl .logger .Errorw ("error in updating ci artifact after handling scan event for this artifact" , "ciArtifact" , ciArtifact , "err" , err )
695
+ return err
696
+ }
697
+ }
654
698
if len (pluginRegistryImageDetails ) > 0 {
655
699
PostCDArtifacts , err := impl .commonArtifactService .SavePluginArtifacts (ciArtifact , pluginRegistryImageDetails , cdPipelineId , repository .POST_CD , triggeredBy )
656
700
if err != nil {
@@ -710,6 +754,24 @@ func (impl *WorkflowDagExecutorImpl) UpdateCiWorkflowForCiSuccess(request *bean2
710
754
return nil
711
755
}
712
756
757
+ func (impl * WorkflowDagExecutorImpl ) isArtifactScannedByPluginForPipeline (ciArtifact * repository.CiArtifact , pipelineId int ,
758
+ pipelineStage repository4.PipelineStageType , pluginName string ) (bool , bool , error ) {
759
+ var isScanningDone bool
760
+ isScanPluginConfigured , err := impl .pipelineStageService .IsScanPluginConfiguredAtPipelineStage (pipelineId , pipelineStage , pluginName )
761
+ if err != nil {
762
+ impl .logger .Errorw ("error in fetching if a scan plugin is configured or not in a pipeline" , "pipelineStage" , pipelineStage , "ciArtifact" , ciArtifact )
763
+ return false , false , err
764
+ }
765
+ if isScanPluginConfigured {
766
+ isScanningDone , err = impl .imageScanService .IsImageScanExecutionCompleted (ciArtifact .Image , ciArtifact .ImageDigest )
767
+ if err != nil {
768
+ impl .logger .Errorw ("error in checking if image scanning is completed or not" , "image" , ciArtifact .Image , "imageDigest" , ciArtifact .ImageDigest )
769
+ return false , false , err
770
+ }
771
+ }
772
+ return isScanPluginConfigured , isScanningDone , nil
773
+ }
774
+
713
775
func (impl * WorkflowDagExecutorImpl ) HandleCiSuccessEvent (triggerContext triggerBean.TriggerContext , ciPipelineId int , request * bean2.CiArtifactWebhookRequest , imagePushedAt time.Time ) (id int , err error ) {
714
776
impl .logger .Infow ("webhook for artifact save" , "req" , request )
715
777
pipelineModal , err := impl .ciPipelineRepository .FindByCiAndAppDetailsById (ciPipelineId )
@@ -720,48 +782,36 @@ func (impl *WorkflowDagExecutorImpl) HandleCiSuccessEvent(triggerContext trigger
720
782
if request .PipelineName == "" {
721
783
request .PipelineName = pipelineModal .Name
722
784
}
723
- materialJson , err := request .MaterialInfo .MarshalJSON ()
724
- if err != nil {
725
- impl .logger .Errorw ("unable to marshal material metadata" , "err" , err )
726
- return 0 , err
727
- }
728
- dst := new (bytes.Buffer )
729
- err = json .Compact (dst , materialJson )
785
+ materialJson , err := helper .GetMaterialInfoJson (request .MaterialInfo )
730
786
if err != nil {
787
+ impl .logger .Errorw ("unable to get materialJson" , "materialInfo" , request .MaterialInfo , "err" , err )
731
788
return 0 , err
732
789
}
733
- materialJson = dst .Bytes ()
734
790
createdOn := time .Now ()
735
791
updatedOn := time .Now ()
736
792
if ! imagePushedAt .IsZero () {
737
793
createdOn = imagePushedAt
738
794
}
739
- buildArtifact := & repository.CiArtifact {
740
- Image : request .Image ,
741
- ImageDigest : request .ImageDigest ,
742
- MaterialInfo : string (materialJson ),
743
- DataSource : request .DataSource ,
744
- PipelineId : pipelineModal .Id ,
745
- WorkflowId : request .WorkflowId ,
746
- ScanEnabled : pipelineModal .ScanEnabled ,
747
- IsArtifactUploaded : request .IsArtifactUploaded , // for backward compatibility
748
- Scanned : false ,
749
- AuditLog : sql.AuditLog {CreatedBy : request .UserId , UpdatedBy : request .UserId , CreatedOn : createdOn , UpdatedOn : updatedOn },
750
- }
751
- plugin , err := impl .globalPluginRepository .GetPluginByName (bean3 .VULNERABILITY_SCANNING_PLUGIN )
752
- if err != nil || len (plugin ) == 0 {
753
- impl .logger .Errorw ("error in getting image scanning plugin" , "err" , err )
754
- return 0 , err
755
- }
756
- isScanPluginConfigured , err := impl .pipelineStageRepository .CheckPluginExistsInCiPipeline (pipelineModal .Id , string (repository4 .PIPELINE_STAGE_TYPE_POST_CI ), plugin [0 ].Id )
757
- if err != nil {
758
- impl .logger .Errorw ("error in getting ci pipelineModal plugin" , "err" , err , "pipelineId" , pipelineModal .Id , "pluginId" , plugin [0 ].Id )
759
- return 0 , err
795
+ buildArtifact := adaptor .GetBuildArtifact (request , pipelineModal .Id , materialJson , createdOn , updatedOn )
796
+
797
+ // image scanning plugin can only be applied in Post-ci, scanning in pre-ci doesn't make sense
798
+ pipelineStage := repository4 .PIPELINE_STAGE_TYPE_POST_CI
799
+ if pipelineModal .PipelineType == constants2 .CI_JOB .ToString () {
800
+ pipelineStage = repository4 .PIPELINE_STAGE_TYPE_PRE_CI
760
801
}
761
- if pipelineModal .ScanEnabled || isScanPluginConfigured {
802
+ // this flag comes from ci-runner when scanning is enabled from ciPipeline modal
803
+ if request .IsScanEnabled {
762
804
buildArtifact .Scanned = true
763
805
buildArtifact .ScanEnabled = true
806
+ } else {
807
+ isScanPluginConfigured , isScanningDoneViaPlugin , err := impl .isArtifactScannedByPluginForPipeline (buildArtifact , pipelineModal .Id , pipelineStage , bean2 .ImageScanningPluginToCheckInPipelineStageStep )
808
+ if err != nil {
809
+ impl .logger .Errorw ("error in checking if artifact scanned by plugin for a pipeline or not" , "ciArtifact" , buildArtifact , "err" , err )
810
+ return 0 , err
811
+ }
812
+ helper .UpdateScanStatusInCiArtifact (buildArtifact , isScanPluginConfigured , isScanningDoneViaPlugin )
764
813
}
814
+
765
815
if err = impl .ciArtifactRepository .Save (buildArtifact ); err != nil {
766
816
impl .logger .Errorw ("error in saving material" , "err" , err )
767
817
return 0 , err
@@ -815,12 +865,12 @@ func (impl *WorkflowDagExecutorImpl) HandleCiSuccessEvent(triggerContext trigger
815
865
PipelineId : ci .Id ,
816
866
ParentCiArtifact : buildArtifact .Id ,
817
867
IsArtifactUploaded : request .IsArtifactUploaded , // for backward compatibility
818
- ScanEnabled : ci .ScanEnabled ,
868
+ ScanEnabled : buildArtifact .ScanEnabled ,
819
869
Scanned : false ,
820
870
AuditLog : sql.AuditLog {CreatedBy : request .UserId , UpdatedBy : request .UserId , CreatedOn : time .Now (), UpdatedOn : time .Now ()},
821
871
}
822
- if ci .ScanEnabled {
823
- ciArtifact .Scanned = true
872
+ if buildArtifact .ScanEnabled {
873
+ ciArtifact .Scanned = buildArtifact . Scanned
824
874
}
825
875
ciArtifactArr = append (ciArtifactArr , ciArtifact )
826
876
}
0 commit comments