Skip to content

Commit 7fdb954

Browse files
feat: add remote scan
1 parent aa5a5a7 commit 7fdb954

File tree

4 files changed

+156
-6
lines changed

4 files changed

+156
-6
lines changed

internal/analysis/analysis.go

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,15 @@ type AnalysisOrchestrator interface {
5353
RunIncrementalAnalysis(ctx context.Context, orgId string, rootPath string, workspaceId string, limitToFiles []string) (*sarif.SarifResponse, error)
5454

5555
RunTest(ctx context.Context, orgId string, b bundle.Bundle, target scan.Target, reportingOptions ReportingConfig) (*sarif.SarifResponse, error)
56+
RunTestRemote(ctx context.Context, orgId string, interactionId string, reportingOptions ReportingConfig) (*sarif.SarifResponse, error)
5657
}
5758

5859
type ReportingConfig struct {
5960
Report *bool
6061
ProjectName *string
6162
TargetName *string
63+
ProjectId *uuid.UUID
64+
CommitId *string
6265
}
6366
type analysisOrchestrator struct {
6467
httpClient codeClientHTTP.HTTPClient
@@ -544,6 +547,84 @@ func (a *analysisOrchestrator) RunTest(ctx context.Context, orgId string, b bund
544547
}
545548
}
546549

550+
func (a *analysisOrchestrator) RunTestRemote(ctx context.Context, orgId string, interactionId string, cfg ReportingConfig) (*sarif.SarifResponse, error) {
551+
tracker := a.trackerFactory.GenerateTracker()
552+
tracker.Begin("Snyk Code analysis for remote project", "Retrieving results...")
553+
554+
orgUuid := uuid.MustParse(orgId)
555+
host := a.host(true)
556+
557+
client, err := testApi.NewClient(host, testApi.WithHTTPClient(a.httpClient))
558+
if err != nil {
559+
return nil, err
560+
}
561+
562+
params := testApi.CreateTestParams{Version: testApi.ApiVersion}
563+
projectId := cfg.ProjectId
564+
commitId := cfg.CommitId
565+
fmt.Println("Creating test")
566+
prettyBytes, err := json.MarshalIndent(cfg, "", " ")
567+
if err != nil {
568+
return nil, err
569+
}
570+
fmt.Println(string(prettyBytes))
571+
572+
if projectId == nil || commitId == nil {
573+
return nil, errors.New("projectId and commitId are required")
574+
}
575+
legacyScmProject := testApi.NewTestInputLegacyScmProject(*projectId, *commitId)
576+
body := testApi.NewCreateTestApplicationBody(
577+
testApi.WithInputLegacyScmProject(legacyScmProject),
578+
testApi.WithReporting(cfg.Report),
579+
testApi.WithScanType(a.testType),
580+
testApi.WithProjectId(*projectId),
581+
582+
)
583+
fmt.Println("Creating test")
584+
prettyBytes, err = json.MarshalIndent(body, "", " ")
585+
if err != nil {
586+
return nil, err
587+
}
588+
fmt.Println(string(prettyBytes))
589+
590+
// create test
591+
bodyBytes, err := json.Marshal(body)
592+
if err != nil {
593+
return nil, err
594+
}
595+
resp, err := client.CreateTestWithBody(ctx, orgUuid, &params, "application/json", strings.NewReader(string(bodyBytes)))
596+
if err != nil {
597+
return nil, err
598+
}
599+
600+
parsedResponse, err := testApi.ParseGetTestResultResponse(resp)
601+
defer func() {
602+
closeErr := resp.Body.Close()
603+
if closeErr != nil {
604+
a.logger.Err(closeErr).Msg("failed to close response body")
605+
}
606+
}()
607+
if err != nil {
608+
a.logger.Debug().Msg(err.Error())
609+
return nil, err
610+
}
611+
612+
switch parsedResponse.StatusCode() {
613+
case http.StatusCreated:
614+
// poll results
615+
result, pollErr := a.pollTestForFindings(ctx, client, orgUuid, parsedResponse.ApplicationvndApiJSON200.Data.Id)
616+
formattedResult, err := json.MarshalIndent(parsedResponse.ApplicationvndApiJSON200, "", " ")
617+
if err != nil {
618+
return nil, err
619+
}
620+
fmt.Println(string(formattedResult))
621+
tracker.End("Analysis complete.")
622+
return result, pollErr
623+
default:
624+
return nil, fmt.Errorf("failed to analyze project: %s", parsedResponse.Status())
625+
}
626+
}
627+
547628
func (a *analysisOrchestrator) pollTestForFindings(ctx context.Context, client *testApi.Client, org uuid.UUID, testId openapi_types.UUID) (*sarif.SarifResponse, error) {
548629
method := "analysis.pollTestForFindings"
549630
logger := a.logger.With().Str("method", method).Logger()

internal/analysis/mocks/analysis.go

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/api/test/2024-12-21/helper.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,12 @@ func WithInputBundle(id string, localFilePath string, repoUrl *string, limitTest
3030
}
3131
}
3232

