Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Plugin for image scanning in Pre/Post step #4021

Merged
merged 43 commits into from
Nov 3, 2023
Merged
Show file tree
Hide file tree
Changes from 40 commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
f6be749
image scanning plugin
Ashish-devtron Oct 5, 2023
7418f2b
check for active ci_pipeline_material
Ashish-devtron Oct 11, 2023
78b844f
t checkout ci-pipeMerge branch 'main' of github.com:devtron-labs/devtron
Ashish-devtron Oct 11, 2023
2b0ca95
Merge branch 'main' of github.com:devtron-labs/devtron
Ashish-devtron Oct 12, 2023
d2596ae
Merge branch 'main' into image-scanning-plugin
Ashish-devtron Oct 12, 2023
647bf1d
sql script number change
Ashish-devtron Oct 12, 2023
cf95eaa
sql script number change
Ashish-devtron Oct 12, 2023
f7ce0ff
Merge branch 'main' of github.com:devtron-labs/devtron
Ashish-devtron Oct 12, 2023
7a9a8a9
Merge branch 'main' of github.com:devtron-labs/devtron
Ashish-devtron Oct 13, 2023
3b0ac36
Merge branch 'main' of github.com:devtron-labs/devtron
Ashish-devtron Oct 17, 2023
804ee25
Merge branch 'main' of github.com:devtron-labs/devtron
Ashish-devtron Oct 17, 2023
31cd8ff
Merge branch 'main' of github.com:devtron-labs/devtron
Ashish-devtron Oct 18, 2023
29a213b
image scanning plugin check
Ashish-devtron Oct 20, 2023
46f76d6
image scanning plugin check
Ashish-devtron Oct 20, 2023
6211df2
check for err
Ashish-devtron Oct 20, 2023
84bc2c7
abort print response
Ashish-devtron Oct 23, 2023
1ad0605
Merge branch 'main' of github.com:devtron-labs/devtron
Ashish-devtron Oct 23, 2023
6018be6
Merge branch 'main' of github.com:devtron-labs/devtron
Ashish-devtron Oct 25, 2023
7156314
Merge branch 'main' into image-scanning-plugin
Ashish-devtron Oct 25, 2023
81166be
Merge branch 'main' of github.com:devtron-labs/devtron
Ashish-devtron Oct 25, 2023
f76e2bd
Merge branch 'main' of github.com:devtron-labs/devtron
Ashish-devtron Oct 25, 2023
628a7ed
add dockerregistryId
Ashish-devtron Oct 25, 2023
aefbaea
script number update
Ashish-devtron Oct 25, 2023
f759a91
image scanning plugin name
Ashish-devtron Oct 25, 2023
17b7f23
Image scanner endpoint for both CiCd
Ashish-devtron Oct 25, 2023
9311fd3
Merge branch 'main' of github.com:devtron-labs/devtron
Ashish-devtron Oct 27, 2023
8750cdc
Main merge
Ashish-devtron Oct 27, 2023
88ecb8f
revert postgres port
Ashish-devtron Oct 27, 2023
1f7378b
Merge branch 'main' of github.com:devtron-labs/devtron
Ashish-devtron Oct 30, 2023
b35bbab
Merge branch 'main' of github.com:devtron-labs/devtron
Ashish-devtron Oct 30, 2023
38158cb
Merge branch 'main' of github.com:devtron-labs/devtron
Ashish-devtron Oct 31, 2023
fa2e0db
Merge branch 'main' of github.com:devtron-labs/devtron
Ashish-devtron Oct 31, 2023
5911c2e
Main merge
Ashish-devtron Oct 31, 2023
f04551c
Merge branch 'main' of github.com:devtron-labs/devtron
Ashish-devtron Nov 1, 2023
727da5d
Merge branch 'main' of github.com:devtron-labs/devtron
Ashish-devtron Nov 1, 2023
68d923d
Merge branch 'main' of github.com:devtron-labs/devtron
Ashish-devtron Nov 1, 2023
e708076
Main merge
Ashish-devtron Nov 1, 2023
8af751a
Merge branch 'main' of github.com:devtron-labs/devtron
Ashish-devtron Nov 2, 2023
8c055cf
Merge branch 'main' of github.com:devtron-labs/devtron
Ashish-devtron Nov 2, 2023
1fb0f61
Merge branch 'main' into image-scanning-plugin
Ashish-devtron Nov 2, 2023
8824445
Merge branch 'main' of github.com:devtron-labs/devtron
Ashish-devtron Nov 2, 2023
87a944f
Merge branch 'main' into image-scanning-plugin
Ashish-devtron Nov 2, 2023
b49cd8e
Code review changes
Ashish-devtron Nov 2, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Binary file added assets/ic-plugin-vulnerability-scan.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
68 changes: 44 additions & 24 deletions pkg/pipeline/WebhookService.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ import (
"github.com/devtron-labs/devtron/internal/sql/repository/pipelineConfig"
util2 "github.com/devtron-labs/devtron/internal/util"
"github.com/devtron-labs/devtron/pkg/app"
"github.com/devtron-labs/devtron/pkg/pipeline/bean"
repository2 "github.com/devtron-labs/devtron/pkg/pipeline/repository"
types2 "github.com/devtron-labs/devtron/pkg/pipeline/types"
repository3 "github.com/devtron-labs/devtron/pkg/plugin/repository"
"github.com/devtron-labs/devtron/pkg/sql"
"github.com/devtron-labs/devtron/util/event"
"github.com/go-pg/pg"
Expand Down Expand Up @@ -61,17 +64,19 @@ type WebhookService interface {
}

type WebhookServiceImpl struct {
ciArtifactRepository repository.CiArtifactRepository
ciConfig *types2.CiConfig
logger *zap.SugaredLogger
ciPipelineRepository pipelineConfig.CiPipelineRepository
ciWorkflowRepository pipelineConfig.CiWorkflowRepository
appService app.AppService
eventClient client.EventClient
eventFactory client.EventFactory
workflowDagExecutor WorkflowDagExecutor
ciHandler CiHandler
customTagService CustomTagService
ciArtifactRepository repository.CiArtifactRepository
ciConfig *types2.CiConfig
logger *zap.SugaredLogger
ciPipelineRepository pipelineConfig.CiPipelineRepository
ciWorkflowRepository pipelineConfig.CiWorkflowRepository
appService app.AppService
eventClient client.EventClient
eventFactory client.EventFactory
workflowDagExecutor WorkflowDagExecutor
ciHandler CiHandler
pipelineStageRepository repository2.PipelineStageRepository
globalPluginRepository repository3.GlobalPluginRepository
customTagService CustomTagService
}

func NewWebhookServiceImpl(
Expand All @@ -81,19 +86,23 @@ func NewWebhookServiceImpl(
appService app.AppService, eventClient client.EventClient,
eventFactory client.EventFactory,
ciWorkflowRepository pipelineConfig.CiWorkflowRepository,
customTagService CustomTagService,
workflowDagExecutor WorkflowDagExecutor, ciHandler CiHandler) *WebhookServiceImpl {
workflowDagExecutor WorkflowDagExecutor, ciHandler CiHandler,
pipelineStageRepository repository2.PipelineStageRepository,
globalPluginRepository repository3.GlobalPluginRepository,
customTagService CustomTagService) *WebhookServiceImpl {
webhookHandler := &WebhookServiceImpl{
ciArtifactRepository: ciArtifactRepository,
logger: logger,
ciPipelineRepository: ciPipelineRepository,
appService: appService,
eventClient: eventClient,
eventFactory: eventFactory,
ciWorkflowRepository: ciWorkflowRepository,
workflowDagExecutor: workflowDagExecutor,
ciHandler: ciHandler,
customTagService: customTagService,
ciArtifactRepository: ciArtifactRepository,
logger: logger,
ciPipelineRepository: ciPipelineRepository,
appService: appService,
eventClient: eventClient,
eventFactory: eventFactory,
ciWorkflowRepository: ciWorkflowRepository,
workflowDagExecutor: workflowDagExecutor,
ciHandler: ciHandler,
pipelineStageRepository: pipelineStageRepository,
globalPluginRepository: globalPluginRepository,
customTagService: customTagService,
}
config, err := types2.GetCiConfig()
if err != nil {
Expand Down Expand Up @@ -212,8 +221,19 @@ func (impl WebhookServiceImpl) HandleCiSuccessEvent(ciPipelineId int, request *C
IsArtifactUploaded: request.IsArtifactUploaded,
AuditLog: sql.AuditLog{CreatedBy: request.UserId, UpdatedBy: request.UserId, CreatedOn: createdOn, UpdatedOn: updatedOn},
}
if pipeline.ScanEnabled {
plugin, err := impl.globalPluginRepository.GetPluginByName(bean.IMAGE_SCANNING_PLUGIN)
if err != nil || len(plugin) == 0 {
impl.logger.Errorw("error in getting image scanning plugin", "err", err)
return 0, err
}
isScanPluginConfigured, err := impl.pipelineStageRepository.CheckPluginExistsInCiPipeline(pipeline.Id, string(repository2.PIPELINE_STAGE_TYPE_POST_CI), plugin[0].Id)
if err != nil {
impl.logger.Errorw("error in getting ci pipeline plugin", "err", err)
Ashish-devtron marked this conversation as resolved.
Show resolved Hide resolved
return 0, err
}
if pipeline.ScanEnabled || isScanPluginConfigured {
artifact.Scanned = true
artifact.ScanEnabled = true
}
if err = impl.ciArtifactRepository.Save(artifact); err != nil {
impl.logger.Errorw("error in saving material", "err", err)
Expand Down
2 changes: 2 additions & 0 deletions pkg/pipeline/WorkflowDagExecutor.go
Original file line number Diff line number Diff line change
Expand Up @@ -1221,6 +1221,7 @@ func (impl *WorkflowDagExecutorImpl) buildWFRequest(runner *pipelineConfig.CdWor
cdStageWorkflowRequest.SecretKey = ciPipeline.CiTemplate.DockerRegistry.AWSSecretAccessKey
cdStageWorkflowRequest.DockerRegistryType = string(ciPipeline.CiTemplate.DockerRegistry.RegistryType)
cdStageWorkflowRequest.DockerRegistryURL = ciPipeline.CiTemplate.DockerRegistry.RegistryURL
cdStageWorkflowRequest.DockerRegistryId = ciPipeline.CiTemplate.DockerRegistry.Id
cdStageWorkflowRequest.CiPipelineType = ciPipeline.PipelineType
} else if cdPipeline.AppId > 0 {
ciTemplate, err := impl.CiTemplateRepository.FindByAppId(cdPipeline.AppId)
Expand All @@ -1238,6 +1239,7 @@ func (impl *WorkflowDagExecutorImpl) buildWFRequest(runner *pipelineConfig.CdWor
cdStageWorkflowRequest.DockerRegistryType = string(ciTemplate.DockerRegistry.RegistryType)
cdStageWorkflowRequest.DockerRegistryURL = ciTemplate.DockerRegistry.RegistryURL
appLabels, err := impl.appLabelRepository.FindAllByAppId(cdPipeline.AppId)
cdStageWorkflowRequest.DockerRegistryId = ciPipeline.CiTemplate.DockerRegistry.Id
if err != nil && err != pg.ErrNoRows {
impl.logger.Errorw("error in getting labels by appId", "err", err, "appId", cdPipeline.AppId)
return nil, err
Expand Down
4 changes: 4 additions & 0 deletions pkg/pipeline/bean/pipelineStage.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,7 @@ type PortMap struct {
PortOnLocal int `json:"portOnLocal" validate:"number,gt=0"`
PortOnContainer int `json:"portOnContainer" validate:"number,gt=0"`
}

const (
IMAGE_SCANNING_PLUGIN string = "Vulnerability Scanning"
Ashish-devtron marked this conversation as resolved.
Show resolved Hide resolved
)
14 changes: 14 additions & 0 deletions pkg/pipeline/repository/PipelineStageRepository.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ type PipelineStageRepository interface {
MarkPipelineStageStepsDeletedByStageId(stageId int, updatedBy int32, tx *pg.Tx) error
GetAllStepsByStageId(stageId int) ([]*PipelineStageStep, error)
GetAllCiPipelineIdsByPluginIdAndStageType(pluginId int, stageType string) ([]int, error)
CheckPluginExistsInCiPipeline(pipelineId int, stageType string, pluginId int) (bool, error)
GetStepById(stepId int) (*PipelineStageStep, error)
MarkStepsDeletedByStageId(stageId int) error
MarkStepsDeletedExcludingActiveStepsInUpdateReq(activeStepIdsPresentInReq []int, stageId int) error
Expand Down Expand Up @@ -394,6 +395,19 @@ func (impl *PipelineStageRepositoryImpl) GetAllCiPipelineIdsByPluginIdAndStageTy
return ciPipelineIds, nil
}

func (impl *PipelineStageRepositoryImpl) CheckPluginExistsInCiPipeline(pipelineId int, stageType string, pluginId int) (bool, error) {
var step PipelineStageStep
query := "Select * from pipeline_stage_step pss " +
Ashish-devtron marked this conversation as resolved.
Show resolved Hide resolved
"INNER JOIN pipeline_stage ps ON ps.id = pss.pipeline_stage_id " +
"where pss.ref_plugin_id = ? and ps.type = ? and pss.deleted = false and ps.deleted = false and ps.ci_pipeline_id= ?"
_, err := impl.dbConnection.Query(&step, query, pluginId, stageType, pipelineId)
if err != nil {
impl.logger.Errorw("err in getting pipelineStageStep", "err", err, "pluginId", pluginId, "pipelineId", pipelineId, "stageType", stageType)
return false, err
}
return step.Id != 0, nil
}

func (impl *PipelineStageRepositoryImpl) MarkStepsDeletedByStageId(stageId int) error {
var step PipelineStageStep
_, err := impl.dbConnection.Model(&step).Set("deleted = ?", true).
Expand Down
5 changes: 1 addition & 4 deletions pkg/pipeline/types/Workflow.go
Original file line number Diff line number Diff line change
Expand Up @@ -221,10 +221,7 @@ func (workflowRequest *WorkflowRequest) GetWorkflowTypeForWorkflowRequest() stri
}

func (workflowRequest *WorkflowRequest) getContainerEnvVariables(config *CiCdConfig, workflowJson []byte) (containerEnvVariables []v1.EnvVar) {
if workflowRequest.Type == bean.CI_WORKFLOW_PIPELINE_TYPE ||
workflowRequest.Type == bean.JOB_WORKFLOW_PIPELINE_TYPE {
containerEnvVariables = []v1.EnvVar{{Name: "IMAGE_SCANNER_ENDPOINT", Value: config.ImageScannerEndpoint}}
}
containerEnvVariables = []v1.EnvVar{{Name: "IMAGE_SCANNER_ENDPOINT", Value: config.ImageScannerEndpoint}}
Ashish-devtron marked this conversation as resolved.
Show resolved Hide resolved
eventEnv := v1.EnvVar{Name: "CI_CD_EVENT", Value: string(workflowJson)}
inAppLoggingEnv := v1.EnvVar{Name: "IN_APP_LOGGING", Value: strconv.FormatBool(workflowRequest.InAppLoggingEnabled)}
containerEnvVariables = append(containerEnvVariables, eventEnv, inAppLoggingEnv)
Expand Down
5 changes: 5 additions & 0 deletions scripts/sql/184_image_scan_plugin.down.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
DELETE FROM plugin_step_variable WHERE plugin_step_id =(SELECT ps.id FROM plugin_metadata p inner JOIN plugin_step ps on ps.plugin_id=p.id WHERE p.name='Vulnerability Scanning' and ps."index"=1 and ps.deleted=false);
DELETE FROM plugin_stage_mapping WHERE plugin_id =(SELECT id FROM plugin_metadata WHERE name='Vulnerability Scanning');
DELETE FROM pipeline_stage_step_variable WHERE pipeline_stage_step_id in (SELECT id FROM pipeline_stage_step where ref_plugin_id =(SELECT id from plugin_metadata WHERE name ='Vulnerability Scanning'));
DELETE FROM pipeline_stage_step where ref_plugin_id in (SELECT id from plugin_metadata WHERE name ='Vulnerability Scanning');
DELETE FROM plugin_metadata WHERE name ='Vulnerability Scanning';
39 changes: 39 additions & 0 deletions scripts/sql/184_image_scan_plugin.up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
INSERT INTO "plugin_metadata" ("id", "name", "description","type","icon","deleted", "created_on", "created_by", "updated_on", "updated_by")
VALUES (nextval('id_seq_plugin_metadata'), 'Vulnerability Scanning','Scan a image','PRESET','https://raw.githubusercontent.com/devtron-labs/devtron/main/assets/ic-plugin-vulnerability-scan.png','f', 'now()', 1, 'now()', 1);

INSERT INTO "plugin_stage_mapping" ("plugin_id","stage_type","created_on", "created_by", "updated_on", "updated_by")
VALUES ((SELECT id FROM plugin_metadata WHERE name='Vulnerability Scanning'),0,'now()', 1, 'now()', 1);

INSERT INTO "plugin_pipeline_script" ("id", "script", "type","deleted","created_on", "created_by", "updated_on", "updated_by")
VALUES (nextval('id_seq_plugin_pipeline_script'),
'#!/bin/sh
echo "IMAGE SCAN"
curl -X POST $IMAGE_SCANNER_ENDPOINT/scanner/image -H "Content-Type: application/json" -d "{\"image\": \"$DEST\", \"imageDigest\": \"$DIGEST\", \"pipelineId\" : $PIPELINE_ID, \"userId\":
$TRIGGERED_BY, \"dockerRegistryId\": \"$DOCKER_REGISTRY_ID\" }" >/dev/null 2>&1
if [ $? != 0 ]
then
echo -e "\033[1m======== Vulnerability Scanning request failed ========"
exit 1
fi',
'SHELL',
'f',
'now()',
1,
'now()',
1);




INSERT INTO "plugin_step" ("id", "plugin_id","name","description","index","step_type","script_id","deleted", "created_on", "created_by", "updated_on", "updated_by")
VALUES (nextval('id_seq_plugin_step'), (SELECT id FROM plugin_metadata WHERE name='Vulnerability Scanning'),'Step 1','Step 1 - Vulnerability Scanning','1','INLINE',(SELECT last_value FROM id_seq_plugin_pipeline_script),'f','now()', 1, 'now()', 1);


INSERT INTO "plugin_step_variable" ("id", "plugin_step_id", "name", "format", "description", "is_exposed", "allow_empty_value","variable_type", "value_type", "variable_step_index",reference_variable_name, "deleted", "created_on", "created_by", "updated_on", "updated_by") VALUES
Ashish-devtron marked this conversation as resolved.
Show resolved Hide resolved
(nextval('id_seq_plugin_step_variable'), (SELECT ps.id FROM plugin_metadata p inner JOIN plugin_step ps on ps.plugin_id=p.id WHERE p.name='Vulnerability Scanning' and ps."index"=1 and ps.deleted=false), 'DEST','STRING','image dest',false,true,'INPUT','GLOBAL',1 ,'DEST','f','now()', 1, 'now()', 1),
(nextval('id_seq_plugin_step_variable'), (SELECT ps.id FROM plugin_metadata p inner JOIN plugin_step ps on ps.plugin_id=p.id WHERE p.name='Vulnerability Scanning' and ps."index"=1 and ps.deleted=false), 'DIGEST','STRING','Image Digest',false,true,'INPUT','GLOBAL',1 ,'DIGEST','f','now()', 1, 'now()', 1),
(nextval('id_seq_plugin_step_variable'), (SELECT ps.id FROM plugin_metadata p inner JOIN plugin_step ps on ps.plugin_id=p.id WHERE p.name='Vulnerability Scanning' and ps."index"=1 and ps.deleted=false), 'PIPELINE_ID','STRING','Pipeline id',false,true,'INPUT','GLOBAL',1 ,'PIPELINE_ID','f','now()', 1, 'now()', 1),
(nextval('id_seq_plugin_step_variable'), (SELECT ps.id FROM plugin_metadata p inner JOIN plugin_step ps on ps.plugin_id=p.id WHERE p.name='Vulnerability Scanning' and ps."index"=1 and ps.deleted=false), 'TRIGGERED_BY','STRING','triggered by user',false,true,'INPUT','GLOBAL',1 ,'TRIGGERED_BY','f','now()', 1, 'now()', 1),
(nextval('id_seq_plugin_step_variable'), (SELECT ps.id FROM plugin_metadata p inner JOIN plugin_step ps on ps.plugin_id=p.id WHERE p.name='Vulnerability Scanning' and ps."index"=1 and ps.deleted=false), 'DOCKER_REGISTRY_ID','STRING','docker registry id',false,true,'INPUT','GLOBAL',1 ,'DOCKER_REGISTRY_ID','f','now()', 1, 'now()', 1),
(nextval('id_seq_plugin_step_variable'), (SELECT ps.id FROM plugin_metadata p inner JOIN plugin_step ps on ps.plugin_id=p.id WHERE p.name='Vulnerability Scanning' and ps."index"=1 and ps.deleted=false), 'IMAGE_SCANNER_ENDPOINT','STRING','image scanner endpoint',false,true,'INPUT','GLOBAL',1 ,'IMAGE_SCANNER_ENDPOINT','f','now()', 1, 'now()', 1);

2 changes: 1 addition & 1 deletion wire_gen.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.