Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 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
1 change: 1 addition & 0 deletions internal/params/binds.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,5 @@ var EnvVarsBinds = []struct {
{ASCAPortKey, ASCAPortEnv, ""},
{ScsRepoTokenKey, ScsRepoTokenEnv, ""},
{RiskManagementPathKey, RiskManagementPathEnv, "api/risk-management/projects/%s/results"},
{ConfigFilePathKey, ConfigFilePathEnv, ""},
}
1 change: 1 addition & 0 deletions internal/params/envs.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,5 @@ const (
ASCAPortEnv = "CX_ASCA_PORT"
ScsRepoTokenEnv = "SCS_REPO_TOKEN"
RiskManagementPathEnv = "CX_RISK_MANAGEMENT_PATH"
ConfigFilePathEnv = "CX_CONFIG_FILE_PATH"
)
1 change: 1 addition & 0 deletions internal/params/keys.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,4 +73,5 @@ var (
ASCAPortKey = strings.ToLower(ASCAPortEnv)
ScsRepoTokenKey = strings.ToLower(ScsRepoTokenEnv)
RiskManagementPathKey = strings.ToLower(RiskManagementPathEnv)
ConfigFilePathKey = strings.ToLower(ConfigFilePathEnv)
)
68 changes: 55 additions & 13 deletions internal/wrappers/configuration/configuration.go
Original file line number Diff line number Diff line change
Expand Up @@ -118,17 +118,54 @@ func SetConfigProperty(propName, propValue string) {
}

func LoadConfiguration() {
usr, err := user.Current()
configFilePath := viper.GetString(params.ConfigFilePathKey)

if configFilePath != "" {
err := validateConfigFile(configFilePath)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
viper.SetConfigFile(configFilePath)
if err = viper.ReadInConfig(); err != nil {
fmt.Println("An error occurred while accessing the file or environment variable. Please verify the CLI configuration file")
os.Exit(1)
}
} else {
usr, err := user.Current()
if err != nil {
log.Fatal("Cannot file home directory.", err)
}
fullPath := usr.HomeDir + configDirName
verifyConfigDir(fullPath)
viper.AddConfigPath(fullPath)
configFile := "checkmarxcli"
viper.SetConfigName(configFile)
viper.SetConfigType("yaml")
_ = viper.ReadInConfig()
}
}

func validateConfigFile(configFilePath string) error {
info, err := os.Stat(configFilePath)
if err != nil {
if os.IsNotExist(err) {
return fmt.Errorf("The specified file does not exist. Please check the path and ensure the CLI configuration file is available.")
}
return fmt.Errorf("An error occurred while accessing the file or environment variable. Please verify the CLI configuration file")
}

if info.IsDir() {
return fmt.Errorf("The specified path points to a directory, not a file. Please provide a valid CLI configuration file path.")
}

file, err := os.OpenFile(configFilePath, os.O_RDONLY, 0644)
if err != nil {
log.Fatal("Cannot file home directory.", err)
return fmt.Errorf("Access to the specified file is restricted. Please ensure you have the necessary permissions to access the CLI configuration file")
}
fullPath := usr.HomeDir + configDirName
verifyConfigDir(fullPath)
viper.AddConfigPath(fullPath)
configFile := "checkmarxcli"
viper.SetConfigName(configFile)
viper.SetConfigType("yaml")
_ = viper.ReadInConfig()
defer file.Close()

return nil
}

