From 2423c01d92aa3362434865da2f8d55239650e5da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Cunha=20Martins?= Date: Fri, 13 Oct 2023 15:26:05 +0100 Subject: [PATCH 01/22] Experimental queries as ff with this commit we are change our system of experimental queries from a file that we should read for a feature flag --- internal/console/assets/scan-flags.json | 4 +- internal/console/scan.go | 2 +- pkg/engine/inspector_test.go | 4 +- pkg/engine/source/filesystem.go | 108 +++++---------- pkg/engine/source/filesystem_test.go | 123 +++++++----------- pkg/engine/source/source.go | 2 +- pkg/model/model.go | 3 +- pkg/remediation/scan.go | 23 ++-- pkg/scan/client.go | 2 +- pkg/scan/scan.go | 13 +- pkg/scanner/scanner_test.go | 2 +- .../experimental/test/metadata.json | 4 +- .../tested/tested_query/metadata.json | 22 ++-- 13 files changed, 115 insertions(+), 197 deletions(-) diff --git a/internal/console/assets/scan-flags.json b/internal/console/assets/scan-flags.json index aa3973fedc0..4b8b4644732 100644 --- a/internal/console/assets/scan-flags.json +++ b/internal/console/assets/scan-flags.json @@ -62,8 +62,8 @@ "experimental-queries": { "flagType": "multiStr", "shorthandFlag": "", - "defaultValue": null, - "usage": "include experimental queries (queries not yet thoroughly reviewed) by providing the path of the queries folder\ncan be provided multiple times or as a comma-separated string (platform/cloudProvider or platform)\nexample: 'terraform/databricks'\npossible values found in: '/assets/utils/experimental-queries.json'", + "defaultValue": "false", + "usage": "include experimental queries (queries not yet thoroughly reviewed) ", "validation": "validateMultiStr" }, "fail-on": { diff --git a/internal/console/scan.go b/internal/console/scan.go index 52524ae3b48..c9ea0e5f2d7 100644 --- a/internal/console/scan.go +++ b/internal/console/scan.go @@ -116,7 +116,7 @@ func getScanParameters(changedDefaultQueryPath, changedDefaultLibrariesPath bool ExcludeQueries: flags.GetMultiStrFlag(flags.ExcludeQueriesFlag), ExcludeResults: flags.GetMultiStrFlag(flags.ExcludeResultsFlag), ExcludeSeverities: flags.GetMultiStrFlag(flags.ExcludeSeveritiesFlag), - ExperimentalQueries: flags.GetMultiStrFlag(flags.ExperimentalQueriesFlag), + ExperimentalQueries: flags.GetBoolFlag(flags.ExperimentalQueriesFlag), IncludeQueries: flags.GetMultiStrFlag(flags.IncludeQueriesFlag), InputData: flags.GetStrFlag(flags.InputDataFlag), OutputName: flags.GetStrFlag(flags.OutputNameFlag), diff --git a/pkg/engine/inspector_test.go b/pkg/engine/inspector_test.go index 4e5b584d95b..87e9099700b 100644 --- a/pkg/engine/inspector_test.go +++ b/pkg/engine/inspector_test.go @@ -678,7 +678,7 @@ func TestShouldSkipFile(t *testing.T) { } func newInspectorInstance(t *testing.T, queryPath []string) *Inspector { - querySource := source.NewFilesystemSource(queryPath, []string{""}, []string{""}, filepath.FromSlash("./assets/libraries"), filepath.FromSlash("./assets/utils/experimental-queries.json")) + querySource := source.NewFilesystemSource(queryPath, []string{""}, []string{""}, filepath.FromSlash("./assets/libraries"), true) var vb = func(ctx *QueryContext, tracker Tracker, v interface{}, detector *detector.DetectLine) (*model.Vulnerability, error) { return &model.Vulnerability{}, nil @@ -701,7 +701,7 @@ type mockSource struct { } func (m *mockSource) GetQueries(queryFilter *source.QueryInspectorParameters) ([]model.QueryMetadata, error) { - sources := source.NewFilesystemSource(m.Source, []string{""}, []string{""}, filepath.FromSlash("./assets/libraries"), filepath.FromSlash("./assets/utils/experimental-queries.json")) + sources := source.NewFilesystemSource(m.Source, []string{""}, []string{""}, filepath.FromSlash("./assets/libraries"), true) return sources.GetQueries(queryFilter) } diff --git a/pkg/engine/source/filesystem.go b/pkg/engine/source/filesystem.go index eab3e6b5048..41f96f469f4 100644 --- a/pkg/engine/source/filesystem.go +++ b/pkg/engine/source/filesystem.go @@ -3,7 +3,6 @@ package source import ( "encoding/json" "fmt" - "io" "os" "path" "path/filepath" @@ -26,7 +25,7 @@ type FilesystemSource struct { Types []string CloudProviders []string Library string - ExperimentalQueries string + ExperimentalQueries bool } const ( @@ -45,7 +44,7 @@ const ( ) // NewFilesystemSource initializes a NewFilesystemSource with source to queries and types of queries to load -func NewFilesystemSource(source, types, cloudProviders []string, libraryPath, experimentalQueriesPath string) *FilesystemSource { +func NewFilesystemSource(source, types, cloudProviders []string, libraryPath string, experimentalQueries bool) *FilesystemSource { log.Debug().Msg("source.NewFilesystemSource()") if len(types) == 0 { @@ -65,7 +64,7 @@ func NewFilesystemSource(source, types, cloudProviders []string, libraryPath, ex Types: types, CloudProviders: cloudProviders, Library: filepath.FromSlash(libraryPath), - ExperimentalQueries: experimentalQueriesPath, + ExperimentalQueries: experimentalQueries, } } @@ -249,33 +248,8 @@ func checkQueryExclude(metadata map[string]interface{}, queryParameters *QueryIn // GetQueries walks a given filesource path returns all queries found in an array of // QueryMetadata struct func (s *FilesystemSource) GetQueries(queryParameters *QueryInspectorParameters) ([]model.QueryMetadata, error) { - experimentalQueriesPaths := make([]string, 0) - if s.ExperimentalQueries != "" { - experimentalQueriesFile, errOpeningFile := os.Open(s.ExperimentalQueries) - if errOpeningFile != nil { - return nil, errOpeningFile - } - - defer func(experimentalQueriesFile *os.File) { - errClosingFile := experimentalQueriesFile.Close() - if errClosingFile != nil { - log.Err(errClosingFile).Msg("Failed to close experimental queries file") - } - }(experimentalQueriesFile) - - byteValue, err := io.ReadAll(experimentalQueriesFile) - if err != nil { - return nil, err - } - - err = json.Unmarshal(byteValue, &experimentalQueriesPaths) - if err != nil { - return nil, err - } - } - - queryDirs, err := s.iterateSources(experimentalQueriesPaths, queryParameters) + queryDirs, err := s.iterateSources() if err != nil { return nil, err } @@ -285,7 +259,7 @@ func (s *FilesystemSource) GetQueries(queryParameters *QueryInspectorParameters) return queries, nil } -func (s *FilesystemSource) iterateSources(experimentalQueriesPaths []string, queryParameters *QueryInspectorParameters) ([]string, error) { +func (s *FilesystemSource) iterateSources() ([]string, error) { queryDirs := make([]string, 0) for _, source := range s.Source { @@ -300,19 +274,13 @@ func (s *FilesystemSource) iterateSources(experimentalQueriesPaths []string, que } querypathDir := filepath.Dir(p) - absQueryPathDir, err1 := filepath.Abs(querypathDir) - absQueriesPath, err2 := filepath.Abs(source) - if err1 == nil && err2 == nil { - var cleanPlatformCloudProviderDir string - cleanPlatformCloudProviderDir, err = filepath.Rel(absQueriesPath, absQueryPathDir) - if err == nil && isExperimental(querypathDir, cleanPlatformCloudProviderDir, experimentalQueriesPaths, queryParameters) { - queryDirs = append(queryDirs, querypathDir) - } else if err != nil { - return errors.Wrap(err, "Failed to get query relative path") - } - } else { - return errors.Wrap(err, "Failed to get query absolute path") + + if err == nil { + queryDirs = append(queryDirs, querypathDir) + } else if err != nil { + return errors.Wrap(err, "Failed to get query relative path") } + return nil }) if err != nil { @@ -323,32 +291,6 @@ func (s *FilesystemSource) iterateSources(experimentalQueriesPaths []string, que return queryDirs, nil } -func isExperimental( - querypathDir, cleanPlatformCloudProviderDir string, - experimentalQueriesPaths []string, - queryParameters *QueryInspectorParameters) bool { - cleanPlatformCloudProviderDir = filepath.FromSlash(cleanPlatformCloudProviderDir) - inExperimentalQueriesJSON := false - for _, queryPath := range experimentalQueriesPaths { - queryPath = filepath.FromSlash(queryPath) - if strings.Contains(querypathDir, queryPath) { - inExperimentalQueriesJSON = true - break - } - } - - inExperimentalQueriesFlag := false - for _, experimentalFlag := range queryParameters.ExperimentalQueries { - experimentalFlag = filepath.FromSlash(experimentalFlag) - if strings.HasPrefix(cleanPlatformCloudProviderDir, experimentalFlag) { - inExperimentalQueriesFlag = true - break - } - } - - return inExperimentalQueriesFlag || !inExperimentalQueriesJSON -} - // iterateQueryDirs iterates all query directories and reads the respective queries func (s *FilesystemSource) iterateQueryDirs(queryDirs []string, queryParameters *QueryInspectorParameters) []model.QueryMetadata { queries := make([]model.QueryMetadata, 0, len(queryDirs)) @@ -365,6 +307,10 @@ func (s *FilesystemSource) iterateQueryDirs(queryDirs []string, queryParameters continue } + if !queryParameters.ExperimentalQueries && query.Experimental { + continue + } + if !s.CheckType(query.Metadata["platform"]) { continue } @@ -449,13 +395,17 @@ func ReadQuery(queryDir string) (model.QueryMetadata, error) { aggregation = int(agg.(float64)) } + readExperimental, _ := metadata["experimental"].(string) + experimental := getExperimental(readExperimental) + return model.QueryMetadata{ - Query: path.Base(filepath.ToSlash(queryDir)), - Content: string(queryContent), - Metadata: metadata, - Platform: platform, - InputData: inputData, - Aggregation: aggregation, + Query: path.Base(filepath.ToSlash(queryDir)), + Content: string(queryContent), + Metadata: metadata, + Platform: platform, + InputData: inputData, + Aggregation: aggregation, + Experimental: experimental, }, nil } @@ -523,6 +473,14 @@ func getPlatform(metadataPlatform string) string { return "unknown" } +func getExperimental(experimental string) bool { + if experimental == "true" { + return true + } else { + return false + } +} + func readInputData(inputDataPath string) (string, error) { inputData, err := os.ReadFile(filepath.Clean(inputDataPath)) if err != nil { diff --git a/pkg/engine/source/filesystem_test.go b/pkg/engine/source/filesystem_test.go index 173396bd8cd..af4a516802e 100644 --- a/pkg/engine/source/filesystem_test.go +++ b/pkg/engine/source/filesystem_test.go @@ -28,7 +28,7 @@ func BenchmarkFilesystemSource_GetQueries(b *testing.B) { Types []string CloudProviders []string Library string - ExperimentalQueries string + ExperimentalQueries bool } tests := []struct { name string @@ -41,7 +41,7 @@ func BenchmarkFilesystemSource_GetQueries(b *testing.B) { Types: []string{""}, CloudProviders: []string{""}, Library: "./assets/libraries", - ExperimentalQueries: "./assets/utils/experimental-queries.json", + ExperimentalQueries: true, }, }, } @@ -74,7 +74,7 @@ func TestFilesystemSource_GetQueriesWithExclude(t *testing.T) { //nolint Types []string CloudProviders []string Library string - ExperimentalQueries string + ExperimentalQueries bool } tests := []struct { name string @@ -90,7 +90,7 @@ func TestFilesystemSource_GetQueriesWithExclude(t *testing.T) { //nolint fields: fields{ Source: []string{source_get_queries}, Types: []string{""}, CloudProviders: []string{""}, Library: "./assets/libraries", - ExperimentalQueries: "./assets/utils/experimental-queries.json", + ExperimentalQueries: true, }, excludeCategory: []string{}, excludeSeverities: []string{}, @@ -109,8 +109,9 @@ func TestFilesystemSource_GetQueriesWithExclude(t *testing.T) { //nolint "severity": model.SeverityHigh, "platform": "Terraform", }, - Platform: "terraform", - Aggregation: 1, + Platform: "terraform", + Aggregation: 1, + Experimental: false, }, }, wantErr: false, @@ -198,7 +199,7 @@ func TestFilesystemSource_GetQueriesWithInclude(t *testing.T) { Types []string CloudProviders []string Library string - ExperimentalQueries string + ExperimentalQueries bool } tests := []struct { name string @@ -212,7 +213,7 @@ func TestFilesystemSource_GetQueriesWithInclude(t *testing.T) { fields: fields{ Source: []string{source_get_queries}, Types: []string{""}, CloudProviders: []string{""}, Library: "./assets/libraries", - ExperimentalQueries: "./assets/utils/experimental-queries.json", + ExperimentalQueries: true, }, includeIDs: []string{"57b9893d-33b1-4419-bcea-b828fb87e318"}, want: []model.QueryMetadata{ @@ -229,8 +230,9 @@ func TestFilesystemSource_GetQueriesWithInclude(t *testing.T) { "severity": model.SeverityHigh, "platform": "Terraform", }, - Platform: "terraform", - Aggregation: 1, + Platform: "terraform", + Aggregation: 1, + Experimental: false, }, }, wantErr: false, @@ -291,7 +293,7 @@ func TestFilesystemSource_GetQueryLibrary(t *testing.T) { //nolint type fields struct { Source []string Library string - ExperimentalQueries string + ExperimentalQueries bool } type args struct { platform string @@ -308,7 +310,7 @@ func TestFilesystemSource_GetQueryLibrary(t *testing.T) { //nolint fields: fields{ Source: []string{"./assets/queries/template"}, Library: "./assets/libraries", - ExperimentalQueries: "./assets/utils/experimental-queries.json", + ExperimentalQueries: true, }, args: args{ platform: "terraform", @@ -321,7 +323,7 @@ func TestFilesystemSource_GetQueryLibrary(t *testing.T) { //nolint fields: fields{ Source: []string{"./assets/queries/template"}, Library: "./assets/libraries", - ExperimentalQueries: "./assets/utils/experimental-queries.json", + ExperimentalQueries: true, }, args: args{ platform: "common", @@ -334,7 +336,7 @@ func TestFilesystemSource_GetQueryLibrary(t *testing.T) { //nolint fields: fields{ Source: []string{"./assets/queries/template"}, Library: "./assets/libraries", - ExperimentalQueries: "./assets/utils/experimental-queries.json", + ExperimentalQueries: true, }, args: args{ platform: "cloudFormation", @@ -347,7 +349,7 @@ func TestFilesystemSource_GetQueryLibrary(t *testing.T) { //nolint fields: fields{ Source: []string{"./assets/queries/template"}, Library: "./assets/libraries", - ExperimentalQueries: "./assets/utils/experimental-queries.json", + ExperimentalQueries: true, }, args: args{ platform: "ansible", @@ -360,7 +362,7 @@ func TestFilesystemSource_GetQueryLibrary(t *testing.T) { //nolint fields: fields{ Source: []string{"./assets/queries/template"}, Library: "./assets/libraries", - ExperimentalQueries: "./assets/utils/experimental-queries.json", + ExperimentalQueries: true, }, args: args{ platform: "dockerfile", @@ -373,7 +375,7 @@ func TestFilesystemSource_GetQueryLibrary(t *testing.T) { //nolint fields: fields{ Source: []string{"./assets/queries/template"}, Library: "./assets/libraries", - ExperimentalQueries: "./assets/utils/experimental-queries.json", + ExperimentalQueries: true, }, args: args{ platform: "k8s", @@ -384,8 +386,9 @@ func TestFilesystemSource_GetQueryLibrary(t *testing.T) { //nolint { name: "get_generic_query_cicd", fields: fields{ - Source: []string{"./assets/queries/template"}, - Library: "./assets/libraries", + Source: []string{"./assets/queries/template"}, + Library: "./assets/libraries", + ExperimentalQueries: true, }, args: args{ platform: "cicd", @@ -398,7 +401,7 @@ func TestFilesystemSource_GetQueryLibrary(t *testing.T) { //nolint fields: fields{ Source: []string{"./assets/queries/template"}, Library: "./assets/libraries", - ExperimentalQueries: "./assets/utils/experimental-queries.json", + ExperimentalQueries: true, }, args: args{ platform: "unknown", @@ -435,12 +438,11 @@ func TestFilesystemSource_GetQueries(t *testing.T) { require.NoError(t, err) type fields struct { - Source []string - Types []string - CloudProviders []string - Library string - ExperimentalQueries string - ExperimentalQueriesFlag []string + Source []string + Types []string + CloudProviders []string + Library string + ExperimentalQueries bool } tests := []struct { name string @@ -452,9 +454,8 @@ func TestFilesystemSource_GetQueries(t *testing.T) { name: "get_queries_1", fields: fields{ Source: []string{source_get_queries, source_get_queries}, Types: []string{""}, CloudProviders: []string{""}, - Library: "./assets/libraries", - ExperimentalQueries: "./assets/utils/experimental-queries.json", - ExperimentalQueriesFlag: []string{}, + Library: "./assets/libraries", + ExperimentalQueries: false, }, want: []model.QueryMetadata{ { @@ -470,8 +471,9 @@ func TestFilesystemSource_GetQueries(t *testing.T) { "severity": model.SeverityHigh, "platform": "Terraform", }, - Platform: "terraform", - Aggregation: 1, + Platform: "terraform", + Aggregation: 1, + Experimental: false, }, { Query: "all_auth_users_get_read_access", @@ -486,8 +488,9 @@ func TestFilesystemSource_GetQueries(t *testing.T) { "severity": model.SeverityHigh, "platform": "Terraform", }, - Platform: "terraform", - Aggregation: 1, + Platform: "terraform", + Aggregation: 1, + Experimental: false, }, }, wantErr: false, @@ -495,50 +498,18 @@ func TestFilesystemSource_GetQueries(t *testing.T) { { name: "get_queries_error", fields: fields{ - Source: []string{"../no-path"}, - ExperimentalQueries: "./assets/utils/experimental-queries.json", - ExperimentalQueriesFlag: []string{}, + Source: []string{"../no-path"}, + ExperimentalQueries: false, }, want: nil, wantErr: true, }, - { - name: "get_queries_experimental_no_flag", - fields: fields{ - Source: []string{source_get_queries_experimental}, Types: []string{""}, CloudProviders: []string{""}, - Library: "./assets/libraries", - ExperimentalQueries: "./test/fixtures/test_experimental_queries/utils/experimental-queries.json", - ExperimentalQueriesFlag: []string{"tested"}, - }, - want: []model.QueryMetadata{ - { - Query: "tested_query", - Content: string(contentByteExperimental), - InputData: "{}", - Metadata: map[string]interface{}{ - "category": "Insecure Configurations", - "descriptionText": "SSL Client Certificate should be enabled", - "descriptionUrl": "https://docs.ansible.com/ansible/2.8/modules/aws_api_gateway_module.html", - "id": "b47b98ab-e481-4a82-8bb1-1ab39fd36e34", - "queryName": "API Gateway Without SSL Certificate", - "severity": model.SeverityMedium, - "platform": "Ansible", - "cloudProvider": "aws", - "descriptionID": "82608f36", - }, - Platform: "ansible", - Aggregation: 1, - }, - }, - wantErr: false, - }, { name: "get_queries_experimental_with_flag", fields: fields{ Source: []string{source_get_queries_experimental}, Types: []string{""}, CloudProviders: []string{""}, - Library: "./assets/libraries", - ExperimentalQueries: "./test/fixtures/test_experimental_queries/utils/experimental-queries.json", - ExperimentalQueriesFlag: []string{"experimental"}, + Library: "./assets/libraries", + ExperimentalQueries: true, }, want: []model.QueryMetadata{ { @@ -555,9 +526,11 @@ func TestFilesystemSource_GetQueries(t *testing.T) { "platform": "Ansible", "cloudProvider": "aws", "descriptionID": "82608f36", + "experimental": "true", }, - Platform: "ansible", - Aggregation: 1, + Platform: "ansible", + Aggregation: 1, + Experimental: true, }, { Query: "tested_query", @@ -573,9 +546,11 @@ func TestFilesystemSource_GetQueries(t *testing.T) { "platform": "Ansible", "cloudProvider": "aws", "descriptionID": "82608f36", + "experimental": "true", }, - Platform: "ansible", - Aggregation: 1, + Platform: "ansible", + Aggregation: 1, + Experimental: true, }, }, wantErr: false, @@ -591,7 +566,7 @@ func TestFilesystemSource_GetQueries(t *testing.T) { ByIDs: []string{}, ByCategories: []string{}, }, - ExperimentalQueries: tt.fields.ExperimentalQueriesFlag, + ExperimentalQueries: tt.fields.ExperimentalQueries, InputDataPath: "", } got, err := s.GetQueries(&filter) diff --git a/pkg/engine/source/source.go b/pkg/engine/source/source.go index 2b70137ffc9..fb9912b0d3a 100644 --- a/pkg/engine/source/source.go +++ b/pkg/engine/source/source.go @@ -15,7 +15,7 @@ import ( type QueryInspectorParameters struct { IncludeQueries IncludeQueries ExcludeQueries ExcludeQueries - ExperimentalQueries []string + ExperimentalQueries bool InputDataPath string BomQueries bool } diff --git a/pkg/model/model.go b/pkg/model/model.go index fb6aaa03280..8abe34bd083 100644 --- a/pkg/model/model.go +++ b/pkg/model/model.go @@ -141,7 +141,8 @@ type QueryMetadata struct { Platform string // special field for generic queries // represents how many queries are aggregated into a single rego file - Aggregation int + Aggregation int + Experimental bool } // Vulnerability is a representation of a detected vulnerability in scanned files diff --git a/pkg/remediation/scan.go b/pkg/remediation/scan.go index 48f53e57c92..79d51c399da 100644 --- a/pkg/remediation/scan.go +++ b/pkg/remediation/scan.go @@ -4,7 +4,6 @@ import ( "context" "encoding/json" "errors" - "path/filepath" "time" "github.com/Checkmarx/kics/pkg/engine" @@ -14,7 +13,6 @@ import ( "github.com/open-policy-agent/opa/topdown" "github.com/Checkmarx/kics/internal/console/flags" - consoleHelpers "github.com/Checkmarx/kics/internal/console/helpers" "github.com/Checkmarx/kics/internal/tracker" "github.com/Checkmarx/kics/pkg/engine/source" "github.com/Checkmarx/kics/pkg/parser" @@ -187,12 +185,13 @@ func runQuery(r *runQueryInfo) []model.Vulnerability { func initScan(queryID string) (*engine.Inspector, error) { scanParams := &scan.Parameters{ - QueriesPath: flags.GetMultiStrFlag(flags.QueriesPath), - Platform: flags.GetMultiStrFlag(flags.TypeFlag), - CloudProvider: flags.GetMultiStrFlag(flags.CloudProviderFlag), - LibrariesPath: flags.GetStrFlag(flags.LibrariesPath), - PreviewLines: flags.GetIntFlag(flags.PreviewLinesFlag), - QueryExecTimeout: flags.GetIntFlag(flags.QueryExecTimeoutFlag), + QueriesPath: flags.GetMultiStrFlag(flags.QueriesPath), + Platform: flags.GetMultiStrFlag(flags.TypeFlag), + CloudProvider: flags.GetMultiStrFlag(flags.CloudProviderFlag), + LibrariesPath: flags.GetStrFlag(flags.LibrariesPath), + PreviewLines: flags.GetIntFlag(flags.PreviewLinesFlag), + QueryExecTimeout: flags.GetIntFlag(flags.QueryExecTimeoutFlag), + ExperimentalQueries: flags.GetBoolFlag(flags.ExperimentalQueriesFlag), } c := &scan.Client{ @@ -205,18 +204,12 @@ func initScan(queryID string) (*engine.Inspector, error) { return &engine.Inspector{}, err } - experimentalQueries, err := consoleHelpers.GetDefaultExperimentalPath(filepath.FromSlash("./assets/utils/experimental-queries.json")) - if err != nil { - log.Err(err) - return &engine.Inspector{}, err - } - queriesSource := source.NewFilesystemSource( c.ScanParams.QueriesPath, c.ScanParams.Platform, c.ScanParams.CloudProvider, c.ScanParams.LibrariesPath, - experimentalQueries) + c.ScanParams.ExperimentalQueries) includeQueries := source.IncludeQueries{ ByIDs: []string{queryID}, diff --git a/pkg/scan/client.go b/pkg/scan/client.go index 55b07a72cb9..18484ddf8d3 100644 --- a/pkg/scan/client.go +++ b/pkg/scan/client.go @@ -21,7 +21,7 @@ type Parameters struct { ExcludeQueries []string ExcludeResults []string ExcludeSeverities []string - ExperimentalQueries []string + ExperimentalQueries bool IncludeQueries []string InputData string OutputName string diff --git a/pkg/scan/scan.go b/pkg/scan/scan.go index 8c9f76f38c2..1af9c4fba52 100644 --- a/pkg/scan/scan.go +++ b/pkg/scan/scan.go @@ -3,11 +3,7 @@ package scan import ( "context" - "os" - "path/filepath" - "github.com/Checkmarx/kics/assets" - consoleHelpers "github.com/Checkmarx/kics/internal/console/helpers" "github.com/Checkmarx/kics/pkg/engine" "github.com/Checkmarx/kics/pkg/engine/provider" "github.com/Checkmarx/kics/pkg/engine/secrets" @@ -26,6 +22,7 @@ import ( "github.com/Checkmarx/kics/pkg/resolver" "github.com/Checkmarx/kics/pkg/resolver/helm" "github.com/Checkmarx/kics/pkg/scanner" + "os" "github.com/rs/zerolog/log" ) @@ -58,18 +55,12 @@ func (c *Client) initScan(ctx context.Context) (*executeScanParameters, error) { return nil, nil } - experimentalQueries, err := consoleHelpers.GetDefaultExperimentalPath(filepath.FromSlash("./assets/utils/experimental-queries.json")) - if err != nil { - log.Err(err) - return nil, err - } - querySource := source.NewFilesystemSource( c.ScanParams.QueriesPath, c.ScanParams.Platform, c.ScanParams.CloudProvider, c.ScanParams.LibrariesPath, - experimentalQueries) + c.ScanParams.ExperimentalQueries) queryFilter := c.createQueryFilter() diff --git a/pkg/scanner/scanner_test.go b/pkg/scanner/scanner_test.go index d479778e2cf..5dddffaff5a 100644 --- a/pkg/scanner/scanner_test.go +++ b/pkg/scanner/scanner_test.go @@ -97,7 +97,7 @@ func createServices(types, cloudProviders []string) (serviceSlice, *storage.Memo } t := &tracker.CITracker{} - querySource := source.NewFilesystemSource(sourcePath, types, cloudProviders, filepath.FromSlash("../../assets/libraries"), filepath.FromSlash("../../assets/utils/experimental-queries.json")) + querySource := source.NewFilesystemSource(sourcePath, types, cloudProviders, filepath.FromSlash("../../assets/libraries"), true) inspector, err := engine.NewInspector(context.Background(), querySource, engine.DefaultVulnerabilityBuilder, diff --git a/test/fixtures/test_experimental_queries/experimental_queries_queries/experimental/test/metadata.json b/test/fixtures/test_experimental_queries/experimental_queries_queries/experimental/test/metadata.json index 44f7883c443..43a91062a2b 100644 --- a/test/fixtures/test_experimental_queries/experimental_queries_queries/experimental/test/metadata.json +++ b/test/fixtures/test_experimental_queries/experimental_queries_queries/experimental/test/metadata.json @@ -7,6 +7,6 @@ "descriptionUrl": "https://docs.ansible.com/ansible/2.8/modules/aws_api_gateway_module.html", "platform": "Ansible", "descriptionID": "82608f36", - "cloudProvider": "aws" + "cloudProvider": "aws", + "experimental": "true" } - \ No newline at end of file diff --git a/test/fixtures/test_experimental_queries/experimental_queries_queries/tested/tested_query/metadata.json b/test/fixtures/test_experimental_queries/experimental_queries_queries/tested/tested_query/metadata.json index 96b8f4bcc79..c432788d1ce 100644 --- a/test/fixtures/test_experimental_queries/experimental_queries_queries/tested/tested_query/metadata.json +++ b/test/fixtures/test_experimental_queries/experimental_queries_queries/tested/tested_query/metadata.json @@ -1,12 +1,12 @@ { - "id": "b47b98ab-e481-4a82-8bb1-1ab39fd36e34", - "queryName": "API Gateway Without SSL Certificate", - "severity": "MEDIUM", - "category": "Insecure Configurations", - "descriptionText": "SSL Client Certificate should be enabled", - "descriptionUrl": "https://docs.ansible.com/ansible/2.8/modules/aws_api_gateway_module.html", - "platform": "Ansible", - "descriptionID": "82608f36", - "cloudProvider": "aws" - } - \ No newline at end of file + "id": "b47b98ab-e481-4a82-8bb1-1ab39fd36e34", + "queryName": "API Gateway Without SSL Certificate", + "severity": "MEDIUM", + "category": "Insecure Configurations", + "descriptionText": "SSL Client Certificate should be enabled", + "descriptionUrl": "https://docs.ansible.com/ansible/2.8/modules/aws_api_gateway_module.html", + "platform": "Ansible", + "descriptionID": "82608f36", + "cloudProvider": "aws", + "experimental": "true" +} From 04a5a883b8a9f5316acc1f80a04fcbb2613fa0d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Cunha=20Martins?= Date: Mon, 16 Oct 2023 10:06:03 +0100 Subject: [PATCH 02/22] move casting logic to auxiliary function --- pkg/engine/source/filesystem.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pkg/engine/source/filesystem.go b/pkg/engine/source/filesystem.go index 41f96f469f4..ec8132be26f 100644 --- a/pkg/engine/source/filesystem.go +++ b/pkg/engine/source/filesystem.go @@ -395,8 +395,7 @@ func ReadQuery(queryDir string) (model.QueryMetadata, error) { aggregation = int(agg.(float64)) } - readExperimental, _ := metadata["experimental"].(string) - experimental := getExperimental(readExperimental) + experimental := getExperimental(metadata["experimental"]) return model.QueryMetadata{ Query: path.Base(filepath.ToSlash(queryDir)), @@ -473,8 +472,9 @@ func getPlatform(metadataPlatform string) string { return "unknown" } -func getExperimental(experimental string) bool { - if experimental == "true" { +func getExperimental(experimental interface{}) bool { + readExperimental, _ := experimental.(string) + if readExperimental == "true" { return true } else { return false From 5c6e0d880e9e024a05589d9440b59bf6ae9d2fca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Cunha=20Martins?= Date: Mon, 16 Oct 2023 11:13:49 +0100 Subject: [PATCH 03/22] remove experimental from docker file --- Dockerfile | 1 - docs/commands.md | 2 +- internal/console/helpers/helpers.go | 12 ------------ 3 files changed, 1 insertion(+), 14 deletions(-) diff --git a/Dockerfile b/Dockerfile index 38dd8c7611a..b79e429be81 100644 --- a/Dockerfile +++ b/Dockerfile @@ -67,7 +67,6 @@ RUN wget https://github.com/GoogleCloudPlatform/terraformer/releases/download/0. COPY --from=build_env /app/bin/kics /app/bin/kics COPY --from=build_env /app/assets/queries /app/bin/assets/queries COPY --from=build_env /app/assets/libraries/* /app/bin/assets/libraries/ -COPY --from=build_env /app/assets/utils/* /app/bin/assets/utils/ WORKDIR /app/bin diff --git a/docs/commands.md b/docs/commands.md index ad6f93af765..1f5afc447b9 100644 --- a/docs/commands.md +++ b/docs/commands.md @@ -79,7 +79,7 @@ Flags: 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 - cannot be provided with query exclusion flags + c[Dockerfile](..%2FDockerfile)annot be provided with query exclusion flags can be provided multiple times or as a comma separated string example: 'e69890e6-fce5-461d-98ad-cb98318dfc96,4728cd65-a20c-49da-8b31-9c08b423e4db' --input-data string path to query input data files diff --git a/internal/console/helpers/helpers.go b/internal/console/helpers/helpers.go index 96942ff9189..1209acd033d 100644 --- a/internal/console/helpers/helpers.go +++ b/internal/console/helpers/helpers.go @@ -140,18 +140,6 @@ func GetDefaultQueryPath(queriesPath string) (string, error) { return queriesDirectory, nil } -// GetDefaultExperimentalPath returns the default Experimental path -func GetDefaultExperimentalPath(experimentalQueriesPath string) (string, error) { - log.Debug().Msg("helpers.GetDefaultExperimentalPath()") - experimentalQueriesFile, err := GetFullPath(experimentalQueriesPath) - if err != nil { - return "", err - } - - log.Debug().Msgf("Experimental Queries found in %s", experimentalQueriesFile) - return experimentalQueriesFile, nil -} - // GetFulPath returns the full path of a partial path used for queries or experimental queries json path func GetFullPath(partialPath string) (string, error) { executableDirPath := GetExecutableDirectory() From 38de59ad1fe96422ebe42f4985ed5ebaff01197f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Cunha=20Martins?= Date: Mon, 16 Oct 2023 14:47:54 +0100 Subject: [PATCH 04/22] fix flag information --- docs/commands.md | 28 ++++++++++++++++--------- internal/console/assets/scan-flags.json | 2 +- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/docs/commands.md b/docs/commands.md index 1f5afc447b9..8f3f0d2d62c 100644 --- a/docs/commands.md +++ b/docs/commands.md @@ -1,6 +1,7 @@ # KICS CLI -KICS is a command line tool, and should be used in a terminal. The next section describes the usage, the same help content is displayed when kics is provided with the `--help` flag. +KICS is a command line tool, and should be used in a terminal. The next section describes the usage, the same help +content is displayed when kics is provided with the `--help` flag. ## KICS Command @@ -67,10 +68,7 @@ Flags: can be provided multiple times or as a comma separated string example: 'info,low' possible values: 'high, medium, low, info, trace' - --experimental-queries strings include experimental queries (queries not yet thoroughly reviewed) by providing the path of the queries folder - can be provided multiple times or as a comma-separated string (platform/cloudProvider or platform) - example: 'terraform/databricks' - possible values found in: '/assets/utils/experimental-queries.json' + --experimental-queries strings include experimental queries (queries not yet thoroughly reviewed) --fail-on strings which kind of results should return an exit code different from 0 accepts: high, medium, low and info example: "high,low" (default [high,medium,low,info]) @@ -79,7 +77,7 @@ Flags: 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 - c[Dockerfile](..%2FDockerfile)annot be provided with query exclusion flags + cannot be provided with query exclusion flags can be provided multiple times or as a comma separated string example: 'e69890e6-fce5-461d-98ad-cb98318dfc96,4728cd65-a20c-49da-8b31-9c08b423e4db' --input-data string path to query input data files @@ -134,13 +132,22 @@ Flags: The other commands have no further options. ## Exclude Paths -By default, KICS excludes paths specified in the .gitignore file in the root of the repository. To disable this behavior, use flag `--exclude-gitignore`. + +By default, KICS excludes paths specified in the .gitignore file in the root of the repository. To disable this +behavior, use flag `--exclude-gitignore`. ## Library Flag Usage -As mentioned above, the library flag (`-b` or `--libraries-path`) refers to the directory with libraries. The functions need to be grouped by platform and the library file name should follow the format: `.rego` to be loaded by KICS. It doesn't matter your directory structure. In other words, for example, if you want to indicate a directory that contains a library for your terraform queries, you should group your functions (used in your terraform queries) in a file named `terraform.rego` wherever you want. +As mentioned above, the library flag (`-b` or `--libraries-path`) refers to the directory with libraries. The functions +need to be grouped by platform and the library file name should follow the format: `.rego` to be loaded by +KICS. It doesn't matter your directory structure. In other words, for example, if you want to indicate a directory that +contains a library for your terraform queries, you should group your functions (used in your terraform queries) in a +file named `terraform.rego` wherever you want. -This will merge the custom libraries found on the flag's path with KICS's default libraries. Note that any functions declared in a custom library with the same signature as an existing function in the [default libraries](https://github.com/Checkmarx/kics/tree/master/assets/libraries) will cause **the default library function to be overwritten by the custom definition provided**. +This will merge the custom libraries found on the flag's path with KICS's default libraries. Note that any functions +declared in a custom library with the same signature as an existing function in +the [default libraries](https://github.com/Checkmarx/kics/tree/master/assets/libraries) will cause **the default library +function to be overwritten by the custom definition provided**. --- @@ -154,7 +161,8 @@ You can only enable one profiler at a time, CPU or MEM. ## Disable Crash Report -You can disable KICS crash report to [sentry.io](https://sentry.io) with `DISABLE_CRASH_REPORT` environment variable set to `0` or `false` e.g: +You can disable KICS crash report to [sentry.io](https://sentry.io) with `DISABLE_CRASH_REPORT` environment variable set +to `0` or `false` e.g: ```sh DISABLE_CRASH_REPORT=0 ./bin/kics version diff --git a/internal/console/assets/scan-flags.json b/internal/console/assets/scan-flags.json index 4b8b4644732..c66928b1fdc 100644 --- a/internal/console/assets/scan-flags.json +++ b/internal/console/assets/scan-flags.json @@ -63,7 +63,7 @@ "flagType": "multiStr", "shorthandFlag": "", "defaultValue": "false", - "usage": "include experimental queries (queries not yet thoroughly reviewed) ", + "usage": "include experimental queries (queries not yet thoroughly reviewed)", "validation": "validateMultiStr" }, "fail-on": { From df2196e915bdf68089cce590db0f306899ee9675 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Cunha=20Martins?= Date: Mon, 16 Oct 2023 15:20:57 +0100 Subject: [PATCH 05/22] wip --- docs/commands.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/commands.md b/docs/commands.md index 8f3f0d2d62c..e7d4561d728 100644 --- a/docs/commands.md +++ b/docs/commands.md @@ -68,7 +68,7 @@ Flags: can be provided multiple times or as a comma separated string example: 'info,low' possible values: 'high, medium, low, info, trace' - --experimental-queries strings include experimental queries (queries not yet thoroughly reviewed) + --experimental-queries strings include experimental queries (queries not yet thoroughly reviewed) --fail-on strings which kind of results should return an exit code different from 0 accepts: high, medium, low and info example: "high,low" (default [high,medium,low,info]) @@ -138,9 +138,9 @@ behavior, use flag `--exclude-gitignore`. ## Library Flag Usage -As mentioned above, the library flag (`-b` or `--libraries-path`) refers to the directory with libraries. The functions +As mentioned above, the library flag (`-b` or `--libraries-path`) refers to the directory with libraries. The functions need to be grouped by platform and the library file name should follow the format: `.rego` to be loaded by -KICS. It doesn't matter your directory structure. In other words, for example, if you want to indicate a directory that +KICS. It doesn't matter your directory structure. In other words, for example, if you want to indicate a directory that contains a library for your terraform queries, you should group your functions (used in your terraform queries) in a file named `terraform.rego` wherever you want. From ee213e5decfb81db2ac3d3eb209a4647d058deab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Cunha=20Martins?= Date: Mon, 16 Oct 2023 15:23:44 +0100 Subject: [PATCH 06/22] wip --- docs/commands.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/commands.md b/docs/commands.md index e7d4561d728..419e7a9d44d 100644 --- a/docs/commands.md +++ b/docs/commands.md @@ -68,7 +68,7 @@ Flags: can be provided multiple times or as a comma separated string example: 'info,low' possible values: 'high, medium, low, info, trace' - --experimental-queries strings include experimental queries (queries not yet thoroughly reviewed) + --experimental-queries include experimental queries (queries not yet thoroughly reviewed) --fail-on strings which kind of results should return an exit code different from 0 accepts: high, medium, low and info example: "high,low" (default [high,medium,low,info]) From 672824c6173fee5cbf4bc248811e314f01b31f88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Cunha=20Martins?= Date: Mon, 16 Oct 2023 16:25:55 +0100 Subject: [PATCH 07/22] wip --- e2e/fixtures/assets/scan_help | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/e2e/fixtures/assets/scan_help b/e2e/fixtures/assets/scan_help index d583c415e36..271b72b5b5e 100644 --- a/e2e/fixtures/assets/scan_help +++ b/e2e/fixtures/assets/scan_help @@ -28,10 +28,7 @@ Flags: --exclude-type strings case insensitive list of platform types not to scan (Ansible, AzureResourceManager, Buildah, CICD, CloudFormation, Crossplane, DockerCompose, Dockerfile, GRPC, GoogleDeploymentManager, Knative, Kubernetes, OpenAPI, Pulumi, ServerlessFW, Terraform) cannot be provided with type inclusion flags - --experimental-queries strings include experimental queries (queries not yet thoroughly reviewed) by providing the path of the queries folder - can be provided multiple times or as a comma-separated string (platform/cloudProvider or platform) - example: 'terraform/databricks' - possible values found in: '/assets/utils/experimental-queries.json' + --experimental-queries include experimental queries (queries not yet thoroughly reviewed) --fail-on strings which kind of results should return an exit code different from 0 accepts: high, medium, low and info example: "high,low" (default [high,medium,low,info]) From 1317d676b451d54931b360e86813c4abe6cb4252 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Cunha=20Martins?= Date: Mon, 16 Oct 2023 17:14:29 +0100 Subject: [PATCH 08/22] wip --- docs/dockerhub.md | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/docs/dockerhub.md b/docs/dockerhub.md index 6a09fd8865a..d65bc137837 100644 --- a/docs/dockerhub.md +++ b/docs/dockerhub.md @@ -104,10 +104,7 @@ Flags: --exclude-severities strings exclude results by providing the severity of a result can be provided multiple times or as a comma separated string example: 'info,low' - --experimental-queries strings include experimental queries (queries not yet thoroughly reviewed) by providing the path of the queries folder - can be provided multiple times or as a comma-separated string (platform/cloudProvider or platform) - example: 'terraform/databricks' - possible values found in: '/assets/utils/experimental-queries.json' + --experimental-queries include experimental queries (queries not yet thoroughly reviewed) --fail-on strings which kind of results should return an exit code different from 0 accepts: high, medium, low and info example: "high,low" (default [high,medium,low,info]) From d3a6af0fe710b936dd4205a3663f5dc55ebf427a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Cunha=20Martins?= Date: Mon, 16 Oct 2023 17:53:28 +0100 Subject: [PATCH 09/22] wip --- docs/commands.md | 2 +- docs/dockerhub.md | 2 +- internal/console/assets/scan-flags.json | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/commands.md b/docs/commands.md index 419e7a9d44d..dc6e1fb505b 100644 --- a/docs/commands.md +++ b/docs/commands.md @@ -68,7 +68,7 @@ Flags: can be provided multiple times or as a comma separated string example: 'info,low' possible values: 'high, medium, low, info, trace' - --experimental-queries include experimental queries (queries not yet thoroughly reviewed) + --experimental-queries include experimental queries (queries not yet thoroughly reviewed) (default [false]) --fail-on strings which kind of results should return an exit code different from 0 accepts: high, medium, low and info example: "high,low" (default [high,medium,low,info]) diff --git a/docs/dockerhub.md b/docs/dockerhub.md index d65bc137837..6c30d17f3fe 100644 --- a/docs/dockerhub.md +++ b/docs/dockerhub.md @@ -104,7 +104,7 @@ Flags: --exclude-severities strings exclude results by providing the severity of a result can be provided multiple times or as a comma separated string example: 'info,low' - --experimental-queries include experimental queries (queries not yet thoroughly reviewed) + --experimental-queries include experimental queries (queries not yet thoroughly reviewed) (default [false]) --fail-on strings which kind of results should return an exit code different from 0 accepts: high, medium, low and info example: "high,low" (default [high,medium,low,info]) diff --git a/internal/console/assets/scan-flags.json b/internal/console/assets/scan-flags.json index c66928b1fdc..4cece324975 100644 --- a/internal/console/assets/scan-flags.json +++ b/internal/console/assets/scan-flags.json @@ -60,7 +60,7 @@ "usage": "include bill of materials (BoM) in results output" }, "experimental-queries": { - "flagType": "multiStr", + "flagType": "bool", "shorthandFlag": "", "defaultValue": "false", "usage": "include experimental queries (queries not yet thoroughly reviewed)", From 9239e411db19681378c8246266f6f24f59a1cd88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Cunha=20Martins?= Date: Mon, 16 Oct 2023 18:28:56 +0100 Subject: [PATCH 10/22] wip --- internal/console/assets/scan-flags.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/internal/console/assets/scan-flags.json b/internal/console/assets/scan-flags.json index 4cece324975..fb7164209fa 100644 --- a/internal/console/assets/scan-flags.json +++ b/internal/console/assets/scan-flags.json @@ -63,8 +63,7 @@ "flagType": "bool", "shorthandFlag": "", "defaultValue": "false", - "usage": "include experimental queries (queries not yet thoroughly reviewed)", - "validation": "validateMultiStr" + "usage": "include experimental queries (queries not yet thoroughly reviewed)" }, "fail-on": { "flagType": "multiStr", From d272ae6f3ea2c13b3537157e324edbdb54093e1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Cunha=20Martins?= Date: Tue, 17 Oct 2023 09:57:23 +0100 Subject: [PATCH 11/22] fix e2e --- e2e/fixtures/assets/scan_help | 114 +++++++++++++++++----------------- 1 file changed, 57 insertions(+), 57 deletions(-) diff --git a/e2e/fixtures/assets/scan_help b/e2e/fixtures/assets/scan_help index 271b72b5b5e..4531f28b2c5 100644 --- a/e2e/fixtures/assets/scan_help +++ b/e2e/fixtures/assets/scan_help @@ -2,63 +2,63 @@ Usage: kics scan [flags] Flags: - -m, --bom include bill of materials (BoM) in results output - --cloud-provider strings list of cloud providers to scan (alicloud, aws, azure, gcp) - --config string path to configuration file - --disable-full-descriptions disable request for full descriptions and use default vulnerability descriptions - --disable-secrets disable secrets scanning - --exclude-categories strings exclude categories by providing its name - cannot be provided with query inclusion flags - can be provided multiple times or as a comma separated string - example: 'Access control,Best practices' - --exclude-gitignore disables the exclusion of paths specified within .gitignore file - -e, --exclude-paths strings exclude paths from scan - supports glob and can be provided multiple times or as a quoted comma separated string - example: './shouldNotScan/*,somefile.txt' - --exclude-queries strings exclude queries by providing the query ID - cannot be provided with query inclusion flags - can be provided multiple times or as a comma separated string - example: 'e69890e6-fce5-461d-98ad-cb98318dfc96,4728cd65-a20c-49da-8b31-9c08b423e4db' - -x, --exclude-results strings exclude results by providing the similarity ID of a result - can be provided multiple times or as a comma separated string - example: 'fec62a97d569662093dbb9739360942f...,31263s5696620s93dbb973d9360942fc2a...' - --exclude-severities strings exclude results by providing the severity of a result - can be provided multiple times or as a comma separated string - example: 'info,low' - --exclude-type strings case insensitive list of platform types not to scan - (Ansible, AzureResourceManager, Buildah, CICD, CloudFormation, Crossplane, DockerCompose, Dockerfile, GRPC, GoogleDeploymentManager, Knative, Kubernetes, OpenAPI, Pulumi, ServerlessFW, Terraform) - cannot be provided with type inclusion flags - --experimental-queries include experimental queries (queries not yet thoroughly reviewed) - --fail-on strings which kind of results should return an exit code different from 0 - accepts: high, medium, low and info - example: "high,low" (default [high,medium,low,info]) - -h, --help help for scan - --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 - cannot be provided with query exclusion flags - can be provided multiple times or as a comma separated string - example: 'e69890e6-fce5-461d-98ad-cb98318dfc96,4728cd65-a20c-49da-8b31-9c08b423e4db' - --input-data string path to query input data files - -b, --libraries-path string path to directory with libraries (default "./assets/libraries") - --minimal-ui simplified version of CLI output - --no-progress hides the progress bar - --output-name string name used on report creations (default "results") - -o, --output-path string directory path to store reports - -p, --path strings paths or directories to scan - example: "./somepath,somefile.txt" - --payload-lines adds line information inside the payload when printing the payload file - -d, --payload-path string path to store internal representation JSON file - --preview-lines int number of lines to be display in CLI results (min: 1, max: 30) (default 3) - -q, --queries-path strings paths to directory with queries (default [./assets/queries]) - --report-formats strings formats in which the results will be exported (all, asff, codeclimate, csv, cyclonedx, glsast, html, json, junit, pdf, sarif, sonarqube) (default [json]) - -r, --secrets-regexes-path string path to secrets regex rules configuration file - --terraform-vars-path string path where terraform variables are present - --timeout int number of seconds the query has to execute before being canceled (default 60) - -t, --type strings case insensitive list of platform types to scan - (Ansible, AzureResourceManager, Buildah, CICD, CloudFormation, Crossplane, DockerCompose, Dockerfile, GRPC, GoogleDeploymentManager, Knative, Kubernetes, OpenAPI, Pulumi, ServerlessFW, Terraform) - cannot be provided with type exclusion flags + -m, --bom include bill of materials (BoM) in results output + --cloud-provider strings list of cloud providers to scan (alicloud, aws, azure, gcp) + --config string path to configuration file + --disable-full-descriptions disable request for full descriptions and use default vulnerability descriptions + --disable-secrets disable secrets scanning + --exclude-categories strings exclude categories by providing its name + cannot be provided with query inclusion flags + can be provided multiple times or as a comma separated string + example: 'Access control,Best practices' + --exclude-gitignore disables the exclusion of paths specified within .gitignore file + -e, --exclude-paths strings exclude paths from scan + supports glob and can be provided multiple times or as a quoted comma separated string + example: './shouldNotScan/*,somefile.txt' + --exclude-queries strings exclude queries by providing the query ID + cannot be provided with query inclusion flags + can be provided multiple times or as a comma separated string + example: 'e69890e6-fce5-461d-98ad-cb98318dfc96,4728cd65-a20c-49da-8b31-9c08b423e4db' + -x, --exclude-results strings exclude results by providing the similarity ID of a result + can be provided multiple times or as a comma separated string + example: 'fec62a97d569662093dbb9739360942f...,31263s5696620s93dbb973d9360942fc2a...' + --exclude-severities strings exclude results by providing the severity of a result + can be provided multiple times or as a comma separated string + example: 'info,low' + --exclude-type strings case insensitive list of platform types not to scan + (Ansible, AzureResourceManager, Buildah, CICD, CloudFormation, Crossplane, DockerCompose, Dockerfile, GRPC, GoogleDeploymentManager, Knative, Kubernetes, OpenAPI, Pulumi, ServerlessFW, Terraform) + cannot be provided with type inclusion flags + --experimental-queries include experimental queries (queries not yet thoroughly reviewed) + --fail-on strings which kind of results should return an exit code different from 0 + accepts: high, medium, low and info + example: "high,low" (default [high,medium,low,info]) + -h, --help help for scan + --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 + cannot be provided with query exclusion flags + can be provided multiple times or as a comma separated string + example: 'e69890e6-fce5-461d-98ad-cb98318dfc96,4728cd65-a20c-49da-8b31-9c08b423e4db' + --input-data string path to query input data files + -b, --libraries-path string path to directory with libraries (default "./assets/libraries") + --minimal-ui simplified version of CLI output + --no-progress hides the progress bar + --output-name string name used on report creations (default "results") + -o, --output-path string directory path to store reports + -p, --path strings paths or directories to scan + example: "./somepath,somefile.txt" + --payload-lines adds line information inside the payload when printing the payload file + -d, --payload-path string path to store internal representation JSON file + --preview-lines int number of lines to be display in CLI results (min: 1, max: 30) (default 3) + -q, --queries-path strings paths to directory with queries (default [./assets/queries]) + --report-formats strings formats in which the results will be exported (all, asff, codeclimate, csv, cyclonedx, glsast, html, json, junit, pdf, sarif, sonarqube) (default [json]) + -r, --secrets-regexes-path string path to secrets regex rules configuration file + --terraform-vars-path string path where terraform variables are present + --timeout int number of seconds the query has to execute before being canceled (default 60) + -t, --type strings case insensitive list of platform types to scan + (Ansible, AzureResourceManager, Buildah, CICD, CloudFormation, Crossplane, DockerCompose, Dockerfile, GRPC, GoogleDeploymentManager, Knative, Kubernetes, OpenAPI, Pulumi, ServerlessFW, Terraform) + cannot be provided with type exclusion flags Global Flags: --ci display only log messages to CLI output (mutually exclusive with silent) From be38c59c59ac16af817b9d980579f22e9ee23ced Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Cunha=20Martins?= Date: Tue, 17 Oct 2023 12:35:17 +0100 Subject: [PATCH 12/22] wip --- internal/tracker/ci_test.go | 1 + pkg/detector/default_detect_test.go | 10 +++++----- pkg/engine/source/filesystem.go | 1 - test/queries_content_test.go | 3 +-- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/internal/tracker/ci_test.go b/internal/tracker/ci_test.go index c20d1d8c159..8e317346298 100644 --- a/internal/tracker/ci_test.go +++ b/internal/tracker/ci_test.go @@ -12,6 +12,7 @@ import ( /* TestCITracker tests the functions [TrackQueryLoad(),TrackQueryExecution(),TrackFileFound(), + TrackFileParse(),TrackFileParse(),FailedDetectLine(),FailedComputeSimilarityID()] */ func TestCITracker(t *testing.T) { diff --git a/pkg/detector/default_detect_test.go b/pkg/detector/default_detect_test.go index 5a172807e0b..1118fcb604b 100644 --- a/pkg/detector/default_detect_test.go +++ b/pkg/detector/default_detect_test.go @@ -58,11 +58,11 @@ func Test_detectLine(t *testing.T) { //nolint VulnLines: &[]model.CodeLine{ { Position: 2, - Line: ` bucket = "my-tf-test-bucket"`, + Line: ` bucket = "my-tf-test-bucket"`, }, { Position: 3, - Line: ` acl = "authenticated-read"`, + Line: ` acl = "authenticated-read"`, }, { Position: 4, @@ -92,15 +92,15 @@ func Test_detectLine(t *testing.T) { //nolint VulnLines: &[]model.CodeLine{ { Position: 6, - Line: ` Name = "My bucket"`, + Line: ` Name = "My bucket"`, }, { Position: 7, - Line: ` Environment = "Dev.123"`, + Line: ` Environment = "Dev.123"`, }, { Position: 8, - Line: ` Environment = "test"`, + Line: ` Environment = "test"`, }, }, LineWithVulnerability: "", diff --git a/pkg/engine/source/filesystem.go b/pkg/engine/source/filesystem.go index ec8132be26f..780543bba3e 100644 --- a/pkg/engine/source/filesystem.go +++ b/pkg/engine/source/filesystem.go @@ -248,7 +248,6 @@ func checkQueryExclude(metadata map[string]interface{}, queryParameters *QueryIn // GetQueries walks a given filesource path returns all queries found in an array of // QueryMetadata struct func (s *FilesystemSource) GetQueries(queryParameters *QueryInspectorParameters) ([]model.QueryMetadata, error) { - queryDirs, err := s.iterateSources() if err != nil { return nil, err diff --git a/test/queries_content_test.go b/test/queries_content_test.go index f17bf655dc0..e3196456067 100644 --- a/test/queries_content_test.go +++ b/test/queries_content_test.go @@ -56,8 +56,7 @@ var ( "../assets/queries/terraform/aws/redshift_cluster_without_vpc", "../assets/queries/openAPI/general/response_code_missing", "../assets/queries/cicd/github/run_block_injection", - "../assets/queries/cicd/github/script_block_injection", - + "../assets/queries/cicd/github/script_block_injection", } // TODO uncomment this test once all metadata are fixed From df5c9a942026d0d0699c850922c7f1f3ced74659 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Cunha=20Martins?= Date: Tue, 17 Oct 2023 14:51:52 +0100 Subject: [PATCH 13/22] workaround for lint fails https://github.com/golangci/golangci-lint-action/issues/807 --- .github/workflows/go-ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/go-ci.yml b/.github/workflows/go-ci.yml index 93c9febd1fb..f155fc5207f 100644 --- a/.github/workflows/go-ci.yml +++ b/.github/workflows/go-ci.yml @@ -14,6 +14,7 @@ jobs: uses: actions/setup-go@v4 with: go-version: 1.20.x + cache: false - name: golangci-lint uses: golangci/golangci-lint-action@v3.5.0 with: From cccc01e42e19b07c0538005ddb6a5818dc116401 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Cunha=20Martins?= Date: Tue, 17 Oct 2023 15:05:36 +0100 Subject: [PATCH 14/22] fix --- pkg/scan/scan.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pkg/scan/scan.go b/pkg/scan/scan.go index 1af9c4fba52..dd4c83a1f6c 100644 --- a/pkg/scan/scan.go +++ b/pkg/scan/scan.go @@ -3,6 +3,8 @@ package scan import ( "context" + "os" + "github.com/Checkmarx/kics/assets" "github.com/Checkmarx/kics/pkg/engine" "github.com/Checkmarx/kics/pkg/engine/provider" @@ -22,8 +24,6 @@ import ( "github.com/Checkmarx/kics/pkg/resolver" "github.com/Checkmarx/kics/pkg/resolver/helm" "github.com/Checkmarx/kics/pkg/scanner" - "os" - "github.com/rs/zerolog/log" ) From 8f4b29619be33b7f28821468c6e5b539640bed49 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Cunha=20Martins?= Date: Fri, 27 Oct 2023 10:58:26 +0100 Subject: [PATCH 15/22] remove references to the experimental-queries.json --- assets/utils/experimental-queries.json | 4 ---- docker/Dockerfile.apispec | 1 - docker/Dockerfile.apispec.debian | 1 - docker/Dockerfile.debian | 1 - 4 files changed, 7 deletions(-) delete mode 100644 assets/utils/experimental-queries.json diff --git a/assets/utils/experimental-queries.json b/assets/utils/experimental-queries.json deleted file mode 100644 index 06d45b989fc..00000000000 --- a/assets/utils/experimental-queries.json +++ /dev/null @@ -1,4 +0,0 @@ -[ - "terraform/databricks", - "terraform/nifcloud" -] \ No newline at end of file diff --git a/docker/Dockerfile.apispec b/docker/Dockerfile.apispec index ef936ff6e9a..7a7aa413505 100644 --- a/docker/Dockerfile.apispec +++ b/docker/Dockerfile.apispec @@ -56,7 +56,6 @@ COPY --from=build_env /app/assets/libraries/common /app/bin/assets/libraries/com COPY --from=build_env /app/assets/libraries/openapi /app/bin/assets/libraries/openapi COPY --from=build_env /app/assets/queries/openAPI /app/bin/assets/queries/openAPI COPY --from=build_env /app/assets/queries/common /app/bin/assets/queries/common -COPY --from=build_env /app/assets/utils/* /app/bin/assets/utils/ WORKDIR /app/bin diff --git a/docker/Dockerfile.apispec.debian b/docker/Dockerfile.apispec.debian index c0ceb596087..c90f5d44cb6 100644 --- a/docker/Dockerfile.apispec.debian +++ b/docker/Dockerfile.apispec.debian @@ -70,7 +70,6 @@ COPY --from=build_env /app/assets/libraries/common /app/bin/assets/libraries/com COPY --from=build_env /app/assets/libraries/openapi /app/bin/assets/libraries/openapi COPY --from=build_env /app/assets/queries/openAPI /app/bin/assets/queries/openAPI COPY --from=build_env /app/assets/queries/common /app/bin/assets/queries/common -COPY --from=build_env /app/assets/utils/* /app/bin/assets/utils/ WORKDIR /app/bin diff --git a/docker/Dockerfile.debian b/docker/Dockerfile.debian index 7746fabc742..6c9137aa75f 100644 --- a/docker/Dockerfile.debian +++ b/docker/Dockerfile.debian @@ -69,7 +69,6 @@ RUN mkdir ~/.terraform.d && mkdir ~/.terraform.d/plugins && mkdir ~/.terraform.d COPY --from=build_env /app/bin/kics /app/bin/kics COPY --from=build_env /app/assets/queries /app/bin/assets/queries COPY --from=build_env /app/assets/libraries/* /app/bin/assets/libraries/ -COPY --from=build_env /app/assets/utils/* /app/bin/assets/utils/ WORKDIR /app/bin From a2335da5ff0d84d1f9d94d479220d7da2d8a5378 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Cunha=20Martins?= <75611928+JoaoCxMartins@users.noreply.github.com> Date: Fri, 27 Oct 2023 12:27:37 +0100 Subject: [PATCH 16/22] Update pkg/engine/source/filesystem.go Co-authored-by: Gabriel --- pkg/engine/source/filesystem.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/engine/source/filesystem.go b/pkg/engine/source/filesystem.go index 780543bba3e..5ad463d944c 100644 --- a/pkg/engine/source/filesystem.go +++ b/pkg/engine/source/filesystem.go @@ -306,7 +306,7 @@ func (s *FilesystemSource) iterateQueryDirs(queryDirs []string, queryParameters continue } - if !queryParameters.ExperimentalQueries && query.Experimental { + if query.Experimental && !queryParameters.ExperimentalQueries { continue } From 5de337736710b90c94427a7671ab729dcbb01953 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Cunha=20Martins?= Date: Fri, 27 Oct 2023 16:48:11 +0100 Subject: [PATCH 17/22] add two e2e one where we scan and ignore the experimental and other scan where we don't ignore --- .../e2e-cli-069_igore_experimental_query.go | 25 +++++ ...2e-cli-070_not_igore_experimental_query.go | 26 ++++++ .../redis_disable_experimental/metadata.json | 12 +++ .../redis_disable_experimental/query.rego | 92 +++++++++++++++++++ .../queries/redis_disabled/metadata.json | 11 +++ .../queries/redis_disabled/query.rego | 92 +++++++++++++++++++ .../experimental_test/sample/sample.tf | 9 ++ 7 files changed, 267 insertions(+) create mode 100644 e2e/testcases/e2e-cli-069_igore_experimental_query.go create mode 100644 e2e/testcases/e2e-cli-070_not_igore_experimental_query.go create mode 100644 test/fixtures/experimental_test/queries/redis_disable_experimental/metadata.json create mode 100644 test/fixtures/experimental_test/queries/redis_disable_experimental/query.rego create mode 100644 test/fixtures/experimental_test/queries/redis_disabled/metadata.json create mode 100644 test/fixtures/experimental_test/queries/redis_disabled/query.rego create mode 100644 test/fixtures/experimental_test/sample/sample.tf diff --git a/e2e/testcases/e2e-cli-069_igore_experimental_query.go b/e2e/testcases/e2e-cli-069_igore_experimental_query.go new file mode 100644 index 00000000000..3b082c2e49d --- /dev/null +++ b/e2e/testcases/e2e-cli-069_igore_experimental_query.go @@ -0,0 +1,25 @@ +package testcases + +// E2E-CLI-069 - KICS scan and ignore experimental queries +// should perform the scan successfully and return exit code 40 +func init() { //nolint + testSample := TestCase{ + Name: "should perform a valid scan and ignore the experimental queries [E2E-CLI-069]", + Args: args{ + Args: []cmdArgs{ + []string{"scan", "-o", "/path/e2e/output", "--output-name", "E2E_CLI_069_RESULT", + "-p", "/path/test/fixtures/experimental_test/sample", "-q", "/path/test/fixtures/experimental_test/queries", + }, + }, + ExpectedResult: []ResultsValidation{ + { + ResultsFile: "E2E_CLI_069_RESULT", + ResultsFormats: []string{"json"}, + }, + }, + }, + WantStatus: []int{40}, + } + + Tests = append(Tests, testSample) +} diff --git a/e2e/testcases/e2e-cli-070_not_igore_experimental_query.go b/e2e/testcases/e2e-cli-070_not_igore_experimental_query.go new file mode 100644 index 00000000000..cc5c82ee3dd --- /dev/null +++ b/e2e/testcases/e2e-cli-070_not_igore_experimental_query.go @@ -0,0 +1,26 @@ +package testcases + +// E2E-CLI-070 - KICS scan and not ignore experimental queries +// should perform the scan successfully and return exit code 40 and 50 +func init() { //nolint + testSample := TestCase{ + Name: "should perform a valid scan and not ignore the experimental queries [E2E-CLI-070]", + Args: args{ + Args: []cmdArgs{ + []string{"scan", "-o", "/path/e2e/output", "--output-name", "E2E_CLI_070_RESULT", + "-p", "/path/test/fixtures/experimental_test/sample", "-q", "/path/test/fixtures/experimental_test/queries", + "--experimental-queries", + }, + }, + ExpectedResult: []ResultsValidation{ + { + ResultsFile: "E2E_CLI_070_RESULT", + ResultsFormats: []string{"json"}, + }, + }, + }, + WantStatus: []int{50}, + } + + Tests = append(Tests, testSample) +} diff --git a/test/fixtures/experimental_test/queries/redis_disable_experimental/metadata.json b/test/fixtures/experimental_test/queries/redis_disable_experimental/metadata.json new file mode 100644 index 00000000000..1da83e327e5 --- /dev/null +++ b/test/fixtures/experimental_test/queries/redis_disable_experimental/metadata.json @@ -0,0 +1,12 @@ +{ + "id": "4bd15dd9-8d5e-4008-8532-27eb0c3706d4", + "queryName": "Redis Disabled Experimental", + "severity": "HIGH", + "category": "Encryption", + "descriptionText": "ElastiCache should have Redis enabled, since it covers Compliance Certifications such as FedRAMP, HIPAA, and PCI DSS. For more information, take a look at 'https://docs.aws.amazon.com/AmazonElastiCache/latest/mem-ug/SelectEngine.html'", + "descriptionUrl": "https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/elasticache_cluster#engine", + "platform": "Terraform", + "descriptionID": "68984bf2", + "cloudProvider": "aws", + "experimental": "true" +} diff --git a/test/fixtures/experimental_test/queries/redis_disable_experimental/query.rego b/test/fixtures/experimental_test/queries/redis_disable_experimental/query.rego new file mode 100644 index 00000000000..3d56f8598e3 --- /dev/null +++ b/test/fixtures/experimental_test/queries/redis_disable_experimental/query.rego @@ -0,0 +1,92 @@ +package Cx + +CxPolicy[result] { + resource := input.document[i].resource.aws_elasticache_cluster[name] + resource.engine != "redis" + + result := { + "documentId": input.document[i].id, + "resourceType": "aws_elasticache_cluster", + "resourceName": get_specific_resource_name(resource, "aws_elasticache_cluster", name), + "searchKey": sprintf("resource.aws_elasticache_cluster[%s].engine", [name]), + "searchLine": build_search_line(["resource", "aws_elasticache_cluster", name, "engine"], []), + "issueType": "IncorrectValue", + "keyExpectedValue": sprintf("resource.aws_elasticache_cluster[%s].engine should have Redis enabled", [name]), + "keyActualValue": sprintf("resource.aws_elasticache_cluster[%s].engine doesn't enable Redis", [name]), + "remediation": json.marshal({ + "before": "memcached", + "after": "redis" + }), + "remediationType": "replacement", + } +} + +get_specific_resource_name(resource, resourceType, resourceDefinitionName) = name { + field := resourceFieldName[resourceType] + name := resource[field] +} else = name { + name := get_resource_name(resource, resourceDefinitionName) +} + +get_resource_name(resource, resourceDefinitionName) = name { + name := resource["name"] +} else = name { + name := resource["display_name"] +} else = name { + name := resource.metadata.name +} else = name { + prefix := resource.name_prefix + name := sprintf("%s", [prefix]) +} else = name { + name := get_tag_name_if_exists(resource) +} else = name { + name := resourceDefinitionName +} + +build_search_line(path, obj) = resolvedPath { + resolveArray := [x | pathItem := path[n]; x := convert_path_item(pathItem)] + resolvedObj := [x | objItem := obj[n]; x := convert_path_item(objItem)] + resolvedPath = array.concat(resolveArray, resolvedObj) +} + +convert_path_item(pathItem) = convertedPath { + is_number(pathItem) + convertedPath := sprintf("%d", [pathItem]) +} else = convertedPath { + convertedPath := sprintf("%s", [pathItem]) +} + +get_tag_name_if_exists(resource) = name { + name := resource.tags.Name +} else = name { + tag := resource.Properties.Tags[_] + tag.Key == "Name" + name := tag.Value +} else = name { + tag := resource.Properties.FileSystemTags[_] + tag.Key == "Name" + name := tag.Value +} else = name { + tag := resource.Properties.Tags[key] + key == "Name" + name := tag +} else = name { + tag := resource.spec.forProvider.tags[_] + tag.key == "Name" + name := tag.value +} else = name { + tag := resource.properties.tags[key] + key == "Name" + name := tag +} + +resourceFieldName = { + "google_bigquery_dataset": "friendly_name", + "alicloud_actiontrail_trail": "trail_name", + "alicloud_ros_stack": "stack_name", + "alicloud_oss_bucket": "bucket", + "aws_s3_bucket": "bucket", + "aws_msk_cluster": "cluster_name", + "aws_mq_broker": "broker_name", + "aws_elasticache_cluster": "cluster_id", +} diff --git a/test/fixtures/experimental_test/queries/redis_disabled/metadata.json b/test/fixtures/experimental_test/queries/redis_disabled/metadata.json new file mode 100644 index 00000000000..950faf01e92 --- /dev/null +++ b/test/fixtures/experimental_test/queries/redis_disabled/metadata.json @@ -0,0 +1,11 @@ +{ + "id": "4bd15dd9-8d5e-4008-8532-27eb0c3706d3", + "queryName": "Redis Disabled", + "severity": "MEDIUM", + "category": "Encryption", + "descriptionText": "ElastiCache should have Redis enabled, since it covers Compliance Certifications such as FedRAMP, HIPAA, and PCI DSS. For more information, take a look at 'https://docs.aws.amazon.com/AmazonElastiCache/latest/mem-ug/SelectEngine.html'", + "descriptionUrl": "https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/elasticache_cluster#engine", + "platform": "Terraform", + "descriptionID": "68984bf2", + "cloudProvider": "aws" +} diff --git a/test/fixtures/experimental_test/queries/redis_disabled/query.rego b/test/fixtures/experimental_test/queries/redis_disabled/query.rego new file mode 100644 index 00000000000..3d56f8598e3 --- /dev/null +++ b/test/fixtures/experimental_test/queries/redis_disabled/query.rego @@ -0,0 +1,92 @@ +package Cx + +CxPolicy[result] { + resource := input.document[i].resource.aws_elasticache_cluster[name] + resource.engine != "redis" + + result := { + "documentId": input.document[i].id, + "resourceType": "aws_elasticache_cluster", + "resourceName": get_specific_resource_name(resource, "aws_elasticache_cluster", name), + "searchKey": sprintf("resource.aws_elasticache_cluster[%s].engine", [name]), + "searchLine": build_search_line(["resource", "aws_elasticache_cluster", name, "engine"], []), + "issueType": "IncorrectValue", + "keyExpectedValue": sprintf("resource.aws_elasticache_cluster[%s].engine should have Redis enabled", [name]), + "keyActualValue": sprintf("resource.aws_elasticache_cluster[%s].engine doesn't enable Redis", [name]), + "remediation": json.marshal({ + "before": "memcached", + "after": "redis" + }), + "remediationType": "replacement", + } +} + +get_specific_resource_name(resource, resourceType, resourceDefinitionName) = name { + field := resourceFieldName[resourceType] + name := resource[field] +} else = name { + name := get_resource_name(resource, resourceDefinitionName) +} + +get_resource_name(resource, resourceDefinitionName) = name { + name := resource["name"] +} else = name { + name := resource["display_name"] +} else = name { + name := resource.metadata.name +} else = name { + prefix := resource.name_prefix + name := sprintf("%s", [prefix]) +} else = name { + name := get_tag_name_if_exists(resource) +} else = name { + name := resourceDefinitionName +} + +build_search_line(path, obj) = resolvedPath { + resolveArray := [x | pathItem := path[n]; x := convert_path_item(pathItem)] + resolvedObj := [x | objItem := obj[n]; x := convert_path_item(objItem)] + resolvedPath = array.concat(resolveArray, resolvedObj) +} + +convert_path_item(pathItem) = convertedPath { + is_number(pathItem) + convertedPath := sprintf("%d", [pathItem]) +} else = convertedPath { + convertedPath := sprintf("%s", [pathItem]) +} + +get_tag_name_if_exists(resource) = name { + name := resource.tags.Name +} else = name { + tag := resource.Properties.Tags[_] + tag.Key == "Name" + name := tag.Value +} else = name { + tag := resource.Properties.FileSystemTags[_] + tag.Key == "Name" + name := tag.Value +} else = name { + tag := resource.Properties.Tags[key] + key == "Name" + name := tag +} else = name { + tag := resource.spec.forProvider.tags[_] + tag.key == "Name" + name := tag.value +} else = name { + tag := resource.properties.tags[key] + key == "Name" + name := tag +} + +resourceFieldName = { + "google_bigquery_dataset": "friendly_name", + "alicloud_actiontrail_trail": "trail_name", + "alicloud_ros_stack": "stack_name", + "alicloud_oss_bucket": "bucket", + "aws_s3_bucket": "bucket", + "aws_msk_cluster": "cluster_name", + "aws_mq_broker": "broker_name", + "aws_elasticache_cluster": "cluster_id", +} diff --git a/test/fixtures/experimental_test/sample/sample.tf b/test/fixtures/experimental_test/sample/sample.tf new file mode 100644 index 00000000000..6f202546eb2 --- /dev/null +++ b/test/fixtures/experimental_test/sample/sample.tf @@ -0,0 +1,9 @@ +#this is a problematic code where the query should report a result(s) +resource "aws_elasticache_cluster" "positive1" { + cluster_id = "cluster-example" + engine = "memcached" + node_type = "cache.m4.large" + num_cache_nodes = 1 + engine_version = "3.2.10" + port = 6379 +} From a4988180e014fc694ed3b6d99c682b5466d22c5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Cunha=20Martins?= Date: Fri, 27 Oct 2023 16:54:19 +0100 Subject: [PATCH 18/22] add the results files to fixture e2e --- e2e/fixtures/E2E_CLI_069_RESULT.json | 58 +++++++++++++++++++ e2e/fixtures/E2E_CLI_070_RESULT.json | 86 ++++++++++++++++++++++++++++ 2 files changed, 144 insertions(+) create mode 100644 e2e/fixtures/E2E_CLI_069_RESULT.json create mode 100644 e2e/fixtures/E2E_CLI_070_RESULT.json diff --git a/e2e/fixtures/E2E_CLI_069_RESULT.json b/e2e/fixtures/E2E_CLI_069_RESULT.json new file mode 100644 index 00000000000..c7e2e89f505 --- /dev/null +++ b/e2e/fixtures/E2E_CLI_069_RESULT.json @@ -0,0 +1,58 @@ +{ + "kics_version": "development", + "files_scanned": 1, + "lines_scanned": 10, + "files_parsed": 1, + "lines_parsed": 9, + "lines_ignored": 1, + "files_failed_to_scan": 0, + "queries_total": 1, + "queries_failed_to_execute": 0, + "queries_failed_to_compute_similarity_id": 0, + "scan_id": "console", + "severity_counters": { + "HIGH": 0, + "INFO": 0, + "LOW": 0, + "MEDIUM": 1, + "TRACE": 0 + }, + "total_counter": 1, + "total_bom_resources": 0, + "start": "2023-10-27T16:37:16.0886334+01:00", + "end": "2023-10-27T16:37:16.4789259+01:00", + "paths": [ + "/test/fixtures/experimental_test/sample", + "/test/fixtures/experimental_test/queries" + ], + "queries": [ + { + "query_name": "Redis Disabled", + "query_id": "4bd15dd9-8d5e-4008-8532-27eb0c3706d3", + "query_url": "https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/elasticache_cluster#engine", + "severity": "MEDIUM", + "platform": "Terraform", + "cloud_provider": "AWS", + "category": "Encryption", + "description": "ElastiCache should have Redis enabled, since it covers Compliance Certifications such as FedRAMP, HIPAA, and PCI DSS. For more information, take a look at 'https://docs.aws.amazon.com/AmazonElastiCache/latest/mem-ug/SelectEngine.html'", + "description_id": "68984bf2", + "files": [ + { + "file_name": "test\\fixtures\\experimental_test\\sample\\sample.tf", + "similarity_id": "32a6747d15f909ebe86d171c563878dd7e06dfb2f9ec1b569ef46e810860f27a", + "line": 4, + "resource_type": "aws_elasticache_cluster", + "resource_name": "cluster-example", + "issue_type": "IncorrectValue", + "search_key": "resource.aws_elasticache_cluster[positive1].engine", + "search_line": 4, + "search_value": "", + "expected_value": "resource.aws_elasticache_cluster[positive1].engine should have Redis enabled", + "actual_value": "resource.aws_elasticache_cluster[positive1].engine doesn't enable Redis", + "remediation": "{\"after\":\"redis\",\"before\":\"memcached\"}", + "remediation_type": "replacement" + } + ] + } + ] +} diff --git a/e2e/fixtures/E2E_CLI_070_RESULT.json b/e2e/fixtures/E2E_CLI_070_RESULT.json new file mode 100644 index 00000000000..2499b124296 --- /dev/null +++ b/e2e/fixtures/E2E_CLI_070_RESULT.json @@ -0,0 +1,86 @@ +{ + "kics_version": "development", + "files_scanned": 1, + "lines_scanned": 10, + "files_parsed": 1, + "lines_parsed": 9, + "lines_ignored": 1, + "files_failed_to_scan": 0, + "queries_total": 2, + "queries_failed_to_execute": 0, + "queries_failed_to_compute_similarity_id": 0, + "scan_id": "console", + "severity_counters": { + "HIGH": 1, + "INFO": 0, + "LOW": 0, + "MEDIUM": 1, + "TRACE": 0 + }, + "total_counter": 2, + "total_bom_resources": 0, + "start": "2023-10-27T16:46:52.5513995+01:00", + "end": "2023-10-27T16:46:52.8805179+01:00", + "paths": [ + "/test/fixtures/experimental_test/sample", + "/test/fixtures/experimental_test/queries" + ], + "queries": [ + { + "query_name": "Redis Disabled Experimental", + "query_id": "4bd15dd9-8d5e-4008-8532-27eb0c3706d4", + "query_url": "https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/elasticache_cluster#engine", + "severity": "HIGH", + "platform": "Terraform", + "cloud_provider": "AWS", + "category": "Encryption", + "description": "ElastiCache should have Redis enabled, since it covers Compliance Certifications such as FedRAMP, HIPAA, and PCI DSS. For more information, take a look at 'https://docs.aws.amazon.com/AmazonElastiCache/latest/mem-ug/SelectEngine.html'", + "description_id": "68984bf2", + "files": [ + { + "file_name": "test\\fixtures\\experimental_test\\sample\\sample.tf", + "similarity_id": "4e651f5c005de96ab66f25419b1f160d9e0eecae83181edfcd1b72b3afbe9f69", + "line": 4, + "resource_type": "aws_elasticache_cluster", + "resource_name": "cluster-example", + "issue_type": "IncorrectValue", + "search_key": "resource.aws_elasticache_cluster[positive1].engine", + "search_line": 4, + "search_value": "", + "expected_value": "resource.aws_elasticache_cluster[positive1].engine should have Redis enabled", + "actual_value": "resource.aws_elasticache_cluster[positive1].engine doesn't enable Redis", + "remediation": "{\"after\":\"redis\",\"before\":\"memcached\"}", + "remediation_type": "replacement" + } + ] + }, + { + "query_name": "Redis Disabled", + "query_id": "4bd15dd9-8d5e-4008-8532-27eb0c3706d3", + "query_url": "https://registry.terraform.io/providers/hashicorp/aws/latest/docs/resources/elasticache_cluster#engine", + "severity": "MEDIUM", + "platform": "Terraform", + "cloud_provider": "AWS", + "category": "Encryption", + "description": "ElastiCache should have Redis enabled, since it covers Compliance Certifications such as FedRAMP, HIPAA, and PCI DSS. For more information, take a look at 'https://docs.aws.amazon.com/AmazonElastiCache/latest/mem-ug/SelectEngine.html'", + "description_id": "68984bf2", + "files": [ + { + "file_name": "test\\fixtures\\experimental_test\\sample\\sample.tf", + "similarity_id": "32a6747d15f909ebe86d171c563878dd7e06dfb2f9ec1b569ef46e810860f27a", + "line": 4, + "resource_type": "aws_elasticache_cluster", + "resource_name": "cluster-example", + "issue_type": "IncorrectValue", + "search_key": "resource.aws_elasticache_cluster[positive1].engine", + "search_line": 4, + "search_value": "", + "expected_value": "resource.aws_elasticache_cluster[positive1].engine should have Redis enabled", + "actual_value": "resource.aws_elasticache_cluster[positive1].engine doesn't enable Redis", + "remediation": "{\"after\":\"redis\",\"before\":\"memcached\"}", + "remediation_type": "replacement" + } + ] + } + ] +} From 0cc6f8164e51816903252a9a4f4811fe8edd19e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Cunha=20Martins?= Date: Fri, 27 Oct 2023 17:14:50 +0100 Subject: [PATCH 19/22] rename tests --- ...rimental_query.go => e2e-cli-069_ignore_experimental_query.go} | 0 ...ntal_query.go => e2e-cli-070_not_ignore_experimental_query.go} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename e2e/testcases/{e2e-cli-069_igore_experimental_query.go => e2e-cli-069_ignore_experimental_query.go} (100%) rename e2e/testcases/{e2e-cli-070_not_igore_experimental_query.go => e2e-cli-070_not_ignore_experimental_query.go} (100%) diff --git a/e2e/testcases/e2e-cli-069_igore_experimental_query.go b/e2e/testcases/e2e-cli-069_ignore_experimental_query.go similarity index 100% rename from e2e/testcases/e2e-cli-069_igore_experimental_query.go rename to e2e/testcases/e2e-cli-069_ignore_experimental_query.go diff --git a/e2e/testcases/e2e-cli-070_not_igore_experimental_query.go b/e2e/testcases/e2e-cli-070_not_ignore_experimental_query.go similarity index 100% rename from e2e/testcases/e2e-cli-070_not_igore_experimental_query.go rename to e2e/testcases/e2e-cli-070_not_ignore_experimental_query.go From 79cfb742f6082ab61ca9c24c3b860e12f4edd7dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Cunha=20Martins?= Date: Mon, 30 Oct 2023 09:22:50 +0000 Subject: [PATCH 20/22] fix tests --- e2e/testcases/e2e-cli-069_ignore_experimental_query.go | 2 +- e2e/testcases/e2e-cli-070_not_ignore_experimental_query.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/e2e/testcases/e2e-cli-069_ignore_experimental_query.go b/e2e/testcases/e2e-cli-069_ignore_experimental_query.go index 3b082c2e49d..b930126d359 100644 --- a/e2e/testcases/e2e-cli-069_ignore_experimental_query.go +++ b/e2e/testcases/e2e-cli-069_ignore_experimental_query.go @@ -8,7 +8,7 @@ func init() { //nolint Args: args{ Args: []cmdArgs{ []string{"scan", "-o", "/path/e2e/output", "--output-name", "E2E_CLI_069_RESULT", - "-p", "/path/test/fixtures/experimental_test/sample", "-q", "/path/test/fixtures/experimental_test/queries", + "-p", "\"/path/test/fixtures/experimental_test/sample\"", "-q", "\"/path/test/fixtures/experimental_test/queries\"", }, }, ExpectedResult: []ResultsValidation{ diff --git a/e2e/testcases/e2e-cli-070_not_ignore_experimental_query.go b/e2e/testcases/e2e-cli-070_not_ignore_experimental_query.go index cc5c82ee3dd..1dd2bc64d4a 100644 --- a/e2e/testcases/e2e-cli-070_not_ignore_experimental_query.go +++ b/e2e/testcases/e2e-cli-070_not_ignore_experimental_query.go @@ -8,7 +8,7 @@ func init() { //nolint Args: args{ Args: []cmdArgs{ []string{"scan", "-o", "/path/e2e/output", "--output-name", "E2E_CLI_070_RESULT", - "-p", "/path/test/fixtures/experimental_test/sample", "-q", "/path/test/fixtures/experimental_test/queries", + "-p", "\"/path/test/fixtures/experimental_test/sample\"", "-q", "\"/path/test/fixtures/experimental_test/queries\"", "--experimental-queries", }, }, From 754eb294c58572fffaca6c2132b08a915d3e4389 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Cunha=20Martins?= Date: Mon, 30 Oct 2023 09:54:47 +0000 Subject: [PATCH 21/22] fix path on e2e --- e2e/fixtures/E2E_CLI_069_RESULT.json | 4 ++-- e2e/fixtures/E2E_CLI_070_RESULT.json | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/e2e/fixtures/E2E_CLI_069_RESULT.json b/e2e/fixtures/E2E_CLI_069_RESULT.json index c7e2e89f505..9b9f28e9948 100644 --- a/e2e/fixtures/E2E_CLI_069_RESULT.json +++ b/e2e/fixtures/E2E_CLI_069_RESULT.json @@ -22,8 +22,8 @@ "start": "2023-10-27T16:37:16.0886334+01:00", "end": "2023-10-27T16:37:16.4789259+01:00", "paths": [ - "/test/fixtures/experimental_test/sample", - "/test/fixtures/experimental_test/queries" + "/path/test/fixtures/experimental_test/sample", + "/path/test/fixtures/experimental_test/queries" ], "queries": [ { diff --git a/e2e/fixtures/E2E_CLI_070_RESULT.json b/e2e/fixtures/E2E_CLI_070_RESULT.json index 2499b124296..072da73637b 100644 --- a/e2e/fixtures/E2E_CLI_070_RESULT.json +++ b/e2e/fixtures/E2E_CLI_070_RESULT.json @@ -22,8 +22,8 @@ "start": "2023-10-27T16:46:52.5513995+01:00", "end": "2023-10-27T16:46:52.8805179+01:00", "paths": [ - "/test/fixtures/experimental_test/sample", - "/test/fixtures/experimental_test/queries" + "/path/test/fixtures/experimental_test/sample", + "/path/test/fixtures/experimental_test/queries" ], "queries": [ { From 843a53d17f6d591185213f029ebef9be8613126c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Cunha=20Martins?= Date: Mon, 30 Oct 2023 10:04:35 +0000 Subject: [PATCH 22/22] wip --- e2e/fixtures/E2E_CLI_069_RESULT.json | 2 +- e2e/fixtures/E2E_CLI_070_RESULT.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/e2e/fixtures/E2E_CLI_069_RESULT.json b/e2e/fixtures/E2E_CLI_069_RESULT.json index 9b9f28e9948..2253d7b85a1 100644 --- a/e2e/fixtures/E2E_CLI_069_RESULT.json +++ b/e2e/fixtures/E2E_CLI_069_RESULT.json @@ -38,7 +38,7 @@ "description_id": "68984bf2", "files": [ { - "file_name": "test\\fixtures\\experimental_test\\sample\\sample.tf", + "file_name": "path\\test\\fixtures\\experimental_test\\sample\\sample.tf", "similarity_id": "32a6747d15f909ebe86d171c563878dd7e06dfb2f9ec1b569ef46e810860f27a", "line": 4, "resource_type": "aws_elasticache_cluster", diff --git a/e2e/fixtures/E2E_CLI_070_RESULT.json b/e2e/fixtures/E2E_CLI_070_RESULT.json index 072da73637b..7b4f1b32ba5 100644 --- a/e2e/fixtures/E2E_CLI_070_RESULT.json +++ b/e2e/fixtures/E2E_CLI_070_RESULT.json @@ -38,7 +38,7 @@ "description_id": "68984bf2", "files": [ { - "file_name": "test\\fixtures\\experimental_test\\sample\\sample.tf", + "file_name": "path\\test\\fixtures\\experimental_test\\sample\\sample.tf", "similarity_id": "4e651f5c005de96ab66f25419b1f160d9e0eecae83181edfcd1b72b3afbe9f69", "line": 4, "resource_type": "aws_elasticache_cluster", @@ -66,7 +66,7 @@ "description_id": "68984bf2", "files": [ { - "file_name": "test\\fixtures\\experimental_test\\sample\\sample.tf", + "file_name": "path\\test\\fixtures\\experimental_test\\sample\\sample.tf", "similarity_id": "32a6747d15f909ebe86d171c563878dd7e06dfb2f9ec1b569ef46e810860f27a", "line": 4, "resource_type": "aws_elasticache_cluster",