Skip to content

Commit

Permalink
feat(detectExecuteScan): Also scan images that are in the CPE (#4678)
Browse files Browse the repository at this point in the history
feat(detectExecuteScan): Also scan images that are in the cpe

Signed-off-by: Ralf Pannemans <[email protected]>
Signed-off-by: Johannes Dillmann <[email protected]>
Signed-off-by: Pavel Busko <[email protected]>
Co-authored-by: Johannes Dillmann <[email protected]>
Co-authored-by: Pavel Busko <[email protected]>
  • Loading branch information
3 people authored Feb 12, 2024
1 parent f51fbc3 commit 49b8080
Show file tree
Hide file tree
Showing 5 changed files with 310 additions and 11 deletions.
120 changes: 111 additions & 9 deletions cmd/detectExecuteScan.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import (
"github.com/SAP/jenkins-library/pkg/log"
"github.com/SAP/jenkins-library/pkg/maven"
"github.com/SAP/jenkins-library/pkg/orchestrator"
"github.com/SAP/jenkins-library/pkg/piperenv"

Check failure on line 23 in cmd/detectExecuteScan.go

View workflow job for this annotation

GitHub Actions / Build Piper

"github.com/SAP/jenkins-library/pkg/piperenv" imported and not used
"github.com/SAP/jenkins-library/pkg/piperutils"
"github.com/SAP/jenkins-library/pkg/reporting"
"github.com/SAP/jenkins-library/pkg/telemetry"
Expand All @@ -30,6 +31,8 @@ import (
"github.com/pkg/errors"
)

const NO_VERSION_SUFFIX = ""

type detectUtils interface {
piperutils.FileUtils

Expand Down Expand Up @@ -202,7 +205,7 @@ func runDetect(ctx context.Context, config detectExecuteScanOptions, utils detec
blackduckSystem := newBlackduckSystem(config)

args := []string{"./detect.sh"}
args, err = addDetectArgs(args, config, utils, blackduckSystem)
args, err = addDetectArgs(args, config, utils, blackduckSystem, NO_VERSION_SUFFIX, NO_VERSION_SUFFIX)
if err != nil {
return err
}
Expand All @@ -214,7 +217,18 @@ func runDetect(ctx context.Context, config detectExecuteScanOptions, utils detec
utils.SetDir(".")
utils.SetEnv(envs)

err = utils.RunShell("/bin/bash", script)
err = mapDetectError(utils.RunShell("/bin/bash", script), config, utils)
if config.ScanContainerDistro != "" {
imageError := mapDetectError(runDetectImages(ctx, config, utils, blackduckSystem, influx, blackduckSystem), config, utils)
if imageError != nil {
if err != nil {
err = errors.Wrapf(err, "error during scanning images: %q", imageError.Error())
} else {
err = imageError
}
}
}

reportingErr := postScanChecksAndReporting(ctx, config, influx, utils, blackduckSystem)
if reportingErr != nil {
if strings.Contains(reportingErr.Error(), "License Policy Violations found") {
Expand All @@ -227,6 +241,17 @@ func runDetect(ctx context.Context, config detectExecuteScanOptions, utils detec
log.Entry().Warnf("Failed to generate reports: %v", reportingErr)
}
}
// create Toolrecord file
toolRecordFileName, toolRecordErr := createToolRecordDetect(utils, "./", config, blackduckSystem)
if toolRecordErr != nil {
// do not fail until the framework is well established
log.Entry().Warning("TR_DETECT: Failed to create toolrecord file "+toolRecordFileName, err)
}

return err
}

func mapDetectError(err error, config detectExecuteScanOptions, utils detectUtils) error {
if err != nil {
// Setting error category based on exit code
mapErrorCategory(utils.GetExitCode())
Expand All @@ -238,15 +263,52 @@ func runDetect(ctx context.Context, config detectExecuteScanOptions, utils detec
err = errors.Wrapf(err, exitCodeMapping(utils.GetExitCode()))
}
}
// create Toolrecord file
toolRecordFileName, toolRecordErr := createToolRecordDetect(utils, "./", config, blackduckSystem)
if toolRecordErr != nil {
// do not fail until the framework is well established
log.Entry().Warning("TR_DETECT: Failed to create toolrecord file "+toolRecordFileName, err)
}
return err
}

func runDetectImages(ctx context.Context, config detectExecuteScanOptions, utils detectUtils, sys *blackduckSystem, influx *detectExecuteScanInflux, blackduckSystem *blackduckSystem) error {
cpePath := filepath.Join(GeneralConfig.EnvRootPath, "commonPipelineEnvironment")
imagesRaw := piperenv.GetResourceParameter(cpePath, "container", "imageNameTags.json")
if imagesRaw == "" {
log.Entry().Debugf("No images found to be scanned")
return nil
}

var err error
log.Entry().Infof("Scanning %d images", len(config.ImageNameTags))
for _, image := range config.ImageNameTags {
// Download image to be scanned
log.Entry().Debugf("Scanning image: %q", image)
tarName := fmt.Sprintf("%s.tar", strings.Split(image, ":")[0])

options := containerSaveImageOptions{
ContainerRegistryURL: config.RegistryURL,
ContainerImage: image,
ContainerRegistryPassword: config.RepositoryPassword,
ContainerRegistryUser: config.RepositoryUsername,
FilePath: tarName,
ImageFormat: "legacy",
}
containerSaveImage(options, &telemetry.CustomData{})

args := []string{"./detect.sh"}
args, err = addDetectArgsImages(args, config, utils, sys, tarName)
if err != nil {
return err
}
script := strings.Join(args, " ")

err = utils.RunShell("/bin/bash", script)
err = mapDetectError(err, config, utils)

if err != nil {
return err
}
}

return nil
}

// Get proper error category
func mapErrorCategory(exitCodeKey int) {
switch exitCodeKey {
Expand Down Expand Up @@ -331,8 +393,11 @@ func getDetectScript(config detectExecuteScanOptions, utils detectUtils) error {
return nil
}

func addDetectArgs(args []string, config detectExecuteScanOptions, utils detectUtils, sys *blackduckSystem) ([]string, error) {
func addDetectArgs(args []string, config detectExecuteScanOptions, utils detectUtils, sys *blackduckSystem, versionSuffix, locationSuffix string) ([]string, error) {
detectVersionName := getVersionName(config)
if versionSuffix != NO_VERSION_SUFFIX {
detectVersionName = fmt.Sprintf("%s-%s", detectVersionName, versionSuffix)
}
// Split on spaces, the scanPropeties, so that each property is available as a single string
// instead of all properties being part of a single string
config.ScanProperties = piperutils.SplitAndTrim(config.ScanProperties, " ")
Expand Down Expand Up @@ -393,6 +458,10 @@ func addDetectArgs(args []string, config detectExecuteScanOptions, utils detectU
codelocation := config.CodeLocation
if len(codelocation) == 0 && len(config.ProjectName) > 0 {
codelocation = fmt.Sprintf("%v/%v", config.ProjectName, detectVersionName)

if locationSuffix != "" {
codelocation = fmt.Sprintf("%v-%v", codelocation, locationSuffix)
}
}

args = append(args, fmt.Sprintf("\"--detect.project.name=%v\"", config.ProjectName))
Expand Down Expand Up @@ -467,6 +536,39 @@ func addDetectArgs(args []string, config detectExecuteScanOptions, utils detectU
return args, nil
}

func addDetectArgsImages(args []string, config detectExecuteScanOptions, utils detectUtils, sys *blackduckSystem, imageTar string) ([]string, error) {
// suffix := strings.Split(imageTar, ".")[0]
// In order to preserve source scan result
config.Unmap = false
args, err := addDetectArgs(args, config, utils, sys, NO_VERSION_SUFFIX, fmt.Sprintf("image-%s", strings.Split(imageTar, ".")[0]))
if err != nil {
return []string{}, err
}

args = append(args, fmt.Sprintf("--detect.docker.tar=./%s", imageTar))
args = append(args, "--detect.target.type=IMAGE")
// https://community.synopsys.com/s/article/Docker-image-scanning-CLI-examples-and-some-Q-As
args = append(args, "--detect.tools.excluded=DETECTOR")
args = append(args, "--detect.docker.passthrough.shared.dir.path.local=/opt/blackduck/blackduck-imageinspector/shared/")
args = append(args, "--detect.docker.passthrough.shared.dir.path.imageinspector=/opt/blackduck/blackduck-imageinspector/shared")
args = append(args, fmt.Sprintf("--detect.docker.passthrough.imageinspector.service.distro.default=%s", config.ScanContainerDistro))
args = append(args, "--detect.docker.passthrough.imageinspector.service.start=false")
args = append(args, "--detect.docker.passthrough.output.include.squashedimage=false")

switch config.ScanContainerDistro {
case "ubuntu":
args = append(args, "--detect.docker.passthrough.imageinspector.service.url=http://localhost:8082")
case "centos":
args = append(args, "--detect.docker.passthrough.imageinspector.service.url=http://localhost:8081")
case "alpine":
args = append(args, "--detect.docker.passthrough.imageinspector.service.url=http://localhost:8080")
default:
return nil, fmt.Errorf("unknown container distro %q", config.ScanContainerDistro)
}

return args, nil
}

func getVersionName(config detectExecuteScanOptions) string {
detectVersionName := config.CustomScanVersion
if len(detectVersionName) > 0 {
Expand Down
80 changes: 80 additions & 0 deletions cmd/detectExecuteScan_generated.go

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

2 changes: 1 addition & 1 deletion cmd/detectExecuteScan_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -807,7 +807,7 @@ func TestAddDetectArgs(t *testing.T) {
config := detectExecuteScanOptions{Token: "token", ServerURL: "https://my.blackduck.system", ProjectName: v.options.ProjectName, Version: v.options.Version, CustomScanVersion: v.options.CustomScanVersion}
sys := newBlackduckMockSystem(config)

got, err := addDetectArgs(v.args, v.options, newDetectTestUtilsBundle(v.isPullRequest), &sys)
got, err := addDetectArgs(v.args, v.options, newDetectTestUtilsBundle(v.isPullRequest), &sys, NO_VERSION_SUFFIX, "")
assert.NoError(t, err)
assert.Equal(t, v.expected, got)
})
Expand Down
3 changes: 2 additions & 1 deletion pkg/docker/docker.go
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,8 @@ func (c *Client) DownloadImage(imageSource, targetFile string) (v1.Image, error)
craneCmd := cranecmd.NewCmdPull(&noOpts)
craneCmd.SetOut(log.Writer())
craneCmd.SetErr(log.Writer())
craneCmd.SetArgs([]string{imageRef.Name(), tmpFile.Name(), "--format=" + c.imageFormat})
args := []string{imageRef.Name(), tmpFile.Name(), "--format=" + c.imageFormat}
craneCmd.SetArgs(args)

if err := craneCmd.Execute(); err != nil {
defer os.Remove(tmpFile.Name())
Expand Down
Loading

0 comments on commit 49b8080

Please sign in to comment.