From db805f22d52b10db29f4c9fd5e15beaa7c33355a Mon Sep 17 00:00:00 2001 From: Giridhar Shenoy Date: Mon, 20 Sep 2021 11:28:16 +0200 Subject: [PATCH] detectExecuteScan: Fail step when License policy violations are found (#3106) * fail step for license violation * add toolrecord creation * toolrecord generation in all cases --- cmd/detectExecuteScan.go | 69 ++++++++++++++--------------------- cmd/detectExecuteScan_test.go | 27 +++++++++++++- 2 files changed, 53 insertions(+), 43 deletions(-) diff --git a/cmd/detectExecuteScan.go b/cmd/detectExecuteScan.go index ea6f732f4..c2f08b6af 100644 --- a/cmd/detectExecuteScan.go +++ b/cmd/detectExecuteScan.go @@ -157,43 +157,32 @@ func runDetect(config detectExecuteScanOptions, utils detectUtils, influx *detec utils.SetEnv(envs) err = utils.RunShell("/bin/bash", script) - reportingErr := postScanChecksAndReporting(config, influx, utils, newBlackduckSystem(config)) + blackduckSystem := newBlackduckSystem(config) + reportingErr := postScanChecksAndReporting(config, influx, utils, blackduckSystem) if reportingErr != nil { - log.Entry().Warnf("Failed to generate reports: %v", reportingErr) + if strings.Contains(reportingErr.Error(), "License Policy Violations found") { + log.Entry().Errorf("License Policy Violations found") + log.SetErrorCategory(log.ErrorCompliance) + if err == nil { + err = errors.New("License Policy Violations found") + } + } else { + log.Entry().Warnf("Failed to generate reports: %v", reportingErr) + } } - if err == nil && piperutils.ContainsString(config.FailOn, "BLOCKER") { - violations := struct { - PolicyViolations int `json:"policyViolations"` - Reports []string `json:"reports"` - }{ - PolicyViolations: 0, - Reports: []string{}, - } - - if files, err := utils.Glob("**/*BlackDuck_RiskReport.pdf"); err == nil && len(files) > 0 { - // there should only be one RiskReport thus only taking the first one - _, reportFile := filepath.Split(files[0]) - violations.Reports = append(violations.Reports, reportFile) - } - - violationContent, err := json.Marshal(violations) - if err != nil { - return fmt.Errorf("failed to marshal policy violation data: %w", err) - } - - err = utils.FileWrite("blackduck-ip.json", violationContent, 0666) - if err != nil { - return fmt.Errorf("failed to write policy violation report: %w", err) - } - } else if err != nil { + if err != nil { // Setting error category based on exit code mapErrorCategory(utils.GetExitCode()) // Error code mapping with more human readable text - // log.Entry().Errorf("[ERROR ERRORF] => %v", exitCodeMapping(utils.GetExitCode())) - return errors.Wrapf(err, exitCodeMapping(utils.GetExitCode())) + err = errors.Wrapf(err, exitCodeMapping(utils.GetExitCode())) + } + // create Toolrecord file + toolRecordFileName, toolRecordErr := createToolRecordDetect("./", 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 } @@ -235,6 +224,7 @@ func mapErrorCategory(exitCodeKey int) { func exitCodeMapping(exitCodeKey int) string { exitCodes := map[int]string{ + 0: "Detect Scan completed successfully", 1: "FAILURE_BLACKDUCK_CONNECTIVITY => Detect was unable to connect to Black Duck. Check your configuration and connection.", 2: "FAILURE_TIMEOUT => Detect could not wait for actions to be completed on Black Duck. Check your Black Duck server or increase your timeout.", 3: "FAILURE_POLICY_VIOLATION => Detect found policy violations.", @@ -383,15 +373,12 @@ func postScanChecksAndReporting(config detectExecuteScanOptions, influx *detectE if err != nil { return errors.Wrapf(err, "failed to check and report scan results") } - policyJsonErr := writeIpPolicyJson(config, utils, paths, sys) + policyJsonErr, violationCount := writeIpPolicyJson(config, utils, paths, sys) if policyJsonErr != nil { return errors.Wrapf(policyJsonErr, "failed to write IP policy violations json file") } - // create Toolrecord file - toolRecordFileName, err := createToolRecordDetect("./", config, sys) - if err != nil { - // do not fail until the framework is well established - log.Entry().Warning("TR_DETECT: Failed to create toolrecord file "+toolRecordFileName, err) + if violationCount > 0 { + return errors.Errorf("License Policy Violations found") } return nil } @@ -590,11 +577,11 @@ func writePolicyStatusReports(scanReport reporting.ScanReport, config detectExec return reportPaths, nil } -func writeIpPolicyJson(config detectExecuteScanOptions, utils detectUtils, paths []piperutils.Path, sys *blackduckSystem) error { +func writeIpPolicyJson(config detectExecuteScanOptions, utils detectUtils, paths []piperutils.Path, sys *blackduckSystem) (error, int) { components, err := sys.Client.GetComponentsWithLicensePolicyRule(config.ProjectName, getVersionName(config)) if err != nil { errors.Wrapf(err, "failed to get License Policy Violations") - return err + return err, 0 } violationCount := getActivePolicyViolations(components) @@ -617,14 +604,14 @@ func writeIpPolicyJson(config detectExecuteScanOptions, utils detectUtils, paths violationContent, err := json.Marshal(violations) if err != nil { - return fmt.Errorf("failed to marshal policy violation data: %w", err) + return fmt.Errorf("failed to marshal policy violation data: %w", err), violationCount } err = utils.FileWrite("blackduck-ip.json", violationContent, 0666) if err != nil { - return fmt.Errorf("failed to write policy violation report: %w", err) + return fmt.Errorf("failed to write policy violation report: %w", err), violationCount } - return nil + return nil, violationCount } func getActivePolicyViolations(components *bd.Components) int { diff --git a/cmd/detectExecuteScan_test.go b/cmd/detectExecuteScan_test.go index ba999a7d3..068240364 100644 --- a/cmd/detectExecuteScan_test.go +++ b/cmd/detectExecuteScan_test.go @@ -231,6 +231,7 @@ func TestRunDetect(t *testing.T) { utilsMock.ExitCode = 3 utilsMock.AddFile("detect.sh", []byte("")) err := runDetect(detectExecuteScanOptions{}, utilsMock, &detectExecuteScanInflux{}) + assert.Equal(t, utilsMock.ExitCode, 3) assert.Contains(t, err.Error(), "FAILURE_POLICY_VIOLATION => Detect found policy violations.") assert.True(t, utilsMock.HasRemovedFile("detect.sh")) }) @@ -598,7 +599,7 @@ func TestPostScanChecksAndReporting(t *testing.T) { sys := newBlackduckMockSystem(config) err := postScanChecksAndReporting(config, &detectExecuteScanInflux{}, utils, &sys) - assert.NoError(t, err) + assert.EqualError(t, err, "License Policy Violations found") content, err := utils.FileRead("blackduck-ip.json") assert.NoError(t, err) assert.Contains(t, string(content), `"policyViolations":2`) @@ -631,7 +632,7 @@ func TestIsMajorVulnerability(t *testing.T) { }) } -func TestIstActiveVulnerability(t *testing.T) { +func TestIsActiveVulnerability(t *testing.T) { t.Parallel() t.Run("Case true", func(t *testing.T) { vr := bd.VulnerabilityWithRemediation{ @@ -658,3 +659,25 @@ func TestIstActiveVulnerability(t *testing.T) { assert.False(t, isActiveVulnerability(v)) }) } + +func TestIsActivePolicyViolation(t *testing.T) { + t.Parallel() + t.Run("Case true", func(t *testing.T) { + assert.True(t, isActivePolicyViolation("IN_VIOLATION")) + }) + t.Run("Case False", func(t *testing.T) { + assert.False(t, isActivePolicyViolation("NOT_IN_VIOLATION")) + }) +} + +func TestGetActivePolicyViolations(t *testing.T) { + t.Parallel() + t.Run("Case true", func(t *testing.T) { + config := detectExecuteScanOptions{Token: "token", ServerURL: "https://my.blackduck.system", ProjectName: "SHC-PiperTest", Version: "", CustomScanVersion: "1.0"} + sys := newBlackduckMockSystem(config) + + components, err := sys.Client.GetComponents("SHC-PiperTest", "1.0") + assert.NoError(t, err) + assert.Equal(t, getActivePolicyViolations(components), 2) + }) +}