Skip to content

Latest commit

 

History

760 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Repository Update

This repository will remain public but will be moving to a new location in the future. More details around the timeline will be shared as soon as they are available - apologies for the inconvenience.

Module information

This is a basic CheckmarxOne REST API client written in GoLang.

Documentation for LLM-assisted development

The _examples/ directory contains a set of docs generated specifically to let an LLM (or a human unfamiliar with this library) write correct scripts against Cx1ClientGo without guessing at API shape or object-creation order. Start at _examples/USAGE.md

  • it routes to worked examples of individual API mechanics, end-to-end task recipes, and a description of how CheckmarxOne platform objects relate to and depend on each other.

Basic usage

package main

import (
	"net/http"

	"github.com/cxpsemea/Cx1ClientGo"
	log "github.com/sirupsen/logrus"
)

func main() {
	logger := log.New()
	logger.Infof( "Starting" )
	cx1client, err := Cx1ClientGo.NewClient(&http.Client{}, logger)
	if err != nil {
		log.Error( "Error creating client: " + err.Error() )
		return 
	}

	// no err means that the client is initialized
	logger.Infof( "Client initialized: %s", cx1client.String() )
}

Using the NewClient function includes command-line arguments - the above example will include output help on command-line arguments when executed:

> go run . -h
[INFO][2025-11-11 14:00:57.344] Starting
Usage of C:\..\cx1test.exe:
  -apikey string
        CheckmarxOne API Key (if not using client id/secret)
  -client string
        CheckmarxOne Client ID (if not using API Key)
  -cx1 string
        Optional: CheckmarxOne platform URL, if not defined in the test config.yaml
  -iam string
        Optional: CheckmarxOne IAM URL, if not defined in the test config.yaml
  -secret string
        CheckmarxOne Client Secret (if not using API Key)
  -tenant string
        Optional: CheckmarxOne tenant, if not defined in the test config.yaml

More complete workflow example

package main

import (
	"crypto/tls"
	"fmt"
	"net/http"
	"net/url"
	"os"
	"time"

	"github.com/cxpsemea/Cx1ClientGo"
	log "github.com/sirupsen/logrus"
)