func SafeWriteSingleConfigKey(configFilePath, key string, value int) error {
Expand Down Expand Up @@ -231,11 +268,16 @@ func SaveConfig(path string, config map[string]interface{}) error {
}

func GetConfigFilePath() (string, error) {
usr, err := user.Current()
if err != nil {
return "", fmt.Errorf("error getting current user: %w", err)
configFilePath := viper.GetString(params.ConfigFilePathKey)

if configFilePath == "" {
usr, err := user.Current()
if err != nil {
return "", fmt.Errorf("error getting current user: %w", err)
}
configFilePath = usr.HomeDir + configDirName + "/checkmarxcli.yaml"
}
return usr.HomeDir + configDirName + "/checkmarxcli.yaml", nil
return configFilePath, nil
}

func verifyConfigDir(fullPath string) {
Expand Down
95 changes: 95 additions & 0 deletions test/integration/configuration_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
////go:build integration

Check failure on line 1 in test/integration/configuration_test.go

View workflow job for this annotation

GitHub Actions / lint

: # github.com/checkmarx/ast-cli/test/integration [github.com/checkmarx/ast-cli/test/integration.test]
//
//package integration
//
//import (
// "gotest.tools/assert"
// "os"
// "strings"
// "testing"
//)
//
//var filePath = "data/config.yaml"
//
//func TestIntegration_LoadConfiguration_EnvVarConfigFilePath(t *testing.T) {
// os.Setenv("CX_CONFIG_FILE_PATH", filePath)
// defer os.Unsetenv("CX_CONFIG_FILE_PATH")
//
// cmd, buffer := createRedirectedTestCommand(t)
//
// err := execute(cmd, "configure", "show")
// assert.NilError(t, err)
//
// output := buffer.String()
// if !strings.Contains(output, "cx_base_uri: https://example.com") {
// t.Errorf("expected output to contain 'cx_base_uri: https://example.com', but it did not")
// }
//}
//
//func TestIntegration_LoadConfiguration_FileNotFound(t *testing.T) {
// // Set an invalid file path
// os.Setenv("CX_CONFIG_FILE_PATH", "data/nonexistent_config.yaml")
// defer os.Unsetenv("CX_CONFIG_FILE_PATH")
//
// cmd, buffer := createRedirectedTestCommand(t)
//
// // Execute the command
// err := execute(cmd, "configure", "show")
//
// // Verify that an error occurred
// assert.ErrorContains(t, err, "The specified file does not exist")
//
// // Verify the output contains the expected error message
// output := buffer.String()
// if !strings.Contains(output, "The specified file does not exist") {
// t.Errorf("expected output to contain 'The specified file does not exist', but it did not")
// }
//}
//
//func TestIntegration_LoadConfiguration_FileWithoutPermission_UsingConfigFile(t *testing.T) {
//
// // Set the file to have no permissions
// if err := os.Chmod(filePath, 0000); err != nil {
// t.Fatalf("failed to set file permissions: %v", err)
// }
// defer os.Chmod(filePath, 0644) // Restore permissions for cleanup
//
// // Set the environment variable to point to the restricted file
// os.Setenv("CX_CONFIG_FILE_PATH", filePath)
// defer os.Unsetenv("CX_CONFIG_FILE_PATH")
//
// cmd, buffer := createRedirectedTestCommand(t)
//
// // Execute the command
// err := execute(cmd, "configure", "show")
//
// // Verify that an error occurred
// assert.ErrorContains(t, err, "Access to the specified file is restricted")
//
// // Verify the output contains the expected error message
// output := buffer.String()
// if !strings.Contains(output, "Access to the specified file is restricted") {
// t.Errorf("expected output to contain 'Access to the specified file is restricted', but it did not")
// }
//}
//
//
//func TestIntegration_SetConfigProperty_EnvVarConfigFilePath(t *testing.T) {
// // Set environment variable
// os.Setenv("CX_CONFIG_FILE_PATH", filePath)
// defer os.Unsetenv("CX_CONFIG_FILE_PATH")
//
// // Create command
// cmd, buffer := createRedirectedTestCommand(t)
//
// // Execute command
// err := execute(cmd, "configure", "set", "--prop-name", "new_key", "--prop-value", "new_value")
// assert.NilError(t, err)
//
// // Verify output
// output := buffer.String()
// asserts.Contains(t, output, "Setting property [new_key] to value [new_value]")
//
// // Verify configuration
// asserts.Equal(t, viper.GetString("new_key"), "new_value")
//}

Check failure on line 95 in test/integration/configuration_test.go

View workflow job for this annotation

GitHub Actions / integration-tests

expected 'package', found 'EOF'

Check failure on line 95 in test/integration/configuration_test.go

View workflow job for this annotation

GitHub Actions / govulncheck

expected 'package', found 'EOF'

Check failure on line 95 in test/integration/configuration_test.go

View workflow job for this annotation

GitHub Actions / govulncheck

expected ';', found 'EOF'

Check failure on line 95 in test/integration/configuration_test.go

View workflow job for this annotation

GitHub Actions / govulncheck

expected 'IDENT', found 'EOF'

Check failure on line 95 in test/integration/configuration_test.go

View workflow job for this annotation

GitHub Actions / govulncheck

expected 'package', found 'EOF'

Check failure on line 95 in test/integration/configuration_test.go

View workflow job for this annotation

GitHub Actions / lint

expected 'package', found 'EOF' (typecheck)

Check failure on line 95 in test/integration/configuration_test.go

View workflow job for this annotation

GitHub Actions / unit-tests

expected 'package', found 'EOF'
7 changes: 7 additions & 0 deletions test/integration/data/config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
cx_base_uri: https://example.com
cx_base_auth_uri: https://auth.example.com
cx_tenant: example_tenant
cx_api_key: example_api_key
cx_client_id: example_client_id
cx_client_secret: example_client_secret
cx_proxy: http://proxy.example.com
2 changes: 2 additions & 0 deletions test/integration/util_command.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/checkmarx/ast-cli/internal/commands"
"github.com/checkmarx/ast-cli/internal/params"
"github.com/checkmarx/ast-cli/internal/wrappers"
"github.com/checkmarx/ast-cli/internal/wrappers/configuration"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"gotest.tools/assert"
Expand Down Expand Up @@ -56,6 +57,7 @@ func bindProxy(t *testing.T) {
func createASTIntegrationTestCommand(t *testing.T) *cobra.Command {
bindProxy(t)
bindKeysToEnvAndDefault(t)
configuration.LoadConfiguration()
_ = viper.BindEnv(pat)
viper.AutomaticEnv()
viper.Set("CX_TOKEN_EXPIRY_SECONDS", 2)
Expand Down
Loading