diff --git a/cmd/checkmarxOneExecuteScan.go b/cmd/checkmarxOneExecuteScan.go index f06f5a2164..3dfd48a4cc 100644 --- a/cmd/checkmarxOneExecuteScan.go +++ b/cmd/checkmarxOneExecuteScan.go @@ -202,7 +202,7 @@ func Authenticate(config checkmarxOneExecuteScanOptions, influx *checkmarxOneExe if err != nil { log.Entry().WithError(err).Warning("Failed to get GitHub client") } - sys, err := checkmarxOne.NewSystemInstance(client, config.ServerURL, config.IamURL, config.Tenant, config.APIKey, config.ClientID, config.ClientSecret) + sys, err := checkmarxOne.NewSystemInstance(client, config.ServerURL, config.IamURL, config.Tenant, config.APIKey, config.ClientID, config.ClientSecret, config.AccessToken) if err != nil { return checkmarxOneExecuteScanHelper{}, fmt.Errorf("failed to create Checkmarx One client talking to URLs %v and %v with tenant %v: %s", config.ServerURL, config.IamURL, config.Tenant, err) } diff --git a/cmd/checkmarxOneExecuteScan_generated.go b/cmd/checkmarxOneExecuteScan_generated.go index 2d6deb1b53..80e8c513c3 100644 --- a/cmd/checkmarxOneExecuteScan_generated.go +++ b/cmd/checkmarxOneExecuteScan_generated.go @@ -36,6 +36,7 @@ type checkmarxOneExecuteScanOptions struct { GitBranch string `json:"gitBranch,omitempty"` ClientSecret string `json:"clientSecret,omitempty"` APIKey string `json:"APIKey,omitempty"` + AccessToken string `json:"accessToken,omitempty"` Preset string `json:"preset,omitempty"` LanguageMode string `json:"languageMode,omitempty"` ProjectCriticality string `json:"projectCriticality,omitempty"` @@ -280,6 +281,7 @@ thresholds instead of ` + "`" + `percentage` + "`" + ` whereas we strongly recom log.RegisterSecret(stepConfig.GithubToken) log.RegisterSecret(stepConfig.ClientSecret) log.RegisterSecret(stepConfig.APIKey) + log.RegisterSecret(stepConfig.AccessToken) log.RegisterSecret(stepConfig.ClientID) if len(GeneralConfig.HookConfig.SentryConfig.Dsn) > 0 { @@ -382,6 +384,7 @@ func addCheckmarxOneExecuteScanFlags(cmd *cobra.Command, stepConfig *checkmarxOn 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.AccessToken, "accessToken", os.Getenv("PIPER_accessToken"), "Token for APIs access. This parameter is used uniquely for the integration with Trust Engine API and the value will be filled automatically by the system. Outside this usecase, OAuth client (clientId/clientSecret) or APIKey must be used for authentication.") 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`") cmd.Flags().StringVar(&stepConfig.LanguageMode, "languageMode", `multi`, "Specifies whether the scan should be run for a 'single' language or 'multi' language, default 'multi'") cmd.Flags().StringVar(&stepConfig.ProjectCriticality, "projectCriticality", `3`, "The criticality of the checkmarxOne project, used during project creation") @@ -413,6 +416,7 @@ func addCheckmarxOneExecuteScanFlags(cmd *cobra.Command, stepConfig *checkmarxOn cmd.MarkFlagRequired("clientSecret") cmd.MarkFlagRequired("APIKey") + cmd.MarkFlagRequired("accessToken") cmd.MarkFlagRequired("projectCriticality") cmd.MarkFlagRequired("projectName") cmd.MarkFlagRequired("branch") @@ -603,6 +607,21 @@ func checkmarxOneExecuteScanMetadata() config.StepData { Aliases: []config.Alias{}, Default: os.Getenv("PIPER_APIKey"), }, + { + Name: "accessToken", + ResourceRef: []config.ResourceReference{ + { + Name: "cxoneSystemtrustSecretName", + Type: "systemTrustSecret", + Default: "cxone", + }, + }, + Scope: []string{"PARAMETERS"}, + Type: "string", + Mandatory: true, + Aliases: []config.Alias{}, + Default: os.Getenv("PIPER_accessToken"), + }, { Name: "preset", ResourceRef: []config.ResourceReference{}, diff --git a/pkg/checkmarxone/checkmarxone.go b/pkg/checkmarxone/checkmarxone.go index 6b25da1325..8e32987037 100644 --- a/pkg/checkmarxone/checkmarxone.go +++ b/pkg/checkmarxone/checkmarxone.go @@ -283,6 +283,7 @@ type SystemInstance struct { APIKey string // New for Cx1 oauth_client_id string // separate from APIKey oauth_client_secret string //separate from APIKey + accessToken string client piperHttp.Uploader logger *logrus.Entry } @@ -338,7 +339,7 @@ type System interface { // NewSystemInstance returns a new Checkmarx client for communicating with the backend // Updated for Cx1 -func NewSystemInstance(client piperHttp.Uploader, serverURL, iamURL, tenant, APIKey, client_id, client_secret string) (*SystemInstance, error) { +func NewSystemInstance(client piperHttp.Uploader, serverURL, iamURL, tenant, APIKey, client_id, client_secret, accessToken string) (*SystemInstance, error) { loggerInstance := log.Entry().WithField("package", "SAP/jenkins-library/pkg/checkmarxOne") sys := &SystemInstance{ serverURL: serverURL, @@ -347,27 +348,36 @@ func NewSystemInstance(client piperHttp.Uploader, serverURL, iamURL, tenant, API APIKey: APIKey, oauth_client_id: client_id, oauth_client_secret: client_secret, + accessToken: accessToken, client: client, logger: loggerInstance, } var token string var err error - - if APIKey != "" { + var authModel string + + if accessToken != "" { // use access token if provided by the system trust API + authModel = "SystemTrust" + tokenType := "Bearer " + token = tokenType + accessToken + } else if APIKey != "" { + authModel = "APIKey" token, err = sys.getAPIToken() if err != nil { return sys, errors.Wrap(err, fmt.Sprintf("Error fetching oAuth token using API Key: %v", shortenGUID(APIKey))) } } else if client_id != "" && client_secret != "" { + authModel = "OAuth2" token, err = sys.getOAuth2Token() if err != nil { return sys, errors.Wrap(err, fmt.Sprintf("Error fetching oAuth token using OIDC client: %v/%v", shortenGUID(client_id), shortenGUID(client_secret))) } } else { - return sys, errors.New("No APIKey or client_id/client_secret provided.") + return sys, errors.New("No APIKey or client_id/client_secret or system trust token provided.") } + sys.logger.Debugf("Created access token from %v", authModel) log.RegisterSecret(token) options := piperHttp.ClientOptions{ diff --git a/pkg/checkmarxone/checkmarxone_test.go b/pkg/checkmarxone/checkmarxone_test.go index 6b7ccf499c..f1a169fc86 100644 --- a/pkg/checkmarxone/checkmarxone_test.go +++ b/pkg/checkmarxone/checkmarxone_test.go @@ -119,7 +119,7 @@ func TestGetOAuthToken(t *testing.T) { opts := piperHttp.ClientOptions{} t.Run("test success", func(t *testing.T) { myTestClient := senderMock{responseBody: `{"token_type":"Bearer","access_token":"abcd12345","expires_in":7045634}`, httpStatusCode: 200} - sys, _ := NewSystemInstance(&myTestClient, "https://cx1.server.com", "https://cx1iam.server.com", "tenant", "", "client", "secret") + sys, _ := NewSystemInstance(&myTestClient, "https://cx1.server.com", "https://cx1iam.server.com", "tenant", "", "client", "secret", "") myTestClient.SetOptions(opts) token, err := sys.getOAuth2Token() @@ -143,7 +143,7 @@ func TestGetOAuthToken(t *testing.T) { t.Run("test new system", func(t *testing.T) { myTestClient := senderMock{responseBody: `{"token_type":"Bearer","access_token":"abcd12345","expires_in":7045634}`, httpStatusCode: 200} - _, err := NewSystemInstance(&myTestClient, "https://cx1.server.com", "https://cx1iam.server.com", "tenant", "", "client", "secret") + _, err := NewSystemInstance(&myTestClient, "https://cx1.server.com", "https://cx1iam.server.com", "tenant", "", "client", "secret", "") assert.NoError(t, err, "Error occurred but none expected") assert.Equal(t, "https://cx1iam.server.com/auth/realms/tenant/protocol/openid-connect/token", myTestClient.urlCalled, "Called url incorrect") diff --git a/resources/metadata/checkmarxOneExecuteScan.yaml b/resources/metadata/checkmarxOneExecuteScan.yaml index ff89ea18b3..9a7d3bef20 100644 --- a/resources/metadata/checkmarxOneExecuteScan.yaml +++ b/resources/metadata/checkmarxOneExecuteScan.yaml @@ -170,6 +170,17 @@ spec: - type: vaultSecret name: checkmarxOneVaultSecretName default: checkmarxOne + - name: accessToken + type: string + description: Token for APIs access. This parameter is used uniquely for the integration with Trust Engine API and the value will be filled automatically by the system. Outside this usecase, OAuth client (clientId/clientSecret) or APIKey must be used for authentication. + mandatory: true + scope: + - PARAMETERS + secret: true + resourceRef: + - type: systemTrustSecret + name: cxoneSystemtrustSecretName + default: cxone - name: preset type: string description: 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`