Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ func main() {
accessManagementWrapper := wrappers.NewAccessManagementHTTPWrapper(accessManagementPath)
byorWrapper := wrappers.NewByorHTTPWrapper(byorPath)
containerResolverWrapper := wrappers.NewContainerResolverWrapper()
enginesWrapper := wrappers.NewHTTPEnginesWrapper()

astCli := commands.NewAstCLI(
applicationsWrapper,
Expand Down Expand Up @@ -127,6 +128,7 @@ func main() {
accessManagementWrapper,
byorWrapper,
containerResolverWrapper,
enginesWrapper,
)
exitListener()
err = astCli.Execute()
Expand Down
184 changes: 184 additions & 0 deletions internal/commands/engines.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
package commands

import (
"github.com/MakeNowJust/heredoc"
"github.com/checkmarx/ast-cli/internal/commands/util/printer"
"github.com/checkmarx/ast-cli/internal/params"
"github.com/checkmarx/ast-cli/internal/services"
"github.com/checkmarx/ast-cli/internal/wrappers"
"github.com/pkg/errors"
"github.com/spf13/cobra"
)

func NewEnginesCommand(
enginesWrapper wrappers.EnginesWrapper,
) *cobra.Command {
enginesCmd := &cobra.Command{
Use: "engines",
Short: "Fetch supported API of scanner engines",
Long: "The engines command enables the ability to fetch engines APIs list in Checkmarx One.",
Annotations: map[string]string{
"command:doc": heredoc.Doc(
`
https://checkmarx.com/resource/documents/en/34965-68643-scan.html
`,
),
},
}
listEngineAPIcmd := enginesListAPISubCommand(enginesWrapper)
enginesCmd.AddCommand(listEngineAPIcmd)
return enginesCmd
}

func enginesListAPISubCommand(
enginesWrapper wrappers.EnginesWrapper,
) *cobra.Command {
enginesListAPIcmd := &cobra.Command{
Use: "list-api",
Short: "fetch the API list of scanner engines",
Long: "The create list-api fetch the API list of scanner engines in Checkmarx One.",
Example: heredoc.Doc(
`
$ cx engines list-api --engine-name <Engine Name>
`,
),
Annotations: map[string]string{
"command:doc": heredoc.Doc(
`
https://checkmarx.com/resource/documents/en/34965-68643-scan.html#UUID-a0bb20d5-5182-3fb4-3da0-0e263344ffe7
`,
),
},
RunE: runEnginesListAPICommand(enginesWrapper),
}
enginesListAPIcmd.PersistentFlags().String("engine-name", "", "The name of the Checkmarx scanner engine to use.")

addOutputFormatFlag(
enginesListAPIcmd,
printer.FormatTable,
printer.FormatJSON,
printer.FormatYAML,
)
return enginesListAPIcmd
}

func runEnginesListAPICommand(enginesWrapper wrappers.EnginesWrapper) func(cmd *cobra.Command, args []string) error {
//fmt.Println("Inside the command execution runEnginesListAPICommand function")
return func(cmd *cobra.Command, args []string) error {
var apiModels []wrappers.ApiModel
var errorModel *wrappers.ErrorModel
//fmt.Println("Before flag")
engineName, err := cmd.Flags().GetString("engine-name")
if err != nil {
return errors.Wrapf(err, "%s", "Invalid 'engine-name' flag")
}
apiModels, errorModel, err = enginesWrapper.GetAllAPIs(engineName)
if err != nil {
return errors.Wrapf(err, "%s\n", "Failed to fetch all engines APIs")
}

//fmt.Println(apiModels)
// Checking the response
if errorModel != nil {
return errors.Errorf(services.ErrorCodeFormat, "Failed to Getting All apis in error model", errorModel.Code, errorModel.Message)
} else if apiModels != nil && len(apiModels) > 0 {
f1, _ := cmd.Flags().GetString(params.OutputFormatFlag)
if f1 == "table" {
views := toAPIsViews(apiModels)
if err != nil {
return err
}
err = printByOutputFormat(cmd, views)
if err != nil {
return err
}
} else {
views := toEnginesView(apiModels)
if err != nil {
return err
}
err = printByOutputFormat(cmd, views)
if err != nil {
return err
}
}
}
return nil
}

}

type Engine struct {
EngineID string `json:"engine_id"`
EngineName string `json:"engine_name"`
APIs []API `json:"apis"`
}

type API struct {
ApiUrl string `json:"api_url"`
ApiName string `json:"api_name"`
Description string `json:"description"`
}

type EnginesView struct {
Engines []Engine `json:"engines"`
}

func toEnginesView(models []wrappers.ApiModel) EnginesView {
engineMap := make(map[string]Engine)

// Group APIs by engine
for _, model := range models {
api := API{
ApiUrl: model.ApiUrl,
ApiName: model.ApiName,
Description: model.Description,
}

engine, exists := engineMap[model.EngineId]
if !exists {
engine = Engine{
EngineID: model.EngineId,
EngineName: model.EngineName,
APIs: []API{},
}
}
engine.APIs = append(engine.APIs, api)
engineMap[model.EngineId] = engine
}

// Collect all engines
var engines []Engine
for _, engine := range engineMap {
engines = append(engines, engine)
}

return EnginesView{
Engines: engines,
}
}

func toAPIsViews(models []wrappers.ApiModel) []apiView {
result := make([]apiView, len(models))
for i := 0; i < len(models); i++ {
result[i] = toAPIView(models[i])
}
return result
}
func toAPIView(model wrappers.ApiModel) apiView {
return apiView{
ApiName: model.ApiName,
Description: model.Description,
ApiUrl: model.ApiUrl,
EngineName: model.EngineName,
EngineId: model.EngineId,
}
}

type apiView struct {
ApiName string
Description string
ApiUrl string
EngineName string
EngineId string
}
98 changes: 98 additions & 0 deletions internal/commands/engines_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package commands

import (
"github.com/checkmarx/ast-cli/internal/wrappers/mock"
"gotest.tools/assert"
"testing"
)

func TestNewEnginesCommand(t *testing.T) {

cmd := NewEnginesCommand(&mock.NewHTTPEnginesMockWrapper{})
err := executeTestCommand(cmd, "")
assert.NilError(t, err)
}

func TestNewEnginesCommandHelp(t *testing.T) {

cmd := NewEnginesCommand(&mock.NewHTTPEnginesMockWrapper{})
err := executeTestCommand(cmd, "help")
assert.NilError(t, err)
}

func TestNewEnginesSubCommand(t *testing.T) {

cmd := NewEnginesCommand(&mock.NewHTTPEnginesMockWrapper{})
err := executeTestCommand(cmd, "list-api")
assert.NilError(t, err)
}

func TestNewEnginesSubCommandHelp(t *testing.T) {

cmd := NewEnginesCommand(&mock.NewHTTPEnginesMockWrapper{})
err := executeTestCommand(cmd, "list-api", "--help")
assert.NilError(t, err)
}

func TestSubCommandEngineType1(t *testing.T) {

cmd := NewEnginesCommand(&mock.NewHTTPEnginesMockWrapper{})
err := executeTestCommand(cmd, "list-api", "--engine-name", "SAST")
assert.NilError(t, err)
}

func TestSubCommandEngineType2(t *testing.T) {

cmd := NewEnginesCommand(&mock.NewHTTPEnginesMockWrapper{})
err := executeTestCommand(cmd, "list-api", "--engine-name", "SCA")
assert.NilError(t, err)
}

func TestSubCommandEngineType3(t *testing.T) {

cmd := NewEnginesCommand(&mock.NewHTTPEnginesMockWrapper{})
err := executeTestCommand(cmd, "list-api", "--engine-name", "Iac")
assert.NilError(t, err)
}

func TestSubCommandOutPutFormat1(t *testing.T) {

cmd := NewEnginesCommand(&mock.NewHTTPEnginesMockWrapper{})
err := executeTestCommand(cmd, "list-api", "--output-format", "json")
assert.NilError(t, err)
}

func TestSubCommandOutPutFormat2(t *testing.T) {

cmd := NewEnginesCommand(&mock.NewHTTPEnginesMockWrapper{})
err := executeTestCommand(cmd, "list-api", "--output-format", "yaml")
assert.NilError(t, err)
}

func TestSubCommandOutPutFormat3(t *testing.T) {

cmd := NewEnginesCommand(&mock.NewHTTPEnginesMockWrapper{})
err := executeTestCommand(cmd, "list-api", "--output-format", "table")
assert.NilError(t, err)
}

func TestSubCommandEngineError1(t *testing.T) {

cmd := NewEnginesCommand(&mock.NewHTTPEnginesMockWrapper{})
err := executeTestCommand(cmd, "list-api", "--chibute", "SAST")
assert.Assert(t, err != nil)
}

func TestSubCommandEngineError2(t *testing.T) {

cmd := NewEnginesCommand(&mock.NewHTTPEnginesMockWrapper{})
err := executeTestCommand(cmd, "list-api", "--engine-name", "SASTS")
assert.NilError(t, err)
}

func TestSubCommandEngineError3(t *testing.T) {

cmd := NewEnginesCommand(&mock.NewHTTPEnginesMockWrapper{})
err := executeTestCommand(cmd, "list-api", "--output-format", "jsonsa")
assert.Assert(t, err != nil)
}
17 changes: 17 additions & 0 deletions internal/commands/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ func NewAstCLI(
accessManagementWrapper wrappers.AccessManagementWrapper,
byorWrapper wrappers.ByorWrapper,
containerResolverWrapper wrappers.ContainerResolverWrapper,
enginesWrapper wrappers.EnginesWrapper,
) *cobra.Command {
// Create the root
rootCmd := &cobra.Command{
Expand Down Expand Up @@ -203,6 +204,8 @@ func NewAstCLI(
chatCmd := NewChatCommand(chatWrapper, tenantWrapper)
hooksCmd := NewHooksCommand(jwtWrapper)

enginesCmd := NewEnginesCommand(enginesWrapper)

rootCmd.AddCommand(
scanCmd,
projectCmd,
Expand All @@ -214,6 +217,7 @@ func NewAstCLI(
configCmd,
chatCmd,
hooksCmd,
enginesCmd,
)

rootCmd.SilenceUsage = true
Expand Down Expand Up @@ -296,6 +300,13 @@ func addResultFormatFlag(cmd *cobra.Command, defaultFormat string, otherAvailabl
)
}

func addOutputFormatFlag(cmd *cobra.Command, defaultFormat string, otherAvailableFormats ...string) {
cmd.PersistentFlags().String(
params.OutputFormatFlag, defaultFormat,
fmt.Sprintf(params.FormatFlagUsageFormat, append(otherAvailableFormats, defaultFormat)),
)
}

func markFlagAsRequired(cmd *cobra.Command, flag string) {
err := cmd.MarkPersistentFlagRequired(flag)
if err != nil {
Expand All @@ -319,6 +330,12 @@ func printByFormat(cmd *cobra.Command, view interface{}) error {
f, _ := cmd.Flags().GetString(params.FormatFlag)
return printer.Print(cmd.OutOrStdout(), view, f)
}

func printByOutputFormat(cmd *cobra.Command, view interface{}) error {
f, _ := cmd.Flags().GetString(params.OutputFormatFlag)
return printer.Print(cmd.OutOrStdout(), view, f)
}

func printByScanInfoFormat(cmd *cobra.Command, view interface{}) error {
f, _ := cmd.Flags().GetString(params.ScanInfoFormatFlag)
return printer.Print(cmd.OutOrStdout(), view, f)
Expand Down
2 changes: 2 additions & 0 deletions internal/commands/root_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ func createASTTestCommand() *cobra.Command {
byorWrapper := &mock.ByorMockWrapper{}
containerResolverMockWrapper := &mock.ContainerResolverMockWrapper{}
customStatesMockWrapper := &mock.CustomStatesMockWrapper{}
newHTTPEnginesMockWrapper := &mock.NewHTTPEnginesMockWrapper{}
return NewAstCLI(
applicationWrapper,
scansMockWrapper,
Expand Down Expand Up @@ -103,6 +104,7 @@ func createASTTestCommand() *cobra.Command {
accessManagementWrapper,
byorWrapper,
containerResolverMockWrapper,
newHTTPEnginesMockWrapper,
)
}

Expand Down
8 changes: 8 additions & 0 deletions internal/commands/util/printer/printer.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package printer
import (
"encoding/json"
"fmt"
yaml "gopkg.in/yaml.v3"
"io"
"reflect"
"strconv"
Expand Down Expand Up @@ -30,6 +31,7 @@ const (
FormatXML = "xml"
FormatGLSast = "gl-sast"
FormatGLSca = "gl-sca"
FormatYAML = "yaml"
)

func Print(w io.Writer, view interface{}, format string) error {
Expand All @@ -51,6 +53,12 @@ func Print(w io.Writer, view interface{}, format string) error {
} else if IsFormat(format, FormatTable) {
entities := toEntities(view)
printTable(w, entities)
} else if IsFormat(format, FormatYAML) {
viewYaml, err := yaml.Marshal(view)
if err != nil {
return err
}
_, _ = fmt.Fprintln(w, string(viewYaml))
} else {
return errors.Errorf("Invalid format %s", format)
}
Expand Down
Loading
Loading