Skip to content

Commit

Permalink
Feature/ast 11602 cli add ssh key scan create (#387)
Browse files Browse the repository at this point in the history
* AST-11602 - CLI | Add SSH key to scan create command

- Added --ssh-key flag to scan create
- Added unit tests and integration tests
- Code refactoring

* AST-11602 - CLI | Add SSH key to scan create command

- Added missing private key in integration tests

* AST-11602 - CLI | Add SSH key to scan create command

- Fixed unit tests

* AST-11602 - CLI | Add SSH key to scan create command

- Added --ssh-key flag to scan create
- Added unit tests and integration tests
- Code refactoring

* AST-11602 - CLI | Add SSH key to scan create command

- Added missing private key in integration tests

* AST-11602 - CLI | Add SSH key to scan create command

- Fixed unit tests

* AST-11602 - CLI | Add SSH key to scan create command

- Fixed unit tests and lint

* AST-11602 - CLI | Add SSH key to scan create command

- Fixed unit tests

* AST-11602 - CLI | Add SSH key to scan create command

- Added debug flag to check error in cicd

* AST-11602 - CLI | Add SSH key to scan create command

- print error cicd

* AST-11602 - CLI | Add SSH key to scan create command

- Fixed ssh test to create temp file to read ssh key

* AST-11602 - CLI | Add SSH key to scan create command

- Fix cicd integration tests

* AST-11602 - CLI | Add SSH key to scan create command

- Remove helping printed messages

* AST-11603 - CLI | Add SSH key to project create command

- Add --ssh-key flag to project create and update project configuration with the ssh-key after project create

- Unit tests and integration tests added

* AST-11603 - CLI | Add SSH key to project create command

- Fixed lint errors

* AST-11621 - CLI | Handle file filters when source is zip file

- Added logs to check tests in CICD

* AST-11621 - CLI | Handle file filters when source is zip file

- Added logs to check tests in CICD

* AST-11602 - CLI | Add SSH key to scan create command

- Removed private keys from project;
- defer remove file

* AST-11603 - CLI | Add SSH key to project create command

- added repository url to create project command;

* AST-11603 - CLI | Add SSH key to project create command

- added unit tests and integration tests for project creation with ssh key

* AST-11603 - CLI | Add SSH key to project create command

- Fix lint errors

* AST-11603 - CLI | Add SSH key to project create command

- Fix lint errors

* AST-11603 - CLI | Add SSH key to project create command

- Fix unit tests

* AST-11603 - CLI | Add SSH key to project create command

- Fixed integration tests

* AST-11603 - CLI | Add SSH key to project create command

- Clarify it is a private key required
  • Loading branch information
hmmachadocx authored Apr 28, 2022
1 parent 01c4ae5 commit 0077efe
Show file tree
Hide file tree
Showing 16 changed files with 523 additions and 152 deletions.
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ jobs:
CX_AST_PASSWORD: ${{ secrets.CX_AST_PASSWORD }}
CX_APIKEY: ${{ secrets.CX_APIKEY }}
CX_TENANT: ${{ secrets.CX_TENANT }}
CX_SCAN_SSH_KEY: ${{ secrets.CX_SCAN_SSH_KEY }}
PERSONAL_ACCESS_TOKEN: ${{ secrets.PERSONAL_ACCESS_TOKEN }}
PROXY_HOST: localhost
PROXY_PORT: 3128
Expand Down
111 changes: 110 additions & 1 deletion internal/commands/project.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"time"

"github.com/MakeNowJust/heredoc"
"github.com/checkmarx/ast-cli/internal/commands/util"
"github.com/checkmarx/ast-cli/internal/commands/util/printer"

commonParams "github.com/checkmarx/ast-cli/internal/params"
Expand All @@ -23,6 +24,11 @@ const (
failedDeletingProj = "Failed deleting a project"
failedGettingBranches = "Failed getting branches for project"
failedFindingGroup = "Failed finding groups"
projOriginLevel = "Project"
repoConfKey = "scan.handler.git.repository"
sshConfKey = "scan.handler.git.sshKey"
mandatoryRepoURLError = "flag --repo-url is mandatory when --ssh-key is provided"
invalidRepoURL = "provided repository url doesn't need a key. Make sure you are defining the right repository or remove the flag --ssh-key"
)

var (
Expand Down Expand Up @@ -88,6 +94,8 @@ func NewProjectCommand(projectsWrapper wrappers.ProjectsWrapper, groupsWrapper w
createProjCmd.PersistentFlags().String(commonParams.GroupList, "", "List of groups, ex: (PowerUsers,etc)")
createProjCmd.PersistentFlags().StringP(commonParams.ProjectName, "", "", "Name of project")
createProjCmd.PersistentFlags().StringP(commonParams.MainBranchFlag, "", "", "Main branch")
createProjCmd.PersistentFlags().String(commonParams.SSHKeyFlag, "", "Path to ssh private key")
createProjCmd.PersistentFlags().String(commonParams.RepoURLFlag, "", "Repository URL")

listProjectsCmd := &cobra.Command{
Use: "list",
Expand Down Expand Up @@ -283,7 +291,11 @@ func runCreateProjectCommand(
if err != nil {
return err
}
updateTagValues(&input, cmd)
setupScanTags(&input, cmd)
err = validateConfiguration(cmd)
if err != nil {
return err
}
var projModel = wrappers.Project{}
var projResponseModel *wrappers.ProjectResponseModel
var errorModel *wrappers.ErrorModel
Expand All @@ -299,6 +311,7 @@ func runCreateProjectCommand(
if err != nil {
return errors.Wrapf(err, "%s", failedCreatingProj)
}

// Checking the response
if errorModel != nil {
return errors.Errorf(ErrorCodeFormat, failedCreatingProj, errorModel.Code, errorModel.Message)
Expand All @@ -308,10 +321,106 @@ func runCreateProjectCommand(
return errors.Wrapf(err, "%s", failedCreatingProj)
}
}

err = updateProjectConfigurationIfNeeded(cmd, projectsWrapper, projResponseModel.ID)
if err != nil {
return err
}

return nil
}
}

func updateProjectConfigurationIfNeeded(cmd *cobra.Command, projectsWrapper wrappers.ProjectsWrapper, projectID string) error {
// Just update project configuration id a repository url is defined
if cmd.Flags().Changed(commonParams.RepoURLFlag) {
var projectConfigurations []wrappers.ProjectConfiguration

repoURL, _ := cmd.Flags().GetString(commonParams.RepoURLFlag)

urlConf := getProjectConfiguration(repoConfKey, "repository", git, projOriginLevel, repoURL, "String", true)

projectConfigurations = append(projectConfigurations, urlConf)

if cmd.Flags().Changed(commonParams.SSHKeyFlag) {
sshKeyPath, _ := cmd.Flags().GetString(commonParams.SSHKeyFlag)

sshKey, sshErr := util.ReadFileAsString(sshKeyPath)
if sshErr != nil {
return sshErr
}

sshKeyConf := getProjectConfiguration(sshConfKey, "sshKey", git, projOriginLevel, sshKey, "Secret", true)

projectConfigurations = append(projectConfigurations, sshKeyConf)
}

_, configErr := projectsWrapper.UpdateConfiguration(projectID, projectConfigurations)
if configErr != nil {
return configErr
}
}

return nil
}

func getProjectConfiguration(key, name, category, level, value, valueType string, allowOverride bool) wrappers.ProjectConfiguration {
config := wrappers.ProjectConfiguration{}
config.Key = key
config.Name = name
config.Category = category
config.OriginLevel = level
config.Value = value
config.ValueType = valueType
config.AllowOverride = allowOverride

return config
}

func validateConfiguration(cmd *cobra.Command) error {
var sshKeyDefined bool
var repoURLDefined bool

// Validate if ssh key is empty when provided
if cmd.Flags().Changed(commonParams.SSHKeyFlag) {
sshKey, _ := cmd.Flags().GetString(commonParams.SSHKeyFlag)

if strings.TrimSpace(sshKey) == "" {
return errors.New("flag needs an argument: --ssh-key")
}

sshKeyDefined = true
}

// Validate if repo url is empty when provided
if cmd.Flags().Changed(commonParams.RepoURLFlag) {
repoURL, _ := cmd.Flags().GetString(commonParams.RepoURLFlag)

if strings.TrimSpace(repoURL) == "" {
return errors.New("flag needs an argument: --repo-url")
}

repoURLDefined = true
}

// If ssh key is defined we have two checks to validate:
// 1. repo url needs to be provided
// 2. provided repo url needs to be a ssh url
if sshKeyDefined {
if !repoURLDefined {
return errors.New(mandatoryRepoURLError)
}

repoURL, _ := cmd.Flags().GetString(commonParams.RepoURLFlag)

if !util.IsSSHURL(repoURL) {
return errors.New(invalidRepoURL)
}
}

return nil
}

func runListProjectsCommand(projectsWrapper wrappers.ProjectsWrapper) func(cmd *cobra.Command, args []string) error {
return func(cmd *cobra.Command, args []string) error {
var allProjectsModel *wrappers.ProjectsCollectionResponseModel
Expand Down
63 changes: 63 additions & 0 deletions internal/commands/project_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import (
"testing"

"gotest.tools/assert"

"github.com/checkmarx/ast-cli/internal/commands/util"
)

func TestProjectHelp(t *testing.T) {
Expand Down Expand Up @@ -101,3 +103,64 @@ func TestRunProjectCreateInvalidGroup(t *testing.T) {
"project", "create", "--project-name", "invalidprj", "--groups", "invalidgroup")
assert.Assert(t, err.Error() == "Failed finding groups: [invalidgroup]")
}

func TestCreateProjectMissingSSHValue(t *testing.T) {
baseArgs := []string{"project", "create", "--project-name", "MOCK"}

err := execCmdNotNilAssertion(t, append(baseArgs, "--ssh-key")...)
assert.Error(t, err, "flag needs an argument: --ssh-key", err.Error())

err = execCmdNotNilAssertion(t, append(baseArgs, "--ssh-key", "")...)
assert.Error(t, err, "flag needs an argument: --ssh-key", err.Error())

err = execCmdNotNilAssertion(t, append(baseArgs, "--ssh-key", " ")...)
assert.Error(t, err, "flag needs an argument: --ssh-key", err.Error())
}

func TestCreateProjectMissingRepoURLWithSSHValue(t *testing.T) {
baseArgs := []string{"project", "create", "--project-name", "MOCK"}

err := execCmdNotNilAssertion(t, append(baseArgs, "--ssh-key", "dummy_key", "--repo-url")...)
assert.Error(t, err, "flag needs an argument: --repo-url", err.Error())

err = execCmdNotNilAssertion(t, append(baseArgs, "--ssh-key", "dummy_key", "--repo-url", "")...)
assert.Error(t, err, "flag needs an argument: --repo-url", err.Error())

err = execCmdNotNilAssertion(t, append(baseArgs, "--ssh-key", "dummy_key", "--repo-url", " ")...)
assert.Error(t, err, "flag needs an argument: --repo-url", err.Error())
}

func TestCreateProjectMandatoryRepoURLWhenSSHKeyProvided(t *testing.T) {
baseArgs := []string{"project", "create", "--project-name", "MOCK"}

err := execCmdNotNilAssertion(t, append(baseArgs, "--ssh-key", "dummy_key")...)

assert.Error(t, err, mandatoryRepoURLError)
}

func TestCreateProjectInvalidRepoURLWithSSHKey(t *testing.T) {
baseArgs := []string{"project", "create", "--project-name", "MOCK"}

err := execCmdNotNilAssertion(t, append(baseArgs, "--ssh-key", "dummy_key", "--repo-url", "https://github.com/dummyuser/dummy_project.git")...)

assert.Error(t, err, invalidRepoURL)
}

func TestCreateProjectWrongSSHKeyPath(t *testing.T) {
baseArgs := []string{"project", "create", "--project-name", "MOCK"}

err := execCmdNotNilAssertion(t, append(baseArgs, "--ssh-key", "dummy_key", "--repo-url", "git@github.com:dummyRepo/dummyProject.git")...)

expectedMessages := []string{
"open dummy_key: The system cannot find the file specified.",
"open dummy_key: no such file or directory",
}

assert.Assert(t, util.Contains(expectedMessages, err.Error()))
}

func TestCreateProjectWithSSHKey(t *testing.T) {
baseArgs := []string{"project", "create", "--project-name", "MOCK"}

execCmdNilAssertion(t, append(baseArgs, "--ssh-key", "data/sources.zip", "--repo-url", "git@github.com:dummyRepo/dummyProject.git")...)
}
Loading

0 comments on commit 0077efe

Please sign in to comment.