Skip to content

Commit fb04524

Browse files
code changes for engines feature
1 parent 0f89a04 commit fb04524

File tree

12 files changed

+505
-7
lines changed

12 files changed

+505
-7
lines changed

cmd/main.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@ func main() {
9191
accessManagementWrapper := wrappers.NewAccessManagementHTTPWrapper(accessManagementPath)
9292
byorWrapper := wrappers.NewByorHTTPWrapper(byorPath)
9393
containerResolverWrapper := wrappers.NewContainerResolverWrapper()
94+
enginesWrapper := wrappers.NewHTTPEnginesWrapper()
9495

9596
astCli := commands.NewAstCLI(
9697
applicationsWrapper,
@@ -127,6 +128,7 @@ func main() {
127128
accessManagementWrapper,
128129
byorWrapper,
129130
containerResolverWrapper,
131+
enginesWrapper,
130132
)
131133
exitListener()
132134
err = astCli.Execute()

internal/commands/engines.go

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
package commands
2+
3+
import (
4+
"github.com/MakeNowJust/heredoc"
5+
"github.com/checkmarx/ast-cli/internal/commands/util/printer"
6+
"github.com/checkmarx/ast-cli/internal/params"
7+
"github.com/checkmarx/ast-cli/internal/services"
8+
"github.com/checkmarx/ast-cli/internal/wrappers"
9+
"github.com/pkg/errors"
10+
"github.com/spf13/cobra"
11+
)
12+
13+
func NewEnginesCommand(
14+
enginesWrapper wrappers.EnginesWrapper,
15+
) *cobra.Command {
16+
enginesCmd := &cobra.Command{
17+
Use: "engines",
18+
Short: "Fetch supported API of scanner engines",
19+
Long: "The engines command enables the ability to fetch engines APIs list in Checkmarx One.",
20+
Annotations: map[string]string{
21+
"command:doc": heredoc.Doc(
22+
`
23+
https://checkmarx.com/resource/documents/en/34965-68643-scan.html
24+
`,
25+
),
26+
},
27+
}
28+
listEngineAPIcmd := enginesListAPISubCommand(enginesWrapper)
29+
enginesCmd.AddCommand(listEngineAPIcmd)
30+
return enginesCmd
31+
}
32+
33+
func enginesListAPISubCommand(
34+
enginesWrapper wrappers.EnginesWrapper,
35+
) *cobra.Command {
36+
enginesListAPIcmd := &cobra.Command{
37+
Use: "list-api",
38+
Short: "fetch the API list of scanner engines",
39+
Long: "The create list-api fetch the API list of scanner engines in Checkmarx One.",
40+
Example: heredoc.Doc(
41+
`
42+
$ cx engines list-api --engine-name <Engine Name>
43+
`,
44+
),
45+
Annotations: map[string]string{
46+
"command:doc": heredoc.Doc(
47+
`
48+
https://checkmarx.com/resource/documents/en/34965-68643-scan.html#UUID-a0bb20d5-5182-3fb4-3da0-0e263344ffe7
49+
`,
50+
),
51+
},
52+
RunE: runEnginesListAPICommand(enginesWrapper),
53+
}
54+
enginesListAPIcmd.PersistentFlags().String("engine-name", "", "The name of the Checkmarx scanner engine to use.")
55+
56+
addOutputFormatFlag(
57+
enginesListAPIcmd,
58+
printer.FormatTable,
59+
printer.FormatJSON,
60+
printer.FormatYAML,
61+
)
62+
return enginesListAPIcmd
63+
}
64+
65+
func runEnginesListAPICommand(enginesWrapper wrappers.EnginesWrapper) func(cmd *cobra.Command, args []string) error {
66+
//fmt.Println("Inside the command execution runEnginesListAPICommand function")
67+
return func(cmd *cobra.Command, args []string) error {
68+
var apiModels []wrappers.ApiModel
69+
var errorModel *wrappers.ErrorModel
70+
//fmt.Println("Before flag")
71+
engineName, err := cmd.Flags().GetString("engine-name")
72+
if err != nil {
73+
return errors.Wrapf(err, "%s", "Invalid 'engine-name' flag")
74+
}
75+
apiModels, errorModel, err = enginesWrapper.GetAllAPIs(engineName)
76+
if err != nil {
77+
return errors.Wrapf(err, "%s\n", "Failed to fetch all engines APIs")
78+
}
79+
80+
//fmt.Println(apiModels)
81+
// Checking the response
82+
if errorModel != nil {
83+
return errors.Errorf(services.ErrorCodeFormat, "Failed to Getting All apis in error model", errorModel.Code, errorModel.Message)
84+
} else if apiModels != nil && len(apiModels) > 0 {
85+
f1, _ := cmd.Flags().GetString(params.OutputFormatFlag)
86+
if f1 == "table" {
87+
views := toAPIsViews(apiModels)
88+
if err != nil {
89+
return err
90+
}
91+
err = printByOutputFormat(cmd, views)
92+
if err != nil {
93+
return err
94+
}
95+
} else {
96+
views := toEnginesView(apiModels)
97+
if err != nil {
98+
return err
99+
}
100+
err = printByOutputFormat(cmd, views)
101+
if err != nil {
102+
return err
103+
}
104+
}
105+
}
106+
return nil
107+
}
108+
109+
}
110+
111+
type Engine struct {
112+
EngineID string `json:"engine_id"`
113+
EngineName string `json:"engine_name"`
114+
APIs []API `json:"apis"`
115+
}
116+
117+
type API struct {
118+
ApiUrl string `json:"api_url"`
119+
ApiName string `json:"api_name"`
120+
Description string `json:"description"`
121+
}
122+
123+
type EnginesView struct {
124+
Engines []Engine `json:"engines"`
125+
}
126+
127+
func toEnginesView(models []wrappers.ApiModel) EnginesView {
128+
engineMap := make(map[string]Engine)
129+
130+
// Group APIs by engine
131+
for _, model := range models {
132+
api := API{
133+
ApiUrl: model.ApiUrl,
134+
ApiName: model.ApiName,
135+
Description: model.Description,
136+
}
137+
138+
engine, exists := engineMap[model.EngineId]
139+
if !exists {
140+
engine = Engine{
141+
EngineID: model.EngineId,
142+
EngineName: model.EngineName,
143+
APIs: []API{},
144+
}
145+
}
146+
engine.APIs = append(engine.APIs, api)
147+
engineMap[model.EngineId] = engine
148+
}
149+
150+
// Collect all engines
151+
var engines []Engine
152+
for _, engine := range engineMap {
153+
engines = append(engines, engine)
154+
}
155+
156+
return EnginesView{
157+
Engines: engines,
158+
}
159+
}
160+
161+
func toAPIsViews(models []wrappers.ApiModel) []apiView {
162+
result := make([]apiView, len(models))
163+
for i := 0; i < len(models); i++ {
164+
result[i] = toAPIView(models[i])
165+
}
166+
return result
167+
}
168+
func toAPIView(model wrappers.ApiModel) apiView {
169+
return apiView{
170+
ApiName: model.ApiName,
171+
Description: model.Description,
172+
ApiUrl: model.ApiUrl,
173+
EngineName: model.EngineName,
174+
EngineId: model.EngineId,
175+
}
176+
}
177+
178+
type apiView struct {
179+
ApiName string
180+
Description string
181+
ApiUrl string
182+
EngineName string
183+
EngineId string
184+
}

internal/commands/engines_test.go

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
package commands
2+
3+
import (
4+
"github.com/checkmarx/ast-cli/internal/wrappers/mock"
5+
"gotest.tools/assert"
6+
"testing"
7+
)
8+
9+
func TestNewEnginesCommand(t *testing.T) {
10+
11+
cmd := NewEnginesCommand(&mock.NewHTTPEnginesMockWrapper{})
12+
err := executeTestCommand(cmd, "")
13+
assert.NilError(t, err)
14+
}
15+
16+
func TestNewEnginesCommandHelp(t *testing.T) {
17+
18+
cmd := NewEnginesCommand(&mock.NewHTTPEnginesMockWrapper{})
19+
err := executeTestCommand(cmd, "help")
20+
assert.NilError(t, err)
21+
}
22+
23+
func TestNewEnginesSubCommand(t *testing.T) {
24+
25+
cmd := NewEnginesCommand(&mock.NewHTTPEnginesMockWrapper{})
26+
err := executeTestCommand(cmd, "list-api")
27+
assert.NilError(t, err)
28+
}
29+
30+
func TestNewEnginesSubCommandHelp(t *testing.T) {
31+
32+
cmd := NewEnginesCommand(&mock.NewHTTPEnginesMockWrapper{})
33+
err := executeTestCommand(cmd, "list-api", "--help")
34+
assert.NilError(t, err)
35+
}
36+
37+
func TestSubCommandEngineType1(t *testing.T) {
38+
39+
cmd := NewEnginesCommand(&mock.NewHTTPEnginesMockWrapper{})
40+
err := executeTestCommand(cmd, "list-api", "--engine-name", "SAST")
41+
assert.NilError(t, err)
42+
}
43+
44+
func TestSubCommandEngineType2(t *testing.T) {
45+
46+
cmd := NewEnginesCommand(&mock.NewHTTPEnginesMockWrapper{})
47+
err := executeTestCommand(cmd, "list-api", "--engine-name", "SCA")
48+
assert.NilError(t, err)
49+
}
50+
51+
func TestSubCommandEngineType3(t *testing.T) {
52+
53+
cmd := NewEnginesCommand(&mock.NewHTTPEnginesMockWrapper{})
54+
err := executeTestCommand(cmd, "list-api", "--engine-name", "Iac")
55+
assert.NilError(t, err)
56+
}
57+
58+
func TestSubCommandOutPutFormat1(t *testing.T) {
59+
60+
cmd := NewEnginesCommand(&mock.NewHTTPEnginesMockWrapper{})
61+
err := executeTestCommand(cmd, "list-api", "--output-format", "json")
62+
assert.NilError(t, err)
63+
}
64+
65+
func TestSubCommandOutPutFormat2(t *testing.T) {
66+
67+
cmd := NewEnginesCommand(&mock.NewHTTPEnginesMockWrapper{})
68+
err := executeTestCommand(cmd, "list-api", "--output-format", "yaml")
69+
assert.NilError(t, err)
70+
}
71+
72+
func TestSubCommandOutPutFormat3(t *testing.T) {
73+
74+
cmd := NewEnginesCommand(&mock.NewHTTPEnginesMockWrapper{})
75+
err := executeTestCommand(cmd, "list-api", "--output-format", "table")
76+
assert.NilError(t, err)
77+
}
78+
79+
func TestSubCommandEngineError1(t *testing.T) {
80+
81+
cmd := NewEnginesCommand(&mock.NewHTTPEnginesMockWrapper{})
82+
err := executeTestCommand(cmd, "list-api", "--chibute", "SAST")
83+
assert.Assert(t, err != nil)
84+
}
85+
86+
func TestSubCommandEngineError2(t *testing.T) {
87+
88+
cmd := NewEnginesCommand(&mock.NewHTTPEnginesMockWrapper{})
89+
err := executeTestCommand(cmd, "list-api", "--engine-name", "SASTS")
90+
assert.NilError(t, err)
91+
}
92+
93+
func TestSubCommandEngineError3(t *testing.T) {
94+
95+
cmd := NewEnginesCommand(&mock.NewHTTPEnginesMockWrapper{})
96+
err := executeTestCommand(cmd, "list-api", "--output-format", "jsonsa")
97+
assert.Assert(t, err != nil)
98+
}

internal/commands/root.go

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import (
1919
"github.com/spf13/viper"
2020
)
2121

22-
// NewAstCLI Return a Checkmarx One CLI root command to execute
2322
func NewAstCLI(
2423
applicationsWrapper wrappers.ApplicationsWrapper,
2524
scansWrapper wrappers.ScansWrapper,
@@ -55,8 +54,9 @@ func NewAstCLI(
5554
accessManagementWrapper wrappers.AccessManagementWrapper,
5655
byorWrapper wrappers.ByorWrapper,
5756
containerResolverWrapper wrappers.ContainerResolverWrapper,
57+
enginesWrapper wrappers.EnginesWrapper,
5858
) *cobra.Command {
59-
// Create the root
59+
6060
rootCmd := &cobra.Command{
6161
Use: "cx <command> <subcommand> [flags]",
6262
Short: "Checkmarx One CLI",
@@ -77,7 +77,6 @@ func NewAstCLI(
7777
},
7878
}
7979

80-
// Load default flags
8180
rootCmd.PersistentFlags().Bool(params.DebugFlag, false, params.DebugUsage)
8281
rootCmd.PersistentFlags().String(params.AccessKeyIDFlag, "", params.AccessKeyIDFlagUsage)
8382
rootCmd.PersistentFlags().String(params.AccessKeySecretFlag, "", params.AccessKeySecretFlagUsage)
@@ -99,8 +98,6 @@ func NewAstCLI(
9998

10099
_ = rootCmd.PersistentFlags().MarkHidden(params.ApikeyOverrideFlag)
101100

102-
// This monitors and traps situations where "extra/garbage" commands
103-
// are passed to Cobra.
104101
rootCmd.PersistentPreRun = func(cmd *cobra.Command, args []string) {
105102
PrintConfiguration()
106103
// Need to check the __complete command to allow correct behavior of the autocomplete
@@ -109,7 +106,7 @@ func NewAstCLI(
109106
os.Exit(0)
110107
}
111108
}
112-
// Link the environment variable to the CLI argument(s).
109+
113110
_ = viper.BindPFlag(params.AccessKeyIDConfigKey, rootCmd.PersistentFlags().Lookup(params.AccessKeyIDFlag))
114111
_ = viper.BindPFlag(params.AccessKeySecretConfigKey, rootCmd.PersistentFlags().Lookup(params.AccessKeySecretFlag))
115112
_ = viper.BindPFlag(params.BaseURIKey, rootCmd.PersistentFlags().Lookup(params.BaseURIFlag))
@@ -203,6 +200,8 @@ func NewAstCLI(
203200
chatCmd := NewChatCommand(chatWrapper, tenantWrapper)
204201
hooksCmd := NewHooksCommand(jwtWrapper)
205202

203+
enginesCmd := NewEnginesCommand(enginesWrapper)
204+
206205
rootCmd.AddCommand(
207206
scanCmd,
208207
projectCmd,
@@ -214,6 +213,7 @@ func NewAstCLI(
214213
configCmd,
215214
chatCmd,
216215
hooksCmd,
216+
enginesCmd,
217217
)
218218

219219
rootCmd.SilenceUsage = true
@@ -257,7 +257,7 @@ func getFilters(cmd *cobra.Command) (map[string]string, error) {
257257
}
258258

259259
func validateExtraFilters(filterKeyVal []string) []string {
260-
// Add support for state = exclude-not-exploitable, will replace all values of filter flag state to "TO_VERIFY;PROPOSED_NOT_EXPLOITABLE;CONFIRMED;URGENT"
260+
261261
if extraFilter[filterKeyVal[0]] != nil {
262262
for privateFilter, value := range extraFilter[filterKeyVal[0]] {
263263
if strings.Contains(filterKeyVal[1], privateFilter) {
@@ -296,6 +296,13 @@ func addResultFormatFlag(cmd *cobra.Command, defaultFormat string, otherAvailabl
296296
)
297297
}
298298

299+
func addOutputFormatFlag(cmd *cobra.Command, defaultFormat string, otherAvailableFormats ...string) {
300+
cmd.PersistentFlags().String(
301+
params.OutputFormatFlag, defaultFormat,
302+
fmt.Sprintf(params.FormatFlagUsageFormat, append(otherAvailableFormats, defaultFormat)),
303+
)
304+
}
305+
299306
func markFlagAsRequired(cmd *cobra.Command, flag string) {
300307
err := cmd.MarkPersistentFlagRequired(flag)
301308
if err != nil {
@@ -319,6 +326,12 @@ func printByFormat(cmd *cobra.Command, view interface{}) error {
319326
f, _ := cmd.Flags().GetString(params.FormatFlag)
320327
return printer.Print(cmd.OutOrStdout(), view, f)
321328
}
329+
330+
func printByOutputFormat(cmd *cobra.Command, view interface{}) error {
331+
f, _ := cmd.Flags().GetString(params.OutputFormatFlag)
332+
return printer.Print(cmd.OutOrStdout(), view, f)
333+
}
334+
322335
func printByScanInfoFormat(cmd *cobra.Command, view interface{}) error {
323336
f, _ := cmd.Flags().GetString(params.ScanInfoFormatFlag)
324337
return printer.Print(cmd.OutOrStdout(), view, f)

0 commit comments

Comments
 (0)