From 1cac0459ec520ec8193a7fda63dffb70c2b43641 Mon Sep 17 00:00:00 2001 From: Dominik Richter Date: Sun, 10 Sep 2023 09:52:29 -0700 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=9B=20datapoints=20are=20conditional?= =?UTF-8?q?=20on=20providers?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The os provider may not exist on the run or on the system. In these cases, the method to determine the datapoint for vulnerability report or kernel info will fail. To better handle these errors, we abandon the previous approach of `MustGetOneDatapoint` via `MustCompile` and instead use the provider info to report back to users. There may still be other reasons why the compile fails, but we will keep this focused on the primary reason in a tested environment with a working provider runtime that indicates why this fails: no provider for this code. Signed-off-by: Dominik Richter --- cli/reporter/junit.go | 15 +++++++--- cli/reporter/print_compact.go | 16 +++++++--- cli/reporter/render_advisory_policy.go | 26 ++++++++++++---- cli/reporter/reporter.go | 41 +++++++++++++++++++++++--- 4 files changed, 80 insertions(+), 18 deletions(-) diff --git a/cli/reporter/junit.go b/cli/reporter/junit.go index 1e59e9c0..e95f3d9d 100644 --- a/cli/reporter/junit.go +++ b/cli/reporter/junit.go @@ -10,10 +10,12 @@ import ( "github.com/jstemmer/go-junit-report/v2/junit" "github.com/mitchellh/mapstructure" + "github.com/rs/zerolog/log" "go.mondoo.com/cnquery/explorer" + "go.mondoo.com/cnquery/providers" "go.mondoo.com/cnquery/providers-sdk/v1/inventory" - "go.mondoo.com/cnquery/shared" "go.mondoo.com/cnquery/providers-sdk/v1/upstream/mvd" + "go.mondoo.com/cnquery/shared" "go.mondoo.com/cnspec/policy" ) @@ -162,8 +164,14 @@ func assetMvdTests(r *policy.ReportCollection, assetMrn string, assetObj *invent return nil } + schema := providers.DefaultRuntime().Schema() + vulnChecksum, err := defaultChecksum(vulnReport, schema) + if err != nil { + log.Debug().Err(err).Msg("could not determine vulnerability report checksum") + } + rawResults := results.RawResults() - value, ok := rawResults[vulnReportDatapointChecksum] + value, ok := rawResults[vulnChecksum] if !ok { return nil } @@ -200,8 +208,7 @@ func assetMvdTests(r *policy.ReportCollection, assetMrn string, assetObj *invent TagName: "json", } decoder, _ := mapstructure.NewDecoder(cfg) - err := decoder.Decode(rawData) - if err != nil { + if err = decoder.Decode(rawData); err != nil { ts.Errors++ ts.Testcases = append(ts.Testcases, junit.Testcase{ Failure: &junit.Result{ diff --git a/cli/reporter/print_compact.go b/cli/reporter/print_compact.go index 85426a06..b4ca704d 100644 --- a/cli/reporter/print_compact.go +++ b/cli/reporter/print_compact.go @@ -18,9 +18,10 @@ import ( "go.mondoo.com/cnquery/cli/components" "go.mondoo.com/cnquery/explorer" "go.mondoo.com/cnquery/llx" + "go.mondoo.com/cnquery/providers" "go.mondoo.com/cnquery/providers-sdk/v1/inventory" - "go.mondoo.com/cnquery/utils/stringx" "go.mondoo.com/cnquery/providers-sdk/v1/upstream/mvd" + "go.mondoo.com/cnquery/utils/stringx" cnspecComponents "go.mondoo.com/cnspec/cli/components" "go.mondoo.com/cnspec/policy" ) @@ -583,7 +584,15 @@ func (r *defaultReporter) printCheck(score *policy.Score, query *explorer.Mquery func (r *defaultReporter) printVulns(resolved *policy.ResolvedPolicy, report *policy.Report, results map[string]*llx.RawResult) { print := r.Printer - value, ok := results[vulnReportDatapointChecksum] + schema := providers.DefaultRuntime().Schema() + vulnChecksum, err := defaultChecksum(vulnReport, schema) + if err != nil { + log.Debug().Err(err).Msg("could not determine vulnerability report checksum") + r.out.Write([]byte(print.Error("No vulnerabilities for this provider"))) + return + } + + value, ok := results[vulnChecksum] if !ok { return } @@ -611,8 +620,7 @@ func (r *defaultReporter) printVulns(resolved *policy.ResolvedPolicy, report *po TagName: "json", } decoder, _ := mapstructure.NewDecoder(cfg) - err := decoder.Decode(rawData) - if err != nil { + if err = decoder.Decode(rawData); err != nil { r.out.Write([]byte(print.Error("could not decode advisory report" + NewLineCharacter + NewLineCharacter))) return } diff --git a/cli/reporter/render_advisory_policy.go b/cli/reporter/render_advisory_policy.go index 6d9c0288..eec1f3c4 100644 --- a/cli/reporter/render_advisory_policy.go +++ b/cli/reporter/render_advisory_policy.go @@ -11,10 +11,12 @@ import ( "github.com/mitchellh/mapstructure" "github.com/muesli/termenv" + "github.com/rs/zerolog/log" "go.mondoo.com/cnquery/cli/printer" "go.mondoo.com/cnquery/cli/theme/colors" - "go.mondoo.com/cnquery/utils/stringx" + "go.mondoo.com/cnquery/providers" "go.mondoo.com/cnquery/providers-sdk/v1/upstream/mvd" + "go.mondoo.com/cnquery/utils/stringx" "go.mondoo.com/cnspec/cli/components" "go.mondoo.com/cnspec/policy" ) @@ -34,9 +36,16 @@ func renderAdvisoryPolicy(print *printer.Printer, policyObj *policy.Policy, repo // render mini score card score := report.Scores[policyObj.Mrn] - var vulnReport mvd.VulnReport + schema := providers.DefaultRuntime().Schema() + vulnCheckpoint, err := defaultChecksum(vulnReport, schema) + if err != nil { + log.Debug().Err(err).Msg("could not determine vulnerability report checksum") + b.WriteString(print.Error("no vulnerabilities for this provider")) + return b.String() + } + results := report.Data - value, ok := results[vulnReportDatapointChecksum] + value, ok := results[vulnCheckpoint] if !ok { b.WriteString(print.Error("could not find advisory report" + NewLineCharacter + NewLineCharacter)) return b.String() @@ -54,14 +63,14 @@ func renderAdvisoryPolicy(print *printer.Printer, policyObj *policy.Policy, repo rawData := value.Data.RawData().Value + var vulnReport mvd.VulnReport cfg := &mapstructure.DecoderConfig{ Metadata: nil, Result: &vulnReport, TagName: "json", } decoder, _ := mapstructure.NewDecoder(cfg) - err := decoder.Decode(rawData) - if err != nil { + if err = decoder.Decode(rawData); err != nil { b.WriteString(print.Error("could not decode advisory report" + NewLineCharacter + NewLineCharacter)) return b.String() } @@ -87,7 +96,12 @@ func renderAdvisoryPolicy(print *printer.Printer, policyObj *policy.Policy, repo } // render additional information - kernelDataValue, ok := results[kernelListDatapointChecksum] + kernelInstalledChecksum, err := defaultChecksum(kernelInstalled, schema) + if err != nil { + log.Debug().Err(err).Msg("could not determine installed kernel checksum") + } + + kernelDataValue, ok := results[kernelInstalledChecksum] if ok && kernelDataValue.Data != nil { if kernelDataValue.Error != "" { b.WriteString(print.Error(kernelDataValue.Error + NewLineCharacter)) diff --git a/cli/reporter/reporter.go b/cli/reporter/reporter.go index 9eb0b005..f16c0b33 100644 --- a/cli/reporter/reporter.go +++ b/cli/reporter/reporter.go @@ -9,20 +9,53 @@ import ( "io" "strings" + "go.mondoo.com/cnquery" "go.mondoo.com/cnquery/cli/printer" "go.mondoo.com/cnquery/cli/theme/colors" - ee "go.mondoo.com/cnquery/explorer/executor" + "go.mondoo.com/cnquery/llx" + "go.mondoo.com/cnquery/mqlc" "go.mondoo.com/cnquery/providers-sdk/v1/upstream/mvd" "go.mondoo.com/cnquery/shared" "go.mondoo.com/cnspec/policy" "sigs.k8s.io/yaml" ) -var ( - vulnReportDatapointChecksum = ee.MustGetOneDatapoint(ee.MustCompile("asset.vulnerabilityReport")) - kernelListDatapointChecksum = ee.MustGetOneDatapoint(ee.MustCompile("kernel.installed")) +type mqlCode string + +const ( + vulnReport mqlCode = "asset.VulnerabilityReport" + kernelInstalled mqlCode = "kernel.installed" ) +var _defaultChecksums = map[mqlCode]struct { + sum string + err error +}{} + +func defaultChecksum(code mqlCode, schema llx.Schema) (string, error) { + res, ok := _defaultChecksums[code] + if ok { + return res.sum, res.err + } + + codeBundle, err := mqlc.Compile(string(code), nil, + mqlc.NewConfig(schema, cnquery.DefaultFeatures)) + if err != nil { + res.err = err + } else if len(codeBundle.CodeV2.Entrypoints()) != 1 { + res.err = errors.New("code bundle should only have 1 entrypoint for: " + string(code)) + } else { + entrypoint := codeBundle.CodeV2.Entrypoints()[0] + res.sum, ok = codeBundle.CodeV2.Checksums[entrypoint] + if !ok { + res.err = errors.New("could not find the datapoint for: " + string(code)) + } + } + + _defaultChecksums[code] = res + return res.sum, res.err +} + type Reporter struct { Format Format Printer *printer.Printer