diff --git a/cliv2/cmd/cliv2/main.go b/cliv2/cmd/cliv2/main.go index 5139cce70b..b54a68a1e1 100644 --- a/cliv2/cmd/cliv2/main.go +++ b/cliv2/cmd/cliv2/main.go @@ -171,6 +171,12 @@ func runWorkflowAndProcessData(engine workflow.Engine, logger *zerolog.Logger, n return err } + output, err = engine.InvokeWithInput(localworkflows.WORKFLOWID_FILTER_FINDINGS, output) + if err != nil { + logger.Err(err).Msg(err.Error()) + return err + } + output, err = engine.InvokeWithInput(localworkflows.WORKFLOWID_OUTPUT_WORKFLOW, output) if err == nil { err = getErrorFromWorkFlowData(engine, output) diff --git a/cliv2/cmd/cliv2/main_test.go b/cliv2/cmd/cliv2/main_test.go index 967747d2b3..40bbaf0198 100644 --- a/cliv2/cmd/cliv2/main_test.go +++ b/cliv2/cmd/cliv2/main_test.go @@ -19,6 +19,7 @@ import ( localworkflows "github.com/snyk/go-application-framework/pkg/local_workflows" "github.com/snyk/go-application-framework/pkg/local_workflows/content_type" "github.com/snyk/go-application-framework/pkg/local_workflows/json_schemas" + "github.com/snyk/go-application-framework/pkg/local_workflows/local_models" "github.com/snyk/go-application-framework/pkg/mocks" "github.com/snyk/go-application-framework/pkg/workflow" "github.com/spf13/cobra" @@ -50,7 +51,7 @@ func Test_MainWithErrorCode(t *testing.T) { func Test_initApplicationConfiguration_DisablesAnalytics(t *testing.T) { t.Run("via SNYK_DISABLE_ANALYTICS (true)", func(t *testing.T) { - c := configuration.NewWithOpts(configuration.WithAutomaticEnv()) + c := configuration.NewWithOpts() assert.False(t, c.GetBool(configuration.ANALYTICS_DISABLED)) c.Set("SNYK_DISABLE_ANALYTICS", "true") @@ -203,6 +204,9 @@ func Test_runMainWorkflow_unknownargs(t *testing.T) { assert.NoError(t, err) _ = globalEngine.Init() + // Register our data filter workflow + err = localworkflows.InitFilterFindingsWorkflow(globalEngine) + assert.NoError(t, err) config := configuration.NewWithOpts(configuration.WithAutomaticEnv()) cmd := &cobra.Command{ @@ -359,6 +363,9 @@ func Test_runWorkflowAndProcessData(t *testing.T) { _, err := globalEngine.Register(workflowId1, workflowConfig, outputFn) assert.NoError(t, err) + // Register our data filter workflow + err = localworkflows.InitFilterFindingsWorkflow(globalEngine) + assert.NoError(t, err) fn := func(invocation workflow.InvocationContext, input []workflow.Data) ([]workflow.Data, error) { typeId := workflow.NewTypeIdentifier(invocation.GetWorkflowIdentifier(), "workflowData") @@ -410,7 +417,7 @@ func Test_runWorkflowAndProcessData(t *testing.T) { assert.Equal(t, constants.SNYK_EXIT_CODE_VULNERABILITIES_FOUND, actualCode) } -func Test_runWorkflowAndProcessData_WithTransformation(t *testing.T) { +func Test_runWorkflowAndProcessData_with_Transformation(t *testing.T) { defer cleanup() globalConfiguration = configuration.New() globalConfiguration.Set(configuration.DEBUG, true) @@ -447,6 +454,10 @@ func Test_runWorkflowAndProcessData_WithTransformation(t *testing.T) { err = localworkflows.InitDataTransformationWorkflow(globalEngine) assert.NoError(t, err) + // Register our data filter workflow + err = localworkflows.InitFilterFindingsWorkflow(globalEngine) + assert.NoError(t, err) + // Invoke a custom command that returns input fn := func(invocation workflow.InvocationContext, input []workflow.Data) ([]workflow.Data, error) { typeId := workflow.NewTypeIdentifier(invocation.GetWorkflowIdentifier(), "workflowData") @@ -487,6 +498,92 @@ func Test_runWorkflowAndProcessData_WithTransformation(t *testing.T) { err = runWorkflowAndProcessData(globalEngine, &logger, testCmnd) } +func Test_runWorkflowAndProcessData_with_Filtering(t *testing.T) { + defer cleanup() + globalConfiguration = configuration.New() + globalConfiguration.Set(configuration.DEBUG, true) + globalConfiguration.Set(configuration.IN_MEMORY_THRESHOLD_BYTES, -1) + globalConfiguration.Set(configuration.FLAG_SEVERITY_THRESHOLD, "critical") + globalConfiguration.Set(configuration.FF_TRANSFORMATION_WORKFLOW, true) + + globalEngine = workflow.NewWorkFlowEngine(globalConfiguration) + + testCmnd := "subcmd1" + workflowId1 := workflow.NewWorkflowIdentifier("output") + + outputFn := func(invocation workflow.InvocationContext, input []workflow.Data) ([]workflow.Data, error) { + var findings local_models.LocalFinding + for i := range input { + mimeType := input[i].GetContentType() + + if strings.HasPrefix(mimeType, content_type.LOCAL_FINDING_MODEL) { + findingsBytes := input[i].GetPayload().([]byte) + err := json.Unmarshal(findingsBytes, &findings) + assert.NoError(t, err) + } + + } + + // expect all findings below critical to be filtered out, test data has no critical severity findings + assert.Equal(t, len(findings.Findings), 0) + + return input, nil + } + + workflowConfig := workflow.ConfigurationOptionsFromFlagset(pflag.NewFlagSet("pla", pflag.ContinueOnError)) + + _, err := globalEngine.Register(workflowId1, workflowConfig, outputFn) + assert.NoError(t, err) + + // Register our data transformation workflow + err = localworkflows.InitDataTransformationWorkflow(globalEngine) + assert.NoError(t, err) + + // Register our data filter workflow + err = localworkflows.InitFilterFindingsWorkflow(globalEngine) + assert.NoError(t, err) + + // Invoke a custom command that returns input + fn := func(invocation workflow.InvocationContext, input []workflow.Data) ([]workflow.Data, error) { + typeId := workflow.NewTypeIdentifier(invocation.GetWorkflowIdentifier(), "workflowData") + testSummary := json_schemas.TestSummary{ + Results: []json_schemas.TestSummaryResult{ + { + Severity: "critical", + Total: 10, + Open: 10, + Ignored: 0, + }, + }, + Type: "sast", + SeverityOrderAsc: []string{"low", "medium", "high", "critical"}, + } + + var d []byte + d, err = json.Marshal(testSummary) + assert.NoError(t, err) + + testSummaryData := workflow.NewData(typeId, content_type.TEST_SUMMARY, d) + sarifData := workflow.NewData(typeId, content_type.SARIF_JSON, + loadJsonFile(t, "sarif.json")) + + return []workflow.Data{ + testSummaryData, + sarifData, + }, nil + } + wrkflowId := workflow.NewWorkflowIdentifier(testCmnd) + entry, err := globalEngine.Register(wrkflowId, workflowConfig, fn) + assert.NoError(t, err) + assert.NotNil(t, entry) + + err = globalEngine.Init() + assert.NoError(t, err) + + logger := zerolog.New(os.Stderr) + err = runWorkflowAndProcessData(globalEngine, &logger, testCmnd) +} + func Test_setTimeout(t *testing.T) { exitedCh := make(chan struct{}) fakeExit := func() { diff --git a/cliv2/go.mod b/cliv2/go.mod index ba87521e00..16e3e7c75d 100644 --- a/cliv2/go.mod +++ b/cliv2/go.mod @@ -17,7 +17,7 @@ require ( github.com/snyk/cli-extension-sbom v0.0.0-20241016065306-0df2be5b3b8f github.com/snyk/container-cli v0.0.0-20240821111304-7ca1c415a5d7 github.com/snyk/error-catalog-golang-public v0.0.0-20240809094525-c48d19c27edb - github.com/snyk/go-application-framework v0.0.0-20241029131533-b495e35f30ac + github.com/snyk/go-application-framework v0.0.0-20241101135023-fb22eed5a7ba github.com/snyk/go-httpauth v0.0.0-20240307114523-1f5ea3f55c65 github.com/snyk/snyk-iac-capture v0.6.5 github.com/snyk/snyk-ls v0.0.0-20241023124225-627b73041471 @@ -138,6 +138,7 @@ require ( github.com/muesli/cancelreader v0.2.2 // indirect github.com/muesli/reflow v0.3.0 // indirect github.com/muesli/termenv v0.15.2 // indirect + github.com/oapi-codegen/oapi-codegen/v2 v2.3.0 // indirect github.com/oapi-codegen/runtime v1.1.1 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/open-policy-agent/opa v0.51.0 // indirect @@ -221,6 +222,7 @@ require ( // version 2491eb6c1c75 contains a valid license replace github.com/mattn/go-localereader v0.0.1 => github.com/mattn/go-localereader v0.0.2-0.20220822084749-2491eb6c1c75 -//replace github.com/snyk/go-application-framework => ../../go-application-framework +// replace github.com/snyk/go-application-framework => ../../go-application-framework + //replace github.com/snyk/snyk-ls => ../../snyk-ls //replace github.com/snyk/code-client-go => ../../code-client-go diff --git a/cliv2/go.sum b/cliv2/go.sum index 294f8ea6c7..d8452227f4 100644 --- a/cliv2/go.sum +++ b/cliv2/go.sum @@ -667,6 +667,8 @@ github.com/muesli/termenv v0.11.1-0.20220212125758-44cd13922739/go.mod h1:Bd5NYQ github.com/muesli/termenv v0.13.0/go.mod h1:sP1+uffeLaEYpyOTb8pLCUctGcGLnoFjSn4YJK5e2bc= github.com/muesli/termenv v0.15.2 h1:GohcuySI0QmI3wN8Ok9PtKGkgkFIk7y6Vpb5PvrY+Wo= github.com/muesli/termenv v0.15.2/go.mod h1:Epx+iuz8sNs7mNKhxzH4fWXGNpZwUaJKRS1noLXviQ8= +github.com/oapi-codegen/oapi-codegen/v2 v2.3.0 h1:rICjNsHbPP1LttefanBPnwsSwl09SqhCO7Ee623qR84= +github.com/oapi-codegen/oapi-codegen/v2 v2.3.0/go.mod h1:4k+cJeSq5ntkwlcpQSxLxICCxQzCL772o30PxdibRt4= github.com/oapi-codegen/runtime v1.1.1 h1:EXLHh0DXIJnWhdRPN2w4MXAzFyE4CskzhNLUmtpMYro= github.com/oapi-codegen/runtime v1.1.1/go.mod h1:SK9X900oXmPWilYR5/WKPzt3Kqxn/uS/+lbpREv+eCg= github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= @@ -762,8 +764,10 @@ github.com/snyk/container-cli v0.0.0-20240821111304-7ca1c415a5d7 h1:Zn5BcV76oFAb github.com/snyk/container-cli v0.0.0-20240821111304-7ca1c415a5d7/go.mod h1:38w+dcAQp9eG3P5t2eNS9eG0reut10AeJjLv5lJ5lpM= github.com/snyk/error-catalog-golang-public v0.0.0-20240809094525-c48d19c27edb h1:w9tJhpTFxWqAhLeraGsMExDjGK9x5Dwj1NRFwb+t+QE= github.com/snyk/error-catalog-golang-public v0.0.0-20240809094525-c48d19c27edb/go.mod h1:Ytttq7Pw4vOCu9NtRQaOeDU2dhBYUyNBe6kX4+nIIQ4= -github.com/snyk/go-application-framework v0.0.0-20241029131533-b495e35f30ac h1:kqy5svAquK3HRnyIt7TkxbgUw7yP1vXtiWQjEuQ5DyU= -github.com/snyk/go-application-framework v0.0.0-20241029131533-b495e35f30ac/go.mod h1:5aMJH42nmeZgPRXvN5fdAZVoutATPnY9yTb68Iz7zYk= +github.com/snyk/go-application-framework v0.0.0-20241030090346-7c026ae95bd3 h1:OS3nX1/CWgY3wM+SzVIs/IOK5NY2G2A4LOsnrDdNmc8= +github.com/snyk/go-application-framework v0.0.0-20241030090346-7c026ae95bd3/go.mod h1:5aMJH42nmeZgPRXvN5fdAZVoutATPnY9yTb68Iz7zYk= +github.com/snyk/go-application-framework v0.0.0-20241101135023-fb22eed5a7ba h1:9bz0lRhukfp2EgY3td478WkIvTfrjgyCfOyshHJO2Ew= +github.com/snyk/go-application-framework v0.0.0-20241101135023-fb22eed5a7ba/go.mod h1:5aMJH42nmeZgPRXvN5fdAZVoutATPnY9yTb68Iz7zYk= github.com/snyk/go-httpauth v0.0.0-20240307114523-1f5ea3f55c65 h1:CEQuYv0Go6MEyRCD3YjLYM2u3Oxkx8GpCpFBd4rUTUk= github.com/snyk/go-httpauth v0.0.0-20240307114523-1f5ea3f55c65/go.mod h1:88KbbvGYlmLgee4OcQ19yr0bNpXpOr2kciOthaSzCAg= github.com/snyk/policy-engine v0.31.3 h1:FepCg6QN/X8uvxYjF+WwB2aiBPJB+NENDgKQeI/FwLg=