diff --git a/.github/workflows/documentation.yml b/.github/workflows/documentation.yml index 4da3319de9..180ace3631 100644 --- a/.github/workflows/documentation.yml +++ b/.github/workflows/documentation.yml @@ -23,7 +23,7 @@ jobs: - uses: actions/setup-go@v5 with: - go-version: '1.20.x' + go-version: '1.21.x' - name: Install Groovy run: sudo apt-get update && sudo apt-get install groovy -y diff --git a/.github/workflows/update-go-dependencies.yml b/.github/workflows/update-go-dependencies.yml index 01338856bd..8f62a4be87 100644 --- a/.github/workflows/update-go-dependencies.yml +++ b/.github/workflows/update-go-dependencies.yml @@ -13,7 +13,7 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: - go-version: '1.20.x' + go-version: '1.21.x' - name: Perform update run: | git checkout -B gh-action-update-golang-dependencies diff --git a/.github/workflows/upload-go-master.yml b/.github/workflows/upload-go-master.yml index 022cf76f81..247b180b96 100644 --- a/.github/workflows/upload-go-master.yml +++ b/.github/workflows/upload-go-master.yml @@ -13,7 +13,7 @@ jobs: - uses: actions/checkout@v4 - uses: actions/setup-go@v5 with: - go-version: '1.20.x' + go-version: '1.21.x' - env: CGO_ENABLED: 0 run: | diff --git a/.github/workflows/verify-go.yml b/.github/workflows/verify-go.yml index 680cad31f0..8c63864fb1 100644 --- a/.github/workflows/verify-go.yml +++ b/.github/workflows/verify-go.yml @@ -15,7 +15,7 @@ jobs: - uses: styfle/cancel-workflow-action@0.11.0 - uses: actions/setup-go@v5 with: - go-version: '1.20.x' + go-version: '1.21.x' - name: Cache Golang Packages uses: actions/cache@v3 with: @@ -43,7 +43,7 @@ jobs: steps: - uses: actions/setup-go@v5 with: - go-version: '1.20.x' + go-version: '1.21.x' - name: Cache Golang Packages uses: actions/cache@v3 with: @@ -63,8 +63,7 @@ jobs: steps: - uses: actions/setup-go@v5 with: - go-version: '1.20.x' - # action requires go@1.20 + go-version: '1.21.x' - name: checkout uses: actions/checkout@v4 with: @@ -79,7 +78,7 @@ jobs: steps: - uses: actions/setup-go@v5 with: - go-version: '1.20.x' + go-version: '1.21.x' - name: Cache Golang Packages uses: actions/cache@v3 with: @@ -99,7 +98,7 @@ jobs: steps: - uses: actions/setup-go@v5 with: - go-version: '1.20.x' + go-version: '1.21.x' - name: Cache Golang Packages uses: actions/cache@v3 with: diff --git a/Dockerfile b/Dockerfile index 80920d2488..bf79b06b4e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.20 AS build-env +FROM golang:1.21 AS build-env COPY . /build WORKDIR /build diff --git a/cmd/abapAddonAssemblyKitCheck.go b/cmd/abapAddonAssemblyKitCheck.go new file mode 100644 index 0000000000..923c27631c --- /dev/null +++ b/cmd/abapAddonAssemblyKitCheck.go @@ -0,0 +1,94 @@ +package cmd + +import ( + "github.com/SAP/jenkins-library/pkg/abap/aakaas" + abapbuild "github.com/SAP/jenkins-library/pkg/abap/build" + "github.com/SAP/jenkins-library/pkg/abaputils" + "github.com/SAP/jenkins-library/pkg/log" + "github.com/SAP/jenkins-library/pkg/piperutils" + "github.com/SAP/jenkins-library/pkg/telemetry" +) + +func abapAddonAssemblyKitCheck(config abapAddonAssemblyKitCheckOptions, telemetryData *telemetry.CustomData, commonPipelineEnvironment *abapAddonAssemblyKitCheckCommonPipelineEnvironment) { + utils := aakaas.NewAakBundle() + + err := runAbapAddonAssemblyKitCheck(&config, telemetryData, utils, commonPipelineEnvironment) + if err != nil { + log.Entry().WithError(err).Fatal("step execution failed") + } +} + +func runAbapAddonAssemblyKitCheck(config *abapAddonAssemblyKitCheckOptions, telemetryData *telemetry.CustomData, utils aakaas.AakUtils, commonPipelineEnvironment *abapAddonAssemblyKitCheckCommonPipelineEnvironment) error { + + log.Entry().Info("╔═══════════════════════════╗") + log.Entry().Info("║ abapAddonAssemblyKitCheck ║") + log.Entry().Info("╚═══════════════════════════╝") + + conn := new(abapbuild.Connector) + if err := conn.InitAAKaaS(config.AbapAddonAssemblyKitEndpoint, config.Username, config.Password, utils, "", config.AbapAddonAssemblyKitCertificateFile, config.AbapAddonAssemblyKitCertificatePass); err != nil { + return err + } + + log.Entry().Infof("reading addonDescriptor (aka addon.yml) file: %s", config.AddonDescriptorFileName) + addonDescriptor, err := utils.ReadAddonDescriptor(config.AddonDescriptorFileName) + if err != nil { + return err + } + log.Entry().Info("building product modelling (and resolving potential wildcards)") + pvh, err := aakaas.NewProductVersionHeader(&addonDescriptor, conn) + if err != nil { + return err + } + printProductVersionHeader(*pvh) + + log.Entry().Info("calling AAKaaS to check product modelling...") + if err := pvh.CheckAndResolveVersion(conn); err != nil { + return err + } + log.Entry().Info("... success!") + pvh.SyncAddonDescriptorVersionFields(&addonDescriptor) + log.Entry().Info("resolved version fields:") + printAddonDescriptorVersionFields(addonDescriptor) + log.Entry().Info("transferring addonDescriptor to commonPipelineEnvironment for usage by subsequent steps of the pipeline") + commonPipelineEnvironment.abap.addonDescriptor = string(addonDescriptor.AsJSON()) + + publishAddonYaml(config, utils) + return nil +} + +func printProductVersionHeader(pvh aakaas.ProductVersionHeader) { + logLine30 := "──────────────────────────────" + log.Entry().Infof("┌─%-30v─┬─%-30v─┐", logLine30, logLine30) + log.Entry().Infof("│ %-30v │ %-30v │", "Product Name", pvh.ProductName) + log.Entry().Infof("│ %-30v │ %-30v │", "Product Version", pvh.SemanticProductVersion) + log.Entry().Infof("├─%-30v─┼─%-30v─┤", logLine30, logLine30) + log.Entry().Infof("│ %-30v │ %-30v │", "Software Component Name", "Software Component Version") + log.Entry().Infof("├─%-30v─┼─%-30v─┤", logLine30, logLine30) + for _, pvc := range pvh.Content { + log.Entry().Infof("│ %-30v │ %-30v │", pvc.SoftwareComponentName, pvc.SemanticSoftwareComponentVersion) + } + log.Entry().Infof("└─%-30v─┴─%-30v─┘", logLine30, logLine30) +} + +func printAddonDescriptorVersionFields(addonDescriptor abaputils.AddonDescriptor) { + logLine30 := "──────────────────────────────" + logLine4 := "────" + log.Entry().Infof("┌─%-30v─┬─%-4v─┬─%-4v─┬─%-4v─┐", logLine30, logLine4, logLine4, logLine4) + log.Entry().Infof("│ %-30v │ %-4v │ %-4v │ %-4v │", "Name", "Vers", "SP", "Pat.") + log.Entry().Infof("├─%-30v─┼─%-4v─┼─%-4v─┼─%-4v─┤", logLine30, logLine4, logLine4, logLine4) + log.Entry().Infof("│ %-30v │ %-4v │ %-4v │ %-4v │", addonDescriptor.AddonProduct, addonDescriptor.AddonVersion, addonDescriptor.AddonSpsLevel, addonDescriptor.AddonPatchLevel) + for _, repo := range addonDescriptor.Repositories { + log.Entry().Infof("│ %-30v │ %-4v │ %-4v │ %-4v │", repo.Name, repo.Version, repo.SpLevel, repo.PatchLevel) + } + log.Entry().Infof("└─%-30v─┴─%-4v─┴─%-4v─┴─%-4v─┘", logLine30, logLine4, logLine4, logLine4) +} + +func publishAddonYaml(config *abapAddonAssemblyKitCheckOptions, utils aakaas.AakUtils) { + var filesToPublish []piperutils.Path + log.Entry().Infof("adding %s to be published", config.AddonDescriptorFileName) + filesToPublish = append(filesToPublish, piperutils.Path{Target: config.AddonDescriptorFileName, Name: "AddonDescriptor", Mandatory: true}) + log.Entry().Infof("publishing %v files", len(filesToPublish)) + if err := piperutils.PersistReportsAndLinks("abapAddonAssemblyKitCheckPV", "", utils, filesToPublish, nil); err != nil { + log.Entry().WithError(err).Error("failed to persist report information") + } +} diff --git a/cmd/abapAddonAssemblyKitCheck_generated.go b/cmd/abapAddonAssemblyKitCheck_generated.go new file mode 100644 index 0000000000..e153d4e165 --- /dev/null +++ b/cmd/abapAddonAssemblyKitCheck_generated.go @@ -0,0 +1,295 @@ +// Code generated by piper's step-generator. DO NOT EDIT. + +package cmd + +import ( + "fmt" + "os" + "path/filepath" + "time" + + "github.com/SAP/jenkins-library/pkg/config" + "github.com/SAP/jenkins-library/pkg/log" + "github.com/SAP/jenkins-library/pkg/piperenv" + "github.com/SAP/jenkins-library/pkg/splunk" + "github.com/SAP/jenkins-library/pkg/telemetry" + "github.com/SAP/jenkins-library/pkg/validation" + "github.com/spf13/cobra" +) + +type abapAddonAssemblyKitCheckOptions struct { + AbapAddonAssemblyKitCertificateFile string `json:"abapAddonAssemblyKitCertificateFile,omitempty"` + AbapAddonAssemblyKitCertificatePass string `json:"abapAddonAssemblyKitCertificatePass,omitempty"` + AbapAddonAssemblyKitEndpoint string `json:"abapAddonAssemblyKitEndpoint,omitempty"` + Username string `json:"username,omitempty"` + Password string `json:"password,omitempty"` + AddonDescriptorFileName string `json:"addonDescriptorFileName,omitempty"` + AddonDescriptor string `json:"addonDescriptor,omitempty"` +} + +type abapAddonAssemblyKitCheckCommonPipelineEnvironment struct { + abap struct { + addonDescriptor string + } +} + +func (p *abapAddonAssemblyKitCheckCommonPipelineEnvironment) persist(path, resourceName string) { + content := []struct { + category string + name string + value interface{} + }{ + {category: "abap", name: "addonDescriptor", value: p.abap.addonDescriptor}, + } + + errCount := 0 + for _, param := range content { + err := piperenv.SetResourceParameter(path, resourceName, filepath.Join(param.category, param.name), param.value) + if err != nil { + log.Entry().WithError(err).Error("Error persisting piper environment.") + errCount++ + } + } + if errCount > 0 { + log.Entry().Error("failed to persist Piper environment") + } +} + +// AbapAddonAssemblyKitCheckCommand This step calls AAKaaS to check the validity of the Addon Product Modelling. +func AbapAddonAssemblyKitCheckCommand() *cobra.Command { + const STEP_NAME = "abapAddonAssemblyKitCheck" + + metadata := abapAddonAssemblyKitCheckMetadata() + var stepConfig abapAddonAssemblyKitCheckOptions + var startTime time.Time + var commonPipelineEnvironment abapAddonAssemblyKitCheckCommonPipelineEnvironment + var logCollector *log.CollectorHook + var splunkClient *splunk.Splunk + telemetryClient := &telemetry.Telemetry{} + + var createAbapAddonAssemblyKitCheckCmd = &cobra.Command{ + Use: STEP_NAME, + Short: "This step calls AAKaaS to check the validity of the Addon Product Modelling.", + Long: `This step does the following: +
+For logon to AAKaaS you can either provide a credential with basic authorization (username and password) or two secret text credentials containing the technical s-users certificate (see note [2805811](https://me.sap.com/notes/2805811) for download) as base64 encoded string and the password to decrypt the file +
+For Terminology refer to the [Scenario Description](https://www.project-piper.io/scenarios/abapEnvironmentAddons/).`, + PreRunE: func(cmd *cobra.Command, _ []string) error { + startTime = time.Now() + log.SetStepName(STEP_NAME) + log.SetVerbose(GeneralConfig.Verbose) + + GeneralConfig.GitHubAccessTokens = ResolveAccessTokens(GeneralConfig.GitHubTokens) + + path, _ := os.Getwd() + fatalHook := &log.FatalHook{CorrelationID: GeneralConfig.CorrelationID, Path: path} + log.RegisterHook(fatalHook) + + err := PrepareConfig(cmd, &metadata, STEP_NAME, &stepConfig, config.OpenPiperFile) + if err != nil { + log.SetErrorCategory(log.ErrorConfiguration) + return err + } + log.RegisterSecret(stepConfig.AbapAddonAssemblyKitCertificateFile) + log.RegisterSecret(stepConfig.AbapAddonAssemblyKitCertificatePass) + log.RegisterSecret(stepConfig.Username) + log.RegisterSecret(stepConfig.Password) + + if len(GeneralConfig.HookConfig.SentryConfig.Dsn) > 0 { + sentryHook := log.NewSentryHook(GeneralConfig.HookConfig.SentryConfig.Dsn, GeneralConfig.CorrelationID) + log.RegisterHook(&sentryHook) + } + + if len(GeneralConfig.HookConfig.SplunkConfig.Dsn) > 0 || len(GeneralConfig.HookConfig.SplunkConfig.ProdCriblEndpoint) > 0 { + splunkClient = &splunk.Splunk{} + logCollector = &log.CollectorHook{CorrelationID: GeneralConfig.CorrelationID} + log.RegisterHook(logCollector) + } + + if err = log.RegisterANSHookIfConfigured(GeneralConfig.CorrelationID); err != nil { + log.Entry().WithError(err).Warn("failed to set up SAP Alert Notification Service log hook") + } + + validation, err := validation.New(validation.WithJSONNamesForStructFields(), validation.WithPredefinedErrorMessages()) + if err != nil { + return err + } + if err = validation.ValidateStruct(stepConfig); err != nil { + log.SetErrorCategory(log.ErrorConfiguration) + return err + } + + return nil + }, + Run: func(_ *cobra.Command, _ []string) { + stepTelemetryData := telemetry.CustomData{} + stepTelemetryData.ErrorCode = "1" + handler := func() { + commonPipelineEnvironment.persist(GeneralConfig.EnvRootPath, "commonPipelineEnvironment") + config.RemoveVaultSecretFiles() + stepTelemetryData.Duration = fmt.Sprintf("%v", time.Since(startTime).Milliseconds()) + stepTelemetryData.ErrorCategory = log.GetErrorCategory().String() + stepTelemetryData.PiperCommitHash = GitCommit + telemetryClient.SetData(&stepTelemetryData) + telemetryClient.Send() + if len(GeneralConfig.HookConfig.SplunkConfig.Dsn) > 0 { + splunkClient.Initialize(GeneralConfig.CorrelationID, + GeneralConfig.HookConfig.SplunkConfig.Dsn, + GeneralConfig.HookConfig.SplunkConfig.Token, + GeneralConfig.HookConfig.SplunkConfig.Index, + GeneralConfig.HookConfig.SplunkConfig.SendLogs) + splunkClient.Send(telemetryClient.GetData(), logCollector) + } + if len(GeneralConfig.HookConfig.SplunkConfig.ProdCriblEndpoint) > 0 { + splunkClient.Initialize(GeneralConfig.CorrelationID, + GeneralConfig.HookConfig.SplunkConfig.ProdCriblEndpoint, + GeneralConfig.HookConfig.SplunkConfig.ProdCriblToken, + GeneralConfig.HookConfig.SplunkConfig.ProdCriblIndex, + GeneralConfig.HookConfig.SplunkConfig.SendLogs) + splunkClient.Send(telemetryClient.GetData(), logCollector) + } + } + log.DeferExitHandler(handler) + defer handler() + telemetryClient.Initialize(GeneralConfig.NoTelemetry, STEP_NAME, GeneralConfig.HookConfig.PendoConfig.Token) + abapAddonAssemblyKitCheck(stepConfig, &stepTelemetryData, &commonPipelineEnvironment) + stepTelemetryData.ErrorCode = "0" + log.Entry().Info("SUCCESS") + }, + } + + addAbapAddonAssemblyKitCheckFlags(createAbapAddonAssemblyKitCheckCmd, &stepConfig) + return createAbapAddonAssemblyKitCheckCmd +} + +func addAbapAddonAssemblyKitCheckFlags(cmd *cobra.Command, stepConfig *abapAddonAssemblyKitCheckOptions) { + cmd.Flags().StringVar(&stepConfig.AbapAddonAssemblyKitCertificateFile, "abapAddonAssemblyKitCertificateFile", os.Getenv("PIPER_abapAddonAssemblyKitCertificateFile"), "base64 encoded certificate pfx file (PKCS12 format) see note [2805811](https://me.sap.com/notes/2805811)") + cmd.Flags().StringVar(&stepConfig.AbapAddonAssemblyKitCertificatePass, "abapAddonAssemblyKitCertificatePass", os.Getenv("PIPER_abapAddonAssemblyKitCertificatePass"), "password to decrypt the certificate file") + cmd.Flags().StringVar(&stepConfig.AbapAddonAssemblyKitEndpoint, "abapAddonAssemblyKitEndpoint", `https://apps.support.sap.com`, "Base URL to the Addon Assembly Kit as a Service (AAKaaS) system") + cmd.Flags().StringVar(&stepConfig.Username, "username", os.Getenv("PIPER_username"), "User for the Addon Assembly Kit as a Service (AAKaaS) system") + cmd.Flags().StringVar(&stepConfig.Password, "password", os.Getenv("PIPER_password"), "Password for the Addon Assembly Kit as a Service (AAKaaS) system") + cmd.Flags().StringVar(&stepConfig.AddonDescriptorFileName, "addonDescriptorFileName", `addon.yml`, "File name of the YAML file which describes the Product Version and corresponding Software Component Versions") + cmd.Flags().StringVar(&stepConfig.AddonDescriptor, "addonDescriptor", os.Getenv("PIPER_addonDescriptor"), "Structure in the commonPipelineEnvironment containing information about the Product Version and corresponding Software Component Versions") + + cmd.MarkFlagRequired("abapAddonAssemblyKitEndpoint") + cmd.MarkFlagRequired("addonDescriptorFileName") +} + +// retrieve step metadata +func abapAddonAssemblyKitCheckMetadata() config.StepData { + var theMetaData = config.StepData{ + Metadata: config.StepMetadata{ + Name: "abapAddonAssemblyKitCheck", + Aliases: []config.Alias{}, + Description: "This step calls AAKaaS to check the validity of the Addon Product Modelling.", + }, + Spec: config.StepSpec{ + Inputs: config.StepInputs{ + Secrets: []config.StepSecrets{ + {Name: "abapAddonAssemblyKitCredentialsId", Description: "CredentialsId stored in Jenkins for the Addon Assembly Kit as a Service (AAKaaS) system", Type: "jenkins"}, + {Name: "abapAddonAssemblyKitCertificateFileCredentialsId", Description: "Jenkins secret text credential ID containing the base64 encoded certificate pfx file (PKCS12 format) see note [2805811](https://me.sap.com/notes/2805811)", Type: "jenkins"}, + {Name: "abapAddonAssemblyKitCertificatePassCredentialsId", Description: "Jenkins secret text credential ID containing the password to decrypt the certificate file stored in abapAddonAssemblyKitCertificateFileCredentialsId", Type: "jenkins"}, + }, + Parameters: []config.StepParameters{ + { + Name: "abapAddonAssemblyKitCertificateFile", + ResourceRef: []config.ResourceReference{ + { + Name: "abapAddonAssemblyKitCertificateFileCredentialsId", + Param: "abapAddonAssemblyKitCertificateFile", + Type: "secret", + }, + }, + Scope: []string{"PARAMETERS"}, + Type: "string", + Mandatory: false, + Aliases: []config.Alias{}, + Default: os.Getenv("PIPER_abapAddonAssemblyKitCertificateFile"), + }, + { + Name: "abapAddonAssemblyKitCertificatePass", + ResourceRef: []config.ResourceReference{ + { + Name: "abapAddonAssemblyKitCertificatePassCredentialsId", + Param: "abapAddonAssemblyKitCertificatePass", + Type: "secret", + }, + }, + Scope: []string{"PARAMETERS"}, + Type: "string", + Mandatory: false, + Aliases: []config.Alias{}, + Default: os.Getenv("PIPER_abapAddonAssemblyKitCertificatePass"), + }, + { + Name: "abapAddonAssemblyKitEndpoint", + ResourceRef: []config.ResourceReference{}, + Scope: []string{"PARAMETERS", "STAGES", "STEPS", "GENERAL"}, + Type: "string", + Mandatory: true, + Aliases: []config.Alias{}, + Default: `https://apps.support.sap.com`, + }, + { + Name: "username", + ResourceRef: []config.ResourceReference{}, + Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, + Type: "string", + Mandatory: false, + Aliases: []config.Alias{}, + Default: os.Getenv("PIPER_username"), + }, + { + Name: "password", + ResourceRef: []config.ResourceReference{}, + Scope: []string{"PARAMETERS"}, + Type: "string", + Mandatory: false, + Aliases: []config.Alias{}, + Default: os.Getenv("PIPER_password"), + }, + { + Name: "addonDescriptorFileName", + ResourceRef: []config.ResourceReference{}, + Scope: []string{"PARAMETERS", "STAGES", "STEPS", "GENERAL"}, + Type: "string", + Mandatory: true, + Aliases: []config.Alias{}, + Default: `addon.yml`, + }, + { + Name: "addonDescriptor", + ResourceRef: []config.ResourceReference{ + { + Name: "commonPipelineEnvironment", + Param: "abap/addonDescriptor", + }, + }, + Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, + Type: "string", + Mandatory: false, + Aliases: []config.Alias{}, + Default: os.Getenv("PIPER_addonDescriptor"), + }, + }, + }, + Outputs: config.StepOutputs{ + Resources: []config.StepResources{ + { + Name: "commonPipelineEnvironment", + Type: "piperEnvironment", + Parameters: []map[string]interface{}{ + {"name": "abap/addonDescriptor"}, + }, + }, + }, + }, + }, + } + return theMetaData +} diff --git a/cmd/abapAddonAssemblyKitCheck_generated_test.go b/cmd/abapAddonAssemblyKitCheck_generated_test.go new file mode 100644 index 0000000000..0cbf7de791 --- /dev/null +++ b/cmd/abapAddonAssemblyKitCheck_generated_test.go @@ -0,0 +1,20 @@ +//go:build unit +// +build unit + +package cmd + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestAbapAddonAssemblyKitCheckCommand(t *testing.T) { + t.Parallel() + + testCmd := AbapAddonAssemblyKitCheckCommand() + + // only high level testing performed - details are tested in step generation procedure + assert.Equal(t, "abapAddonAssemblyKitCheck", testCmd.Use, "command name incorrect") + +} diff --git a/cmd/abapAddonAssemblyKitCheck_test.go b/cmd/abapAddonAssemblyKitCheck_test.go new file mode 100644 index 0000000000..a9b2f41fbe --- /dev/null +++ b/cmd/abapAddonAssemblyKitCheck_test.go @@ -0,0 +1,60 @@ +//go:build unit +// +build unit + +package cmd + +import ( + "testing" + + "github.com/SAP/jenkins-library/pkg/abap/aakaas" + "github.com/SAP/jenkins-library/pkg/abaputils" + "github.com/stretchr/testify/assert" +) + +func TestRunAbapAddonAssemblyKitCheck(t *testing.T) { + var config abapAddonAssemblyKitCheckOptions + var cpe abapAddonAssemblyKitCheckCommonPipelineEnvironment + bundle := aakaas.NewAakBundleMock() + utils := bundle.GetUtils() + config.Username = "dummyUser" + config.Password = "dummyPassword" + + t.Run("happy path", func(t *testing.T) { + config.AddonDescriptorFileName = "addon.yml.mock" + bundle.SetBody(aakaas.ResponseCheck) + bundle.MockAddonDescriptor = abaputils.AddonDescriptor{ + AddonProduct: "/DRNMSPC/PRD01", + AddonVersionYAML: "2.0.0", + Repositories: []abaputils.Repository{ + { + Name: "/DRNMSPC/COMP01", + VersionYAML: "2.0.0", + }, + { + Name: "/DRNMSPC/COMP02", + VersionYAML: "1.0.0", + }, + }, + } + + err := runAbapAddonAssemblyKitCheck(&config, nil, utils, &cpe) + + assert.NoError(t, err) + }) + + t.Run("error path", func(t *testing.T) { + config.AddonDescriptorFileName = "addon.yml.mock" + bundle.SetBody(aakaas.ResponseCheck) + bundle.MockAddonDescriptor = abaputils.AddonDescriptor{ + AddonProduct: "/DRNMSPC/PRD01", + AddonVersionYAML: "2.0.0", + Repositories: []abaputils.Repository{ + //no repos should fail during pvh creation... + }, + } + + err := runAbapAddonAssemblyKitCheck(&config, nil, utils, &cpe) + + assert.EqualError(t, err, "addonDescriptor must contain at least one software component repository") + }) +} diff --git a/cmd/abapEnvironmentAssemblePackages.go b/cmd/abapEnvironmentAssemblePackages.go index 4ee80e2045..5b4a8f6395 100644 --- a/cmd/abapEnvironmentAssemblePackages.go +++ b/cmd/abapEnvironmentAssemblePackages.go @@ -50,7 +50,7 @@ func runAbapEnvironmentAssemblePackages(config *abapEnvironmentAssemblePackagesO return errors.Wrap(err, "Reading AddonDescriptor failed [Make sure abapAddonAssemblyKit...CheckCVs|CheckPV|ReserveNextPackages steps have been run before]") } - builds, err := executeBuilds(addonDescriptor.Repositories, *connBuild, time.Duration(config.MaxRuntimeInMinutes)*time.Minute, time.Duration(config.PollIntervalsInMilliseconds)*time.Millisecond) + builds, err := executeBuilds(addonDescriptor, *connBuild, time.Duration(config.MaxRuntimeInMinutes)*time.Minute, time.Duration(config.PollIntervalsInMilliseconds)*time.Millisecond) if err != nil { return errors.Wrap(err, "Starting Builds for Repositories with reserved AAKaaS packages failed") } @@ -84,10 +84,10 @@ func runAbapEnvironmentAssemblePackages(config *abapEnvironmentAssemblePackagesO return nil } -func executeBuilds(repos []abaputils.Repository, conn abapbuild.Connector, maxRuntimeInMinutes time.Duration, pollInterval time.Duration) ([]buildWithRepository, error) { +func executeBuilds(addonDescriptor *abaputils.AddonDescriptor, conn abapbuild.Connector, maxRuntimeInMinutes time.Duration, pollInterval time.Duration) ([]buildWithRepository, error) { var builds []buildWithRepository - for _, repo := range repos { + for _, repo := range addonDescriptor.Repositories { buildRepo := buildWithRepository{ build: abapbuild.Build{ @@ -98,7 +98,7 @@ func executeBuilds(repos []abaputils.Repository, conn abapbuild.Connector, maxRu if repo.Status == "P" { buildRepo.repo.InBuildScope = true - err := buildRepo.start() + err := buildRepo.start(addonDescriptor) if err != nil { buildRepo.build.RunState = abapbuild.Failed log.Entry().Error(err) @@ -140,7 +140,7 @@ func (br *buildWithRepository) waitToBeFinished(maxRuntimeInMinutes time.Duratio } } -func (br *buildWithRepository) start() error { +func (br *buildWithRepository) start(addonDescriptor *abaputils.AddonDescriptor) error { if br.repo.Name == "" || br.repo.Version == "" || br.repo.SpLevel == "" || br.repo.PackageType == "" || br.repo.PackageName == "" { return errors.New("Parameters missing. Please provide software component name, version, sp-level, packagetype and packagename") } @@ -166,6 +166,10 @@ func (br *buildWithRepository) start() error { ValueID: "PACKAGE_NAME_" + br.repo.PackageType, Value: br.repo.PackageName, }, + { + ValueID: "addonDescriptor", + Value: addonDescriptor.AsReducedJson(), + }, }, } if br.repo.Namespace != "" { diff --git a/cmd/abapEnvironmentAssemblePackages_test.go b/cmd/abapEnvironmentAssemblePackages_test.go index 201a3109ac..c7692d6dc2 100644 --- a/cmd/abapEnvironmentAssemblePackages_test.go +++ b/cmd/abapEnvironmentAssemblePackages_test.go @@ -64,13 +64,15 @@ func TestStartingInvalidInput(t *testing.T) { conn := new(abapbuild.Connector) conn.Client = client conn.Header = make(map[string][]string) - var repos []abaputils.Repository - repo := abaputils.Repository{ - Name: "RepoA", - Status: "P", + aD := abaputils.AddonDescriptor{ + Repositories: []abaputils.Repository{ + { + Name: "RepoA", + Status: "P", + }, + }, } - repos = append(repos, repo) - builds, err := executeBuilds(repos, *conn, time.Duration(0*time.Second), time.Duration(1*time.Millisecond)) + builds, err := executeBuilds(&aD, *conn, time.Duration(0*time.Second), time.Duration(1*time.Millisecond)) assert.NoError(t, err) assert.Equal(t, 1, len(builds)) assert.Equal(t, abapbuild.Failed, builds[0].build.RunState) @@ -95,7 +97,7 @@ func TestStep(t *testing.T) { err := runAbapEnvironmentAssemblePackages(config, nil, autils, &mock.FilesMock{}, &client, cpe) assert.NoError(t, err) - assert.Contains(t, cpe.abap.addonDescriptor, `"InBuildScope":false`) + assert.NotContains(t, cpe.abap.addonDescriptor, `"InBuildScope"`) }) t.Run("abapEnvironmentAssemblePackages: build", func(t *testing.T) { config := &abapEnvironmentAssemblePackagesOptions{ diff --git a/cmd/artifactPrepareVersion.go b/cmd/artifactPrepareVersion.go index 182ca382f8..b8383c46d0 100644 --- a/cmd/artifactPrepareVersion.go +++ b/cmd/artifactPrepareVersion.go @@ -114,13 +114,14 @@ func runArtifactPrepareVersion(config *artifactPrepareVersionOptions, telemetryD // Options for artifact artifactOpts := versioning.Options{ - GlobalSettingsFile: config.GlobalSettingsFile, - M2Path: config.M2Path, - ProjectSettingsFile: config.ProjectSettingsFile, - VersionField: config.CustomVersionField, - VersionSection: config.CustomVersionSection, - VersioningScheme: config.CustomVersioningScheme, - VersionSource: config.DockerVersionSource, + GlobalSettingsFile: config.GlobalSettingsFile, + M2Path: config.M2Path, + ProjectSettingsFile: config.ProjectSettingsFile, + VersionField: config.CustomVersionField, + VersionSection: config.CustomVersionSection, + VersioningScheme: config.CustomVersioningScheme, + VersionSource: config.DockerVersionSource, + CAPVersioningPreference: config.CAPVersioningPreference, } var err error @@ -141,6 +142,9 @@ func runArtifactPrepareVersion(config *artifactPrepareVersionOptions, telemetryD if err != nil { log.SetErrorCategory(log.ErrorConfiguration) return errors.Wrap(err, "failed to retrieve version") + } else if len(version) == 0 { + log.SetErrorCategory(log.ErrorConfiguration) + return fmt.Errorf("version is empty - please check versioning configuration") } log.Entry().Infof("Version before automatic versioning: %v", version) diff --git a/cmd/artifactPrepareVersion_generated.go b/cmd/artifactPrepareVersion_generated.go index e2a7873e1a..7953e72522 100644 --- a/cmd/artifactPrepareVersion_generated.go +++ b/cmd/artifactPrepareVersion_generated.go @@ -20,7 +20,7 @@ import ( type artifactPrepareVersionOptions struct { AdditionalTargetTools []string `json:"additionalTargetTools,omitempty" validate:"possible-values=custom docker dub golang gradle helm maven mta npm pip sbt yarn"` AdditionalTargetDescriptors []string `json:"additionalTargetDescriptors,omitempty"` - BuildTool string `json:"buildTool,omitempty" validate:"possible-values=custom docker dub golang gradle helm maven mta npm pip sbt yarn"` + BuildTool string `json:"buildTool,omitempty" validate:"possible-values=custom docker dub golang gradle helm maven mta npm pip sbt yarn CAP"` CommitUserName string `json:"commitUserName,omitempty"` CustomVersionField string `json:"customVersionField,omitempty"` CustomVersionSection string `json:"customVersionSection,omitempty"` @@ -28,6 +28,7 @@ type artifactPrepareVersionOptions struct { DockerVersionSource string `json:"dockerVersionSource,omitempty"` FetchCoordinates bool `json:"fetchCoordinates,omitempty"` FilePath string `json:"filePath,omitempty"` + CAPVersioningPreference string `json:"CAPVersioningPreference,omitempty" validate:"possible-values=maven npm,required_if=BuildTool CAP"` GlobalSettingsFile string `json:"globalSettingsFile,omitempty"` IncludeCommitID bool `json:"includeCommitId,omitempty"` IsOptimizedAndScheduled bool `json:"isOptimizedAndScheduled,omitempty"` @@ -260,6 +261,7 @@ func addArtifactPrepareVersionFlags(cmd *cobra.Command, stepConfig *artifactPrep cmd.Flags().StringVar(&stepConfig.DockerVersionSource, "dockerVersionSource", os.Getenv("PIPER_dockerVersionSource"), "For `buildTool: docker`: Defines the source of the version. Can be `FROM`, any supported _buildTool_ or an environment variable name.") cmd.Flags().BoolVar(&stepConfig.FetchCoordinates, "fetchCoordinates", false, "If set to `true` the step will retreive artifact coordinates and store them in the common pipeline environment.") cmd.Flags().StringVar(&stepConfig.FilePath, "filePath", os.Getenv("PIPER_filePath"), "Defines a custom path to the descriptor file. Build tool specific defaults are used (e.g. `maven: pom.xml`, `npm: package.json`, `mta: mta.yaml`).") + cmd.Flags().StringVar(&stepConfig.CAPVersioningPreference, "CAPVersioningPreference", `maven`, "For CAP build tool only: Defines which file should be used for versioning.") cmd.Flags().StringVar(&stepConfig.GlobalSettingsFile, "globalSettingsFile", os.Getenv("PIPER_globalSettingsFile"), "Maven only - Path to the mvn settings file that should be used as global settings file.") cmd.Flags().BoolVar(&stepConfig.IncludeCommitID, "includeCommitId", true, "Defines if the automatically generated version (`versioningType: cloud`) should include the commit id hash.") cmd.Flags().BoolVar(&stepConfig.IsOptimizedAndScheduled, "isOptimizedAndScheduled", false, "Whether the pipeline runs in optimized mode and the current execution is a scheduled one") @@ -382,6 +384,15 @@ func artifactPrepareVersionMetadata() config.StepData { Aliases: []config.Alias{}, Default: os.Getenv("PIPER_filePath"), }, + { + Name: "CAPVersioningPreference", + ResourceRef: []config.ResourceReference{}, + Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, + Type: "string", + Mandatory: false, + Aliases: []config.Alias{}, + Default: `maven`, + }, { Name: "globalSettingsFile", ResourceRef: []config.ResourceReference{}, @@ -533,6 +544,7 @@ func artifactPrepareVersionMetadata() config.StepData { }, Containers: []config.Container{ {Image: "maven:3.6-jdk-8", Conditions: []config.Condition{{ConditionRef: "strings-equal", Params: []config.Param{{Name: "buildTool", Value: "maven"}}}}}, + {Image: "maven:3.6-jdk-8", Conditions: []config.Condition{{ConditionRef: "strings-equal", Params: []config.Param{{Name: "buildTool", Value: "CAP"}}}}}, }, Outputs: config.StepOutputs{ Resources: []config.StepResources{ diff --git a/cmd/checkmarxOneExecuteScan.go b/cmd/checkmarxOneExecuteScan.go index af790a3487..24731bc674 100644 --- a/cmd/checkmarxOneExecuteScan.go +++ b/cmd/checkmarxOneExecuteScan.go @@ -419,6 +419,9 @@ func (c *checkmarxOneExecuteScanHelper) CreateScanRequest(incremental bool, uplo } branch := c.config.Branch + if len(branch) == 0 && len(c.config.GitBranch) > 0 { + branch = c.config.GitBranch + } if len(c.config.PullRequestName) > 0 { branch = fmt.Sprintf("%v-%v", c.config.PullRequestName, c.config.Branch) } diff --git a/cmd/checkmarxOneExecuteScan_generated.go b/cmd/checkmarxOneExecuteScan_generated.go index 464f1027db..06d8d653f2 100644 --- a/cmd/checkmarxOneExecuteScan_generated.go +++ b/cmd/checkmarxOneExecuteScan_generated.go @@ -32,6 +32,7 @@ type checkmarxOneExecuteScanOptions struct { GithubToken string `json:"githubToken,omitempty"` Incremental bool `json:"incremental,omitempty"` Owner string `json:"owner,omitempty"` + GitBranch string `json:"gitBranch,omitempty"` ClientSecret string `json:"clientSecret,omitempty"` APIKey string `json:"APIKey,omitempty"` Preset string `json:"preset,omitempty"` @@ -356,6 +357,7 @@ func addCheckmarxOneExecuteScanFlags(cmd *cobra.Command, stepConfig *checkmarxOn cmd.Flags().StringVar(&stepConfig.GithubToken, "githubToken", os.Getenv("PIPER_githubToken"), "GitHub personal access token as per https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line") cmd.Flags().BoolVar(&stepConfig.Incremental, "incremental", true, "Whether incremental scans are to be applied which optimizes the scan time but might reduce detection capabilities. Therefore full scans are still required from time to time and should be scheduled via `fullScansScheduled` and `fullScanCycle`") cmd.Flags().StringVar(&stepConfig.Owner, "owner", os.Getenv("PIPER_owner"), "Set the GitHub organization.") + cmd.Flags().StringVar(&stepConfig.GitBranch, "gitBranch", os.Getenv("PIPER_gitBranch"), "Set the GitHub repository branch.") cmd.Flags().StringVar(&stepConfig.ClientSecret, "clientSecret", os.Getenv("PIPER_clientSecret"), "The clientSecret to authenticate using a service account") cmd.Flags().StringVar(&stepConfig.APIKey, "APIKey", os.Getenv("PIPER_APIKey"), "The APIKey to authenticate") cmd.Flags().StringVar(&stepConfig.Preset, "preset", os.Getenv("PIPER_preset"), "The preset to use for scanning, if not set explicitly the step will attempt to look up the project's setting based on the availability of `checkmarxOneCredentialsId`") @@ -521,6 +523,20 @@ func checkmarxOneExecuteScanMetadata() config.StepData { Aliases: []config.Alias{{Name: "githubOrg"}}, Default: os.Getenv("PIPER_owner"), }, + { + Name: "gitBranch", + ResourceRef: []config.ResourceReference{ + { + Name: "commonPipelineEnvironment", + Param: "github/branch", + }, + }, + Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"}, + Type: "string", + Mandatory: false, + Aliases: []config.Alias{}, + Default: os.Getenv("PIPER_gitBranch"), + }, { Name: "clientSecret", ResourceRef: []config.ResourceReference{ diff --git a/cmd/codeqlExecuteScan.go b/cmd/codeqlExecuteScan.go index f54e1ad8e6..fdace77ad3 100644 --- a/cmd/codeqlExecuteScan.go +++ b/cmd/codeqlExecuteScan.go @@ -6,16 +6,13 @@ import ( "net/http" "os" "path/filepath" - "regexp" "strings" - "time" "github.com/SAP/jenkins-library/pkg/codeql" "github.com/SAP/jenkins-library/pkg/command" piperhttp "github.com/SAP/jenkins-library/pkg/http" "github.com/SAP/jenkins-library/pkg/log" "github.com/SAP/jenkins-library/pkg/maven" - "github.com/SAP/jenkins-library/pkg/orchestrator" "github.com/SAP/jenkins-library/pkg/piperutils" "github.com/SAP/jenkins-library/pkg/telemetry" "github.com/pkg/errors" @@ -35,11 +32,6 @@ type codeqlExecuteScanUtilsBundle struct { *piperhttp.Client } -const ( - sarifUploadComplete = "complete" - sarifUploadFailed = "failed" -) - func newCodeqlExecuteScanUtils() codeqlExecuteScanUtils { utils := codeqlExecuteScanUtilsBundle{ Command: &command.Command{}, @@ -53,7 +45,6 @@ func newCodeqlExecuteScanUtils() codeqlExecuteScanUtils { } func codeqlExecuteScan(config codeqlExecuteScanOptions, telemetryData *telemetry.CustomData, influx *codeqlExecuteScanInflux) { - utils := newCodeqlExecuteScanUtils() influx.step_data.fields.codeql = false @@ -100,81 +91,6 @@ func getLangFromBuildTool(buildTool string) string { } } -func getGitRepoInfo(repoUri string, repoInfo *codeql.RepoInfo) error { - if repoUri == "" { - return errors.New("repository param is not set or it cannot be auto populated") - } - - pat := regexp.MustCompile(`^(https:\/\/|git@)([\S]+:[\S]+@)?([^\/:]+)[\/:]([^\/:]+\/[\S]+)$`) - matches := pat.FindAllStringSubmatch(repoUri, -1) - if len(matches) > 0 { - match := matches[0] - repoInfo.ServerUrl = "https://" + match[3] - repoData := strings.Split(strings.TrimSuffix(match[4], ".git"), "/") - if len(repoData) != 2 { - return fmt.Errorf("Invalid repository %s", repoUri) - } - - repoInfo.Owner = repoData[0] - repoInfo.Repo = repoData[1] - return nil - } - - return fmt.Errorf("Invalid repository %s", repoUri) -} - -func initGitInfo(config *codeqlExecuteScanOptions) (codeql.RepoInfo, error) { - var repoInfo codeql.RepoInfo - err := getGitRepoInfo(config.Repository, &repoInfo) - if err != nil { - log.Entry().Error(err) - } - - repoInfo.Ref = config.AnalyzedRef - repoInfo.CommitId = config.CommitID - - provider, err := orchestrator.GetOrchestratorConfigProvider(nil) - if err != nil { - log.Entry().Warn("No orchestrator found. We assume piper is running locally.") - } else { - if repoInfo.Ref == "" { - repoInfo.Ref = provider.GitReference() - } - - if repoInfo.CommitId == "" || repoInfo.CommitId == "NA" { - repoInfo.CommitId = provider.CommitSHA() - } - - if repoInfo.ServerUrl == "" { - err = getGitRepoInfo(provider.RepoURL(), &repoInfo) - if err != nil { - log.Entry().Error(err) - } - } - } - if len(config.TargetGithubRepoURL) > 0 { - log.Entry().Infof("Checking target GitHub repo URL: %s", config.TargetGithubRepoURL) - if strings.Contains(repoInfo.ServerUrl, "github") { - log.Entry().Errorf("TargetGithubRepoURL should not be set as the source repo is on github.") - return repoInfo, errors.New("TargetGithubRepoURL should not be set as the source repo is on github.") - } - err := getGitRepoInfo(config.TargetGithubRepoURL, &repoInfo) - if err != nil { - log.Entry().Error(err) - return repoInfo, err - } - if len(config.TargetGithubBranchName) > 0 { - log.Entry().Infof("Target GitHub branch name: %s", config.TargetGithubBranchName) - repoInfo.Ref = config.TargetGithubBranchName - if len(strings.Split(config.TargetGithubBranchName, "/")) < 3 { - repoInfo.Ref = "refs/heads/" + config.TargetGithubBranchName - } - } - } - - return repoInfo, nil -} - func getToken(config *codeqlExecuteScanOptions) (bool, string) { if len(config.GithubToken) > 0 { return true, config.GithubToken @@ -188,200 +104,106 @@ func getToken(config *codeqlExecuteScanOptions) (bool, string) { return false, "" } -func uploadResults(config *codeqlExecuteScanOptions, repoInfo codeql.RepoInfo, token string, utils codeqlExecuteScanUtils) (string, error) { - cmd := prepareCmdForUploadResults(config, &repoInfo, token) - - //if no git params are passed(commitId, reference, serverUrl, repository), then codeql tries to auto populate it based on git information of the checkout repository. - //It also depends on the orchestrator. Some orchestrator keep git information and some not. - - var bufferOut, bufferErr bytes.Buffer - utils.Stdout(&bufferOut) - defer utils.Stdout(log.Writer()) - utils.Stderr(&bufferErr) - defer utils.Stderr(log.Writer()) - - err := execute(utils, cmd, GeneralConfig.Verbose) - if err != nil { - e := bufferErr.String() - log.Entry().Error(e) - if strings.Contains(e, "Unauthorized") { - log.Entry().Error("Either your Github Token is invalid or you use both Vault and Jenkins credentials where your Vault credentials are invalid, to use your Jenkins credentials try setting 'skipVault:true'") - } - log.Entry().Error("failed to upload sarif results") - return "", err - } - - url := bufferOut.String() - return strings.TrimSpace(url), nil -} - -func waitSarifUploaded(config *codeqlExecuteScanOptions, codeqlSarifUploader codeql.CodeqlSarifUploader) error { - maxRetries := config.SarifCheckMaxRetries - retryInterval := time.Duration(config.SarifCheckRetryInterval) * time.Second - - log.Entry().Info("waiting for the SARIF to upload") - i := 1 - for { - sarifStatus, err := codeqlSarifUploader.GetSarifStatus() - if err != nil { - return err - } - log.Entry().Infof("the SARIF processing status: %s", sarifStatus.ProcessingStatus) - if sarifStatus.ProcessingStatus == sarifUploadComplete { - return nil - } - if sarifStatus.ProcessingStatus == sarifUploadFailed { - for e := range sarifStatus.Errors { - log.Entry().Error(e) - } - return errors.New("failed to upload sarif file") - } - if i <= maxRetries { - log.Entry().Infof("still waiting for the SARIF to upload: retrying in %d seconds... (retry %d/%d)", config.SarifCheckRetryInterval, i, maxRetries) - time.Sleep(retryInterval) - i++ - continue - } - return errors.New("failed to check sarif uploading status: max retries reached") - } -} - -func runCodeqlExecuteScan(config *codeqlExecuteScanOptions, telemetryData *telemetry.CustomData, utils codeqlExecuteScanUtils, influx *codeqlExecuteScanInflux) ([]piperutils.Path, error) { +func printCodeqlImageVersion() { codeqlVersion, err := os.ReadFile("/etc/image-version") if err != nil { log.Entry().Infof("CodeQL image version: unknown") } else { log.Entry().Infof("CodeQL image version: %s", string(codeqlVersion)) } +} + +func runCodeqlExecuteScan(config *codeqlExecuteScanOptions, telemetryData *telemetry.CustomData, utils codeqlExecuteScanUtils, influx *codeqlExecuteScanInflux) ([]piperutils.Path, error) { + printCodeqlImageVersion() var reports []piperutils.Path dbCreateCustomFlags := codeql.ParseCustomFlags(config.DatabaseCreateFlags) - cmd, err := prepareCmdForDatabaseCreate(dbCreateCustomFlags, config, utils) + err := runDatabaseCreate(config, dbCreateCustomFlags, utils) if err != nil { - log.Entry().WithError(err).Error("failed to prepare command for codeql database create") - return reports, err - } - - err = execute(utils, cmd, GeneralConfig.Verbose) - if err != nil { - log.Entry().Error("failed running command codeql database create") + log.Entry().WithError(err).Error("failed to create codeql database") return reports, err } err = os.MkdirAll(filepath.Join(config.ModulePath, "target"), os.ModePerm) if err != nil { - return reports, fmt.Errorf("failed to create directory: %w", err) - } - - dbAnalyzeCustomFlags := codeql.ParseCustomFlags(config.DatabaseAnalyzeFlags) - cmd, err = prepareCmdForDatabaseAnalyze(dbAnalyzeCustomFlags, config, "sarif-latest", "codeqlReport.sarif") - if err != nil { - log.Entry().WithError(err).Error("failed to prepare command for codeql database analyze format=sarif-latest") - return reports, err - } - err = execute(utils, cmd, GeneralConfig.Verbose) - if err != nil { - log.Entry().Error("failed running command codeql database analyze for sarif generation") + log.Entry().WithError(err).Error("failed to create output directory for reports") return reports, err } - reports = append(reports, piperutils.Path{Target: filepath.Join(config.ModulePath, "target", "codeqlReport.sarif")}) - cmd, err = prepareCmdForDatabaseAnalyze(dbAnalyzeCustomFlags, config, "csv", "codeqlReport.csv") - if err != nil { - log.Entry().WithError(err).Error("failed to prepare command for codeql database analyze format=csv") - return reports, err - } - err = execute(utils, cmd, GeneralConfig.Verbose) + dbAnalyzeCustomFlags := codeql.ParseCustomFlags(config.DatabaseAnalyzeFlags) + scanReports, err := runDatabaseAnalyze(config, dbAnalyzeCustomFlags, utils) if err != nil { - log.Entry().Error("failed running command codeql database analyze for csv generation") + log.Entry().WithError(err).Error("failed to analyze codeql database") return reports, err } - reports = append(reports, piperutils.Path{Target: filepath.Join(config.ModulePath, "target", "codeqlReport.csv")}) + reports = append(reports, scanReports...) - repoInfo, err := initGitInfo(config) + repoInfo, err := codeql.GetRepoInfo(config.Repository, config.AnalyzedRef, config.CommitID, + config.TargetGithubRepoURL, config.TargetGithubBranchName) if err != nil { + log.Entry().WithError(err).Error("failed to get repository info") return reports, err } - repoUrl := fmt.Sprintf("%s/%s/%s", repoInfo.ServerUrl, repoInfo.Owner, repoInfo.Repo) - repoReference, err := codeql.BuildRepoReference(repoUrl, repoInfo.Ref) - repoCodeqlScanUrl := fmt.Sprintf("%s/security/code-scanning?query=is:open+ref:%s", repoUrl, repoInfo.Ref) if len(config.TargetGithubRepoURL) > 0 { - log.Entry().Infof("DB sources for %s will be uploaded to target GitHub repo: %s", config.Repository, repoUrl) - hasToken, token := getToken(config) - if !hasToken { - return reports, errors.New("failed running upload db sources to GitHub as githubToken was not specified") - } - repoUploader, err := codeql.NewGitUploaderInstance( - token, - repoInfo.Ref, - config.Database, - repoInfo.CommitId, - config.Repository, - config.TargetGithubRepoURL, - ) + err = uploadProjectToGitHub(config, repoInfo) if err != nil { + log.Entry().WithError(err).Error("failed to upload project to Github") return reports, err } - targetCommitId, err := repoUploader.UploadProjectToGithub() - if err != nil { - return reports, errors.Wrap(err, "failed uploading db sources from non-GitHub SCM to GitHub") - } - repoInfo.CommitId = targetCommitId - log.Entry().Info("DB sources were successfully uploaded to target GitHub repo") } var scanResults []codeql.CodeqlFindings - if !config.UploadResults { log.Entry().Warn("The sarif results will not be uploaded to the repository and compliance report will not be generated as uploadResults is set to false.") } else { - log.Entry().Infof("The sarif results will be uploaded to the repository %s", repoUrl) + log.Entry().Infof("The sarif results will be uploaded to the repository %s", repoInfo.FullUrl) + hasToken, token := getToken(config) if !hasToken { - return reports, errors.New("failed running upload-results as githubToken was not specified") + return reports, fmt.Errorf("failed running upload-results as githubToken was not specified") } - sarifUrl, err := uploadResults(config, repoInfo, token, utils) + err = uploadSarifResults(config, token, repoInfo, utils) if err != nil { + log.Entry().WithError(err).Error("failed to upload sarif results") return reports, err } - codeqlSarifUploader := codeql.NewCodeqlSarifUploaderInstance(sarifUrl, token) - err = waitSarifUploaded(config, &codeqlSarifUploader) - if err != nil { - return reports, errors.Wrap(err, "failed to upload sarif") - } codeqlScanAuditInstance := codeql.NewCodeqlScanAuditInstance(repoInfo.ServerUrl, repoInfo.Owner, repoInfo.Repo, token, []string{}) - scanResults, err = codeqlScanAuditInstance.GetVulnerabilities(repoInfo.Ref) + scanResults, err = codeqlScanAuditInstance.GetVulnerabilities(repoInfo.AnalyzedRef) if err != nil { - return reports, errors.Wrap(err, "failed to get scan results") + log.Entry().WithError(err).Error("failed to get vulnerabilities") + return reports, err } - codeqlAudit := codeql.CodeqlAudit{ToolName: "codeql", RepositoryUrl: repoUrl, CodeScanningLink: repoCodeqlScanUrl, RepositoryReferenceUrl: repoReference, QuerySuite: config.QuerySuite, ScanResults: scanResults} + codeqlAudit := codeql.CodeqlAudit{ + ToolName: "codeql", + RepositoryUrl: repoInfo.FullUrl, + CodeScanningLink: repoInfo.ScanUrl, + RepositoryReferenceUrl: repoInfo.FullRef, + QuerySuite: config.QuerySuite, + ScanResults: scanResults, + } paths, err := codeql.WriteJSONReport(codeqlAudit, config.ModulePath) if err != nil { - return reports, errors.Wrap(err, "failed to write json compliance report") + log.Entry().WithError(err).Error("failed to write json compliance report") + return reports, err } reports = append(reports, paths...) if config.CheckForCompliance { - for _, scanResult := range scanResults { - if scanResult.ClassificationName == codeql.AuditAll { - unaudited := scanResult.Total - scanResult.Audited - if unaudited > config.VulnerabilityThresholdTotal { - msg := fmt.Sprintf("Your repository %v with ref %v is not compliant. Total unaudited issues are %v which is greater than the VulnerabilityThresholdTotal count %v", repoUrl, repoInfo.Ref, unaudited, config.VulnerabilityThresholdTotal) - return reports, errors.Errorf(msg) - } - } + err = checkForCompliance(scanResults, config, repoInfo) + if err != nil { + return reports, err } } } - addDataToInfluxDB(repoUrl, repoReference, repoCodeqlScanUrl, config.QuerySuite, scanResults, influx) + addDataToInfluxDB(repoInfo, config.QuerySuite, scanResults, influx) - toolRecordFileName, err := codeql.CreateAndPersistToolRecord(utils, repoInfo, repoReference, repoUrl, config.ModulePath) + toolRecordFileName, err := codeql.CreateAndPersistToolRecord(utils, repoInfo, config.ModulePath) if err != nil { log.Entry().Warning("TR_CODEQL: Failed to create toolrecord file ...", err) } else { @@ -391,6 +213,70 @@ func runCodeqlExecuteScan(config *codeqlExecuteScanOptions, telemetryData *telem return reports, nil } +func runDatabaseCreate(config *codeqlExecuteScanOptions, customFlags map[string]string, utils codeqlExecuteScanUtils) error { + cmd, err := prepareCmdForDatabaseCreate(customFlags, config, utils) + if err != nil { + log.Entry().Error("failed to prepare command for codeql database create") + return err + } + if err = execute(utils, cmd, GeneralConfig.Verbose); err != nil { + log.Entry().Error("failed running command codeql database create") + return err + } + return nil +} + +func runDatabaseAnalyze(config *codeqlExecuteScanOptions, customFlags map[string]string, utils codeqlExecuteScanUtils) ([]piperutils.Path, error) { + sarifReport, err := executeAnalysis("sarif-latest", "codeqlReport.sarif", customFlags, config, utils) + if err != nil { + return nil, err + } + csvReport, err := executeAnalysis("csv", "codeqlReport.csv", customFlags, config, utils) + if err != nil { + return nil, err + } + return append(sarifReport, csvReport...), nil +} + +func runGithubUploadResults(config *codeqlExecuteScanOptions, repoInfo *codeql.RepoInfo, token string, utils codeqlExecuteScanUtils) (string, error) { + cmd := prepareCmdForUploadResults(config, repoInfo, token) + + var bufferOut, bufferErr bytes.Buffer + utils.Stdout(&bufferOut) + defer utils.Stdout(log.Writer()) + utils.Stderr(&bufferErr) + defer utils.Stderr(log.Writer()) + + if err := execute(utils, cmd, GeneralConfig.Verbose); err != nil { + e := bufferErr.String() + log.Entry().Error(e) + if strings.Contains(e, "Unauthorized") { + log.Entry().Error("Either your Github Token is invalid or you use both Vault and Jenkins credentials where your Vault credentials are invalid, to use your Jenkins credentials try setting 'skipVault:true'") + } + return "", err + } + + url := strings.TrimSpace(bufferOut.String()) + return url, nil +} + +func executeAnalysis(format, reportName string, customFlags map[string]string, config *codeqlExecuteScanOptions, utils codeqlExecuteScanUtils) ([]piperutils.Path, error) { + moduleTargetPath := filepath.Join(config.ModulePath, "target") + report := filepath.Join(moduleTargetPath, reportName) + cmd, err := prepareCmdForDatabaseAnalyze(customFlags, config, format, report) + if err != nil { + log.Entry().Errorf("failed to prepare command for codeql database analyze (format=%s)", format) + return nil, err + } + if err = execute(utils, cmd, GeneralConfig.Verbose); err != nil { + log.Entry().Errorf("failed running command codeql database analyze for %s generation", format) + return nil, err + } + return []piperutils.Path{ + {Target: report}, + }, nil +} + func prepareCmdForDatabaseCreate(customFlags map[string]string, config *codeqlExecuteScanOptions, utils codeqlExecuteScanUtils) ([]string, error) { cmd := []string{"database", "create", config.Database} cmd = codeql.AppendFlagIfNotSetByUser(cmd, []string{"--overwrite", "--no-overwrite"}, []string{"--overwrite"}, customFlags) @@ -430,7 +316,7 @@ func prepareCmdForDatabaseCreate(customFlags map[string]string, config *codeqlEx } func prepareCmdForDatabaseAnalyze(customFlags map[string]string, config *codeqlExecuteScanOptions, format, reportName string) ([]string, error) { - cmd := []string{"database", "analyze", "--format=" + format, fmt.Sprintf("--output=%v", filepath.Join(config.ModulePath, "target", reportName)), config.Database} + cmd := []string{"database", "analyze", "--format=" + format, "--output=" + reportName, config.Database} cmd = codeql.AppendThreadsAndRam(cmd, config.Threads, config.Ram, customFlags) cmd = codeql.AppendCustomFlags(cmd, customFlags) cmd = appendCodeqlQuery(cmd, config.QuerySuite) @@ -459,16 +345,73 @@ func prepareCmdForUploadResults(config *codeqlExecuteScanOptions, repoInfo *code cmd = append(cmd, "--repository="+(repoInfo.Owner+"/"+repoInfo.Repo)) } - if repoInfo.Ref != "" { - cmd = append(cmd, "--ref="+repoInfo.Ref) + if repoInfo.AnalyzedRef != "" { + cmd = append(cmd, "--ref="+repoInfo.AnalyzedRef) } return cmd } -func addDataToInfluxDB(repoUrl, repoRef, repoScanUrl, querySuite string, scanResults []codeql.CodeqlFindings, influx *codeqlExecuteScanInflux) { - influx.codeql_data.fields.repositoryURL = repoUrl - influx.codeql_data.fields.repositoryReferenceURL = repoRef - influx.codeql_data.fields.codeScanningLink = repoScanUrl +func uploadSarifResults(config *codeqlExecuteScanOptions, token string, repoInfo *codeql.RepoInfo, utils codeqlExecuteScanUtils) error { + sarifUrl, err := runGithubUploadResults(config, repoInfo, token, utils) + if err != nil { + return err + } + + codeqlSarifUploader := codeql.NewCodeqlSarifUploaderInstance(sarifUrl, token) + err = codeql.WaitSarifUploaded(config.SarifCheckMaxRetries, config.SarifCheckRetryInterval, &codeqlSarifUploader) + if err != nil { + return errors.Wrap(err, "failed to upload sarif") + } + return nil +} + +func uploadProjectToGitHub(config *codeqlExecuteScanOptions, repoInfo *codeql.RepoInfo) error { + log.Entry().Infof("DB sources for %s will be uploaded to target GitHub repo: %s", config.Repository, repoInfo.FullUrl) + + hasToken, token := getToken(config) + if !hasToken { + return fmt.Errorf("failed running upload db sources to GitHub as githubToken was not specified") + } + repoUploader, err := codeql.NewGitUploaderInstance( + token, + repoInfo.AnalyzedRef, + config.Database, + repoInfo.CommitId, + config.Repository, + config.TargetGithubRepoURL, + ) + if err != nil { + log.Entry().WithError(err).Error("failed to create github uploader") + return err + } + targetCommitId, err := repoUploader.UploadProjectToGithub() + if err != nil { + return errors.Wrap(err, "failed uploading db sources from non-GitHub SCM to GitHub") + } + repoInfo.CommitId = targetCommitId + log.Entry().Info("DB sources were successfully uploaded to target GitHub repo") + + return nil +} + +func checkForCompliance(scanResults []codeql.CodeqlFindings, config *codeqlExecuteScanOptions, repoInfo *codeql.RepoInfo) error { + for _, scanResult := range scanResults { + if scanResult.ClassificationName == codeql.AuditAll { + unaudited := scanResult.Total - scanResult.Audited + if unaudited > config.VulnerabilityThresholdTotal { + msg := fmt.Sprintf("Your repository %v with ref %v is not compliant. Total unaudited issues are %v which is greater than the VulnerabilityThresholdTotal count %v", + repoInfo.FullUrl, repoInfo.AnalyzedRef, unaudited, config.VulnerabilityThresholdTotal) + return errors.Errorf(msg) + } + } + } + return nil +} + +func addDataToInfluxDB(repoInfo *codeql.RepoInfo, querySuite string, scanResults []codeql.CodeqlFindings, influx *codeqlExecuteScanInflux) { + influx.codeql_data.fields.repositoryURL = repoInfo.FullUrl + influx.codeql_data.fields.repositoryReferenceURL = repoInfo.FullRef + influx.codeql_data.fields.codeScanningLink = repoInfo.ScanUrl influx.codeql_data.fields.querySuite = querySuite for _, sr := range scanResults { diff --git a/cmd/codeqlExecuteScan_test.go b/cmd/codeqlExecuteScan_test.go index fbf8e25fb5..775ddea346 100644 --- a/cmd/codeqlExecuteScan_test.go +++ b/cmd/codeqlExecuteScan_test.go @@ -4,14 +4,12 @@ package cmd import ( + "os" "strings" "testing" - "time" "github.com/SAP/jenkins-library/pkg/codeql" "github.com/SAP/jenkins-library/pkg/mock" - "github.com/SAP/jenkins-library/pkg/orchestrator" - "github.com/pkg/errors" "github.com/stretchr/testify/assert" ) @@ -30,281 +28,6 @@ func newCodeqlExecuteScanTestsUtils() codeqlExecuteScanMockUtils { return utils } -func TestRunCodeqlExecuteScan(t *testing.T) { - - influx := &codeqlExecuteScanInflux{} - - t.Run("Valid CodeqlExecuteScan", func(t *testing.T) { - config := codeqlExecuteScanOptions{BuildTool: "maven", ModulePath: "./"} - _, err := runCodeqlExecuteScan(&config, nil, newCodeqlExecuteScanTestsUtils(), influx) - assert.NoError(t, err) - }) - - t.Run("No auth token passed on upload results", func(t *testing.T) { - config := codeqlExecuteScanOptions{BuildTool: "maven", UploadResults: true, ModulePath: "./"} - _, err := runCodeqlExecuteScan(&config, nil, newCodeqlExecuteScanTestsUtils(), influx) - assert.Error(t, err) - }) - - t.Run("GitCommitID is NA on upload results", func(t *testing.T) { - config := codeqlExecuteScanOptions{BuildTool: "maven", UploadResults: true, ModulePath: "./", CommitID: "NA"} - _, err := runCodeqlExecuteScan(&config, nil, newCodeqlExecuteScanTestsUtils(), influx) - assert.Error(t, err) - }) - - t.Run("Custom buildtool", func(t *testing.T) { - config := codeqlExecuteScanOptions{BuildTool: "custom", Language: "javascript", ModulePath: "./"} - _, err := runCodeqlExecuteScan(&config, nil, newCodeqlExecuteScanTestsUtils(), influx) - assert.NoError(t, err) - }) - - t.Run("Custom buildtool but no language specified", func(t *testing.T) { - config := codeqlExecuteScanOptions{BuildTool: "custom", ModulePath: "./", GithubToken: "test"} - _, err := runCodeqlExecuteScan(&config, nil, newCodeqlExecuteScanTestsUtils(), influx) - assert.Error(t, err) - }) - - t.Run("Invalid buildtool and no language specified", func(t *testing.T) { - config := codeqlExecuteScanOptions{BuildTool: "test", ModulePath: "./", GithubToken: "test"} - _, err := runCodeqlExecuteScan(&config, nil, newCodeqlExecuteScanTestsUtils(), influx) - assert.Error(t, err) - }) - - t.Run("Invalid buildtool but language specified", func(t *testing.T) { - config := codeqlExecuteScanOptions{BuildTool: "test", Language: "javascript", ModulePath: "./", GithubToken: "test"} - _, err := runCodeqlExecuteScan(&config, nil, newCodeqlExecuteScanTestsUtils(), influx) - assert.NoError(t, err) - }) -} - -func TestGetGitRepoInfo(t *testing.T) { - t.Run("Valid https URL1", func(t *testing.T) { - var repoInfo codeql.RepoInfo - err := getGitRepoInfo("https://github.hello.test/Testing/fortify.git", &repoInfo) - assert.NoError(t, err) - assert.Equal(t, "https://github.hello.test", repoInfo.ServerUrl) - assert.Equal(t, "fortify", repoInfo.Repo) - assert.Equal(t, "Testing", repoInfo.Owner) - }) - - t.Run("Valid https URL2", func(t *testing.T) { - var repoInfo codeql.RepoInfo - err := getGitRepoInfo("https://github.hello.test/Testing/fortify", &repoInfo) - assert.NoError(t, err) - assert.Equal(t, "https://github.hello.test", repoInfo.ServerUrl) - assert.Equal(t, "fortify", repoInfo.Repo) - assert.Equal(t, "Testing", repoInfo.Owner) - }) - t.Run("Valid https URL1 with dots", func(t *testing.T) { - var repoInfo codeql.RepoInfo - err := getGitRepoInfo("https://github.hello.test/Testing/com.sap.fortify.git", &repoInfo) - assert.NoError(t, err) - assert.Equal(t, "https://github.hello.test", repoInfo.ServerUrl) - assert.Equal(t, "com.sap.fortify", repoInfo.Repo) - assert.Equal(t, "Testing", repoInfo.Owner) - }) - - t.Run("Valid https URL2 with dots", func(t *testing.T) { - var repoInfo codeql.RepoInfo - err := getGitRepoInfo("https://github.hello.test/Testing/com.sap.fortify", &repoInfo) - assert.NoError(t, err) - assert.Equal(t, "https://github.hello.test", repoInfo.ServerUrl) - assert.Equal(t, "com.sap.fortify", repoInfo.Repo) - assert.Equal(t, "Testing", repoInfo.Owner) - }) - t.Run("Valid https URL1 with username and token", func(t *testing.T) { - var repoInfo codeql.RepoInfo - err := getGitRepoInfo("https://username:token@github.hello.test/Testing/fortify.git", &repoInfo) - assert.NoError(t, err) - assert.Equal(t, "https://github.hello.test", repoInfo.ServerUrl) - assert.Equal(t, "fortify", repoInfo.Repo) - assert.Equal(t, "Testing", repoInfo.Owner) - }) - - t.Run("Valid https URL2 with username and token", func(t *testing.T) { - var repoInfo codeql.RepoInfo - err := getGitRepoInfo("https://username:token@github.hello.test/Testing/fortify", &repoInfo) - assert.NoError(t, err) - assert.Equal(t, "https://github.hello.test", repoInfo.ServerUrl) - assert.Equal(t, "fortify", repoInfo.Repo) - assert.Equal(t, "Testing", repoInfo.Owner) - }) - - t.Run("Invalid https URL as no org/Owner passed", func(t *testing.T) { - var repoInfo codeql.RepoInfo - assert.Error(t, getGitRepoInfo("https://github.com/fortify", &repoInfo)) - }) - - t.Run("Invalid URL as no protocol passed", func(t *testing.T) { - var repoInfo codeql.RepoInfo - assert.Error(t, getGitRepoInfo("github.hello.test/Testing/fortify", &repoInfo)) - }) - - t.Run("Valid ssh URL1", func(t *testing.T) { - var repoInfo codeql.RepoInfo - err := getGitRepoInfo("git@github.hello.test/Testing/fortify.git", &repoInfo) - assert.NoError(t, err) - assert.Equal(t, "https://github.hello.test", repoInfo.ServerUrl) - assert.Equal(t, "fortify", repoInfo.Repo) - assert.Equal(t, "Testing", repoInfo.Owner) - }) - - t.Run("Valid ssh URL2", func(t *testing.T) { - var repoInfo codeql.RepoInfo - err := getGitRepoInfo("git@github.hello.test/Testing/fortify", &repoInfo) - assert.NoError(t, err) - assert.Equal(t, "https://github.hello.test", repoInfo.ServerUrl) - assert.Equal(t, "fortify", repoInfo.Repo) - assert.Equal(t, "Testing", repoInfo.Owner) - }) - t.Run("Valid ssh URL1 with dots", func(t *testing.T) { - var repoInfo codeql.RepoInfo - err := getGitRepoInfo("git@github.hello.test/Testing/com.sap.fortify.git", &repoInfo) - assert.NoError(t, err) - assert.Equal(t, "https://github.hello.test", repoInfo.ServerUrl) - assert.Equal(t, "com.sap.fortify", repoInfo.Repo) - assert.Equal(t, "Testing", repoInfo.Owner) - }) - - t.Run("Valid ssh URL2 with dots", func(t *testing.T) { - var repoInfo codeql.RepoInfo - err := getGitRepoInfo("git@github.hello.test/Testing/com.sap.fortify", &repoInfo) - assert.NoError(t, err) - assert.Equal(t, "https://github.hello.test", repoInfo.ServerUrl) - assert.Equal(t, "com.sap.fortify", repoInfo.Repo) - assert.Equal(t, "Testing", repoInfo.Owner) - }) - - t.Run("Invalid ssh URL as no org/Owner passed", func(t *testing.T) { - var repoInfo codeql.RepoInfo - assert.Error(t, getGitRepoInfo("git@github.com/fortify", &repoInfo)) - }) -} - -func TestInitGitInfo(t *testing.T) { - t.Run("Valid URL1", func(t *testing.T) { - config := codeqlExecuteScanOptions{Repository: "https://github.hello.test/Testing/codeql.git", AnalyzedRef: "refs/head/branch", CommitID: "abcd1234"} - repoInfo, err := initGitInfo(&config) - assert.NoError(t, err) - assert.Equal(t, "abcd1234", repoInfo.CommitId) - assert.Equal(t, "Testing", repoInfo.Owner) - assert.Equal(t, "codeql", repoInfo.Repo) - assert.Equal(t, "refs/head/branch", repoInfo.Ref) - assert.Equal(t, "https://github.hello.test", repoInfo.ServerUrl) - }) - - t.Run("Valid URL2", func(t *testing.T) { - config := codeqlExecuteScanOptions{Repository: "https://github.hello.test/Testing/codeql", AnalyzedRef: "refs/head/branch", CommitID: "abcd1234"} - repoInfo, err := initGitInfo(&config) - assert.NoError(t, err) - assert.Equal(t, "abcd1234", repoInfo.CommitId) - assert.Equal(t, "Testing", repoInfo.Owner) - assert.Equal(t, "codeql", repoInfo.Repo) - assert.Equal(t, "refs/head/branch", repoInfo.Ref) - assert.Equal(t, "https://github.hello.test", repoInfo.ServerUrl) - }) - - t.Run("Valid url with dots URL1", func(t *testing.T) { - config := codeqlExecuteScanOptions{Repository: "https://github.hello.test/Testing/com.sap.codeql.git", AnalyzedRef: "refs/head/branch", CommitID: "abcd1234"} - repoInfo, err := initGitInfo(&config) - assert.NoError(t, err) - assert.Equal(t, "abcd1234", repoInfo.CommitId) - assert.Equal(t, "Testing", repoInfo.Owner) - assert.Equal(t, "com.sap.codeql", repoInfo.Repo) - assert.Equal(t, "refs/head/branch", repoInfo.Ref) - assert.Equal(t, "https://github.hello.test", repoInfo.ServerUrl) - }) - - t.Run("Valid url with dots URL2", func(t *testing.T) { - config := codeqlExecuteScanOptions{Repository: "https://github.hello.test/Testing/com.sap.codeql", AnalyzedRef: "refs/head/branch", CommitID: "abcd1234"} - repoInfo, err := initGitInfo(&config) - assert.NoError(t, err) - assert.Equal(t, "abcd1234", repoInfo.CommitId) - assert.Equal(t, "Testing", repoInfo.Owner) - assert.Equal(t, "com.sap.codeql", repoInfo.Repo) - assert.Equal(t, "refs/head/branch", repoInfo.Ref) - assert.Equal(t, "https://github.hello.test", repoInfo.ServerUrl) - }) - - t.Run("Valid url with username and token URL1", func(t *testing.T) { - config := codeqlExecuteScanOptions{Repository: "https://username:token@github.hello.test/Testing/codeql.git", AnalyzedRef: "refs/head/branch", CommitID: "abcd1234"} - repoInfo, err := initGitInfo(&config) - assert.NoError(t, err) - assert.Equal(t, "abcd1234", repoInfo.CommitId) - assert.Equal(t, "Testing", repoInfo.Owner) - assert.Equal(t, "codeql", repoInfo.Repo) - assert.Equal(t, "refs/head/branch", repoInfo.Ref) - assert.Equal(t, "https://github.hello.test", repoInfo.ServerUrl) - }) - - t.Run("Valid url with username and token URL2", func(t *testing.T) { - config := codeqlExecuteScanOptions{Repository: "https://username:token@github.hello.test/Testing/codeql", AnalyzedRef: "refs/head/branch", CommitID: "abcd1234"} - repoInfo, err := initGitInfo(&config) - assert.NoError(t, err) - assert.Equal(t, "abcd1234", repoInfo.CommitId) - assert.Equal(t, "Testing", repoInfo.Owner) - assert.Equal(t, "codeql", repoInfo.Repo) - assert.Equal(t, "refs/head/branch", repoInfo.Ref) - assert.Equal(t, "https://github.hello.test", repoInfo.ServerUrl) - }) - - t.Run("Invalid URL with no org/reponame", func(t *testing.T) { - config := codeqlExecuteScanOptions{Repository: "https://github.hello.test", AnalyzedRef: "refs/head/branch", CommitID: "abcd1234"} - repoInfo, err := initGitInfo(&config) - assert.NoError(t, err) - _, err = orchestrator.GetOrchestratorConfigProvider(nil) - assert.Equal(t, "abcd1234", repoInfo.CommitId) - assert.Equal(t, "refs/head/branch", repoInfo.Ref) - if err != nil { - assert.Equal(t, "", repoInfo.Owner) - assert.Equal(t, "", repoInfo.Repo) - assert.Equal(t, "", repoInfo.ServerUrl) - } - }) -} - -func TestWaitSarifUploaded(t *testing.T) { - t.Parallel() - config := codeqlExecuteScanOptions{SarifCheckRetryInterval: 1, SarifCheckMaxRetries: 5} - t.Run("Fast complete upload", func(t *testing.T) { - codeqlScanAuditMock := CodeqlSarifUploaderMock{counter: 0} - timerStart := time.Now() - err := waitSarifUploaded(&config, &codeqlScanAuditMock) - assert.Less(t, time.Now().Sub(timerStart), time.Second) - assert.NoError(t, err) - }) - t.Run("Long completed upload", func(t *testing.T) { - codeqlScanAuditMock := CodeqlSarifUploaderMock{counter: 2} - timerStart := time.Now() - err := waitSarifUploaded(&config, &codeqlScanAuditMock) - assert.GreaterOrEqual(t, time.Now().Sub(timerStart), time.Second*2) - assert.NoError(t, err) - }) - t.Run("Failed upload", func(t *testing.T) { - codeqlScanAuditMock := CodeqlSarifUploaderMock{counter: -1} - err := waitSarifUploaded(&config, &codeqlScanAuditMock) - assert.Error(t, err) - assert.ErrorContains(t, err, "failed to upload sarif file") - }) - t.Run("Error while checking sarif uploading", func(t *testing.T) { - codeqlScanAuditErrorMock := CodeqlSarifUploaderErrorMock{counter: -1} - err := waitSarifUploaded(&config, &codeqlScanAuditErrorMock) - assert.Error(t, err) - assert.ErrorContains(t, err, "test error") - }) - t.Run("Completed upload after getting errors from server", func(t *testing.T) { - codeqlScanAuditErrorMock := CodeqlSarifUploaderErrorMock{counter: 3} - err := waitSarifUploaded(&config, &codeqlScanAuditErrorMock) - assert.NoError(t, err) - }) - t.Run("Max retries reached", func(t *testing.T) { - codeqlScanAuditErrorMock := CodeqlSarifUploaderErrorMock{counter: 6} - err := waitSarifUploaded(&config, &codeqlScanAuditErrorMock) - assert.Error(t, err) - assert.ErrorContains(t, err, "max retries reached") - }) -} - func TestGetMavenSettings(t *testing.T) { t.Parallel() t.Run("No maven", func(t *testing.T) { @@ -488,10 +211,16 @@ func TestAddDataToInfluxDB(t *testing.T) { repoScanUrl := "https://github.htllo.test/Testing/codeql/security/code-scanning" querySuite := "security.ql" + repoInfo := &codeql.RepoInfo{ + FullUrl: repoUrl, + FullRef: repoRef, + ScanUrl: repoScanUrl, + } + t.Run("No findings", func(t *testing.T) { scanResults := []codeql.CodeqlFindings{} influx := &codeqlExecuteScanInflux{} - addDataToInfluxDB(repoUrl, repoRef, repoScanUrl, querySuite, scanResults, influx) + addDataToInfluxDB(repoInfo, querySuite, scanResults, influx) assert.Equal(t, repoUrl, influx.codeql_data.fields.repositoryURL) assert.Equal(t, repoRef, influx.codeql_data.fields.repositoryReferenceURL) assert.Equal(t, repoScanUrl, influx.codeql_data.fields.codeScanningLink) @@ -511,7 +240,7 @@ func TestAddDataToInfluxDB(t *testing.T) { }, } influx := &codeqlExecuteScanInflux{} - addDataToInfluxDB(repoUrl, repoRef, repoScanUrl, querySuite, scanResults, influx) + addDataToInfluxDB(repoInfo, querySuite, scanResults, influx) assert.Equal(t, repoUrl, influx.codeql_data.fields.repositoryURL) assert.Equal(t, repoRef, influx.codeql_data.fields.repositoryReferenceURL) assert.Equal(t, repoScanUrl, influx.codeql_data.fields.codeScanningLink) @@ -531,7 +260,7 @@ func TestAddDataToInfluxDB(t *testing.T) { }, } influx := &codeqlExecuteScanInflux{} - addDataToInfluxDB(repoUrl, repoRef, repoScanUrl, querySuite, scanResults, influx) + addDataToInfluxDB(repoInfo, querySuite, scanResults, influx) assert.Equal(t, repoUrl, influx.codeql_data.fields.repositoryURL) assert.Equal(t, repoRef, influx.codeql_data.fields.repositoryReferenceURL) assert.Equal(t, repoScanUrl, influx.codeql_data.fields.codeScanningLink) @@ -556,7 +285,7 @@ func TestAddDataToInfluxDB(t *testing.T) { }, } influx := &codeqlExecuteScanInflux{} - addDataToInfluxDB(repoUrl, repoRef, repoScanUrl, querySuite, scanResults, influx) + addDataToInfluxDB(repoInfo, querySuite, scanResults, influx) assert.Equal(t, repoUrl, influx.codeql_data.fields.repositoryURL) assert.Equal(t, repoRef, influx.codeql_data.fields.repositoryReferenceURL) assert.Equal(t, repoScanUrl, influx.codeql_data.fields.codeScanningLink) @@ -682,7 +411,7 @@ func TestPrepareCmdForDatabaseAnalyze(t *testing.T) { config := &codeqlExecuteScanOptions{ Database: "codeqlDB", } - cmd, err := prepareCmdForDatabaseAnalyze(map[string]string{}, config, "sarif-latest", "codeqlReport.sarif") + cmd, err := prepareCmdForDatabaseAnalyze(map[string]string{}, config, "sarif-latest", "target/codeqlReport.sarif") assert.NoError(t, err) assert.NotEmpty(t, cmd) assert.Equal(t, 5, len(cmd)) @@ -693,7 +422,7 @@ func TestPrepareCmdForDatabaseAnalyze(t *testing.T) { config := &codeqlExecuteScanOptions{ Database: "codeqlDB", } - cmd, err := prepareCmdForDatabaseAnalyze(map[string]string{}, config, "csv", "codeqlReport.csv") + cmd, err := prepareCmdForDatabaseAnalyze(map[string]string{}, config, "csv", "target/codeqlReport.csv") assert.NoError(t, err) assert.NotEmpty(t, cmd) assert.Equal(t, 5, len(cmd)) @@ -705,7 +434,7 @@ func TestPrepareCmdForDatabaseAnalyze(t *testing.T) { Database: "codeqlDB", QuerySuite: "security.ql", } - cmd, err := prepareCmdForDatabaseAnalyze(map[string]string{}, config, "sarif-latest", "codeqlReport.sarif") + cmd, err := prepareCmdForDatabaseAnalyze(map[string]string{}, config, "sarif-latest", "target/codeqlReport.sarif") assert.NoError(t, err) assert.NotEmpty(t, cmd) assert.Equal(t, 6, len(cmd)) @@ -719,7 +448,7 @@ func TestPrepareCmdForDatabaseAnalyze(t *testing.T) { Threads: "1", Ram: "2000", } - cmd, err := prepareCmdForDatabaseAnalyze(map[string]string{}, config, "sarif-latest", "codeqlReport.sarif") + cmd, err := prepareCmdForDatabaseAnalyze(map[string]string{}, config, "sarif-latest", "target/codeqlReport.sarif") assert.NoError(t, err) assert.NotEmpty(t, cmd) assert.Equal(t, 8, len(cmd)) @@ -736,7 +465,7 @@ func TestPrepareCmdForDatabaseAnalyze(t *testing.T) { customFlags := map[string]string{ "--threads": "--threads=2", } - cmd, err := prepareCmdForDatabaseAnalyze(customFlags, config, "sarif-latest", "codeqlReport.sarif") + cmd, err := prepareCmdForDatabaseAnalyze(customFlags, config, "sarif-latest", "target/codeqlReport.sarif") assert.NoError(t, err) assert.NotEmpty(t, cmd) assert.Equal(t, 8, len(cmd)) @@ -753,7 +482,7 @@ func TestPrepareCmdForDatabaseAnalyze(t *testing.T) { customFlags := map[string]string{ "-j": "-j=2", } - cmd, err := prepareCmdForDatabaseAnalyze(customFlags, config, "sarif-latest", "codeqlReport.sarif") + cmd, err := prepareCmdForDatabaseAnalyze(customFlags, config, "sarif-latest", "target/codeqlReport.sarif") assert.NoError(t, err) assert.NotEmpty(t, cmd) assert.Equal(t, 8, len(cmd)) @@ -770,7 +499,7 @@ func TestPrepareCmdForDatabaseAnalyze(t *testing.T) { customFlags := map[string]string{ "--no-download": "--no-download", } - cmd, err := prepareCmdForDatabaseAnalyze(customFlags, config, "sarif-latest", "codeqlReport.sarif") + cmd, err := prepareCmdForDatabaseAnalyze(customFlags, config, "sarif-latest", "target/codeqlReport.sarif") assert.NoError(t, err) assert.NotEmpty(t, cmd) assert.Equal(t, 9, len(cmd)) @@ -787,11 +516,11 @@ func TestPrepareCmdForUploadResults(t *testing.T) { t.Run("All configs are set", func(t *testing.T) { repoInfo := &codeql.RepoInfo{ - CommitId: "commitId", - ServerUrl: "http://github.com", - Repo: "repo", - Owner: "owner", - Ref: "refs/heads/branch", + CommitId: "commitId", + ServerUrl: "http://github.com", + Repo: "repo", + Owner: "owner", + AnalyzedRef: "refs/heads/branch", } cmd := prepareCmdForUploadResults(config, repoInfo, "token") assert.NotEmpty(t, cmd) @@ -811,11 +540,11 @@ func TestPrepareCmdForUploadResults(t *testing.T) { t.Run("Empty token", func(t *testing.T) { repoInfo := &codeql.RepoInfo{ - CommitId: "commitId", - ServerUrl: "http://github.com", - Repo: "repo", - Owner: "owner", - Ref: "refs/heads/branch", + CommitId: "commitId", + ServerUrl: "http://github.com", + Repo: "repo", + Owner: "owner", + AnalyzedRef: "refs/heads/branch", } cmd := prepareCmdForUploadResults(config, repoInfo, "") assert.NotEmpty(t, cmd) @@ -830,44 +559,115 @@ func TestPrepareCmdForUploadResults(t *testing.T) { }) } -type CodeqlSarifUploaderMock struct { - counter int +func TestAppendCodeqlQuery(t *testing.T) { + t.Parallel() + + t.Run("Empty query", func(t *testing.T) { + cmd := []string{"database", "analyze"} + query := "" + cmd = appendCodeqlQuery(cmd, query) + assert.Equal(t, 2, len(cmd)) + }) + + t.Run("Not empty query", func(t *testing.T) { + cmd := []string{"database", "analyze"} + query := "java-extended.ql" + cmd = appendCodeqlQuery(cmd, query) + assert.Equal(t, 3, len(cmd)) + }) } -func (c *CodeqlSarifUploaderMock) GetSarifStatus() (codeql.SarifFileInfo, error) { - if c.counter == 0 { - return codeql.SarifFileInfo{ - ProcessingStatus: "complete", - Errors: nil, - }, nil - } - if c.counter == -1 { - return codeql.SarifFileInfo{ - ProcessingStatus: "failed", - Errors: []string{"upload error"}, - }, nil - } - c.counter-- - return codeql.SarifFileInfo{ - ProcessingStatus: "pending", - Errors: nil, - }, nil +func TestGetLangFromBuildTool(t *testing.T) { + t.Parallel() + + t.Run("Build tool Maven", func(t *testing.T) { + assert.Equal(t, "java", getLangFromBuildTool("maven")) + }) + t.Run("Build tool Pip", func(t *testing.T) { + assert.Equal(t, "python", getLangFromBuildTool("pip")) + }) + t.Run("Build tool Npm", func(t *testing.T) { + assert.Equal(t, "javascript", getLangFromBuildTool("npm")) + }) + t.Run("Build tool Yarn", func(t *testing.T) { + assert.Equal(t, "javascript", getLangFromBuildTool("yarn")) + }) + t.Run("Build tool Golang", func(t *testing.T) { + assert.Equal(t, "go", getLangFromBuildTool("golang")) + }) + t.Run("Build tool Unknown", func(t *testing.T) { + assert.Equal(t, "", getLangFromBuildTool("unknown")) + }) } -type CodeqlSarifUploaderErrorMock struct { - counter int +func TestGetToken(t *testing.T) { + t.Run("Token is set in config", func(t *testing.T) { + config := &codeqlExecuteScanOptions{GithubToken: "token"} + os.Setenv("GITHUB_TOKEN", "token_from_env") + hasToken, token := getToken(config) + os.Clearenv() + assert.True(t, hasToken) + assert.NotEmpty(t, token) + assert.Equal(t, "token", token) + }) + + t.Run("Token is set in env", func(t *testing.T) { + config := &codeqlExecuteScanOptions{} + os.Setenv("GITHUB_TOKEN", "token_from_env") + hasToken, token := getToken(config) + os.Clearenv() + assert.True(t, hasToken) + assert.NotEmpty(t, token) + assert.Equal(t, "token_from_env", token) + }) + + t.Run("Token is not set", func(t *testing.T) { + config := &codeqlExecuteScanOptions{} + hasToken, token := getToken(config) + assert.False(t, hasToken) + assert.Empty(t, token) + }) } -func (c *CodeqlSarifUploaderErrorMock) GetSarifStatus() (codeql.SarifFileInfo, error) { - if c.counter == -1 { - return codeql.SarifFileInfo{}, errors.New("test error") - } - if c.counter == 0 { - return codeql.SarifFileInfo{ - ProcessingStatus: "complete", - Errors: nil, - }, nil +func TestCheckForCompliance(t *testing.T) { + t.Parallel() + + config := &codeqlExecuteScanOptions{VulnerabilityThresholdTotal: 0} + repoInfo := &codeql.RepoInfo{ + FullUrl: "http://github.com/Test/repo", + AnalyzedRef: "refs/heads/branch", } - c.counter-- - return codeql.SarifFileInfo{ProcessingStatus: "Service unavailable"}, nil + + t.Run("Project is compliant", func(t *testing.T) { + scanResults := []codeql.CodeqlFindings{ + { + ClassificationName: codeql.AuditAll, + Total: 10, + Audited: 10, + }, + } + assert.NoError(t, checkForCompliance(scanResults, config, repoInfo)) + }) + + t.Run("Project is not compliant", func(t *testing.T) { + scanResults := []codeql.CodeqlFindings{ + { + ClassificationName: codeql.AuditAll, + Total: 20, + Audited: 10, + }, + } + assert.Error(t, checkForCompliance(scanResults, config, repoInfo)) + }) + + t.Run("Don't check Optional findings", func(t *testing.T) { + scanResults := []codeql.CodeqlFindings{ + { + ClassificationName: codeql.Optional, + Total: 10, + Audited: 0, + }, + } + assert.NoError(t, checkForCompliance(scanResults, config, repoInfo)) + }) } diff --git a/cmd/detectExecuteScan.go b/cmd/detectExecuteScan.go index 106708ded1..070f87e22b 100644 --- a/cmd/detectExecuteScan.go +++ b/cmd/detectExecuteScan.go @@ -389,13 +389,16 @@ func getDetectScript(config detectExecuteScanOptions, utils detectUtils) error { log.Entry().Infof("Downloading Detect Script") - err := utils.DownloadFile("https://detect.synopsys.com/detect8.sh", "detect.sh", nil, nil) - if err != nil { - time.Sleep(time.Second * 5) - err = utils.DownloadFile("https://detect.synopsys.com/detect8.sh", "detect.sh", nil, nil) - if err != nil { - return err + downloadScript := func() error { + if config.UseDetect9 { + return utils.DownloadFile("https://detect.synopsys.com/detect9.sh", "detect.sh", nil, nil) } + return utils.DownloadFile("https://detect.synopsys.com/detect8.sh", "detect.sh", nil, nil) + } + + if err := downloadScript(); err != nil { + time.Sleep(5 * time.Second) + return downloadScript() } return nil @@ -426,12 +429,6 @@ func addDetectArgs(args []string, config detectExecuteScanOptions, utils detectU args = append(args, fmt.Sprintf("--detect.excluded.directories=%s", strings.Join(config.ExcludedDirectories, ","))) } - if config.MinScanInterval > 0 { - //Unmap doesnt work well with min-scan-interval and should be removed - config.Unmap = false - args = append(args, fmt.Sprintf("--detect.blackduck.signature.scanner.arguments='--min-scan-interval=%d'", config.MinScanInterval)) - } - if config.Unmap { if !piperutils.ContainsString(config.ScanProperties, "--detect.project.codelocation.unmap=true") { args = append(args, "--detect.project.codelocation.unmap=true") @@ -630,7 +627,11 @@ func createVulnerabilityReport(config detectExecuteScanOptions, vulns *bd.Vulner CounterHeader: "Entry#", } - vulnItems := vulns.Items + var vulnItems []bd.Vulnerability + if vulns != nil { + vulnItems = vulns.Items + } + sort.Slice(vulnItems, func(i, j int) bool { return vulnItems[i].OverallScore > vulnItems[j].OverallScore }) @@ -722,7 +723,12 @@ func postScanChecksAndReporting(ctx context.Context, config detectExecuteScanOpt errorsOccured := []string{} vulns, err := getVulnerabilitiesWithComponents(config, influx, sys) if err != nil { - return errors.Wrap(err, "failed to fetch vulnerabilities") + if config.GenerateReportsForEmptyProjects && + strings.Contains(err.Error(), "No Components found for project version") { + log.Entry().Debug(err.Error()) + } else { + return errors.Wrap(err, "failed to fetch vulnerabilities") + } } if config.CreateResultIssue && len(config.GithubToken) > 0 && len(config.GithubAPIURL) > 0 && len(config.Owner) > 0 && len(config.Repository) > 0 { @@ -1041,6 +1047,7 @@ func logConfigInVerboseMode(config detectExecuteScanOptions) { config.Token = "********" config.GithubToken = "********" config.PrivateModulesGitToken = "********" + config.RepositoryPassword = "********" debugLog, _ := json.Marshal(config) log.Entry().Debugf("Detect configuration: %v", string(debugLog)) } diff --git a/cmd/detectExecuteScan_generated.go b/cmd/detectExecuteScan_generated.go index 0250f6ce38..e08238bb90 100644 --- a/cmd/detectExecuteScan_generated.go +++ b/cmd/detectExecuteScan_generated.go @@ -22,53 +22,55 @@ import ( ) type detectExecuteScanOptions struct { - Token string `json:"token,omitempty"` - CodeLocation string `json:"codeLocation,omitempty"` - ProjectName string `json:"projectName,omitempty"` - Scanners []string `json:"scanners,omitempty" validate:"possible-values=signature source"` - ScanPaths []string `json:"scanPaths,omitempty"` - DependencyPath string `json:"dependencyPath,omitempty"` - Unmap bool `json:"unmap,omitempty"` - ScanProperties []string `json:"scanProperties,omitempty"` - ServerURL string `json:"serverUrl,omitempty"` - Groups []string `json:"groups,omitempty"` - FailOn []string `json:"failOn,omitempty" validate:"possible-values=ALL BLOCKER CRITICAL MAJOR MINOR NONE"` - VersioningModel string `json:"versioningModel,omitempty" validate:"possible-values=major major-minor semantic full"` - Version string `json:"version,omitempty"` - CustomScanVersion string `json:"customScanVersion,omitempty"` - ProjectSettingsFile string `json:"projectSettingsFile,omitempty"` - GlobalSettingsFile string `json:"globalSettingsFile,omitempty"` - M2Path string `json:"m2Path,omitempty"` - InstallArtifacts bool `json:"installArtifacts,omitempty"` - BuildMaven bool `json:"buildMaven,omitempty"` - PomPath string `json:"pomPath,omitempty"` - IncludedPackageManagers []string `json:"includedPackageManagers,omitempty"` - ExcludedPackageManagers []string `json:"excludedPackageManagers,omitempty"` - MavenExcludedScopes []string `json:"mavenExcludedScopes,omitempty"` - DetectTools []string `json:"detectTools,omitempty"` - ScanOnChanges bool `json:"scanOnChanges,omitempty"` - SuccessOnSkip bool `json:"successOnSkip,omitempty"` - CustomEnvironmentVariables []string `json:"customEnvironmentVariables,omitempty"` - MinScanInterval int `json:"minScanInterval,omitempty"` - GithubToken string `json:"githubToken,omitempty"` - CreateResultIssue bool `json:"createResultIssue,omitempty"` - GithubAPIURL string `json:"githubApiUrl,omitempty"` - Owner string `json:"owner,omitempty"` - Repository string `json:"repository,omitempty"` - Assignees []string `json:"assignees,omitempty"` - CustomTLSCertificateLinks []string `json:"customTlsCertificateLinks,omitempty"` - FailOnSevereVulnerabilities bool `json:"failOnSevereVulnerabilities,omitempty"` - BuildTool string `json:"buildTool,omitempty"` - ExcludedDirectories []string `json:"excludedDirectories,omitempty"` - NpmDependencyTypesExcluded []string `json:"npmDependencyTypesExcluded,omitempty" validate:"possible-values=NONE DEV PEER"` - NpmArguments []string `json:"npmArguments,omitempty"` - PrivateModules string `json:"privateModules,omitempty"` - PrivateModulesGitToken string `json:"privateModulesGitToken,omitempty"` - ScanContainerDistro string `json:"scanContainerDistro,omitempty" validate:"possible-values=ubuntu centos alpine"` - ImageNameTags []string `json:"imageNameTags,omitempty" validate:"required_if=ScanContainerDistro ubuntu ScanContainerDistro centos ScanContainerDistro alpine"` - RegistryURL string `json:"registryUrl,omitempty" validate:"required_if=ScanContainerDistro ubuntu ScanContainerDistro centos ScanContainerDistro alpine"` - RepositoryUsername string `json:"repositoryUsername,omitempty" validate:"required_if=ScanContainerDistro ubuntu ScanContainerDistro centos ScanContainerDistro alpine"` - RepositoryPassword string `json:"repositoryPassword,omitempty" validate:"required_if=ScanContainerDistro ubuntu ScanContainerDistro centos ScanContainerDistro alpine"` + Token string `json:"token,omitempty"` + CodeLocation string `json:"codeLocation,omitempty"` + ProjectName string `json:"projectName,omitempty"` + Scanners []string `json:"scanners,omitempty" validate:"possible-values=signature source"` + ScanPaths []string `json:"scanPaths,omitempty"` + DependencyPath string `json:"dependencyPath,omitempty"` + Unmap bool `json:"unmap,omitempty"` + ScanProperties []string `json:"scanProperties,omitempty"` + ServerURL string `json:"serverUrl,omitempty"` + Groups []string `json:"groups,omitempty"` + FailOn []string `json:"failOn,omitempty" validate:"possible-values=ALL BLOCKER CRITICAL MAJOR MINOR NONE"` + VersioningModel string `json:"versioningModel,omitempty" validate:"possible-values=major major-minor semantic full"` + Version string `json:"version,omitempty"` + CustomScanVersion string `json:"customScanVersion,omitempty"` + ProjectSettingsFile string `json:"projectSettingsFile,omitempty"` + GlobalSettingsFile string `json:"globalSettingsFile,omitempty"` + M2Path string `json:"m2Path,omitempty"` + InstallArtifacts bool `json:"installArtifacts,omitempty"` + BuildMaven bool `json:"buildMaven,omitempty"` + GenerateReportsForEmptyProjects bool `json:"generateReportsForEmptyProjects,omitempty"` + PomPath string `json:"pomPath,omitempty"` + IncludedPackageManagers []string `json:"includedPackageManagers,omitempty"` + ExcludedPackageManagers []string `json:"excludedPackageManagers,omitempty"` + MavenExcludedScopes []string `json:"mavenExcludedScopes,omitempty"` + DetectTools []string `json:"detectTools,omitempty"` + ScanOnChanges bool `json:"scanOnChanges,omitempty"` + SuccessOnSkip bool `json:"successOnSkip,omitempty"` + CustomEnvironmentVariables []string `json:"customEnvironmentVariables,omitempty"` + MinScanInterval int `json:"minScanInterval,omitempty"` + GithubToken string `json:"githubToken,omitempty"` + CreateResultIssue bool `json:"createResultIssue,omitempty"` + GithubAPIURL string `json:"githubApiUrl,omitempty"` + Owner string `json:"owner,omitempty"` + Repository string `json:"repository,omitempty"` + Assignees []string `json:"assignees,omitempty"` + CustomTLSCertificateLinks []string `json:"customTlsCertificateLinks,omitempty"` + FailOnSevereVulnerabilities bool `json:"failOnSevereVulnerabilities,omitempty"` + BuildTool string `json:"buildTool,omitempty"` + ExcludedDirectories []string `json:"excludedDirectories,omitempty"` + NpmDependencyTypesExcluded []string `json:"npmDependencyTypesExcluded,omitempty" validate:"possible-values=NONE DEV PEER"` + NpmArguments []string `json:"npmArguments,omitempty"` + PrivateModules string `json:"privateModules,omitempty"` + PrivateModulesGitToken string `json:"privateModulesGitToken,omitempty"` + ScanContainerDistro string `json:"scanContainerDistro,omitempty" validate:"possible-values=ubuntu centos alpine"` + ImageNameTags []string `json:"imageNameTags,omitempty" validate:"required_if=ScanContainerDistro ubuntu ScanContainerDistro centos ScanContainerDistro alpine"` + RegistryURL string `json:"registryUrl,omitempty" validate:"required_if=ScanContainerDistro ubuntu ScanContainerDistro centos ScanContainerDistro alpine"` + RepositoryUsername string `json:"repositoryUsername,omitempty" validate:"required_if=ScanContainerDistro ubuntu ScanContainerDistro centos ScanContainerDistro alpine"` + RepositoryPassword string `json:"repositoryPassword,omitempty" validate:"required_if=ScanContainerDistro ubuntu ScanContainerDistro centos ScanContainerDistro alpine"` + UseDetect9 bool `json:"useDetect9,omitempty"` } type detectExecuteScanInflux struct { @@ -292,6 +294,7 @@ func addDetectExecuteScanFlags(cmd *cobra.Command, stepConfig *detectExecuteScan cmd.Flags().StringVar(&stepConfig.M2Path, "m2Path", os.Getenv("PIPER_m2Path"), "Path to the location of the local repository that should be used.") cmd.Flags().BoolVar(&stepConfig.InstallArtifacts, "installArtifacts", false, "If enabled, it will install all artifacts to the local maven repository to make them available before running detect. This is required if any maven module has dependencies to other modules in the repository and they were not installed before.") cmd.Flags().BoolVar(&stepConfig.BuildMaven, "buildMaven", false, "Experiment parameter for maven multi-modules projects building") + cmd.Flags().BoolVar(&stepConfig.GenerateReportsForEmptyProjects, "generateReportsForEmptyProjects", false, "If enabled, it will generate reports for empty projects. This could be useful to see the compliance reports in Sirius") cmd.Flags().StringVar(&stepConfig.PomPath, "pomPath", `pom.xml`, "Path to the pom file which should be installed including all children.") cmd.Flags().StringSliceVar(&stepConfig.IncludedPackageManagers, "includedPackageManagers", []string{}, "The package managers that need to be included for this scan. Providing the package manager names with this parameter will ensure that the build descriptor file of that package manager will be searched in the scan folder For the complete list of possible values for this parameter, please refer [Synopsys detect documentation](https://community.synopsys.com/s/document-item?bundleId=integrations-detect&topicId=properties%2Fconfiguration%2Fdetector.html&_LANG=enus&anchor=detector-types-included-advanced)") cmd.Flags().StringSliceVar(&stepConfig.ExcludedPackageManagers, "excludedPackageManagers", []string{}, "The package managers that need to be excluded for this scan. Providing the package manager names with this parameter will ensure that the build descriptor file of that package manager will be ignored in the scan folder For the complete list of possible values for this parameter, please refer [Synopsys detect documentation](https://community.synopsys.com/s/document-item?bundleId=integrations-detect&topicId=properties%2Fconfiguration%2Fdetector.html&_LANG=enus&anchor=detector-types-excluded-advanced)") @@ -300,7 +303,7 @@ func addDetectExecuteScanFlags(cmd *cobra.Command, stepConfig *detectExecuteScan cmd.Flags().BoolVar(&stepConfig.ScanOnChanges, "scanOnChanges", false, "This flag determines if the scan is submitted to the server. If set to true, then the scan request is submitted to the server only when changes are detected in the Open Source Bill of Materials If the flag is set to false, then the scan request is submitted to server regardless of any changes. For more details please refer to the [documentation](https://github.com/blackducksoftware/detect_rescan/blob/master/README.md)") cmd.Flags().BoolVar(&stepConfig.SuccessOnSkip, "successOnSkip", true, "This flag allows forces Black Duck to exit with 0 error code if any step is skipped") cmd.Flags().StringSliceVar(&stepConfig.CustomEnvironmentVariables, "customEnvironmentVariables", []string{}, "A list of environment variables which can be set to prepare the environment to run a BlackDuck scan. This includes a list of environment variables defined by Synopsys. The full list can be found [here](https://community.synopsys.com/s/document-item?bundleId=integrations-detect&topicId=configuring%2Fenvvars.html&_LANG=enus) This list affects the detect script downloaded while running the scan. Right now only detect7.sh is available for downloading") - cmd.Flags().IntVar(&stepConfig.MinScanInterval, "minScanInterval", 0, "This parameter controls the frequency (in number of hours) at which the signature scan is re-submitted for scan. When set to a value greater than 0, the signature scans are skipped until the specified number of hours has elapsed since the last signature scan.") + cmd.Flags().IntVar(&stepConfig.MinScanInterval, "minScanInterval", 0, "[DEPRECATED] This parameter controls the frequency (in number of hours) at which the signature scan is re-submitted for scan. When set to a value greater than 0, the signature scans are skipped until the specified number of hours has elapsed since the last signature scan.") cmd.Flags().StringVar(&stepConfig.GithubToken, "githubToken", os.Getenv("PIPER_githubToken"), "GitHub personal access token as per https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line") cmd.Flags().BoolVar(&stepConfig.CreateResultIssue, "createResultIssue", false, "Activate creation of a result issue in GitHub.") cmd.Flags().StringVar(&stepConfig.GithubAPIURL, "githubApiUrl", `https://api.github.com`, "Set the GitHub API URL.") @@ -320,6 +323,7 @@ func addDetectExecuteScanFlags(cmd *cobra.Command, stepConfig *detectExecuteScan cmd.Flags().StringVar(&stepConfig.RegistryURL, "registryUrl", os.Getenv("PIPER_registryUrl"), "Used accessing for the images to be scanned (typically filled by CPE)") cmd.Flags().StringVar(&stepConfig.RepositoryUsername, "repositoryUsername", os.Getenv("PIPER_repositoryUsername"), "Used accessing for the images to be scanned (typically filled by CPE)") cmd.Flags().StringVar(&stepConfig.RepositoryPassword, "repositoryPassword", os.Getenv("PIPER_repositoryPassword"), "Used accessing for the images to be scanned (typically filled by CPE)") + cmd.Flags().BoolVar(&stepConfig.UseDetect9, "useDetect9", false, "This flag enables the use of the supported version 9 of the Detect Script instead of v8") cmd.MarkFlagRequired("token") cmd.MarkFlagRequired("projectName") @@ -533,6 +537,15 @@ func detectExecuteScanMetadata() config.StepData { Aliases: []config.Alias{}, Default: false, }, + { + Name: "generateReportsForEmptyProjects", + ResourceRef: []config.ResourceReference{}, + Scope: []string{"STEPS", "STAGES", "PARAMETERS"}, + Type: "bool", + Mandatory: false, + Aliases: []config.Alias{}, + Default: false, + }, { Name: "pomPath", ResourceRef: []config.ResourceReference{}, @@ -848,6 +861,15 @@ func detectExecuteScanMetadata() config.StepData { Aliases: []config.Alias{}, Default: os.Getenv("PIPER_repositoryPassword"), }, + { + Name: "useDetect9", + ResourceRef: []config.ResourceReference{}, + Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, + Type: "bool", + Mandatory: false, + Aliases: []config.Alias{{Name: "detect/useDetect9"}}, + Default: false, + }, }, }, Containers: []config.Container{ diff --git a/cmd/detectExecuteScan_test.go b/cmd/detectExecuteScan_test.go index 2787908ce3..d6288fd53d 100644 --- a/cmd/detectExecuteScan_test.go +++ b/cmd/detectExecuteScan_test.go @@ -700,11 +700,9 @@ func TestAddDetectArgs(t *testing.T) { VersioningModel: "major-minor", CodeLocation: "", ScanPaths: []string{"path1", "path2"}, - MinScanInterval: 4, }, expected: []string{ "--testProp1=1", - "--detect.blackduck.signature.scanner.arguments='--min-scan-interval=4'", "--blackduck.url=https://server.url", "--blackduck.api.token=apiToken", "\"--detect.project.name=testName\"", @@ -725,13 +723,11 @@ func TestAddDetectArgs(t *testing.T) { VersioningModel: "major-minor", CodeLocation: "", ScanPaths: []string{"path1", "path2"}, - MinScanInterval: 4, CustomScanVersion: "1.0", }, isPullRequest: true, expected: []string{ "--testProp1=1", - "--detect.blackduck.signature.scanner.arguments='--min-scan-interval=4'", "--blackduck.url=https://server.url", "--blackduck.api.token=apiToken", "\"--detect.project.name=Rapid_scan_on_PRs\"", @@ -763,13 +759,11 @@ func TestAddDetectArgs(t *testing.T) { "--detect.excluded.directories=dir1,dir2", }, ExcludedDirectories: []string{"dir3,dir4"}, - MinScanInterval: 4, CustomScanVersion: "2.0", }, isPullRequest: true, expected: []string{ "--testProp1=1", - "--detect.blackduck.signature.scanner.arguments='--min-scan-interval=4'", "--detect.detector.search.depth=5", "--detect.detector.search.continue=false", "--detect.excluded.directories=dir1,dir2", @@ -802,13 +796,11 @@ func TestAddDetectArgs(t *testing.T) { ScanProperties: []string{ "--detect.maven.build.command= --settings .pipeline/settings.xml -DskipTests install", }, - MinScanInterval: 4, CustomScanVersion: "2.0", }, isPullRequest: true, expected: []string{ "--testProp1=1", - "--detect.blackduck.signature.scanner.arguments='--min-scan-interval=4'", "--detect.maven.build.command=", "--settings", ".pipeline/settings.xml", diff --git a/cmd/gcpPublishEvent.go b/cmd/gcpPublishEvent.go new file mode 100644 index 0000000000..1f8a52e78c --- /dev/null +++ b/cmd/gcpPublishEvent.go @@ -0,0 +1,90 @@ +package cmd + +import ( + "github.com/SAP/jenkins-library/pkg/events" + "github.com/SAP/jenkins-library/pkg/gcp" + "github.com/SAP/jenkins-library/pkg/log" + "github.com/SAP/jenkins-library/pkg/orchestrator" + "github.com/SAP/jenkins-library/pkg/telemetry" + + "github.com/pkg/errors" +) + +type gcpPublishEventUtils interface { + GetConfig() *gcpPublishEventOptions + GetOIDCTokenByValidation(roleID string) (string, error) + GetFederatedToken(projectNumber, pool, provider, token string) (string, error) + Publish(projectNumber string, topic string, token string, key string, data []byte) error +} + +type gcpPublishEventUtilsBundle struct { + config *gcpPublishEventOptions +} + +func (g gcpPublishEventUtilsBundle) GetConfig() *gcpPublishEventOptions { + return g.config +} + +func (g gcpPublishEventUtilsBundle) GetFederatedToken(projectNumber, pool, provider, token string) (string, error) { + return gcp.GetFederatedToken(projectNumber, pool, provider, token) +} + +func (g gcpPublishEventUtilsBundle) Publish(projectNumber string, topic string, token string, key string, data []byte) error { + return gcp.Publish(projectNumber, topic, token, key, data) +} + +// to be implemented through another PR! +func (g gcpPublishEventUtilsBundle) GetOIDCTokenByValidation(roleID string) (string, error) { + return "testToken", nil +} + +func gcpPublishEvent(config gcpPublishEventOptions, telemetryData *telemetry.CustomData) { + utils := gcpPublishEventUtilsBundle{ + config: &config, + } + + err := runGcpPublishEvent(utils) + if err != nil { + // do not fail the step + log.Entry().WithError(err).Warnf("step execution failed") + } +} + +func runGcpPublishEvent(utils gcpPublishEventUtils) error { + config := utils.GetConfig() + + var data []byte + var err error + + provider, err := orchestrator.GetOrchestratorConfigProvider(nil) + if err != nil { + log.Entry().WithError(err).Warning("Cannot infer config from CI environment") + } + + data, err = events.NewEvent(config.EventType, config.EventSource).CreateWithJSONData(config.EventData).ToBytes() + if err != nil { + return errors.Wrap(err, "failed to create event data") + } + + // this is currently returning a mock token. function will be implemented through another PR! + // roleID will come from GeneralConfig.HookConfig.OIDCConfig.RoleID + roleID := "test" + oidcToken, err := utils.GetOIDCTokenByValidation(roleID) + if err != nil { + return errors.Wrap(err, "failed to get OIDC token") + } + + token, err := utils.GetFederatedToken(config.GcpProjectNumber, config.GcpWorkloadIDentityPool, config.GcpWorkloadIDentityPoolProvider, oidcToken) + if err != nil { + return errors.Wrap(err, "failed to get federated token") + } + + err = utils.Publish(config.GcpProjectNumber, config.Topic, token, provider.BuildURL(), data) + if err != nil { + return errors.Wrap(err, "failed to publish event") + } + + log.Entry().Info("event published successfully!") + + return nil +} diff --git a/cmd/gcpPublishEvent_generated.go b/cmd/gcpPublishEvent_generated.go new file mode 100644 index 0000000000..47fcea9b21 --- /dev/null +++ b/cmd/gcpPublishEvent_generated.go @@ -0,0 +1,255 @@ +// 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/splunk" + "github.com/SAP/jenkins-library/pkg/telemetry" + "github.com/SAP/jenkins-library/pkg/validation" + "github.com/spf13/cobra" +) + +type gcpPublishEventOptions struct { + VaultNamespace string `json:"vaultNamespace,omitempty"` + VaultServerURL string `json:"vaultServerUrl,omitempty"` + OIDCToken string `json:"OIDCToken,omitempty"` + GcpProjectNumber string `json:"gcpProjectNumber,omitempty"` + GcpWorkloadIDentityPool string `json:"gcpWorkloadIdentityPool,omitempty"` + GcpWorkloadIDentityPoolProvider string `json:"gcpWorkloadIdentityPoolProvider,omitempty"` + Topic string `json:"topic,omitempty"` + EventSource string `json:"eventSource,omitempty"` + EventType string `json:"eventType,omitempty"` + EventData string `json:"eventData,omitempty"` +} + +// GcpPublishEventCommand Publishes an event to GCP using OIDC authentication (beta) +func GcpPublishEventCommand() *cobra.Command { + const STEP_NAME = "gcpPublishEvent" + + metadata := gcpPublishEventMetadata() + var stepConfig gcpPublishEventOptions + var startTime time.Time + var logCollector *log.CollectorHook + var splunkClient *splunk.Splunk + telemetryClient := &telemetry.Telemetry{} + + var createGcpPublishEventCmd = &cobra.Command{ + Use: STEP_NAME, + Short: "Publishes an event to GCP using OIDC authentication (beta)", + Long: `This step is in beta. +Authentication to GCP is handled by an OIDC token received from, for example, Vault.`, + PreRunE: func(cmd *cobra.Command, _ []string) error { + startTime = time.Now() + log.SetStepName(STEP_NAME) + log.SetVerbose(GeneralConfig.Verbose) + + GeneralConfig.GitHubAccessTokens = ResolveAccessTokens(GeneralConfig.GitHubTokens) + + path, _ := os.Getwd() + fatalHook := &log.FatalHook{CorrelationID: GeneralConfig.CorrelationID, Path: path} + log.RegisterHook(fatalHook) + + err := PrepareConfig(cmd, &metadata, STEP_NAME, &stepConfig, config.OpenPiperFile) + if err != nil { + log.SetErrorCategory(log.ErrorConfiguration) + return err + } + + if len(GeneralConfig.HookConfig.SentryConfig.Dsn) > 0 { + sentryHook := log.NewSentryHook(GeneralConfig.HookConfig.SentryConfig.Dsn, GeneralConfig.CorrelationID) + log.RegisterHook(&sentryHook) + } + + if len(GeneralConfig.HookConfig.SplunkConfig.Dsn) > 0 || len(GeneralConfig.HookConfig.SplunkConfig.ProdCriblEndpoint) > 0 { + splunkClient = &splunk.Splunk{} + logCollector = &log.CollectorHook{CorrelationID: GeneralConfig.CorrelationID} + log.RegisterHook(logCollector) + } + + if err = log.RegisterANSHookIfConfigured(GeneralConfig.CorrelationID); err != nil { + log.Entry().WithError(err).Warn("failed to set up SAP Alert Notification Service log hook") + } + + validation, err := validation.New(validation.WithJSONNamesForStructFields(), validation.WithPredefinedErrorMessages()) + if err != nil { + return err + } + if err = validation.ValidateStruct(stepConfig); err != nil { + log.SetErrorCategory(log.ErrorConfiguration) + return err + } + + return nil + }, + Run: func(_ *cobra.Command, _ []string) { + stepTelemetryData := telemetry.CustomData{} + stepTelemetryData.ErrorCode = "1" + handler := func() { + config.RemoveVaultSecretFiles() + stepTelemetryData.Duration = fmt.Sprintf("%v", time.Since(startTime).Milliseconds()) + stepTelemetryData.ErrorCategory = log.GetErrorCategory().String() + stepTelemetryData.PiperCommitHash = GitCommit + telemetryClient.SetData(&stepTelemetryData) + telemetryClient.Send() + if len(GeneralConfig.HookConfig.SplunkConfig.Dsn) > 0 { + splunkClient.Initialize(GeneralConfig.CorrelationID, + GeneralConfig.HookConfig.SplunkConfig.Dsn, + GeneralConfig.HookConfig.SplunkConfig.Token, + GeneralConfig.HookConfig.SplunkConfig.Index, + GeneralConfig.HookConfig.SplunkConfig.SendLogs) + splunkClient.Send(telemetryClient.GetData(), logCollector) + } + if len(GeneralConfig.HookConfig.SplunkConfig.ProdCriblEndpoint) > 0 { + splunkClient.Initialize(GeneralConfig.CorrelationID, + GeneralConfig.HookConfig.SplunkConfig.ProdCriblEndpoint, + GeneralConfig.HookConfig.SplunkConfig.ProdCriblToken, + GeneralConfig.HookConfig.SplunkConfig.ProdCriblIndex, + GeneralConfig.HookConfig.SplunkConfig.SendLogs) + splunkClient.Send(telemetryClient.GetData(), logCollector) + } + } + log.DeferExitHandler(handler) + defer handler() + telemetryClient.Initialize(GeneralConfig.NoTelemetry, STEP_NAME, GeneralConfig.HookConfig.PendoConfig.Token) + gcpPublishEvent(stepConfig, &stepTelemetryData) + stepTelemetryData.ErrorCode = "0" + log.Entry().Info("SUCCESS") + }, + } + + addGcpPublishEventFlags(createGcpPublishEventCmd, &stepConfig) + return createGcpPublishEventCmd +} + +func addGcpPublishEventFlags(cmd *cobra.Command, stepConfig *gcpPublishEventOptions) { + cmd.Flags().StringVar(&stepConfig.VaultNamespace, "vaultNamespace", os.Getenv("PIPER_vaultNamespace"), "") + cmd.Flags().StringVar(&stepConfig.VaultServerURL, "vaultServerUrl", os.Getenv("PIPER_vaultServerUrl"), "") + cmd.Flags().StringVar(&stepConfig.OIDCToken, "OIDCToken", os.Getenv("PIPER_OIDCToken"), "") + cmd.Flags().StringVar(&stepConfig.GcpProjectNumber, "gcpProjectNumber", os.Getenv("PIPER_gcpProjectNumber"), "") + cmd.Flags().StringVar(&stepConfig.GcpWorkloadIDentityPool, "gcpWorkloadIdentityPool", os.Getenv("PIPER_gcpWorkloadIdentityPool"), "A workload identity pool is an entity that lets you manage external identities.") + cmd.Flags().StringVar(&stepConfig.GcpWorkloadIDentityPoolProvider, "gcpWorkloadIdentityPoolProvider", os.Getenv("PIPER_gcpWorkloadIdentityPoolProvider"), "A workload identity pool provider is an entity that describes a relationship between Google Cloud and your IdP.") + cmd.Flags().StringVar(&stepConfig.Topic, "topic", os.Getenv("PIPER_topic"), "The pubsub topic to which the message is published.") + cmd.Flags().StringVar(&stepConfig.EventSource, "eventSource", os.Getenv("PIPER_eventSource"), "The events source as defined by CDEvents.") + cmd.Flags().StringVar(&stepConfig.EventType, "eventType", os.Getenv("PIPER_eventType"), "") + cmd.Flags().StringVar(&stepConfig.EventData, "eventData", os.Getenv("PIPER_eventData"), "Data to be merged with the generated data for the cloud event data field (JSON)") + +} + +// retrieve step metadata +func gcpPublishEventMetadata() config.StepData { + var theMetaData = config.StepData{ + Metadata: config.StepMetadata{ + Name: "gcpPublishEvent", + Aliases: []config.Alias{}, + Description: "Publishes an event to GCP using OIDC authentication (beta)", + }, + Spec: config.StepSpec{ + Inputs: config.StepInputs{ + Parameters: []config.StepParameters{ + { + Name: "vaultNamespace", + ResourceRef: []config.ResourceReference{}, + Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"}, + Type: "string", + Mandatory: false, + Aliases: []config.Alias{}, + Default: os.Getenv("PIPER_vaultNamespace"), + }, + { + Name: "vaultServerUrl", + ResourceRef: []config.ResourceReference{}, + Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"}, + Type: "string", + Mandatory: false, + Aliases: []config.Alias{}, + Default: os.Getenv("PIPER_vaultServerUrl"), + }, + { + Name: "OIDCToken", + ResourceRef: []config.ResourceReference{}, + Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, + Type: "string", + Mandatory: false, + Aliases: []config.Alias{}, + Default: os.Getenv("PIPER_OIDCToken"), + }, + { + Name: "gcpProjectNumber", + ResourceRef: []config.ResourceReference{}, + Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"}, + Type: "string", + Mandatory: false, + Aliases: []config.Alias{}, + Default: os.Getenv("PIPER_gcpProjectNumber"), + }, + { + Name: "gcpWorkloadIdentityPool", + ResourceRef: []config.ResourceReference{}, + Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"}, + Type: "string", + Mandatory: false, + Aliases: []config.Alias{}, + Default: os.Getenv("PIPER_gcpWorkloadIdentityPool"), + }, + { + Name: "gcpWorkloadIdentityPoolProvider", + ResourceRef: []config.ResourceReference{}, + Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"}, + Type: "string", + Mandatory: false, + Aliases: []config.Alias{}, + Default: os.Getenv("PIPER_gcpWorkloadIdentityPoolProvider"), + }, + { + Name: "topic", + ResourceRef: []config.ResourceReference{}, + Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"}, + Type: "string", + Mandatory: false, + Aliases: []config.Alias{}, + Default: os.Getenv("PIPER_topic"), + }, + { + Name: "eventSource", + ResourceRef: []config.ResourceReference{}, + Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"}, + Type: "string", + Mandatory: false, + Aliases: []config.Alias{}, + Default: os.Getenv("PIPER_eventSource"), + }, + { + Name: "eventType", + ResourceRef: []config.ResourceReference{}, + Scope: []string{"PARAMETERS"}, + Type: "string", + Mandatory: false, + Aliases: []config.Alias{}, + Default: os.Getenv("PIPER_eventType"), + }, + { + Name: "eventData", + ResourceRef: []config.ResourceReference{ + { + Name: "commonPipelineEnvironment", + Param: "custom/eventData", + }, + }, + Scope: []string{}, + Type: "string", + Mandatory: false, + Aliases: []config.Alias{}, + Default: os.Getenv("PIPER_eventData"), + }, + }, + }, + }, + } + return theMetaData +} diff --git a/cmd/gcpPublishEvent_generated_test.go b/cmd/gcpPublishEvent_generated_test.go new file mode 100644 index 0000000000..e5116f69f9 --- /dev/null +++ b/cmd/gcpPublishEvent_generated_test.go @@ -0,0 +1,20 @@ +//go:build unit +// +build unit + +package cmd + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestGcpPublishEventCommand(t *testing.T) { + t.Parallel() + + testCmd := GcpPublishEventCommand() + + // only high level testing performed - details are tested in step generation procedure + assert.Equal(t, "gcpPublishEvent", testCmd.Use, "command name incorrect") + +} diff --git a/cmd/gcpPublishEvent_test.go b/cmd/gcpPublishEvent_test.go new file mode 100644 index 0000000000..9dc5933172 --- /dev/null +++ b/cmd/gcpPublishEvent_test.go @@ -0,0 +1,71 @@ +package cmd + +import ( + "testing" + + "github.com/pkg/errors" + "github.com/stretchr/testify/assert" +) + +type mockGcpPublishEventUtilsBundle struct { + config *gcpPublishEventOptions +} + +func (g *mockGcpPublishEventUtilsBundle) GetConfig() *gcpPublishEventOptions { + return g.config +} + +func (g *mockGcpPublishEventUtilsBundle) GetOIDCTokenByValidation(roleID string) (string, error) { + return "testOIDCtoken123", nil +} + +func (g *mockGcpPublishEventUtilsBundle) GetFederatedToken(projectNumber, pool, provider, token string) (string, error) { + return "testFederatedToken123", nil +} + +func (g *mockGcpPublishEventUtilsBundle) Publish(projectNumber string, topic string, token string, key string, data []byte) error { + if topic == "goodTestCase" { + return nil + } else if topic == "badTestCase" { + return errors.New("failed to send request") + } + return nil +} + +func TestRunGcpPublishEvent(t *testing.T) { + t.Parallel() + + t.Run("happy path", func(t *testing.T) { + t.Parallel() + // init + mock := &mockGcpPublishEventUtilsBundle{ + config: &gcpPublishEventOptions{ + EventType: "PipelineRunStarted", + EventSource: "unittest", + Topic: "goodTestCase", + }} + + // test + err := runGcpPublishEvent(mock) + + // assert + assert.NoError(t, err) + }) + + t.Run("error path", func(t *testing.T) { + t.Parallel() + // init + mock := &mockGcpPublishEventUtilsBundle{ + config: &gcpPublishEventOptions{ + EventType: "PipelineRunStarted", + EventSource: "unittest", + Topic: "badTestCase", + }} + + // test + err := runGcpPublishEvent(mock) + + // assert + assert.EqualError(t, err, "failed to publish event: failed to send request") + }) +} diff --git a/cmd/metadata_generated.go b/cmd/metadata_generated.go index 21360f54dd..56cebc07d4 100644 --- a/cmd/metadata_generated.go +++ b/cmd/metadata_generated.go @@ -7,6 +7,7 @@ import "github.com/SAP/jenkins-library/pkg/config" // GetStepMetadata return a map with all the step metadata mapped to their stepName func GetAllStepMetadata() map[string]config.StepData { return map[string]config.StepData{ + "abapAddonAssemblyKitCheck": abapAddonAssemblyKitCheckMetadata(), "abapAddonAssemblyKitCheckCVs": abapAddonAssemblyKitCheckCVsMetadata(), "abapAddonAssemblyKitCheckPV": abapAddonAssemblyKitCheckPVMetadata(), "abapAddonAssemblyKitCreateTargetVector": abapAddonAssemblyKitCreateTargetVectorMetadata(), @@ -57,6 +58,7 @@ func GetAllStepMetadata() map[string]config.StepData { "detectExecuteScan": detectExecuteScanMetadata(), "fortifyExecuteScan": fortifyExecuteScanMetadata(), "gaugeExecuteTests": gaugeExecuteTestsMetadata(), + "gcpPublishEvent": gcpPublishEventMetadata(), "gctsCloneRepository": gctsCloneRepositoryMetadata(), "gctsCreateRepository": gctsCreateRepositoryMetadata(), "gctsDeploy": gctsDeployMetadata(), diff --git a/cmd/piper.go b/cmd/piper.go index bcd5217a05..1ce4f5089f 100644 --- a/cmd/piper.go +++ b/cmd/piper.go @@ -92,6 +92,7 @@ var GeneralConfig GeneralConfigOptions func Execute() { log.Entry().Infof("Version %s", GitCommit) + rootCmd.AddCommand(GcpPublishEventCommand()) rootCmd.AddCommand(ArtifactPrepareVersionCommand()) rootCmd.AddCommand(ConfigCommand()) rootCmd.AddCommand(DefaultsCommand()) @@ -154,6 +155,7 @@ func Execute() { rootCmd.AddCommand(AbapEnvironmentAssemblePackagesCommand()) rootCmd.AddCommand(AbapAddonAssemblyKitCheckCVsCommand()) rootCmd.AddCommand(AbapAddonAssemblyKitCheckPVCommand()) + rootCmd.AddCommand(AbapAddonAssemblyKitCheckCommand()) rootCmd.AddCommand(AbapAddonAssemblyKitCreateTargetVectorCommand()) rootCmd.AddCommand(AbapAddonAssemblyKitPublishTargetVectorCommand()) rootCmd.AddCommand(AbapAddonAssemblyKitRegisterPackagesCommand()) diff --git a/documentation/docs/steps/abapAddonAssemblyKitCheck.md b/documentation/docs/steps/abapAddonAssemblyKitCheck.md new file mode 100644 index 0000000000..feb11316c8 --- /dev/null +++ b/documentation/docs/steps/abapAddonAssemblyKitCheck.md @@ -0,0 +1,42 @@ +# ${docGenStepName} + +## ${docGenDescription} + +### Artifacts + +- addonDescriptorFile (addon.yml) + The addonDescriptorFile as specified in parameter addonDescriptorFileName is archived as artifact. This is done as this file is the main configuration and usually changed with every run. Thus it simplifies support if the corresponding configuration file is directly accessible in the pipeline. + +## Prerequisites + +* The credentials to access the AAKaaS (Technical Communication User) must be stored in the Jenkins Credential Store +* The step needs an addon.yml containing information about the Product Version and corresponding Software Component Versions/Repositories + +A detailed description of all prerequisites of the scenario and how to configure them can be found in the [Scenario Description](https://www.project-piper.io/scenarios/abapEnvironmentAddons/). + +## ${docGenParameters} + +## ${docGenConfiguration} + +## ${docJenkinsPluginDependencies} + +## Examples + +### Configuration in the config.yml + +The recommended way to configure your pipeline is via the config.yml file. In this case, calling the step in the Jenkinsfile is reduced to one line: + +```groovy +abapAddonAssemblyKitCheck script: this +``` + +If the step is to be configured individually the config.yml should look like this: + +```yaml +steps: + abapAddonAssemblyKitCheck: + abapAddonAssemblyKitCredentialsId: 'abapAddonAssemblyKitCredentialsId', + addonDescriptorFileName: 'addon.yml' +``` + +More convenient ways of configuration (e.g. on stage level) are described in the respective scenario/pipeline documentation. diff --git a/documentation/docs/steps/gcpPublishEvent.md b/documentation/docs/steps/gcpPublishEvent.md new file mode 100644 index 0000000000..63991c1344 --- /dev/null +++ b/documentation/docs/steps/gcpPublishEvent.md @@ -0,0 +1,7 @@ +# ${docGenStepName} + +## ${docGenDescription} + +## ${docGenParameters} + +## ${docGenConfiguration} diff --git a/documentation/mkdocs.yml b/documentation/mkdocs.yml index b56abdf4ce..c7e3674b75 100644 --- a/documentation/mkdocs.yml +++ b/documentation/mkdocs.yml @@ -51,13 +51,15 @@ nav: - 'Set up a Pipeline-Based ABAP Development and Testing Process Using Git-Enabled Change and Transport System': scenarios/gCTS_Scenario.md - Extensibility: extensibility.md - 'Library steps': - - abapAddonAssemblyKitCheckCVs: steps/abapAddonAssemblyKitCheckCVs.md - - abapAddonAssemblyKitCheckPV: steps/abapAddonAssemblyKitCheckPV.md - - abapAddonAssemblyKitCreateTargetVector: steps/abapAddonAssemblyKitCreateTargetVector.md - - abapAddonAssemblyKitPublishTargetVector: steps/abapAddonAssemblyKitPublishTargetVector.md - - abapAddonAssemblyKitRegisterPackages: steps/abapAddonAssemblyKitRegisterPackages.md - - abapAddonAssemblyKitReleasePackages: steps/abapAddonAssemblyKitReleasePackages.md - - abapAddonAssemblyKitReserveNextPackages: steps/abapAddonAssemblyKitReserveNextPackages.md + - 'abapAddonAssemblyKit': + - Check: steps/abapAddonAssemblyKitCheck.md + - CheckCVs: steps/abapAddonAssemblyKitCheckCVs.md + - CheckPV: steps/abapAddonAssemblyKitCheckPV.md + - CreateTargetVector: steps/abapAddonAssemblyKitCreateTargetVector.md + - PublishTargetVector: steps/abapAddonAssemblyKitPublishTargetVector.md + - RegisterPackages: steps/abapAddonAssemblyKitRegisterPackages.md + - ReleasePackages: steps/abapAddonAssemblyKitReleasePackages.md + - ReserveNextPackages: steps/abapAddonAssemblyKitReserveNextPackages.md - abapEnvironmentBuild: steps/abapEnvironmentBuild.md - abapEnvironmentAssemblePackages: steps/abapEnvironmentAssemblePackages.md - abapEnvironmentAssembleConfirm: steps/abapEnvironmentAssembleConfirm.md diff --git a/go.mod b/go.mod index cda780af34..b2c2299b60 100644 --- a/go.mod +++ b/go.mod @@ -1,13 +1,15 @@ module github.com/SAP/jenkins-library -go 1.20 +go 1.21 + +toolchain go1.21.9 // It is a locked dependency of github.com/buildpacks/lifecycle@v0.18.4. The maintainers may remove the lock // in future releases. Check if 'replace' statement still there in their go.mod file. Remove line below if not. replace github.com/moby/buildkit => github.com/moby/buildkit v0.11.6 require ( - cloud.google.com/go/storage v1.30.1 + cloud.google.com/go/storage v1.38.0 github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v0.4.1 github.com/BurntSushi/toml v1.3.2 github.com/Jeffail/gabs/v2 v2.6.1 @@ -18,6 +20,7 @@ require ( github.com/bmatcuk/doublestar v1.3.4 github.com/bndr/gojenkins v1.1.1-0.20240109173050-c316119c46d5 github.com/buildpacks/lifecycle v0.18.4 + github.com/cloudevents/sdk-go/v2 v2.10.1 github.com/docker/cli v24.0.6+incompatible github.com/elliotchance/orderedmap v1.4.0 github.com/evanphx/json-patch v5.7.0+incompatible @@ -33,7 +36,7 @@ require ( github.com/google/go-cmp v0.6.0 github.com/google/go-containerregistry v0.16.1 github.com/google/go-github/v45 v45.2.0 - github.com/google/uuid v1.5.0 + github.com/google/uuid v1.6.0 github.com/hashicorp/go-retryablehttp v0.7.2 github.com/hashicorp/vault/api v1.9.2 github.com/iancoleman/orderedmap v0.2.0 @@ -45,7 +48,7 @@ require ( github.com/microsoft/azure-devops-go-api/azuredevops v1.0.0-b5 github.com/mitchellh/mapstructure v1.5.0 github.com/motemen/go-nuts v0.0.0-20220604134737-2658d0104f31 - github.com/package-url/packageurl-go v0.1.1-0.20220428063043-89078438f170 + github.com/package-url/packageurl-go v0.1.1 github.com/piper-validation/fortify-client-go v0.0.0-20220126145513-7b3e9a72af01 github.com/pkg/errors v0.9.1 github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 @@ -56,9 +59,9 @@ require ( github.com/testcontainers/testcontainers-go v0.10.0 github.com/xuri/excelize/v2 v2.4.1 golang.org/x/mod v0.14.0 - golang.org/x/oauth2 v0.16.0 + golang.org/x/oauth2 v0.17.0 golang.org/x/text v0.14.0 - google.golang.org/api v0.157.0 + google.golang.org/api v0.167.0 gopkg.in/ini.v1 v1.67.0 gopkg.in/yaml.v2 v2.4.0 helm.sh/helm/v3 v3.14.0 @@ -95,21 +98,24 @@ require ( github.com/oapi-codegen/runtime v1.0.0 // indirect github.com/pjbgf/sha1cd v0.3.0 // indirect github.com/skeema/knownhosts v1.2.1 // indirect - go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 // indirect - go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 // indirect - go.opentelemetry.io/otel v1.21.0 // indirect - go.opentelemetry.io/otel/metric v1.21.0 // indirect - go.opentelemetry.io/otel/trace v1.21.0 // indirect + go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.48.0 // indirect + go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.48.0 // indirect + go.opentelemetry.io/otel v1.23.0 // indirect + go.opentelemetry.io/otel/metric v1.23.0 // indirect + go.opentelemetry.io/otel/trace v1.23.0 // indirect + go.uber.org/atomic v1.7.0 // indirect + go.uber.org/multierr v1.6.0 // indirect + go.uber.org/zap v1.17.0 // indirect golang.org/x/image v0.0.0-20220302094943-723b81ca9867 // indirect golang.org/x/tools v0.17.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240304161311-37d4d3c04a78 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240228224816-df926f6c8641 // indirect ) require ( - cloud.google.com/go v0.111.0 // indirect - cloud.google.com/go/compute v1.23.3 // indirect - cloud.google.com/go/iam v1.1.5 // indirect + cloud.google.com/go v0.112.1 // indirect + cloud.google.com/go/compute v1.24.0 // indirect + cloud.google.com/go/iam v1.1.6 // indirect github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0 // indirect github.com/Azure/azure-sdk-for-go/sdk/internal v1.3.0 // indirect github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect @@ -154,7 +160,7 @@ require ( github.com/fatih/color v1.15.0 // indirect github.com/go-errors/errors v1.4.2 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect - github.com/go-logr/logr v1.3.0 // indirect + github.com/go-logr/logr v1.4.1 // indirect github.com/go-openapi/analysis v0.21.2 // indirect github.com/go-openapi/errors v0.20.2 // indirect github.com/go-openapi/jsonpointer v0.19.6 // indirect @@ -173,7 +179,7 @@ require ( github.com/google/gofuzz v1.2.0 // indirect github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 // indirect github.com/googleapis/enterprise-certificate-proxy v0.3.2 // indirect - github.com/googleapis/gax-go/v2 v2.12.0 // indirect + github.com/googleapis/gax-go/v2 v2.12.2 // indirect github.com/gorilla/mux v1.8.0 // indirect github.com/gregjones/httpcache v0.0.0-20190611155906-901d90724c79 // indirect github.com/hashicorp/errwrap v1.1.0 // indirect @@ -237,16 +243,16 @@ require ( go.mongodb.org/mongo-driver v1.11.6 // indirect go.opencensus.io v0.24.0 // indirect go.starlark.net v0.0.0-20230525235612-a134d8f9ddca // indirect - golang.org/x/crypto v0.18.0 + golang.org/x/crypto v0.19.0 golang.org/x/exp v0.0.0-20240205201215-2c58cdc269a3 - golang.org/x/net v0.20.0 // indirect + golang.org/x/net v0.21.0 // indirect golang.org/x/sync v0.6.0 - golang.org/x/sys v0.16.0 // indirect - golang.org/x/term v0.16.0 // indirect + golang.org/x/sys v0.17.0 // indirect + golang.org/x/term v0.17.0 // indirect golang.org/x/time v0.5.0 // indirect google.golang.org/appengine v1.6.8 // indirect - google.golang.org/genproto v0.0.0-20240102182953-50ed04b92917 // indirect - google.golang.org/grpc v1.60.1 // indirect + google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 // indirect + google.golang.org/grpc v1.62.0 // indirect google.golang.org/protobuf v1.32.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect diff --git a/go.sum b/go.sum index c7a1f181d2..7c3f129471 100644 --- a/go.sum +++ b/go.sum @@ -14,22 +14,22 @@ cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKV cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs= cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc= cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY= -cloud.google.com/go v0.111.0 h1:YHLKNupSD1KqjDbQ3+LVdQ81h/UJbJyZG203cEfnQgM= -cloud.google.com/go v0.111.0/go.mod h1:0mibmpKP1TyOOFYQY5izo0LnT+ecvOQ0Sg3OdmMiNRU= +cloud.google.com/go v0.112.1 h1:uJSeirPke5UNZHIb4SxfZklVSiWWVqW4oXlETwZziwM= +cloud.google.com/go v0.112.1/go.mod h1:+Vbu+Y1UU+I1rjmzeMOb/8RfkKJK2Gyxi1X6jJCZLo4= cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o= cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE= cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc= cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg= cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc= cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ= -cloud.google.com/go/compute v1.23.3 h1:6sVlXXBmbd7jNX0Ipq0trII3e4n1/MsADLK6a+aiVlk= -cloud.google.com/go/compute v1.23.3/go.mod h1:VCgBUoMnIVIR0CscqQiPJLAG25E3ZRZMzcFZeQ+h8CI= +cloud.google.com/go/compute v1.24.0 h1:phWcR2eWzRJaL/kOiJwfFsPs4BaKq1j6vnpZrc1YlVg= +cloud.google.com/go/compute v1.24.0/go.mod h1:kw1/T+h/+tK2LJK0wiPPx1intgdAM3j/g3hFDlscY40= cloud.google.com/go/compute/metadata v0.2.3 h1:mg4jlk7mCAj6xXp9UJ4fjI9VUI5rubuGBW5aJ7UnBMY= cloud.google.com/go/compute/metadata v0.2.3/go.mod h1:VAV5nSsACxMJvgaAuX6Pk2AawlZn8kiOGuCv6gTkwuA= cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE= cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk= -cloud.google.com/go/iam v1.1.5 h1:1jTsCu4bcsNsE4iiqNT5SHwrDRCfRmIaaaVFhRveTJI= -cloud.google.com/go/iam v1.1.5/go.mod h1:rB6P/Ic3mykPbFio+vo7403drjlgvoWfYpJhMXEbzv8= +cloud.google.com/go/iam v1.1.6 h1:bEa06k05IO4f4uJonbB5iAgKTPpABy1ayxaIZV/GHVc= +cloud.google.com/go/iam v1.1.6/go.mod h1:O0zxdPeGBoFdWW3HWmBxJsk0pfvNM/p/qa82rWOGTwI= cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw= cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA= @@ -39,8 +39,8 @@ cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0Zeo cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk= cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs= cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0= -cloud.google.com/go/storage v1.30.1 h1:uOdMxAs8HExqBlnLtnQyP0YkvbiDpdGShGKtx6U/oNM= -cloud.google.com/go/storage v1.30.1/go.mod h1:NfxhC0UJE1aXSx7CIIbCf7y9HKT7BiccwkR7+P7gN8E= +cloud.google.com/go/storage v1.38.0 h1:Az68ZRGlnNTpIBbLjSMIV2BDcwwXYlRlQzis0llkpJg= +cloud.google.com/go/storage v1.38.0/go.mod h1:tlUADB0mAb9BgYls9lq+8MGkfzOXuLrnHXlpHmvFJoY= dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= @@ -48,6 +48,7 @@ github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9 github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= github.com/Azure/azure-sdk-for-go v16.2.1+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU= +github.com/Azure/azure-sdk-for-go v68.0.0+incompatible/go.mod h1:9XXNKU+eRnpl9moKnB4QOLf1HestfXbmab5FXxiDBjc= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0 h1:8kDqDngH+DmVBiCtIjCFTGa7MBnsIOkF9IccInFEbjk= github.com/Azure/azure-sdk-for-go/sdk/azcore v1.6.0/go.mod h1:bjGvMhVMb+EEm3VRNQawDMUyMMjo+S5ewNjflkep/0Q= github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0 h1:vcYCAze6p19qBW7MhZybIsqD8sMV8js0NyQM8JDnVtg= @@ -64,20 +65,26 @@ github.com/Azure/go-autorest v14.2.0+incompatible h1:V5VMDjClD3GiElqLWO7mz2MxNAK github.com/Azure/go-autorest v14.2.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= github.com/Azure/go-autorest/autorest v0.11.1/go.mod h1:JFgpikqFJ/MleTTxwepExTKnFUKKszPS8UavbQYUMuw= github.com/Azure/go-autorest/autorest v0.11.29 h1:I4+HL/JDvErx2LjyzaVxllw2lRDB5/BT2Bm4g20iqYw= +github.com/Azure/go-autorest/autorest v0.11.29/go.mod h1:ZtEzC4Jy2JDrZLxvWs8LrBWEBycl1hbT1eknI8MtfAs= github.com/Azure/go-autorest/autorest/adal v0.9.0/go.mod h1:/c022QCutn2P7uY+/oQWWNcK9YU+MH96NgK+jErpbcg= github.com/Azure/go-autorest/autorest/adal v0.9.5/go.mod h1:B7KF7jKIeC9Mct5spmyCB/A8CG/sEz1vwIRGv/bbw7A= github.com/Azure/go-autorest/autorest/adal v0.9.23 h1:Yepx8CvFxwNKpH6ja7RZ+sKX+DWYNldbLiALMC3BTz8= +github.com/Azure/go-autorest/autorest/adal v0.9.23/go.mod h1:5pcMqFkdPhviJdlEy3kC/v1ZLnQl0MH6XA5YCcMhy4c= github.com/Azure/go-autorest/autorest/azure/auth v0.5.12 h1:wkAZRgT/pn8HhFyzfe9UnqOjJYqlembgCTi72Bm/xKk= +github.com/Azure/go-autorest/autorest/azure/auth v0.5.12/go.mod h1:84w/uV8E37feW2NCJ08uT9VBfjfUHpgLVnG2InYD6cg= github.com/Azure/go-autorest/autorest/azure/cli v0.4.6 h1:w77/uPk80ZET2F+AfQExZyEWtn+0Rk/uw17m9fv5Ajc= +github.com/Azure/go-autorest/autorest/azure/cli v0.4.6/go.mod h1:piCfgPho7BiIDdEQ1+g4VmKyD5y+p/XtSNqE6Hc4QD0= github.com/Azure/go-autorest/autorest/date v0.3.0 h1:7gUk1U5M/CQbp9WoqinNzJar+8KY+LPI6wiWrP/myHw= github.com/Azure/go-autorest/autorest/date v0.3.0/go.mod h1:BI0uouVdmngYNUzGWeSYnokU+TrmwEsOqdt8Y6sso74= github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= github.com/Azure/go-autorest/logger v0.2.1 h1:IG7i4p/mDa2Ce4TRyAO8IHnVhAVF3RFU+ZtXWSmf4Tg= +github.com/Azure/go-autorest/logger v0.2.1/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUMfuitfgcfuo= github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0 h1:OBhqkivkhkMqLPymWEppkm7vgPQY2XsHoEkaMQ0AdZY= +github.com/AzureAD/microsoft-authentication-library-for-go v1.0.0/go.mod h1:kgDmCTgBzIEPFElEF+FK0SdjAor06dRq2Go927dnQ6o= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v1.3.2 h1:o7IhLm0Msx3BaB+n3Ag7L8EVlByGnpq14C4YWiu/gL8= github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ= @@ -131,6 +138,7 @@ github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRF github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= github.com/andreyvit/diff v0.0.0-20170406064948-c7f18ee00883/go.mod h1:rCTlJbsFo29Kk6CurOXKm700vrz8f0KW0JNfpkRJY/8= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= +github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= github.com/antchfx/htmlquery v1.2.4 h1:qLteofCMe/KGovBI6SQgmou2QNyedFUW+pE+BpeZ494= github.com/antchfx/htmlquery v1.2.4/go.mod h1:2xO6iu3EVWs7R2JYqBbp8YzG50gj/ofqs5/0VZoDZLc= github.com/antchfx/xpath v1.2.0 h1:mbwv7co+x0RwgeGAOHdrKy89GvHaGvxxBtPK0uF9Zr8= @@ -144,6 +152,7 @@ github.com/aphistic/golf v0.0.0-20180712155816-02c07f170c5a/go.mod h1:3NqKYiepwy github.com/aphistic/sweet v0.2.0/go.mod h1:fWDlIh/isSE9n6EPsRmC0det+whmX6dJid3stzu0Xys= github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= 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/go.mod h1:lB+ZfQJz7igIIfQNfa7Ml4HSf2uFQQRzpGGRXenZAgY= github.com/asaskevich/govalidator v0.0.0-20200907205600-7a23bdc65eef/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw= @@ -173,7 +182,9 @@ github.com/aws/aws-sdk-go-v2/internal/ini v1.3.45/go.mod h1:lD5M20o09/LCuQ2mE62M github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.23 h1:DWYZIsyqagnWL00f8M/SOr9fN063OEQWn9LLTbdYXsk= github.com/aws/aws-sdk-go-v2/internal/v4a v1.0.23/go.mod h1:uIiFgURZbACBEQJfqTZPb/jxO7R+9LeoHUFudtIdeQI= github.com/aws/aws-sdk-go-v2/service/ecr v1.20.2 h1:y6LX9GUoEA3mO0qpFl1ZQHj1rFyPWVphlzebiSt2tKE= +github.com/aws/aws-sdk-go-v2/service/ecr v1.20.2/go.mod h1:Q0LcmaN/Qr8+4aSBrdrXXePqoX0eOuYpJLbYpilmWnA= github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.18.2 h1:PpbXaecV3sLAS6rjQiaKw4/jyq3Z8gNzmoJupHAoBp0= +github.com/aws/aws-sdk-go-v2/service/ecrpublic v1.18.2/go.mod h1:fUHpGXr4DrXkEDpGAjClPsviWf+Bszeb0daKE0blxv8= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11 h1:y2+VQzC6Zh2ojtV2LoC0MNwHWc6qXv/j2vrQtlftkdA= github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.9.11/go.mod h1:iV4q2hsqtNECrfmlXyord9u4zyuFEJX9eLgLpSPzWA8= github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.1.26 h1:CeuSeq/8FnYpPtnuIeLQEEvDv9zUjneuYi8EghMBdwQ= @@ -195,6 +206,7 @@ github.com/aws/smithy-go v1.13.5/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J github.com/aws/smithy-go v1.15.0 h1:PS/durmlzvAFpQHDs4wi4sNNP9ExsqZh6IlfdHXgKK8= github.com/aws/smithy-go v1.15.0/go.mod h1:Tg+OJXh4MB2R/uN61Ko2f6hTZwB/ZYGOtib8J3gBHzA= github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20231003182221-725682229e60 h1:ONd54l3oubhjMPcj7HpjPWvlFI6WXsu0/W7DsKCPI9w= +github.com/awslabs/amazon-ecr-credential-helper/ecr-login v0.0.0-20231003182221-725682229e60/go.mod h1:eSn65Noe23f/Z7A2ESqw3dbhAFSEyzZf38nXcKVNxtE= github.com/aybabtme/rgbterm v0.0.0-20170906152045-cc83f3b3ce59/go.mod h1:q/89r3U2H7sSsE2t6Kca0lfwTK8JdoNGS/yzM/4iH5I= github.com/beorn7/perks v0.0.0-20160804104726-4c0e84591b9a/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= @@ -215,6 +227,7 @@ github.com/bradleyjkemp/cupaloy/v2 v2.7.0 h1:AT0vOjO68RcLyenLCHOGZzSNiuto7ziqzq6 github.com/bradleyjkemp/cupaloy/v2 v2.7.0/go.mod h1:bm7JXdkRd4BHJk9HpwqAI8BoAY1lps46Enkdqw6aRX0= github.com/bshuster-repo/logrus-logstash-hook v0.4.1/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= github.com/bshuster-repo/logrus-logstash-hook v1.0.0 h1:e+C0SB5R1pu//O4MQ3f9cFuPGoOVeF2fE4Og9otCc70= +github.com/bshuster-repo/logrus-logstash-hook v1.0.0/go.mod h1:zsTqEiSzDgAa/8GZR7E1qaXrhYNDKBYy5/dWPTIflbk= github.com/buger/jsonparser v0.0.0-20180808090653-f4dd9f5a6b44/go.mod h1:bbYlZJ7hK1yFx9hf58LP0zeX7UjIGs20ufpu3evjr+s= github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd h1:rFt+Y/IK1aEZkEHchZRSq9OQbsSzIT/OrI8YFFmRIng= github.com/bugsnag/bugsnag-go v0.0.0-20141110184014-b1d153021fcd/go.mod h1:2oa8nejYd4cQ/b0hMIopN0lCRxU0bueqREvZLWFrtK8= @@ -237,6 +250,7 @@ github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/checkpoint-restore/go-criu/v4 v4.1.0/go.mod h1:xUQBLp4RLc5zJtWY++yjOoMoB5lihDt7fai+75m+rGw= github.com/chrismellard/docker-credential-acr-env v0.0.0-20230304212654-82a0ddb27589 h1:krfRl01rzPzxSxyLyrChD+U+MzsBXbm0OwYYB67uF+4= +github.com/chrismellard/docker-credential-acr-env v0.0.0-20230304212654-82a0ddb27589/go.mod h1:OuDyvmLnMCwa2ep4Jkm6nyA0ocJuZlGyk2gGseVzERM= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= @@ -244,10 +258,13 @@ github.com/cilium/ebpf v0.0.0-20200110133405-4032b1d8aae3/go.mod h1:MA5e5Lr8slmE github.com/cilium/ebpf v0.0.0-20200702112145-1c8d4c9ef775/go.mod h1:7cR51M8ViRLIdUjrmSXlK9pkrsDlLHbO8jiB8X8JnOc= github.com/cilium/ebpf v0.2.0/go.mod h1:To2CFviqOWL/M0gIMsvSMlqe7em/l1ALkX1PyjrX2Qs= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cloudevents/sdk-go/v2 v2.10.1 h1:qNFovJ18fWOd8Q9ydWJPk1oiFudXyv1GxJIP7MwPjuM= +github.com/cloudevents/sdk-go/v2 v2.10.1/go.mod h1:GpCBmUj7DIRiDhVvsK5d6WCbgTWs8DxAWTRtAwQmIXs= github.com/cloudflare/circl v1.3.3 h1:fE/Qz0QdIGqeWfnwq0RE0R7MI51s0M2E4Ga9kq5AEMs= github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= -github.com/cncf/xds/go v0.0.0-20230607035331-e9ce68804cb4 h1:/inchEIKaYC1Akx+H+gqO04wryn5h75LSazbRlnya1k= +github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa h1:jQCWAUqqlij9Pgj2i/PB79y4KOPYVyFYdROxgaCwdTQ= +github.com/cncf/xds/go v0.0.0-20231128003011-0fa0005c9caa/go.mod h1:x/1Gn8zydmfq8dk6e9PdstVsDgu9RuyIIJqAaF//0IM= github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= github.com/containerd/aufs v0.0.0-20200908144142-dab0cbea06f4/go.mod h1:nukgQABAEopAHvB6j7cnP5zJ+/3aVcE7hCYqvIwAHyE= github.com/containerd/btrfs v0.0.0-20201111183144-404b9149801e/go.mod h1:jg2QkJcsabfHugurUvvPhS3E08Oxiuh5W/g1ybB4e0E= @@ -257,6 +274,7 @@ github.com/containerd/cgroups v0.0.0-20200531161412-0dbf7f05ba59/go.mod h1:pA0z1 github.com/containerd/cgroups v0.0.0-20200710171044-318312a37340/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= github.com/containerd/cgroups v0.0.0-20200824123100-0b889c03f102/go.mod h1:s5q4SojHctfxANBDvMeIaIovkq29IP48TKAxnhYRxvo= github.com/containerd/cgroups v1.1.0 h1:v8rEWFl6EoqHB+swVNjVoCJE8o3jX7e8nqBGPLaDFBM= +github.com/containerd/cgroups v1.1.0/go.mod h1:6ppBcbh/NOOUU+dMKrykgaBnK9lCIBxHqJDGwsa1mIw= github.com/containerd/console v0.0.0-20180822173158-c12b1e7919c1/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= github.com/containerd/console v0.0.0-20181022165439-0650fd9eeb50/go.mod h1:Tj/on1eG8kiEhd0+fhSDzsPAFESxzBBvdyEgyryXffw= github.com/containerd/console v0.0.0-20191206165004-02ecf6a7291e/go.mod h1:8Pf4gM6VEbTNRIT26AyyU7hxdQU3MvAvxVI0sc00XBE= @@ -276,6 +294,7 @@ github.com/containerd/continuity v0.0.0-20191127005431-f65d91d395eb/go.mod h1:GL github.com/containerd/continuity v0.0.0-20200710164510-efbc4488d8fe/go.mod h1:cECdGN1O8G9bgKTlLhuPJimka6Xb/Gg7vYzCTNVxhvo= github.com/containerd/continuity v0.0.0-20201208142359-180525291bb7/go.mod h1:kR3BEg7bDFaEddKm54WSmrol1fKWDU1nKYkgrcgZT7Y= github.com/containerd/continuity v0.4.2 h1:v3y/4Yz5jwnvqPKJJ+7Wf93fyWoCB3F5EclWG023MDM= +github.com/containerd/continuity v0.4.2/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= github.com/containerd/fifo v0.0.0-20180307165137-3d5202aec260/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv3Kuk8dQz2ZQXpnv/UZZUHUCL7pnLehbXgQI= github.com/containerd/fifo v0.0.0-20200410184934-f15a3290365b/go.mod h1:jPQ2IAeZRCYxpS/Cm1495vGFww6ecHmMk1YJH2Q5ln0= @@ -322,6 +341,7 @@ github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46t github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= +github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= github.com/cyphar/filepath-securejoin v0.2.2/go.mod h1:FpkQEhXnPnOthhzymB7CGsFk2G9VLXONKD9G7QGMM+4= github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= @@ -337,11 +357,14 @@ github.com/denverdino/aliyungo v0.0.0-20190125010748-a747050bb1ba/go.mod h1:dV8l github.com/dgrijalva/jwt-go v0.0.0-20170104182250-a601269ab70c/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= github.com/dimchansky/utfbom v1.1.1 h1:vV6w1AhK4VMnhBno/TPVCoK9U/LP0PkLCS9tbxHdi/U= +github.com/dimchansky/utfbom v1.1.1/go.mod h1:SxdoEBH5qIqFocHMyGOXVAybYJdr71b1Q/j0mACtrfE= github.com/distribution/distribution/v3 v3.0.0-20221208165359-362910506bc2 h1:aBfCb7iqHmDEIp6fBvC/hQUddQfg+3qdYjwzaiP9Hnc= +github.com/distribution/distribution/v3 v3.0.0-20221208165359-362910506bc2/go.mod h1:WHNsWjnIn2V1LYOrME7e8KxSeKunYHsxEm4am0BUtcI= github.com/distribution/reference v0.5.0 h1:/FUIFXtfc/x2gpa5/VGfiGLuOIdYa1t65IKK2OFGvA0= github.com/distribution/reference v0.5.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= github.com/dnaeon/go-vcr v1.0.1/go.mod h1:aBB1+wY4s93YsC3HHjMBMrwTj2R9FHDzUr9KyGc8n1E= github.com/dnaeon/go-vcr v1.2.0 h1:zHCHvJYTMh1N7xnV7zf1m1GPBF9Ad0Jk/whtQ1663qI= +github.com/dnaeon/go-vcr v1.2.0/go.mod h1:R4UdLID7HZT3taECzJs4YgbbH6PIGXB6W/sc5OLb6RQ= github.com/docker/cli v24.0.6+incompatible h1:fF+XCQCgJjjQNIMjzaSmiKJSCcfcXb3TWTcc7GAneOY= github.com/docker/cli v24.0.6+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= github.com/docker/distribution v0.0.0-20190905152932-14b96e55d84c/go.mod h1:0+TTO4EOBfRPhZXAeF1Vu+W3hHZ8eLp8PgKVZlcvtFY= @@ -368,12 +391,14 @@ github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4 github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7 h1:UhxFibDNY/bfvqU5CAUmr9zpesgbU6SWc8/B4mflAE4= +github.com/docker/libtrust v0.0.0-20160708172513-aabc10ec26b7/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/elazarl/goproxy v0.0.0-20180725130230-947c36da3153/go.mod h1:/Zj4wYkgs4iZTTu3o/KG3Itv/qCCa8VVMlb3i9OVuzc= github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU= +github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= github.com/elliotchance/orderedmap v1.4.0 h1:wZtfeEONCbx6in1CZyE6bELEt/vFayMvsxqI5SgsR+A= github.com/elliotchance/orderedmap v1.4.0/go.mod h1:wsDwEaX5jEoyhbs7x93zk2H/qv0zwuhg4inXhDkYqys= github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs= @@ -386,7 +411,8 @@ github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymF github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= -github.com/envoyproxy/protoc-gen-validate v1.0.2 h1:QkIBuU5k+x7/QXPvPPnWXWlCdaBFApVqftFV6k087DA= +github.com/envoyproxy/protoc-gen-validate v1.0.4 h1:gVPz/FMfvh57HdSJQyvBtF00j8JU4zdyUgIUNhlgg0A= +github.com/envoyproxy/protoc-gen-validate v1.0.4/go.mod h1:qys6tmnRsYrQqIhm2bvKZH4Blx/1gTIZ2UKVY1M+Yew= github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v5.7.0+incompatible h1:vgGkfT/9f8zE6tvSCe74nfpAVDQ2tG6yudJd8LBksgI= github.com/evanphx/json-patch v5.7.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= @@ -398,9 +424,11 @@ github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2 github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/foxcpp/go-mockdns v1.0.0 h1:7jBqxd3WDWwi/6WhDvacvH1XsN3rOLXyHM1uhvIx6FI= +github.com/foxcpp/go-mockdns v1.0.0/go.mod h1:lgRN6+KxQBawyIghpnl5CezHFGS9VLzvtVlwxvzXTQ4= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= +github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXtdwXqoenmZCw6S+25EAm2MkxbG0deNDu4cbSA= github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= @@ -412,6 +440,7 @@ github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeME github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32 h1:Mn26/9ZMNWSw9C9ERFA1PUxfmGpolnw2v0bKOREu5ew= github.com/ghodss/yaml v1.0.1-0.20190212211648-25d852aebe32/go.mod h1:GIjDIg/heH5DOkXY3YJ/wNhfHsQHoXGjl8G8amsYQ1I= github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY= +github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4= github.com/globalsign/mgo v0.0.0-20180905125535-1ca0a4f7cbcb/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= github.com/globalsign/mgo v0.0.0-20181015135952-eeefdecb41b8/go.mod h1:xkRDCp4j0OGD1HRkm4kmhM+pmpv3AKq5SU7GMg4oO/Q= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= @@ -421,6 +450,7 @@ github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmS github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU= github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= +github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= github.com/go-git/go-git/v5 v5.11.0 h1:XIZc1p+8YzypNr34itUfSvYJcv+eYdTnTvOZ2vD3cA4= github.com/go-git/go-git/v5 v5.11.0/go.mod h1:6GFcX2P3NM7FPBfpePbpLd21XxsgdAt+lKqXmCUiUCY= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= @@ -436,8 +466,9 @@ github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU= github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= -github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ= +github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-openapi/analysis v0.0.0-20180825180245-b006789cd277/go.mod h1:k70tL6pCuVxPJOHXQ+wIac1FUrvNkHolPie/cLEU6hI= @@ -520,6 +551,7 @@ github.com/go-openapi/validate v0.21.0/go.mod h1:rjnrwK57VJ7A8xqfpAOEKRH8yQSGUri github.com/go-openapi/validate v0.22.0 h1:b0QecH6VslW/TxtpKgzpO1SNG7GU2FsaqKdP1E2T50Y= github.com/go-openapi/validate v0.22.0/go.mod h1:rjnrwK57VJ7A8xqfpAOEKRH8yQSGUriMu5/zuPSQ1hg= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= @@ -535,6 +567,7 @@ github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/me github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP3XYfe4= github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= +github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls= github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg= github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= github.com/gobuffalo/attrs v0.0.0-20190224210810-a9411de4debd/go.mod h1:4duuawTqi2wkkpB4ePgWMaai6/Kc6WEz83bhFwpHzj0= @@ -576,6 +609,7 @@ github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt v3.2.1+incompatible h1:73Z+4BJcrTC+KczS6WvTPvRGOp1WmfEP4Q1lOd9Z/+c= github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= +github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= 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-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -592,6 +626,7 @@ github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4= github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8= github.com/golang/mock v1.6.0 h1:ErTB+efbowRARo13NNdxyJji2egdxLGQhRaY+DUumQc= +github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs= 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= @@ -612,6 +647,7 @@ github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/gomodule/redigo v1.8.2 h1:H5XSIre1MB5NbPYFp+i1NBbb5qN1W8Y8YAQoAYbkm8k= +github.com/gomodule/redigo v1.8.2/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v1.0.1 h1:gK4Kx5IaGY9CD5sPJ36FHiBJ6ZXl0kilRiiCj+jdYp4= @@ -646,6 +682,7 @@ github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPg github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0= github.com/google/martian/v3 v3.3.2 h1:IqNFLAmvJOgVlpdEBiQbDc2EwKW77amAycfTuWKdfvw= +github.com/google/martian/v3 v3.3.2/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= @@ -654,6 +691,7 @@ github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hf github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM= github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1 h1:K6RDEckDVWvDI9JAJYCmNdQXq6neHJOYx3V6jnqNEec= +github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/s2a-go v0.1.7 h1:60BLSyTrOV4/haCDW4zb1guZItoSq8foHCXrAnjBo/o= github.com/google/s2a-go v0.1.7/go.mod h1:50CgR4k1jNlWBu4UfS4AcfhVe1r6pdZPygJ3R8F0Qdw= @@ -663,19 +701,20 @@ github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+ github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.2.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU= -github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/googleapis/enterprise-certificate-proxy v0.3.2 h1:Vie5ybvEvT75RniqhfFxPRy3Bf7vr3h0cechB90XaQs= github.com/googleapis/enterprise-certificate-proxy v0.3.2/go.mod h1:VLSiSSBs/ksPL8kq3OBOQ6WRI2QnaFynd1DCjZ62+V0= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= -github.com/googleapis/gax-go/v2 v2.12.0 h1:A+gCJKdRfqXkr+BIRGtZLibNXf0m1f9E4HG56etFpas= -github.com/googleapis/gax-go/v2 v2.12.0/go.mod h1:y+aIqrI5eb1YGMVJfuV3185Ts/D7qKpsEkdD5+I6QGU= +github.com/googleapis/gax-go/v2 v2.12.2 h1:mhN09QQW1jEWeMF74zGR81R30z4VJzjZsfkUhuHF+DA= +github.com/googleapis/gax-go/v2 v2.12.2/go.mod h1:61M8vcyyXR2kqKFxKrfA22jaA8JGF7Dc8App1U3H6jc= github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= github.com/gorilla/handlers v1.5.1 h1:9lRY6j8DEeeBT10CvO9hGW0gmky0BprnvDI5vfhUHH4= +github.com/gorilla/handlers v1.5.1/go.mod h1:t8XrUpc4KVXb7HGyJ4/cEnwQiaxrX/hz1Zv/4g96P1Q= github.com/gorilla/mux v1.7.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So= @@ -714,6 +753,7 @@ github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjG github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= github.com/hashicorp/golang-lru v1.0.2 h1:dV3g9Z/unq5DpblPpw+Oqcv4dU/1omnb4Ok8iPY6p1c= +github.com/hashicorp/golang-lru v1.0.2/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.1-vault-5 h1:kI3hhbbyzr4dldA8UdTb7ZlVVlI2DACdCfz31RPDgJM= github.com/hashicorp/hcl v1.0.1-vault-5/go.mod h1:XYhtn6ijBSAj6n4YqAaf7RBPS4I06AItNorpy+MoQNM= github.com/hashicorp/vault/api v1.9.2 h1:YjkZLJ7K3inKgMZ0wzCU9OHqc+UqMQyXsPXnf3Cl2as= @@ -784,12 +824,14 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= +github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.5/go.mod h1:9r2w37qlBe7rQ6e1fg1S/9xpWHSnaqNdHD3WcMdbPDA= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4= github.com/liggitt/tabwriter v0.0.0-20181228230101-89fcab3d43de h1:9TO3cAIGXtEhnIaL+V+BEER86oLrvS+kWobKpbJuye0= @@ -863,6 +905,7 @@ github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YO github.com/moby/sys/mount v0.2.0/go.mod h1:aAivFE2LB3W4bACsUXChRHQ0qKWsetY4Y9V7sxOougM= github.com/moby/sys/mountinfo v0.4.0/go.mod h1:rEr8tzG/lsIZHBtN/JjGG+LMYx9eXgW2JI+6q0qou+A= github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vygl78= +github.com/moby/sys/mountinfo v0.6.2/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI= github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= github.com/moby/sys/symlink v0.1.0/go.mod h1:GGDODQmbFOjFsXvfLVn3+ZRxkch54RkSiGqsZeMYowQ= @@ -912,6 +955,7 @@ github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108 github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE= github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU= github.com/onsi/ginkgo/v2 v2.13.0 h1:0jY9lJquiL8fcf3M4LAXN5aMlS/b2BV86HFFPCPMgE4= +github.com/onsi/ginkgo/v2 v2.13.0/go.mod h1:TE309ZR8s5FsKKpuB1YAQYBzCaAfUgatB/xlT/ETL/o= github.com/onsi/gomega v0.0.0-20151007035656-2152b45fa28a/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA= 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= @@ -919,6 +963,7 @@ github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1Cpa github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo= github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg= +github.com/onsi/gomega v1.29.0/go.mod h1:9sxs+SwGrKI0+PWe4Fxa9tFQQBG5xSsSbMXOI8PPpoQ= github.com/opencontainers/go-digest v0.0.0-20170106003457-a6d0ee40d420/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v0.0.0-20180430190053-c9281466c8b2/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s= @@ -947,8 +992,8 @@ github.com/opencontainers/selinux v1.8.0/go.mod h1:RScLhm78qiWa2gbVCcGkC7tCGdgk3 github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b h1:FfH+VrHHk6Lxt9HdVS0PXzSXFyS2NbZKXv33FYPol0A= github.com/opentracing/opentracing-go v1.2.1-0.20220228012449-10b1cf09e00b/go.mod h1:AC62GU6hc0BrNm+9RK9VSiwa/EUe1bkIeFORAMcHvJU= -github.com/package-url/packageurl-go v0.1.1-0.20220428063043-89078438f170 h1:DiLBVp4DAcZlBVBEtJpNWZpZVq0AEeCY7Hqk8URVs4o= -github.com/package-url/packageurl-go v0.1.1-0.20220428063043-89078438f170/go.mod h1:uQd4a7Rh3ZsVg5j0lNyAfyxIeGde9yrlhjF78GzeW0c= +github.com/package-url/packageurl-go v0.1.1 h1:KTRE0bK3sKbFKAk3yy63DpeskU7Cvs/x/Da5l+RtzyU= +github.com/package-url/packageurl-go v0.1.1/go.mod h1:uQd4a7Rh3ZsVg5j0lNyAfyxIeGde9yrlhjF78GzeW0c= github.com/pasztorpisti/qs v0.0.0-20171216220353-8d6c33ee906c h1:Gcce/r5tSQeprxswXXOwQ/RBU1bjQWVd9dB7QKoPXBE= github.com/pasztorpisti/qs v0.0.0-20171216220353-8d6c33ee906c/go.mod h1:1iCZ0433JJMecYqCa+TdWA9Pax8MGl4ByuNDZ7eSnQY= github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= @@ -956,12 +1001,15 @@ github.com/pelletier/go-toml v1.7.0/go.mod h1:vwGMzjaWMwyfHwgIBhI2YUM4fB6nL6lVAv github.com/peterbourgon/diskv v2.0.1+incompatible h1:UBdAOUP5p4RWqPBg048CAvpKN+vxiaj6gdUUzhl4XmI= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5 h1:Ii+DKncOVM8Cu1Hc+ETb5K+23HdAMvESYE3ZJ5b5cMI= +github.com/phayes/freeport v0.0.0-20220201140144-74d24b5ae9f5/go.mod h1:iIss55rKnNBTvrwdmkUpLnDpZoAHvWaiq5+iMmen4AE= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= +github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= github.com/piper-validation/fortify-client-go v0.0.0-20220126145513-7b3e9a72af01 h1:eGWtA25A6ryV+I2wHt0iE+i6euveKwbCi9d87RZu0fA= github.com/piper-validation/fortify-client-go v0.0.0-20220126145513-7b3e9a72af01/go.mod h1:EZkdCgngw/tInYdidqDQlRIXvyM1fSbqn/vx83YNCcw= github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= +github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -1015,6 +1063,7 @@ github.com/rogpeppe/go-internal v1.2.2/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= github.com/rogpeppe/go-internal v1.8.1/go.mod h1:JeRgkft04UBgHMgCIwADu4Pn6Mtm5d4nPKWu0nJ5d+o= github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= +github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= @@ -1026,6 +1075,7 @@ github.com/safchain/ethtool v0.0.0-20190326074333-42ed695e3de8/go.mod h1:Z0q5wiB github.com/saintfish/chardet v0.0.0-20120816061221-3af4cd4741ca/go.mod h1:uugorj2VCxiV1x+LzaIdVa9b4S4qGAcH6cbhh4qVxOU= github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= github.com/sclevine/spec v1.4.0 h1:z/Q9idDcay5m5irkZ28M7PtQM4aOISzOpj4bUPkDee8= +github.com/sclevine/spec v1.4.0/go.mod h1:LvpgJaFyvQzRvc1kaDs0bulYwzC70PbiYjC4QnFHkOM= github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvWlF4P2Ca7zGrPiEpWo= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= @@ -1103,6 +1153,8 @@ github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/vbatts/tar-split v0.11.5 h1:3bHCTIheBm1qFTcgh9oPu+nNBtX+XJIupG/vacinCts= github.com/vbatts/tar-split v0.11.5/go.mod h1:yZbwRsSeGjusneWgA781EKej9HF8vme8okylkAeNKLk= github.com/vektah/gqlparser v1.1.2/go.mod h1:1ycwN7Ij5njmMkPPAOaRFY4rET2Enx7IkVv3vaXspKw= @@ -1160,23 +1212,30 @@ go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0= go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1 h1:SpGay3w+nEwMpfVnbqOLH5gY52/foP8RE8UzTZ1pdSE= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.46.1/go.mod h1:4UoMYEZOC0yN/sPGH76KPkkU7zgiEWYWL9vwmbnTJPE= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1 h1:aFJWCqJMNjENlcleuuOkGAPH82y0yULBScfXcIEdS24= -go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.46.1/go.mod h1:sEGXWArGqc3tVa+ekntsN65DmVbVeW+7lTKTjZF3/Fo= -go.opentelemetry.io/otel v1.21.0 h1:hzLeKBZEL7Okw2mGzZ0cc4k/A7Fta0uoPgaJCr8fsFc= -go.opentelemetry.io/otel v1.21.0/go.mod h1:QZzNPQPm1zLX4gZK4cMi+71eaorMSGT3A4znnUvNNEo= -go.opentelemetry.io/otel/metric v1.21.0 h1:tlYWfeo+Bocx5kLEloTjbcDwBuELRrIFxwdQ36PlJu4= -go.opentelemetry.io/otel/metric v1.21.0/go.mod h1:o1p3CA8nNHW8j5yuQLdc1eeqEaPfzug24uvsyIEJRWM= -go.opentelemetry.io/otel/sdk v1.19.0 h1:6USY6zH+L8uMH8L3t1enZPR3WFEmSTADlqldyHtJi3o= -go.opentelemetry.io/otel/trace v1.21.0 h1:WD9i5gzvoUPuXIXH24ZNBudiarZDKuekPqi/E8fpfLc= -go.opentelemetry.io/otel/trace v1.21.0/go.mod h1:LGbsEB0f9LGjN+OZaQQ26sohbOmiMR+BaslueVtS/qQ= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.48.0 h1:P+/g8GpuJGYbOp2tAdKrIPUX9JO02q8Q0YNlHolpibA= +go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.48.0/go.mod h1:tIKj3DbO8N9Y2xo52og3irLsPI4GW02DSMtrVgNMgxg= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.48.0 h1:doUP+ExOpH3spVTLS0FcWGLnQrPct/hD/bCPbDRUEAU= +go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.48.0/go.mod h1:rdENBZMT2OE6Ne/KLwpiXudnAsbdrdBaqBvTN8M8BgA= +go.opentelemetry.io/otel v1.23.0 h1:Df0pqjqExIywbMCMTxkAwzjLZtRf+bBKLbUcpxO2C9E= +go.opentelemetry.io/otel v1.23.0/go.mod h1:YCycw9ZeKhcJFrb34iVSkyT0iczq/zYDtZYFufObyB0= +go.opentelemetry.io/otel/metric v1.23.0 h1:pazkx7ss4LFVVYSxYew7L5I6qvLXHA0Ap2pwV+9Cnpo= +go.opentelemetry.io/otel/metric v1.23.0/go.mod h1:MqUW2X2a6Q8RN96E2/nqNoT+z9BSms20Jb7Bbp+HiTo= +go.opentelemetry.io/otel/sdk v1.22.0 h1:6coWHw9xw7EfClIC/+O31R8IY3/+EiRFHevmHafB2Gw= +go.opentelemetry.io/otel/sdk v1.22.0/go.mod h1:iu7luyVGYovrRpe2fmj3CVKouQNdTOkxtLzPvPz1DOc= +go.opentelemetry.io/otel/trace v1.23.0 h1:37Ik5Ib7xfYVb4V1UtnT97T1jI+AoIYkJyPkuL4iJgI= +go.opentelemetry.io/otel/trace v1.23.0/go.mod h1:GSGTbIClEsuZrGIzoEHqsVfxgn5UkggkflQwDScNUsk= go.starlark.net v0.0.0-20230525235612-a134d8f9ddca h1:VdD38733bfYv5tUZwEIskMM93VanwNIi5bIKnDrJdEY= go.starlark.net v0.0.0-20230525235612-a134d8f9ddca/go.mod h1:jxU+3+j+71eXOW14274+SmmuW82qJzl6iZSeqEtTGds= 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= +go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= +go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= +go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.17.0 h1:MTjgFu6ZLKvY6Pvaqk97GlxNBuMpV4Hy/3P6tRGlI2U= +go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo= golang.org/x/crypto v0.0.0-20171113213409-9f005a07e0d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181009213950-7c1a557ab941/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -1200,8 +1259,8 @@ golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5y golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= -golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/crypto v0.19.0 h1:ENy+Az/9Y1vSrlrvBSyna3PITt4tiZLf7sgCjZBX7Wo= +golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -1293,16 +1352,16 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= -golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20220524215830-622c5d57e401/go.mod h1:DAh4E804XQdzx2j+YRIaUnCqCV2RuMz24cGBJ5QYIrc= -golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ= -golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o= +golang.org/x/oauth2 v0.17.0 h1:6m3ZPmLEFdVxKKWnKq4VqZ60gutO35zm+zrAHVmHyDQ= +golang.org/x/oauth2 v0.17.0/go.mod h1:OzPDGQiuQMguemayvdylqddI7qcD9lnSDb+1FiwQ5HA= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -1403,8 +1462,8 @@ golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.17.0 h1:25cE3gD+tdBA7lp7QfhuV+rJiE9YXTcS3VG1SqssI/Y= +golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= @@ -1412,8 +1471,8 @@ golang.org/x/term v0.0.0-20220526004731-065cf7ba2467/go.mod h1:jbD1KX2456YbFQfuX golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.16.0 h1:m+B6fahuftsE9qjo0VWp2FW0mB3MTJvR0BaMQrq0pmE= -golang.org/x/term v0.16.0/go.mod h1:yn7UURbUtPyrVJPGPq404EukNFxcm/foM+bV/bfcDsY= +golang.org/x/term v0.17.0 h1:mkTF7LCd6WGJNL3K1Ad7kwxNfYAW6a8a8QqtMblp/4U= +golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -1434,6 +1493,7 @@ golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxb 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-20200630173020-3af7569d3a1e/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -1498,7 +1558,8 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20220907171357-04be3eba64a2 h1:H2TDz8ibqkAF6YGhCdN3jS9O0/s90v0rJh3X/OLHEUk= +golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 h1:+cNy6SZtPcJQH3LJVLOSmiC7MMxXNOb3PU/VUEz+EhU= +golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90= google.golang.org/api v0.0.0-20160322025152-9bf6e6e569ff/go.mod h1:4mhQ8q/RsB7i+udVvVy5NUi08OU8ZlA0gRVgrF7VFY0= google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE= google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M= @@ -1516,8 +1577,8 @@ google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0M google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE= google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM= google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc= -google.golang.org/api v0.157.0 h1:ORAeqmbrrozeyw5NjnMxh7peHO0UzV4wWYSwZeCUb20= -google.golang.org/api v0.157.0/go.mod h1:+z4v4ufbZ1WEpld6yMGHyggs+PmAHiaLNj5ytP3N01g= +google.golang.org/api v0.167.0 h1:CKHrQD1BLRii6xdkatBDXyKzM0mkawt2QP+H3LtPmSE= +google.golang.org/api v0.167.0/go.mod h1:4FcBc686KFi7QI/U51/2GKKevfZMpM17sCdibqe/bSA= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= @@ -1560,12 +1621,12 @@ google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6D google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= google.golang.org/genproto v0.0.0-20201110150050-8816d57aaa9a/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no= -google.golang.org/genproto v0.0.0-20240102182953-50ed04b92917 h1:nz5NESFLZbJGPFxDT/HCn+V1mZ8JGNoY4nUpmW/Y2eg= -google.golang.org/genproto v0.0.0-20240102182953-50ed04b92917/go.mod h1:pZqR+glSb11aJ+JQcczCvgf47+duRuzNSKqE8YAQnV0= -google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 h1:rcS6EyEaoCO52hQDupoSfrxI3R6C2Tq741is7X8OvnM= -google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917/go.mod h1:CmlNWB9lSezaYELKS5Ym1r44VrrbPUa7JTvw+6MbpJ0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac h1:nUQEQmH/csSvFECKYRv6HWEyypysidKl2I6Qpsglq/0= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240116215550-a9fa1716bcac/go.mod h1:daQN87bsDqDoe316QbbvX60nMoJQa4r6Ds0ZuoAe5yA= +google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9 h1:9+tzLLstTlPTRyJTh+ah5wIMsBW5c4tQwGTN3thOW9Y= +google.golang.org/genproto v0.0.0-20240213162025-012b6fc9bca9/go.mod h1:mqHbVIp48Muh7Ywss/AD6I5kNVKZMmAa/QEW58Gxp2s= +google.golang.org/genproto/googleapis/api v0.0.0-20240304161311-37d4d3c04a78 h1:SzXBGiWM1LNVYLCRP3e0/Gsze804l4jGoJ5lYysEO5I= +google.golang.org/genproto/googleapis/api v0.0.0-20240304161311-37d4d3c04a78/go.mod h1:O1cOfN1Cy6QEYr7VxtjOyP5AdAuR0aJ/MYZaaof623Y= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240228224816-df926f6c8641 h1:DKU1r6Tj5s1vlU/moGhuGz7E3xRfwjdAfDzbsaQJtEY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240228224816-df926f6c8641/go.mod h1:UCOku4NytXMJuLQE5VuqA5lX3PcHCBo8pxNyvkf4xBs= google.golang.org/grpc v0.0.0-20160317175043-d3ddb4469d5a/go.mod h1:yo6s7OP7yaDglbqo1J04qKzAhqBH6lvTonzMVmEdcZw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= @@ -1583,8 +1644,8 @@ google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3Iji google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak= google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc= -google.golang.org/grpc v1.60.1 h1:26+wFr+cNqSGFcOXcabYC0lUVJVRa2Sb2ortSK7VrEU= -google.golang.org/grpc v1.60.1/go.mod h1:OlCHIeLYqSSsLi6i49B5QGdzaMZK9+M7LXN2FKz4eGM= +google.golang.org/grpc v1.62.0 h1:HQKZ/fa1bXkX1oFOvSjmZEUL8wLSaZTjCcLAlmZRtdk= +google.golang.org/grpc v1.62.0/go.mod h1:IWTG0VlJLCh1SkC58F7np9ka9mx/WNkjl4PGJaiq+QE= google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= @@ -1643,6 +1704,7 @@ gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo= gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw= gotest.tools/v3 v3.0.2/go.mod h1:3SzNCllyD9/Y+b5r9JIKQ474KzkZyqLqEfYqMsX94Bk= gotest.tools/v3 v3.4.0 h1:ZazjZUfuVeZGLAmlKKuyv3IKP5orXcwtOwDQH6YVr6o= +gotest.tools/v3 v3.4.0/go.mod h1:CtbdzLSsqVhDgMtKsx03ird5YTGB3ar27v0u/yKBW5g= helm.sh/helm/v3 v3.14.0 h1:TaZIH6uOchn7L27ptwnnuHJiFrT/BsD4dFdp/HLT2nM= helm.sh/helm/v3 v3.14.0/go.mod h1:2itvvDv2WSZXTllknfQo6j7u3VVgMAvm8POCDgYH424= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/integration/testdata/TestGolangIntegration/golang-project1/go.mod b/integration/testdata/TestGolangIntegration/golang-project1/go.mod index 866ca68c05..bd761d5a17 100644 --- a/integration/testdata/TestGolangIntegration/golang-project1/go.mod +++ b/integration/testdata/TestGolangIntegration/golang-project1/go.mod @@ -1,5 +1,5 @@ module github.com/example/golang-app -go 1.20 +go 1.21 require github.com/gorilla/mux v1.8.0 diff --git a/integration/testdata/TestGolangIntegration/golang-project2/go.mod b/integration/testdata/TestGolangIntegration/golang-project2/go.mod index 86def7320d..e43c18361e 100644 --- a/integration/testdata/TestGolangIntegration/golang-project2/go.mod +++ b/integration/testdata/TestGolangIntegration/golang-project2/go.mod @@ -1,3 +1,3 @@ module github.com/example/golang-app -go 1.20 +go 1.21 diff --git a/pkg/abap/aakaas/aakUtils_mock.go b/pkg/abap/aakaas/aakUtils_mock.go index 307771ef4a..5e4de0a8f0 100644 --- a/pkg/abap/aakaas/aakUtils_mock.go +++ b/pkg/abap/aakaas/aakUtils_mock.go @@ -17,7 +17,8 @@ type AakBundleMock struct { *mock.ExecMockRunner *abaputils.ClientMock *mock.FilesMock - maxRuntime time.Duration + maxRuntime time.Duration + MockAddonDescriptor abaputils.AddonDescriptor } func NewAakBundleMock() *AakBundleMock { @@ -99,6 +100,10 @@ func (bundle *AakBundleMock) ReadAddonDescriptor(FileName string) (abaputils.Add { err = errors.New("error in ReadAddonDescriptor") } + case "addon.yml.mock": + { + return bundle.MockAddonDescriptor, nil + } } return addonDescriptor, err } diff --git a/pkg/abap/aakaas/productVersionHeader.go b/pkg/abap/aakaas/productVersionHeader.go new file mode 100644 index 0000000000..444e04ad3d --- /dev/null +++ b/pkg/abap/aakaas/productVersionHeader.go @@ -0,0 +1,149 @@ +package aakaas + +import ( + "encoding/json" + + abapbuild "github.com/SAP/jenkins-library/pkg/abap/build" + "github.com/SAP/jenkins-library/pkg/abaputils" + "github.com/pkg/errors" +) + +type jsonProductVersionHeader struct { + Pvh *ProductVersionHeader `json:"d"` +} + +type ProductVersionHeader struct { + ProductName string + SemanticProductVersion string `json:"SemProductVersion"` + ProductVersion string + SpsLevel string + PatchLevel string + Vendor string + VendorType string + Content []ProductVersionContent `json:"-"` //for developer access + JsonContent ProductVersionContents `json:"Content"` //for json (Un)Marshaling +} + +type ProductVersionContents struct { + Content []ProductVersionContent `json:"results"` +} + +type ProductVersionContent struct { + ProductName string + SemanticProductVersion string `json:"SemProductVersion"` + SoftwareComponentName string `json:"ScName"` + SemanticSoftwareComponentVersion string `json:"SemScVersion"` + SoftwareComponentVersion string `json:"ScVersion"` + SpLevel string + PatchLevel string + Vendor string + VendorType string +} + +func NewProductVersionHeader(addonDescriptor *abaputils.AddonDescriptor, conn *abapbuild.Connector) (*ProductVersionHeader, error) { + productVersion := new(ProductVersion) + if err := productVersion.ConstructProductversion(*addonDescriptor, *conn); err != nil { + return nil, err + } + pvh := ProductVersionHeader{ + ProductName: productVersion.Name, + SemanticProductVersion: productVersion.Version, + Content: []ProductVersionContent{}, + } + + for _, repo := range addonDescriptor.Repositories { + componentVersion := new(ComponentVersion) + if err := componentVersion.ConstructComponentVersion(repo, *conn); err != nil { + return nil, err + } + pvc := ProductVersionContent{ + ProductName: pvh.ProductName, + SemanticProductVersion: pvh.SemanticProductVersion, + SoftwareComponentName: componentVersion.Name, + SemanticSoftwareComponentVersion: componentVersion.Version, + } + pvh.Content = append(pvh.Content, pvc) + } + + if len(pvh.Content) == 0 { + return nil, errors.New("addonDescriptor must contain at least one software component repository") + } + + return &pvh, nil +} + +func (pv *ProductVersionHeader) CheckAndResolveVersion(conn *abapbuild.Connector) error { + conn.GetToken("/odata/aas_ocs_package") + pv.JsonContent = ProductVersionContents{ + Content: pv.Content, + } + requestJson, err := json.Marshal(pv) + if err != nil { + return err + } + + appendum := "/odata/aas_ocs_package/ProductVersionHeaderSet" + responseBody, err := conn.Post(appendum, string(requestJson)) + if err != nil { + return errors.Wrap(err, "Checking Product Modeling in AAkaaS failed") + } + + var resultPv jsonProductVersionHeader + if err := json.Unmarshal(responseBody, &resultPv); err != nil { + return errors.Wrap(err, "Unexpected AAKaaS response for checking Product Modeling "+string(responseBody)) + } + + pv.ProductVersion = resultPv.Pvh.ProductVersion + pv.SpsLevel = resultPv.Pvh.SpsLevel + pv.PatchLevel = resultPv.Pvh.PatchLevel + + for pvc_index, pvc := range pv.Content { + foundPvc := ProductVersionContent{} + for _, resultPvc := range resultPv.Pvh.JsonContent.Content { + if pvc.SoftwareComponentName == resultPvc.SoftwareComponentName && foundPvc.SoftwareComponentName == "" { + foundPvc = resultPvc + } else if pvc.SoftwareComponentName == resultPvc.SoftwareComponentName { + return errors.New("Software Component Name must be unique in the ProductVersionContent") + } + } + if foundPvc.SoftwareComponentName == "" { + return errors.New("Software Component Name not found in the ProductVersionContent") + } + pv.Content[pvc_index].PatchLevel = foundPvc.PatchLevel + pv.Content[pvc_index].SpLevel = foundPvc.SpLevel + pv.Content[pvc_index].SoftwareComponentVersion = foundPvc.SoftwareComponentVersion + } + + pv.JsonContent = ProductVersionContents{} + return nil +} + +func (pv *ProductVersionHeader) SyncAddonDescriptorVersionFields(addonDescriptor *abaputils.AddonDescriptor) error { + addonDescriptor.AddonVersion = pv.ProductVersion + addonDescriptor.AddonSpsLevel = pv.SpsLevel + addonDescriptor.AddonPatchLevel = pv.PatchLevel + addonDescriptor.AddonVersionYAML = pv.SemanticProductVersion //In case it had wildCards which got resolved + + //in NewPvh function pvh was build up 1:1 based on addonDescriptor + //in checkAndResolve pvh was synced from AAKaaS reply assuming it does not contain more content than before(if it does it is ignored) + for repo_index, repo := range addonDescriptor.Repositories { + foundPvc := ProductVersionContent{} + for _, pvc := range pv.Content { + if pvc.SoftwareComponentName == repo.Name && foundPvc.SoftwareComponentName == "" { + foundPvc = pvc + } else if pvc.SoftwareComponentName == repo.Name { + return errors.New("Software Component Name must be unique in addon descriptor(aka addon.yml)") + } + } + if foundPvc.SoftwareComponentName == "" { + return errors.New("ProductVersionContent & addon descriptor (aka addon.yml) out of sync") + } + + addonDescriptor.Repositories[repo_index].PatchLevel = foundPvc.PatchLevel + addonDescriptor.Repositories[repo_index].SpLevel = foundPvc.SpLevel + addonDescriptor.Repositories[repo_index].Version = foundPvc.SoftwareComponentVersion + addonDescriptor.Repositories[repo_index].VersionYAML = foundPvc.SemanticSoftwareComponentVersion //In case it had wildCards which got resolved + } + + return nil +} diff --git a/pkg/abap/aakaas/testData.go b/pkg/abap/aakaas/testData.go index 3a0b10dbe4..adc64a167a 100644 --- a/pkg/abap/aakaas/testData.go +++ b/pkg/abap/aakaas/testData.go @@ -34,6 +34,44 @@ var ResponseCheckCVs = `{ } }` +var ResponseCheck = `{ + "d": { + "ProductName": "/DRNMSPC/PRD01", + "SemProductVersion": "2.0.0", + "ProductVersion": "0002", + "SpsLevel": "0000", + "PatchLevel": "0000", + "Vendor": "", + "VendorType": "", + "Content": { + "results": [ + { + "ProductName": "/DRNMSPC/PRD01", + "SemProductVersion": "2.0.0", + "ScName": "/DRNMSPC/COMP01", + "SemScVersion": "2.0.0", + "ScVersion": "0002", + "SpLevel": "0000", + "PatchLevel": "0000", + "Vendor": "", + "VendorType": "" + }, + { + "ProductName": "/DRNMSPC/PRD01", + "SemProductVersion": "2.0.0", + "ScName": "/DRNMSPC/COMP02", + "SemScVersion": "1.0.0", + "ScVersion": "0001", + "SpLevel": "0000", + "PatchLevel": "0000", + "Vendor": "", + "VendorType": "" + } + ] + } + } +}` + var emptyResultBody = `{ "d": { "results": [] diff --git a/pkg/abap/build/connector.go b/pkg/abap/build/connector.go index 80339b605e..2ee1109664 100644 --- a/pkg/abap/build/connector.go +++ b/pkg/abap/build/connector.go @@ -155,10 +155,11 @@ func (conn *Connector) InitAAKaaS(aAKaaSEndpoint string, username string, passwo } conn.Client.SetOptions(piperhttp.ClientOptions{ - Username: username, - Password: password, - CookieJar: cookieJar, - Certificates: tlsCertificates, + Username: username, + Password: password, + CookieJar: cookieJar, + Certificates: tlsCertificates, + TransportTimeout: 15 * time.Minute, //Usually ABAP Backend has timeout of 10min, let them interrupt the connection... }) if tlsCertificates != nil { diff --git a/pkg/abaputils/descriptor.go b/pkg/abaputils/descriptor.go index c7ec8e9c27..e2add90192 100644 --- a/pkg/abaputils/descriptor.go +++ b/pkg/abaputils/descriptor.go @@ -26,34 +26,34 @@ import ( // AddonDescriptor contains fields about the addonProduct type AddonDescriptor struct { AddonProduct string `json:"addonProduct"` - AddonVersionYAML string `json:"addonVersion"` + AddonVersionYAML string `json:"addonVersion,omitempty"` AddonVersion string `json:"addonVersionAAK"` AddonSpsLevel string AddonPatchLevel string - TargetVectorID string + TargetVectorID string `json:",omitempty"` Repositories []Repository `json:"repositories"` } // Repository contains fields for the repository/component version type Repository struct { Name string `json:"name"` - UseClassicCTS bool `json:"useClassicCTS"` - Tag string `json:"tag"` - Branch string `json:"branch"` - CommitID string `json:"commitID"` - VersionYAML string `json:"version"` + UseClassicCTS bool `json:"useClassicCTS,omitempty"` + Tag string `json:"tag,omitempty"` + Branch string `json:"branch,omitempty"` + CommitID string `json:"commitID,omitempty"` + VersionYAML string `json:"version,omitempty"` Version string `json:"versionAAK"` - AdditionalPiecelist string `json:"additionalPiecelist"` - PackageName string - PackageType string + AdditionalPiecelist string `json:"additionalPiecelist,omitempty"` + PackageName string `json:",omitempty"` + PackageType string `json:",omitempty"` SpLevel string PatchLevel string - PredecessorCommitID string - Status string - Namespace string - SarXMLFilePath string - Languages []string `json:"languages"` - InBuildScope bool + PredecessorCommitID string `json:",omitempty"` + Status string `json:",omitempty"` + Namespace string `json:",omitempty"` + SarXMLFilePath string `json:",omitempty"` + Languages []string `json:"languages,omitempty"` + InBuildScope bool `json:",omitempty"` } // ReadAddonDescriptorType is the type for ReadAddonDescriptor for mocking @@ -182,3 +182,22 @@ func (me *AddonDescriptor) GetRepositoriesInBuildScope() []Repository { } return RepositoriesInBuildScope } + +func (me *AddonDescriptor) AsReducedJson() string { + input := AddonDescriptor{ + AddonProduct: me.AddonProduct, + AddonVersion: me.AddonVersion, + AddonSpsLevel: me.AddonSpsLevel, + AddonPatchLevel: me.AddonPatchLevel, + } + for _, repo := range me.Repositories { + input.Repositories = append(input.Repositories, Repository{ + Name: repo.Name, + Version: repo.Version, + SpLevel: repo.SpLevel, + PatchLevel: repo.PatchLevel, + }) + } + + return input.AsJSONstring() +} diff --git a/pkg/abaputils/descriptor_test.go b/pkg/abaputils/descriptor_test.go index 0e2c133987..79713a6e94 100644 --- a/pkg/abaputils/descriptor_test.go +++ b/pkg/abaputils/descriptor_test.go @@ -40,6 +40,9 @@ func TestAddonDescriptorNew(t *testing.T) { assert.Equal(t, "/DMO/REPO_B", repos[0].Name) }) + t.Run("AsReducedJson", func(t *testing.T) { + assert.NotContains(t, "commitID", addonDescriptor.AsReducedJson()) + }) } var TestAddonDescriptorYAML = `--- diff --git a/pkg/abaputils/manageGitRepositoryUtils.go b/pkg/abaputils/manageGitRepositoryUtils.go index bc7d596ba4..7d6b8224de 100644 --- a/pkg/abaputils/manageGitRepositoryUtils.go +++ b/pkg/abaputils/manageGitRepositoryUtils.go @@ -40,7 +40,13 @@ func PollEntity(api SoftwareComponentApiInterface, pollIntervall time.Duration) } func PrintLogs(api SoftwareComponentApiInterface) { - // connectionDetails.URL = connectionDetails.URL + "?$expand=to_Log_Overview" + + // Get Execution Logs + executionLogs, err := api.GetExecutionLog() + if err == nil { + printExecutionLogs(executionLogs) + } + results, err := api.GetLogOverview() if err != nil || len(results) == 0 { // return if no logs are available @@ -63,6 +69,17 @@ func PrintLogs(api SoftwareComponentApiInterface) { return } +func printExecutionLogs(executionLogs ExecutionLog) { + log.Entry().Infof("\n") + AddDefaultDashedLine(1) + log.Entry().Infof("Execution Logs") + AddDefaultDashedLine(1) + for _, entry := range executionLogs.Value { + log.Entry().Infof("%7s - %s", entry.Type, entry.Descr) + } + AddDefaultDashedLine(1) +} + func printOverview(results []LogResultsV2) { logOutputPhaseLength, logOutputLineLength := calculateLenghts(results) diff --git a/pkg/abaputils/manageGitRepositoryUtils_test.go b/pkg/abaputils/manageGitRepositoryUtils_test.go index 21ee7785b4..ffd96a614b 100644 --- a/pkg/abaputils/manageGitRepositoryUtils_test.go +++ b/pkg/abaputils/manageGitRepositoryUtils_test.go @@ -300,3 +300,18 @@ func TestCreateRequestBodies(t *testing.T) { assert.Equal(t, `{"sc_name":"/DMO/REPO", "tag_name":"myTag"}`, body, "Expected different body") }) } + +func TestExecutionLogOutput(t *testing.T) { + t.Run("Test execution log output", func(t *testing.T) { + + executionLogValue := []ExecutionLogValue{ + {IndexNo: 1, Type: "Success", Descr: "Something went well", Timestamp: "/Date(1644332299000+0000)/"}, + {IndexNo: 2, Type: "Error", Descr: "Something went wrong", Timestamp: "/Date(1644332299000+0000)/"}, + } + executionLog := ExecutionLog{ + Value: executionLogValue, + } + printExecutionLogs(executionLog) + + }) +} diff --git a/pkg/abaputils/sap_com_0510.go b/pkg/abaputils/sap_com_0510.go index 2874dd557c..b330224f66 100644 --- a/pkg/abaputils/sap_com_0510.go +++ b/pkg/abaputils/sap_com_0510.go @@ -52,6 +52,10 @@ func (api *SAP_COM_0510) init(con ConnectionDetailsHTTP, client piperhttp.Sender api.retryAllowedErrorCodes = append(api.retryAllowedErrorCodes, "A4C_A2G/501") } +func (api *SAP_COM_0510) GetExecutionLog() (execLog ExecutionLog, err error) { + return execLog, errors.New("Not implemented") +} + func (api *SAP_COM_0510) getUUID() string { return api.uuid } diff --git a/pkg/abaputils/sap_com_0948.go b/pkg/abaputils/sap_com_0948.go index d272c988fb..f6b7be68b5 100644 --- a/pkg/abaputils/sap_com_0948.go +++ b/pkg/abaputils/sap_com_0948.go @@ -59,6 +59,36 @@ func (api *SAP_COM_0948) getUUID() string { return api.uuid } +// reads the execution log from the ABAP system +func (api *SAP_COM_0948) GetExecutionLog() (execLog ExecutionLog, err error) { + + connectionDetails := api.con + connectionDetails.URL = api.con.URL + api.path + api.actionsEntity + "/" + api.getUUID() + "/_Execution_log" + resp, err := GetHTTPResponse("GET", connectionDetails, nil, api.client) + if err != nil { + log.SetErrorCategory(log.ErrorInfrastructure) + _, err = HandleHTTPError(resp, err, api.failureMessage, connectionDetails) + return execLog, err + } + defer resp.Body.Close() + + // Parse response + bodyText, _ := io.ReadAll(resp.Body) + + marshallError := json.Unmarshal(bodyText, &execLog) + if marshallError != nil { + return execLog, errors.Wrap(marshallError, "Could not parse response from the ABAP Environment system") + } + + if reflect.DeepEqual(ExecutionLog{}, execLog) { + log.Entry().WithField("StatusCode", resp.Status).Error(api.failureMessage) + log.SetErrorCategory(log.ErrorInfrastructure) + var err = errors.New("Request to ABAP System not successful") + return execLog, err + } + return execLog, nil +} + func (api *SAP_COM_0948) CreateTag(tag Tag) error { if reflect.DeepEqual(Tag{}, tag) { diff --git a/pkg/abaputils/sap_com_0948_test.go b/pkg/abaputils/sap_com_0948_test.go index 72c8fdd158..24f7e6702c 100644 --- a/pkg/abaputils/sap_com_0948_test.go +++ b/pkg/abaputils/sap_com_0948_test.go @@ -11,17 +11,17 @@ import ( "github.com/stretchr/testify/assert" ) -var connection ConnectionDetailsHTTP -var repository Repository +var conTest0948 ConnectionDetailsHTTP +var repoTest0948 Repository func init() { - connection.User = "CC_USER" - connection.Password = "123abc" - connection.URL = "https://example.com" + conTest0948.User = "CC_USER" + conTest0948.Password = "123abc" + conTest0948.URL = "https://example.com" - repository.Name = "/DMO/REPO" - repository.Branch = "main" + repoTest0948.Name = "/DMO/REPO" + repoTest0948.Branch = "main" } @@ -481,3 +481,26 @@ func TestSleepTime0948(t *testing.T) { assert.ErrorContains(t, err, "Exceeded max sleep time") }) } + +func TestGetExecutionLog(t *testing.T) { + t.Run("Test Get Executionlog Success", func(t *testing.T) { + + client := &ClientMock{ + BodyList: []string{ + `{ "value" : [{"index_no":1,"timestamp":"2021-08-23T12:00:00.000Z","type":"Success", "descr":"First log entry"}]}`, + ``, + }, + Token: "myToken", + StatusCode: 200, + } + + apiManager := &SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + + api, _ := apiManager.GetAPI(con, Repository{Name: "/DMO/REPO"}) + + results, errAction := api.GetExecutionLog() + assert.NoError(t, errAction) + assert.NotEmpty(t, results) + assert.Equal(t, "First log entry", results.Value[0].Descr) + }) +} diff --git a/pkg/abaputils/softwareComponentApiManager.go b/pkg/abaputils/softwareComponentApiManager.go index 9b5e06332d..813df3c3ef 100644 --- a/pkg/abaputils/softwareComponentApiManager.go +++ b/pkg/abaputils/softwareComponentApiManager.go @@ -59,14 +59,15 @@ type SoftwareComponentApiInterface interface { setSleepTimeConfig(timeUnit time.Duration, maxSleepTime time.Duration) getSleepTime(n int) (time.Duration, error) getUUID() string + GetRepository() (bool, string, error) Clone() error Pull() error CheckoutBranch() error - GetRepository() (bool, string, error) GetAction() (string, error) + CreateTag(tag Tag) error GetLogOverview() ([]LogResultsV2, error) GetLogProtocol(LogResultsV2, int) (result []LogProtocol, count int, err error) - CreateTag(tag Tag) error + GetExecutionLog() (ExecutionLog, error) } /**************************************** @@ -148,6 +149,17 @@ type LogResultsV2 struct { ToLogProtocol LogProtocolDeferred `json:"to_Log_Protocol"` } +type ExecutionLog struct { + Value []ExecutionLogValue `json:"value"` +} + +type ExecutionLogValue struct { + IndexNo int `json:"index_no"` + Type string `json:"type"` + Descr string `json:"descr"` + Timestamp string `json:"timestamp"` +} + type LogProtocolDeferred struct { Deferred URI `json:"__deferred"` } diff --git a/pkg/checkmarxone/cxjson_to_sarif.go b/pkg/checkmarxone/cxjson_to_sarif.go index 27d8e0cecc..7560eaebe5 100644 --- a/pkg/checkmarxone/cxjson_to_sarif.go +++ b/pkg/checkmarxone/cxjson_to_sarif.go @@ -20,6 +20,7 @@ func ConvertCxJSONToSarif(sys System, serverURL string, scanResults *[]ScanResul sarif.Version = "2.1.0" var checkmarxRun format.Runs checkmarxRun.ColumnKind = "utf16CodeUnits" + checkmarxRun.Results = make([]format.Results, 0) sarif.Runs = append(sarif.Runs, checkmarxRun) rulesArray := []format.SarifRule{} @@ -226,7 +227,17 @@ func ConvertCxJSONToSarif(sys System, serverURL string, scanResults *[]ScanResul if r.VulnerabilityDetails.CweId != 0 { rule.Properties.Tags = append(rule.Properties.Tags, fmt.Sprintf("external/cwe/cwe-%d", r.VulnerabilityDetails.CweId)) } - rulesArray = append(rulesArray, rule) + + match := false + for _, r := range rulesArray { + if r.ID == rule.ID { + match = true + break + } + } + if !match { + rulesArray = append(rulesArray, rule) + } } // Handle driver object @@ -237,7 +248,7 @@ func ConvertCxJSONToSarif(sys System, serverURL string, scanResults *[]ScanResul // TODO: a way to fetch/store the version tool.Driver.Version = "1" //strings.Split(cxxml.CheckmarxVersion, "V ") - tool.Driver.InformationUri = "https://checkmarx.com/resource/documents/en/34965-68571-viewing-results.html" + tool.Driver.InformationUri = "https://checkmarx.com/resource/documents/en/34965-165898-results-details-per-scanner.html" tool.Driver.Rules = rulesArray sarif.Runs[0].Tool = tool @@ -250,6 +261,7 @@ func ConvertCxJSONToSarif(sys System, serverURL string, scanResults *[]ScanResul taxonomy.Name = "CWE" taxonomy.Organization = "MITRE" taxonomy.ShortDescription.Text = "The MITRE Common Weakness Enumeration" + taxonomy.Taxa = make([]format.Taxa, 0) for key := range cweIdsForTaxonomies { taxa := *new(format.Taxa) taxa.Id = fmt.Sprintf("%d", key) diff --git a/pkg/codeql/repo_info.go b/pkg/codeql/repo_info.go new file mode 100644 index 0000000000..40c5b5907b --- /dev/null +++ b/pkg/codeql/repo_info.go @@ -0,0 +1,140 @@ +package codeql + +import ( + "errors" + "fmt" + "regexp" + "strings" + + "github.com/SAP/jenkins-library/pkg/log" + "github.com/SAP/jenkins-library/pkg/orchestrator" +) + +type RepoInfo struct { + ServerUrl string + Owner string + Repo string + CommitId string + AnalyzedRef string + FullRef string + FullUrl string + ScanUrl string +} + +func GetRepoInfo(repository, analyzedRef, commitID, targetGithubRepoURL, targetGithubBranchName string) (*RepoInfo, error) { + repoInfo := &RepoInfo{} + err := setRepoInfoFromRepoUri(repository, repoInfo) + if err != nil { + log.Entry().Error(err) + } + repoInfo.AnalyzedRef = analyzedRef + repoInfo.CommitId = commitID + + getRepoInfoFromOrchestrator(repoInfo) + + if len(targetGithubRepoURL) > 0 { + log.Entry().Infof("Checking target GitHub repo URL: %s", targetGithubRepoURL) + if err := setTargetGithubRepoInfo(targetGithubRepoURL, targetGithubBranchName, repoInfo); err != nil { + return repoInfo, err + } + } + + repoUrl := fmt.Sprintf("%s/%s/%s", repoInfo.ServerUrl, repoInfo.Owner, repoInfo.Repo) + repoInfo.FullUrl = repoUrl + repoInfo.ScanUrl = fmt.Sprintf("%s/security/code-scanning?query=is:open+ref:%s", repoUrl, repoInfo.AnalyzedRef) + + repoRef, err := buildRepoReference(repoUrl, repoInfo.AnalyzedRef) + if err != nil { + return nil, err + } + repoInfo.FullRef = repoRef + + return repoInfo, nil +} + +func buildRepoReference(repository, analyzedRef string) (string, error) { + ref := strings.Split(analyzedRef, "/") + if len(ref) < 3 { + return "", fmt.Errorf("wrong analyzedRef format: %s", analyzedRef) + } + if strings.Contains(analyzedRef, "pull") { + if len(ref) < 4 { + return "", fmt.Errorf("wrong analyzedRef format: %s", analyzedRef) + } + return fmt.Sprintf("%s/pull/%s", repository, ref[2]), nil + } + return fmt.Sprintf("%s/tree/%s", repository, ref[2]), nil +} + +func setRepoInfoFromRepoUri(repoUri string, repoInfo *RepoInfo) error { + if repoUri == "" { + return errors.New("repository param is not set or it cannot be auto populated") + } + serverUrl, owner, repo, err := parseRepoUri(repoUri) + if err != nil { + return err + } + repoInfo.ServerUrl = serverUrl + repoInfo.Owner = owner + repoInfo.Repo = repo + return nil +} + +func parseRepoUri(repoUri string) (string, string, string, error) { + pat := regexp.MustCompile(`^(https:\/\/|git@)([\S]+:[\S]+@)?([^\/:]+)[\/:]([^\/:]+\/[\S]+)$`) + matches := pat.FindAllStringSubmatch(repoUri, -1) + if len(matches) > 0 { + match := matches[0] + serverUrl := "https://" + match[3] + repoData := strings.Split(strings.TrimSuffix(match[4], ".git"), "/") + if len(repoData) != 2 { + return "", "", "", fmt.Errorf("invalid repository %s", repoUri) + } + owner, repo := repoData[0], repoData[1] + return serverUrl, owner, repo, nil + } + return "", "", "", fmt.Errorf("invalid repository %s", repoUri) +} + +func getRepoInfoFromOrchestrator(repoInfo *RepoInfo) { + provider, err := orchestrator.GetOrchestratorConfigProvider(nil) + if err != nil { + log.Entry().Warn("No orchestrator found. We assume piper is running locally.") + } else { + if repoInfo.AnalyzedRef == "" { + repoInfo.AnalyzedRef = provider.GitReference() + } + if repoInfo.CommitId == "" || repoInfo.CommitId == "NA" { + repoInfo.CommitId = provider.CommitSHA() + } + if repoInfo.ServerUrl == "" { + err := setRepoInfoFromRepoUri(provider.RepoURL(), repoInfo) + if err != nil { + log.Entry().WithError(err).Error("failed to get repo info from orchestrator") + } + } + } +} + +func setTargetGithubRepoInfo(targetGHRepoURL, targetGHBranchName string, repoInfo *RepoInfo) error { + if strings.Contains(repoInfo.ServerUrl, "github") { + return errors.New("TargetGithubRepoURL should not be set as the source repo is on github") + } + err := setRepoInfoFromRepoUri(targetGHRepoURL, repoInfo) + if err != nil { + log.Entry().WithError(err).Error("Failed to get target github repo info") + return err + } + if len(targetGHBranchName) > 0 { + log.Entry().Infof("Target GitHub branch name: %s", targetGHBranchName) + repoInfo.AnalyzedRef = getFullBranchName(targetGHBranchName) + } + return nil +} + +func getFullBranchName(branchName string) string { + if len(strings.Split(branchName, "/")) < 3 { + return "refs/heads/" + branchName + } + return branchName +} diff --git a/pkg/codeql/repo_info_test.go b/pkg/codeql/repo_info_test.go new file mode 100644 index 0000000000..efecc303ac --- /dev/null +++ b/pkg/codeql/repo_info_test.go @@ -0,0 +1,367 @@ +package codeql + +import ( + "testing" + + "github.com/SAP/jenkins-library/pkg/orchestrator" + "github.com/stretchr/testify/assert" +) + +func TestGetRepoInfo(t *testing.T) { + t.Run("Valid URL1", func(t *testing.T) { + repo := "https://github.hello.test/Testing/codeql.git" + analyzedRef := "refs/heads/branch" + commitID := "abcd1234" + + repoInfo, err := GetRepoInfo(repo, analyzedRef, commitID, "", "") + assert.NoError(t, err) + assert.Equal(t, "abcd1234", repoInfo.CommitId) + assert.Equal(t, "Testing", repoInfo.Owner) + assert.Equal(t, "codeql", repoInfo.Repo) + assert.Equal(t, "refs/heads/branch", repoInfo.AnalyzedRef) + assert.Equal(t, "https://github.hello.test", repoInfo.ServerUrl) + assert.Equal(t, "https://github.hello.test/Testing/codeql", repoInfo.FullUrl) + assert.Equal(t, "https://github.hello.test/Testing/codeql/security/code-scanning?query=is:open+ref:refs/heads/branch", repoInfo.ScanUrl) + assert.Equal(t, "https://github.hello.test/Testing/codeql/tree/branch", repoInfo.FullRef) + }) + + t.Run("Valid URL2", func(t *testing.T) { + repo := "https://github.hello.test/Testing/codeql" + analyzedRef := "refs/heads/branch" + commitID := "abcd1234" + + repoInfo, err := GetRepoInfo(repo, analyzedRef, commitID, "", "") + assert.NoError(t, err) + assert.Equal(t, "abcd1234", repoInfo.CommitId) + assert.Equal(t, "Testing", repoInfo.Owner) + assert.Equal(t, "codeql", repoInfo.Repo) + assert.Equal(t, "refs/heads/branch", repoInfo.AnalyzedRef) + assert.Equal(t, "https://github.hello.test", repoInfo.ServerUrl) + assert.Equal(t, "https://github.hello.test/Testing/codeql", repoInfo.FullUrl) + assert.Equal(t, "https://github.hello.test/Testing/codeql/security/code-scanning?query=is:open+ref:refs/heads/branch", repoInfo.ScanUrl) + assert.Equal(t, "https://github.hello.test/Testing/codeql/tree/branch", repoInfo.FullRef) + }) + + t.Run("Valid url with dots URL1", func(t *testing.T) { + repo := "https://github.hello.test/Testing/com.sap.codeql.git" + analyzedRef := "refs/heads/branch" + commitID := "abcd1234" + + repoInfo, err := GetRepoInfo(repo, analyzedRef, commitID, "", "") + assert.NoError(t, err) + assert.Equal(t, "abcd1234", repoInfo.CommitId) + assert.Equal(t, "Testing", repoInfo.Owner) + assert.Equal(t, "com.sap.codeql", repoInfo.Repo) + assert.Equal(t, "refs/heads/branch", repoInfo.AnalyzedRef) + assert.Equal(t, "https://github.hello.test", repoInfo.ServerUrl) + assert.Equal(t, "https://github.hello.test/Testing/com.sap.codeql", repoInfo.FullUrl) + assert.Equal(t, "https://github.hello.test/Testing/com.sap.codeql/security/code-scanning?query=is:open+ref:refs/heads/branch", repoInfo.ScanUrl) + assert.Equal(t, "https://github.hello.test/Testing/com.sap.codeql/tree/branch", repoInfo.FullRef) + }) + + t.Run("Valid url with dots URL2", func(t *testing.T) { + repo := "https://github.hello.test/Testing/com.sap.codeql" + analyzedRef := "refs/heads/branch" + commitID := "abcd1234" + + repoInfo, err := GetRepoInfo(repo, analyzedRef, commitID, "", "") + assert.NoError(t, err) + assert.Equal(t, "abcd1234", repoInfo.CommitId) + assert.Equal(t, "Testing", repoInfo.Owner) + assert.Equal(t, "com.sap.codeql", repoInfo.Repo) + assert.Equal(t, "refs/heads/branch", repoInfo.AnalyzedRef) + assert.Equal(t, "https://github.hello.test", repoInfo.ServerUrl) + assert.Equal(t, "https://github.hello.test/Testing/com.sap.codeql", repoInfo.FullUrl) + assert.Equal(t, "https://github.hello.test/Testing/com.sap.codeql/security/code-scanning?query=is:open+ref:refs/heads/branch", repoInfo.ScanUrl) + assert.Equal(t, "https://github.hello.test/Testing/com.sap.codeql/tree/branch", repoInfo.FullRef) + }) + + t.Run("Valid url with username and token URL1", func(t *testing.T) { + repo := "https://username:token@github.hello.test/Testing/codeql.git" + analyzedRef := "refs/heads/branch" + commitID := "abcd1234" + + repoInfo, err := GetRepoInfo(repo, analyzedRef, commitID, "", "") + assert.NoError(t, err) + assert.Equal(t, "abcd1234", repoInfo.CommitId) + assert.Equal(t, "Testing", repoInfo.Owner) + assert.Equal(t, "codeql", repoInfo.Repo) + assert.Equal(t, "refs/heads/branch", repoInfo.AnalyzedRef) + assert.Equal(t, "https://github.hello.test", repoInfo.ServerUrl) + assert.Equal(t, "https://github.hello.test/Testing/codeql", repoInfo.FullUrl) + assert.Equal(t, "https://github.hello.test/Testing/codeql/security/code-scanning?query=is:open+ref:refs/heads/branch", repoInfo.ScanUrl) + assert.Equal(t, "https://github.hello.test/Testing/codeql/tree/branch", repoInfo.FullRef) + }) + + t.Run("Valid url with username and token URL2", func(t *testing.T) { + repo := "https://username:token@github.hello.test/Testing/codeql" + analyzedRef := "refs/heads/branch" + commitID := "abcd1234" + + repoInfo, err := GetRepoInfo(repo, analyzedRef, commitID, "", "") + assert.NoError(t, err) + assert.Equal(t, "abcd1234", repoInfo.CommitId) + assert.Equal(t, "Testing", repoInfo.Owner) + assert.Equal(t, "codeql", repoInfo.Repo) + assert.Equal(t, "refs/heads/branch", repoInfo.AnalyzedRef) + assert.Equal(t, "https://github.hello.test", repoInfo.ServerUrl) + assert.Equal(t, "https://github.hello.test/Testing/codeql", repoInfo.FullUrl) + assert.Equal(t, "https://github.hello.test/Testing/codeql/security/code-scanning?query=is:open+ref:refs/heads/branch", repoInfo.ScanUrl) + assert.Equal(t, "https://github.hello.test/Testing/codeql/tree/branch", repoInfo.FullRef) + }) + + t.Run("Invalid URL with no org/reponame", func(t *testing.T) { + repo := "https://github.hello.test" + analyzedRef := "refs/heads/branch" + commitID := "abcd1234" + + repoInfo, err := GetRepoInfo(repo, analyzedRef, commitID, "", "") + assert.NoError(t, err) + _, err = orchestrator.GetOrchestratorConfigProvider(nil) + assert.Equal(t, "abcd1234", repoInfo.CommitId) + assert.Equal(t, "refs/heads/branch", repoInfo.AnalyzedRef) + if err != nil { + assert.Equal(t, "", repoInfo.Owner) + assert.Equal(t, "", repoInfo.Repo) + assert.Equal(t, "", repoInfo.ServerUrl) + } + }) + + t.Run("Non-Github SCM, TargetGithubRepo is not empty", func(t *testing.T) { + repo := "https://gitlab.test/Testing/codeql.git" + analyzedRef := "refs/heads/branch" + commitID := "abcd1234" + targetGHRepoUrl := "https://github.hello.test/Testing/codeql" + + repoInfo, err := GetRepoInfo(repo, analyzedRef, commitID, targetGHRepoUrl, "") + assert.NoError(t, err) + assert.Equal(t, "abcd1234", repoInfo.CommitId) + assert.Equal(t, "Testing", repoInfo.Owner) + assert.Equal(t, "codeql", repoInfo.Repo) + assert.Equal(t, "refs/heads/branch", repoInfo.AnalyzedRef) + assert.Equal(t, "https://github.hello.test", repoInfo.ServerUrl) + assert.Equal(t, "https://github.hello.test/Testing/codeql", repoInfo.FullUrl) + assert.Equal(t, "https://github.hello.test/Testing/codeql/security/code-scanning?query=is:open+ref:refs/heads/branch", repoInfo.ScanUrl) + assert.Equal(t, "https://github.hello.test/Testing/codeql/tree/branch", repoInfo.FullRef) + + }) + + t.Run("Non-Github SCM, TargetGithubRepo and TargetGithubBranch are not empty", func(t *testing.T) { + repo := "https://gitlab.test/Testing/codeql.git" + analyzedRef := "refs/heads/branch" + commitID := "abcd1234" + targetGHRepoUrl := "https://github.hello.test/Testing/codeql" + targetGHRepoBranch := "new-branch" + + repoInfo, err := GetRepoInfo(repo, analyzedRef, commitID, targetGHRepoUrl, targetGHRepoBranch) + assert.NoError(t, err) + assert.Equal(t, "abcd1234", repoInfo.CommitId) + assert.Equal(t, "Testing", repoInfo.Owner) + assert.Equal(t, "codeql", repoInfo.Repo) + assert.Equal(t, "refs/heads/new-branch", repoInfo.AnalyzedRef) + assert.Equal(t, "https://github.hello.test", repoInfo.ServerUrl) + assert.Equal(t, "https://github.hello.test/Testing/codeql", repoInfo.FullUrl) + assert.Equal(t, "https://github.hello.test/Testing/codeql/security/code-scanning?query=is:open+ref:refs/heads/new-branch", repoInfo.ScanUrl) + assert.Equal(t, "https://github.hello.test/Testing/codeql/tree/new-branch", repoInfo.FullRef) + + }) +} + +func TestBuildRepoReference(t *testing.T) { + t.Run("Valid AnalyzedRef with branch", func(t *testing.T) { + repo := "https://github.hello.test/Testing/fortify" + analyzedRef := "refs/heads/branch" + ref, err := buildRepoReference(repo, analyzedRef) + assert.NoError(t, err) + assert.Equal(t, "https://github.hello.test/Testing/fortify/tree/branch", ref) + }) + t.Run("Valid AnalyzedRef with PR", func(t *testing.T) { + repo := "https://github.hello.test/Testing/fortify" + analyzedRef := "refs/pull/1/merge" + ref, err := buildRepoReference(repo, analyzedRef) + assert.NoError(t, err) + assert.Equal(t, "https://github.hello.test/Testing/fortify/pull/1", ref) + }) + t.Run("Invalid AnalyzedRef without branch name", func(t *testing.T) { + repo := "https://github.hello.test/Testing/fortify" + analyzedRef := "refs/heads" + ref, err := buildRepoReference(repo, analyzedRef) + assert.Error(t, err) + assert.ErrorContains(t, err, "wrong analyzedRef format") + assert.Equal(t, "", ref) + }) + t.Run("Invalid AnalyzedRef without PR id", func(t *testing.T) { + repo := "https://github.hello.test/Testing/fortify" + analyzedRef := "refs/pull/merge" + ref, err := buildRepoReference(repo, analyzedRef) + assert.Error(t, err) + assert.ErrorContains(t, err, "wrong analyzedRef format") + assert.Equal(t, "", ref) + }) +} + +func TestSetRepoInfoFromRepoUri(t *testing.T) { + t.Run("Valid https URL1", func(t *testing.T) { + var repoInfo RepoInfo + err := setRepoInfoFromRepoUri("https://github.hello.test/Testing/fortify.git", &repoInfo) + assert.NoError(t, err) + assert.Equal(t, "https://github.hello.test", repoInfo.ServerUrl) + assert.Equal(t, "fortify", repoInfo.Repo) + assert.Equal(t, "Testing", repoInfo.Owner) + }) + + t.Run("Valid https URL2", func(t *testing.T) { + var repoInfo RepoInfo + err := setRepoInfoFromRepoUri("https://github.hello.test/Testing/fortify", &repoInfo) + assert.NoError(t, err) + assert.Equal(t, "https://github.hello.test", repoInfo.ServerUrl) + assert.Equal(t, "fortify", repoInfo.Repo) + assert.Equal(t, "Testing", repoInfo.Owner) + }) + t.Run("Valid https URL1 with dots", func(t *testing.T) { + var repoInfo RepoInfo + err := setRepoInfoFromRepoUri("https://github.hello.test/Testing/com.sap.fortify.git", &repoInfo) + assert.NoError(t, err) + assert.Equal(t, "https://github.hello.test", repoInfo.ServerUrl) + assert.Equal(t, "com.sap.fortify", repoInfo.Repo) + assert.Equal(t, "Testing", repoInfo.Owner) + }) + + t.Run("Valid https URL2 with dots", func(t *testing.T) { + var repoInfo RepoInfo + err := setRepoInfoFromRepoUri("https://github.hello.test/Testing/com.sap.fortify", &repoInfo) + assert.NoError(t, err) + assert.Equal(t, "https://github.hello.test", repoInfo.ServerUrl) + assert.Equal(t, "com.sap.fortify", repoInfo.Repo) + assert.Equal(t, "Testing", repoInfo.Owner) + }) + t.Run("Valid https URL1 with username and token", func(t *testing.T) { + var repoInfo RepoInfo + err := setRepoInfoFromRepoUri("https://username:token@github.hello.test/Testing/fortify.git", &repoInfo) + assert.NoError(t, err) + assert.Equal(t, "https://github.hello.test", repoInfo.ServerUrl) + assert.Equal(t, "fortify", repoInfo.Repo) + assert.Equal(t, "Testing", repoInfo.Owner) + }) + + t.Run("Valid https URL2 with username and token", func(t *testing.T) { + var repoInfo RepoInfo + err := setRepoInfoFromRepoUri("https://username:token@github.hello.test/Testing/fortify", &repoInfo) + assert.NoError(t, err) + assert.Equal(t, "https://github.hello.test", repoInfo.ServerUrl) + assert.Equal(t, "fortify", repoInfo.Repo) + assert.Equal(t, "Testing", repoInfo.Owner) + }) + + t.Run("Invalid https URL as no org/Owner passed", func(t *testing.T) { + var repoInfo RepoInfo + assert.Error(t, setRepoInfoFromRepoUri("https://github.com/fortify", &repoInfo)) + }) + + t.Run("Invalid URL as no protocol passed", func(t *testing.T) { + var repoInfo RepoInfo + assert.Error(t, setRepoInfoFromRepoUri("github.hello.test/Testing/fortify", &repoInfo)) + }) + + t.Run("Valid ssh URL1", func(t *testing.T) { + var repoInfo RepoInfo + err := setRepoInfoFromRepoUri("git@github.hello.test/Testing/fortify.git", &repoInfo) + assert.NoError(t, err) + assert.Equal(t, "https://github.hello.test", repoInfo.ServerUrl) + assert.Equal(t, "fortify", repoInfo.Repo) + assert.Equal(t, "Testing", repoInfo.Owner) + }) + + t.Run("Valid ssh URL2", func(t *testing.T) { + var repoInfo RepoInfo + err := setRepoInfoFromRepoUri("git@github.hello.test/Testing/fortify", &repoInfo) + assert.NoError(t, err) + assert.Equal(t, "https://github.hello.test", repoInfo.ServerUrl) + assert.Equal(t, "fortify", repoInfo.Repo) + assert.Equal(t, "Testing", repoInfo.Owner) + }) + t.Run("Valid ssh URL1 with dots", func(t *testing.T) { + var repoInfo RepoInfo + err := setRepoInfoFromRepoUri("git@github.hello.test/Testing/com.sap.fortify.git", &repoInfo) + assert.NoError(t, err) + assert.Equal(t, "https://github.hello.test", repoInfo.ServerUrl) + assert.Equal(t, "com.sap.fortify", repoInfo.Repo) + assert.Equal(t, "Testing", repoInfo.Owner) + }) + + t.Run("Valid ssh URL2 with dots", func(t *testing.T) { + var repoInfo RepoInfo + err := setRepoInfoFromRepoUri("git@github.hello.test/Testing/com.sap.fortify", &repoInfo) + assert.NoError(t, err) + assert.Equal(t, "https://github.hello.test", repoInfo.ServerUrl) + assert.Equal(t, "com.sap.fortify", repoInfo.Repo) + assert.Equal(t, "Testing", repoInfo.Owner) + }) + + t.Run("Invalid ssh URL as no org/Owner passed", func(t *testing.T) { + var repoInfo RepoInfo + assert.Error(t, setRepoInfoFromRepoUri("git@github.com/fortify", &repoInfo)) + }) +} + +func TestSetTargetGithubRepoInfo(t *testing.T) { + t.Parallel() + + t.Run("Source repo server is github", func(t *testing.T) { + repoInfo := &RepoInfo{ + ServerUrl: "https://github.com", + Owner: "owner", + Repo: "repo", + } + targetRepo := "https://github.com/target/repo" + targetBranch := "target-branch" + err := setTargetGithubRepoInfo(targetRepo, targetBranch, repoInfo) + assert.Error(t, err) + }) + + t.Run("Success", func(t *testing.T) { + repoInfo := &RepoInfo{ + ServerUrl: "https://gitlab.com", + Owner: "owner", + Repo: "repo", + AnalyzedRef: "refs/heads/source-branch", + } + targetRepo := "https://github.com/target/repo" + targetBranch := "target-branch" + err := setTargetGithubRepoInfo(targetRepo, targetBranch, repoInfo) + assert.NoError(t, err) + assert.Equal(t, "https://github.com", repoInfo.ServerUrl) + assert.Equal(t, "target", repoInfo.Owner) + assert.Equal(t, "repo", repoInfo.Repo) + assert.Equal(t, "refs/heads/target-branch", repoInfo.AnalyzedRef) + }) + + t.Run("Empty target branch", func(t *testing.T) { + repoInfo := &RepoInfo{ + ServerUrl: "https://gitlab.com", + Owner: "owner", + Repo: "repo", + AnalyzedRef: "refs/heads/source-branch", + } + targetRepo := "https://github.com/target/repo" + err := setTargetGithubRepoInfo(targetRepo, "", repoInfo) + assert.NoError(t, err) + assert.Equal(t, "https://github.com", repoInfo.ServerUrl) + assert.Equal(t, "target", repoInfo.Owner) + assert.Equal(t, "repo", repoInfo.Repo) + assert.Equal(t, "refs/heads/source-branch", repoInfo.AnalyzedRef) + }) +} + +func TestGetFullBranchName(t *testing.T) { + t.Parallel() + + t.Run("Given short branch name", func(t *testing.T) { + input := "branch-name" + assert.Equal(t, "refs/heads/branch-name", getFullBranchName(input)) + }) + t.Run("Given full branch name", func(t *testing.T) { + input := "refs/heads/branch-name" + assert.Equal(t, "refs/heads/branch-name", getFullBranchName(input)) + }) +} diff --git a/pkg/codeql/reporting.go b/pkg/codeql/reporting.go index fc095ccffa..7e65c4fa22 100644 --- a/pkg/codeql/reporting.go +++ b/pkg/codeql/reporting.go @@ -4,7 +4,6 @@ import ( "encoding/json" "fmt" "path/filepath" - "strings" "github.com/SAP/jenkins-library/pkg/log" "github.com/SAP/jenkins-library/pkg/piperutils" @@ -27,14 +26,6 @@ type CodeqlFindings struct { Audited int `json:"audited"` } -type RepoInfo struct { - ServerUrl string - Repo string - CommitId string - Ref string - Owner string -} - func WriteJSONReport(jsonReport CodeqlAudit, modulePath string) ([]piperutils.Path, error) { utils := piperutils.Files{} reportPaths := []piperutils.Path{} @@ -56,22 +47,8 @@ func WriteJSONReport(jsonReport CodeqlAudit, modulePath string) ([]piperutils.Pa return reportPaths, nil } -func BuildRepoReference(repository, analyzedRef string) (string, error) { - ref := strings.Split(analyzedRef, "/") - if len(ref) < 3 { - return "", errors.New(fmt.Sprintf("Wrong analyzedRef format: %s", analyzedRef)) - } - if strings.Contains(analyzedRef, "pull") { - if len(ref) < 4 { - return "", errors.New(fmt.Sprintf("Wrong analyzedRef format: %s", analyzedRef)) - } - return fmt.Sprintf("%s/pull/%s", repository, ref[2]), nil - } - return fmt.Sprintf("%s/tree/%s", repository, ref[2]), nil -} - -func CreateAndPersistToolRecord(utils piperutils.FileUtils, repoInfo RepoInfo, repoReference, repoUrl, modulePath string) (string, error) { - toolRecord, err := createToolRecordCodeql(utils, repoInfo, repoReference, repoUrl, modulePath) +func CreateAndPersistToolRecord(utils piperutils.FileUtils, repoInfo *RepoInfo, modulePath string) (string, error) { + toolRecord, err := createToolRecordCodeql(utils, repoInfo, modulePath) if err != nil { return "", err } @@ -84,7 +61,7 @@ func CreateAndPersistToolRecord(utils piperutils.FileUtils, repoInfo RepoInfo, r return toolRecordFileName, nil } -func createToolRecordCodeql(utils piperutils.FileUtils, repoInfo RepoInfo, repoUrl, repoReference, modulePath string) (*toolrecord.Toolrecord, error) { +func createToolRecordCodeql(utils piperutils.FileUtils, repoInfo *RepoInfo, modulePath string) (*toolrecord.Toolrecord, error) { record := toolrecord.New(utils, modulePath, "codeql", repoInfo.ServerUrl) if repoInfo.ServerUrl == "" { @@ -95,33 +72,33 @@ func createToolRecordCodeql(utils piperutils.FileUtils, repoInfo RepoInfo, repoU return record, errors.New("CommitId not set") } - if repoInfo.Ref == "" { + if repoInfo.AnalyzedRef == "" { return record, errors.New("Analyzed Reference not set") } - record.DisplayName = fmt.Sprintf("%s %s - %s %s", repoInfo.Owner, repoInfo.Repo, repoInfo.Ref, repoInfo.CommitId) - record.DisplayURL = fmt.Sprintf("%s/security/code-scanning?query=is:open+ref:%s", repoUrl, repoInfo.Ref) + record.DisplayName = fmt.Sprintf("%s %s - %s %s", repoInfo.Owner, repoInfo.Repo, repoInfo.AnalyzedRef, repoInfo.CommitId) + record.DisplayURL = repoInfo.ScanUrl err := record.AddKeyData("repository", fmt.Sprintf("%s/%s", repoInfo.Owner, repoInfo.Repo), fmt.Sprintf("%s %s", repoInfo.Owner, repoInfo.Repo), - repoUrl) + repoInfo.FullUrl) if err != nil { return record, err } err = record.AddKeyData("repositoryReference", - repoInfo.Ref, - fmt.Sprintf("%s - %s", repoInfo.Repo, repoInfo.Ref), - repoReference) + repoInfo.AnalyzedRef, + fmt.Sprintf("%s - %s", repoInfo.Repo, repoInfo.AnalyzedRef), + repoInfo.FullRef) if err != nil { return record, err } err = record.AddKeyData("scanResult", - fmt.Sprintf("%s/%s", repoInfo.Ref, repoInfo.CommitId), - fmt.Sprintf("%s %s - %s %s", repoInfo.Owner, repoInfo.Repo, repoInfo.Ref, repoInfo.CommitId), - fmt.Sprintf("%s/security/code-scanning?query=is:open+ref:%s", repoUrl, repoInfo.Ref)) + fmt.Sprintf("%s/%s", repoInfo.AnalyzedRef, repoInfo.CommitId), + fmt.Sprintf("%s %s - %s %s", repoInfo.Owner, repoInfo.Repo, repoInfo.AnalyzedRef, repoInfo.CommitId), + repoInfo.ScanUrl) if err != nil { return record, err } diff --git a/pkg/codeql/reporting_test.go b/pkg/codeql/reporting_test.go index 2587a559fd..04910d7a1e 100644 --- a/pkg/codeql/reporting_test.go +++ b/pkg/codeql/reporting_test.go @@ -1,7 +1,6 @@ package codeql import ( - "fmt" "testing" "github.com/SAP/jenkins-library/pkg/mock" @@ -21,87 +20,54 @@ func newCodeqlExecuteScanTestsUtils() codeqlExecuteScanMockUtils { return utils } -func TestBuildRepoReference(t *testing.T) { - t.Run("Valid Ref with branch", func(t *testing.T) { - repository := "https://github.hello.test/Testing/fortify" - analyzedRef := "refs/head/branch" - ref, err := BuildRepoReference(repository, analyzedRef) - assert.NoError(t, err) - assert.Equal(t, "https://github.hello.test/Testing/fortify/tree/branch", ref) - }) - t.Run("Valid Ref with PR", func(t *testing.T) { - repository := "https://github.hello.test/Testing/fortify" - analyzedRef := "refs/pull/1/merge" - ref, err := BuildRepoReference(repository, analyzedRef) - assert.NoError(t, err) - assert.Equal(t, "https://github.hello.test/Testing/fortify/pull/1", ref) - }) - t.Run("Invalid Ref without branch name", func(t *testing.T) { - repository := "https://github.hello.test/Testing/fortify" - analyzedRef := "refs/head" - ref, err := BuildRepoReference(repository, analyzedRef) - assert.Error(t, err) - assert.ErrorContains(t, err, "Wrong analyzedRef format") - assert.Equal(t, "", ref) - }) - t.Run("Invalid Ref without PR id", func(t *testing.T) { - repository := "https://github.hello.test/Testing/fortify" - analyzedRef := "refs/pull/merge" - ref, err := BuildRepoReference(repository, analyzedRef) - assert.Error(t, err) - assert.ErrorContains(t, err, "Wrong analyzedRef format") - assert.Equal(t, "", ref) - }) -} - -func getRepoReferences(repoInfo RepoInfo) (string, string) { - repoUrl := fmt.Sprintf("%s/%s/%s", repoInfo.ServerUrl, repoInfo.Owner, repoInfo.Repo) - repoReference, _ := BuildRepoReference(repoUrl, repoInfo.Ref) - return repoUrl, repoReference -} - func TestCreateToolRecordCodeql(t *testing.T) { modulePath := "./" t.Run("Valid toolrun file", func(t *testing.T) { - repoInfo := RepoInfo{ServerUrl: "https://github.hello.test", CommitId: "test", Ref: "refs/head/branch", Owner: "Testing", Repo: "fortify"} - repoUrl, repoReference := getRepoReferences(repoInfo) - toolRecord, err := createToolRecordCodeql(newCodeqlExecuteScanTestsUtils(), repoInfo, repoUrl, repoReference, modulePath) + repoInfo := &RepoInfo{ + ServerUrl: "https://github.hello.test", + CommitId: "test", + AnalyzedRef: "refs/heads/branch", + Owner: "Testing", + Repo: "codeql", + FullUrl: "https://github.hello.test/Testing/codeql", + FullRef: "https://github.hello.test/Testing/codeql/tree/branch", + ScanUrl: "https://github.hello.test/Testing/codeql/security/code-scanning?query=is:open+ref:refs/heads/branch", + } + toolRecord, err := createToolRecordCodeql(newCodeqlExecuteScanTestsUtils(), repoInfo, modulePath) assert.NoError(t, err) assert.Equal(t, toolRecord.ToolName, "codeql") assert.Equal(t, toolRecord.ToolInstance, "https://github.hello.test") - assert.Equal(t, toolRecord.DisplayName, "Testing fortify - refs/head/branch test") - assert.Equal(t, toolRecord.DisplayURL, "https://github.hello.test/Testing/fortify/security/code-scanning?query=is:open+ref:refs/head/branch") + assert.Equal(t, toolRecord.DisplayName, "Testing codeql - refs/heads/branch test") + assert.Equal(t, toolRecord.DisplayURL, "https://github.hello.test/Testing/codeql/security/code-scanning?query=is:open+ref:refs/heads/branch") }) + t.Run("Empty repository URL", func(t *testing.T) { - repoInfo := RepoInfo{ServerUrl: "", CommitId: "test", Ref: "refs/head/branch", Owner: "Testing", Repo: "fortify"} - repoUrl, repoReference := getRepoReferences(repoInfo) - _, err := createToolRecordCodeql(newCodeqlExecuteScanTestsUtils(), repoInfo, repoUrl, repoReference, modulePath) + repoInfo := &RepoInfo{ServerUrl: "", CommitId: "test", AnalyzedRef: "refs/heads/branch", Owner: "Testing", Repo: "codeql"} + _, err := createToolRecordCodeql(newCodeqlExecuteScanTestsUtils(), repoInfo, modulePath) assert.Error(t, err) assert.ErrorContains(t, err, "Repository not set") }) t.Run("Empty analyzedRef", func(t *testing.T) { - repoInfo := RepoInfo{ServerUrl: "https://github.hello.test", CommitId: "test", Ref: "", Owner: "Testing", Repo: "fortify"} - repoUrl, repoReference := getRepoReferences(repoInfo) - _, err := createToolRecordCodeql(newCodeqlExecuteScanTestsUtils(), repoInfo, repoUrl, repoReference, modulePath) + repoInfo := &RepoInfo{ServerUrl: "https://github.hello.test", CommitId: "test", AnalyzedRef: "", Owner: "Testing", Repo: "codeql"} + _, err := createToolRecordCodeql(newCodeqlExecuteScanTestsUtils(), repoInfo, modulePath) assert.Error(t, err) assert.ErrorContains(t, err, "Analyzed Reference not set") }) t.Run("Empty CommitId", func(t *testing.T) { - repoInfo := RepoInfo{ServerUrl: "https://github.hello.test", CommitId: "", Ref: "refs/head/branch", Owner: "Testing", Repo: "fortify"} - repoUrl, repoReference := getRepoReferences(repoInfo) - _, err := createToolRecordCodeql(newCodeqlExecuteScanTestsUtils(), repoInfo, repoUrl, repoReference, modulePath) + repoInfo := &RepoInfo{ServerUrl: "https://github.hello.test", CommitId: "", AnalyzedRef: "refs/heads/branch", Owner: "Testing", Repo: "codeql"} + _, err := createToolRecordCodeql(newCodeqlExecuteScanTestsUtils(), repoInfo, modulePath) assert.Error(t, err) assert.ErrorContains(t, err, "CommitId not set") }) + t.Run("Invalid analyzedRef", func(t *testing.T) { - repoInfo := RepoInfo{ServerUrl: "https://github.hello.test", CommitId: "", Ref: "refs/branch", Owner: "Testing", Repo: "fortify"} - repoUrl, repoReference := getRepoReferences(repoInfo) - _, err := createToolRecordCodeql(newCodeqlExecuteScanTestsUtils(), repoInfo, repoUrl, repoReference, modulePath) + repoInfo := &RepoInfo{ServerUrl: "https://github.hello.test", CommitId: "", AnalyzedRef: "refs/branch", Owner: "Testing", Repo: "codeql"} + _, err := createToolRecordCodeql(newCodeqlExecuteScanTestsUtils(), repoInfo, modulePath) assert.Error(t, err) }) diff --git a/pkg/codeql/sarif_upload.go b/pkg/codeql/sarif_upload.go index 3b241b7f38..2e1b1526cb 100644 --- a/pkg/codeql/sarif_upload.go +++ b/pkg/codeql/sarif_upload.go @@ -2,8 +2,17 @@ package codeql import ( "encoding/json" + "errors" "io" "net/http" + "time" + + "github.com/SAP/jenkins-library/pkg/log" +) + +const ( + sarifUploadComplete = "complete" + sarifUploadFailed = "failed" ) type CodeqlSarifUploader interface { @@ -66,3 +75,33 @@ func getSarifUploadingStatus(sarifURL, token string) (SarifFileInfo, error) { } return sarifInfo, nil } + +func WaitSarifUploaded(maxRetries, checkRetryInterval int, codeqlSarifUploader CodeqlSarifUploader) error { + retryInterval := time.Duration(checkRetryInterval) * time.Second + + log.Entry().Info("waiting for the SARIF to upload") + i := 1 + for { + sarifStatus, err := codeqlSarifUploader.GetSarifStatus() + if err != nil { + return err + } + log.Entry().Infof("the SARIF processing status: %s", sarifStatus.ProcessingStatus) + if sarifStatus.ProcessingStatus == sarifUploadComplete { + return nil + } + if sarifStatus.ProcessingStatus == sarifUploadFailed { + for e := range sarifStatus.Errors { + log.Entry().Error(e) + } + return errors.New("failed to upload sarif file") + } + if i <= maxRetries { + log.Entry().Infof("still waiting for the SARIF to upload: retrying in %d seconds... (retry %d/%d)", checkRetryInterval, i, maxRetries) + time.Sleep(retryInterval) + i++ + continue + } + return errors.New("failed to check sarif uploading status: max retries reached") + } +} diff --git a/pkg/codeql/sarif_upload_test.go b/pkg/codeql/sarif_upload_test.go new file mode 100644 index 0000000000..5b67c99971 --- /dev/null +++ b/pkg/codeql/sarif_upload_test.go @@ -0,0 +1,94 @@ +package codeql + +import ( + "testing" + "time" + + "github.com/pkg/errors" + "github.com/stretchr/testify/assert" +) + +type CodeqlSarifUploaderMock struct { + counter int +} + +func (c *CodeqlSarifUploaderMock) GetSarifStatus() (SarifFileInfo, error) { + if c.counter == 0 { + return SarifFileInfo{ + ProcessingStatus: "complete", + Errors: nil, + }, nil + } + if c.counter == -1 { + return SarifFileInfo{ + ProcessingStatus: "failed", + Errors: []string{"upload error"}, + }, nil + } + c.counter-- + return SarifFileInfo{ + ProcessingStatus: "pending", + Errors: nil, + }, nil +} + +type CodeqlSarifUploaderErrorMock struct { + counter int +} + +func (c *CodeqlSarifUploaderErrorMock) GetSarifStatus() (SarifFileInfo, error) { + if c.counter == -1 { + return SarifFileInfo{}, errors.New("test error") + } + if c.counter == 0 { + return SarifFileInfo{ + ProcessingStatus: "complete", + Errors: nil, + }, nil + } + c.counter-- + return SarifFileInfo{ProcessingStatus: "Service unavailable"}, nil +} + +func TestWaitSarifUploaded(t *testing.T) { + t.Parallel() + sarifCheckRetryInterval := 1 + sarifCheckMaxRetries := 5 + t.Run("Fast complete upload", func(t *testing.T) { + codeqlScanAuditMock := CodeqlSarifUploaderMock{counter: 0} + timerStart := time.Now() + err := WaitSarifUploaded(sarifCheckMaxRetries, sarifCheckRetryInterval, &codeqlScanAuditMock) + assert.Less(t, time.Now().Sub(timerStart), time.Second) + assert.NoError(t, err) + }) + t.Run("Long completed upload", func(t *testing.T) { + codeqlScanAuditMock := CodeqlSarifUploaderMock{counter: 2} + timerStart := time.Now() + err := WaitSarifUploaded(sarifCheckMaxRetries, sarifCheckRetryInterval, &codeqlScanAuditMock) + assert.GreaterOrEqual(t, time.Now().Sub(timerStart), time.Second*2) + assert.NoError(t, err) + }) + t.Run("Failed upload", func(t *testing.T) { + codeqlScanAuditMock := CodeqlSarifUploaderMock{counter: -1} + err := WaitSarifUploaded(sarifCheckMaxRetries, sarifCheckRetryInterval, &codeqlScanAuditMock) + assert.Error(t, err) + assert.ErrorContains(t, err, "failed to upload sarif file") + }) + t.Run("Error while checking sarif uploading", func(t *testing.T) { + codeqlScanAuditErrorMock := CodeqlSarifUploaderErrorMock{counter: -1} + err := WaitSarifUploaded(sarifCheckMaxRetries, sarifCheckRetryInterval, &codeqlScanAuditErrorMock) + assert.Error(t, err) + assert.ErrorContains(t, err, "test error") + }) + t.Run("Completed upload after getting errors from server", func(t *testing.T) { + codeqlScanAuditErrorMock := CodeqlSarifUploaderErrorMock{counter: 3} + err := WaitSarifUploaded(sarifCheckMaxRetries, sarifCheckRetryInterval, &codeqlScanAuditErrorMock) + assert.NoError(t, err) + }) + t.Run("Max retries reached", func(t *testing.T) { + codeqlScanAuditErrorMock := CodeqlSarifUploaderErrorMock{counter: 6} + err := WaitSarifUploaded(sarifCheckMaxRetries, sarifCheckRetryInterval, &codeqlScanAuditErrorMock) + assert.Error(t, err) + assert.ErrorContains(t, err, "max retries reached") + }) +} diff --git a/pkg/config/config.go b/pkg/config/config.go index 4190428728..e1dd4addd3 100644 --- a/pkg/config/config.go +++ b/pkg/config/config.go @@ -510,7 +510,7 @@ func merge(base, overlay map[string]interface{}, metadata StepData) map[string]i for _, v := range metadata.Spec.Inputs.Parameters { tVal := reflect.TypeOf(value).String() if v.Name == key && tVal != v.Type { - log.Entry().Warn("config value provided for", v.Name, " is of wrong type", tVal, "should be of type", v.Type) + log.Entry().Warn("config value provided for ", v.Name, " is of wrong type ", tVal, " should be of type ", v.Type) } } } diff --git a/pkg/events/events.go b/pkg/events/events.go new file mode 100644 index 0000000000..cd8d78e03b --- /dev/null +++ b/pkg/events/events.go @@ -0,0 +1,59 @@ +package events + +import ( + "encoding/json" + "time" + + cloudevents "github.com/cloudevents/sdk-go/v2" + "github.com/google/uuid" + "github.com/pkg/errors" +) + +// type EventType string + +type EventData struct { + URL string `json:"url"` + CommitId string `json:"commitId"` + RepositoryURL string `json:"repositoryUrl"` +} + +type Event struct { + cloudEvent cloudevents.Event + eventType string + eventSource string +} + +func NewEvent(eventType, eventSource string) Event { + return Event{ + eventType: eventType, + eventSource: eventSource, + } +} + +func (e Event) CreateWithJSONData(data string, opts ...Option) Event { + return e.Create(data, opts...) +} + +func (e Event) Create(data any, opts ...Option) Event { + e.cloudEvent = cloudevents.NewEvent("1.0") + // set default values + e.cloudEvent.SetID(uuid.New().String()) + e.cloudEvent.SetType(e.eventType) + e.cloudEvent.SetTime(time.Now()) + e.cloudEvent.SetSource(e.eventSource) + e.cloudEvent.SetData("application/json", data) + + for _, applyOpt := range opts { + applyOpt(e.cloudEvent.Context.AsV1()) + } + + return e +} + +func (e Event) ToBytes() ([]byte, error) { + data, err := json.Marshal(e.cloudEvent) + if err != nil { + return nil, errors.Wrap(err, "failed to marshal event data") + } + return data, nil +} diff --git a/pkg/events/events_test.go b/pkg/events/events_test.go new file mode 100644 index 0000000000..2ef1a0a00f --- /dev/null +++ b/pkg/events/events_test.go @@ -0,0 +1,19 @@ +package events + +import ( + "testing" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" +) + +func TestEventCreation(t *testing.T) { + t.Run("success", func(t *testing.T) { + // init + // test + event := NewEvent(mock.Anything, mock.Anything).Create(nil) + // asserts + assert.Equal(t, mock.Anything, event.cloudEvent.Type()) + assert.Equal(t, mock.Anything, event.cloudEvent.Source()) + }) +} diff --git a/pkg/events/options.go b/pkg/events/options.go new file mode 100644 index 0000000000..924068df1b --- /dev/null +++ b/pkg/events/options.go @@ -0,0 +1,17 @@ +package events + +import cloudevents "github.com/cloudevents/sdk-go/v2" + +type Option func(o *cloudevents.EventContextV1) + +func WithID(id string) Option { + return func(o *cloudevents.EventContextV1) { + o.SetID(id) + } +} + +func WithType(etype string) Option { + return func(o *cloudevents.EventContextV1) { + o.SetType(etype) + } +} diff --git a/pkg/events/options_test.go b/pkg/events/options_test.go new file mode 100644 index 0000000000..657a8bc173 --- /dev/null +++ b/pkg/events/options_test.go @@ -0,0 +1,23 @@ +package events + +import ( + "testing" + + cloudevents "github.com/cloudevents/sdk-go/v2" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" +) + +func Test(t *testing.T) { + t.Run("success", func(t *testing.T) { + // init + ec := cloudevents.EventContextV1{} + opts := []Option{WithID(mock.Anything)} + // test + for _, applyOpt := range opts { + applyOpt(&ec) + } + // asserts + assert.Equal(t, mock.Anything, ec.GetID()) + }) +} diff --git a/pkg/gcp/pubsub.go b/pkg/gcp/pubsub.go new file mode 100644 index 0000000000..3dd604ade3 --- /dev/null +++ b/pkg/gcp/pubsub.go @@ -0,0 +1,64 @@ +package gcp + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "net/http" + + "github.com/pkg/errors" +) + +const api_url = "https://pubsub.googleapis.com/v1/projects/%s/topics/%s:publish" + +// https://pkg.go.dev/cloud.google.com/go/pubsub#Message +type EventMessage struct { + Data []byte `json:"data"` + OrderingKey string `json:"orderingKey"` +} + +type Event struct { + Messages []EventMessage `json:"messages"` +} + +func Publish(projectNumber string, topic string, token string, key string, data []byte) error { + ctx := context.Background() + + // build event + event := Event{ + Messages: []EventMessage{{ + Data: data, + OrderingKey: key, + }}, + } + + // marshal event + eventBytes, err := json.Marshal(event) + if err != nil { + return errors.Wrap(err, "failed to marshal event") + } + + // create request + request, err := http.NewRequestWithContext(ctx, http.MethodPost, fmt.Sprintf(api_url, projectNumber, topic), bytes.NewReader(eventBytes)) + if err != nil { + return errors.Wrap(err, "failed to create request") + } + + // add headers + request.Header.Set("Content-Type", "application/json") + request.Header.Set("Authorization", fmt.Sprintf("Bearer %s", token)) + + // send request + response, err := http.DefaultClient.Do(request) + if err != nil { + return errors.Wrap(err, "failed to send request") + } + if response.StatusCode != http.StatusOK { + return fmt.Errorf("invalid status code: %v", response.StatusCode) + } + + //TODO: read response & messageIds + + return nil +} diff --git a/pkg/gcp/pubsub_test.go b/pkg/gcp/pubsub_test.go new file mode 100644 index 0000000000..a25e0a3b38 --- /dev/null +++ b/pkg/gcp/pubsub_test.go @@ -0,0 +1,45 @@ +package gcp + +import ( + "fmt" + "net/http" + "testing" + + "github.com/jarcoal/httpmock" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" +) + +func TestPublish(t *testing.T) { + t.Run("success", func(t *testing.T) { + // init + projectNumber := "PROJECT_NUMBER" + topic := "TOPIC" + token := "TOKEN" + data := []byte(mock.Anything) + + apiurl := fmt.Sprintf(api_url, projectNumber, topic) + + mockResponse := map[string]interface{}{ + "messageIds": []string{"10721501285371497"}, + } + + // mock + httpmock.Activate() + defer httpmock.DeactivateAndReset() + httpmock.RegisterResponder(http.MethodPost, apiurl, + func(req *http.Request) (*http.Response, error) { + assert.Contains(t, req.Header, "Authorization") + assert.Equal(t, req.Header.Get("Authorization"), "Bearer TOKEN") + assert.Contains(t, req.Header, "Content-Type") + assert.Equal(t, req.Header.Get("Content-Type"), "application/json") + return httpmock.NewJsonResponse(http.StatusOK, mockResponse) + }, + ) + + // test + err := Publish(projectNumber, topic, token, mock.Anything, data) + // asserts + assert.NoError(t, err) + }) +} diff --git a/pkg/gcp/token.go b/pkg/gcp/token.go new file mode 100644 index 0000000000..fe7a59346a --- /dev/null +++ b/pkg/gcp/token.go @@ -0,0 +1,64 @@ +package gcp + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "net/http" + + "github.com/pkg/errors" + "google.golang.org/api/sts/v1" +) + +// https://cloud.google.com/iam/docs/reference/sts/rest +const exchangeTokenAPIURL = "https://sts.googleapis.com/v1/token" + +func GetFederatedToken(projectNumber, pool, provider, token string) (string, error) { + ctx := context.Background() + requestData := getExchangeTokenRequestData(projectNumber, pool, provider, token) + + // data to byte + jsonData, err := json.Marshal(requestData) + if err != nil { + return "", errors.Wrapf(err, "failed to marshal the request data") + } + + // build request + request, err := http.NewRequestWithContext(ctx, http.MethodPost, exchangeTokenAPIURL, bytes.NewReader(jsonData)) + if err != nil { + return "", errors.Wrap(err, "failed to build request") + } + + // send request + response, err := http.DefaultClient.Do(request) + if err != nil { + return "", errors.Wrap(err, "failed to send request") + } + if response.StatusCode != http.StatusOK { + return "", fmt.Errorf("invalid status code: %v", response.StatusCode) + } + + // response to data + defer response.Body.Close() + responseData := sts.GoogleIdentityStsV1ExchangeTokenResponse{} + err = json.NewDecoder(response.Body).Decode(&responseData) + if err != nil { + return "", errors.Wrap(err, "failed to decode response") + } + + return responseData.AccessToken, nil +} + +func getExchangeTokenRequestData(projectNumber string, pool string, provider string, token string) sts.GoogleIdentityStsV1ExchangeTokenRequest { + return sts.GoogleIdentityStsV1ExchangeTokenRequest{ + Audience: fmt.Sprintf( + "//iam.googleapis.com/projects/%s/locations/global/workloadIdentityPools/%s/providers/%s", + projectNumber, pool, provider), + Scope: "https://www.googleapis.com/auth/cloud-platform", + SubjectToken: token, + SubjectTokenType: "urn:ietf:params:oauth:token-type:jwt", + GrantType: "urn:ietf:params:oauth:grant-type:token-exchange", + RequestedTokenType: "urn:ietf:params:oauth:token-type:access_token", + } +} diff --git a/pkg/gcp/token_test.go b/pkg/gcp/token_test.go new file mode 100644 index 0000000000..00d5a6131a --- /dev/null +++ b/pkg/gcp/token_test.go @@ -0,0 +1,50 @@ +package gcp + +import ( + "net/http" + "testing" + + "github.com/jarcoal/httpmock" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/mock" + "google.golang.org/api/sts/v1" +) + +func TestGetExchangeTokenRequestData(t *testing.T) { + // ctx := context.Background() + t.Run("success", func(t *testing.T) { + // init + projectNumber := "PROJECT_NUMBER" + pool := "POOL" + provider := "PROVIDER" + // test + data := getExchangeTokenRequestData(projectNumber, pool, provider, mock.Anything) + // asserts + assert.Equal(t, data.Audience, "//iam.googleapis.com/projects/PROJECT_NUMBER/locations/global/workloadIdentityPools/POOL/providers/PROVIDER") + assert.Equal(t, data.SubjectToken, mock.Anything) + }) +} + +func TestGetFederatedToken(t *testing.T) { + t.Run("success", func(t *testing.T) { + // init + projectNumber := "PROJECT_NUMBER" + pool := "POOL" + provider := "PROVIDER" + + // mock + httpmock.Activate() + defer httpmock.DeactivateAndReset() + httpmock.RegisterResponder(http.MethodPost, exchangeTokenAPIURL, + func(req *http.Request) (*http.Response, error) { + return httpmock.NewJsonResponse(http.StatusOK, sts.GoogleIdentityStsV1ExchangeTokenResponse{AccessToken: mock.Anything}) + }, + ) + + // test + federatedToken, err := GetFederatedToken(projectNumber, pool, provider, mock.Anything) + // asserts + assert.NoError(t, err) + assert.Equal(t, mock.Anything, federatedToken) + }) +} diff --git a/pkg/generator/helper/helper.go b/pkg/generator/helper/helper.go index a13d1ef738..75e25c183c 100644 --- a/pkg/generator/helper/helper.go +++ b/pkg/generator/helper/helper.go @@ -424,7 +424,7 @@ func {{.StepName}}(config {{ .StepName }}Options, telemetryData *telemetry.Custo // Error situations should be bubbled up until they reach the line below which will then stop execution // through the log.Entry().Fatal() call leading to an os.Exit(1) in the end. - err := run{{.StepName | title}}(&config, telemetryData, utils{{ range $notused, $oRes := .OutputResources}}, &{{ index $oRes "name" }}{{ end }}) + err := run{{.StepName | title}}(&config, telemetryData, utils{{ range $notused, $oRes := .OutputResources}}, {{ index $oRes "name" }}{{ end }}) if err != nil { log.Entry().WithError(err).Fatal("step execution failed") } diff --git a/pkg/http/http.go b/pkg/http/http.go index 768206bf2b..affac535f6 100644 --- a/pkg/http/http.go +++ b/pkg/http/http.go @@ -308,7 +308,7 @@ func (c *Client) initializeHttpClient() *http.Client { log.Entry().Debug("adding certs for tls to trust") err := c.configureTLSToTrustCertificates(transport) if err != nil { - log.Entry().Infof("adding certs for tls config failed : %v, continuing with the existing tsl config", err) + log.Entry().Infof("adding certs for tls config failed : %v, continuing with the existing tls config", err) } } else { log.Entry().Debug("no trusted certs found / using default transport / insecure skip set to true / : continuing with existing tls config") diff --git a/pkg/http/http_cert_logon_test.go b/pkg/http/http_cert_logon_test.go index c8f4ee01a9..31f6cb7723 100644 --- a/pkg/http/http_cert_logon_test.go +++ b/pkg/http/http_cert_logon_test.go @@ -87,7 +87,7 @@ func TestCertificateLogon(t *testing.T) { clientPemKey, clientPemCert := GenerateSelfSignedClientAuthCertificate() - //server + // server clientCertPool := x509.NewCertPool() clientCertPool.AppendCertsFromPEM(clientPemCert) @@ -102,7 +102,7 @@ func TestCertificateLogon(t *testing.T) { server.StartTLS() defer server.Close() - //client + // client tlsKeyPair, err := tls.X509KeyPair(clientPemCert, clientPemKey) if err != nil { log.Fatal("Failed to create clients tls key pair") @@ -131,7 +131,7 @@ func TestCertificateLogon(t *testing.T) { }) _, err := c.SendRequest("GET", server.URL, nil, nil, nil) - assert.ErrorContains(t, err, "bad certificate") + assert.ErrorContains(t, err, "certificate required") }) t.Run("Failure - Login with wrong certificate", func(t *testing.T) { @@ -150,14 +150,14 @@ func TestCertificateLogon(t *testing.T) { }) _, err = c.SendRequest("GET", server.URL, nil, nil, nil) - assert.ErrorContains(t, err, "bad certificate") + assert.ErrorContains(t, err, "unknown certificate authority") }) t.Run("SanityCheck", func(t *testing.T) { client := &http.Client{ Transport: &http.Transport{ TLSClientConfig: &tls.Config{ - //RootCAs: certPool, + // RootCAs: certPool, InsecureSkipVerify: true, Certificates: []tls.Certificate{tlsKeyPair}, }, diff --git a/pkg/reporting/pullRequestReport.go b/pkg/reporting/pullRequestReport.go index d40f0e783a..1b643d94ff 100644 --- a/pkg/reporting/pullRequestReport.go +++ b/pkg/reporting/pullRequestReport.go @@ -94,12 +94,12 @@ type OtherViolation struct { } const rapidReportMdTemplate = ` -## {{if .Success}}:heavy_check_mark: OSS related checks passed successfully - ### :clipboard: OSS related checks executed by Black Duck - rapid scan passed successfully. -

RAPID SCAN

+ {{if .Success}}:heavy_check_mark: **OSS related checks passed successfully** + :clipboard: OSS related checks executed by Black Duck - rapid scan passed successfully. +

RAPID SCAN

-{{else}} :x: OSS related checks failed - ### :clipboard: Policies violated by added OSS components +{{else}} :x: **OSS related checks failed** + :clipboard: Policies violated by added OSS components {{range $s := .MainTableHeaders -}}{{- end}} {{range $s := .MainTableValues -}}{{range $s1 := $s }}{{- end}} @@ -109,8 +109,8 @@ const rapidReportMdTemplate = ` {{range $index := .VulnerabilitiesTable -}}
{{$len := len $index.Values}} -{{if le $len 1}}

{{$len}} Policy Violation of {{$index.PolicyViolationName}}

-{{else}}

{{$len}} Policy Violations of {{$index.PolicyViolationName}}

{{end}} +{{if le $len 1}}

{{$len}} Policy Violation of {{$index.PolicyViolationName}}

+{{else}}

{{$len}} Policy Violations of {{$index.PolicyViolationName}}

{{end}}
{{$s}}
{{$s1}}
@@ -125,8 +125,8 @@ const rapidReportMdTemplate = ` {{range $index := .LicensesTable -}}
{{$len := len $index.Values}} -{{if le $len 1}}

{{$len}} Policy Violation of {{$index.PolicyViolationName}}

-{{else}}

{{$len}} Policy Violations of {{$index.PolicyViolationName}}

{{end}} +{{if le $len 1}}

{{$len}} Policy Violation of {{$index.PolicyViolationName}}

+{{else}}

{{$len}} Policy Violations of {{$index.PolicyViolationName}}

{{end}}
Vulnerability IDVulnerability ScoreComponent Name
@@ -139,8 +139,8 @@ const rapidReportMdTemplate = ` {{range $index := .OtherViolationsTable -}}
{{$len := len $index.Values}} -{{if le $len 1}}

{{$len}} Policy Violation of {{$index.PolicyViolationName}}

-{{else}}

{{$len}} Policy Violations of {{$index.PolicyViolationName}}

{{end}} +{{if le $len 1}}

{{$len}} Policy Violation of {{$index.PolicyViolationName}}

+{{else}}

{{$len}} Policy Violations of {{$index.PolicyViolationName}}

{{end}}
License NameComponent Name
diff --git a/pkg/reporting/pullRequestReport_test.go b/pkg/reporting/pullRequestReport_test.go index 6195444e27..02cf7e7cd4 100644 --- a/pkg/reporting/pullRequestReport_test.go +++ b/pkg/reporting/pullRequestReport_test.go @@ -113,34 +113,34 @@ func TestCreateMarkdownReport(t *testing.T) { ErrorMessage: "", }, }, - expectedReport: "\n## :x: OSS related checks failed\n ### :clipboard: Policies violated by added OSS components\n " + + expectedReport: "\n :x: **OSS related checks failed**\n :clipboard: Policies violated by added OSS components\n " + "
Component Name
\n \n \n
Component nameHigh Vulnerability Security IssueOutdatedFOSSLibraries" + "Test High Severity Vuln Filter
Chalk 1.1.3 (npmjs:chalk/1.1.3)010
Lodash " + "4.17.10 (npmjs:lodash/4.17.10)313
qs - QS Querystring 5.2.1 " + - "(npmjs:qs/5.2.1)100
\n\n
\n\n

4 Policy " + - "Violations of High Vulnerability Security Issue

\n
\n\t\n\t\t\n
Vulnerability IDVulnerability" + + "(npmjs:qs/5.2.1)100
\n\n
\n\n

4 Policy " + + "Violations of High Vulnerability Security Issue

\n
\n\t\n\t\t\n\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\t\t\n\t\t\t\n\t\t
Vulnerability IDVulnerability" + " ScoreComponent Name
CVE-2019-10744 9.1 CRITICALLodash 4.17.10 " + "(npmjs:lodash/4.17.10)
" + "CVE-2017-1000048 7.5 HIGHqs - QS Querystring 5.2.1 (npmjs:qs/5.2.1)
" + " CVE-2020-8203 7.4 HIGHLodash " + "4.17.10 (npmjs:lodash/4.17.10)
" + - "BDSA-2019-3842 7.1 HIGHLodash 4.17.10 (npmjs:lodash/4.17.10)
\n
\n
\n\n

" + - "3 Policy Violations of Test High Severity Vuln Filter

\n
\n\t\n\t\t\n\t\t\t\n\t\t
Vulnerability IDVulnerability " + + "BDSA-2019-3842 7.1 HIGHLodash 4.17.10 (npmjs:lodash/4.17.10)
\n
\n
\n\n

" + + "3 Policy Violations of Test High Severity Vuln Filter

\n
\n\t\n\t\t\n\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\t\t\n\t\t\t\n\t\t\n\t\t\t\n\t\t\t\n\t\t
Vulnerability IDVulnerability " + "ScoreComponent Name
" + "CVE-2019-10744 9.1 CRITICALLodash 4.17.10 (npmjs:lodash/4.17.10)
" + " CVE-2020-8203 7.4 " + "HIGHLodash 4.17.10 (npmjs:lodash/4.17.10)
" + - "BDSA-2019-3842 7.1 HIGHLodash 4.17.10 (npmjs:lodash/4.17.10)
\n
\n
\n\n

" + - "2 Policy Violations of OutdatedFOSSLibraries

\n
\n\t\n\t\t\n\t\t\n\t\t\t\n\t\t
Component Name
Chalk 1.1.3 " + + "BDSA-2019-3842 7.1 HIGHLodash 4.17.10 (npmjs:lodash/4.17.10)
\n
\n
\n\n

" + + "2 Policy Violations of OutdatedFOSSLibraries

\n
\n\t\n\t\t\n\t\t\n\t\t\n\t\t
Component Name
Chalk 1.1.3 " + "(npmjs:chalk/1.1.3)
Lodash 4.17.10 (npmjs:lodash/4.17.10)
\n
\n\n", }, { testName: "No vulnerabilities && successful build", components: &Components{}, - expectedReport: "\n## :heavy_check_mark: OSS related checks passed successfully\n ### :clipboard: OSS related checks executed by Black Duck " + + expectedReport: "\n :heavy_check_mark: **OSS related checks passed successfully**\n :clipboard: OSS related checks executed by Black Duck " + "- rapid scan passed successfully.\n" + - " " + - "

RAPID SCAN

\n\n\n", + "

" + + "RAPID SCAN

\n\n\n", }, } diff --git a/pkg/versioning/versioning.go b/pkg/versioning/versioning.go index 3d20363e30..471bd55846 100644 --- a/pkg/versioning/versioning.go +++ b/pkg/versioning/versioning.go @@ -7,9 +7,8 @@ import ( "os" "path/filepath" - "github.com/SAP/jenkins-library/pkg/piperutils" - "github.com/SAP/jenkins-library/pkg/maven" + "github.com/SAP/jenkins-library/pkg/piperutils" ) // Coordinates to address the artifact coordinates like groupId, artifactId, version and packaging @@ -30,16 +29,17 @@ type Artifact interface { // Options define build tool specific settings in order to properly retrieve e.g. the version / coordinates of an artifact type Options struct { - ProjectSettingsFile string - DockerImage string - GlobalSettingsFile string - M2Path string - Defines []string - VersionSource string - VersionSection string - VersionField string - VersioningScheme string - HelmUpdateAppVersion bool + ProjectSettingsFile string + DockerImage string + GlobalSettingsFile string + M2Path string + Defines []string + VersionSource string + VersionSection string + VersionField string + VersioningScheme string + HelmUpdateAppVersion bool + CAPVersioningPreference string } // Utils defines the versioning operations for various build tools @@ -75,6 +75,12 @@ func GetArtifact(buildTool, buildDescriptorFilePath string, opts *Options, utils if fileExists == nil { fileExists = piperutils.FileExists } + + // CAPVersioningPreference can only be 'maven' or 'npm'. Verification done on artifactPrepareVersion.yaml level + if buildTool == "CAP" { + buildTool = opts.CAPVersioningPreference + } + switch buildTool { case "custom": var err error diff --git a/pkg/versioning/versioning_test.go b/pkg/versioning/versioning_test.go index 1cb3351830..c18867efdf 100644 --- a/pkg/versioning/versioning_test.go +++ b/pkg/versioning/versioning_test.go @@ -150,6 +150,25 @@ func TestGetArtifact(t *testing.T) { assert.Equal(t, "maven", maven.VersioningScheme()) }) + t.Run("CAP - maven", func(t *testing.T) { + opts := Options{ + ProjectSettingsFile: "projectsettings.xml", + GlobalSettingsFile: "globalsettings.xml", + M2Path: "m2/path", + CAPVersioningPreference: "maven", + } + maven, err := GetArtifact("CAP", "", &opts, nil) + assert.NoError(t, err) + + theType, ok := maven.(*Maven) + assert.True(t, ok) + assert.Equal(t, "pom.xml", theType.options.PomPath) + assert.Equal(t, opts.ProjectSettingsFile, theType.options.ProjectSettingsFile) + assert.Equal(t, opts.GlobalSettingsFile, theType.options.GlobalSettingsFile) + assert.Equal(t, opts.M2Path, theType.options.M2Path) + assert.Equal(t, "maven", maven.VersioningScheme()) + }) + t.Run("mta", func(t *testing.T) { mta, err := GetArtifact("mta", "", &Options{VersionField: "theversion"}, nil) @@ -174,6 +193,17 @@ func TestGetArtifact(t *testing.T) { assert.Equal(t, "semver2", npm.VersioningScheme()) }) + t.Run("CAP - npm", func(t *testing.T) { + npm, err := GetArtifact("CAP", "", &Options{VersionField: "theversion", CAPVersioningPreference: "npm"}, nil) + assert.NoError(t, err) + + theType, ok := npm.(*JSONfile) + assert.True(t, ok) + assert.Equal(t, "package.json", theType.path) + assert.Equal(t, "version", theType.versionField) + assert.Equal(t, "semver2", npm.VersioningScheme()) + }) + t.Run("yarn", func(t *testing.T) { npm, err := GetArtifact("yarn", "", &Options{VersionField: "theversion"}, nil) diff --git a/resources/metadata/abapAddonAssemblyKitCheck.yaml b/resources/metadata/abapAddonAssemblyKitCheck.yaml new file mode 100644 index 0000000000..19842737b1 --- /dev/null +++ b/resources/metadata/abapAddonAssemblyKitCheck.yaml @@ -0,0 +1,101 @@ +metadata: + name: abapAddonAssemblyKitCheck + description: This step calls AAKaaS to check the validity of the Addon Product Modelling. + longDescription: | + This step does the following: +
+ For logon to AAKaaS you can either provide a credential with basic authorization (username and password) or two secret text credentials containing the technical s-users certificate (see note [2805811](https://me.sap.com/notes/2805811) for download) as base64 encoded string and the password to decrypt the file +
+ For Terminology refer to the [Scenario Description](https://www.project-piper.io/scenarios/abapEnvironmentAddons/). +spec: + inputs: + secrets: + - name: abapAddonAssemblyKitCredentialsId + description: CredentialsId stored in Jenkins for the Addon Assembly Kit as a Service (AAKaaS) system + type: jenkins + - name: abapAddonAssemblyKitCertificateFileCredentialsId + description: Jenkins secret text credential ID containing the base64 encoded certificate pfx file (PKCS12 format) see note [2805811](https://me.sap.com/notes/2805811) + type: jenkins + - name: abapAddonAssemblyKitCertificatePassCredentialsId + description: Jenkins secret text credential ID containing the password to decrypt the certificate file stored in abapAddonAssemblyKitCertificateFileCredentialsId + type: jenkins + params: + - name: abapAddonAssemblyKitCertificateFile + type: string + description: base64 encoded certificate pfx file (PKCS12 format) see note [2805811](https://me.sap.com/notes/2805811) + scope: + - PARAMETERS + mandatory: false + secret: true + resourceRef: + - name: abapAddonAssemblyKitCertificateFileCredentialsId + type: secret + param: abapAddonAssemblyKitCertificateFile + - name: abapAddonAssemblyKitCertificatePass + type: string + description: password to decrypt the certificate file + scope: + - PARAMETERS + mandatory: false + secret: true + resourceRef: + - name: abapAddonAssemblyKitCertificatePassCredentialsId + type: secret + param: abapAddonAssemblyKitCertificatePass + - name: abapAddonAssemblyKitEndpoint + type: string + description: Base URL to the Addon Assembly Kit as a Service (AAKaaS) system + scope: + - PARAMETERS + - STAGES + - STEPS + - GENERAL + mandatory: true + default: https://apps.support.sap.com + - name: username + type: string + description: User for the Addon Assembly Kit as a Service (AAKaaS) system + scope: + - PARAMETERS + - STAGES + - STEPS + mandatory: false + secret: true + - name: password + type: string + description: Password for the Addon Assembly Kit as a Service (AAKaaS) system + scope: + - PARAMETERS + mandatory: false + secret: true + - name: addonDescriptorFileName + type: string + description: File name of the YAML file which describes the Product Version and corresponding Software Component Versions + mandatory: true + default: addon.yml + scope: + - PARAMETERS + - STAGES + - STEPS + - GENERAL + - name: addonDescriptor + type: string + description: Structure in the commonPipelineEnvironment containing information about the Product Version and corresponding Software Component Versions + mandatory: false + scope: + - PARAMETERS + - STAGES + - STEPS + resourceRef: + - name: commonPipelineEnvironment + param: abap/addonDescriptor + outputs: + resources: + - name: commonPipelineEnvironment + type: piperEnvironment + params: + - name: abap/addonDescriptor diff --git a/resources/metadata/artifactPrepareVersion.yaml b/resources/metadata/artifactPrepareVersion.yaml index 44abf0577d..34389c21eb 100644 --- a/resources/metadata/artifactPrepareVersion.yaml +++ b/resources/metadata/artifactPrepareVersion.yaml @@ -151,6 +151,7 @@ spec: - pip - sbt - yarn + - CAP - name: commitUserName aliases: - name: gitUserName @@ -209,6 +210,25 @@ spec: - PARAMETERS - STAGES - STEPS + - name: CAPVersioningPreference + type: string + description: "For CAP build tool only: Defines which file should be used for versioning." + longDescription: | + If `maven` is chosen (default value), then the step expects a pom.xml file in the project's root folder. Alternatively, you can specify the path to the file using the `filePath` parameter. + If `npm` is chosen, then the step expects a package.json file in the project's root folder. Alternatively, you can specify the path to the file using the `filePath` parameter. + + In case you want to propagate version to addition file(s), it can be done via `additionalTargetTools` and `additionalTargetDescriptors` parameters. + scope: + - PARAMETERS + - STAGES + - STEPS + default: maven + possibleValues: + - maven + - npm + mandatoryIf: + - name: buildTool + value: CAP - name: globalSettingsFile aliases: - name: maven/globalSettingsFile @@ -372,3 +392,9 @@ spec: params: - name: buildTool value: maven + - image: maven:3.6-jdk-8 + conditions: + - conditionRef: strings-equal + params: + - name: buildTool + value: CAP diff --git a/resources/metadata/checkmarxOneExecuteScan.yaml b/resources/metadata/checkmarxOneExecuteScan.yaml index a6f64ed786..0807f7ff2e 100644 --- a/resources/metadata/checkmarxOneExecuteScan.yaml +++ b/resources/metadata/checkmarxOneExecuteScan.yaml @@ -127,6 +127,17 @@ spec: - STAGES - STEPS type: string + - name: gitBranch + description: "Set the GitHub repository branch." + resourceRef: + - name: commonPipelineEnvironment + param: github/branch + scope: + - GENERAL + - PARAMETERS + - STAGES + - STEPS + type: string - name: clientSecret type: string description: The clientSecret to authenticate using a service account diff --git a/resources/metadata/detectExecuteScan.yaml b/resources/metadata/detectExecuteScan.yaml index 2110312a2e..8873952f2f 100644 --- a/resources/metadata/detectExecuteScan.yaml +++ b/resources/metadata/detectExecuteScan.yaml @@ -257,6 +257,15 @@ spec: - STEPS - STAGES - PARAMETERS + - name: generateReportsForEmptyProjects + type: bool + default: false + description: + "If enabled, it will generate reports for empty projects. This could be useful to see the compliance reports in Sirius" + scope: + - STEPS + - STAGES + - PARAMETERS - name: pomPath type: string description: Path to the pom file which should be installed including all children. @@ -340,15 +349,17 @@ spec: - PARAMETERS - STAGES - STEPS + ## --- to remove minScanInterval from parameters list --- - name: minScanInterval description: - "This parameter controls the frequency (in number of hours) at which the signature scan is re-submitted for scan. When set to a + "[DEPRECATED] This parameter controls the frequency (in number of hours) at which the signature scan is re-submitted for scan. When set to a value greater than 0, the signature scans are skipped until the specified number of hours has elapsed since the last signature scan." type: int scope: - PARAMETERS - STAGES - STEPS + ## ----------- - name: githubToken description: "GitHub personal access token as per https://help.github.com/en/github/authenticating-to-github/creating-a-personal-access-token-for-the-command-line" @@ -590,6 +601,17 @@ spec: resourceRef: - name: commonPipelineEnvironment param: container/repositoryPassword + - name: useDetect9 + description: + "This flag enables the use of the supported version 9 of the Detect Script instead of v8" + aliases: + - name: detect/useDetect9 + type: bool + scope: + - PARAMETERS + - STAGES + - STEPS + default: false outputs: resources: - name: influx diff --git a/resources/metadata/gcpPublishEvent.yaml b/resources/metadata/gcpPublishEvent.yaml new file mode 100644 index 0000000000..fb7abd048f --- /dev/null +++ b/resources/metadata/gcpPublishEvent.yaml @@ -0,0 +1,83 @@ +metadata: + name: gcpPublishEvent + description: Publishes an event to GCP using OIDC authentication (beta) + longDescription: | + This step is in beta. + Authentication to GCP is handled by an OIDC token received from, for example, Vault. +spec: + inputs: + params: + - name: vaultNamespace + type: "string" + description: + scope: + - GENERAL + - PARAMETERS + - STAGES + - STEPS + - name: vaultServerUrl + type: "string" + description: + scope: + - GENERAL + - PARAMETERS + - STAGES + - STEPS + - name: OIDCToken + description: + type: "string" + scope: + - PARAMETERS + - STAGES + - STEPS + - name: gcpProjectNumber + description: + type: "string" + scope: + - GENERAL + - PARAMETERS + - STAGES + - STEPS + - name: gcpWorkloadIdentityPool + description: A workload identity pool is an entity that lets you manage external identities. + type: "string" + scope: + - GENERAL + - PARAMETERS + - STAGES + - STEPS + - name: gcpWorkloadIdentityPoolProvider + description: A workload identity pool provider is an entity that describes a relationship between Google Cloud and your IdP. + type: "string" + scope: + - GENERAL + - PARAMETERS + - STAGES + - STEPS + - name: topic + description: The pubsub topic to which the message is published. + type: "string" + scope: + - GENERAL + - PARAMETERS + - STAGES + - STEPS + - name: eventSource + description: The events source as defined by CDEvents. + type: "string" + scope: + - GENERAL + - PARAMETERS + - STAGES + - STEPS + - name: eventType + description: + type: "string" + scope: + - PARAMETERS + - name: eventData + type: string + description: Data to be merged with the generated data for the cloud event data field (JSON) + resourceRef: + - name: commonPipelineEnvironment + param: custom/eventData diff --git a/src/com/sap/piper/PiperGoUtils.groovy b/src/com/sap/piper/PiperGoUtils.groovy index dfaa7b69df..d3ca507e87 100644 --- a/src/com/sap/piper/PiperGoUtils.groovy +++ b/src/com/sap/piper/PiperGoUtils.groovy @@ -30,7 +30,7 @@ class PiperGoUtils implements Serializable { if (steps.env.REPOSITORY_UNDER_TEST && steps.env.LIBRARY_VERSION_UNDER_TEST) { steps.echo("Running in a consumer test, building unit-under-test binary for verification.") - steps.dockerExecute(script: steps, dockerImage: 'golang:1.20', dockerOptions: '-u 0', dockerEnvVars: [ + steps.dockerExecute(script: steps, dockerImage: 'golang:1.21', dockerOptions: '-u 0', dockerEnvVars: [ REPOSITORY_UNDER_TEST: steps.env.REPOSITORY_UNDER_TEST, LIBRARY_VERSION_UNDER_TEST: steps.env.LIBRARY_VERSION_UNDER_TEST ]) { diff --git a/test/groovy/CommonStepsTest.groovy b/test/groovy/CommonStepsTest.groovy index a5ff1bbedf..30c5715828 100644 --- a/test/groovy/CommonStepsTest.groovy +++ b/test/groovy/CommonStepsTest.groovy @@ -106,6 +106,7 @@ public class CommonStepsTest extends BasePiperTest{ } private static fieldRelatedWhitelist = [ + 'abapAddonAssemblyKitCheck', //implementing new golang pattern without fields 'abapAddonAssemblyKitCheckCVs', //implementing new golang pattern without fields 'abapAddonAssemblyKitCheckPV', //implementing new golang pattern without fields 'abapAddonAssemblyKitCreateTargetVector', //implementing new golang pattern without fields diff --git a/vars/abapAddonAssemblyKitCheck.groovy b/vars/abapAddonAssemblyKitCheck.groovy new file mode 100644 index 0000000000..30c5f1b0e5 --- /dev/null +++ b/vars/abapAddonAssemblyKitCheck.groovy @@ -0,0 +1,13 @@ +import groovy.transform.Field + +@Field String STEP_NAME = getClass().getName() +@Field String METADATA_FILE = 'metadata/abapAddonAssemblyKitCheck.yaml' + +void call(Map parameters = [:]) { + List credentials = [ + [type: 'usernamePassword', id: 'abapAddonAssemblyKitCredentialsId', env: ['PIPER_username', 'PIPER_password']], + [type: 'token', id: 'abapAddonAssemblyKitCertificateFileCredentialsId', env: ['PIPER_abapAddonAssemblyKitCertificateFile']], + [type: 'token', id: 'abapAddonAssemblyKitCertificatePassCredentialsId', env: ['PIPER_abapAddonAssemblyKitCertificatePass']] + ] + piperExecuteBin(parameters, STEP_NAME, METADATA_FILE, credentials, false, false, true) +} diff --git a/vars/abapEnvironmentPipelineStageInitialChecks.groovy b/vars/abapEnvironmentPipelineStageInitialChecks.groovy index 0d07359909..9ee6aaea9d 100644 --- a/vars/abapEnvironmentPipelineStageInitialChecks.groovy +++ b/vars/abapEnvironmentPipelineStageInitialChecks.groovy @@ -6,8 +6,8 @@ import static com.sap.piper.Prerequisites.checkScript @Field String STEP_NAME = getClass().getName() @Field Set GENERAL_CONFIG_KEYS = [] @Field STAGE_STEP_KEYS = [ - 'abapAddonAssemblyKitCheckPV', - 'abapAddonAssemblyKitCheckCVs' + 'abapAddonAssemblyKitCheck', + 'abapAddonAssemblyKitReserveNextPackages' ] @Field Set STEP_CONFIG_KEYS = GENERAL_CONFIG_KEYS.plus(STAGE_STEP_KEYS) @Field Set PARAMETER_KEYS = STEP_CONFIG_KEYS @@ -19,8 +19,7 @@ void call(Map parameters = [:]) { def stageName = parameters.stageName?:env.STAGE_NAME piperStageWrapper (script: script, stageName: stageName, stashContent: [], stageLocking: false) { - abapAddonAssemblyKitCheckPV script: parameters.script - abapAddonAssemblyKitCheckCVs script: parameters.script + abapAddonAssemblyKitCheck script: parameters.script abapAddonAssemblyKitReserveNextPackages script: parameters.script }