Skip to content

Commit e66e3a7

Browse files
cx-rui-oliveiracx-margarita-levitmcx-anurag-dalke
authored
AST-120196-Enable/disable commit history scanning (#1357)
* feat: Add git-commit-history flag for Secret Detection scans * test: add UTs for flag validation and enabling logic * refactor: update git-commit-history flag description for clarity * refactor: reduce cyclomatic complexity * refactor: enhance functionality with feature flag integration for commit history * test: add and update UTs considering commit history FF * test: add clearFlags() calls for consistency * test: add wrappers.ClearCache() calls to clear cache * test: ensure that flags are cleared after use * refactor: set git commit history to false if configured correctly to allow overrides * test: remove redundant case insensitive TRUE/FALSE tests for flag values * refactor: improve use of warning messages and remove default value * refactor: update warning messages for git commit history flag usage --------- Co-authored-by: Margarita Levit <[email protected]> Co-authored-by: Anurag Dalke <[email protected]>
1 parent 279518b commit e66e3a7

File tree

7 files changed

+728
-40
lines changed

7 files changed

+728
-40
lines changed

internal/commands/groups_test.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import (
99

1010
func TestCreateScanAndProjectWithGroupFFTrue(t *testing.T) {
1111
mock.Flags = wrappers.FeatureFlagsResponseModel{{Name: "ACCESS_MANAGEMENT_ENABLED", Status: true}}
12+
defer clearFlags()
1213
execCmdNilAssertion(
1314
t,
1415
"scan", "create", "--project-name", "new-project", "-b", "dummy_branch", "-s", ".", "--project-groups", "group",
@@ -17,20 +18,23 @@ func TestCreateScanAndProjectWithGroupFFTrue(t *testing.T) {
1718

1819
func TestCreateScanAndProjectWithGroupFFFalse(t *testing.T) {
1920
mock.Flags = wrappers.FeatureFlagsResponseModel{{Name: "ACCESS_MANAGEMENT_ENABLED", Status: false}}
21+
defer clearFlags()
2022
execCmdNilAssertion(
2123
t,
2224
"scan", "create", "--project-name", "new-project", "-b", "dummy_branch", "-s", ".", "--project-groups", "group",
2325
)
2426
}
2527
func TestCreateProjectWithGroupFFTrue(t *testing.T) {
2628
mock.Flags = wrappers.FeatureFlagsResponseModel{{Name: "ACCESS_MANAGEMENT_ENABLED", Status: true}}
29+
defer clearFlags()
2730
execCmdNilAssertion(
2831
t, "project", "create", "--project-name", "new-project", "--groups", "group",
2932
)
3033
}
3134

3235
func TestCreateProjectWithGroupFFFalse(t *testing.T) {
3336
mock.Flags = wrappers.FeatureFlagsResponseModel{{Name: "ACCESS_MANAGEMENT_ENABLED", Status: false}}
37+
defer clearFlags()
3438
execCmdNilAssertion(
3539
t,
3640
"project", "create", "--project-name", "new-project", "--groups", "group",
@@ -39,6 +43,7 @@ func TestCreateProjectWithGroupFFFalse(t *testing.T) {
3943

4044
func TestCreateScanForExistingProjectWithGroupFFTrue(t *testing.T) {
4145
mock.Flags = wrappers.FeatureFlagsResponseModel{{Name: "ACCESS_MANAGEMENT_ENABLED", Status: true}}
46+
defer clearFlags()
4247
execCmdNilAssertion(
4348
t,
4449
"scan", "create", "--project-name", "MOCK", "-b", "dummy_branch", "-s", ".", "--project-groups", "group",

internal/commands/scan.go

Lines changed: 124 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -124,6 +124,12 @@ const (
124124
"--scs-repo-url your_repo_url --scs-repo-token your_repo_token"
125125
ScsScorecardUnsupportedHostWarningMsg = "SCS scan warning: Unable to run Scorecard scanner due to unsupported repo host. Currently, Scorecard can only run on GitHub Cloud repos."
126126

127+
gitCommitHistoryInvalidValueErrorMsg = "Invalid value for --git-commit-history. Valid values are: 'true' or 'false'"
128+
gitCommitHistoryNotAvailableWarningMsg = "Secret Detection scan warning: --git-commit-history flag ignored because git commit history scanning is not available."
129+
gitCommitHistoryNotSelectedWarningMsg = "Secret Detection scan warning: --git-commit-history flag ignored because scs was not specified in scan types."
130+
gitCommitHistoryNotApplicableWarningMsg = "Secret Detection scan warning: --git-commit-history flag ignored because secret detection wasn't run on this scan."
131+
gitCommitHistoryNoGitRepositoryWarningMsg = "Secret Detection scan warning: No Git history found. Secret Detection will scan the working tree only."
132+
127133
jsonExt = ".json"
128134
xmlExt = ".xml"
129135
sbomScanTypeErrMsg = "The --sbom-only flag can only be used when the scan type is sca"
@@ -884,6 +890,7 @@ func scanCreateSubCommand(
884890
createScanCmd.PersistentFlags().String(commonParams.SCSRepoTokenFlag, "", "Provide a token with read permission for the repo that you are scanning (for scorecard scans)")
885891
createScanCmd.PersistentFlags().String(commonParams.SCSRepoURLFlag, "", "The URL of the repo that you are scanning with scs (for scorecard scans)")
886892
createScanCmd.PersistentFlags().String(commonParams.SCSEnginesFlag, "", "Specify which scs engines will run (default: all licensed engines)")
893+
createScanCmd.PersistentFlags().String(commonParams.GitCommitHistoryFlag, "", commonParams.GitCommitHistoryFlagDescription)
887894
createScanCmd.PersistentFlags().Bool(commonParams.ScaHideDevAndTestDepFlag, false, scaHideDevAndTestDepFlagDescription)
888895

889896
// Container config flags
@@ -1010,9 +1017,8 @@ func setupScanTypeProjectAndConfig(
10101017
configArr = append(configArr, containersConfig)
10111018
}
10121019

1013-
scsLicensingV2Flag, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.ScsLicensingV2Enabled)
1014-
var SCSConfig, scsErr = addSCSScan(cmd, resubmitConfig, scsLicensingV2Flag.Status, userAllowedEngines[commonParams.RepositoryHealthType],
1015-
userAllowedEngines[commonParams.SecretDetectionType], userAllowedEngines[commonParams.EnterpriseSecretsType])
1020+
var SCSConfig, scsErr = addSCSScan(cmd, resubmitConfig, userAllowedEngines[commonParams.RepositoryHealthType],
1021+
userAllowedEngines[commonParams.SecretDetectionType], userAllowedEngines[commonParams.EnterpriseSecretsType], featureFlagsWrapper)
10161022
if scsErr != nil {
10171023
return scsErr
10181024
} else if SCSConfig != nil {
@@ -1388,14 +1394,15 @@ func isScorecardRunnable(isScsEnginesFlagSet, scsScorecardSelected bool, scsRepo
13881394
return isURLSupportedByScorecard(scsRepoURL), nil
13891395
}
13901396

1391-
func addSCSScan(cmd *cobra.Command, resubmitConfig []wrappers.Config, scsLicensingV2, hasRepositoryHealthLicense,
1392-
hasSecretDetectionLicense, hasEnterpriseSecretsLicense bool) (map[string]interface{}, error) {
1393-
scsEnabled := isScsEnabled(scsLicensingV2)
1397+
func addSCSScan(cmd *cobra.Command, resubmitConfig []wrappers.Config, hasRepositoryHealthLicense,
1398+
hasSecretDetectionLicense, hasEnterpriseSecretsLicense bool, featureFlagsWrapper wrappers.FeatureFlagsWrapper) (map[string]interface{}, error) {
1399+
scsLicensingV2Flag, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.ScsLicensingV2Enabled)
1400+
scsEnabled := isScsEnabled(scsLicensingV2Flag.Status)
13941401
if !scsEnabled {
13951402
return nil, nil
13961403
}
1397-
scsScorecardAllowed := isScsScorecardAllowed(scsLicensingV2, hasRepositoryHealthLicense)
1398-
scsSecretDetectionAllowed := isScsSecretDetectionAllowed(scsLicensingV2, hasSecretDetectionLicense, hasEnterpriseSecretsLicense)
1404+
scsScorecardAllowed := isScsScorecardAllowed(scsLicensingV2Flag.Status, hasRepositoryHealthLicense)
1405+
scsSecretDetectionAllowed := isScsSecretDetectionAllowed(scsLicensingV2Flag.Status, hasSecretDetectionLicense, hasEnterpriseSecretsLicense)
13991406
if !scsScorecardAllowed && !scsSecretDetectionAllowed {
14001407
return nil, nil
14011408
}
@@ -1426,6 +1433,12 @@ func addSCSScan(cmd *cobra.Command, resubmitConfig []wrappers.Config, scsLicensi
14261433

14271434
if scsSecretDetectionSelected && scsSecretDetectionAllowed {
14281435
scsConfig.Twoms = trueString
1436+
1437+
// Set git commit history based on FF and validations
1438+
commitHistoryFlag, _ := wrappers.GetSpecificFeatureFlag(featureFlagsWrapper, wrappers.SscsCommitHistoryEnabled)
1439+
if gitCommitHistoryValue := getGitCommitHistoryValue(cmd, commitHistoryFlag.Status); gitCommitHistoryValue != "" {
1440+
scsConfig.GitCommitHistory = gitCommitHistoryValue
1441+
}
14291442
}
14301443

14311444
isScsEnginesFlagSet := scsEngines != ""
@@ -3512,6 +3525,13 @@ func validateCreateScanFlags(cmd *cobra.Command) error {
35123525
}
35133526
}
35143527
}
3528+
3529+
// Validate git-commit-history flag
3530+
err = validateGitCommitHistoryFlag(cmd)
3531+
if err != nil {
3532+
return err
3533+
}
3534+
35153535
return nil
35163536
}
35173537

@@ -3783,6 +3803,102 @@ func validateBooleanString(value string) error {
37833803
return nil
37843804
}
37853805

3806+
// validateGitCommitHistoryFlag validates the git-commit-history flag (needed for Secret Detection)
3807+
func validateGitCommitHistoryFlag(cmd *cobra.Command) error {
3808+
gitCommitHistory, _ := cmd.Flags().GetString(commonParams.GitCommitHistoryFlag)
3809+
3810+
err := validateBooleanString(gitCommitHistory)
3811+
if err != nil {
3812+
return errors.Errorf(gitCommitHistoryInvalidValueErrorMsg)
3813+
}
3814+
3815+
return nil
3816+
}
3817+
3818+
// getGitCommitHistoryValue determines the value for git commit history config based on flag and validations
3819+
func getGitCommitHistoryValue(cmd *cobra.Command, isFeatureFlagEnabled bool) string {
3820+
if !isFeatureFlagEnabled {
3821+
fmt.Println(gitCommitHistoryNotAvailableWarningMsg)
3822+
return ""
3823+
}
3824+
3825+
gitCommitHistory, _ := cmd.Flags().GetString(commonParams.GitCommitHistoryFlag)
3826+
gitCommitHistoryValue := strings.ToLower(gitCommitHistory)
3827+
3828+
if !validateGitCommitHistoryContext(cmd) {
3829+
return ""
3830+
}
3831+
3832+
return gitCommitHistoryValue
3833+
}
3834+
3835+
// validateGitCommitHistoryContext validates if the context is appropriate for functionality
3836+
func validateGitCommitHistoryContext(cmd *cobra.Command) bool {
3837+
userScanTypes, _ := cmd.Flags().GetString(commonParams.ScanTypes)
3838+
if !strings.Contains(strings.ToLower(userScanTypes), commonParams.ScsType) {
3839+
fmt.Println(gitCommitHistoryNotSelectedWarningMsg)
3840+
return false
3841+
}
3842+
3843+
scsEngines, _ := cmd.Flags().GetString(commonParams.SCSEnginesFlag)
3844+
scsScoreCardSelected, scsSecretDetectionSelected := getSCSEnginesSelected(scsEngines)
3845+
if scsScoreCardSelected && !scsSecretDetectionSelected {
3846+
fmt.Println(gitCommitHistoryNotApplicableWarningMsg)
3847+
return false
3848+
}
3849+
3850+
source, _ := cmd.Flags().GetString(commonParams.SourcesFlag)
3851+
if !hasGitRepository(source) {
3852+
fmt.Println(gitCommitHistoryNoGitRepositoryWarningMsg)
3853+
return false
3854+
}
3855+
3856+
return true
3857+
}
3858+
3859+
// hasGitRepository checks if the source directory contains a Git repository (skipping validation for git URLs or zip files)
3860+
func hasGitRepository(source string) bool {
3861+
if source == "" {
3862+
return false
3863+
}
3864+
3865+
sourceTrimmed := strings.TrimSpace(source)
3866+
3867+
if util.IsGitURL(sourceTrimmed) || filepath.Ext(sourceTrimmed) == constants.ZipExtension {
3868+
return true
3869+
}
3870+
3871+
info, err := os.Stat(sourceTrimmed)
3872+
if err != nil || !info.IsDir() {
3873+
return false
3874+
}
3875+
3876+
// Check if .git exists in the root directory
3877+
gitPath := filepath.Join(sourceTrimmed, ".git")
3878+
if _, err := os.Stat(gitPath); err == nil {
3879+
return true
3880+
}
3881+
3882+
// fallback: search for .git in subdirectories
3883+
return searchGitInSubdirectories(sourceTrimmed)
3884+
}
3885+
3886+
// searchGitInSubdirectories walks through subdirectories to find a .git folder
3887+
func searchGitInSubdirectories(sourcePath string) bool {
3888+
found := false
3889+
_ = filepath.Walk(sourcePath, func(path string, info os.FileInfo, err error) error {
3890+
if err != nil || found {
3891+
return nil
3892+
}
3893+
if info.IsDir() && info.Name() == ".git" {
3894+
found = true
3895+
return filepath.SkipAll
3896+
}
3897+
return nil
3898+
})
3899+
return found
3900+
}
3901+
37863902
func parseArgs(input string) []string {
37873903
var args []string
37883904
var current strings.Builder

0 commit comments

Comments
 (0)