Skip to content

Commit b1dcebb

Browse files
- Vorpal Custom Path Implementation
1 parent 262cc8f commit b1dcebb

15 files changed

Lines changed: 467 additions & 24 deletions

File tree

internal/commands/asca/asca-engine.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,16 +6,24 @@ import (
66
"github.com/checkmarx/ast-cli/internal/services"
77
"github.com/checkmarx/ast-cli/internal/wrappers"
88
"github.com/checkmarx/ast-cli/internal/wrappers/grpcs"
9+
"github.com/checkmarx/ast-cli/internal/wrappers/utils"
910
"github.com/spf13/cobra"
1011
"github.com/spf13/viper"
1112
)
1213

1314
func RunScanASCACommand(jwtWrapper wrappers.JWTWrapper) func(cmd *cobra.Command, args []string) error {
1415
return func(cmd *cobra.Command, args []string) error {
16+
var vorpalLocation string
1517
ASCALatestVersion, _ := cmd.Flags().GetBool(commonParams.ASCALatestVersion)
1618
fileSourceFlag, _ := cmd.Flags().GetString(commonParams.SourcesFlag)
1719
ignoredFilePathFlag, _ := cmd.Flags().GetString(commonParams.IgnoredFilePathFlag)
1820
agent, _ := cmd.Flags().GetString(commonParams.AgentFlag)
21+
vorpal := viper.GetString(commonParams.VorpalCustomPathKey)
22+
if vorpal != "" {
23+
vorpalLocation = vorpal
24+
} else if location := utils.GetOptionalParam(commonParams.ASCALocationFlag); location != "" {
25+
vorpalLocation = location
26+
}
1927
var port = viper.GetInt(commonParams.ASCAPortKey)
2028
ASCAWrapper := grpcs.NewASCAGrpcWrapper(port)
2129
ASCAParams := services.AscaScanParams{
@@ -28,7 +36,7 @@ func RunScanASCACommand(jwtWrapper wrappers.JWTWrapper) func(cmd *cobra.Command,
2836
JwtWrapper: jwtWrapper,
2937
ASCAWrapper: ASCAWrapper,
3038
}
31-
scanResult, err := services.CreateASCAScanRequest(ASCAParams, wrapperParams)
39+
scanResult, err := services.CreateASCAScanRequest(ASCAParams, wrapperParams, vorpalLocation)
3240
if err != nil {
3341
return err
3442
}

internal/commands/asca/asca-engine_test.go

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,8 @@ func Test_ExecuteAscaScan(t *testing.T) {
7575
JwtWrapper: &mock.JWTMockWrapper{},
7676
ASCAWrapper: &mock.ASCAMockWrapper{},
7777
}
78-
got, err := services.CreateASCAScanRequest(ASCAParams, wrapperParams)
78+
// No CustomVorpal Location
79+
got, err := services.CreateASCAScanRequest(ASCAParams, wrapperParams, "")
7980
if (err != nil) != ttt.wantErr {
8081
t.Errorf("executeASCAScan() error = %v, wantErr %v", err, ttt.wantErr)
8182
return
@@ -140,3 +141,59 @@ func Test_runScanASCACommand(t *testing.T) {
140141
})
141142
}
142143
}
144+
145+
func Test_runScanASCAWithAscaLocationFlagCommand(t *testing.T) {
146+
tests := []struct {
147+
name string
148+
sourceFlag string
149+
engineFlag bool
150+
ascaLocation string
151+
wantErr bool
152+
want *grpcs.ScanResult
153+
wantErrMsg string
154+
}{
155+
{
156+
name: "Test with empty fileSourceFlag",
157+
sourceFlag: "",
158+
engineFlag: true,
159+
ascaLocation: "C:/Users/test/Downloads/vorpal.exe",
160+
wantErr: false,
161+
want: nil,
162+
},
163+
{
164+
name: "Test with valid fileSource Flag and ASCAUpdateVersion flag set false ",
165+
sourceFlag: "data/python-vul-file.py",
166+
engineFlag: false,
167+
ascaLocation: "C:/Users/test/Downloads/vorpal.exe",
168+
want: nil,
169+
wantErr: false,
170+
},
171+
{
172+
name: "Test with valid fileSource Flag and ASCAUpdateVersion flag set true ",
173+
sourceFlag: "data/python-vul-file.py",
174+
engineFlag: true,
175+
ascaLocation: "C:/Users/test/Downloads/vorpal.exe",
176+
want: nil,
177+
wantErr: false,
178+
},
179+
}
180+
for _, tt := range tests {
181+
ttt := tt
182+
t.Run(ttt.name, func(t *testing.T) {
183+
cmd := &cobra.Command{}
184+
cmd.Flags().String(commonParams.SourcesFlag, ttt.sourceFlag, "")
185+
cmd.Flags().Bool(commonParams.ASCALatestVersion, ttt.engineFlag, "")
186+
cmd.Flags().String(commonParams.FormatFlag, printer.FormatJSON, "")
187+
cmd.Flags().String(commonParams.ASCALocationFlag, ttt.ascaLocation, "")
188+
runFunc := RunScanASCACommand(&mock.JWTMockWrapper{})
189+
err := runFunc(cmd, []string{})
190+
if (err != nil) != ttt.wantErr {
191+
t.Errorf("RunScanASCACommand() error = %v, wantErr %v", err, ttt.wantErr)
192+
return
193+
}
194+
if ttt.wantErr && err.Error() != ttt.wantErrMsg {
195+
t.Errorf("RunScanASCACommand() error message = %v, wantErrMsg %v", err.Error(), ttt.wantErrMsg)
196+
}
197+
})
198+
}
199+
}

internal/commands/root.go

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ package commands
22

33
import (
44
"fmt"
5+
"github.com/checkmarx/ast-cli/internal/wrappers/utils"
56
"io"
67
"log"
78
"os"
@@ -106,6 +107,7 @@ func NewAstCLI(
106107
rootCmd.PersistentFlags().String(params.ConfigFilePathFlag, "", "Path to the configuration file")
107108

108109
rootCmd.PersistentFlags().Bool(params.ApikeyOverrideFlag, false, "")
110+
rootCmd.PersistentFlags().String(params.OptionalFlags, "", params.OptionalFlagUsage)
109111

110112
_ = rootCmd.PersistentFlags().MarkHidden(params.ApikeyOverrideFlag)
111113
rootCmd.PersistentFlags().String(params.LogFileFlag, "", params.LogFileUsage)
@@ -115,7 +117,8 @@ func NewAstCLI(
115117
// are passed to Cobra.
116118
rootCmd.PersistentPreRunE = func(cmd *cobra.Command, args []string) error {
117119
CheckPreferredCredentials(cmd)
118-
err := customLogConfiguration(rootCmd)
120+
err := extractOptionalFlags()
121+
err = customLogConfiguration(rootCmd)
119122
if err != nil {
120123
return err
121124
}
@@ -149,6 +152,8 @@ func NewAstCLI(
149152
_ = viper.BindPFlag(params.OriginKey, rootCmd.PersistentFlags().Lookup(params.OriginFlag))
150153
_ = viper.BindPFlag(params.IgnoreProxyKey, rootCmd.PersistentFlags().Lookup(params.IgnoreProxyFlag))
151154
_ = viper.BindPFlag(params.ConfigFilePathKey, rootCmd.PersistentFlags().Lookup(params.ConfigFilePathFlag))
155+
_ = viper.BindPFlag(params.OptionalFlagsKey, rootCmd.PersistentFlags().Lookup(params.OptionalFlags))
156+
152157
// Key here is the actual flag since it doesn't use an environment variable
153158
_ = viper.BindPFlag(params.DebugFlag, rootCmd.PersistentFlags().Lookup(params.DebugFlag))
154159
_ = viper.BindPFlag(params.InsecureFlag, rootCmd.PersistentFlags().Lookup(params.InsecureFlag))
@@ -427,3 +432,23 @@ func CheckPreferredCredentials(cmd *cobra.Command) {
427432
viper.Set(params.PreferredCredentialTypeKey, "")
428433
}
429434
}
435+
436+
func extractOptionalFlags() error {
437+
optionalFlags := strings.TrimSpace(viper.GetString(params.OptionalFlagsKey))
438+
if optionalFlags == "" {
439+
return nil
440+
}
441+
pairs := strings.Split(optionalFlags, ";")
442+
for _, pair := range pairs {
443+
pair = strings.TrimSpace(pair)
444+
if pair == "" {
445+
continue
446+
}
447+
keyVal := strings.Split(pair, "=")
448+
if len(keyVal) != params.KeyValuePairSize {
449+
return errors.New("Invalid optional flags. Optional flags should be in a KEY1=VALUE1;KEY2=VALUE2 format")
450+
}
451+
utils.SetOptionalParam(keyVal[0], keyVal[1])
452+
}
453+
return nil
454+
}

internal/commands/root_test.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,3 +309,10 @@ func TestSetLogOutputFromFlag_DirPath_Console_Success(t *testing.T) {
309309
err := setLogOutputFromFlag(params.LogFileConsoleFlag, tempDir)
310310
assert.NilError(t, err)
311311
}
312+
313+
func TestOptionalFlag(t *testing.T) {
314+
baseArgs := []string{"scan", "create", "--project-name", "MOCK", "-s", githubDummyRepo, "-b", "dummy_branch", "--optional-flags", "asca-location=/optional/path"}
315+
cmd := createASTTestCommand()
316+
err := executeTestCommand(cmd, baseArgs...)
317+
assert.NilError(t, err)
318+
}

internal/commands/scan.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -482,6 +482,9 @@ func scanASCASubCommand(jwtWrapper wrappers.JWTWrapper, featureFlagsWrapper wrap
482482
)
483483

484484
scanASCACmd.PersistentFlags().String(commonParams.IgnoredFilePathFlag, "", "Path to ignored secrets file")
485+
scanASCACmd.PersistentFlags().String(commonParams.ASCALocationFlag, "", "Path to ASCA installed location")
486+
_ = viper.BindPFlag(commonParams.VorpalCustomPathKey, scanASCACmd.PersistentFlags().Lookup(commonParams.ASCALocationFlag))
487+
485488
return scanASCACmd
486489
}
487490

internal/params/binds.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,4 +87,6 @@ var EnvVarsBinds = []struct {
8787
{CompleteMultiPartUploadPathKey, CompleteMultipartUploadPathEnv, "api/uploads/complete-multipart-upload"},
8888
{MultipartFileSizeKey, MultipartFileSizeEnv, "2"},
8989
{DisableASCALatestVersionKey, DisableASCALatestVersionEnv, ""},
90+
{VorpalCustomPathKey, VorpalPathEnv, ""},
91+
{OptionalFlagsKey, OptionalFlagsEnv, ""},
9092
}

internal/params/envs.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,4 +90,6 @@ const (
9090
CompleteMultipartUploadPathEnv = "CX_COMPLETE_MULTIPART_UPLOAD_PATH"
9191
MultipartFileSizeEnv = "MULTIPART_FILE_SIZE"
9292
DisableASCALatestVersionEnv = "DISABLE_ASCA_UPDATE"
93+
VorpalPathEnv = "CX_ASCA_PATH"
94+
OptionalFlagsEnv = "CX_OPTIONAL_FLAGS"
9395
)

internal/params/flags.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,9 +64,11 @@ const (
6464
FormatFlagUsageFormat = "Format for the output. One of %s"
6565
FilterFlag = "filter"
6666
ASCALatestVersion = "asca-latest-version"
67+
ASCALocationFlag = "asca-location"
6768
BaseURIFlag = "base-uri"
6869
ProxyFlag = "proxy"
6970
ProxyFlagUsage = "Proxy server to send communication through"
71+
OptionalFlagUsage = "Optional global flags for CLI "
7072
IgnoreProxyFlag = "ignore-proxy"
7173
IgnoreProxyFlagUsage = "Ignore proxy configuration"
7274
ProxyTypeFlag = "proxy-auth-type"
@@ -77,6 +79,7 @@ const (
7779
KerberosProxySPNFlag = "proxy-kerberos-spn"
7880
KerberosKrb5ConfFlag = "proxy-kerberos-krb5-conf"
7981
KerberosCcacheFlag = "proxy-kerberos-ccache"
82+
OptionalFlags = "optional-flags"
8083
SastFastScanFlag = "sast-fast-scan"
8184
SastLightQueriesFlag = "sast-light-queries"
8285
BranchPrimaryFlag = "branch-primary"

internal/params/keys.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,4 +89,6 @@ var (
8989
CompleteMultiPartUploadPathKey = strings.ToLower(CompleteMultipartUploadPathEnv)
9090
MultipartFileSizeKey = strings.ToLower(MultipartFileSizeEnv)
9191
DisableASCALatestVersionKey = strings.ToLower(DisableASCALatestVersionEnv)
92+
VorpalCustomPathKey = strings.ToLower(VorpalPathEnv)
93+
OptionalFlagsKey = strings.ToLower(OptionalFlagsEnv)
9294
)

internal/services/asca.go

Lines changed: 43 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,6 @@ package services
33
import (
44
"encoding/json"
55
"fmt"
6-
"net"
7-
"os"
8-
"os/exec"
9-
"path/filepath"
10-
"strings"
11-
"time"
126

137
"github.com/checkmarx/ast-cli/internal/commands/asca/ascaconfig"
148
"github.com/checkmarx/ast-cli/internal/logger"
@@ -19,7 +13,14 @@ import (
1913
"github.com/checkmarx/ast-cli/internal/wrappers/configuration"
2014
"github.com/checkmarx/ast-cli/internal/wrappers/grpcs"
2115
getport "github.com/jsumners/go-getport"
16+
"github.com/pkg/errors"
2217
"github.com/spf13/viper"
18+
"net"
19+
"os"
20+
"os/exec"
21+
"path/filepath"
22+
"strings"
23+
"time"
2324
)
2425

2526
const (
@@ -39,22 +40,53 @@ type AscaWrappersParam struct {
3940
ASCAWrapper grpcs.AscaWrapper
4041
}
4142

42-
func CreateASCAScanRequest(ascaParams AscaScanParams, wrapperParams AscaWrappersParam) (*grpcs.ScanResult, error) {
43-
err := manageASCAInstallation(ascaParams, wrapperParams)
43+
func validateVorpalDirExist(dirPath string) error {
44+
info, err := os.Stat(dirPath)
4445
if err != nil {
45-
return nil, err
46+
if os.IsNotExist(err) {
47+
return errors.Errorf("%s path does not exist", dirPath)
48+
}
49+
if errors.Is(err, os.ErrPermission) {
50+
return errors.Errorf("permission denied while accessing path %s", dirPath)
51+
}
52+
return errors.Errorf("cannot access path %s: %v", dirPath, err)
53+
}
54+
if !info.IsDir() {
55+
return errors.Errorf("provided path is not a directory %s", dirPath)
4656
}
57+
return nil
58+
}
59+
60+
func ValidateCustomASCAInstallation(vorpalLocation string) error {
61+
if err := validateVorpalDirExist(vorpalLocation); err != nil {
62+
return errors.Wrap(err, "Failed to validate ASCA location")
63+
}
64+
ascaconfig.Params.SetVorpalCustomPath(vorpalLocation)
65+
ASCAInstalled, _ := osinstaller.FileExists(ascaconfig.Params.ExecutableFilePath())
66+
if !ASCAInstalled {
67+
return errors.Errorf("No ASCA executable found in provided location: %s", vorpalLocation)
68+
}
69+
return nil
70+
}
4771

72+
func CreateASCAScanRequest(ascaParams AscaScanParams, wrapperParams AscaWrappersParam, vorpalLocation string) (*grpcs.ScanResult, error) {
73+
var err error
74+
if vorpalLocation == "" {
75+
err = manageASCAInstallation(ascaParams, wrapperParams)
76+
if err != nil {
77+
return nil, err
78+
}
79+
} else if err = ValidateCustomASCAInstallation(vorpalLocation); err != nil {
80+
return nil, err
81+
}
4882
err = ensureASCAServiceRunning(wrapperParams, ascaParams)
4983
if err != nil {
5084
return nil, err
5185
}
52-
5386
emptyResults := validateFilePath(ascaParams.FilePath)
5487
if emptyResults != nil {
5588
return emptyResults, nil
5689
}
57-
5890
ignoredResults := validateIgnoredFilePath(ascaParams.IgnoredFilePath)
5991
if ignoredResults != nil {
6092
return ignoredResults, nil
@@ -266,7 +298,6 @@ func RunASCAEngine(port int) error {
266298
if err != nil {
267299
return err
268300
}
269-
270301
ready := waitForServer(fmt.Sprintf("localhost:%d", port), dialTimeout)
271302
if !ready {
272303
return fmt.Errorf("server did not become ready in time")

0 commit comments

Comments
 (0)