33+
func WithInputLegacyScmProject(project v20241221.TestInputLegacyScmProject) CreateTestOption {
34+
return func(body *CreateTestApplicationVndAPIPlusJSONRequestBody) {
35+
body.Data.Attributes.Input.FromTestInputLegacyScmProject(project)
36+
}
37+
}
38+
3339
func WithScanType(t v20241221.Scan) CreateTestOption {
3440
return func(body *CreateTestApplicationVndAPIPlusJSONRequestBody) {
3541
body.Data.Attributes.Configuration.Scan = struct {
@@ -69,6 +75,13 @@ func WithProjectName(name *string) CreateTestOption {
6975
}
7076
}
7177

78+
func WithProjectId(id openapi_types.UUID) CreateTestOption {
79+
return func(body *CreateTestApplicationVndAPIPlusJSONRequestBody) {
80+
out := ensureOutput(body)
81+
out.ProjectId = &id
82+
}
83+
}
84+
7285
func WithTargetName(name *string) CreateTestOption {
7386
return func(body *CreateTestApplicationVndAPIPlusJSONRequestBody) {
7487
if name == nil {
@@ -98,3 +111,11 @@ func NewCreateTestApplicationBody(options ...CreateTestOption) *CreateTestApplic
98111

99112
return result
100113
}
114+
115+
func NewTestInputLegacyScmProject(projectId openapi_types.UUID, commitId string) v20241221.TestInputLegacyScmProject {
116+
return v20241221.TestInputLegacyScmProject{
117+
ProjectId: projectId,
118+
CommitId: commitId,
119+
Type: v20241221.LegacyScmProject,
120+
}
121+
}

scan.go

Lines changed: 39 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ package codeclient
2020
import (
2121
"context"
2222

23+
"github.com/google/uuid"
2324
"github.com/pkg/errors"
2425
"github.com/rs/zerolog"
2526

@@ -55,7 +56,7 @@ type CodeScanner interface {
5556
target scan.Target,
5657
files <-chan string,
5758
changedFiles map[string]bool,
58-
options ...UploadAndAnalyzeOption,
59+
options ...ReportingOption,
5960
) (*sarif.SarifResponse, string, error)
6061
}
6162

@@ -110,12 +111,23 @@ func WithTargetName(targetName *string) OptionFunc {
110111
}
111112
}
112113

113-
type UploadAndAnalyzeOption func(*analysis.ReportingConfig)
114+
type ReportingOption func(*analysis.ReportingConfig)
114115

115-
func WithReportingConfig(projectName *string, targetName *string) UploadAndAnalyzeOption {
116+
func WithReportingConfig(report bool, config map[string]interface{}) ReportingOption {
116117
return func(c *analysis.ReportingConfig) {
117-
c.ProjectName = projectName
118-
c.TargetName = targetName
118+
c.Report = &report
119+
if projectName, ok := config["projectName"].(*string); ok {
120+
c.ProjectName = projectName
121+
}
122+
if targetName, ok := config["targetName"].(*string); ok {
123+
c.TargetName = targetName
124+
}
125+
if projectId, ok := config["projectId"].(*uuid.UUID); ok {
126+
c.ProjectId = projectId
127+
}
128+
if commitId, ok := config["commitId"].(*string); ok {
129+
c.CommitId = commitId
130+
}
119131
}
120132
}
121133

@@ -193,7 +205,7 @@ func (c *codeScanner) UploadAndAnalyze(
193205
target scan.Target,
194206
files <-chan string,
195207
changedFiles map[string]bool,
196-
options ...UploadAndAnalyzeOption,
208+
options ...ReportingOption,
197209
) (*sarif.SarifResponse, string, error) {
198210
cfg := analysis.ReportingConfig{}
199211
for _, opt := range options {
@@ -248,3 +260,24 @@ func (c *codeScanner) UploadAndAnalyze(
248260

249261
return response, bundleHash, err
250262
}
263+
264+
func (c *codeScanner) AnalyzeRemote(ctx context.Context, interactionId string, options ...ReportingOption) (*sarif.SarifResponse, error) {
265+
cfg := analysis.ReportingConfig{}
266+
for _, opt := range options {
267+
opt(&cfg)
268+
}
269+
270+
if ctx.Err() != nil {
271+
c.logger.Info().Msg("Canceling Code scan - Code scanner received cancellation signal")
272+
return nil, nil
273+
}
274+
response, err := c.analysisOrchestrator.RunTestRemote(ctx, c.config.Organization(), interactionId, cfg)
275+
276+
277+
if ctx.Err() != nil {
278+
c.logger.Info().Msg("Canceling Code scan - Code scanner received cancellation signal")
279+
return nil, nil
280+
}
281+
282+
return response, err
283+
}

0 commit comments

Comments
 (0)