1
0
mirror of https://github.com/SAP/jenkins-library.git synced 2025-01-16 05:16:08 +02:00

Whitesource scan (MVP) (#1658)

* Whitesource MVP for Gradle, Golang, and NPM/Yarn

* Refactoring

* Refactor and cleanup, better error checking

* publish stepResults, use pkg/versioning, bubble up errors, add gomod versioning support

* Run gofmt and cleanup comments

* Resolve PR comments

* Update resources/metadata/whitesource.yaml

Co-authored-by: Christopher Fenner <26137398+CCFenner@users.noreply.github.com>

* Only determine project coordinates if they are missing

Co-authored-by: Stephan Aßmus <stephan.assmus@sap.com>

* Gradle versioning artifact

* fix gradle artifact version regexp and refactor

* Fix token extraction from output buffer

* Fix some issues with pip and jsonfile versioning logic

* Remove useless spacing

* Remove unnecessary test file and fix naming style for JSONDescriptor

* Automatically download wss-unified-agent if file does not exist

* adds downloadVulnerabilityReport, checkSecurityViolations, minor refactoring

* adds config.ReportDirectoryName, improves readability

* Version-wide reporting for vulnerabilities and list of libraries.

* Refactor and improve build accuracy

* fix sed command

* Add includes file pattern config option

* Adds --exclude command line flag

* run go mod tidy and regenerate step framework

* Fix unit tests

* revert changes

* poll project status before downloading reports

* merge with master

* go mod tidy, go fmt, and fix whitesource unit test

* sync go.mod

* sync go.mod again

Co-authored-by: Christopher Fenner <26137398+CCFenner@users.noreply.github.com>
Co-authored-by: Stephan Aßmus <stephan.assmus@sap.com>
Co-authored-by: Oliver Nocon <33484802+OliverNocon@users.noreply.github.com>
This commit is contained in:
Jordan Levin 2020-06-30 22:54:13 -07:00 committed by GitHub
parent de3afe9476
commit 34967c502c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 2118 additions and 53 deletions

View File

@ -88,6 +88,7 @@ func Execute() {
rootCmd.AddCommand(GctsCreateRepositoryCommand())
rootCmd.AddCommand(GctsDeployCommand())
rootCmd.AddCommand(MalwareExecuteScanCommand())
rootCmd.AddCommand(WhitesourceExecuteScanCommand())
rootCmd.AddCommand(GctsCloneRepositoryCommand())
rootCmd.AddCommand(JsonApplyPatchCommand())

View File

@ -0,0 +1,520 @@
package cmd
import (
"fmt"
"io/ioutil"
"os"
"path/filepath"
"strconv"
"strings"
"time"
"github.com/360EntSecGroup-Skylar/excelize/v2"
"github.com/SAP/jenkins-library/pkg/command"
"github.com/SAP/jenkins-library/pkg/log"
"github.com/SAP/jenkins-library/pkg/piperutils"
"github.com/SAP/jenkins-library/pkg/telemetry"
"github.com/SAP/jenkins-library/pkg/versioning"
"github.com/SAP/jenkins-library/pkg/whitesource"
)
// just to make the lines less long
type ScanOptions = whitesourceExecuteScanOptions
type System = whitesource.System
func whitesourceExecuteScan(config ScanOptions, telemetry *telemetry.CustomData) {
// reroute cmd output to logging framework
c := command.Command{}
c.Stdout(log.Writer())
c.Stderr(log.Writer())
sys := whitesource.NewSystem(config.ServiceURL, config.OrgToken, config.UserToken)
if err := resolveProjectIdentifiers(&c, sys, &config); err != nil {
log.Entry().WithError(err).Fatal("step execution failed on resolving project identifiers")
}
// Generate a vulnerability report for all projects with version = config.ProjectVersion
if config.AggregateVersionWideReport {
if err := aggregateVersionWideLibraries(sys, &config); err != nil {
log.Entry().WithError(err).Fatal("step execution failed on aggregating version wide libraries")
}
if err := aggregateVersionWideVulnerabilities(sys, &config); err != nil {
log.Entry().WithError(err).Fatal("step execution failed on aggregating version wide vulnerabilities")
}
} else {
if err := runWhitesourceScan(&config, sys, telemetry, &c); err != nil {
log.Entry().WithError(err).Fatal("step execution failed on executing whitesource scan")
}
}
}
func runWhitesourceScan(config *ScanOptions, sys *System, _ *telemetry.CustomData, cmd *command.Command) error {
// Start the scan
if err := triggerWhitesourceScan(cmd, config); err != nil {
return err
}
// Scan finished: we need to resolve project token again if the project was just created.
if err := resolveProjectIdentifiers(cmd, sys, config); err != nil {
return err
}
log.Entry().Info("-----------------------------------------------------")
log.Entry().Infof("Project name: '%s'", config.ProjectName)
log.Entry().Infof("Product Version: '%s'", config.ProductVersion)
log.Entry().Infof("Project Token: %s", config.ProjectToken)
log.Entry().Info("-----------------------------------------------------")
if config.Reporting {
paths, err := downloadReports(config, sys)
if err != nil {
return err
}
piperutils.PersistReportsAndLinks("whitesourceExecuteScan", "", nil, paths)
}
// Check for security vulnerabilities and fail the build if cvssSeverityLimit threshold is crossed
if config.SecurityVulnerabilities {
if err := checkSecurityViolations(config, sys); err != nil {
return err
}
}
return nil
}
func resolveProjectIdentifiers(cmd *command.Command, sys *System, config *ScanOptions) error {
if config.ProjectName == "" || config.ProductVersion == "" {
opts := &versioning.Options{}
artifact, err := versioning.GetArtifact(config.ScanType, config.BuildDescriptorFile, opts, cmd)
if err != nil {
return err
}
gav, err := artifact.GetCoordinates()
if err != nil {
return err
}
nameTmpl := `{{list .GroupID .ArtifactID | join "-" | trimAll "-"}}`
pName, pVer := versioning.DetermineProjectCoordinates(nameTmpl, config.DefaultVersioningModel, gav)
if config.ProjectName == "" {
log.Entry().Infof("Resolved project name '%s' from descriptor file", pName)
config.ProjectName = pName
}
if config.ProductVersion == "" {
log.Entry().Infof("Resolved project version '%s' from descriptor file", pVer)
config.ProductVersion = pVer
}
}
// Get product token if user did not specify one at runtime
if config.ProductToken == "" {
log.Entry().Infof("Attempting to resolve product token for product '%s'..", config.ProductName)
product, err := sys.GetProductByName(config.ProductName)
if err != nil {
return err
}
if product != nil {
log.Entry().Infof("Resolved product token: '%s'..", product.Token)
config.ProductToken = product.Token
}
}
// Get project token if user did not specify one at runtime
if config.ProjectToken == "" {
log.Entry().Infof("Attempting to resolve project token for project '%s'..", config.ProjectName)
fullProjName := fmt.Sprintf("%s - %s", config.ProjectName, config.ProductVersion)
projectToken, err := sys.GetProjectToken(config.ProductToken, fullProjName)
if err != nil {
return err
}
if projectToken != "" {
log.Entry().Infof("Resolved project token: '%s'..", projectToken)
config.ProjectToken = projectToken
}
}
return nil
}
func triggerWhitesourceScan(cmd *command.Command, config *ScanOptions) error {
switch config.ScanType {
case "npm":
// Execute whitesource scan with
if err := executeNpmScan(config, cmd); err != nil {
return err
}
default:
// Download the unified agent jar file if one does not exist
if err := downloadAgent(config, cmd); err != nil {
return err
}
// Auto generate a config file based on the working directory's contents.
// TODO/NOTE: Currently this scans the UA jar file as a dependency since it is downloaded beforehand
if err := autoGenerateWhitesourceConfig(config, cmd); err != nil {
return err
}
// Execute whitesource scan with unified agent jar file
if err := executeUAScan(config, cmd); err != nil {
return err
}
}
return nil
}
// executeUAScan
// Executes a scan with the Whitesource Unified Agent
// returns stdout buffer of the unified agent for token extraction in case of multi-module gradle project
func executeUAScan(config *ScanOptions, cmd *command.Command) error {
return cmd.RunExecutable("java", "-jar", config.AgentFileName, "-d", ".", "-c", config.ConfigFilePath,
"-apiKey", config.OrgToken, "-userKey", config.UserToken, "-project", config.ProjectName,
"-product", config.ProductName, "-productVersion", config.ProductVersion)
}
// executeNpmScan
// generates a configuration file whitesource.config.json with appropriate values from config,
// installs whitesource yarn plugin and executes the scan
func executeNpmScan(config *ScanOptions, cmd *command.Command) error {
npmConfig := []byte(fmt.Sprintf(`{
"apiKey": "%s",
"userKey": "%s",
"checkPolicies": true,
"productName": "%s",
"projectName": "%s",
"productVer": "%s",
"devDep": true
}`, config.OrgToken, config.UserToken, config.ProductName, config.ProjectName, config.ProductVersion))
if err := ioutil.WriteFile("whitesource.config.json", npmConfig, 0644); err != nil {
return err
}
if err := cmd.RunExecutable("yarn", "global", "add", "whitesource"); err != nil {
return err
}
if err := cmd.RunExecutable("yarn", "install"); err != nil {
return err
}
if err := cmd.RunExecutable("whitesource", "yarn"); err != nil {
return err
}
return nil
}
// checkSecurityViolations: checks security violations and fails build is severity limit is crossed
func checkSecurityViolations(config *ScanOptions, sys *System) error {
severeVulnerabilities := 0
// convert config.CvssSeverityLimit to float64
cvssSeverityLimit, err := strconv.ParseFloat(config.CvssSeverityLimit, 64)
if err != nil {
return err
}
// get project alerts (vulnerabilities)
alerts, err := sys.GetProjectAlerts(config.ProjectToken)
if err != nil {
return err
}
// https://github.com/SAP/jenkins-library/blob/master/vars/whitesourceExecuteScan.groovy#L537
for _, alert := range alerts {
vuln := alert.Vulnerability
if (vuln.Score >= cvssSeverityLimit || vuln.CVSS3Score >= cvssSeverityLimit) && cvssSeverityLimit >= 0 {
severeVulnerabilities++
}
}
//https://github.com/SAP/jenkins-library/blob/master/vars/whitesourceExecuteScan.groovy#L547
nonSevereVulnerabilities := len(alerts) - severeVulnerabilities
if nonSevereVulnerabilities > 0 {
log.Entry().Warnf("WARNING: %v Open Source Software Security vulnerabilities with "+
"CVSS score below threshold %s detected in project %s.", nonSevereVulnerabilities,
config.CvssSeverityLimit, config.ProjectName)
} else if len(alerts) == 0 {
log.Entry().Infof("No Open Source Software Security vulnerabilities detected in project %s",
config.ProjectName)
}
// https://github.com/SAP/jenkins-library/blob/master/vars/whitesourceExecuteScan.groovy#L558
if severeVulnerabilities > 0 {
return fmt.Errorf("%v Open Source Software Security vulnerabilities with CVSS score greater "+
"or equal to %s detected in project %s",
severeVulnerabilities, config.CvssSeverityLimit, config.ProjectName)
}
return nil
}
// pollProjectStatus polls project LastUpdateTime until it reflects the most recent scan
func pollProjectStatus(config *ScanOptions, sys *System) error {
currentTime := time.Now()
for {
project, err := sys.GetProjectVitals(config.ProjectToken)
if err != nil {
return err
}
// Make sure the project was updated in whitesource backend before downloading any reports
lastUpdatedTime, err := time.Parse("2006-01-02 15:04:05 +0000", project.LastUpdateDate)
if currentTime.Sub(lastUpdatedTime) < 10*time.Second {
//done polling
break
}
log.Entry().Info("time since project was last updated > 10 seconds, polling status...")
time.Sleep(5 * time.Second)
}
return nil
}
// downloadReports downloads a project's risk and vulnerability reports
func downloadReports(config *ScanOptions, sys *System) ([]piperutils.Path, error) {
utils := piperutils.Files{}
// Project was scanned, now we need to wait for Whitesource backend to propagate the changes
if err := pollProjectStatus(config, sys); err != nil {
return nil, err
}
if err := utils.MkdirAll(config.ReportDirectoryName, 0777); err != nil {
return nil, err
}
vulnPath, err := downloadVulnerabilityReport(config, sys)
if err != nil {
return nil, err
}
riskPath, err := downloadRiskReport(config, sys)
if err != nil {
return nil, err
}
return []piperutils.Path{*vulnPath, *riskPath}, nil
}
func downloadVulnerabilityReport(config *ScanOptions, sys *System) (*piperutils.Path, error) {
utils := piperutils.Files{}
if err := utils.MkdirAll(config.ReportDirectoryName, 0777); err != nil {
return nil, err
}
reportBytes, err := sys.GetProjectVulnerabilityReport(config.ProjectToken, config.VulnerabilityReportFormat)
if err != nil {
return nil, err
}
// Write report to file
rptFileName := fmt.Sprintf("%s-vulnerability-report.%s", config.ProjectName, config.VulnerabilityReportFormat)
rptFileName = filepath.Join(config.ReportDirectoryName, rptFileName)
if err := ioutil.WriteFile(rptFileName, reportBytes, 0644); err != nil {
return nil, err
}
log.Entry().Infof("Successfully downloaded vulnerability report to %s", rptFileName)
pathName := fmt.Sprintf("%s Vulnerability Report", config.ProjectName)
return &piperutils.Path{Name: pathName, Target: rptFileName}, nil
}
func downloadRiskReport(config *ScanOptions, sys *System) (*piperutils.Path, error) {
reportBytes, err := sys.GetProjectRiskReport(config.ProjectToken)
if err != nil {
return nil, err
}
rptFileName := fmt.Sprintf("%s-risk-report.pdf", config.ProjectName)
rptFileName = filepath.Join(config.ReportDirectoryName, rptFileName)
if err := ioutil.WriteFile(rptFileName, reportBytes, 0644); err != nil {
return nil, err
}
log.Entry().Infof("Successfully downloaded risk report to %s", rptFileName)
pathName := fmt.Sprintf("%s PDF Risk Report", config.ProjectName)
return &piperutils.Path{Name: pathName, Target: rptFileName}, nil
}
// downloadAgent: Downloads the unified agent jar file if one does not exist
func downloadAgent(config *ScanOptions, cmd *command.Command) error {
agentFile := config.AgentFileName
if !fileExists(agentFile) {
if err := cmd.RunExecutable("curl", "-L", config.AgentDownloadURL, "-o", agentFile); err != nil {
return err
}
}
return nil
}
// autoGenerateWhitesourceConfig
// Auto generate a config file based on the current directory structure, renames it to user specified configFilePath
// Generated file name will be 'wss-generated-file.config'
func autoGenerateWhitesourceConfig(config *ScanOptions, cmd *command.Command) error {
// TODO: Should we rely on -detect, or set the parameters manually?
if err := cmd.RunExecutable("java", "-jar", config.AgentFileName, "-d", ".", "-detect"); err != nil {
return err
}
// Rename generated config file to config.ConfigFilePath parameter
if err := os.Rename("wss-generated-file.config", config.ConfigFilePath); err != nil {
return err
}
// Append aggregateModules=true parameter to config file (consolidates multi-module projects into one)
f, err := os.OpenFile(config.ConfigFilePath, os.O_APPEND|os.O_WRONLY, 0600)
if err != nil {
return err
}
defer f.Close()
// Append additional config parameters to prevent multiple projects being generated
cfg := fmt.Sprintf("gradle.aggregateModules=true\nmaven.aggregateModules=true\ngradle.localRepositoryPath=.gradle\nmaven.m2RepositoryPath=.m2\nexcludes=%s", config.Excludes)
if _, err = f.WriteString(cfg); err != nil {
return err
}
// archiveExtractionDepth=0
if err := cmd.RunExecutable("sed", "-ir", `s/^[#]*\s*archiveExtractionDepth=.*/archiveExtractionDepth=0/`,
config.ConfigFilePath); err != nil {
return err
}
// config.Includes defaults to "**/*.java **/*.jar **/*.py **/*.go **/*.js **/*.ts"
regex := fmt.Sprintf(`s/^[#]*\s*includes=.*/includes="%s"/`, config.Includes)
if err := cmd.RunExecutable("sed", "-ir", regex, config.ConfigFilePath); err != nil {
return err
}
return nil
}
func aggregateVersionWideLibraries(sys *System, config *ScanOptions) error {
log.Entry().Infof("Aggregating list of libraries used for all projects with version: %s", config.ProductVersion)
projects, err := sys.GetProjectsMetaInfo(config.ProductToken)
if err != nil {
return err
}
versionWideLibraries := map[string][]whitesource.Library{} // maps project name to slice of libraries
for _, project := range projects {
projectVersion := strings.Split(project.Name, " - ")[1]
projectName := strings.Split(project.Name, " - ")[0]
if projectVersion == config.ProductVersion {
libs, err := sys.GetProjectLibraryLocations(project.Token)
if err != nil {
return err
}
log.Entry().Infof("Found project: %s with %v libraries.", project.Name, len(libs))
versionWideLibraries[projectName] = libs
}
}
if err := newLibraryCSVReport(versionWideLibraries, config); err != nil {
return err
}
return nil
}
func aggregateVersionWideVulnerabilities(sys *System, config *ScanOptions) error {
log.Entry().Infof("Aggregating list of vulnerabilities for all projects with version: %s", config.ProductVersion)
projects, err := sys.GetProjectsMetaInfo(config.ProductToken)
if err != nil {
return err
}
var versionWideAlerts []whitesource.Alert // all alerts for a given project version
projectNames := `` // holds all project tokens considered a part of the report for debugging
for _, project := range projects {
projectVersion := strings.Split(project.Name, " - ")[1]
if projectVersion == config.ProductVersion {
projectNames += project.Name + "\n"
alerts, err := sys.GetProjectAlerts(project.Token)
if err != nil {
return err
}
log.Entry().Infof("Found project: %s with %v vulnerabilities.", project.Name, len(alerts))
versionWideAlerts = append(versionWideAlerts, alerts...)
}
}
if err := ioutil.WriteFile("whitesource-reports/project-names-aggregated.txt", []byte(projectNames), 0777); err != nil {
return err
}
if err := newVulnerabilityExcelReport(versionWideAlerts, config); err != nil {
return err
}
return nil
}
// outputs an slice of alerts to an excel file
func newVulnerabilityExcelReport(alerts []whitesource.Alert, config *ScanOptions) error {
file := excelize.NewFile()
streamWriter, err := file.NewStreamWriter("Sheet1")
if err != nil {
return err
}
styleID, err := file.NewStyle(`{"font":{"color":"#777777"}}`)
if err != nil {
return err
}
if err := streamWriter.SetRow("A1", []interface{}{excelize.Cell{StyleID: styleID, Value: "Severity"}}); err != nil {
return err
}
if err := streamWriter.SetRow("B1", []interface{}{excelize.Cell{StyleID: styleID, Value: "Library"}}); err != nil {
return err
}
if err := streamWriter.SetRow("C1", []interface{}{excelize.Cell{StyleID: styleID, Value: "Vulnerability ID"}}); err != nil {
return err
}
if err := streamWriter.SetRow("D1", []interface{}{excelize.Cell{StyleID: styleID, Value: "Project"}}); err != nil {
return err
}
if err := streamWriter.SetRow("E1", []interface{}{excelize.Cell{StyleID: styleID, Value: "Resolution"}}); err != nil {
return err
}
for i, alert := range alerts {
row := make([]interface{}, 5)
vuln := alert.Vulnerability
row[0] = vuln.Severity
row[1] = alert.Library.Filename
row[2] = vuln.Level
row[3] = alert.Project
row[4] = vuln.FixResolutionText
cell, _ := excelize.CoordinatesToCellName(1, i+2)
if err := streamWriter.SetRow(cell, row); err != nil {
fmt.Println(err)
}
}
if err := streamWriter.Flush(); err != nil {
return err
}
utils := piperutils.Files{}
if err := utils.MkdirAll(config.ReportDirectoryName, 0777); err != nil {
return err
}
fileName := fmt.Sprintf("%s/vulnerabilities-%s.xlsx", config.ReportDirectoryName, time.Now().Format("2006-01-01 15:00:00"))
if err := file.SaveAs(fileName); err != nil {
return err
}
return nil
}
// outputs an slice of libraries to an excel file based on projects with version == config.ProductVersion
func newLibraryCSVReport(libraries map[string][]whitesource.Library, config *ScanOptions) error {
output := "Library Name, Project Name\n"
for projectName, libraries := range libraries {
log.Entry().Infof("Writing %v libraries for project %s to excel report..", len(libraries), projectName)
for _, library := range libraries {
output += library.Name + ", " + projectName + "\n"
}
}
// Ensure reporting directory exists
utils := piperutils.Files{}
if err := utils.MkdirAll(config.ReportDirectoryName, 0777); err != nil {
return err
}
// Write result to file
fileName := fmt.Sprintf("%s/libraries-%s.csv", config.ReportDirectoryName, time.Now().Format("2006-01-01 15:00:00"))
if err := ioutil.WriteFile(fileName, []byte(output), 0777); err != nil {
return err
}
return nil
}

View File

@ -0,0 +1,477 @@
// Code generated by piper's step-generator. DO NOT EDIT.
package cmd
import (
"fmt"
"os"
"time"
"github.com/SAP/jenkins-library/pkg/config"
"github.com/SAP/jenkins-library/pkg/log"
"github.com/SAP/jenkins-library/pkg/telemetry"
"github.com/spf13/cobra"
)
type whitesourceExecuteScanOptions struct {
BuildDescriptorFile string `json:"buildDescriptorFile,omitempty"`
DefaultVersioningModel string `json:"defaultVersioningModel,omitempty"`
CreateProductFromPipeline bool `json:"createProductFromPipeline,omitempty"`
SecurityVulnerabilities bool `json:"securityVulnerabilities,omitempty"`
Timeout string `json:"timeout,omitempty"`
AgentDownloadURL string `json:"agentDownloadUrl,omitempty"`
ConfigFilePath string `json:"configFilePath,omitempty"`
ReportDirectoryName string `json:"reportDirectoryName,omitempty"`
AggregateVersionWideReport bool `json:"aggregateVersionWideReport,omitempty"`
VulnerabilityReportFormat string `json:"vulnerabilityReportFormat,omitempty"`
ParallelLimit string `json:"parallelLimit,omitempty"`
Reporting bool `json:"reporting,omitempty"`
ServiceURL string `json:"serviceUrl,omitempty"`
BuildDescriptorExcludeList string `json:"buildDescriptorExcludeList,omitempty"`
OrgToken string `json:"orgToken,omitempty"`
UserToken string `json:"userToken,omitempty"`
LicensingVulnerabilities bool `json:"licensingVulnerabilities,omitempty"`
AgentFileName string `json:"agentFileName,omitempty"`
EmailAddressesOfInitialProductAdmins string `json:"emailAddressesOfInitialProductAdmins,omitempty"`
ProductVersion string `json:"productVersion,omitempty"`
JreDownloadURL string `json:"jreDownloadUrl,omitempty"`
ProductName string `json:"productName,omitempty"`
ProjectName string `json:"projectName,omitempty"`
ProjectToken string `json:"projectToken,omitempty"`
VulnerabilityReportTitle string `json:"vulnerabilityReportTitle,omitempty"`
InstallCommand string `json:"installCommand,omitempty"`
ScanType string `json:"scanType,omitempty"`
CvssSeverityLimit string `json:"cvssSeverityLimit,omitempty"`
Includes string `json:"includes,omitempty"`
Excludes string `json:"excludes,omitempty"`
ProductToken string `json:"productToken,omitempty"`
AgentParameters string `json:"agentParameters,omitempty"`
}
// WhitesourceExecuteScanCommand BETA
func WhitesourceExecuteScanCommand() *cobra.Command {
const STEP_NAME = "whitesourceExecuteScan"
metadata := whitesourceExecuteScanMetadata()
var stepConfig whitesourceExecuteScanOptions
var startTime time.Time
var createWhitesourceExecuteScanCmd = &cobra.Command{
Use: STEP_NAME,
Short: "BETA",
Long: `BETA
With this step [WhiteSource](https://www.whitesourcesoftware.com) security and license compliance scans can be executed and assessed.
WhiteSource is a Software as a Service offering based on a so called unified agent that locally determines the dependency
tree of a node.js, Java, Python, Ruby, or Scala based solution and sends it to the WhiteSource server for a policy based license compliance
check and additional Free and Open Source Software Publicly Known Vulnerabilities detection.
!!! note "Docker Images"
The underlying Docker images are public and specific to the solution's programming language(s) and therefore may have to be exchanged
to fit to and support the relevant scenario. The default Python environment used is i.e. Python 3 based.
!!! warn "Restrictions"
Currently the step does contain hardened scan configurations for ` + "`" + `scanType` + "`" + ` ` + "`" + `'pip'` + "`" + ` and ` + "`" + `'go'` + "`" + `. Other environments are still being elaborated,
so please thoroughly check your results and do not take them for granted by default.
Also not all environments have been thoroughly tested already therefore you might need to tweak around with the default containers used or
create your own ones to adequately support your scenario. To do so please modify ` + "`" + `dockerImage` + "`" + ` and ` + "`" + `dockerWorkspace` + "`" + ` parameters.
The step expects an environment containing the programming language related compiler/interpreter as well as the related build tool. For a list
of the supported build tools per environment please refer to the [WhiteSource Unified Agent Documentation](https://whitesource.atlassian.net/wiki/spaces/WD/pages/33718339/Unified+Agent).`,
PreRunE: func(cmd *cobra.Command, _ []string) error {
startTime = time.Now()
log.SetStepName(STEP_NAME)
log.SetVerbose(GeneralConfig.Verbose)
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
}
if len(GeneralConfig.HookConfig.SentryConfig.Dsn) > 0 {
sentryHook := log.NewSentryHook(GeneralConfig.HookConfig.SentryConfig.Dsn, GeneralConfig.CorrelationID)
log.RegisterHook(&sentryHook)
}
return nil
},
Run: func(_ *cobra.Command, _ []string) {
telemetryData := telemetry.CustomData{}
telemetryData.ErrorCode = "1"
handler := func() {
telemetryData.Duration = fmt.Sprintf("%v", time.Since(startTime).Milliseconds())
telemetry.Send(&telemetryData)
}
log.DeferExitHandler(handler)
defer handler()
telemetry.Initialize(GeneralConfig.NoTelemetry, STEP_NAME)
whitesourceExecuteScan(stepConfig, &telemetryData)
telemetryData.ErrorCode = "0"
log.Entry().Info("SUCCESS")
},
}
addWhitesourceExecuteScanFlags(createWhitesourceExecuteScanCmd, &stepConfig)
return createWhitesourceExecuteScanCmd
}
func addWhitesourceExecuteScanFlags(cmd *cobra.Command, stepConfig *whitesourceExecuteScanOptions) {
cmd.Flags().StringVar(&stepConfig.BuildDescriptorFile, "buildDescriptorFile", os.Getenv("PIPER_buildDescriptorFile"), "Explicit path to the build descriptor file.")
cmd.Flags().StringVar(&stepConfig.DefaultVersioningModel, "defaultVersioningModel", `major`, "The default project versioning model used in case `projectVersion` parameter is empty for creating the version based on the build descriptor version to report results in Whitesource, can be one of `'major'`, `'major-minor'`, `'semantic'`, `'full'`")
cmd.Flags().BoolVar(&stepConfig.CreateProductFromPipeline, "createProductFromPipeline", true, "Whether to create the related WhiteSource product on the fly based on the supplied pipeline configuration.")
cmd.Flags().BoolVar(&stepConfig.SecurityVulnerabilities, "securityVulnerabilities", true, "Whether security compliance is considered and reported as part of the assessment.")
cmd.Flags().StringVar(&stepConfig.Timeout, "timeout", `0`, "Timeout in seconds until a HTTP call is forcefully terminated.")
cmd.Flags().StringVar(&stepConfig.AgentDownloadURL, "agentDownloadUrl", `https://github.com/whitesource/unified-agent-distribution/releases/latest/download/wss-unified-agent.jar`, "URL used to download the latest version of the WhiteSource Unified Agent.")
cmd.Flags().StringVar(&stepConfig.ConfigFilePath, "configFilePath", `./wss-generated-file.config`, "Explicit path to the WhiteSource Unified Agent configuration file.")
cmd.Flags().StringVar(&stepConfig.ReportDirectoryName, "reportDirectoryName", `whitesource-reports`, "Name of the directory to save vulnerability/risk reports to")
cmd.Flags().BoolVar(&stepConfig.AggregateVersionWideReport, "aggregateVersionWideReport", false, "This does not run a scan, instead just generated a report for all projects with projectVersion = config.ProductVersion")
cmd.Flags().StringVar(&stepConfig.VulnerabilityReportFormat, "vulnerabilityReportFormat", `xlsx`, "Format of the file the vulnerability report is written to.")
cmd.Flags().StringVar(&stepConfig.ParallelLimit, "parallelLimit", `15`, "Limit of parallel jobs being run at once in case of `scanType: 'mta'` based scenarios, defaults to `15`.")
cmd.Flags().BoolVar(&stepConfig.Reporting, "reporting", true, "Whether assessment is being done at all, defaults to `true`.")
cmd.Flags().StringVar(&stepConfig.ServiceURL, "serviceUrl", `https://saas.whitesourcesoftware.com/api`, "URL to the WhiteSource server API used for communication.")
cmd.Flags().StringVar(&stepConfig.BuildDescriptorExcludeList, "buildDescriptorExcludeList", `[]`, "List of build descriptors and therefore modules to exclude from the scan and assessment activities.")
cmd.Flags().StringVar(&stepConfig.OrgToken, "orgToken", os.Getenv("PIPER_orgToken"), "WhiteSource token identifying your organization.")
cmd.Flags().StringVar(&stepConfig.UserToken, "userToken", os.Getenv("PIPER_userToken"), "WhiteSource token identifying the user executing the scan")
cmd.Flags().BoolVar(&stepConfig.LicensingVulnerabilities, "licensingVulnerabilities", true, "Whether license compliance is considered and reported as part of the assessment.")
cmd.Flags().StringVar(&stepConfig.AgentFileName, "agentFileName", `wss-unified-agent.jar`, "Locally used name for the Unified Agent jar file after download.")
cmd.Flags().StringVar(&stepConfig.EmailAddressesOfInitialProductAdmins, "emailAddressesOfInitialProductAdmins", `[]`, "The list of email addresses to assign as product admins for newly created WhiteSource products.")
cmd.Flags().StringVar(&stepConfig.ProductVersion, "productVersion", os.Getenv("PIPER_productVersion"), "Version of the WhiteSource product to be created and used for results aggregation, usually determined automatically.")
cmd.Flags().StringVar(&stepConfig.JreDownloadURL, "jreDownloadUrl", os.Getenv("PIPER_jreDownloadUrl"), "URL used for downloading the Java Runtime Environment (JRE) required to run the WhiteSource Unified Agent.")
cmd.Flags().StringVar(&stepConfig.ProductName, "productName", os.Getenv("PIPER_productName"), "Name of the WhiteSource product to be created and used for results aggregation.")
cmd.Flags().StringVar(&stepConfig.ProjectName, "projectName", `{{list .GroupID .ArtifactID | join "-" | trimAll "-"}}`, "The project used for reporting results in Whitesource")
cmd.Flags().StringVar(&stepConfig.ProjectToken, "projectToken", os.Getenv("PIPER_projectToken"), "Project token to execute scan on")
cmd.Flags().StringVar(&stepConfig.VulnerabilityReportTitle, "vulnerabilityReportTitle", `WhiteSource Security Vulnerability Report`, "Title of vulnerability report written during the assessment phase.")
cmd.Flags().StringVar(&stepConfig.InstallCommand, "installCommand", os.Getenv("PIPER_installCommand"), "Install command that can be used to populate the default docker image for some scenarios.")
cmd.Flags().StringVar(&stepConfig.ScanType, "scanType", os.Getenv("PIPER_scanType"), "Type of development stack used to implement the solution.")
cmd.Flags().StringVar(&stepConfig.CvssSeverityLimit, "cvssSeverityLimit", `-1`, "Limit of tollerable CVSS v3 score upon assessment and in consequence fails the build, defaults to `-1`.")
cmd.Flags().StringVar(&stepConfig.Includes, "includes", `**\/src\/main\/**\/*.java **\/*.py **\/*.go **\/*.js **\/*.ts`, "Space separated list of file path patterns to include in the scan, slashes must be escaped for sed")
cmd.Flags().StringVar(&stepConfig.Excludes, "excludes", `tests/**/*.py **/src/test/**/*.java`, "Space separated list of file path patterns to exclude in the scan")
cmd.Flags().StringVar(&stepConfig.ProductToken, "productToken", os.Getenv("PIPER_productToken"), "Token of the WhiteSource product to be created and used for results aggregation, usually determined automatically.")
cmd.Flags().StringVar(&stepConfig.AgentParameters, "agentParameters", ``, "Additional parameters passed to the Unified Agent command line.")
cmd.MarkFlagRequired("orgToken")
cmd.MarkFlagRequired("userToken")
cmd.MarkFlagRequired("productName")
}
// retrieve step metadata
func whitesourceExecuteScanMetadata() config.StepData {
var theMetaData = config.StepData{
Metadata: config.StepMetadata{
Name: "whitesourceExecuteScan",
Aliases: []config.Alias{},
},
Spec: config.StepSpec{
Inputs: config.StepInputs{
Parameters: []config.StepParameters{
{
Name: "buildDescriptorFile",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{},
},
{
Name: "buildDescriptorFile",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{},
},
{
Name: "buildDescriptorFile",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{},
},
{
Name: "buildDescriptorFile",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{},
},
{
Name: "buildDescriptorFile",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{},
},
{
Name: "buildDescriptorFile",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{},
},
{
Name: "buildDescriptorFile",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{},
},
{
Name: "defaultVersioningModel",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{},
},
{
Name: "createProductFromPipeline",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "bool",
Mandatory: false,
Aliases: []config.Alias{},
},
{
Name: "securityVulnerabilities",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "bool",
Mandatory: false,
Aliases: []config.Alias{},
},
{
Name: "timeout",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{},
},
{
Name: "agentDownloadUrl",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{},
},
{
Name: "configFilePath",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{},
},
{
Name: "reportDirectoryName",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{},
},
{
Name: "aggregateVersionWideReport",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "bool",
Mandatory: false,
Aliases: []config.Alias{},
},
{
Name: "vulnerabilityReportFormat",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{},
},
{
Name: "parallelLimit",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{},
},
{
Name: "reporting",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "bool",
Mandatory: false,
Aliases: []config.Alias{},
},
{
Name: "serviceUrl",
ResourceRef: []config.ResourceReference{},
Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{},
},
{
Name: "buildDescriptorExcludeList",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{},
},
{
Name: "orgToken",
ResourceRef: []config.ResourceReference{},
Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: true,
Aliases: []config.Alias{},
},
{
Name: "userToken",
ResourceRef: []config.ResourceReference{},
Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: true,
Aliases: []config.Alias{},
},
{
Name: "licensingVulnerabilities",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "bool",
Mandatory: false,
Aliases: []config.Alias{},
},
{
Name: "agentFileName",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{},
},
{
Name: "emailAddressesOfInitialProductAdmins",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{},
},
{
Name: "productVersion",
ResourceRef: []config.ResourceReference{},
Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{},
},
{
Name: "jreDownloadUrl",
ResourceRef: []config.ResourceReference{},
Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{},
},
{
Name: "productName",
ResourceRef: []config.ResourceReference{},
Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: true,
Aliases: []config.Alias{},
},
{
Name: "projectName",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{{Name: "whitesourceProjectName"}},
},
{
Name: "projectToken",
ResourceRef: []config.ResourceReference{},
Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{},
},
{
Name: "vulnerabilityReportTitle",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{},
},
{
Name: "installCommand",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{},
},
{
Name: "scanType",
ResourceRef: []config.ResourceReference{},
Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{},
},
{
Name: "cvssSeverityLimit",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{},
},
{
Name: "includes",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{},
},
{
Name: "excludes",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{},
},
{
Name: "productToken",
ResourceRef: []config.ResourceReference{},
Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{},
},
{
Name: "agentParameters",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{},
},
},
},
},
}
return theMetaData
}

View File

@ -0,0 +1,16 @@
package cmd
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestWhitesourceExecuteScanCommand(t *testing.T) {
testCmd := WhitesourceExecuteScanCommand()
// only high level testing performed - details are tested in step generation procudure
assert.Equal(t, "whitesourceExecuteScan", testCmd.Use, "command name incorrect")
}

2
go.mod
View File

@ -3,6 +3,7 @@ module github.com/SAP/jenkins-library
go 1.13
require (
github.com/360EntSecGroup-Skylar/excelize/v2 v2.2.0
github.com/GoogleContainerTools/container-diff v0.15.0
github.com/Jeffail/gabs/v2 v2.5.1
github.com/Masterminds/goutils v1.1.0 // indirect
@ -42,6 +43,7 @@ require (
github.com/testcontainers/testcontainers-go v0.5.1
go.mongodb.org/mongo-driver v1.3.3 // indirect
golang.org/x/crypto v0.0.0-20200602180216-279210d13fed // indirect
golang.org/x/mod v0.3.0
golang.org/x/net v0.0.0-20200602114024-627f9648deb9 // indirect
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d
golang.org/x/sys v0.0.0-20200602225109-6fdc65e7d980 // indirect

44
go.sum
View File

@ -37,6 +37,8 @@ contrib.go.opencensus.io/exporter/stackdriver v0.12.1/go.mod h1:iwB6wGarfphGGe/e
contrib.go.opencensus.io/integrations/ocsql v0.1.4/go.mod h1:8DsSdjz3F+APR+0z0WkU1aRorQCFfRxvqjUUPMbF3fE=
contrib.go.opencensus.io/resource v0.1.1/go.mod h1:F361eGI91LCmW1I/Saf+rX0+OFcigGlFvXwEGEnkRLA=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/360EntSecGroup-Skylar/excelize/v2 v2.2.0 h1:5DuRTdH6M8yPjvFfBkACVmuk7SoTzmaB8yM6KVqEhP8=
github.com/360EntSecGroup-Skylar/excelize/v2 v2.2.0/go.mod h1:Uwb0d1GgxJieUWZG5WylTrgQ2SrldfjagAxheU8W6MQ=
github.com/AndreasBriese/bbloom v0.0.0-20190306092124-e2d15f34fcf9/go.mod h1:bOvUY6CB00SOBii9/FifXqc0awNKxLFCL/+pkDPuyl8=
github.com/Azure/azure-amqp-common-go/v2 v2.1.0/go.mod h1:R8rea+gJRuJR6QxTir/XuEd+YuKoUiazDC/N96FiDEU=
github.com/Azure/azure-pipeline-go v0.2.1/go.mod h1:UGSo8XybXnIGZ3epmeBw7Jdz+HiUVpqIlpz/HKHylF4=
@ -96,11 +98,9 @@ github.com/Masterminds/semver/v3 v3.1.0/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0
github.com/Masterminds/sprig v2.22.0+incompatible h1:z4yfnGrZ7netVz+0EDJ0Wi+5VZCSYp4Z0m2dk6cEM60=
github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o=
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
github.com/Microsoft/go-winio v0.4.14 h1:+hMXMk01us9KgxGb7ftKQt2Xpf5hH/yky+TDA+qxleU=
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5 h1:ygIc8M6trr62pF5DucadTWGdEB4mEyvzi0e2nbcmcyA=
github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw=
github.com/Microsoft/hcsshim v0.8.6 h1:ZfF0+zZeYdzMIVMZHKtDKJvLHj76XCuVae/jNkjj0IA=
github.com/Microsoft/hcsshim v0.8.6/go.mod h1:Op3hHsoHPAvb6lceZHDtd9OkTew38wNoXnJs8iY7rUg=
github.com/Microsoft/hcsshim v0.8.9 h1:VrfodqvztU8YSOvygU+DN1BGaSGxmrNfqOv5oOuX2Bk=
github.com/Microsoft/hcsshim v0.8.9/go.mod h1:5692vkUqntj1idxauYlpoINNKeqCiG6Sg38RRsjT5y8=
@ -140,7 +140,6 @@ github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio=
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/asaskevich/govalidator v0.0.0-20180720115003-f9ffefc3facf/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a h1:idn718Q4B6AGu/h5Sxe66HYVdqdGu2l9Iebqhi/AEoA=
github.com/asaskevich/govalidator v0.0.0-20190424111038-f61b66f89f4a/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY=
github.com/asaskevich/govalidator v0.0.0-20200108200545-475eaeb16496/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg=
github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 h1:4daAzAu0S6Vi7/lbWECcX0j45yZReDZ56BQsrVBOEEY=
@ -182,10 +181,8 @@ github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDk
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8=
github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0/go.mod h1:4Zcjuz89kmFXt9morQgcfYZAYZ5n8WHjt81YYWIwtTM=
github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f h1:tSNMc+rJDfmYntojat8lljbt1mgKNpTxUZJsSzJ9Y1s=
github.com/containerd/cgroups v0.0.0-20190919134610-bf292b21730f/go.mod h1:OApqhQ4XNSNC13gXIwDjhOQxjWa/NxkwZXJ1EvqT0ko=
github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw=
github.com/containerd/containerd v1.3.0 h1:xjvXQWABwS2uiv3TWgQt5Uth60Gu86LTGZXMJkjc7rY=
github.com/containerd/containerd v1.3.0/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
github.com/containerd/containerd v1.3.2/go.mod h1:bC6axHOhabU15QhwfG7w5PipXdVtMXFTttgp+kVtyUA=
github.com/containerd/containerd v1.3.4 h1:3o0smo5SKY7H6AJCmJhsnCjR2/V2T8VmiHt7seN2/kI=
@ -211,7 +208,6 @@ github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfc
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY=
github.com/creack/pty v1.1.9 h1:uDmaGzcdjhF4i/plgjmEsriH11Y0o7RKapEf/LDaM3w=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -231,7 +227,6 @@ github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BU
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
github.com/docker/docker v0.7.3-0.20190327010347-be7ac8be2ae0/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v0.7.3-0.20190506211059-b20a14b54661/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7 h1:Cvj7S8I4Xpx78KAl6TwTmMHuHlZ/0SM60NUneGJQ7IE=
github.com/docker/docker v1.4.2-0.20190924003213-a8608b5b67c7/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
github.com/docker/docker v1.4.2-0.20200114201811-16a3519d870b h1:CrNyKukWIBVy2bR9+Mff24Yc85oD8LUwW4f81kjSvFw=
github.com/docker/docker v1.4.2-0.20200114201811-16a3519d870b/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk=
@ -268,7 +263,6 @@ github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjr
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/fortytw2/leaktest v1.2.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
@ -315,14 +309,12 @@ github.com/go-openapi/analysis v0.17.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpR
github.com/go-openapi/analysis v0.18.0/go.mod h1:IowGgpVeD0vNm45So8nr+IcQ3pxVtpRoBWb8PVZO0ik=
github.com/go-openapi/analysis v0.19.2/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9snX6gxi44djMjk=
github.com/go-openapi/analysis v0.19.4/go.mod h1:3P1osvZa9jKjb8ed2TPng3f0i/UY9snX6gxi44djMjk=
github.com/go-openapi/analysis v0.19.5 h1:8b2ZgKfKIUTVQpTb77MoRDIMEIwvDVw40o3aOXdfYzI=
github.com/go-openapi/analysis v0.19.5/go.mod h1:hkEAkxagaIvIP7VTn8ygJNkd4kAYON2rCu0v0ObL0AU=
github.com/go-openapi/analysis v0.19.10 h1:5BHISBAXOc/aJK25irLZnx2D3s6WyYaY9D4gmuz9fdE=
github.com/go-openapi/analysis v0.19.10/go.mod h1:qmhS3VNFxBlquFJ0RGoDtylO9y4pgTAUNE9AEEMdlJQ=
github.com/go-openapi/errors v0.17.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0=
github.com/go-openapi/errors v0.18.0/go.mod h1:LcZQpmvG4wyF5j4IhA73wkLFQg+QJXOQHVjmcZxhka0=
github.com/go-openapi/errors v0.19.2/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94=
github.com/go-openapi/errors v0.19.3 h1:7MGZI1ibQDLasvAz8HuhvYk9eNJbJkCOXWsSjjMS+Zc=
github.com/go-openapi/errors v0.19.3/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94=
github.com/go-openapi/errors v0.19.4 h1:fSGwO1tSYHFu70NKaWJt5Qh0qoBRtCm/mXS1yhf+0W0=
github.com/go-openapi/errors v0.19.4/go.mod h1:qX0BLWsyaKfvhluLejVpVNwNRdXZhEbTA4kxxpKBC94=
@ -343,7 +335,6 @@ github.com/go-openapi/loads v0.18.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf
github.com/go-openapi/loads v0.19.0/go.mod h1:72tmFy5wsWx89uEVddd0RjRWPZm92WRLhf7AC+0+OOU=
github.com/go-openapi/loads v0.19.2/go.mod h1:QAskZPMX5V0C2gvfkGZzJlINuP7Hx/4+ix5jWFxsNPs=
github.com/go-openapi/loads v0.19.3/go.mod h1:YVfqhUCdahYwR3f3iiwQLhicVRvLlU/WO5WPaZvcvSI=
github.com/go-openapi/loads v0.19.4 h1:5I4CCSqoWzT+82bBkNIvmLc0UOsoKKQ4Fz+3VxOB7SY=
github.com/go-openapi/loads v0.19.4/go.mod h1:zZVHonKd8DXyxyw4yfnVjPzBjIQcLt0CCsn0N0ZrQsk=
github.com/go-openapi/loads v0.19.5 h1:jZVYWawIQiA1NBnHla28ktg6hrcfTHsCE+3QLVRBIls=
github.com/go-openapi/loads v0.19.5/go.mod h1:dswLCAdonkRufe/gSUC3gN8nTSaB9uaS2es0x5/IbjY=
@ -357,7 +348,6 @@ github.com/go-openapi/spec v0.0.0-20160808142527-6aced65f8501/go.mod h1:J8+jY1nA
github.com/go-openapi/spec v0.17.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
github.com/go-openapi/spec v0.18.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcsZsD5zxMY=
github.com/go-openapi/spec v0.19.3 h1:0XRyw8kguri6Yw4SxhsQA/atC88yqrk0+G4YhI2wabc=
github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo=
github.com/go-openapi/spec v0.19.6/go.mod h1:Hm2Jr4jv8G1ciIAo+frC/Ft+rR2kQDh8JHKHb3gWUSk=
github.com/go-openapi/spec v0.19.8 h1:qAdZLh1r6QF/hI/gTq+TJTvsQUodZsM7KLqkAJdiJNg=
@ -375,14 +365,12 @@ github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/
github.com/go-openapi/swag v0.18.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.7 h1:VRuXN2EnMSsZdauzdss6JBC29YotDqG59BZ+tdlIL1s=
github.com/go-openapi/swag v0.19.7/go.mod h1:ao+8BpOPyKdpQz3AOJfbeEVpLmWAvlT1IfTe5McPyhY=
github.com/go-openapi/swag v0.19.9 h1:1IxuqvBUU3S2Bi4YC7tlP9SJF1gVpCvqN0T2Qof4azE=
github.com/go-openapi/swag v0.19.9/go.mod h1:ao+8BpOPyKdpQz3AOJfbeEVpLmWAvlT1IfTe5McPyhY=
github.com/go-openapi/validate v0.18.0/go.mod h1:Uh4HdOzKt19xGIGm1qHf/ofbX1YQ4Y+MYsct2VUrAJ4=
github.com/go-openapi/validate v0.19.2/go.mod h1:1tRCw7m3jtI8eNWEEliiAqUIcBztB2KDnRCRMUi7GTA=
github.com/go-openapi/validate v0.19.3/go.mod h1:90Vh6jjkTn+OT1Eefm0ZixWNFjhtOH7vS9k0lo6zwJo=
github.com/go-openapi/validate v0.19.6 h1:WsKw9J1WzYBVxWRYwLqEk3325RL6G0SSWksuamkk6q0=
github.com/go-openapi/validate v0.19.6/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4=
github.com/go-openapi/validate v0.19.8 h1:YFzsdWIDfVuLvIOF+ZmKjVg1MbPJ1QgY9PihMwei1ys=
github.com/go-openapi/validate v0.19.8/go.mod h1:8DJv2CVJQ6kGNpFW6eV9N3JviE1C85nY1c2z52x1Gk4=
@ -446,17 +434,14 @@ github.com/gofrs/flock v0.0.0-20190320160742-5135e617513b/go.mod h1:F1TvTiK9OcQq
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4=
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d h1:3PaI8p3seN09VjbTYC/QWlUZdZ1qS1zGjy7LH2Wt07I=
github.com/gogo/protobuf v1.2.2-0.20190723190241-65acae22fc9d/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/gogo/protobuf v1.3.1 h1:DqDEcV5aeaTmdFBePNpYsp3FlcVH/2ISVVM9Qf8PSls=
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190129154638-5b532d6fd5ef/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e h1:1r7pUrabqp18hOBcwBwiTsbnFeTZHV9eER/QT5JVZxY=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
@ -468,7 +453,6 @@ github.com/golang/protobuf v0.0.0-20161109072736-4bd1920723d7/go.mod h1:6lQm79b+
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3 h1:gyjaxf+svBWX08ZjK86iN9geUJF0H6gp2IRKX6Nf6/I=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
@ -681,7 +665,6 @@ github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.7.0 h1:aizVhC/NAAcKWb+5QsU1iNOZb4Yws5UO2I+aIprQITM=
github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
github.com/mailru/easyjson v0.7.1 h1:mdxE1MF9o53iCb2Ghj1VfWvh7ZOwHpnVG/xwXrV90U8=
github.com/mailru/easyjson v0.7.1/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
@ -728,11 +711,9 @@ github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eI
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.3.1 h1:cCBH2gTD2K0OtLlv/Y5H01VQCqmlDxz30kS5Y5bqfLA=
github.com/mitchellh/mapstructure v1.3.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/reflectwalk v1.0.0 h1:9D+8oIskB4VJBN5SFlmc27fSlIBZaov1Wpk/IfikLNY=
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
github.com/mitchellh/reflectwalk v1.0.1 h1:FVzMWA5RllMAKIdUSC8mdWo3XtwoecrH79BY70sEEpE=
github.com/mitchellh/reflectwalk v1.0.1/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
@ -741,6 +722,8 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJ
github.com/modern-go/reflect2 v0.0.0-20180320133207-05fbef0ca5da/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
github.com/morikuni/aec v0.0.0-20170113033406-39771216ff4c/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
@ -767,7 +750,6 @@ github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.8.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.10.3 h1:OoxbjfXVZyod1fmWYhI7SEyaD8B00ynP3T+D5GiyHOY=
github.com/onsi/ginkgo v1.10.3/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.11.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.12.0 h1:Iw5WCbBcaAAd0fpRb1c9r5YCylv4XDoCSigm1zLevwU=
@ -775,14 +757,12 @@ github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/onsi/gomega v1.5.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.7.1 h1:K0jcRCwNQM3vFGh1ppMtDh/+7ApJrjldlX8fA0jDTLQ=
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
github.com/onsi/gomega v1.8.1/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
github.com/onsi/gomega v1.9.0 h1:R1uwffexN6Pr340GtYRIdZmAiN4J+iw6WG4wog1DUXg=
github.com/onsi/gomega v1.9.0/go.mod h1:Ho0h+IUsWyvy1OpqCwxlQ/21gkhVunqlU8fDGcoTdcA=
github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk=
github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/go-digest v1.0.0-rc1 h1:WzifXhOVOEOuFYOJAW6aQqW0TooG2iki3E3Ii+WN7gQ=
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
@ -863,7 +843,6 @@ github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMB
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/assertions v1.0.0 h1:UVQPSSmc3qtTi+zPPkCXvZX9VvW/xT/NsRvKfwY81a8=
github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM=
@ -955,6 +934,8 @@ github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQ
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/xuri/efp v0.0.0-20191019043341-b7dc4fe9aa91 h1:gp02YctZuIPTk0t7qI+wvg3VQwTPyNmSGG6ZqOsjSL8=
github.com/xuri/efp v0.0.0-20191019043341-b7dc4fe9aa91/go.mod h1:uBiSUepVYMhGTfDeBKKasV4GpgBlzJ46gXUBAqV8qLk=
github.com/yalp/jsonpath v0.0.0-20180802001716-5cc68e5049a0/go.mod h1:/LWChgwKmvncFJFHJ7Gvn9wZArjbV5/FppcK2fKk/tI=
github.com/yudai/gojsondiff v1.0.0/go.mod h1:AY32+k2cwILAkW1fbgxQ5mUmMiZFgLIV+FBNExI05xg=
github.com/yudai/golcs v0.0.0-20170316035057-ecda9a501e82/go.mod h1:lgjkn3NuSvDfVJdfcVVdX+jpBxNmX4rDAzaS45IcYoM=
@ -966,7 +947,6 @@ go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU=
go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg=
go.mongodb.org/mongo-driver v1.0.3/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.mongodb.org/mongo-driver v1.1.1/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.mongodb.org/mongo-driver v1.1.2 h1:jxcFYjlkl8xaERsgLo+RNquI0epW6zuy/ZRQs6jnrFA=
go.mongodb.org/mongo-driver v1.1.2/go.mod h1:u7ryQJ+DOzQmeO7zB6MHyr8jkEQvC8vH7qLUO4lqsUM=
go.mongodb.org/mongo-driver v1.3.0/go.mod h1:MSWZXKOynuguX+JSvwP8i+58jYCXxbia8HS3gZBapIE=
go.mongodb.org/mongo-driver v1.3.3 h1:9kX7WY6sU/5qBuhm5mdnNWdqaDAQKB2qSZOd5wMEPGQ=
@ -975,7 +955,6 @@ go.opencensus.io v0.15.0/go.mod h1:UffZAU+4sDEINUGP/B7UfBBkq4fqLu9zXAX7ke6CHW0=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3 h1:8sGtKOrtQqkN1bp2AtX+misvLIlOmsEsNd+9NIcPEm8=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
@ -1001,7 +980,6 @@ golang.org/x/crypto v0.0.0-20191002192127-34f69633bfdc/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20191206172530-e9b2fee46413/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073 h1:xMPOj6Pz6UipU1wXLkrtqpHbR0AVFnyPEQq/wRWz9lM=
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200510223506-06a226fb4e37/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20200602180216-279210d13fed h1:g4KENRiCMEx58Q7/ecwfT0N2o8z35Fnbsjig/Alf2T4=
@ -1020,6 +998,8 @@ golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EH
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.0.0-20200430140353-33d19683fad8 h1:6WW6V3x1P/jokJBpRQYUJnMHRP6isStQwCozxnU7XQw=
golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
@ -1037,6 +1017,7 @@ golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20170114055629-f2499483f923/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -1078,7 +1059,6 @@ golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLL
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2 h1:eDrdRpKgkcCqKZQwyZRyeFZgfqt37SL7Kv3tok06cKE=
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200602114024-627f9648deb9 h1:pNX+40auqi2JqRfOP1akLGtYcn15TUbkhwuCO3foqqM=
golang.org/x/net v0.0.0-20200602114024-627f9648deb9/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
@ -1146,7 +1126,6 @@ golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd h1:xhmwyvizuTgC2qz7ZlMluP20uW+C3Rm0FD/WLDX8884=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -1162,7 +1141,6 @@ golang.org/x/text v0.3.2 h1:tW2bmiBqwgJj/UpqtC8EpXEZVYOwU0yG4iWbprSVAcs=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 h1:SvFZT6jyqRaOeXpc5h/JSfZenJ2O330aBsf7JfSUXmQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20200416051211-89c76fbcd5d1 h1:NusfzzA6yGQ+ua51ck7E3omNUX/JuqbFSaRGqU8CcLI=
@ -1269,7 +1247,6 @@ google.golang.org/api v0.25.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0 h1:KxkO13IPW4Lslp2bz+KHP2E3gtFlrIGNThxkZQ3g+4c=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
@ -1279,7 +1256,6 @@ google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoA
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873 h1:nfPFGzJkUDX6uBmpN/pSw7MbOAWegH5QDQuoXFHedLg=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190508193815-b515fa19cec8/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s=
@ -1345,7 +1321,6 @@ gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8
gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.56.0 h1:DPMeDvGTM54DXbPkVIZsp19fp/I2K7zwA/itHYHKo8Y=
gopkg.in/ini.v1 v1.56.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.57.0 h1:9unxIsFcTt4I55uWluz+UmL95q4kdJ0buvQ1ZIqVQww=
gopkg.in/ini.v1 v1.57.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
@ -1364,7 +1339,6 @@ gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10=
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU=
gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=

113
pkg/versioning/gomodfile.go Normal file
View File

@ -0,0 +1,113 @@
package versioning
import (
"io/ioutil"
"os"
"strings"
"golang.org/x/mod/modfile"
"github.com/pkg/errors"
)
// GoModDescriptor holds the unique identifier combination for Go modules
type GoModDescriptor struct {
GroupID string
ArtifactID string
Version string
Packaging string
}
// GoMod utility to interact with Go Modules specific versioning
type GoMod struct {
path string
readFile func(string) ([]byte, error)
writeFile func(string, []byte, os.FileMode) error
fileExists func(string) (bool, error)
buildDescriptorContent string
}
func (m *GoMod) init() error {
if m.readFile == nil {
m.readFile = ioutil.ReadFile
}
if m.writeFile == nil {
m.writeFile = ioutil.WriteFile
}
if len(m.buildDescriptorContent) == 0 {
content, err := m.readFile(m.path)
if err != nil {
return errors.Wrapf(err, "failed to read file '%v'", m.path)
}
m.buildDescriptorContent = string(content)
}
return nil
}
// GetVersion returns the go.mod descriptor version property
func (m *GoMod) GetVersion() (string, error) {
buildDescriptorFilePath := m.path
var err error
if strings.Contains(m.path, "go.mod") {
buildDescriptorFilePath, err = searchDescriptor([]string{"version.txt", "VERSION"}, m.fileExists)
if err != nil {
err = m.init()
if err != nil {
return "", errors.Wrapf(err, "failed to read file '%v'", m.path)
}
parsed, err := modfile.Parse(m.path, []byte(m.buildDescriptorContent), nil)
if err != nil {
return "", errors.Wrap(err, "failed to parse go.mod file")
}
if parsed.Module.Mod.Version != "" {
return parsed.Module.Mod.Version, nil
}
return "", errors.Wrap(err, "failed to retrieve version")
}
}
artifact := &Versionfile{
path: buildDescriptorFilePath,
versioningScheme: m.VersioningScheme(),
}
return artifact.GetVersion()
}
// SetVersion sets the go.mod descriptor version property
func (m *GoMod) SetVersion(v string) error {
return nil
}
// VersioningScheme returns the relevant versioning scheme
func (m *GoMod) VersioningScheme() string {
return "semver2"
}
// GetCoordinates returns the go.mod build descriptor coordinates
func (m *GoMod) GetCoordinates() (Coordinates, error) {
err := m.init()
if err != nil {
return nil, err
}
parsed, err := modfile.Parse(m.path, []byte(m.buildDescriptorContent), nil)
if err != nil {
return "", errors.Wrap(err, "failed to parse go.mod file")
}
descriptor := &GoModDescriptor{}
if parsed.Module == nil {
return "", errors.Wrap(err, "failed to parse go.mod file")
}
if parsed.Module.Mod.Path != "" {
artifactSplit := strings.Split(parsed.Module.Mod.Path, "/")
artifactID := artifactSplit[len(artifactSplit)-1]
descriptor.ArtifactID = artifactID
}
descriptor.Version = parsed.Module.Mod.Version
if descriptor.Version == "" {
descriptor.Version = "unspecified"
}
return descriptor, nil
}

135
pkg/versioning/gradle.go Normal file
View File

@ -0,0 +1,135 @@
package versioning
import (
"bytes"
"github.com/SAP/jenkins-library/pkg/command"
"github.com/SAP/jenkins-library/pkg/log"
"io"
"regexp"
"strings"
)
type gradleExecRunner interface {
Stdout(out io.Writer)
Stderr(err io.Writer)
RunExecutable(e string, p ...string) error
}
// GradleDescriptor holds the unique identifier combination for Gradle built Java artifacts
type GradleDescriptor struct {
GroupID string
ArtifactID string
Version string
Packaging string
}
// Gradle defines a maven artifact used for versioning
type Gradle struct {
execRunner gradleExecRunner
gradlePropsOut []byte
}
func (g *Gradle) init() error {
if g.execRunner == nil {
g.execRunner = &command.Command{}
}
if g.gradlePropsOut == nil {
gradlePropsBuffer := &bytes.Buffer{}
g.execRunner.Stdout(gradlePropsBuffer)
err := g.execRunner.RunExecutable("gradle", "properties", "--no-daemon", "--console=plain", "-q")
if err != nil {
return err
}
g.gradlePropsOut = gradlePropsBuffer.Bytes()
g.execRunner.Stdout(log.Writer())
}
return nil
}
// VersioningScheme returns the relevant versioning scheme
func (g *Gradle) VersioningScheme() string {
return "semver2"
}
// GetCoordinates reads the coordinates from the maven pom.xml descriptor file
func (g *Gradle) GetCoordinates() (Coordinates, error) {
result := &GradleDescriptor{}
var err error
// result.GroupID, err = g.GetGroupID()
// if err != nil {
// return nil, err
// }
result.ArtifactID, err = g.GetArtifactID()
if err != nil {
return nil, err
}
result.Version, err = g.GetVersion()
if err != nil {
return nil, err
}
// result.Packaging, err = g.GetPackaging()
// if err != nil {
// return nil, err
// }
return result, nil
}
// GetPackaging returns the current ID of the Group
// func (g *Gradle) GetPackaging() (string, error) {
// g.init()
// packaging, err := g.runner.Evaluate(&g.options, "project.packaging", g.execRunner)
// if err != nil {
// return "", errors.Wrap(err, "Gradle - getting packaging failed")
// }
// return packaging, nil
// }
// GetGroupID returns the current ID of the Group
// func (g *Gradle) GetGroupID() (string, error) {
// g.init()
// groupID, err := g.runner.Evaluate(&g.options, "project.groupId", g.execRunner)
// if err != nil {
// return "", errors.Wrap(err, "Gradle - getting groupId failed")
// }
// return groupID, nil
// }
// GetArtifactID returns the current ID of the artifact
func (g *Gradle) GetArtifactID() (string, error) {
err := g.init()
if err != nil {
return "", err
}
regex := regexp.MustCompile(`(?m:^rootProject: root project '(.*)')`)
match := string(regex.Find(g.gradlePropsOut))
artifactID := strings.Split(match, `'`)[1]
return artifactID, nil
}
// GetVersion returns the current version of the artifact
func (g *Gradle) GetVersion() (string, error) {
versionID := "unspecified"
err := g.init()
if err != nil {
return "", err
}
r := regexp.MustCompile("(?m:^version: (.*))")
match := r.FindString(string(g.gradlePropsOut))
versionIDSlice := strings.Split(match, ` `)
if len(versionIDSlice) > 1 {
versionID = versionIDSlice[1]
}
return versionID, nil
}
// SetVersion updates the version of the artifact
func (g *Gradle) SetVersion(version string) error {
return nil
}

View File

@ -9,6 +9,14 @@ import (
"github.com/pkg/errors"
)
// JSONDescriptor holds the unique identifier combination for json artifacts
type JSONDescriptor struct {
GroupID string
ArtifactID string
Version string
Packaging string
}
// JSONfile defines an artifact using a json file for versioning
type JSONfile struct {
path string
@ -79,5 +87,15 @@ func (j *JSONfile) SetVersion(version string) error {
// GetCoordinates returns the coordinates
func (j *JSONfile) GetCoordinates() (Coordinates, error) {
return nil, nil
projectVersion, err := j.GetVersion()
if err != nil {
return nil, err
}
projectName := j.content["name"].(string)
artifact := &JSONDescriptor{
ArtifactID: projectName,
Version: projectVersion,
}
return artifact, nil
}

View File

@ -43,7 +43,7 @@ func (p *Pip) init() error {
p.writeFile = ioutil.WriteFile
}
if len(p.buildDescriptorContent) > 0 {
if len(p.buildDescriptorContent) == 0 {
content, err := p.readFile(p.path)
if err != nil {
return errors.Wrapf(err, "failed to read file '%v'", p.path)

View File

@ -71,16 +71,26 @@ func GetArtifact(buildTool, buildDescriptorFilePath string, opts *Options, execR
path: buildDescriptorFilePath,
versionField: "version",
}
case "gradle":
if len(buildDescriptorFilePath) == 0 {
buildDescriptorFilePath = "build.gradle"
}
artifact = &Gradle{}
case "golang":
if len(buildDescriptorFilePath) == 0 {
var err error
buildDescriptorFilePath, err = searchDescriptor([]string{"VERSION", "version.txt"}, fileExists)
buildDescriptorFilePath, err = searchDescriptor([]string{"VERSION", "version.txt", "go.mod"}, fileExists)
if err != nil {
return artifact, err
}
}
artifact = &Versionfile{
path: buildDescriptorFilePath,
switch buildDescriptorFilePath {
case "go.mod":
artifact = &GoMod{path: buildDescriptorFilePath}
break
default:
artifact = &Versionfile{path: buildDescriptorFilePath}
}
case "maven":
if len(buildDescriptorFilePath) == 0 {

View File

@ -61,7 +61,7 @@ func TestGetArtifact(t *testing.T) {
fileExists = func(string) (bool, error) { return false, nil }
_, err := GetArtifact("golang", "", &Options{}, nil)
assert.EqualError(t, err, "no build descriptor available, supported: [VERSION version.txt]")
assert.EqualError(t, err, "no build descriptor available, supported: [VERSION version.txt go.mod]")
})
t.Run("maven", func(t *testing.T) {

View File

@ -20,8 +20,39 @@ type Product struct {
LastUpdateDate string `json:"lastUpdatedDate,omitempty"`
}
// Alert
type Alert struct {
Vulnerability Vulnerability `json:"vulnerability"`
Library Library `json:"library,omitempty"`
Project string `json:"project,omitempty"`
CreationDate string `json:"creation_date,omitempty"`
}
// Library
type Library struct {
Name string `json:"name,omitempty"`
Filename string `json:"filename,omitempty"`
Version string `json:"version,omitempty"`
Project string `json:"project,omitempty"`
}
// Vulnerability
type Vulnerability struct {
Name string `json:"name,omitempty"`
Type string `json:"type,omitempty"`
Level string `json:"level,omitempty"`
Description string `json:"description,omitempty"`
Severity string `json:"severity,omitempty"`
CVSS3Severity string `json:"cvss3_severity,omitempty"`
CVSS3Score float64 `json:"cvss3_score,omitempty"`
Score float64 `json:"score,omitempty"`
FixResolutionText string `json:"fixResolutionText,omitempty"`
PublishDate string `json:"publishDate,omitempty"`
}
// Project defines a WhiteSource project with name and token
type Project struct {
ID int64 `json:"id"`
Name string `json:"name"`
PluginName string `json:"pluginName"`
Token string `json:"token"`
@ -35,8 +66,10 @@ type Request struct {
RequestType string `json:"requestType,omitempty"`
UserKey string `json:"userKey,omitempty"`
ProductToken string `json:"productToken,omitempty"`
ProductName string `json:"productName,omitempty"`
ProjectToken string `json:"projectToken,omitempty"`
OrgToken string `json:"orgToken,omitempty"`
Format string `json:"format,omitempty"`
}
// System defines a WhiteSource system including respective tokens (e.g. org token, user token)
@ -47,6 +80,16 @@ type System struct {
UserToken string
}
// NewSystem constructs a new system instance
func NewSystem(serverURL, orgToken, userToken string) *System {
return &System{
ServerURL: serverURL,
OrgToken: orgToken,
UserToken: userToken,
HTTPClient: &piperhttp.Client{},
}
}
// GetProductsMetaInfo retrieves meta information for all WhiteSource products a user has access to
func (s *System) GetProductsMetaInfo() ([]Product, error) {
wsResponse := struct {
@ -103,39 +146,104 @@ func (s *System) GetProjectsMetaInfo(productToken string) ([]Project, error) {
respBody, err := s.sendRequest(req)
if err != nil {
return wsResponse.ProjectVitals, errors.Wrap(err, "WhiteSource request failed")
return nil, errors.Wrap(err, "WhiteSource request failed")
}
err = json.Unmarshal(respBody, &wsResponse)
if err != nil {
return wsResponse.ProjectVitals, errors.Wrap(err, "failed to parse WhiteSource response")
return nil, errors.Wrap(err, "failed to parse WhiteSource response")
}
return wsResponse.ProjectVitals, nil
}
//GetProjectToken returns the project token for a project with a given name
// GetProjectToken returns the project token for a project with a given name
func (s *System) GetProjectToken(productToken, projectName string) (string, error) {
var token string
project, err := s.GetProjectByName(productToken, projectName)
if err != nil {
return "", err
}
// returns a nil token and no error if not found
if project != nil {
token = project.Token
}
return token, nil
}
// GetProjectVitals returns project meta info given a project token
func (s *System) GetProjectVitals(projectToken string) (*Project, error) {
wsResponse := struct {
ProjectVitals []Project `json:"projectVitals"`
}{
ProjectVitals: []Project{},
}
req := Request{
RequestType: "getProjectVitals",
ProjectToken: projectToken,
}
respBody, err := s.sendRequest(req)
if err != nil {
return nil, errors.Wrap(err, "WhiteSource request failed")
}
err = json.Unmarshal(respBody, &wsResponse)
if err != nil {
return nil, errors.Wrap(err, "failed to parse WhiteSource response")
}
return &wsResponse.ProjectVitals[0], nil
}
// GetProjectByName returns the finds and returns a project by name
func (s *System) GetProjectByName(productToken, projectName string) (*Project, error) {
var project *Project
projects, err := s.GetProjectsMetaInfo(productToken)
if err != nil {
return "", errors.Wrap(err, "failed to retrieve WhiteSource project meta info")
return nil, errors.Wrap(err, "failed to retrieve WhiteSource project meta info")
}
for _, proj := range projects {
if projectName == proj.Name {
project = &proj
break
}
}
// returns a nil project and no error if no project exists with projectName
return project, nil
}
// GetProjectsByIDs: get all project tokens given a list of project ids
func (s *System) GetProjectsByIDs(productToken string, projectIDs []int64) ([]Project, error) {
var projectsMatched []Project
projects, err := s.GetProjectsMetaInfo(productToken)
if err != nil {
return nil, errors.Wrap(err, "failed to retrieve WhiteSource project meta info")
}
for _, project := range projects {
if projectName == project.Name {
return project.Token, nil
for _, projectID := range projectIDs {
if projectID == project.ID {
projectsMatched = append(projectsMatched, project)
}
}
}
return "", nil
return projectsMatched, nil
}
//GetProjectTokens returns the project tokens for a list of given project names
// GetProjectTokens returns the project tokens matching a given a slice of project names
func (s *System) GetProjectTokens(productToken string, projectNames []string) ([]string, error) {
projectTokens := []string{}
projects, err := s.GetProjectsMetaInfo(productToken)
if err != nil {
return projectTokens, errors.Wrap(err, "failed to retrieve WhiteSource project meta info")
return nil, errors.Wrap(err, "failed to retrieve WhiteSource project meta info")
}
for _, project := range projects {
@ -148,7 +256,7 @@ func (s *System) GetProjectTokens(productToken string, projectNames []string) ([
return projectTokens, nil
}
//GetProductName returns the product name for a given product token
// GetProductName returns the product name for a given product token
func (s *System) GetProductName(productToken string) (string, error) {
wsResponse := struct {
ProductTags []Product `json:"productTags"`
@ -177,8 +285,136 @@ func (s *System) GetProductName(productToken string) (string, error) {
return "", nil
}
// GetProjectRiskReport
func (s *System) GetProjectRiskReport(projectToken string) ([]byte, error) {
req := Request{
RequestType: "getProjectRiskReport",
ProjectToken: projectToken,
}
respBody, err := s.sendRequest(req)
if err != nil {
return nil, errors.Wrap(err, "WhiteSource getProjectRiskReport request failed")
}
return respBody, nil
}
// GetProjectVulnerabilityReport
func (s *System) GetProjectVulnerabilityReport(projectToken string, format string) ([]byte, error) {
req := Request{
RequestType: "getProjectVulnerabilityReport",
ProjectToken: projectToken,
Format: format,
}
respBody, err := s.sendRequest(req)
if err != nil {
return nil, errors.Wrap(err, "WhiteSource getProjectVulnerabilityReport request failed")
}
return respBody, nil
}
// GetOrganizationProductVitals
func (s *System) GetOrganizationProductVitals() ([]Product, error) {
wsResponse := struct {
ProductVitals []Product `json:"productVitals"`
}{
ProductVitals: []Product{},
}
req := Request{
RequestType: "getOrganizationProductVitals",
}
respBody, err := s.sendRequest(req)
if err != nil {
return nil, errors.Wrap(err, "WhiteSource request failed")
}
err = json.Unmarshal(respBody, &wsResponse)
if err != nil {
return nil, errors.Wrap(err, "failed to parse WhiteSource response")
}
return wsResponse.ProductVitals, nil
}
// GetProductByName
func (s *System) GetProductByName(productName string) (*Product, error) {
var product Product
products, err := s.GetOrganizationProductVitals()
if err != nil {
return nil, errors.Wrap(err, "failed to getOrganizationProductVitals")
}
for _, prod := range products {
if prod.Name == productName {
product = prod
}
}
// returns nil, nil if no product was found
return &product, nil
}
// GetProjectAlerts
func (s *System) GetProjectAlerts(projectToken string) ([]Alert, error) {
wsResponse := struct {
Alerts []Alert `json:"alerts"`
}{
Alerts: []Alert{},
}
req := Request{
RequestType: "getProjectAlerts",
ProjectToken: projectToken,
}
respBody, err := s.sendRequest(req)
if err != nil {
return nil, errors.Wrap(err, "WhiteSource request failed")
}
err = json.Unmarshal(respBody, &wsResponse)
if err != nil {
return nil, errors.Wrap(err, "failed to parse WhiteSource response")
}
return wsResponse.Alerts, nil
}
// GetProjectLibraryLocations
func (s *System) GetProjectLibraryLocations(projectToken string) ([]Library, error) {
wsResponse := struct {
Libraries []Library `json:"libraryLocations"`
}{
Libraries: []Library{},
}
req := Request{
RequestType: "getProjectLibraryLocations",
ProjectToken: projectToken,
}
respBody, err := s.sendRequest(req)
if err != nil {
return nil, errors.Wrap(err, "WhiteSource request failed")
}
err = json.Unmarshal(respBody, &wsResponse)
if err != nil {
return nil, errors.Wrap(err, "failed to parse WhiteSource response")
}
return wsResponse.Libraries, nil
}
func (s *System) sendRequest(req Request) ([]byte, error) {
responseBody := []byte{}
var responseBody []byte
if req.UserKey == "" {
req.UserKey = s.UserToken
}

View File

@ -0,0 +1,563 @@
metadata:
name: whitesourceExecuteScan
description: BETA
longDescription: |-
BETA
With this step [WhiteSource](https://www.whitesourcesoftware.com) security and license compliance scans can be executed and assessed.
WhiteSource is a Software as a Service offering based on a so called unified agent that locally determines the dependency
tree of a node.js, Java, Python, Ruby, or Scala based solution and sends it to the WhiteSource server for a policy based license compliance
check and additional Free and Open Source Software Publicly Known Vulnerabilities detection.
!!! note "Docker Images"
The underlying Docker images are public and specific to the solution's programming language(s) and therefore may have to be exchanged
to fit to and support the relevant scenario. The default Python environment used is i.e. Python 3 based.
!!! warn "Restrictions"
Currently the step does contain hardened scan configurations for `scanType` `'pip'` and `'go'`. Other environments are still being elaborated,
so please thoroughly check your results and do not take them for granted by default.
Also not all environments have been thoroughly tested already therefore you might need to tweak around with the default containers used or
create your own ones to adequately support your scenario. To do so please modify `dockerImage` and `dockerWorkspace` parameters.
The step expects an environment containing the programming language related compiler/interpreter as well as the related build tool. For a list
of the supported build tools per environment please refer to the [WhiteSource Unified Agent Documentation](https://whitesource.atlassian.net/wiki/spaces/WD/pages/33718339/Unified+Agent).
spec:
inputs:
params:
- name: buildDescriptorFile
type: string
description: Explicit path to the build descriptor file.
mandatory: false
scope:
- PARAMETERS
- STAGES
- STEPS
default: null
conditions:
- conditionRef: strings-equal
params:
- name: scanType
value: golang
- name: buildDescriptorFile
type: string
description: Explicit path to the build descriptor file.
mandatory: false
scope:
- PARAMETERS
- STAGES
- STEPS
default: ./pom.xml
conditions:
- conditionRef: strings-equal
params:
- name: scanType
value: maven
- name: buildDescriptorFile
type: string
description: Explicit path to the build descriptor file.
mandatory: false
scope:
- PARAMETERS
- STAGES
- STEPS
default: null
conditions:
- conditionRef: strings-equal
params:
- name: scanType
value: mta
- name: buildDescriptorFile
type: string
description: Explicit path to the build descriptor file.
mandatory: false
scope:
- PARAMETERS
- STAGES
- STEPS
default: ./package.json
conditions:
- conditionRef: strings-equal
params:
- name: scanType
value: npm
- name: buildDescriptorFile
type: string
description: Explicit path to the build descriptor file.
mandatory: false
scope:
- PARAMETERS
- STAGES
- STEPS
default: ./setup.py
conditions:
- conditionRef: strings-equal
params:
- name: scanType
value: pip
- name: buildDescriptorFile
type: string
description: Explicit path to the build descriptor file.
mandatory: false
scope:
- PARAMETERS
- STAGES
- STEPS
default: ./build.sbt
conditions:
- conditionRef: strings-equal
params:
- name: scanType
value: sbt
- name: buildDescriptorFile
type: string
description: Explicit path to the build descriptor file.
mandatory: false
scope:
- PARAMETERS
- STAGES
- STEPS
default: ./dub.json
conditions:
- conditionRef: strings-equal
params:
- name: scanType
value: dub
- name: defaultVersioningModel
type: string
description: The default project versioning model used in case `projectVersion` parameter is empty for creating the version based on the build descriptor version to report results in Whitesource, can be one of `'major'`, `'major-minor'`, `'semantic'`, `'full'`
scope:
- PARAMETERS
- STAGES
- STEPS
default: 'major'
- name: createProductFromPipeline
type: bool
description: Whether to create the related WhiteSource product on the fly based on the supplied pipeline configuration.
mandatory: false
scope:
- PARAMETERS
- STAGES
- STEPS
default: true
- name: securityVulnerabilities
type: bool
description: Whether security compliance is considered and reported as part of the assessment.
mandatory: false
scope:
- PARAMETERS
- STAGES
- STEPS
default: true
- name: timeout
type: string
description: Timeout in seconds until a HTTP call is forcefully terminated.
mandatory: false
scope:
- PARAMETERS
- STAGES
- STEPS
default: 0
- name: agentDownloadUrl
type: string
description: URL used to download the latest version of the WhiteSource Unified Agent.
mandatory: false
scope:
- PARAMETERS
- STAGES
- STEPS
default: https://github.com/whitesource/unified-agent-distribution/releases/latest/download/wss-unified-agent.jar
- name: configFilePath
type: string
description: Explicit path to the WhiteSource Unified Agent configuration file.
mandatory: false
scope:
- PARAMETERS
- STAGES
- STEPS
default: ./wss-generated-file.config
- name: reportDirectoryName
type: string
description: Name of the directory to save vulnerability/risk reports to
mandatory: false
scope:
- PARAMETERS
- STAGES
- STEPS
default: "whitesource-reports"
- name: aggregateVersionWideReport
type: bool
description: 'This does not run a scan, instead just generated a report for all projects with projectVersion = config.ProductVersion'
mandatory: false
scope:
- PARAMETERS
- STAGES
- STEPS
default: false
- name: vulnerabilityReportFormat
type: string
description: Format of the file the vulnerability report is written to.
mandatory: false
possibleValues: [xlsx, json, xml]
scope:
- PARAMETERS
- STAGES
- STEPS
default: xlsx
- name: parallelLimit
type: string
description: 'Limit of parallel jobs being run at once in case of `scanType:
''mta''` based scenarios, defaults to `15`.'
mandatory: false
scope:
- PARAMETERS
- STAGES
- STEPS
default: 15
- name: reporting
type: bool
description: Whether assessment is being done at all, defaults to `true`.
mandatory: false
scope:
- PARAMETERS
- STAGES
- STEPS
default: true
- name: serviceUrl
type: string
description: URL to the WhiteSource server API used for communication.
mandatory: false
scope:
- GENERAL
- PARAMETERS
- STAGES
- STEPS
default: https://saas.whitesourcesoftware.com/api
- name: buildDescriptorExcludeList
type: string
description: List of build descriptors and therefore modules to exclude from the scan and assessment activities.
mandatory: false
scope:
- PARAMETERS
- STAGES
- STEPS
default: []
- name: orgToken
type: string
description: WhiteSource token identifying your organization.
mandatory: true
scope:
- GENERAL
- PARAMETERS
- STAGES
- STEPS
default: null
- name: userToken
type: string
description: WhiteSource token identifying the user executing the scan
mandatory: true
scope:
- GENERAL
- PARAMETERS
- STAGES
- STEPS
default: null
- name: licensingVulnerabilities
type: bool
description: Whether license compliance is considered and reported as part of the assessment.
mandatory: false
scope:
- PARAMETERS
- STAGES
- STEPS
default: true
- name: agentFileName
type: string
description: Locally used name for the Unified Agent jar file after download.
mandatory: false
scope:
- PARAMETERS
- STAGES
- STEPS
default: wss-unified-agent.jar
- name: emailAddressesOfInitialProductAdmins
type: string
description: The list of email addresses to assign as product admins for newly created WhiteSource products.
mandatory: false
scope:
- PARAMETERS
- STAGES
- STEPS
default: []
- name: productVersion
type: string
description: Version of the WhiteSource product to be created and used for results aggregation, usually determined automatically.
mandatory: false
scope:
- GENERAL
- PARAMETERS
- STAGES
- STEPS
default: null
- name: jreDownloadUrl
type: string
description: URL used for downloading the Java Runtime Environment (JRE) required to run the WhiteSource Unified Agent.
mandatory: false
scope:
- GENERAL
- PARAMETERS
- STAGES
- STEPS
default: null
- name: productName
type: string
description: Name of the WhiteSource product to be created and used for results aggregation.
mandatory: true
scope:
- GENERAL
- PARAMETERS
- STAGES
- STEPS
default: null
- name: projectName
aliases:
- name: whitesourceProjectName
type: string
description: "The project used for reporting results in Whitesource"
scope:
- PARAMETERS
- STAGES
- STEPS
default: '{{list .GroupID .ArtifactID | join "-" | trimAll "-"}}'
- name: projectToken
type: string
description: Project token to execute scan on
mandatory: false
scope:
- GENERAL
- PARAMETERS
- STAGES
- STEPS
default: null
- name: vulnerabilityReportTitle
type: string
description: Title of vulnerability report written during the assessment phase.
mandatory: false
scope:
- PARAMETERS
- STAGES
- STEPS
default: WhiteSource Security Vulnerability Report
- name: installCommand
type: string
description: Install command that can be used to populate the default docker image for some scenarios.
mandatory: false
scope:
- PARAMETERS
- STAGES
- STEPS
default: null
- name: scanType
type: string
description: Type of development stack used to implement the solution.
mandatory: false
scope:
- GENERAL
- PARAMETERS
- STAGES
- STEPS
default: null
possibleValues: ["golang", "npm", "gradle", "pip"]
- name: cvssSeverityLimit
type: string
description: Limit of tollerable CVSS v3 score upon assessment and in consequence fails the build, defaults to `-1`.
mandatory: false
scope:
- PARAMETERS
- STAGES
- STEPS
default: -1
- name: includes
type: string
description: Space separated list of file path patterns to include in the scan, slashes must be escaped for sed
mandatory: false
scope:
- PARAMETERS
- STAGES
- STEPS
default: '**\/src\/main\/**\/*.java **\/*.py **\/*.go **\/*.js **\/*.ts'
- name: excludes
type: string
description: Space separated list of file path patterns to exclude in the scan
mandatory: false
scope:
- PARAMETERS
- STAGES
- STEPS
default: 'tests/**/*.py **/src/test/**/*.java'
- name: productToken
type: string
description: Token of the WhiteSource product to be created and used for results aggregation, usually determined automatically.
mandatory: false
scope:
- GENERAL
- PARAMETERS
- STAGES
- STEPS
default: null
- name: agentParameters
type: string
description: Additional parameters passed to the Unified Agent command line.
mandatory: false
scope:
- PARAMETERS
- STAGES
- STEPS
default: ''
secrets:
- name: userTokenCredentialsId
type: jenkins
- name: orgAdminUserTokenCredentialsId
type: jenkins
resources:
- name: buildDescriptor
type: stash
conditions:
- conditionRef: strings-equal
params:
- name: scanType
value: golang
- name: opensourceConfiguration
type: stash
conditions:
- conditionRef: strings-equal
params:
- name: scanType
value: golang
- name: checkmarx
type: stash
conditions:
- conditionRef: strings-equal
params:
- name: scanType
value: golang
- name: buildDescriptor
type: stash
conditions:
- conditionRef: strings-equal
params:
- name: scanType
value: maven
- name: opensourceConfiguration
type: stash
conditions:
- conditionRef: strings-equal
params:
- name: scanType
value: maven
- name: buildDescriptor
type: stash
conditions:
- conditionRef: strings-equal
params:
- name: scanType
value: mta
- name: opensourceConfiguration
type: stash
conditions:
- conditionRef: strings-equal
params:
- name: scanType
value: mta
- name: buildDescriptor
type: stash
conditions:
- conditionRef: strings-equal
params:
- name: scanType
value: npm
- name: opensourceConfiguration
type: stash
conditions:
- conditionRef: strings-equal
params:
- name: scanType
value: npm
- name: buildDescriptor
type: stash
conditions:
- conditionRef: strings-equal
params:
- name: scanType
value: pip
- name: opensourceConfiguration
type: stash
conditions:
- conditionRef: strings-equal
params:
- name: scanType
value: pip
- name: buildDescriptor
type: stash
conditions:
- conditionRef: strings-equal
params:
- name: scanType
value: sbt
- name: opensourceConfiguration
type: stash
conditions:
- conditionRef: strings-equal
params:
- name: scanType
value: sbt
- name: buildDescriptor
type: stash
conditions:
- conditionRef: strings-equal
params:
- name: scanType
value: dub
- name: checkmarx
type: stash
conditions:
- conditionRef: strings-equal
params:
- name: scanType
value: dub
containers:
- image: maven:3.5-jdk-8
workingDir: /home/java
env: []
conditions:
- conditionRef: strings-equal
params:
- name: scanType
value: maven
- image: null
workingDir: null
env: []
conditions:
- conditionRef: strings-equal
params:
- name: scanType
value: mta
- image: node:lts-stretch
workingDir: /home/node
env: []
conditions:
- conditionRef: strings-equal
params:
- name: scanType
value: npm
- image: hseeberger/scala-sbt:8u181_2.12.8_1.2.8
workingDir: /home/scala
env: []
conditions:
- conditionRef: strings-equal
params:
- name: scanType
value: sbt
- image: buildpack-deps:stretch-curl
workingDir: /home/dub
env: []
conditions:
- conditionRef: strings-equal
params:
- name: scanType
value: dub