// Code generated by piper's step-generator. DO NOT EDIT. package cmd import ( "fmt" "os" "path/filepath" "reflect" "strings" "time" "github.com/SAP/jenkins-library/pkg/config" "github.com/SAP/jenkins-library/pkg/gcs" "github.com/SAP/jenkins-library/pkg/log" "github.com/SAP/jenkins-library/pkg/piperenv" "github.com/SAP/jenkins-library/pkg/splunk" "github.com/SAP/jenkins-library/pkg/telemetry" "github.com/SAP/jenkins-library/pkg/validation" "github.com/bmatcuk/doublestar" "github.com/spf13/cobra" ) type fortifyExecuteScanOptions struct { AdditionalScanParameters []string `json:"additionalScanParameters,omitempty"` Assignees []string `json:"assignees,omitempty"` AuthToken string `json:"authToken,omitempty"` BuildDescriptorExcludeList []string `json:"buildDescriptorExcludeList,omitempty"` CustomScanVersion string `json:"customScanVersion,omitempty"` GithubToken string `json:"githubToken,omitempty"` AutoCreate bool `json:"autoCreate,omitempty"` ModulePath string `json:"modulePath,omitempty"` PythonRequirementsFile string `json:"pythonRequirementsFile,omitempty"` AutodetectClasspath bool `json:"autodetectClasspath,omitempty"` MustAuditIssueGroups string `json:"mustAuditIssueGroups,omitempty"` SpotAuditIssueGroups string `json:"spotAuditIssueGroups,omitempty"` PythonRequirementsInstallSuffix string `json:"pythonRequirementsInstallSuffix,omitempty"` PythonVersion string `json:"pythonVersion,omitempty"` UploadResults bool `json:"uploadResults,omitempty"` Version string `json:"version,omitempty"` BuildDescriptorFile string `json:"buildDescriptorFile,omitempty"` CommitID string `json:"commitId,omitempty"` CommitMessage string `json:"commitMessage,omitempty"` GithubAPIURL string `json:"githubApiUrl,omitempty"` Owner string `json:"owner,omitempty"` Repository string `json:"repository,omitempty"` Memory string `json:"memory,omitempty"` UpdateRulePack bool `json:"updateRulePack,omitempty"` ReportDownloadEndpoint string `json:"reportDownloadEndpoint,omitempty"` PollingMinutes int `json:"pollingMinutes,omitempty"` QuickScan bool `json:"quickScan,omitempty"` Translate string `json:"translate,omitempty"` Src []string `json:"src,omitempty"` Exclude []string `json:"exclude,omitempty"` APIEndpoint string `json:"apiEndpoint,omitempty"` ReportType string `json:"reportType,omitempty"` PythonAdditionalPath []string `json:"pythonAdditionalPath,omitempty"` ArtifactURL string `json:"artifactUrl,omitempty"` ConsiderSuspicious bool `json:"considerSuspicious,omitempty"` ConvertToSarif bool `json:"convertToSarif,omitempty"` FprUploadEndpoint string `json:"fprUploadEndpoint,omitempty"` ProjectName string `json:"projectName,omitempty"` Reporting bool `json:"reporting,omitempty"` ServerURL string `json:"serverUrl,omitempty"` PullRequestMessageRegexGroup int `json:"pullRequestMessageRegexGroup,omitempty"` DeltaMinutes int `json:"deltaMinutes,omitempty"` SpotCheckMinimum int `json:"spotCheckMinimum,omitempty"` FprDownloadEndpoint string `json:"fprDownloadEndpoint,omitempty"` VersioningModel string `json:"versioningModel,omitempty" validate:"possible-values=major major-minor semantic full"` PythonInstallCommand string `json:"pythonInstallCommand,omitempty"` ReportTemplateID int `json:"reportTemplateId,omitempty"` FilterSetTitle string `json:"filterSetTitle,omitempty"` PullRequestName string `json:"pullRequestName,omitempty"` PullRequestMessageRegex string `json:"pullRequestMessageRegex,omitempty"` BuildTool string `json:"buildTool,omitempty"` ProjectSettingsFile string `json:"projectSettingsFile,omitempty"` GlobalSettingsFile string `json:"globalSettingsFile,omitempty"` M2Path string `json:"m2Path,omitempty"` VerifyOnly bool `json:"verifyOnly,omitempty"` InstallArtifacts bool `json:"installArtifacts,omitempty"` CreateResultIssue bool `json:"createResultIssue,omitempty"` } type fortifyExecuteScanInflux struct { step_data struct { fields struct { fortify bool } tags struct { } } fortify_data struct { fields struct { projectName string projectVersion string projectVersionID int64 violations int corporateTotal int corporateAudited int auditAllTotal int auditAllAudited int spotChecksTotal int spotChecksAudited int spotChecksGap int suspicious int exploitable int suppressed int } tags struct { } } } func (i *fortifyExecuteScanInflux) persist(path, resourceName string) { measurementContent := []struct { measurement string valType string name string value interface{} }{ {valType: config.InfluxField, measurement: "step_data", name: "fortify", value: i.step_data.fields.fortify}, {valType: config.InfluxField, measurement: "fortify_data", name: "projectName", value: i.fortify_data.fields.projectName}, {valType: config.InfluxField, measurement: "fortify_data", name: "projectVersion", value: i.fortify_data.fields.projectVersion}, {valType: config.InfluxField, measurement: "fortify_data", name: "projectVersionId", value: i.fortify_data.fields.projectVersionID}, {valType: config.InfluxField, measurement: "fortify_data", name: "violations", value: i.fortify_data.fields.violations}, {valType: config.InfluxField, measurement: "fortify_data", name: "corporateTotal", value: i.fortify_data.fields.corporateTotal}, {valType: config.InfluxField, measurement: "fortify_data", name: "corporateAudited", value: i.fortify_data.fields.corporateAudited}, {valType: config.InfluxField, measurement: "fortify_data", name: "auditAllTotal", value: i.fortify_data.fields.auditAllTotal}, {valType: config.InfluxField, measurement: "fortify_data", name: "auditAllAudited", value: i.fortify_data.fields.auditAllAudited}, {valType: config.InfluxField, measurement: "fortify_data", name: "spotChecksTotal", value: i.fortify_data.fields.spotChecksTotal}, {valType: config.InfluxField, measurement: "fortify_data", name: "spotChecksAudited", value: i.fortify_data.fields.spotChecksAudited}, {valType: config.InfluxField, measurement: "fortify_data", name: "spotChecksGap", value: i.fortify_data.fields.spotChecksGap}, {valType: config.InfluxField, measurement: "fortify_data", name: "suspicious", value: i.fortify_data.fields.suspicious}, {valType: config.InfluxField, measurement: "fortify_data", name: "exploitable", value: i.fortify_data.fields.exploitable}, {valType: config.InfluxField, measurement: "fortify_data", name: "suppressed", value: i.fortify_data.fields.suppressed}, } errCount := 0 for _, metric := range measurementContent { err := piperenv.SetResourceParameter(path, resourceName, filepath.Join(metric.measurement, fmt.Sprintf("%vs", metric.valType), metric.name), metric.value) if err != nil { log.Entry().WithError(err).Error("Error persisting influx environment.") errCount++ } } if errCount > 0 { log.Entry().Error("failed to persist Influx environment") } } type fortifyExecuteScanReports struct { } func (p *fortifyExecuteScanReports) persist(stepConfig fortifyExecuteScanOptions, gcpJsonKeyFilePath string, gcsBucketId string, gcsFolderPath string, gcsSubFolder string) { if gcsBucketId == "" { log.Entry().Info("persisting reports to GCS is disabled, because gcsBucketId is empty") return } log.Entry().Info("Uploading reports to Google Cloud Storage...") content := []gcs.ReportOutputParam{ {FilePattern: "**/*.PDF", ParamRef: "", StepResultType: "fortify"}, {FilePattern: "**/*.fpr", ParamRef: "", StepResultType: "fortify"}, {FilePattern: "**/fortify-scan.*", ParamRef: "", StepResultType: "fortify"}, {FilePattern: "**/toolrun_fortify_*.json", ParamRef: "", StepResultType: "fortify"}, {FilePattern: "**/piper_fortify_report.json", ParamRef: "", StepResultType: "fortify"}, {FilePattern: "**/piper_fortify_report.html", ParamRef: "", StepResultType: "fortify"}, } envVars := []gcs.EnvVar{ {Name: "GOOGLE_APPLICATION_CREDENTIALS", Value: gcpJsonKeyFilePath, Modified: false}, } gcsClient, err := gcs.NewClient(gcs.WithEnvVars(envVars)) if err != nil { log.Entry().Errorf("creation of GCS client failed: %v", err) return } defer gcsClient.Close() structVal := reflect.ValueOf(&stepConfig).Elem() inputParameters := map[string]string{} for i := 0; i < structVal.NumField(); i++ { field := structVal.Type().Field(i) if field.Type.String() == "string" { paramName := strings.Split(field.Tag.Get("json"), ",") paramValue, _ := structVal.Field(i).Interface().(string) inputParameters[paramName[0]] = paramValue } } if err := gcs.PersistReportsToGCS(gcsClient, content, inputParameters, gcsFolderPath, gcsBucketId, gcsSubFolder, doublestar.Glob, os.Stat); err != nil { log.Entry().Errorf("failed to persist reports: %v", err) } } // FortifyExecuteScanCommand This step executes a Fortify scan on the specified project to perform static code analysis and check the source code for security flaws. func FortifyExecuteScanCommand() *cobra.Command { const STEP_NAME = "fortifyExecuteScan" metadata := fortifyExecuteScanMetadata() var stepConfig fortifyExecuteScanOptions var startTime time.Time var influx fortifyExecuteScanInflux var reports fortifyExecuteScanReports var logCollector *log.CollectorHook var splunkClient *splunk.Splunk telemetryClient := &telemetry.Telemetry{} var createFortifyExecuteScanCmd = &cobra.Command{ Use: STEP_NAME, Short: "This step executes a Fortify scan on the specified project to perform static code analysis and check the source code for security flaws.", Long: `This step executes a Fortify scan on the specified project to perform static code analysis and check the source code for security flaws. The Fortify step triggers a scan locally on your Jenkins within a docker container so finally you have to supply a docker image with a Fortify SCA and Java plus Maven / Gradle or alternatively Python installed into it for being able to perform any scans. !!! hint "Scanning MTA projects" Build type ` + "`" + `maven` + "`" + ` requires a so called aggregator pom which includes all modules to be scanned. If used in a mta-project which includes non-java submodules as maven dependency (e.g. node via frontend-maven-plugin), exclude those by specifying java path explicitly, e.g. ` + "`" + `java/**/src/main/java/**/*` + "`" + `. Besides triggering a scan the step verifies the results after they have been uploaded and processed by the Fortify SSC. By default the following KPIs are enforced: * All issues must be audited from the Corporate Security Requirements folder. * All issues must be audited from the Audit All folder. * At least one issue per category must be audited from the Spot Checks of Each Category folder. * Nothing needs to be audited from the Optional folder.`, PreRunE: func(cmd *cobra.Command, _ []string) error { startTime = time.Now() log.SetStepName(STEP_NAME) log.SetVerbose(GeneralConfig.Verbose) GeneralConfig.GitHubAccessTokens = ResolveAccessTokens(GeneralConfig.GitHubTokens) path, _ := os.Getwd() fatalHook := &log.FatalHook{CorrelationID: GeneralConfig.CorrelationID, Path: path} log.RegisterHook(fatalHook) err := PrepareConfig(cmd, &metadata, STEP_NAME, &stepConfig, config.OpenPiperFile) if err != nil { log.SetErrorCategory(log.ErrorConfiguration) return err } log.RegisterSecret(stepConfig.AuthToken) log.RegisterSecret(stepConfig.GithubToken) if len(GeneralConfig.HookConfig.SentryConfig.Dsn) > 0 { sentryHook := log.NewSentryHook(GeneralConfig.HookConfig.SentryConfig.Dsn, GeneralConfig.CorrelationID) log.RegisterHook(&sentryHook) } if len(GeneralConfig.HookConfig.SplunkConfig.Dsn) > 0 { splunkClient = &splunk.Splunk{} logCollector = &log.CollectorHook{CorrelationID: GeneralConfig.CorrelationID} log.RegisterHook(logCollector) } validation, err := validation.New(validation.WithJSONNamesForStructFields(), validation.WithPredefinedErrorMessages()) if err != nil { return err } if err = validation.ValidateStruct(stepConfig); err != nil { log.SetErrorCategory(log.ErrorConfiguration) return err } return nil }, Run: func(_ *cobra.Command, _ []string) { stepTelemetryData := telemetry.CustomData{} stepTelemetryData.ErrorCode = "1" handler := func() { influx.persist(GeneralConfig.EnvRootPath, "influx") reports.persist(stepConfig, GeneralConfig.GCPJsonKeyFilePath, GeneralConfig.GCSBucketId, GeneralConfig.GCSFolderPath, GeneralConfig.GCSSubFolder) config.RemoveVaultSecretFiles() stepTelemetryData.Duration = fmt.Sprintf("%v", time.Since(startTime).Milliseconds()) stepTelemetryData.ErrorCategory = log.GetErrorCategory().String() stepTelemetryData.PiperCommitHash = GitCommit telemetryClient.SetData(&stepTelemetryData) telemetryClient.Send() if len(GeneralConfig.HookConfig.SplunkConfig.Dsn) > 0 { splunkClient.Send(telemetryClient.GetData(), logCollector) } } log.DeferExitHandler(handler) defer handler() telemetryClient.Initialize(GeneralConfig.NoTelemetry, STEP_NAME) if len(GeneralConfig.HookConfig.SplunkConfig.Dsn) > 0 { splunkClient.Initialize(GeneralConfig.CorrelationID, GeneralConfig.HookConfig.SplunkConfig.Dsn, GeneralConfig.HookConfig.SplunkConfig.Token, GeneralConfig.HookConfig.SplunkConfig.Index, GeneralConfig.HookConfig.SplunkConfig.SendLogs) } fortifyExecuteScan(stepConfig, &stepTelemetryData, &influx) stepTelemetryData.ErrorCode = "0" log.Entry().Info("SUCCESS") }, } addFortifyExecuteScanFlags(createFortifyExecuteScanCmd, &stepConfig) return createFortifyExecuteScanCmd } func addFortifyExecuteScanFlags(cmd *cobra.Command, stepConfig *fortifyExecuteScanOptions) { cmd.Flags().StringSliceVar(&stepConfig.AdditionalScanParameters, "additionalScanParameters", []string{}, "List of additional scan parameters to be used for Fortify sourceanalyzer command execution.") cmd.Flags().StringSliceVar(&stepConfig.Assignees, "assignees", []string{``}, "Defines the assignees for the Github Issue created/updated with the results of the scan as a list of login names.") cmd.Flags().StringVar(&stepConfig.AuthToken, "authToken", os.Getenv("PIPER_authToken"), "The FortifyToken to use for authentication") cmd.Flags().StringSliceVar(&stepConfig.BuildDescriptorExcludeList, "buildDescriptorExcludeList", []string{`unit-tests/pom.xml`, `integration-tests/pom.xml`}, "List of build descriptors and therefore modules to exclude from the scan and assessment activities.") cmd.Flags().StringVar(&stepConfig.CustomScanVersion, "customScanVersion", os.Getenv("PIPER_customScanVersion"), "Custom version of the Fortify project used as source.") cmd.Flags().StringVar(&stepConfig.GithubToken, "githubToken", os.Getenv("PIPER_githubToken"), "GitHub personal access token as per https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line") cmd.Flags().BoolVar(&stepConfig.AutoCreate, "autoCreate", false, "Whether Fortify project and project version shall be implicitly auto created in case they cannot be found in the backend") cmd.Flags().StringVar(&stepConfig.ModulePath, "modulePath", `./`, "Allows providing the path for the module to scan") cmd.Flags().StringVar(&stepConfig.PythonRequirementsFile, "pythonRequirementsFile", os.Getenv("PIPER_pythonRequirementsFile"), "The requirements file used in `buildTool: 'pip'` to populate the build environment with the necessary dependencies") cmd.Flags().BoolVar(&stepConfig.AutodetectClasspath, "autodetectClasspath", true, "Whether the classpath is automatically determined via build tool i.e. maven or pip or not at all") cmd.Flags().StringVar(&stepConfig.MustAuditIssueGroups, "mustAuditIssueGroups", `Corporate Security Requirements, Audit All`, "Comma separated list of issue groups that must be audited completely") cmd.Flags().StringVar(&stepConfig.SpotAuditIssueGroups, "spotAuditIssueGroups", `Spot Checks of Each Category`, "Comma separated list of issue groups that are spot checked and for which `spotCheckMinimum` audited issues are enforced") cmd.Flags().StringVar(&stepConfig.PythonRequirementsInstallSuffix, "pythonRequirementsInstallSuffix", os.Getenv("PIPER_pythonRequirementsInstallSuffix"), "The suffix for the command used to install the requirements file in `buildTool: 'pip'` to populate the build environment with the necessary dependencies") cmd.Flags().StringVar(&stepConfig.PythonVersion, "pythonVersion", `python3`, "Python version to be used in `buildTool: 'pip'`") cmd.Flags().BoolVar(&stepConfig.UploadResults, "uploadResults", true, "Whether results shall be uploaded or not") cmd.Flags().StringVar(&stepConfig.Version, "version", os.Getenv("PIPER_version"), "Version used in conjunction with [`versioningModel`](#versioningModel) to identify the Fortify project to be created and used for results aggregation.") cmd.Flags().StringVar(&stepConfig.BuildDescriptorFile, "buildDescriptorFile", `./pom.xml`, "Path to the build descriptor file addressing the module/folder to be scanned.") cmd.Flags().StringVar(&stepConfig.CommitID, "commitId", os.Getenv("PIPER_commitId"), "Set the Git commit ID for identifying artifacts throughout the scan.") cmd.Flags().StringVar(&stepConfig.CommitMessage, "commitMessage", os.Getenv("PIPER_commitMessage"), "Set the Git commit message for identifying pull request merges throughout the scan.") cmd.Flags().StringVar(&stepConfig.GithubAPIURL, "githubApiUrl", `https://api.github.com`, "Set the GitHub API URL.") cmd.Flags().StringVar(&stepConfig.Owner, "owner", os.Getenv("PIPER_owner"), "Set the GitHub organization.") cmd.Flags().StringVar(&stepConfig.Repository, "repository", os.Getenv("PIPER_repository"), "Set the GitHub repository.") cmd.Flags().StringVar(&stepConfig.Memory, "memory", `-Xmx4G -Xms512M`, "The amount of memory granted to the translate/scan executions") cmd.Flags().BoolVar(&stepConfig.UpdateRulePack, "updateRulePack", true, "Whether the rule pack shall be updated and pulled from Fortify SSC before scanning or not") cmd.Flags().StringVar(&stepConfig.ReportDownloadEndpoint, "reportDownloadEndpoint", `/transfer/reportDownload.html`, "Fortify SSC endpoint for Report downloads") cmd.Flags().IntVar(&stepConfig.PollingMinutes, "pollingMinutes", 30, "The number of minutes for which an uploaded FPR artifact''s status is being polled to finish queuing/processing, if exceeded polling will be stopped and an error will be thrown") cmd.Flags().BoolVar(&stepConfig.QuickScan, "quickScan", false, "Whether a quick scan should be performed, please consult the related Fortify documentation on JAM on the impact of this setting") cmd.Flags().StringVar(&stepConfig.Translate, "translate", os.Getenv("PIPER_translate"), "Options for translate phase of Fortify. Most likely, you do not need to set this parameter. See src, exclude. If `'src'` and `'exclude'` are set they are automatically used. Technical details: It has to be a JSON string of list of maps with required key `'src'`, and optional keys `'exclude'`, `'libDirs'`, `'aspnetcore'`, and `'dotNetCoreVersion'`") cmd.Flags().StringSliceVar(&stepConfig.Src, "src", []string{}, "A list of source directories to scan. Wildcards can be used, e.g., `'src/main/java/**/*'`. If `'translate'` is set, this will ignored. The default value for `buildTool: 'maven'` is `['**/*.xml', '**/*.html', '**/*.jsp', '**/*.js', '**/src/main/resources/**/*', '**/src/main/java/**/*', '**/target/main/java/**/*', '**/target/main/resources/**/*', '**/target/generated-sources/**/*']`, for `buildTool: 'pip'` it is `['./**/*']`.") cmd.Flags().StringSliceVar(&stepConfig.Exclude, "exclude", []string{}, "A list of directories/files to be excluded from the scan. Wildcards can be used, e.g., `'**/Test.java'`. If `translate` is set, this will ignored. The default value for `buildTool: 'maven'` is `['**/src/test/**/*']`, for `buildTool: 'pip'` it is `['./**/tests/**/*', './**/setup.py']`.") cmd.Flags().StringVar(&stepConfig.APIEndpoint, "apiEndpoint", `/api/v1`, "Fortify SSC endpoint used for uploading the scan results and checking the audit state") cmd.Flags().StringVar(&stepConfig.ReportType, "reportType", `PDF`, "The type of report to be generated") cmd.Flags().StringSliceVar(&stepConfig.PythonAdditionalPath, "pythonAdditionalPath", []string{`./lib`, `.`}, "A list of additional paths which can be used in `buildTool: 'pip'` for customization purposes") cmd.Flags().StringVar(&stepConfig.ArtifactURL, "artifactUrl", os.Getenv("PIPER_artifactUrl"), "Path/URL pointing to an additional artifact repository for resolution of additional artifacts during the build") cmd.Flags().BoolVar(&stepConfig.ConsiderSuspicious, "considerSuspicious", true, "Whether suspicious issues should trigger the check to fail or not") cmd.Flags().BoolVar(&stepConfig.ConvertToSarif, "convertToSarif", false, "[BETA] Convert the proprietary format of Fortify scan results to the open SARIF standard. Uploaded through Cumulus later on.") cmd.Flags().StringVar(&stepConfig.FprUploadEndpoint, "fprUploadEndpoint", `/upload/resultFileUpload.html`, "Fortify SSC endpoint for FPR uploads") cmd.Flags().StringVar(&stepConfig.ProjectName, "projectName", `{{list .GroupID .ArtifactID | join "-" | trimAll "-"}}`, "The project used for reporting results in SSC") cmd.Flags().BoolVar(&stepConfig.Reporting, "reporting", false, "Influences whether a report is generated or not") 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().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") cmd.Flags().IntVar(&stepConfig.ReportTemplateID, "reportTemplateId", 18, "Report template ID to be used for generating the Fortify report") cmd.Flags().StringVar(&stepConfig.FilterSetTitle, "filterSetTitle", `SAP`, "Title of the filter set to use for analysing the results") cmd.Flags().StringVar(&stepConfig.PullRequestName, "pullRequestName", os.Getenv("PIPER_pullRequestName"), "The name of the pull request branch which will trigger creation of a new version in Fortify SSC based on the master branch version") cmd.Flags().StringVar(&stepConfig.PullRequestMessageRegex, "pullRequestMessageRegex", `.*Merge pull request #(\\d+) from.*`, "Regex used to identify the PR-XXX reference within the merge commit message") cmd.Flags().StringVar(&stepConfig.BuildTool, "buildTool", `maven`, "Scan type used for the step which can be `'maven'`, `'pip'` or `'gradle'`") cmd.Flags().StringVar(&stepConfig.ProjectSettingsFile, "projectSettingsFile", os.Getenv("PIPER_projectSettingsFile"), "Path to the mvn settings file that should be used as project settings file.") cmd.Flags().StringVar(&stepConfig.GlobalSettingsFile, "globalSettingsFile", os.Getenv("PIPER_globalSettingsFile"), "Path to the mvn settings file that should be used as global settings file.") cmd.Flags().StringVar(&stepConfig.M2Path, "m2Path", os.Getenv("PIPER_m2Path"), "Path to the location of the local repository that should be used.") cmd.Flags().BoolVar(&stepConfig.VerifyOnly, "verifyOnly", false, "Whether the step shall only apply verification checks or whether it does a full scan and check cycle") cmd.Flags().BoolVar(&stepConfig.InstallArtifacts, "installArtifacts", false, "If enabled, it will install all artifacts to the local maven repository to make them available before running Fortify. This is required if any maven module has dependencies to other modules in the repository and they were not installed before.") cmd.Flags().BoolVar(&stepConfig.CreateResultIssue, "createResultIssue", false, "Whether the step creates a GitHub issue containing the scan results in the originating repo. Since optimized pipelines are headless the creation is implicitly activated for schedules runs.") cmd.MarkFlagRequired("authToken") cmd.Flags().MarkDeprecated("pythonAdditionalPath", "this is deprecated") cmd.MarkFlagRequired("serverUrl") } // retrieve step metadata func fortifyExecuteScanMetadata() config.StepData { var theMetaData = config.StepData{ Metadata: config.StepMetadata{ Name: "fortifyExecuteScan", Aliases: []config.Alias{}, Description: "This step executes a Fortify scan on the specified project to perform static code analysis and check the source code for security flaws.", }, Spec: config.StepSpec{ Inputs: config.StepInputs{ Secrets: []config.StepSecrets{ {Name: "fortifyCredentialsId", Description: "Jenkins 'Secret text' credentials ID containing token to authenticate to Fortify SSC.", Type: "jenkins"}, {Name: "githubTokenCredentialsId", Description: "Jenkins 'Secret text' credentials ID containing token to authenticate to GitHub.", Type: "jenkins"}, }, Resources: []config.StepResources{ {Name: "commonPipelineEnvironment"}, {Name: "buildDescriptor", Type: "stash"}, {Name: "deployDescriptor", Type: "stash"}, {Name: "tests", Type: "stash"}, {Name: "opensourceConfiguration", Type: "stash"}, }, Parameters: []config.StepParameters{ { Name: "additionalScanParameters", ResourceRef: []config.ResourceReference{}, Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, Type: "[]string", Mandatory: false, Aliases: []config.Alias{}, Default: []string{}, }, { Name: "assignees", ResourceRef: []config.ResourceReference{}, Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, Type: "[]string", Mandatory: false, Aliases: []config.Alias{}, Default: []string{``}, }, { Name: "authToken", ResourceRef: []config.ResourceReference{ { Name: "fortifyCredentialsId", Type: "secret", }, { Name: "fortifyVaultSecretName", Type: "vaultSecret", Default: "fortify", }, }, Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, Type: "string", Mandatory: true, Aliases: []config.Alias{}, Default: os.Getenv("PIPER_authToken"), }, { Name: "buildDescriptorExcludeList", ResourceRef: []config.ResourceReference{}, Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, Type: "[]string", Mandatory: false, Aliases: []config.Alias{}, Default: []string{`unit-tests/pom.xml`, `integration-tests/pom.xml`}, }, { Name: "customScanVersion", ResourceRef: []config.ResourceReference{}, Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"}, Type: "string", Mandatory: false, Aliases: []config.Alias{}, Default: os.Getenv("PIPER_customScanVersion"), }, { Name: "githubToken", ResourceRef: []config.ResourceReference{ { Name: "githubTokenCredentialsId", Type: "secret", }, { Name: "githubVaultSecretName", Type: "vaultSecret", Default: "github", }, }, Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"}, Type: "string", Mandatory: false, Aliases: []config.Alias{{Name: "access_token"}}, Default: os.Getenv("PIPER_githubToken"), }, { Name: "autoCreate", ResourceRef: []config.ResourceReference{}, Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, Type: "bool", Mandatory: false, Aliases: []config.Alias{}, Default: false, }, { Name: "modulePath", ResourceRef: []config.ResourceReference{}, Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, Type: "string", Mandatory: false, Aliases: []config.Alias{}, Default: `./`, }, { Name: "pythonRequirementsFile", ResourceRef: []config.ResourceReference{}, Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, Type: "string", Mandatory: false, Aliases: []config.Alias{}, Default: os.Getenv("PIPER_pythonRequirementsFile"), }, { Name: "autodetectClasspath", ResourceRef: []config.ResourceReference{}, Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, Type: "bool", Mandatory: false, Aliases: []config.Alias{}, Default: true, }, { Name: "mustAuditIssueGroups", ResourceRef: []config.ResourceReference{}, Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, Type: "string", Mandatory: false, Aliases: []config.Alias{}, Default: `Corporate Security Requirements, Audit All`, }, { Name: "spotAuditIssueGroups", ResourceRef: []config.ResourceReference{}, Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, Type: "string", Mandatory: false, Aliases: []config.Alias{}, Default: `Spot Checks of Each Category`, }, { Name: "pythonRequirementsInstallSuffix", ResourceRef: []config.ResourceReference{}, Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, Type: "string", Mandatory: false, Aliases: []config.Alias{}, Default: os.Getenv("PIPER_pythonRequirementsInstallSuffix"), }, { Name: "pythonVersion", ResourceRef: []config.ResourceReference{}, Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"}, Type: "string", Mandatory: false, Aliases: []config.Alias{}, Default: `python3`, }, { Name: "uploadResults", ResourceRef: []config.ResourceReference{}, Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, Type: "bool", Mandatory: false, Aliases: []config.Alias{}, Default: true, }, { Name: "version", ResourceRef: []config.ResourceReference{ { Name: "commonPipelineEnvironment", Param: "artifactVersion", }, }, Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"}, Type: "string", Mandatory: false, Aliases: []config.Alias{{Name: "fortifyProjectVersion", Deprecated: true}}, Default: os.Getenv("PIPER_version"), }, { Name: "buildDescriptorFile", ResourceRef: []config.ResourceReference{}, Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, Type: "string", Mandatory: false, Aliases: []config.Alias{}, Default: `./pom.xml`, Conditions: []config.Condition{{ConditionRef: "strings-equal", Params: []config.Param{{Name: "buildTool", Value: "maven"}}}}, }, { Name: "buildDescriptorFile", ResourceRef: []config.ResourceReference{}, Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, Type: "string", Mandatory: false, Aliases: []config.Alias{}, Default: `./setup.py`, Conditions: []config.Condition{{ConditionRef: "strings-equal", Params: []config.Param{{Name: "buildTool", Value: "pip"}}}}, }, { Name: "buildDescriptorFile", ResourceRef: []config.ResourceReference{}, Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, Type: "string", Mandatory: false, Aliases: []config.Alias{}, Default: `./build.gradle`, Conditions: []config.Condition{{ConditionRef: "strings-equal", Params: []config.Param{{Name: "buildTool", Value: "gradle"}}}}, }, { Name: "commitId", ResourceRef: []config.ResourceReference{ { Name: "commonPipelineEnvironment", Param: "git/commitId", }, }, Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, Type: "string", Mandatory: false, Aliases: []config.Alias{}, Default: os.Getenv("PIPER_commitId"), }, { Name: "commitMessage", ResourceRef: []config.ResourceReference{ { Name: "commonPipelineEnvironment", Param: "git/commitMessage", }, }, Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, Type: "string", Mandatory: false, Aliases: []config.Alias{}, Default: os.Getenv("PIPER_commitMessage"), }, { Name: "githubApiUrl", ResourceRef: []config.ResourceReference{}, Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"}, Type: "string", Mandatory: false, Aliases: []config.Alias{}, Default: `https://api.github.com`, }, { Name: "owner", ResourceRef: []config.ResourceReference{ { Name: "commonPipelineEnvironment", Param: "github/owner", }, }, Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"}, Type: "string", Mandatory: false, Aliases: []config.Alias{{Name: "githubOrg"}}, Default: os.Getenv("PIPER_owner"), }, { Name: "repository", ResourceRef: []config.ResourceReference{ { Name: "commonPipelineEnvironment", Param: "github/repository", }, }, Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"}, Type: "string", Mandatory: false, Aliases: []config.Alias{{Name: "githubRepo"}}, Default: os.Getenv("PIPER_repository"), }, { Name: "memory", ResourceRef: []config.ResourceReference{}, Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, Type: "string", Mandatory: false, Aliases: []config.Alias{}, Default: `-Xmx4G -Xms512M`, }, { Name: "updateRulePack", ResourceRef: []config.ResourceReference{}, Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, Type: "bool", Mandatory: false, Aliases: []config.Alias{}, Default: true, }, { Name: "reportDownloadEndpoint", ResourceRef: []config.ResourceReference{}, Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"}, Type: "string", Mandatory: false, Aliases: []config.Alias{{Name: "fortifyReportDownloadEndpoint"}}, Default: `/transfer/reportDownload.html`, }, { Name: "pollingMinutes", ResourceRef: []config.ResourceReference{}, Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, Type: "int", Mandatory: false, Aliases: []config.Alias{}, Default: 30, }, { Name: "quickScan", ResourceRef: []config.ResourceReference{}, Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, Type: "bool", Mandatory: false, Aliases: []config.Alias{}, Default: false, }, { Name: "translate", ResourceRef: []config.ResourceReference{}, Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, Type: "string", Mandatory: false, Aliases: []config.Alias{}, Default: os.Getenv("PIPER_translate"), }, { Name: "src", ResourceRef: []config.ResourceReference{}, Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, Type: "[]string", Mandatory: false, Aliases: []config.Alias{}, Default: []string{}, }, { Name: "exclude", ResourceRef: []config.ResourceReference{}, Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, Type: "[]string", Mandatory: false, Aliases: []config.Alias{}, Default: []string{}, }, { Name: "apiEndpoint", ResourceRef: []config.ResourceReference{}, Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"}, Type: "string", Mandatory: false, Aliases: []config.Alias{{Name: "fortifyApiEndpoint"}}, Default: `/api/v1`, }, { Name: "reportType", ResourceRef: []config.ResourceReference{}, Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, Type: "string", Mandatory: false, Aliases: []config.Alias{}, Default: `PDF`, }, { Name: "pythonAdditionalPath", ResourceRef: []config.ResourceReference{}, Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, Type: "[]string", Mandatory: false, Aliases: []config.Alias{}, Default: []string{`./lib`, `.`}, DeprecationMessage: "this is deprecated", }, { Name: "artifactUrl", ResourceRef: []config.ResourceReference{}, Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, Type: "string", Mandatory: false, Aliases: []config.Alias{}, Default: os.Getenv("PIPER_artifactUrl"), }, { Name: "considerSuspicious", ResourceRef: []config.ResourceReference{}, Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, Type: "bool", Mandatory: false, Aliases: []config.Alias{}, Default: true, }, { Name: "convertToSarif", ResourceRef: []config.ResourceReference{}, Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, Type: "bool", Mandatory: false, Aliases: []config.Alias{}, Default: false, }, { Name: "fprUploadEndpoint", ResourceRef: []config.ResourceReference{}, Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"}, Type: "string", Mandatory: false, Aliases: []config.Alias{{Name: "fortifyFprUploadEndpoint"}}, Default: `/upload/resultFileUpload.html`, }, { Name: "projectName", ResourceRef: []config.ResourceReference{}, Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, Type: "string", Mandatory: false, Aliases: []config.Alias{{Name: "fortifyProjectName"}}, Default: `{{list .GroupID .ArtifactID | join "-" | trimAll "-"}}`, }, { Name: "reporting", ResourceRef: []config.ResourceReference{}, Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, Type: "bool", Mandatory: false, Aliases: []config.Alias{}, Default: false, }, { Name: "serverUrl", ResourceRef: []config.ResourceReference{}, Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"}, Type: "string", Mandatory: true, Aliases: []config.Alias{{Name: "fortifyServerUrl"}, {Name: "sscUrl", Deprecated: true}}, Default: os.Getenv("PIPER_serverUrl"), }, { Name: "pullRequestMessageRegexGroup", ResourceRef: []config.ResourceReference{}, Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, Type: "int", Mandatory: false, Aliases: []config.Alias{}, Default: 1, }, { Name: "deltaMinutes", ResourceRef: []config.ResourceReference{}, Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, Type: "int", Mandatory: false, Aliases: []config.Alias{}, Default: 5, }, { Name: "spotCheckMinimum", ResourceRef: []config.ResourceReference{}, Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, Type: "int", Mandatory: false, Aliases: []config.Alias{}, Default: 1, }, { Name: "fprDownloadEndpoint", ResourceRef: []config.ResourceReference{}, Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"}, Type: "string", Mandatory: false, Aliases: []config.Alias{{Name: "fortifyFprDownloadEndpoint"}}, Default: `/download/currentStateFprDownload.html`, }, { Name: "versioningModel", ResourceRef: []config.ResourceReference{}, Scope: []string{"PARAMETERS", "GENERAL", "STAGES", "STEPS"}, Type: "string", Mandatory: false, Aliases: []config.Alias{{Name: "defaultVersioningModel", Deprecated: true}}, Default: `major`, }, { Name: "pythonInstallCommand", ResourceRef: []config.ResourceReference{}, Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, Type: "string", Mandatory: false, Aliases: []config.Alias{}, Default: `{{.Pip}} install --user .`, }, { Name: "reportTemplateId", ResourceRef: []config.ResourceReference{}, Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, Type: "int", Mandatory: false, Aliases: []config.Alias{}, Default: 18, }, { Name: "filterSetTitle", ResourceRef: []config.ResourceReference{}, Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, Type: "string", Mandatory: false, Aliases: []config.Alias{}, Default: `SAP`, }, { Name: "pullRequestName", ResourceRef: []config.ResourceReference{}, Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, Type: "string", Mandatory: false, Aliases: []config.Alias{}, Default: os.Getenv("PIPER_pullRequestName"), }, { Name: "pullRequestMessageRegex", ResourceRef: []config.ResourceReference{}, Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, Type: "string", Mandatory: false, Aliases: []config.Alias{}, Default: `.*Merge pull request #(\\d+) from.*`, }, { Name: "buildTool", ResourceRef: []config.ResourceReference{}, Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"}, Type: "string", Mandatory: false, Aliases: []config.Alias{}, Default: `maven`, }, { Name: "projectSettingsFile", ResourceRef: []config.ResourceReference{}, Scope: []string{"GENERAL", "STEPS", "STAGES", "PARAMETERS"}, Type: "string", Mandatory: false, Aliases: []config.Alias{{Name: "maven/projectSettingsFile"}}, Default: os.Getenv("PIPER_projectSettingsFile"), }, { Name: "globalSettingsFile", ResourceRef: []config.ResourceReference{}, Scope: []string{"GENERAL", "STEPS", "STAGES", "PARAMETERS"}, Type: "string", Mandatory: false, Aliases: []config.Alias{{Name: "maven/globalSettingsFile"}}, Default: os.Getenv("PIPER_globalSettingsFile"), }, { Name: "m2Path", ResourceRef: []config.ResourceReference{}, Scope: []string{"GENERAL", "STEPS", "STAGES", "PARAMETERS"}, Type: "string", Mandatory: false, Aliases: []config.Alias{{Name: "maven/m2Path"}}, Default: os.Getenv("PIPER_m2Path"), }, { Name: "verifyOnly", ResourceRef: []config.ResourceReference{}, Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, Type: "bool", Mandatory: false, Aliases: []config.Alias{}, Default: false, }, { Name: "installArtifacts", ResourceRef: []config.ResourceReference{}, Scope: []string{"GENERAL", "STEPS", "STAGES", "PARAMETERS"}, Type: "bool", Mandatory: false, Aliases: []config.Alias{}, Default: false, }, { Name: "createResultIssue", ResourceRef: []config.ResourceReference{ { Name: "commonPipelineEnvironment", Param: "custom/optimizedAndScheduled", }, }, Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, Type: "bool", Mandatory: false, Aliases: []config.Alias{}, Default: false, }, }, }, Containers: []config.Container{ {}, }, Outputs: config.StepOutputs{ Resources: []config.StepResources{ { Name: "influx", Type: "influx", Parameters: []map[string]interface{}{ {"name": "step_data", "fields": []map[string]string{{"name": "fortify"}}}, {"name": "fortify_data", "fields": []map[string]string{{"name": "projectName"}, {"name": "projectVersion"}, {"name": "projectVersionId"}, {"name": "violations"}, {"name": "corporateTotal"}, {"name": "corporateAudited"}, {"name": "auditAllTotal"}, {"name": "auditAllAudited"}, {"name": "spotChecksTotal"}, {"name": "spotChecksAudited"}, {"name": "spotChecksGap"}, {"name": "suspicious"}, {"name": "exploitable"}, {"name": "suppressed"}}}, }, }, { Name: "reports", Type: "reports", Parameters: []map[string]interface{}{ {"filePattern": "**/*.PDF", "type": "fortify"}, {"filePattern": "**/*.fpr", "type": "fortify"}, {"filePattern": "**/fortify-scan.*", "type": "fortify"}, {"filePattern": "**/toolrun_fortify_*.json", "type": "fortify"}, {"filePattern": "**/piper_fortify_report.json", "type": "fortify"}, {"filePattern": "**/piper_fortify_report.html", "type": "fortify"}, }, }, }, }, }, } return theMetaData }