func main() {
	logger := log.New()
	logger.Infof( "Starting" )
	//logger.SetLevel( log.TraceLevel ) 

	api_key := os.Args[1]
	project_name := os.Args[2]
	group_name := os.Args[3]
	project_repo := os.Args[4]
	branch_name := os.Args[5]
	
	proxyURL, err := url.Parse( "http://127.0.0.1:8080" )
	transport := &http.Transport{}
	transport.Proxy = http.ProxyURL(proxyURL)
	transport.TLSClientConfig = &tls.Config{ InsecureSkipVerify: true, }
	
	httpClient := &http.Client{}
	//httpClient.Transport = transport
	
	// base_url, iam_url, and tenant are derived automatically from the API key's own JWT claims
	cx1client, err := Cx1ClientGo.NewAPIKeyClient( httpClient, api_key, logger )
	if err != nil {
		log.Error( "Error creating client: " + err.Error() )
		return 
	}

	// no err means that the client is initialized
	logger.Infof( "Client initialized: %s", cx1client.String() )
	
	group, err := cx1client.GetGroupByName( group_name )
	if err != nil {
		if err.Error() != fmt.Sprintf( "no group %v found", group_name ) {
			logger.Infof( "Failed to retrieve group named %s: %v", group_name, err )
			return
		}
		
		logger.Infof( "No group named %s exists - it will now be created", group_name )
		group, err = cx1client.CreateGroup( group_name )
		if err != nil {
			logger.Errorf( "Failed to create group %s: %v", group_name, err )
			return
		}
		
		logger.Infof( "Created group named '%v' with ID %v", group.Name, group.GroupID )
	} else {	
		logger.Infof( "Found group named %v with ID %v", group.Name, group.GroupID )
	}
	
	projects, err := cx1client.GetProjectsByNameAndGroupID( project_name, group.GroupID )
	if err != nil {
		logger.Errorf( "Failed to retrieve project named %s: %v", project_name, err )
		return
	}	
	
	var project Cx1ClientGo.Project
	if len(projects) == 0 {
		logger.Infof( "No project named %s found under group %s - it will now be created", project_name, group_name )
		project, err = cx1client.CreateProject( project_name, []string{ group.GroupID }, map[string]string{ "CreatedBy" : "Cx1ClientGo" } )
		if err != nil {
			logger.Errorf( "Failed to create project %s: %v", project_name, err )
			return
		}
		logger.Infof( "Created project named '%v' with ID %v", project.Name, project.ProjectID )
	} else {
		project = projects[0]
		logger.Infof( "First project matching '%v' in group '%v' is named '%v' with ID %v", project_name, group_name, project.Name, project.ProjectID )
	}
	
	scanConfig := Cx1ClientGo.ScanConfiguration{}
	scanConfig.ScanType = "sast"
	scanConfig.Values = map[string]string{ "incremental" : "false" }
	
	scan, err := cx1client.ScanProjectGitByID( project.ProjectID, project_repo, branch_name, []Cx1ClientGo.ScanConfiguration{scanConfig}, map[string]string{ "CreatedBy" : "Cx1ClientGo" } )
	
	if err != nil {
		logger.Errorf( "Failed to trigger scan with repository '%v' branch '%v': %s", project_repo, branch_name, err )
		return
	}
	
	logger.Infof( "Triggered scan %v, polling status", scan.ScanID )
	for scan.Status == "Running" {
		time.Sleep( 10 * time.Second )
		scan, err = cx1client.GetScanByID( scan.ScanID )
		if err != nil {
			logger.Errorf( "Failed to get scan status: %v", err )
			return
		}
		logger.Infof( " - %v", scan.Status )
	}
	
	reportID, err := cx1client.RequestNewReportByID( scan.ScanID, project.ProjectID, branch_name, "pdf", []string{"sast"}, []string{"ScanSummary", "ExecutiveSummary", "ScanResults"} )
	if err != nil {
		logger.Errorf( "Failed to trigger new report generation for scan ID %v, project ID %v: %s", scan.ScanID, project.ProjectID, err )
		return
	}
	
	logger.Infof( "Generating report %v, polling status", reportID )
	var status Cx1ClientGo.ReportStatus
	
	for status.Status != "completed" {
		time.Sleep( 10 * time.Second )
		status, err = cx1client.GetReportStatusByID( reportID )
		if err != nil {
			logger.Errorf( "Failed to get report status: %v", err )
			return
		}
		
		logger.Infof( " - %v", status.Status )
	}
	
	logger.Infof( "Downloading report from %v", status.ReportURL )
	reportData, err := cx1client.DownloadReport( status.ReportURL )
	if err != nil {
		logger.Errorf( "Failed to download report: %s", err )
		return
	}
	
	err = os.WriteFile( "report.pdf", reportData, 0o700 )
	if err != nil {
		logger.Errorf( "Failed to Update report: %s", err )
		return
	}
	logger.Infof( "Report Updated to report.pdf" )
	
	// GetScanResultsByID takes a limit on how many results to retrieve (0 fetches just the first page);
	// use GetAllScanResultsByID to page through everything
	scanresults, err := cx1client.GetAllScanResultsByID( scan.ScanID )
	if err != nil {
		logger.Errorf( "Failed to retrieve scan results: %s", err )
		return
	}
	
	logger.Infof( "%d SAST results retrieved", len(scanresults.SAST) )
	
	for _, result := range scanresults.SAST {
		logger.Infof( "Finding with similarity ID: %v", result.SimilarityID )
	}
}

Invocation for the more complicated example: go run . "API Key" "Project Name" "Group Name" "https://my.github/project/repo" "branch"

Note that the Cx1ClientGo library is not an official Checkmarx product and does not include any guarantees of support or future improvements. It is a library built to facilitate delivering custom development work on integrations with the CheckmarxOne platform.

About

Simple client for Cx1 written in GoLang

Resources

Stars

1 star

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages