Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(cli): include queries filter #3431

Merged
merged 4 commits into from
May 26, 2021
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
4 changes: 4 additions & 0 deletions e2e/fixtures/E2E_CLI_002
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ Flags:
--ignore-on-exit string defines which kind of non-zero exits code should be ignored
accepts: all, results, errors, none
example: if 'results' is set, only engine errors will make KICS exit code different from 0 (default "none")
-i, --include-queries strings include queries by providing the query ID
takes precedence over excluded queries
can be provided multiple times or as a comma separated string
example: 'e69890e6-fce5-461d-98ad-cb98318dfc96,4728cd65-a20c-49da-8b31-9c08b423e4db'
--minimal-ui simplified version of CLI output
--no-progress hides the progress bar
-o, --output-path string directory path to store reports
Expand Down
4 changes: 4 additions & 0 deletions e2e/fixtures/E2E_CLI_003
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ Flags:
--ignore-on-exit string defines which kind of non-zero exits code should be ignored
accepts: all, results, errors, none
example: if 'results' is set, only engine errors will make KICS exit code different from 0 (default "none")
-i, --include-queries strings include queries by providing the query ID
takes precedence over excluded queries
can be provided multiple times or as a comma separated string
example: 'e69890e6-fce5-461d-98ad-cb98318dfc96,4728cd65-a20c-49da-8b31-9c08b423e4db'
--minimal-ui simplified version of CLI output
--no-progress hides the progress bar
-o, --output-path string directory path to store reports
Expand Down
4 changes: 4 additions & 0 deletions e2e/fixtures/E2E_CLI_004
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ Flags:
--ignore-on-exit string defines which kind of non-zero exits code should be ignored
accepts: all, results, errors, none
example: if 'results' is set, only engine errors will make KICS exit code different from 0 (default "none")
-i, --include-queries strings include queries by providing the query ID
takes precedence over excluded queries
can be provided multiple times or as a comma separated string
example: 'e69890e6-fce5-461d-98ad-cb98318dfc96,4728cd65-a20c-49da-8b31-9c08b423e4db'
--minimal-ui simplified version of CLI output
--no-progress hides the progress bar
-o, --output-path string directory path to store reports
Expand Down
4 changes: 4 additions & 0 deletions e2e/fixtures/E2E_CLI_016_INVALID_SCAN_FLAG
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ Flags:
--ignore-on-exit string defines which kind of non-zero exits code should be ignored
accepts: all, results, errors, none
example: if 'results' is set, only engine errors will make KICS exit code different from 0 (default "none")
-i, --include-queries strings include queries by providing the query ID
takes precedence over excluded queries
can be provided multiple times or as a comma separated string
example: 'e69890e6-fce5-461d-98ad-cb98318dfc96,4728cd65-a20c-49da-8b31-9c08b423e4db'
--minimal-ui simplified version of CLI output
--no-progress hides the progress bar
-o, --output-path string directory path to store reports
Expand Down
49 changes: 47 additions & 2 deletions internal/console/scan.go
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ var (
excludeIDs []string
excludePath []string
excludeResults []string
includeIDs []string
failOn []string
ignoreOnExit string
min bool
Expand All @@ -69,6 +70,8 @@ const (
excludeQueriesFlag = "exclude-queries"
excludeResultsFlag = "exclude-results"
excludeResutlsShorthand = "x"
includeQueriesFlag = "include-queries"
inlcudeQueriesShorthand = "i"
failOnFlag = "fail-on"
ignoreOnExitFlag = "ignore-on-exit"
minimalUIFlag = "minimal-ui"
Expand Down Expand Up @@ -134,6 +137,10 @@ func preRun(cmd *cobra.Command) error {
if err != nil {
return errors.New(initError + err.Error())
}
err = validateQuerySelectionFlags()
if err != nil {
return err
}
err = internalPrinter.SetupPrinter(cmd.InheritedFlags())
if err != nil {
return errors.New(initError + err.Error())
Expand All @@ -145,6 +152,22 @@ func preRun(cmd *cobra.Command) error {
return nil
}

func formatNewError(flag1, flag2 string) error {
return errors.Errorf("can't provide '%s' and '%s' flags simultaneously",
flag1,
flag2)
}

func validateQuerySelectionFlags() error {
if len(includeIDs) > 0 && len(excludeIDs) > 0 {
return formatNewError(includeQueriesFlag, excludeQueriesFlag)
}
if len(includeIDs) > 0 && len(excludeCategories) > 0 {
return formatNewError(includeQueriesFlag, excludeCategoriesFlag)
}
return nil
}

func initializeConfig(cmd *cobra.Command) error {
log.Debug().Msg("console.initializeConfig()")

Expand Down Expand Up @@ -314,6 +337,15 @@ func initScanFlags(scanCmd *cobra.Command) {
msg+
"example: 'e69890e6-fce5-461d-98ad-cb98318dfc96,4728cd65-a20c-49da-8b31-9c08b423e4db'",
)
scanCmd.Flags().StringSliceVarP(&includeIDs,
includeQueriesFlag,
inlcudeQueriesShorthand,
[]string{},
"include queries by providing the query ID\n"+
"takes precedence over excluded queries\n"+
msg+
"example: 'e69890e6-fce5-461d-98ad-cb98318dfc96,4728cd65-a20c-49da-8b31-9c08b423e4db'",
)
scanCmd.Flags().StringSliceVarP(&excludeResults,
excludeResultsFlag,
excludeResutlsShorthand,
Expand Down Expand Up @@ -398,9 +430,22 @@ func createInspector(t engine.Tracker, querySource source.QueriesSource) (*engin
ByCategories: excludeCategories,
}

includeQueries := source.IncludeQueries{
ByIDs: includeIDs,
}

queryFilter := source.QuerySelectionFilter{
IncludeQueries: includeQueries,
ExcludeQueries: excludeQueries,
}

inspector, err := engine.NewInspector(ctx,
querySource, engine.DefaultVulnerabilityBuilder,
t, excludeQueries, excludeResultsMap, queryExecTimeout)
querySource,
engine.DefaultVulnerabilityBuilder,
t,
queryFilter,
excludeResultsMap,
queryExecTimeout)
if err != nil {
return nil, err
}
Expand Down
4 changes: 2 additions & 2 deletions pkg/engine/inspector.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,13 +101,13 @@ func NewInspector(
queriesSource source.QueriesSource,
vb VulnerabilityBuilder,
tracker Tracker,
excludeQueries source.ExcludeQueries,
queryFilter source.QuerySelectionFilter,
excludeResults map[string]bool,
queryTimeout int) (*Inspector, error) {
log.Debug().Msg("engine.NewInspector()")

metrics.Metric.Start("get_queries")
queries, err := queriesSource.GetQueries(excludeQueries)
queries, err := queriesSource.GetQueries(queryFilter)
if err != nil {
return nil, errors.Wrap(err, "failed to get queries")
}
Expand Down
21 changes: 13 additions & 8 deletions pkg/engine/inspector_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ func TestNewInspector(t *testing.T) { // nolint
source source.QueriesSource
vb VulnerabilityBuilder
tracker Tracker
excludeQueries source.ExcludeQueries
queryFilter source.QuerySelectionFilter
excludeResults map[string]bool
queryExecTimeout int
}
Expand All @@ -374,9 +374,14 @@ func TestNewInspector(t *testing.T) { // nolint
vb: vbs,
tracker: track,
source: sources,
excludeQueries: source.ExcludeQueries{
ByIDs: []string{},
ByCategories: []string{},
queryFilter: source.QuerySelectionFilter{
IncludeQueries: source.IncludeQueries{
ByIDs: []string{},
},
ExcludeQueries: source.ExcludeQueries{
ByIDs: []string{},
ByCategories: []string{},
},
},
excludeResults: map[string]bool{},
queryExecTimeout: 60,
Expand All @@ -395,7 +400,7 @@ func TestNewInspector(t *testing.T) { // nolint
tt.args.source,
tt.args.vb,
tt.args.tracker,
tt.args.excludeQueries,
tt.args.queryFilter,
tt.args.excludeResults,
tt.args.queryExecTimeout)

Expand Down Expand Up @@ -556,7 +561,7 @@ func newInspectorInstance(t *testing.T, queryPath string) *Inspector {
detector *detector.DetectLine) (model.Vulnerability, error) {
return model.Vulnerability{}, nil
}
ins, err := NewInspector(context.Background(), querySource, vb, &tracker.CITracker{}, source.ExcludeQueries{}, map[string]bool{}, 60)
ins, err := NewInspector(context.Background(), querySource, vb, &tracker.CITracker{}, source.QuerySelectionFilter{}, map[string]bool{}, 60)
require.NoError(t, err)
return ins
}
Expand All @@ -566,10 +571,10 @@ type mockSource struct {
Types []string
}

func (m *mockSource) GetQueries(excludeQueries source.ExcludeQueries) ([]model.QueryMetadata, error) {
func (m *mockSource) GetQueries(queryFilter source.QuerySelectionFilter) ([]model.QueryMetadata, error) {
sources := source.NewFilesystemSource(m.Source, []string{""})

return sources.GetQueries(excludeQueries)
return sources.GetQueries(queryFilter)
}

func (m *mockSource) GetQueryLibrary(platform string) (string, error) {
Expand Down
10 changes: 5 additions & 5 deletions pkg/engine/mock/source.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

38 changes: 30 additions & 8 deletions pkg/engine/source/filesystem.go
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,21 @@ func (s *FilesystemSource) CheckType(queryPlatform interface{}) bool {
return true
}

func checkQueryInclude(id interface{}, includedQueries []string) bool {
queryMetadataKey, ok := id.(string)
if !ok {
log.Warn().
Msgf("Can't cast query metadata key = %v", id)
return false
}
for _, includedQuery := range includedQueries {
if queryMetadataKey == includedQuery {
return true
}
}
return false
}

func checkQueryExclude(id interface{}, excludeQueries []string) bool {
queryMetadataKey, ok := id.(string)
if !ok {
Expand All @@ -131,7 +146,7 @@ func checkQueryExclude(id interface{}, excludeQueries []string) bool {

// GetQueries walks a given filesource path returns all queries found in an array of
// QueryMetadata struct
func (s *FilesystemSource) GetQueries(excludeQueries ExcludeQueries) ([]model.QueryMetadata, error) {
func (s *FilesystemSource) GetQueries(queryFilter QuerySelectionFilter) ([]model.QueryMetadata, error) {
queryDirs := make([]string, 0)
err := filepath.Walk(s.Source,
func(p string, f os.FileInfo, err error) error {
Expand Down Expand Up @@ -164,14 +179,21 @@ func (s *FilesystemSource) GetQueries(excludeQueries ExcludeQueries) ([]model.Qu
if !s.CheckType(query.Metadata["platform"]) {
continue
}
if checkQueryExclude(query.Metadata["id"], excludeQueries.ByIDs) ||
checkQueryExclude(query.Metadata["category"], excludeQueries.ByCategories) {
log.Debug().
Msgf("Excluding query ID: %s category: %s", query.Metadata["id"], query.Metadata["category"])
continue
}

queries = append(queries, query)
if len(queryFilter.IncludeQueries.ByIDs) > 0 {
if checkQueryInclude(query.Metadata["id"], queryFilter.IncludeQueries.ByIDs) {
queries = append(queries, query)
}
} else {
if checkQueryExclude(query.Metadata["id"], queryFilter.ExcludeQueries.ByIDs) ||
checkQueryExclude(query.Metadata["category"], queryFilter.ExcludeQueries.ByCategories) {
log.Debug().
Msgf("Excluding query ID: %s category: %s", query.Metadata["id"], query.Metadata["category"])
continue
}

queries = append(queries, query)
}
}

return queries, err
Expand Down
Loading