1
0
mirror of https://github.com/SAP/jenkins-library.git synced 2025-09-16 09:26:22 +02:00

feat(detect): add flag containerScan to detect step (#5312)

Co-authored-by: Manjunath <43342804+manjunathSurendrakumar@users.noreply.github.com>
This commit is contained in:
KunPang
2025-04-22 16:31:38 +02:00
committed by GitHub
parent 40bddefd76
commit bdfddf0d29
4 changed files with 120 additions and 89 deletions

View File

@@ -257,21 +257,24 @@ func runDetect(ctx context.Context, config detectExecuteScanOptions, utils detec
blackduckSystem := newBlackduckSystem(config)
args := []string{"./detect.sh"}
args, err = addDetectArgs(args, config, utils, blackduckSystem, NO_VERSION_SUFFIX, NO_VERSION_SUFFIX)
if err != nil {
return err
}
script := strings.Join(args, " ")
envs := []string{"BLACKDUCK_SKIP_PHONE_HOME=true"}
envs = append(envs, config.CustomEnvironmentVariables...)
utils.SetDir(".")
utils.SetEnv(envs)
err = mapDetectError(utils.RunShell("bash", script), config, utils)
if config.ScanContainerDistro != "" {
// When containerScan is set to true, only the container scan will be executed
if !config.ContainerScan {
args := []string{"./detect.sh"}
args, err = addDetectArgs(args, config, utils, blackduckSystem, NO_VERSION_SUFFIX, NO_VERSION_SUFFIX)
if err != nil {
return err
}
script := strings.Join(args, " ")
err = mapDetectError(utils.RunShell("bash", script), config, utils)
}
if config.ScanContainerDistro != "" || config.ContainerScan {
imageError := mapDetectError(runDetectImages(ctx, config, utils, blackduckSystem, influx, blackduckSystem), config, utils)
if imageError != nil {
if err != nil {
@@ -622,6 +625,11 @@ func addDetectArgsImages(args []string, config detectExecuteScanOptions, utils d
if err != nil {
return []string{}, err
}
if config.ContainerScan {
args = append(args, "--detect.tools=CONTAINER_SCAN")
args = append(args, fmt.Sprintf("--detect.container.scan.file.path=./%s", imageTar))
return args, nil
}
args = append(args, fmt.Sprintf("--detect.docker.tar=./%s", imageTar))
args = append(args, "--detect.target.type=IMAGE")

View File

@@ -79,6 +79,7 @@ type detectExecuteScanOptions struct {
RepositoryPassword string `json:"repositoryPassword,omitempty" validate:"required_if=ScanContainerDistro ubuntu ScanContainerDistro centos ScanContainerDistro alpine"`
UseDetect8 bool `json:"useDetect8,omitempty"`
UseDetect9 bool `json:"useDetect9,omitempty"`
ContainerScan bool `json:"containerScan,omitempty"`
}
type detectExecuteScanInflux struct {
@@ -358,6 +359,7 @@ func addDetectExecuteScanFlags(cmd *cobra.Command, stepConfig *detectExecuteScan
cmd.Flags().StringVar(&stepConfig.RepositoryPassword, "repositoryPassword", os.Getenv("PIPER_repositoryPassword"), "Used accessing for the images to be scanned (typically filled by CPE)")
cmd.Flags().BoolVar(&stepConfig.UseDetect8, "useDetect8", false, "This flag enables the use of the supported version 8 of the Detect script instead of default version 10")
cmd.Flags().BoolVar(&stepConfig.UseDetect9, "useDetect9", false, "This flag enables the use of the supported version 9 of the Detect script instead of default version 10")
cmd.Flags().BoolVar(&stepConfig.ContainerScan, "containerScan", false, "When set to true, Container Scanning will be used instead of Docker Inspector as the Detect tool for scanning images, and all other detect tools will be ignored in the scan")
cmd.MarkFlagRequired("token")
cmd.MarkFlagRequired("projectName")
@@ -967,6 +969,15 @@ func detectExecuteScanMetadata() config.StepData {
Aliases: []config.Alias{{Name: "detect/useDetect9"}},
Default: false,
},
{
Name: "containerScan",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "bool",
Mandatory: false,
Aliases: []config.Alias{{Name: "detect/containerScan"}},
Default: false,
},
},
},
Containers: []config.Container{

View File

@@ -376,6 +376,22 @@ func TestRunDetect(t *testing.T) {
expectedParam2 := "--detect.docker.tar=./bar_bazz_latest.tar --detect.target.type=IMAGE --detect.tools.excluded=DETECTOR --detect.docker.passthrough.shared.dir.path.local=/opt/blackduck/blackduck-imageinspector/shared/ --detect.docker.passthrough.shared.dir.path.imageinspector=/opt/blackduck/blackduck-imageinspector/shared --detect.docker.passthrough.imageinspector.service.distro.default=ubuntu --detect.docker.passthrough.imageinspector.service.start=false --detect.docker.passthrough.output.include.squashedimage=false --detect.docker.passthrough.imageinspector.service.url=http://localhost:8082"
assert.Contains(t, utilsMock.Calls[2], expectedParam2)
})
t.Run("container scan only", func(t *testing.T) {
t.Parallel()
ctx := context.Background()
utilsMock := newDetectTestUtilsBundle(false)
utilsMock.AddFile("detect.sh", []byte(""))
err := runDetect(ctx, detectExecuteScanOptions{
ContainerScan: true,
ImageNameTags: []string{"foo/bar:latest"},
}, utilsMock, &detectExecuteScanInflux{})
assert.NoError(t, err)
assert.Equal(t, 1, len(utilsMock.Calls), "Only one detect script call should have been executed")
assert.Contains(t, utilsMock.Calls[0], "--detect.tools=CONTAINER_SCAN", "Container scan tool should be specified")
assert.Contains(t, utilsMock.Calls[0], "--detect.container.scan.file.path=./foo_bar_latest.tar", "Container scan file path should be specified")
})
}
func TestAddDetectArgs(t *testing.T) {
@@ -578,86 +594,6 @@ func TestAddDetectArgs(t *testing.T) {
"--detect.tools=DETECTOR",
},
},
{
args: []string{"--testProp1=1"},
options: detectExecuteScanOptions{
ServerURL: "https://server.url",
Token: "apiToken",
ProjectName: "testName",
CodeLocation: "testLocation",
FailOn: []string{"BLOCKER", "MAJOR"},
Scanners: []string{"source"},
ScanPaths: []string{"path1", "path2"},
Groups: []string{"testGroup", "testGroup2"},
Version: "1.0",
VersioningModel: "major-minor",
DependencyPath: "pathx",
Unmap: true,
IncludedPackageManagers: []string{"maven", "GRADLE"},
ExcludedPackageManagers: []string{"npm", "NUGET"},
MavenExcludedScopes: []string{"TEST", "compile"},
DetectTools: []string{"DETECTOR"},
},
expected: []string{
"--testProp1=1",
"--detect.excluded.directories=.pipeline/*",
"--detect.project.codelocation.unmap=true",
"--blackduck.url=https://server.url",
"--blackduck.api.token=apiToken",
"\"--detect.project.name=testName\"",
"\"--detect.project.version.name=1.0\"",
"\"--detect.project.user.groups=testGroup,testGroup2\"",
"--detect.policy.check.fail.on.severities=BLOCKER,MAJOR",
"\"--detect.code.location.name=testLocation\"",
"\"--detect.force.success.on.skip=true\"",
"--detect.blackduck.signature.scanner.paths=path1,path2",
"--detect.source.path=pathx",
"--detect.included.detector.types=MAVEN,GRADLE",
"--detect.excluded.detector.types=NPM,NUGET",
"--detect.maven.excluded.scopes=test,compile",
"--detect.tools=DETECTOR",
},
},
{
args: []string{"--testProp1=1"},
options: detectExecuteScanOptions{
ServerURL: "https://server.url",
Token: "apiToken",
ProjectName: "testName",
CodeLocation: "testLocation",
FailOn: []string{"BLOCKER", "MAJOR"},
Scanners: []string{"source"},
ScanPaths: []string{"path1", "path2"},
Groups: []string{"testGroup", "testGroup2"},
Version: "1.0",
VersioningModel: "major-minor",
DependencyPath: "pathx",
Unmap: true,
IncludedPackageManagers: []string{"maven", "GRADLE"},
ExcludedPackageManagers: []string{"npm", "NUGET"},
MavenExcludedScopes: []string{"TEST", "compile"},
DetectTools: []string{"DETECTOR"},
},
expected: []string{
"--testProp1=1",
"--detect.excluded.directories=.pipeline/*",
"--detect.project.codelocation.unmap=true",
"--blackduck.url=https://server.url",
"--blackduck.api.token=apiToken",
"\"--detect.project.name=testName\"",
"\"--detect.project.version.name=1.0\"",
"\"--detect.project.user.groups=testGroup,testGroup2\"",
"--detect.policy.check.fail.on.severities=BLOCKER,MAJOR",
"\"--detect.code.location.name=testLocation\"",
"\"--detect.force.success.on.skip=true\"",
"--detect.blackduck.signature.scanner.paths=path1,path2",
"--detect.source.path=pathx",
"--detect.included.detector.types=MAVEN,GRADLE",
"--detect.excluded.detector.types=NPM,NUGET",
"--detect.maven.excluded.scopes=test,compile",
"--detect.tools=DETECTOR",
},
},
{
args: []string{"--testProp1=1"},
options: detectExecuteScanOptions{
@@ -1009,3 +945,69 @@ func TestGetVulnerabilitiesWithComponents(t *testing.T) {
assert.Equal(t, vulnerableComponentLog4j, vulnerabilityLog4j2.Component)
})
}
func TestAddDetectArgsImages(t *testing.T) {
t.Parallel()
t.Run("with docker inspector", func(t *testing.T) {
args := []string{"./detect.sh"}
config := detectExecuteScanOptions{
ServerURL: "https://server.url",
Token: "apiToken",
ProjectName: "testProject",
Version: "1.0",
ScanContainerDistro: "ubuntu",
}
utils := newDetectTestUtilsBundle(false)
sys := newBlackduckMockSystem(config)
result, err := addDetectArgsImages(args, config, utils, &sys, "test.tar")
assert.NoError(t, err)
assert.Contains(t, result, "--detect.docker.tar=./test.tar")
assert.Contains(t, result, "--detect.target.type=IMAGE")
assert.Contains(t, result, "--detect.tools.excluded=DETECTOR")
})
t.Run("with container scan", func(t *testing.T) {
args := []string{"./detect.sh"}
config := detectExecuteScanOptions{
ServerURL: "https://server.url",
Token: "apiToken",
ProjectName: "testProject",
Version: "1.0",
ContainerScan: true,
}
utils := newDetectTestUtilsBundle(false)
sys := newBlackduckMockSystem(config)
result, err := addDetectArgsImages(args, config, utils, &sys, "test.tar")
assert.NoError(t, err)
assert.Contains(t, result, "--detect.tools=CONTAINER_SCAN")
assert.Contains(t, result, "--detect.container.scan.file.path=./test.tar")
assert.NotContains(t, result, "--detect.docker.tar=./test.tar")
assert.NotContains(t, result, "--detect.target.type=IMAGE")
})
}
func TestRunDetectWithContainerScanAndDistro(t *testing.T) {
t.Parallel()
t.Run("both containerScan and scanContainerDistro set", func(t *testing.T) {
ctx := context.Background()
utilsMock := newDetectTestUtilsBundle(false)
utilsMock.AddFile("detect.sh", []byte(""))
err := runDetect(ctx, detectExecuteScanOptions{
ContainerScan: true,
ScanContainerDistro: "ubuntu",
ImageNameTags: []string{"foo/bar:latest"},
}, utilsMock, &detectExecuteScanInflux{})
assert.NoError(t, err)
assert.Equal(t, 1, len(utilsMock.Calls), "Only one detect script call should have been executed")
assert.Contains(t, utilsMock.Calls[0], "--detect.tools=CONTAINER_SCAN", "Container scan tool should be specified")
assert.Contains(t, utilsMock.Calls[0], "--detect.container.scan.file.path=./foo_bar_latest.tar", "Container scan file path should be specified")
assert.NotContains(t, utilsMock.Calls[0], "--detect.docker.passthrough.imageinspector.service.distro.default=ubuntu",
"Docker inspector parameters should not be included when containerScan is true")
})
}

View File

@@ -675,6 +675,16 @@ spec:
- STAGES
- STEPS
default: false
- name: containerScan
description: "When set to true, Container Scanning will be used instead of Docker Inspector as the Detect tool for scanning images, and all other detect tools will be ignored in the scan"
aliases:
- name: detect/containerScan
type: bool
scope:
- PARAMETERS
- STAGES
- STEPS
default: false
outputs:
resources:
- name: influx