diff --git a/apps/cnquery/cmd/bundle.go b/apps/cnquery/cmd/bundle.go index 8335fc5068..166d0b09b2 100644 --- a/apps/cnquery/cmd/bundle.go +++ b/apps/cnquery/cmd/bundle.go @@ -8,7 +8,6 @@ import ( _ "embed" "fmt" "os" - "strconv" "github.com/cockroachdb/errors" "github.com/rs/zerolog/log" @@ -17,6 +16,7 @@ import ( "go.mondoo.com/cnquery/v10/cli/config" cli_errors "go.mondoo.com/cnquery/v10/cli/errors" "go.mondoo.com/cnquery/v10/explorer" + "go.mondoo.com/cnquery/v10/internal/bundle" "go.mondoo.com/cnquery/v10/providers" "go.mondoo.com/cnquery/v10/providers-sdk/v1/upstream" "go.mondoo.com/cnquery/v10/utils/stringx" @@ -69,49 +69,6 @@ var queryPackInitCmd = &cobra.Command{ }, } -func validate(queryPackBundle *explorer.Bundle) []string { - errors := []string{} - - // check that we have uids for packs and queries - for i := range queryPackBundle.Packs { - pack := queryPackBundle.Packs[i] - packId := strconv.Itoa(i) - - if pack.Uid == "" { - errors = append(errors, fmt.Sprintf("pack %s does not define a uid", packId)) - } else { - packId = pack.Uid - } - - if pack.Name == "" { - errors = append(errors, fmt.Sprintf("pack %s does not define a name", packId)) - } - - for j := range pack.Queries { - query := pack.Queries[j] - queryId := strconv.Itoa(j) - if query.Uid == "" { - errors = append(errors, fmt.Sprintf("query %s/%s does not define a uid", packId, queryId)) - } else { - queryId = query.Uid - } - - if query.Title == "" { - errors = append(errors, fmt.Sprintf("query %s/%s does not define a name", packId, queryId)) - } - } - } - - // we compile after the checks because it removes the uids and replaces it with mrns - schema := providers.DefaultRuntime().Schema() - _, err := queryPackBundle.Compile(context.Background(), schema) - if err != nil { - errors = append(errors, "could not compile the query pack bundle", err.Error()) - } - - return errors -} - // ensureProviders ensures that all providers are locally installed func ensureProviders() error { for _, v := range providers.DefaultProviders { @@ -139,7 +96,7 @@ var queryPackLintCmd = &cobra.Command{ return cli_errors.NewCommandError(errors.Wrap(err, "could not load query pack"), 1) } - errors := validate(queryPackBundle) + errors := bundle.Lint(queryPackBundle) if len(errors) > 0 { log.Error().Msg("could not validate query pack") for i := range errors { @@ -177,7 +134,7 @@ var queryPackPublishCmd = &cobra.Command{ return cli_errors.NewCommandError(errors.Wrap(err, "could not load query pack bundle"), 1) } - bundleErrors := validate(queryPackBundle) + bundleErrors := bundle.Lint(queryPackBundle) if len(bundleErrors) > 0 { log.Error().Msg("could not validate query pack") for i := range bundleErrors { diff --git a/examples/complex.mql.yaml b/examples/complex.mql.yaml index 1253c77790..b247193b6a 100644 --- a/examples/complex.mql.yaml +++ b/examples/complex.mql.yaml @@ -5,6 +5,7 @@ # show off some of the more advanced features. It is meant as a demo only. packs: - uid: mixed-os + name: Sample OS Query Pack for Linux and macOS filters: - asset.family.contains("unix") diff --git a/examples/k8s.mql.yaml b/examples/k8s.mql.yaml index d6b86b7532..ddad67531e 100644 --- a/examples/k8s.mql.yaml +++ b/examples/k8s.mql.yaml @@ -3,6 +3,7 @@ packs: - uid: kubernetes-pod-security-info + name: Kubernetes Pod Security Info filters: - asset.platform == "k8s-pod" queries: diff --git a/examples/lint_test.go b/examples/lint_test.go new file mode 100644 index 0000000000..abccf72d60 --- /dev/null +++ b/examples/lint_test.go @@ -0,0 +1,20 @@ +// Copyright (c) Mondoo, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package examples + +import ( + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + "go.mondoo.com/cnquery/v10/explorer" + "go.mondoo.com/cnquery/v10/internal/bundle" + "testing" +) + +func TestExampleLint(t *testing.T) { + queryPackBundle, err := explorer.BundleFromPaths(".") + require.NoError(t, err) + + lintErr := bundle.Lint(queryPackBundle) + assert.Equal(t, []string{}, lintErr) +} diff --git a/examples/os.mql.yaml b/examples/os.mql.yaml index d566a08a23..b1b1d3b77f 100644 --- a/examples/os.mql.yaml +++ b/examples/os.mql.yaml @@ -3,6 +3,7 @@ packs: - uid: linux-mixed-queries + name: Linux Mixed Queries filters: - asset.family.contains("unix") diff --git a/internal/bundle/lint.go b/internal/bundle/lint.go new file mode 100644 index 0000000000..c395351dea --- /dev/null +++ b/internal/bundle/lint.go @@ -0,0 +1,55 @@ +// Copyright (c) Mondoo, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package bundle + +import ( + "context" + "fmt" + "go.mondoo.com/cnquery/v10/explorer" + "go.mondoo.com/cnquery/v10/providers" + "strconv" +) + +func Lint(queryPackBundle *explorer.Bundle) []string { + errors := []string{} + + // check that we have uids for packs and queries + for i := range queryPackBundle.Packs { + pack := queryPackBundle.Packs[i] + packId := strconv.Itoa(i) + + if pack.Uid == "" { + errors = append(errors, fmt.Sprintf("pack %s does not define a uid", packId)) + } else { + packId = pack.Uid + } + + if pack.Name == "" { + errors = append(errors, fmt.Sprintf("pack %s does not define a name", packId)) + } + + for j := range pack.Queries { + query := pack.Queries[j] + queryId := strconv.Itoa(j) + if query.Uid == "" { + errors = append(errors, fmt.Sprintf("query %s/%s does not define a uid", packId, queryId)) + } else { + queryId = query.Uid + } + + if query.Title == "" { + errors = append(errors, fmt.Sprintf("query %s/%s does not define a name", packId, queryId)) + } + } + } + + // we compile after the checks because it removes the uids and replaces it with mrns + schema := providers.DefaultRuntime().Schema() + _, err := queryPackBundle.Compile(context.Background(), schema) + if err != nil { + errors = append(errors, "could not compile the query pack bundle", err.Error()) + } + + return errors +}