Skip to content

Commit fadda38

Browse files
CLI | Container Security filter flags (AST-82260) (#1023)
* CLI | Container Security filter flags (AST-82260) * CLI | Container Security filter flags (AST-82260) * Added resubmit support fo container engine configuration * refactor initializeContainersConfigWithResubmitValues - deleted unnecessary conditions * Add integration tests * Change docs * Added example to flags documentations --------- Co-authored-by: AlvoBen <[email protected]>
1 parent 2ad78d5 commit fadda38

File tree

4 files changed

+209
-47
lines changed

4 files changed

+209
-47
lines changed

internal/commands/scan.go

Lines changed: 99 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -53,50 +53,54 @@ const (
5353
notExploitable = "NOT_EXPLOITABLE"
5454
ignored = "IGNORED"
5555

56-
git = "git"
57-
invalidSSHSource = "provided source does not need a key. Make sure you are defining the right source or remove the flag --ssh-key"
58-
errorUnzippingFile = "an error occurred while unzipping file. Reason: "
59-
containerRun = "run"
60-
containerVolumeFlag = "-v"
61-
containerNameFlag = "--name"
62-
containerRemove = "--rm"
63-
containerImage = "checkmarx/kics:v2.1.3"
64-
containerScan = "scan"
65-
containerScanPathFlag = "-p"
66-
containerScanPath = "/path"
67-
containerScanOutputFlag = "-o"
68-
containerScanOutput = "/path"
69-
containerScanFormatFlag = "--report-formats"
70-
containerScanFormatOutput = "json"
71-
containerStarting = "Starting kics container"
72-
containerFormatInfo = "The report format and output path cannot be overridden."
73-
containerFolderRemoving = "Removing folder in temp"
74-
containerCreateFolderError = "Error creating temporary directory"
75-
containerWriteFolderError = " Error writing file to temporary directory"
76-
containerFileSourceMissing = "--file is required for kics-realtime command"
77-
containerFileSourceIncompatible = ". Provided file is not supported by kics"
78-
containerFileSourceError = " Error reading file"
79-
containerResultsFileFormat = "%s/results.json"
80-
containerVolumeFormat = "%s:/path"
81-
containerTempDirPattern = "kics"
82-
kicsContainerPrefixName = "cli-kics-realtime-"
83-
cleanupMaxRetries = 3
84-
cleanupRetryWaitSeconds = 15
85-
DanglingSymlinkError = "Skipping dangling symbolic link"
86-
configFilterKey = "filter"
87-
configFilterPlatforms = "platforms"
88-
configIncremental = "incremental"
89-
configFastScan = "fastScanMode"
90-
configPresetName = "presetName"
91-
configEngineVerbose = "engineVerbose"
92-
configLanguageMode = "languageMode"
93-
resultsMapValue = "value"
94-
resultsMapType = "type"
95-
trueString = "true"
96-
configTwoms = "2ms"
97-
falseString = "false"
98-
maxPollingWaitTime = 60
99-
engineNotAllowed = "It looks like the \"%s\" scan type does not exist or you are trying to run a scan without the \"%s\" package license." +
56+
git = "git"
57+
invalidSSHSource = "provided source does not need a key. Make sure you are defining the right source or remove the flag --ssh-key"
58+
errorUnzippingFile = "an error occurred while unzipping file. Reason: "
59+
containerRun = "run"
60+
containerVolumeFlag = "-v"
61+
containerNameFlag = "--name"
62+
containerRemove = "--rm"
63+
containerImage = "checkmarx/kics:v2.1.3"
64+
containerScan = "scan"
65+
containerScanPathFlag = "-p"
66+
containerScanPath = "/path"
67+
containerScanOutputFlag = "-o"
68+
containerScanOutput = "/path"
69+
containerScanFormatFlag = "--report-formats"
70+
containerScanFormatOutput = "json"
71+
containerStarting = "Starting kics container"
72+
containerFormatInfo = "The report format and output path cannot be overridden."
73+
containerFolderRemoving = "Removing folder in temp"
74+
containerCreateFolderError = "Error creating temporary directory"
75+
containerWriteFolderError = " Error writing file to temporary directory"
76+
containerFileSourceMissing = "--file is required for kics-realtime command"
77+
containerFileSourceIncompatible = ". Provided file is not supported by kics"
78+
containerFileSourceError = " Error reading file"
79+
containerResultsFileFormat = "%s/results.json"
80+
containerVolumeFormat = "%s:/path"
81+
containerTempDirPattern = "kics"
82+
kicsContainerPrefixName = "cli-kics-realtime-"
83+
cleanupMaxRetries = 3
84+
cleanupRetryWaitSeconds = 15
85+
DanglingSymlinkError = "Skipping dangling symbolic link"
86+
configFilterKey = "filter"
87+
configFilterPlatforms = "platforms"
88+
configIncremental = "incremental"
89+
configFastScan = "fastScanMode"
90+
configPresetName = "presetName"
91+
configEngineVerbose = "engineVerbose"
92+
configLanguageMode = "languageMode"
93+
ConfigContainersFilesFilterKey = "filesFilter"
94+
ConfigContainersImagesFilterKey = "imagesFilter"
95+
ConfigContainersPackagesFilterKey = "packagesFilter"
96+
ConfigContainersNonFinalStagesFilterKey = "nonFinalStagesFilter"
97+
resultsMapValue = "value"
98+
resultsMapType = "type"
99+
trueString = "true"
100+
configTwoms = "2ms"
101+
falseString = "false"
102+
maxPollingWaitTime = 60
103+
engineNotAllowed = "It looks like the \"%s\" scan type does not exist or you are trying to run a scan without the \"%s\" package license." +
100104
"\nTo use this feature, you would need to purchase a license." +
101105
"\nPlease contact our support team for assistance if you believe you have already purchased a license." +
102106
"\nLicensed packages: %s"
@@ -657,6 +661,12 @@ func scanCreateSubCommand(
657661
createScanCmd.PersistentFlags().String(commonParams.SCSEnginesFlag, "", "Specify which scs engines will run (default: all licensed engines)")
658662
createScanCmd.PersistentFlags().Bool(commonParams.ScaHideDevAndTestDepFlag, false, scaHideDevAndTestDepFlagDescription)
659663

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

@@ -764,7 +774,7 @@ func setupScanTypeProjectAndConfig(
764774
if apiSecConfig != nil {
765775
configArr = append(configArr, apiSecConfig)
766776
}
767-
var containersConfig = addContainersScan(containerEngineCLIEnabled.Status)
777+
var containersConfig = addContainersScan(cmd, resubmitConfig, containerEngineCLIEnabled.Status)
768778
if containersConfig != nil {
769779
configArr = append(configArr, containersConfig)
770780
}
@@ -935,19 +945,61 @@ func addScaScan(cmd *cobra.Command, resubmitConfig []wrappers.Config, hasContain
935945
return nil
936946
}
937947

938-
func addContainersScan(containerEngineCLIEnabled bool) map[string]interface{} {
948+
func addContainersScan(cmd *cobra.Command, resubmitConfig []wrappers.Config, containerEngineCLIEnabled bool) map[string]interface{} {
939949
if !scanTypeEnabled(commonParams.ContainersType) || !containerEngineCLIEnabled {
940950
return nil
941951
}
942952
containerMapConfig := make(map[string]interface{})
943953
containerMapConfig[resultsMapType] = commonParams.ContainersType
944-
945954
containerConfig := wrappers.ContainerConfig{}
946955

956+
initializeContainersConfigWithResubmitValues(resubmitConfig, &containerConfig)
957+
958+
fileFolderFilter, _ := cmd.PersistentFlags().GetString(commonParams.ContainersFileFolderFilterFlag)
959+
if fileFolderFilter != "" {
960+
containerConfig.FilesFilter = fileFolderFilter
961+
}
962+
packageFilter, _ := cmd.PersistentFlags().GetString(commonParams.ContainersPackageFilterFlag)
963+
if packageFilter != "" {
964+
containerConfig.PackagesFilter = packageFilter
965+
}
966+
excludeNonFinalStages, _ := cmd.PersistentFlags().GetBool(commonParams.ContainersExcludeNonFinalStagesFlag)
967+
if cmd.PersistentFlags().Changed(commonParams.ContainersExcludeNonFinalStagesFlag) {
968+
containerConfig.NonFinalStagesFilter = strconv.FormatBool(excludeNonFinalStages)
969+
}
970+
imageTagFilter, _ := cmd.Flags().GetString(commonParams.ContainersImageTagFilterFlag)
971+
if imageTagFilter != "" {
972+
containerConfig.ImagesFilter = imageTagFilter
973+
}
974+
947975
containerMapConfig[resultsMapValue] = &containerConfig
948976
return containerMapConfig
949977
}
950978

979+
func initializeContainersConfigWithResubmitValues(resubmitConfig []wrappers.Config, containerConfig *wrappers.ContainerConfig) {
980+
for _, config := range resubmitConfig {
981+
if config.Type != commonParams.ContainersType {
982+
continue
983+
}
984+
resubmitFilesFilter := config.Value[ConfigContainersFilesFilterKey]
985+
if resubmitFilesFilter != nil && resubmitFilesFilter != "" {
986+
containerConfig.FilesFilter = resubmitFilesFilter.(string)
987+
}
988+
resubmitPackagesFilter := config.Value[ConfigContainersPackagesFilterKey]
989+
if resubmitPackagesFilter != nil && resubmitPackagesFilter != "" {
990+
containerConfig.PackagesFilter = resubmitPackagesFilter.(string)
991+
}
992+
resubmitNonFinalStagesFilter := config.Value[ConfigContainersNonFinalStagesFilterKey]
993+
if resubmitNonFinalStagesFilter != nil && resubmitNonFinalStagesFilter != "" {
994+
containerConfig.NonFinalStagesFilter = resubmitNonFinalStagesFilter.(string)
995+
}
996+
resubmitImagesFilter := config.Value[ConfigContainersImagesFilterKey]
997+
if resubmitImagesFilter != nil && resubmitImagesFilter != "" {
998+
containerConfig.ImagesFilter = resubmitImagesFilter.(string)
999+
}
1000+
}
1001+
}
1002+
9511003
func addAPISecScan(cmd *cobra.Command) map[string]interface{} {
9521004
if scanTypeEnabled(commonParams.APISecurityType) {
9531005
apiSecMapConfig := make(map[string]interface{})

internal/params/flags.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,12 @@ const (
207207
// SCS (Github)
208208
SCSRepoTokenFlag = "scs-repo-token"
209209
SCSRepoURLFlag = "scs-repo-url"
210+
211+
// Containers Config Flags
212+
ContainersFileFolderFilterFlag = "containers-file-folder-filter"
213+
ContainersImageTagFilterFlag = "containers-image-tag-filter"
214+
ContainersPackageFilterFlag = "containers-package-filter"
215+
ContainersExcludeNonFinalStagesFlag = "containers-exclude-non-final-stages"
210216
)
211217

212218
// Parameter values

internal/wrappers/scans.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,10 @@ type ScaConfig struct {
142142
EnableContainersScan bool `json:"enableContainersScan,omitempty"`
143143
}
144144
type ContainerConfig struct {
145+
FilesFilter string `json:"filesFilter,omitempty"`
146+
ImagesFilter string `json:"imagesFilter,omitempty"`
147+
PackagesFilter string `json:"packagesFilter,omitempty"`
148+
NonFinalStagesFilter string `json:"nonFinalStagesFilter,omitempty"`
145149
}
146150
type APISecConfig struct {
147151
SwaggerFilter string `json:"swaggerFilter,omitempty"`

test/integration/scan_test.go

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2035,3 +2035,103 @@ func TestCreateScanWithResubmitFlag_ProjectNotExist_ScanCreatedSuccessfullyWithD
20352035
err, _ := executeCommand(t, args...)
20362036
assert.NilError(t, err)
20372037
}
2038+
func TestScanCreate_WithContainerFilterFlags_CreatingScanSuccessfully(t *testing.T) {
2039+
bindKeysToEnvAndDefault(t)
2040+
var createdScan wrappers.ScanResponseModel
2041+
var createdScanConfig wrappers.Config
2042+
scansPath := viper.GetString(params.ScansPathKey)
2043+
scanWrapper := wrappers.NewHTTPScansWrapper(scansPath)
2044+
2045+
args := []string{
2046+
"scan", "create",
2047+
flag(params.ProjectName), GenerateRandomProjectNameForScan(),
2048+
flag(params.SourcesFlag), ".",
2049+
flag(params.ScanTypes), params.ContainersTypeFlag,
2050+
flag(params.ContainersFileFolderFilterFlag), "!*.log",
2051+
flag(params.ContainersExcludeNonFinalStagesFlag),
2052+
flag(params.ContainersImageTagFilterFlag), "*dev",
2053+
flag(params.ContainersPackageFilterFlag), "^internal-.*",
2054+
flag(params.BranchFlag), "dummy_branch",
2055+
flag(params.ScanInfoFormatFlag), printer.FormatJSON,
2056+
flag(params.AsyncFlag),
2057+
}
2058+
scanID, projectID := executeCreateScan(t, args)
2059+
2060+
mapParams := make(map[string]string)
2061+
mapParams["project-id"] = projectID
2062+
allScansModel, _, _ := scanWrapper.Get(mapParams)
2063+
2064+
createdScan = allScansModel.Scans[0]
2065+
2066+
assert.Assert(t, createdScan.ID == scanID, "Scan ID should be equal")
2067+
assert.Equal(t, len(createdScan.Metadata.Configs), 1, "Scan should have only containers config")
2068+
2069+
createdScanConfig = createdScan.Metadata.Configs[0]
2070+
2071+
assert.Equal(t, createdScanConfig.Type, params.ContainersType, "Scan type should be equal")
2072+
assert.Equal(t, createdScanConfig.Value[commands.ConfigContainersFilesFilterKey], "!*.log", "File/Folder filter should be equal")
2073+
assert.Equal(t, createdScanConfig.Value[commands.ConfigContainersNonFinalStagesFilterKey], "true", "Exclude non final stages should be equal")
2074+
assert.Equal(t, createdScanConfig.Value[commands.ConfigContainersImagesFilterKey], "*dev", "Image tag filter should be equal")
2075+
assert.Equal(t, createdScanConfig.Value[commands.ConfigContainersPackagesFilterKey], "^internal-.*", "Package filter should be equal")
2076+
2077+
}
2078+
2079+
func TestScanCreate_WithContainerFilterFlagsAndResubmitFlag_CreatingScanWithLatestScanConfigurationSuccessfully(t *testing.T) {
2080+
bindKeysToEnvAndDefault(t)
2081+
2082+
var createdScan wrappers.ScanResponseModel
2083+
var createdScanConfig wrappers.Config
2084+
2085+
scansPath := viper.GetString(params.ScansPathKey)
2086+
scanWrapper := wrappers.NewHTTPScansWrapper(scansPath)
2087+
2088+
projectName := GenerateRandomProjectNameForScan()
2089+
2090+
args := []string{
2091+
"scan", "create",
2092+
flag(params.ProjectName), projectName,
2093+
flag(params.SourcesFlag), ".",
2094+
flag(params.ScanTypes), params.ContainersTypeFlag,
2095+
flag(params.ContainersFileFolderFilterFlag), "!*.log",
2096+
flag(params.ContainersImageTagFilterFlag), "*dev",
2097+
flag(params.ContainersPackageFilterFlag), "^internal-.*",
2098+
flag(params.BranchFlag), "dummy_branch",
2099+
flag(params.ScanInfoFormatFlag), printer.FormatJSON,
2100+
flag(params.AsyncFlag),
2101+
}
2102+
2103+
_, projectID := executeCreateScan(t, args)
2104+
2105+
args = []string{
2106+
"scan", "create",
2107+
flag(params.ProjectName), projectName,
2108+
flag(params.SourcesFlag), ".",
2109+
flag(params.ScanTypes), params.ContainersTypeFlag,
2110+
flag(params.ContainersFileFolderFilterFlag), "!dockerfile",
2111+
flag(params.BranchFlag), "dummy_branch",
2112+
flag(params.ScanInfoFormatFlag), printer.FormatJSON,
2113+
flag(params.AsyncFlag),
2114+
flag(params.ScanResubmit),
2115+
}
2116+
2117+
resubmitScanID, resubmitProjectID := executeCreateScan(t, args)
2118+
2119+
assert.Equal(t, projectID, resubmitProjectID, "Project ID should be equal")
2120+
2121+
mapParams := make(map[string]string)
2122+
mapParams["project-id"] = resubmitProjectID
2123+
allScansModel, _, _ := scanWrapper.Get(mapParams)
2124+
2125+
createdScan = allScansModel.Scans[0]
2126+
2127+
assert.Assert(t, createdScan.ID == resubmitScanID, "Scan ID should be equal")
2128+
assert.Equal(t, len(createdScan.Metadata.Configs), 1, "Scan should have only containers config")
2129+
2130+
createdScanConfig = createdScan.Metadata.Configs[0]
2131+
2132+
assert.Equal(t, createdScanConfig.Type, params.ContainersType, "Scan type should be equal")
2133+
assert.Equal(t, createdScanConfig.Value[commands.ConfigContainersFilesFilterKey], "!dockerfile", "File/Folder filter should be equal")
2134+
assert.Equal(t, createdScanConfig.Value[commands.ConfigContainersNonFinalStagesFilterKey], nil, "Exclude non final stages should be equal")
2135+
assert.Equal(t, createdScanConfig.Value[commands.ConfigContainersImagesFilterKey], "*dev", "Image tag filter should be equal")
2136+
assert.Equal(t, createdScanConfig.Value[commands.ConfigContainersPackagesFilterKey], "^internal-.*", "Package filter should be equal")
2137+
}

0 commit comments

Comments
 (0)