mirror of
https://github.com/SAP/jenkins-library.git
synced 2024-12-12 10:55:20 +02:00
feat(fortifyExecuteScan): new spotcheck flags (#3923)
This commit is contained in:
parent
2f1f4b18ac
commit
c8f069efb2
@ -386,6 +386,11 @@ func prepareReportData(influx *fortifyExecuteScanInflux) fortify.FortifyReportDa
|
||||
|
||||
func analyseUnauditedIssues(config fortifyExecuteScanOptions, sys fortify.System, projectVersion *models.ProjectVersion, filterSet *models.FilterSet, issueFilterSelectorSet *models.IssueFilterSelectorSet, influx *fortifyExecuteScanInflux, auditStatus map[string]string, spotChecksCountByCategory *[]fortify.SpotChecksAuditCount) (int, []*models.ProjectVersionIssueGroup, error) {
|
||||
log.Entry().Info("Analyzing unaudited issues")
|
||||
|
||||
if config.SpotCheckMinimumUnit != "percentage" && config.SpotCheckMinimumUnit != "number" {
|
||||
return 0, nil, fmt.Errorf("Invalid spotCheckMinimumUnit. Please set it as 'percentage' or 'number'.")
|
||||
}
|
||||
|
||||
reducedFilterSelectorSet := sys.ReduceIssueFilterSelectorSet(issueFilterSelectorSet, []string{"Folder"}, nil)
|
||||
fetchedIssueGroups, err := sys.GetProjectIssuesByIDAndFilterSetGroupedBySelector(projectVersion.ID, "", filterSet.GUID, reducedFilterSelectorSet)
|
||||
if err != nil {
|
||||
@ -454,6 +459,7 @@ func getSpotIssueCount(config fortifyExecuteScanOptions, sys fortify.System, spo
|
||||
overallDelta := 0
|
||||
overallIssues := 0
|
||||
overallIssuesAudited := 0
|
||||
|
||||
for _, issueGroup := range spotCheckCategories {
|
||||
group := ""
|
||||
total := 0
|
||||
@ -465,9 +471,12 @@ func getSpotIssueCount(config fortifyExecuteScanOptions, sys fortify.System, spo
|
||||
}
|
||||
flagOutput := ""
|
||||
|
||||
if ((total <= config.SpotCheckMinimum || config.SpotCheckMinimum < 0) && audited != total) || (total > config.SpotCheckMinimum && audited < config.SpotCheckMinimum) {
|
||||
currentDelta := config.SpotCheckMinimum - audited
|
||||
if config.SpotCheckMinimum < 0 || config.SpotCheckMinimum > total {
|
||||
minSpotChecksPerCategory := getMinSpotChecksPerCategory(config, total)
|
||||
log.Entry().Debugf("Minimum spot checks for group %v is %v with audit count %v and total issue count %v", group, minSpotChecksPerCategory, audited, total)
|
||||
|
||||
if ((total <= minSpotChecksPerCategory || minSpotChecksPerCategory < 0) && audited != total) || (total > minSpotChecksPerCategory && audited < minSpotChecksPerCategory) {
|
||||
currentDelta := minSpotChecksPerCategory - audited
|
||||
if minSpotChecksPerCategory < 0 || minSpotChecksPerCategory > total {
|
||||
currentDelta = total - audited
|
||||
}
|
||||
if currentDelta > 0 {
|
||||
@ -494,6 +503,30 @@ func getSpotIssueCount(config fortifyExecuteScanOptions, sys fortify.System, spo
|
||||
return overallDelta
|
||||
}
|
||||
|
||||
func getMinSpotChecksPerCategory(config fortifyExecuteScanOptions, totalCount int) int {
|
||||
if config.SpotCheckMinimumUnit == "percentage" {
|
||||
spotCheckMinimumPercentageValue := int(math.Round(float64(config.SpotCheckMinimum) / 100.0 * float64(totalCount)))
|
||||
if spotCheckMinimumPercentageValue == 0 {
|
||||
return 1
|
||||
}
|
||||
return getSpotChecksMinAsPerMaximum(config.SpotCheckMaximum, spotCheckMinimumPercentageValue)
|
||||
}
|
||||
|
||||
return getSpotChecksMinAsPerMaximum(config.SpotCheckMaximum, config.SpotCheckMinimum)
|
||||
}
|
||||
|
||||
func getSpotChecksMinAsPerMaximum(spotCheckMax int, spotCheckMin int) int {
|
||||
if spotCheckMax == 0 {
|
||||
return spotCheckMin
|
||||
}
|
||||
|
||||
if spotCheckMin > spotCheckMax {
|
||||
return spotCheckMax
|
||||
}
|
||||
|
||||
return spotCheckMin
|
||||
}
|
||||
|
||||
func analyseSuspiciousExploitable(config fortifyExecuteScanOptions, sys fortify.System, projectVersion *models.ProjectVersion, filterSet *models.FilterSet, issueFilterSelectorSet *models.IssueFilterSelectorSet, influx *fortifyExecuteScanInflux, auditStatus map[string]string) (int, []*models.ProjectVersionIssueGroup) {
|
||||
log.Entry().Info("Analyzing suspicious and exploitable issues")
|
||||
reducedFilterSelectorSet := sys.ReduceIssueFilterSelectorSet(issueFilterSelectorSet, []string{"Analysis"}, []string{})
|
||||
|
@ -65,6 +65,8 @@ type fortifyExecuteScanOptions struct {
|
||||
PullRequestMessageRegexGroup int `json:"pullRequestMessageRegexGroup,omitempty"`
|
||||
DeltaMinutes int `json:"deltaMinutes,omitempty"`
|
||||
SpotCheckMinimum int `json:"spotCheckMinimum,omitempty"`
|
||||
SpotCheckMinimumUnit string `json:"spotCheckMinimumUnit,omitempty" validate:"possible-values=number percentage"`
|
||||
SpotCheckMaximum int `json:"SpotCheckMaximum,omitempty"`
|
||||
FprDownloadEndpoint string `json:"fprDownloadEndpoint,omitempty"`
|
||||
VersioningModel string `json:"versioningModel,omitempty" validate:"possible-values=major major-minor semantic full"`
|
||||
PythonInstallCommand string `json:"pythonInstallCommand,omitempty"`
|
||||
@ -343,7 +345,9 @@ func addFortifyExecuteScanFlags(cmd *cobra.Command, stepConfig *fortifyExecuteSc
|
||||
cmd.Flags().StringVar(&stepConfig.ServerURL, "serverUrl", os.Getenv("PIPER_serverUrl"), "Fortify SSC Url to be used for accessing the APIs")
|
||||
cmd.Flags().IntVar(&stepConfig.PullRequestMessageRegexGroup, "pullRequestMessageRegexGroup", 1, "The group number for extracting the pull request id in `'pullRequestMessageRegex'`")
|
||||
cmd.Flags().IntVar(&stepConfig.DeltaMinutes, "deltaMinutes", 5, "The number of minutes for which an uploaded FPR artifact is considered to be recent and healthy, if exceeded an error will be thrown")
|
||||
cmd.Flags().IntVar(&stepConfig.SpotCheckMinimum, "spotCheckMinimum", 1, "The minimum number of issues that must be audited per category in the `Spot Checks of each Category` folder to avoid an error being thrown")
|
||||
cmd.Flags().IntVar(&stepConfig.SpotCheckMinimum, "spotCheckMinimum", 1, "The minimum number/percentage of issues that must be audited per category in the `Spot Checks of each Category` folder to avoid an error being thrown")
|
||||
cmd.Flags().StringVar(&stepConfig.SpotCheckMinimumUnit, "spotCheckMinimumUnit", `number`, "The unit for the spotCheckMinimum to apply.")
|
||||
cmd.Flags().IntVar(&stepConfig.SpotCheckMaximum, "SpotCheckMaximum", 0, "The maximum number of issues that must be audited per category in the `Spot Checks of each Category` folder to avoid an error being thrown. Note that this flag depends on the result of spotCheckMinimum. For example if spotCheckMinimum percentage value exceeds spotCheckMaximum then spotCheckMaximum will be considerd else spotCheckMinimum is considered. If zero, this flag will be ignored.")
|
||||
cmd.Flags().StringVar(&stepConfig.FprDownloadEndpoint, "fprDownloadEndpoint", `/download/currentStateFprDownload.html`, "Fortify SSC endpoint for FPR downloads")
|
||||
cmd.Flags().StringVar(&stepConfig.VersioningModel, "versioningModel", `major`, "The default project versioning model used for creating the version based on the build descriptor version to report results in SSC, can be one of `'major'`, `'major-minor'`, `'semantic'`, `'full'`")
|
||||
cmd.Flags().StringVar(&stepConfig.PythonInstallCommand, "pythonInstallCommand", `{{.Pip}} install --user .`, "Additional install command that can be run when `buildTool: 'pip'` is used which allows further customizing the execution environment of the scan")
|
||||
@ -842,6 +846,24 @@ func fortifyExecuteScanMetadata() config.StepData {
|
||||
Aliases: []config.Alias{},
|
||||
Default: 1,
|
||||
},
|
||||
{
|
||||
Name: "spotCheckMinimumUnit",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
Default: `number`,
|
||||
},
|
||||
{
|
||||
Name: "SpotCheckMaximum",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "int",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
Default: 0,
|
||||
},
|
||||
{
|
||||
Name: "fprDownloadEndpoint",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
|
@ -494,7 +494,7 @@ func TestAnalyseSuspiciousExploitable(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestAnalyseUnauditedIssues(t *testing.T) {
|
||||
config := fortifyExecuteScanOptions{SpotCheckMinimum: 4, MustAuditIssueGroups: "Audit All, Corporate Security Requirements", SpotAuditIssueGroups: "Spot Checks of Each Category"}
|
||||
config := fortifyExecuteScanOptions{SpotCheckMinimumUnit: "number", SpotCheckMinimum: 4, MustAuditIssueGroups: "Audit All, Corporate Security Requirements", SpotAuditIssueGroups: "Spot Checks of Each Category"}
|
||||
ff := fortifyMock{}
|
||||
influx := fortifyExecuteScanInflux{}
|
||||
name := "test"
|
||||
@ -551,6 +551,16 @@ func TestAnalyseUnauditedIssues(t *testing.T) {
|
||||
assert.Equal(t, 3, len(spotChecksCountByCategory))
|
||||
}
|
||||
|
||||
func TestAnalyseUnauditedIssuesWithWrongConfig(t *testing.T) {
|
||||
config := fortifyExecuteScanOptions{SpotCheckMinimumUnit: "float"}
|
||||
spotChecksCountByCategory := []fortify.SpotChecksAuditCount{}
|
||||
ff := fortifyMock{}
|
||||
auditStatus := map[string]string{}
|
||||
_, _, err := analyseUnauditedIssues(config, &ff, &models.ProjectVersion{}, &models.FilterSet{}, &models.IssueFilterSelectorSet{}, &fortifyExecuteScanInflux{}, auditStatus, &spotChecksCountByCategory)
|
||||
assert.Error(t, err)
|
||||
assert.Equal(t, "Invalid spotCheckMinimumUnit. Please set it as 'percentage' or 'number'.", err.Error())
|
||||
}
|
||||
|
||||
func TestTriggerFortifyScan(t *testing.T) {
|
||||
t.Run("maven", func(t *testing.T) {
|
||||
dir := t.TempDir()
|
||||
@ -637,6 +647,30 @@ func TestTriggerFortifyScan(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
func TestGetMinSpotChecksPerCategory(t *testing.T) {
|
||||
testExpectedGetMinSpotChecksPerCategory := func(spotChecksMinUnit string, spotChecksMax int, spotChecksMin int, issuesPerCategory int, spotChecksMinCalculatedExpected int) {
|
||||
testName := fmt.Sprintf("Test GetMinSpotChecksPerCategory for SpotCheckMinimumUnit: %v, SpotCheckMaximum: %v, SpotCheckMinimum: %v, issuesPerCategory: %v", spotChecksMinUnit, spotChecksMax, spotChecksMin, issuesPerCategory)
|
||||
t.Run(testName, func(t *testing.T) {
|
||||
config := fortifyExecuteScanOptions{SpotCheckMinimumUnit: spotChecksMinUnit, SpotCheckMaximum: spotChecksMax, SpotCheckMinimum: spotChecksMin}
|
||||
spotCheckMin := getMinSpotChecksPerCategory(config, issuesPerCategory)
|
||||
assert.Equal(t, spotChecksMinCalculatedExpected, spotCheckMin)
|
||||
})
|
||||
}
|
||||
|
||||
testExpectedGetMinSpotChecksPerCategory("percentage", 0, 1, 10, 1)
|
||||
testExpectedGetMinSpotChecksPerCategory("percentage", 10, 10, 3, 1)
|
||||
testExpectedGetMinSpotChecksPerCategory("percentage", 10, 10, 8, 1)
|
||||
testExpectedGetMinSpotChecksPerCategory("percentage", 10, 10, 10, 1)
|
||||
testExpectedGetMinSpotChecksPerCategory("percentage", 10, 10, 24, 2)
|
||||
testExpectedGetMinSpotChecksPerCategory("percentage", 10, 10, 26, 3)
|
||||
testExpectedGetMinSpotChecksPerCategory("percentage", 10, 10, 100, 10)
|
||||
testExpectedGetMinSpotChecksPerCategory("percentage", 10, 10, 200, 10)
|
||||
testExpectedGetMinSpotChecksPerCategory("percentage", 10, 50, 10, 5)
|
||||
|
||||
testExpectedGetMinSpotChecksPerCategory("number", 0, 1, 10, 1)
|
||||
testExpectedGetMinSpotChecksPerCategory("number", 5, 10, 100, 5)
|
||||
}
|
||||
|
||||
func TestGenerateAndDownloadQGateReport(t *testing.T) {
|
||||
ffMock := fortifyMock{Successive: false}
|
||||
config := fortifyExecuteScanOptions{ReportTemplateID: 18, ReportType: "PDF"}
|
||||
|
@ -490,13 +490,39 @@ spec:
|
||||
- name: spotCheckMinimum
|
||||
type: int
|
||||
description:
|
||||
"The minimum number of issues that must be audited per category in the `Spot Checks of each
|
||||
"The minimum number/percentage of issues that must be audited per category in the `Spot Checks of each
|
||||
Category` folder to avoid an error being thrown"
|
||||
scope:
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
default: 1
|
||||
- name: spotCheckMinimumUnit
|
||||
type: string
|
||||
description:
|
||||
"The unit for the spotCheckMinimum to apply."
|
||||
scope:
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
default: 'number'
|
||||
possibleValues:
|
||||
- number
|
||||
- percentage
|
||||
- name: SpotCheckMaximum
|
||||
type: int
|
||||
description:
|
||||
"The maximum number of issues that must be audited per category in the `Spot Checks of each
|
||||
Category` folder to avoid an error being thrown.
|
||||
Note that this flag depends on the result of spotCheckMinimum.
|
||||
For example if spotCheckMinimum percentage value exceeds spotCheckMaximum then
|
||||
spotCheckMaximum will be considerd else spotCheckMinimum is considered.
|
||||
If zero, this flag will be ignored."
|
||||
scope:
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
default: 0
|
||||
- name: fprDownloadEndpoint
|
||||
aliases:
|
||||
- name: fortifyFprDownloadEndpoint
|
||||
|
Loading…
Reference in New Issue
Block a user