From 28610de64ba65832b9def803105f406a92fe25c0 Mon Sep 17 00:00:00 2001 From: Ivan Milchev Date: Mon, 22 Jul 2024 15:02:48 +0300 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20lint=20error=20when=20query=20is=20?= =?UTF-8?q?used=20both=20as=20check=20and=20data=20query?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Ivan Milchev --- internal/bundle/lint.go | 31 +++++++++++++++++++ internal/bundle/lint_test.go | 14 +++++++++ .../bundle/testdata/mixing-queries.mql.yaml | 22 +++++++++++++ 3 files changed, 67 insertions(+) create mode 100644 internal/bundle/testdata/mixing-queries.mql.yaml diff --git a/internal/bundle/lint.go b/internal/bundle/lint.go index e1ff4c66..294c9103 100644 --- a/internal/bundle/lint.go +++ b/internal/bundle/lint.go @@ -34,6 +34,7 @@ const ( queryTitle = "query-name" queryUidUnique = "query-uid-unique" queryUnassigned = "query-unassigned" + queryUsedAsDifferentTypes = "query-used-as-different-types" ) type Rule struct { @@ -229,6 +230,8 @@ func lintFile(file string) (*Results, error) { // index global queries that are not embedded globalQueriesUids := map[string]int{} globalQueriesByUid := map[string]*Mquery{} + checks := map[string]struct{}{} + dataQueries := map[string]struct{}{} // child to parent mapping variantMapping := map[string]string{} for i := range policyBundle.Queries { @@ -419,6 +422,20 @@ func lintFile(file string) (*Results, error) { // NOTE: embedded queries do not need a uid lintQuery(check, file, globalQueriesUids, assignedQueries, variantMapping, false) } else { + checks[uid] = struct{}{} + if _, ok := dataQueries[uid]; ok { + res.Entries = append(res.Entries, Entry{ + RuleID: queryUsedAsDifferentTypes, + Message: fmt.Sprintf("query %s is used as a check and data query", uid), + Level: levelError, + Location: []Location{{ + File: file, + Line: group.FileContext.Line, + Column: group.FileContext.Column, + }}, + }) + } + // if the query is not embedded, then it needs to be available globally _, ok := globalQueriesUids[uid] if !ok { @@ -447,6 +464,20 @@ func lintFile(file string) (*Results, error) { // NOTE: embedded queries do not need a uid lintQuery(query, file, globalQueriesUids, assignedQueries, variantMapping, false) } else { + dataQueries[uid] = struct{}{} + if _, ok := checks[uid]; ok { + res.Entries = append(res.Entries, Entry{ + RuleID: queryUsedAsDifferentTypes, + Message: fmt.Sprintf("query %s is used as a check and data query", uid), + Level: levelError, + Location: []Location{{ + File: file, + Line: group.FileContext.Line, + Column: group.FileContext.Column, + }}, + }) + } + // if the query is not embedded, then it needs to be available globally _, ok := globalQueriesUids[uid] if !ok { diff --git a/internal/bundle/lint_test.go b/internal/bundle/lint_test.go index 77dbca3c..4a2059a7 100644 --- a/internal/bundle/lint_test.go +++ b/internal/bundle/lint_test.go @@ -85,3 +85,17 @@ func TestLintFail(t *testing.T) { require.NoError(t, err) assert.True(t, len(data) > 0) } + +func TestLintFail_MixQueries(t *testing.T) { + file := "./testdata/mixing-queries.mql.yaml" + results, err := bundle.Lint(schema, file) + require.NoError(t, err) + + assert.Equal(t, 1, len(results.BundleLocations)) + assert.Equal(t, 1, len(results.Entries)) + assert.True(t, results.HasError()) + + entry := results.Entries[0] + assert.Equal(t, "query-used-as-different-types", entry.RuleID) + assert.Equal(t, "query sshd-sshd-01 is used as a check and data query", entry.Message) +} diff --git a/internal/bundle/testdata/mixing-queries.mql.yaml b/internal/bundle/testdata/mixing-queries.mql.yaml new file mode 100644 index 00000000..e8233883 --- /dev/null +++ b/internal/bundle/testdata/mixing-queries.mql.yaml @@ -0,0 +1,22 @@ +policies: + - uid: data-queries-mix + name: Test data SSH Policy + version: "1.0.0" + owner_mrn: "" + is_public: true + authors: + - name: Mondoo, Inc. + email: hello@mondoo.com + groups: + - title: group 01 + checks: + - uid: sshd-sshd-01 + queries: + - uid: sshd-sshd-01 + filters: | + asset.family.contains(_ == 'unix') + +queries: + - uid: sshd-sshd-01 + title: Asset name is "test" + query: asset.name == "test"