Skip to content
Merged
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
146 changes: 99 additions & 47 deletions internal/commands/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,50 +53,54 @@ const (
notExploitable = "NOT_EXPLOITABLE"
ignored = "IGNORED"

git = "git"
invalidSSHSource = "provided source does not need a key. Make sure you are defining the right source or remove the flag --ssh-key"
errorUnzippingFile = "an error occurred while unzipping file. Reason: "
containerRun = "run"
containerVolumeFlag = "-v"
containerNameFlag = "--name"
containerRemove = "--rm"
containerImage = "checkmarx/kics:v2.1.3"
containerScan = "scan"
containerScanPathFlag = "-p"
containerScanPath = "/path"
containerScanOutputFlag = "-o"
containerScanOutput = "/path"
containerScanFormatFlag = "--report-formats"
containerScanFormatOutput = "json"
containerStarting = "Starting kics container"
containerFormatInfo = "The report format and output path cannot be overridden."
containerFolderRemoving = "Removing folder in temp"
containerCreateFolderError = "Error creating temporary directory"
containerWriteFolderError = " Error writing file to temporary directory"
containerFileSourceMissing = "--file is required for kics-realtime command"
containerFileSourceIncompatible = ". Provided file is not supported by kics"
containerFileSourceError = " Error reading file"
containerResultsFileFormat = "%s/results.json"
containerVolumeFormat = "%s:/path"
containerTempDirPattern = "kics"
kicsContainerPrefixName = "cli-kics-realtime-"
cleanupMaxRetries = 3
cleanupRetryWaitSeconds = 15
DanglingSymlinkError = "Skipping dangling symbolic link"
configFilterKey = "filter"
configFilterPlatforms = "platforms"
configIncremental = "incremental"
configFastScan = "fastScanMode"
configPresetName = "presetName"
configEngineVerbose = "engineVerbose"
configLanguageMode = "languageMode"
resultsMapValue = "value"
resultsMapType = "type"
trueString = "true"
configTwoms = "2ms"
falseString = "false"
maxPollingWaitTime = 60
engineNotAllowed = "It looks like the \"%s\" scan type does not exist or you are trying to run a scan without the \"%s\" package license." +
git = "git"
invalidSSHSource = "provided source does not need a key. Make sure you are defining the right source or remove the flag --ssh-key"
errorUnzippingFile = "an error occurred while unzipping file. Reason: "
containerRun = "run"
containerVolumeFlag = "-v"
containerNameFlag = "--name"
containerRemove = "--rm"
containerImage = "checkmarx/kics:v2.1.3"
containerScan = "scan"
containerScanPathFlag = "-p"
containerScanPath = "/path"
containerScanOutputFlag = "-o"
containerScanOutput = "/path"
containerScanFormatFlag = "--report-formats"
containerScanFormatOutput = "json"
containerStarting = "Starting kics container"
containerFormatInfo = "The report format and output path cannot be overridden."
containerFolderRemoving = "Removing folder in temp"
containerCreateFolderError = "Error creating temporary directory"
containerWriteFolderError = " Error writing file to temporary directory"
containerFileSourceMissing = "--file is required for kics-realtime command"
containerFileSourceIncompatible = ". Provided file is not supported by kics"
containerFileSourceError = " Error reading file"
containerResultsFileFormat = "%s/results.json"
containerVolumeFormat = "%s:/path"
containerTempDirPattern = "kics"
kicsContainerPrefixName = "cli-kics-realtime-"
cleanupMaxRetries = 3
cleanupRetryWaitSeconds = 15
DanglingSymlinkError = "Skipping dangling symbolic link"
configFilterKey = "filter"
configFilterPlatforms = "platforms"
configIncremental = "incremental"
configFastScan = "fastScanMode"
configPresetName = "presetName"
configEngineVerbose = "engineVerbose"
configLanguageMode = "languageMode"
ConfigContainersFilesFilterKey = "filesFilter"
ConfigContainersImagesFilterKey = "imagesFilter"
ConfigContainersPackagesFilterKey = "packagesFilter"
ConfigContainersNonFinalStagesFilterKey = "nonFinalStagesFilter"
resultsMapValue = "value"
resultsMapType = "type"
trueString = "true"
configTwoms = "2ms"
falseString = "false"
maxPollingWaitTime = 60
engineNotAllowed = "It looks like the \"%s\" scan type does not exist or you are trying to run a scan without the \"%s\" package license." +
"\nTo use this feature, you would need to purchase a license." +
"\nPlease contact our support team for assistance if you believe you have already purchased a license." +
"\nLicensed packages: %s"
Expand Down Expand Up @@ -657,6 +661,12 @@ func scanCreateSubCommand(
createScanCmd.PersistentFlags().String(commonParams.SCSEnginesFlag, "", "Specify which scs engines will run (default: all licensed engines)")
createScanCmd.PersistentFlags().Bool(commonParams.ScaHideDevAndTestDepFlag, false, scaHideDevAndTestDepFlagDescription)

// Container config flags
createScanCmd.PersistentFlags().String(commonParams.ContainersFileFolderFilterFlag, "", "Specify files and folders to be included or excluded from scans, ex: \"!*.log\"")
createScanCmd.PersistentFlags().String(commonParams.ContainersPackageFilterFlag, "", "Exclude packages by package name or file path using regex, ex: \"^internal-.*\"")
createScanCmd.PersistentFlags().Bool(commonParams.ContainersExcludeNonFinalStagesFlag, false, "Scan only the final deployable image")
createScanCmd.PersistentFlags().String(commonParams.ContainersImageTagFilterFlag, "", "Exclude images by image name and/or tag, ex: \"*dev\"")

return createScanCmd
}

Expand Down Expand Up @@ -764,7 +774,7 @@ func setupScanTypeProjectAndConfig(
if apiSecConfig != nil {
configArr = append(configArr, apiSecConfig)
}
var containersConfig = addContainersScan(containerEngineCLIEnabled.Status)
var containersConfig = addContainersScan(cmd, resubmitConfig, containerEngineCLIEnabled.Status)
if containersConfig != nil {
configArr = append(configArr, containersConfig)
}
Expand Down Expand Up @@ -935,19 +945,61 @@ func addScaScan(cmd *cobra.Command, resubmitConfig []wrappers.Config, hasContain
return nil
}

func addContainersScan(containerEngineCLIEnabled bool) map[string]interface{} {
func addContainersScan(cmd *cobra.Command, resubmitConfig []wrappers.Config, containerEngineCLIEnabled bool) map[string]interface{} {
if !scanTypeEnabled(commonParams.ContainersType) || !containerEngineCLIEnabled {
return nil
}
containerMapConfig := make(map[string]interface{})
containerMapConfig[resultsMapType] = commonParams.ContainersType

containerConfig := wrappers.ContainerConfig{}

initializeContainersConfigWithResubmitValues(resubmitConfig, &containerConfig)

fileFolderFilter, _ := cmd.PersistentFlags().GetString(commonParams.ContainersFileFolderFilterFlag)
if fileFolderFilter != "" {
containerConfig.FilesFilter = fileFolderFilter
}
packageFilter, _ := cmd.PersistentFlags().GetString(commonParams.ContainersPackageFilterFlag)
if packageFilter != "" {
containerConfig.PackagesFilter = packageFilter
}
excludeNonFinalStages, _ := cmd.PersistentFlags().GetBool(commonParams.ContainersExcludeNonFinalStagesFlag)
if cmd.PersistentFlags().Changed(commonParams.ContainersExcludeNonFinalStagesFlag) {
containerConfig.NonFinalStagesFilter = strconv.FormatBool(excludeNonFinalStages)
}
imageTagFilter, _ := cmd.Flags().GetString(commonParams.ContainersImageTagFilterFlag)
if imageTagFilter != "" {
containerConfig.ImagesFilter = imageTagFilter
}

containerMapConfig[resultsMapValue] = &containerConfig
return containerMapConfig
}

func initializeContainersConfigWithResubmitValues(resubmitConfig []wrappers.Config, containerConfig *wrappers.ContainerConfig) {
for _, config := range resubmitConfig {
if config.Type != commonParams.ContainersType {
continue
}
resubmitFilesFilter := config.Value[ConfigContainersFilesFilterKey]
if resubmitFilesFilter != nil && resubmitFilesFilter != "" {
containerConfig.FilesFilter = resubmitFilesFilter.(string)
}
resubmitPackagesFilter := config.Value[ConfigContainersPackagesFilterKey]
if resubmitPackagesFilter != nil && resubmitPackagesFilter != "" {
containerConfig.PackagesFilter = resubmitPackagesFilter.(string)
}
resubmitNonFinalStagesFilter := config.Value[ConfigContainersNonFinalStagesFilterKey]
if resubmitNonFinalStagesFilter != nil && resubmitNonFinalStagesFilter != "" {
containerConfig.NonFinalStagesFilter = resubmitNonFinalStagesFilter.(string)
}
resubmitImagesFilter := config.Value[ConfigContainersImagesFilterKey]
if resubmitImagesFilter != nil && resubmitImagesFilter != "" {
containerConfig.ImagesFilter = resubmitImagesFilter.(string)
}
}
}

func addAPISecScan(cmd *cobra.Command) map[string]interface{} {
if scanTypeEnabled(commonParams.APISecurityType) {
apiSecMapConfig := make(map[string]interface{})
Expand Down
6 changes: 6 additions & 0 deletions internal/params/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,12 @@ const (
// SCS (Github)
SCSRepoTokenFlag = "scs-repo-token"
SCSRepoURLFlag = "scs-repo-url"

// Containers Config Flags
ContainersFileFolderFilterFlag = "containers-file-folder-filter"
ContainersImageTagFilterFlag = "containers-image-tag-filter"
ContainersPackageFilterFlag = "containers-package-filter"
ContainersExcludeNonFinalStagesFlag = "containers-exclude-non-final-stages"
)

// Parameter values
Expand Down
4 changes: 4 additions & 0 deletions internal/wrappers/scans.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,10 @@ type ScaConfig struct {
EnableContainersScan bool `json:"enableContainersScan,omitempty"`
}
type ContainerConfig struct {
FilesFilter string `json:"filesFilter,omitempty"`
ImagesFilter string `json:"imagesFilter,omitempty"`
PackagesFilter string `json:"packagesFilter,omitempty"`
NonFinalStagesFilter string `json:"nonFinalStagesFilter,omitempty"`
}
type APISecConfig struct {
SwaggerFilter string `json:"swaggerFilter,omitempty"`
Expand Down
100 changes: 100 additions & 0 deletions test/integration/scan_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2035,3 +2035,103 @@ func TestCreateScanWithResubmitFlag_ProjectNotExist_ScanCreatedSuccessfullyWithD
err, _ := executeCommand(t, args...)
assert.NilError(t, err)
}
func TestScanCreate_WithContainerFilterFlags_CreatingScanSuccessfully(t *testing.T) {
bindKeysToEnvAndDefault(t)
var createdScan wrappers.ScanResponseModel
var createdScanConfig wrappers.Config
scansPath := viper.GetString(params.ScansPathKey)
scanWrapper := wrappers.NewHTTPScansWrapper(scansPath)

args := []string{
"scan", "create",
flag(params.ProjectName), GenerateRandomProjectNameForScan(),
flag(params.SourcesFlag), ".",
flag(params.ScanTypes), params.ContainersTypeFlag,
flag(params.ContainersFileFolderFilterFlag), "!*.log",
flag(params.ContainersExcludeNonFinalStagesFlag),
flag(params.ContainersImageTagFilterFlag), "*dev",
flag(params.ContainersPackageFilterFlag), "^internal-.*",
flag(params.BranchFlag), "dummy_branch",
flag(params.ScanInfoFormatFlag), printer.FormatJSON,
flag(params.AsyncFlag),
}
scanID, projectID := executeCreateScan(t, args)

mapParams := make(map[string]string)
mapParams["project-id"] = projectID
allScansModel, _, _ := scanWrapper.Get(mapParams)

createdScan = allScansModel.Scans[0]

assert.Assert(t, createdScan.ID == scanID, "Scan ID should be equal")
assert.Equal(t, len(createdScan.Metadata.Configs), 1, "Scan should have only containers config")

createdScanConfig = createdScan.Metadata.Configs[0]

assert.Equal(t, createdScanConfig.Type, params.ContainersType, "Scan type should be equal")
assert.Equal(t, createdScanConfig.Value[commands.ConfigContainersFilesFilterKey], "!*.log", "File/Folder filter should be equal")
assert.Equal(t, createdScanConfig.Value[commands.ConfigContainersNonFinalStagesFilterKey], "true", "Exclude non final stages should be equal")
assert.Equal(t, createdScanConfig.Value[commands.ConfigContainersImagesFilterKey], "*dev", "Image tag filter should be equal")
assert.Equal(t, createdScanConfig.Value[commands.ConfigContainersPackagesFilterKey], "^internal-.*", "Package filter should be equal")

}

func TestScanCreate_WithContainerFilterFlagsAndResubmitFlag_CreatingScanWithLatestScanConfigurationSuccessfully(t *testing.T) {
bindKeysToEnvAndDefault(t)

var createdScan wrappers.ScanResponseModel
var createdScanConfig wrappers.Config

scansPath := viper.GetString(params.ScansPathKey)
scanWrapper := wrappers.NewHTTPScansWrapper(scansPath)

projectName := GenerateRandomProjectNameForScan()

args := []string{
"scan", "create",
flag(params.ProjectName), projectName,
flag(params.SourcesFlag), ".",
flag(params.ScanTypes), params.ContainersTypeFlag,
flag(params.ContainersFileFolderFilterFlag), "!*.log",
flag(params.ContainersImageTagFilterFlag), "*dev",
flag(params.ContainersPackageFilterFlag), "^internal-.*",
flag(params.BranchFlag), "dummy_branch",
flag(params.ScanInfoFormatFlag), printer.FormatJSON,
flag(params.AsyncFlag),
}

_, projectID := executeCreateScan(t, args)

args = []string{
"scan", "create",
flag(params.ProjectName), projectName,
flag(params.SourcesFlag), ".",
flag(params.ScanTypes), params.ContainersTypeFlag,
flag(params.ContainersFileFolderFilterFlag), "!dockerfile",
flag(params.BranchFlag), "dummy_branch",
flag(params.ScanInfoFormatFlag), printer.FormatJSON,
flag(params.AsyncFlag),
flag(params.ScanResubmit),
}

resubmitScanID, resubmitProjectID := executeCreateScan(t, args)

assert.Equal(t, projectID, resubmitProjectID, "Project ID should be equal")

mapParams := make(map[string]string)
mapParams["project-id"] = resubmitProjectID
allScansModel, _, _ := scanWrapper.Get(mapParams)

createdScan = allScansModel.Scans[0]

assert.Assert(t, createdScan.ID == resubmitScanID, "Scan ID should be equal")
assert.Equal(t, len(createdScan.Metadata.Configs), 1, "Scan should have only containers config")

createdScanConfig = createdScan.Metadata.Configs[0]

assert.Equal(t, createdScanConfig.Type, params.ContainersType, "Scan type should be equal")
assert.Equal(t, createdScanConfig.Value[commands.ConfigContainersFilesFilterKey], "!dockerfile", "File/Folder filter should be equal")
assert.Equal(t, createdScanConfig.Value[commands.ConfigContainersNonFinalStagesFilterKey], nil, "Exclude non final stages should be equal")
assert.Equal(t, createdScanConfig.Value[commands.ConfigContainersImagesFilterKey], "*dev", "Image tag filter should be equal")
assert.Equal(t, createdScanConfig.Value[commands.ConfigContainersPackagesFilterKey], "^internal-.*", "Package filter should be equal")
}
Loading