github.com/jaylevin/jenkins-library@v1.230.4/cmd/protecodeExecuteScan_generated.go (about)

     1  // Code generated by piper's step-generator. DO NOT EDIT.
     2  
     3  package cmd
     4  
     5  import (
     6  	"fmt"
     7  	"os"
     8  	"path/filepath"
     9  	"reflect"
    10  	"strings"
    11  	"time"
    12  
    13  	"github.com/SAP/jenkins-library/pkg/config"
    14  	"github.com/SAP/jenkins-library/pkg/gcs"
    15  	"github.com/SAP/jenkins-library/pkg/log"
    16  	"github.com/SAP/jenkins-library/pkg/piperenv"
    17  	"github.com/SAP/jenkins-library/pkg/splunk"
    18  	"github.com/SAP/jenkins-library/pkg/telemetry"
    19  	"github.com/SAP/jenkins-library/pkg/validation"
    20  	"github.com/bmatcuk/doublestar"
    21  	"github.com/spf13/cobra"
    22  )
    23  
    24  type protecodeExecuteScanOptions struct {
    25  	ExcludeCVEs                 string `json:"excludeCVEs,omitempty"`
    26  	FailOnSevereVulnerabilities bool   `json:"failOnSevereVulnerabilities,omitempty"`
    27  	ScanImage                   string `json:"scanImage,omitempty"`
    28  	DockerRegistryURL           string `json:"dockerRegistryUrl,omitempty"`
    29  	DockerConfigJSON            string `json:"dockerConfigJSON,omitempty"`
    30  	CleanupMode                 string `json:"cleanupMode,omitempty" validate:"possible-values=none binary complete"`
    31  	FilePath                    string `json:"filePath,omitempty"`
    32  	TimeoutMinutes              string `json:"timeoutMinutes,omitempty"`
    33  	ServerURL                   string `json:"serverUrl,omitempty"`
    34  	ReportFileName              string `json:"reportFileName,omitempty"`
    35  	FetchURL                    string `json:"fetchUrl,omitempty"`
    36  	Group                       string `json:"group,omitempty"`
    37  	VerifyOnly                  bool   `json:"verifyOnly,omitempty"`
    38  	ReplaceProductID            int    `json:"replaceProductId,omitempty"`
    39  	Username                    string `json:"username,omitempty"`
    40  	Password                    string `json:"password,omitempty"`
    41  	Version                     string `json:"version,omitempty"`
    42  	CustomScanVersion           string `json:"customScanVersion,omitempty"`
    43  	VersioningModel             string `json:"versioningModel,omitempty" validate:"possible-values=major major-minor semantic full"`
    44  	PullRequestName             string `json:"pullRequestName,omitempty"`
    45  }
    46  
    47  type protecodeExecuteScanInflux struct {
    48  	step_data struct {
    49  		fields struct {
    50  			protecode bool
    51  		}
    52  		tags struct {
    53  		}
    54  	}
    55  	protecode_data struct {
    56  		fields struct {
    57  			excluded_vulnerabilities   int
    58  			historical_vulnerabilities int
    59  			major_vulnerabilities      int
    60  			minor_vulnerabilities      int
    61  			triaged_vulnerabilities    int
    62  			vulnerabilities            int
    63  		}
    64  		tags struct {
    65  		}
    66  	}
    67  }
    68  
    69  func (i *protecodeExecuteScanInflux) persist(path, resourceName string) {
    70  	measurementContent := []struct {
    71  		measurement string
    72  		valType     string
    73  		name        string
    74  		value       interface{}
    75  	}{
    76  		{valType: config.InfluxField, measurement: "step_data", name: "protecode", value: i.step_data.fields.protecode},
    77  		{valType: config.InfluxField, measurement: "protecode_data", name: "excluded_vulnerabilities", value: i.protecode_data.fields.excluded_vulnerabilities},
    78  		{valType: config.InfluxField, measurement: "protecode_data", name: "historical_vulnerabilities", value: i.protecode_data.fields.historical_vulnerabilities},
    79  		{valType: config.InfluxField, measurement: "protecode_data", name: "major_vulnerabilities", value: i.protecode_data.fields.major_vulnerabilities},
    80  		{valType: config.InfluxField, measurement: "protecode_data", name: "minor_vulnerabilities", value: i.protecode_data.fields.minor_vulnerabilities},
    81  		{valType: config.InfluxField, measurement: "protecode_data", name: "triaged_vulnerabilities", value: i.protecode_data.fields.triaged_vulnerabilities},
    82  		{valType: config.InfluxField, measurement: "protecode_data", name: "vulnerabilities", value: i.protecode_data.fields.vulnerabilities},
    83  	}
    84  
    85  	errCount := 0
    86  	for _, metric := range measurementContent {
    87  		err := piperenv.SetResourceParameter(path, resourceName, filepath.Join(metric.measurement, fmt.Sprintf("%vs", metric.valType), metric.name), metric.value)
    88  		if err != nil {
    89  			log.Entry().WithError(err).Error("Error persisting influx environment.")
    90  			errCount++
    91  		}
    92  	}
    93  	if errCount > 0 {
    94  		log.Entry().Error("failed to persist Influx environment")
    95  	}
    96  }
    97  
    98  type protecodeExecuteScanReports struct {
    99  }
   100  
   101  func (p *protecodeExecuteScanReports) persist(stepConfig protecodeExecuteScanOptions, gcpJsonKeyFilePath string, gcsBucketId string, gcsFolderPath string, gcsSubFolder string) {
   102  	if gcsBucketId == "" {
   103  		log.Entry().Info("persisting reports to GCS is disabled, because gcsBucketId is empty")
   104  		return
   105  	}
   106  	log.Entry().Info("Uploading reports to Google Cloud Storage...")
   107  	content := []gcs.ReportOutputParam{
   108  		{FilePattern: "**/toolrun_protecode_*.json", ParamRef: "", StepResultType: "protecode"},
   109  		{FilePattern: "", ParamRef: "reportFileName", StepResultType: "protecode"},
   110  		{FilePattern: "**/protecodeExecuteScan.json", ParamRef: "", StepResultType: "protecode"},
   111  		{FilePattern: "**/protecodescan_vulns.json", ParamRef: "", StepResultType: "protecode"},
   112  	}
   113  	envVars := []gcs.EnvVar{
   114  		{Name: "GOOGLE_APPLICATION_CREDENTIALS", Value: gcpJsonKeyFilePath, Modified: false},
   115  	}
   116  	gcsClient, err := gcs.NewClient(gcs.WithEnvVars(envVars))
   117  	if err != nil {
   118  		log.Entry().Errorf("creation of GCS client failed: %v", err)
   119  		return
   120  	}
   121  	defer gcsClient.Close()
   122  	structVal := reflect.ValueOf(&stepConfig).Elem()
   123  	inputParameters := map[string]string{}
   124  	for i := 0; i < structVal.NumField(); i++ {
   125  		field := structVal.Type().Field(i)
   126  		if field.Type.String() == "string" {
   127  			paramName := strings.Split(field.Tag.Get("json"), ",")
   128  			paramValue, _ := structVal.Field(i).Interface().(string)
   129  			inputParameters[paramName[0]] = paramValue
   130  		}
   131  	}
   132  	if err := gcs.PersistReportsToGCS(gcsClient, content, inputParameters, gcsFolderPath, gcsBucketId, gcsSubFolder, doublestar.Glob, os.Stat); err != nil {
   133  		log.Entry().Errorf("failed to persist reports: %v", err)
   134  	}
   135  }
   136  
   137  // ProtecodeExecuteScanCommand Black Duck Binary Analysis (BDBA), previously known as Protecode is an Open Source Vulnerability Scanner that is capable of scanning binaries. It can be used to scan docker images but is supports many other programming languages especially those of the C family.
   138  func ProtecodeExecuteScanCommand() *cobra.Command {
   139  	const STEP_NAME = "protecodeExecuteScan"
   140  
   141  	metadata := protecodeExecuteScanMetadata()
   142  	var stepConfig protecodeExecuteScanOptions
   143  	var startTime time.Time
   144  	var influx protecodeExecuteScanInflux
   145  	var reports protecodeExecuteScanReports
   146  	var logCollector *log.CollectorHook
   147  	var splunkClient *splunk.Splunk
   148  	telemetryClient := &telemetry.Telemetry{}
   149  
   150  	var createProtecodeExecuteScanCmd = &cobra.Command{
   151  		Use:   STEP_NAME,
   152  		Short: "Black Duck Binary Analysis (BDBA), previously known as Protecode is an Open Source Vulnerability Scanner that is capable of scanning binaries. It can be used to scan docker images but is supports many other programming languages especially those of the C family.",
   153  		Long: `Black Duck Binary Analysis (previously known as Protecode) is an Open Source Vulnerability Scan tool which provides the composition of Open Source components in a product along with Security information (no license info is provided).
   154  BDBA (Protecode) uses a combination of static binary analysis techniques to X-ray the provided software package to identify third-party software components and their exact versions with a high level of confidence. Methods range from simple string matching to proprietary patent-pending techniques.
   155  
   156  !!! hint "Auditing findings (Triaging)"
   157      Triaging is now supported by the BDBA (Protecode) backend and also Piper does consider this information during the analysis of the scan results though product versions are not supported by BDBA (Protecode). Therefore please make sure that the ` + "`" + `fileName` + "`" + ` you are providing does either contain a stable version or that it does not contain one at all. By ensuring that you are able to triage CVEs globally on the upload file's name without affecting any other artifacts scanned in the same BDBA (Protecode) group and as such triaged vulnerabilities will be considered during the next scan and will not fail the build anymore.`,
   158  		PreRunE: func(cmd *cobra.Command, _ []string) error {
   159  			startTime = time.Now()
   160  			log.SetStepName(STEP_NAME)
   161  			log.SetVerbose(GeneralConfig.Verbose)
   162  
   163  			GeneralConfig.GitHubAccessTokens = ResolveAccessTokens(GeneralConfig.GitHubTokens)
   164  
   165  			path, _ := os.Getwd()
   166  			fatalHook := &log.FatalHook{CorrelationID: GeneralConfig.CorrelationID, Path: path}
   167  			log.RegisterHook(fatalHook)
   168  
   169  			err := PrepareConfig(cmd, &metadata, STEP_NAME, &stepConfig, config.OpenPiperFile)
   170  			if err != nil {
   171  				log.SetErrorCategory(log.ErrorConfiguration)
   172  				return err
   173  			}
   174  			log.RegisterSecret(stepConfig.DockerConfigJSON)
   175  			log.RegisterSecret(stepConfig.Username)
   176  			log.RegisterSecret(stepConfig.Password)
   177  
   178  			if len(GeneralConfig.HookConfig.SentryConfig.Dsn) > 0 {
   179  				sentryHook := log.NewSentryHook(GeneralConfig.HookConfig.SentryConfig.Dsn, GeneralConfig.CorrelationID)
   180  				log.RegisterHook(&sentryHook)
   181  			}
   182  
   183  			if len(GeneralConfig.HookConfig.SplunkConfig.Dsn) > 0 {
   184  				splunkClient = &splunk.Splunk{}
   185  				logCollector = &log.CollectorHook{CorrelationID: GeneralConfig.CorrelationID}
   186  				log.RegisterHook(logCollector)
   187  			}
   188  
   189  			validation, err := validation.New(validation.WithJSONNamesForStructFields(), validation.WithPredefinedErrorMessages())
   190  			if err != nil {
   191  				return err
   192  			}
   193  			if err = validation.ValidateStruct(stepConfig); err != nil {
   194  				log.SetErrorCategory(log.ErrorConfiguration)
   195  				return err
   196  			}
   197  
   198  			return nil
   199  		},
   200  		Run: func(_ *cobra.Command, _ []string) {
   201  			stepTelemetryData := telemetry.CustomData{}
   202  			stepTelemetryData.ErrorCode = "1"
   203  			handler := func() {
   204  				influx.persist(GeneralConfig.EnvRootPath, "influx")
   205  				reports.persist(stepConfig, GeneralConfig.GCPJsonKeyFilePath, GeneralConfig.GCSBucketId, GeneralConfig.GCSFolderPath, GeneralConfig.GCSSubFolder)
   206  				config.RemoveVaultSecretFiles()
   207  				stepTelemetryData.Duration = fmt.Sprintf("%v", time.Since(startTime).Milliseconds())
   208  				stepTelemetryData.ErrorCategory = log.GetErrorCategory().String()
   209  				stepTelemetryData.PiperCommitHash = GitCommit
   210  				telemetryClient.SetData(&stepTelemetryData)
   211  				telemetryClient.Send()
   212  				if len(GeneralConfig.HookConfig.SplunkConfig.Dsn) > 0 {
   213  					splunkClient.Send(telemetryClient.GetData(), logCollector)
   214  				}
   215  			}
   216  			log.DeferExitHandler(handler)
   217  			defer handler()
   218  			telemetryClient.Initialize(GeneralConfig.NoTelemetry, STEP_NAME)
   219  			if len(GeneralConfig.HookConfig.SplunkConfig.Dsn) > 0 {
   220  				splunkClient.Initialize(GeneralConfig.CorrelationID,
   221  					GeneralConfig.HookConfig.SplunkConfig.Dsn,
   222  					GeneralConfig.HookConfig.SplunkConfig.Token,
   223  					GeneralConfig.HookConfig.SplunkConfig.Index,
   224  					GeneralConfig.HookConfig.SplunkConfig.SendLogs)
   225  			}
   226  			protecodeExecuteScan(stepConfig, &stepTelemetryData, &influx)
   227  			stepTelemetryData.ErrorCode = "0"
   228  			log.Entry().Info("SUCCESS")
   229  		},
   230  	}
   231  
   232  	addProtecodeExecuteScanFlags(createProtecodeExecuteScanCmd, &stepConfig)
   233  	return createProtecodeExecuteScanCmd
   234  }
   235  
   236  func addProtecodeExecuteScanFlags(cmd *cobra.Command, stepConfig *protecodeExecuteScanOptions) {
   237  	cmd.Flags().StringVar(&stepConfig.ExcludeCVEs, "excludeCVEs", ``, "DEPRECATED: Do use triaging within the Protecode UI instead")
   238  	cmd.Flags().BoolVar(&stepConfig.FailOnSevereVulnerabilities, "failOnSevereVulnerabilities", true, "Whether to fail the job on severe vulnerabilties or not")
   239  	cmd.Flags().StringVar(&stepConfig.ScanImage, "scanImage", os.Getenv("PIPER_scanImage"), "The reference to the docker image to scan with Protecode. Note: If possible please also check [fetchUrl](https://www.project-piper.io/steps/protecodeExecuteScan/#fetchurl) parameter, which might help you to optimize upload time.")
   240  	cmd.Flags().StringVar(&stepConfig.DockerRegistryURL, "dockerRegistryUrl", os.Getenv("PIPER_dockerRegistryUrl"), "The reference to the docker registry to scan with Protecode")
   241  	cmd.Flags().StringVar(&stepConfig.DockerConfigJSON, "dockerConfigJSON", os.Getenv("PIPER_dockerConfigJSON"), "Path to the file `.docker/config.json` - this is typically provided by your CI/CD system. You can find more details about the Docker credentials in the [Docker documentation](https://docs.docker.com/engine/reference/commandline/login/).")
   242  	cmd.Flags().StringVar(&stepConfig.CleanupMode, "cleanupMode", `binary`, "Decides which parts are removed from the Protecode backend after the scan")
   243  	cmd.Flags().StringVar(&stepConfig.FilePath, "filePath", os.Getenv("PIPER_filePath"), "The path to the file from local workspace to scan with Protecode")
   244  	cmd.Flags().StringVar(&stepConfig.TimeoutMinutes, "timeoutMinutes", `60`, "The timeout to wait for the scan to finish")
   245  	cmd.Flags().StringVar(&stepConfig.ServerURL, "serverUrl", os.Getenv("PIPER_serverUrl"), "The URL to the Protecode backend")
   246  	cmd.Flags().StringVar(&stepConfig.ReportFileName, "reportFileName", `protecode_report.pdf`, "The file name of the report to be created")
   247  	cmd.Flags().StringVar(&stepConfig.FetchURL, "fetchUrl", os.Getenv("PIPER_fetchUrl"), "The URL to fetch the file or image to scan with Protecode.")
   248  	cmd.Flags().StringVar(&stepConfig.Group, "group", os.Getenv("PIPER_group"), "The Protecode group ID of your team")
   249  	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")
   250  	cmd.Flags().IntVar(&stepConfig.ReplaceProductID, "replaceProductId", 0, "Specify <replaceProductId> which application binary will be replaced and rescanned and product id remains unchanged. By using this parameter, Protecode avoids creating multiple same products. Note this will affect results and feeds. If product id is not specified, then Piper starts auto detection mechanism, more precisely it searches a product id with scanned product name in that specified group, if there are several scans have been done with the same product name then the latest scan id will be fetched from BDBA backend. After obtaining product id, Piper re-uploads / replaces new binary without affecting already existing product id.")
   251  	cmd.Flags().StringVar(&stepConfig.Username, "username", os.Getenv("PIPER_username"), "User which is used for the protecode scan")
   252  	cmd.Flags().StringVar(&stepConfig.Password, "password", os.Getenv("PIPER_password"), "Password which is used for the user")
   253  	cmd.Flags().StringVar(&stepConfig.Version, "version", os.Getenv("PIPER_version"), "The version of the artifact to allow identification in protecode backend")
   254  	cmd.Flags().StringVar(&stepConfig.CustomScanVersion, "customScanVersion", os.Getenv("PIPER_customScanVersion"), "A custom version used along with the uploaded scan results.")
   255  	cmd.Flags().StringVar(&stepConfig.VersioningModel, "versioningModel", `major`, "The versioning model used for result reporting (based on the artifact version). Example 1.2.3 using `major` will result in version 1")
   256  	cmd.Flags().StringVar(&stepConfig.PullRequestName, "pullRequestName", os.Getenv("PIPER_pullRequestName"), "The name of the pull request")
   257  
   258  	cmd.MarkFlagRequired("serverUrl")
   259  	cmd.MarkFlagRequired("group")
   260  	cmd.MarkFlagRequired("username")
   261  	cmd.MarkFlagRequired("password")
   262  }
   263  
   264  // retrieve step metadata
   265  func protecodeExecuteScanMetadata() config.StepData {
   266  	var theMetaData = config.StepData{
   267  		Metadata: config.StepMetadata{
   268  			Name:        "protecodeExecuteScan",
   269  			Aliases:     []config.Alias{},
   270  			Description: "Black Duck Binary Analysis (BDBA), previously known as Protecode is an Open Source Vulnerability Scanner that is capable of scanning binaries. It can be used to scan docker images but is supports many other programming languages especially those of the C family.",
   271  		},
   272  		Spec: config.StepSpec{
   273  			Inputs: config.StepInputs{
   274  				Secrets: []config.StepSecrets{
   275  					{Name: "protecodeCredentialsId", Description: "Jenkins 'Username with password' credentials ID containing username and password to authenticate to the Protecode system.", Type: "jenkins"},
   276  					{Name: "dockerConfigJsonCredentialsId", Description: "Jenkins 'Secret file' credentials ID containing Docker config.json (with registry credential(s)). You can create it like explained in [Prerequisites](https://www.project-piper.io/steps/protecodeExecuteScan/#prerequisites).", Type: "jenkins", Aliases: []config.Alias{{Name: "dockerCredentialsId", Deprecated: true}}},
   277  				},
   278  				Parameters: []config.StepParameters{
   279  					{
   280  						Name:        "excludeCVEs",
   281  						ResourceRef: []config.ResourceReference{},
   282  						Scope:       []string{"PARAMETERS", "STAGES", "STEPS"},
   283  						Type:        "string",
   284  						Mandatory:   false,
   285  						Aliases:     []config.Alias{{Name: "protecodeExcludeCVEs"}},
   286  						Default:     ``,
   287  					},
   288  					{
   289  						Name:        "failOnSevereVulnerabilities",
   290  						ResourceRef: []config.ResourceReference{},
   291  						Scope:       []string{"PARAMETERS", "STAGES", "STEPS"},
   292  						Type:        "bool",
   293  						Mandatory:   false,
   294  						Aliases:     []config.Alias{{Name: "protecodeFailOnSevereVulnerabilities"}},
   295  						Default:     true,
   296  					},
   297  					{
   298  						Name: "scanImage",
   299  						ResourceRef: []config.ResourceReference{
   300  							{
   301  								Name:  "commonPipelineEnvironment",
   302  								Param: "container/imageNameTag",
   303  							},
   304  						},
   305  						Scope:     []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
   306  						Type:      "string",
   307  						Mandatory: false,
   308  						Aliases:   []config.Alias{{Name: "dockerImage"}},
   309  						Default:   os.Getenv("PIPER_scanImage"),
   310  					},
   311  					{
   312  						Name: "dockerRegistryUrl",
   313  						ResourceRef: []config.ResourceReference{
   314  							{
   315  								Name:  "commonPipelineEnvironment",
   316  								Param: "container/registryUrl",
   317  							},
   318  						},
   319  						Scope:     []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
   320  						Type:      "string",
   321  						Mandatory: false,
   322  						Aliases:   []config.Alias{},
   323  						Default:   os.Getenv("PIPER_dockerRegistryUrl"),
   324  					},
   325  					{
   326  						Name: "dockerConfigJSON",
   327  						ResourceRef: []config.ResourceReference{
   328  							{
   329  								Name:  "commonPipelineEnvironment",
   330  								Param: "custom/dockerConfigJSON",
   331  							},
   332  
   333  							{
   334  								Name: "dockerConfigJsonCredentialsId",
   335  								Type: "secret",
   336  							},
   337  
   338  							{
   339  								Name:    "dockerConfigFileVaultSecretName",
   340  								Type:    "vaultSecretFile",
   341  								Default: "docker-config",
   342  							},
   343  						},
   344  						Scope:     []string{"PARAMETERS", "STAGES", "STEPS"},
   345  						Type:      "string",
   346  						Mandatory: false,
   347  						Aliases:   []config.Alias{},
   348  						Default:   os.Getenv("PIPER_dockerConfigJSON"),
   349  					},
   350  					{
   351  						Name:        "cleanupMode",
   352  						ResourceRef: []config.ResourceReference{},
   353  						Scope:       []string{"PARAMETERS", "STAGES", "STEPS"},
   354  						Type:        "string",
   355  						Mandatory:   false,
   356  						Aliases:     []config.Alias{},
   357  						Default:     `binary`,
   358  					},
   359  					{
   360  						Name:        "filePath",
   361  						ResourceRef: []config.ResourceReference{},
   362  						Scope:       []string{"PARAMETERS", "STAGES", "STEPS"},
   363  						Type:        "string",
   364  						Mandatory:   false,
   365  						Aliases:     []config.Alias{},
   366  						Default:     os.Getenv("PIPER_filePath"),
   367  					},
   368  					{
   369  						Name:        "timeoutMinutes",
   370  						ResourceRef: []config.ResourceReference{},
   371  						Scope:       []string{"PARAMETERS", "STAGES", "STEPS"},
   372  						Type:        "string",
   373  						Mandatory:   false,
   374  						Aliases:     []config.Alias{{Name: "protecodeTimeoutMinutes"}},
   375  						Default:     `60`,
   376  					},
   377  					{
   378  						Name:        "serverUrl",
   379  						ResourceRef: []config.ResourceReference{},
   380  						Scope:       []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
   381  						Type:        "string",
   382  						Mandatory:   true,
   383  						Aliases:     []config.Alias{{Name: "protecodeServerUrl"}},
   384  						Default:     os.Getenv("PIPER_serverUrl"),
   385  					},
   386  					{
   387  						Name:        "reportFileName",
   388  						ResourceRef: []config.ResourceReference{},
   389  						Scope:       []string{"PARAMETERS", "STAGES", "STEPS"},
   390  						Type:        "string",
   391  						Mandatory:   false,
   392  						Aliases:     []config.Alias{},
   393  						Default:     `protecode_report.pdf`,
   394  					},
   395  					{
   396  						Name:        "fetchUrl",
   397  						ResourceRef: []config.ResourceReference{},
   398  						Scope:       []string{"PARAMETERS", "STAGES", "STEPS"},
   399  						Type:        "string",
   400  						Mandatory:   false,
   401  						Aliases:     []config.Alias{},
   402  						Default:     os.Getenv("PIPER_fetchUrl"),
   403  					},
   404  					{
   405  						Name:        "group",
   406  						ResourceRef: []config.ResourceReference{},
   407  						Scope:       []string{"PARAMETERS", "STAGES", "STEPS"},
   408  						Type:        "string",
   409  						Mandatory:   true,
   410  						Aliases:     []config.Alias{{Name: "protecodeGroup"}},
   411  						Default:     os.Getenv("PIPER_group"),
   412  					},
   413  					{
   414  						Name:        "verifyOnly",
   415  						ResourceRef: []config.ResourceReference{},
   416  						Scope:       []string{"PARAMETERS", "STAGES", "STEPS"},
   417  						Type:        "bool",
   418  						Mandatory:   false,
   419  						Aliases:     []config.Alias{{Name: "reuseExisting", Deprecated: true}},
   420  						Default:     false,
   421  					},
   422  					{
   423  						Name:        "replaceProductId",
   424  						ResourceRef: []config.ResourceReference{},
   425  						Scope:       []string{"PARAMETERS", "STAGES", "STEPS"},
   426  						Type:        "int",
   427  						Mandatory:   false,
   428  						Aliases:     []config.Alias{},
   429  						Default:     0,
   430  					},
   431  					{
   432  						Name: "username",
   433  						ResourceRef: []config.ResourceReference{
   434  							{
   435  								Name:  "protecodeCredentialsId",
   436  								Param: "username",
   437  								Type:  "secret",
   438  							},
   439  
   440  							{
   441  								Name:    "protecodeVaultSecretName",
   442  								Type:    "vaultSecret",
   443  								Default: "protecode",
   444  							},
   445  						},
   446  						Scope:     []string{"PARAMETERS", "STAGES", "STEPS"},
   447  						Type:      "string",
   448  						Mandatory: true,
   449  						Aliases:   []config.Alias{{Name: "user", Deprecated: true}},
   450  						Default:   os.Getenv("PIPER_username"),
   451  					},
   452  					{
   453  						Name: "password",
   454  						ResourceRef: []config.ResourceReference{
   455  							{
   456  								Name:  "protecodeCredentialsId",
   457  								Param: "password",
   458  								Type:  "secret",
   459  							},
   460  
   461  							{
   462  								Name:    "protecodeVaultSecretName",
   463  								Type:    "vaultSecret",
   464  								Default: "protecode",
   465  							},
   466  						},
   467  						Scope:     []string{"PARAMETERS", "STAGES", "STEPS"},
   468  						Type:      "string",
   469  						Mandatory: true,
   470  						Aliases:   []config.Alias{},
   471  						Default:   os.Getenv("PIPER_password"),
   472  					},
   473  					{
   474  						Name: "version",
   475  						ResourceRef: []config.ResourceReference{
   476  							{
   477  								Name:  "commonPipelineEnvironment",
   478  								Param: "artifactVersion",
   479  							},
   480  						},
   481  						Scope:     []string{"PARAMETERS", "STAGES", "STEPS"},
   482  						Type:      "string",
   483  						Mandatory: false,
   484  						Aliases:   []config.Alias{{Name: "artifactVersion", Deprecated: true}},
   485  						Default:   os.Getenv("PIPER_version"),
   486  					},
   487  					{
   488  						Name:        "customScanVersion",
   489  						ResourceRef: []config.ResourceReference{},
   490  						Scope:       []string{"GENERAL", "STAGES", "STEPS", "PARAMETERS"},
   491  						Type:        "string",
   492  						Mandatory:   false,
   493  						Aliases:     []config.Alias{},
   494  						Default:     os.Getenv("PIPER_customScanVersion"),
   495  					},
   496  					{
   497  						Name:        "versioningModel",
   498  						ResourceRef: []config.ResourceReference{},
   499  						Scope:       []string{"PARAMETERS", "GENERAL", "STAGES", "STEPS"},
   500  						Type:        "string",
   501  						Mandatory:   false,
   502  						Aliases:     []config.Alias{},
   503  						Default:     `major`,
   504  					},
   505  					{
   506  						Name:        "pullRequestName",
   507  						ResourceRef: []config.ResourceReference{},
   508  						Scope:       []string{"PARAMETERS", "STAGES", "STEPS"},
   509  						Type:        "string",
   510  						Mandatory:   false,
   511  						Aliases:     []config.Alias{},
   512  						Default:     os.Getenv("PIPER_pullRequestName"),
   513  					},
   514  				},
   515  			},
   516  			Outputs: config.StepOutputs{
   517  				Resources: []config.StepResources{
   518  					{
   519  						Name: "influx",
   520  						Type: "influx",
   521  						Parameters: []map[string]interface{}{
   522  							{"name": "step_data", "fields": []map[string]string{{"name": "protecode"}}},
   523  							{"name": "protecode_data", "fields": []map[string]string{{"name": "excluded_vulnerabilities"}, {"name": "historical_vulnerabilities"}, {"name": "major_vulnerabilities"}, {"name": "minor_vulnerabilities"}, {"name": "triaged_vulnerabilities"}, {"name": "vulnerabilities"}}},
   524  						},
   525  					},
   526  					{
   527  						Name: "reports",
   528  						Type: "reports",
   529  						Parameters: []map[string]interface{}{
   530  							{"filePattern": "**/toolrun_protecode_*.json", "type": "protecode"},
   531  							{"type": "protecode"},
   532  							{"filePattern": "**/protecodeExecuteScan.json", "type": "protecode"},
   533  							{"filePattern": "**/protecodescan_vulns.json", "type": "protecode"},
   534  						},
   535  					},
   536  				},
   537  			},
   538  		},
   539  	}
   540  	return theMetaData
   541  }