Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

✨ Add new server-side vulnerability report #978

Merged
merged 3 commits into from
Dec 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -134,3 +134,8 @@ test/lint/govet:
test/lint/golangci-lint/run: prep/tools
golangci-lint --version
golangci-lint run

.PHONY: test/lint/golangci-lint/run/new
test/lint/golangci-lint/run/new: prep/tools
golangci-lint --version
golangci-lint run --timeout 10m --config .github/.golangci.yml --new-from-rev $(shell git log -n 1 origin/main --pretty=format:"%H")
59 changes: 39 additions & 20 deletions apps/cnspec/cmd/vuln.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,9 @@
package cmd

import (
"encoding/json"
"os"

"github.com/mitchellh/mapstructure"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
"github.com/spf13/viper"
Expand All @@ -15,8 +15,10 @@ import (
"go.mondoo.com/cnquery/v9/logger"
"go.mondoo.com/cnquery/v9/providers"
"go.mondoo.com/cnquery/v9/providers-sdk/v1/plugin"
"go.mondoo.com/cnquery/v9/providers-sdk/v1/upstream/gql"
"go.mondoo.com/cnquery/v9/providers-sdk/v1/upstream/mvd"
"go.mondoo.com/cnspec/v9/cli/reporter"
mondoogql "go.mondoo.com/mondoo-go"
"go.mondoo.com/ranger-rpc/codes"
"go.mondoo.com/ranger-rpc/status"
)
Expand Down Expand Up @@ -87,60 +89,77 @@ var vulnCmdRun = func(cmd *cobra.Command, runtime *providers.Runtime, cliRes *pl
log.Error().Err(err).Msg("failed to initialize cnspec shell")
}

vulnReportQuery := "asset.vulnerabilityReport"
vulnReportDatapointChecksum := executor.MustGetOneDatapoint(executor.MustCompile(vulnReportQuery))
_, results, err := sh.RunOnce(vulnReportQuery)
packagesQuery := "packages{ name version }"
packagesDatapointChecksum := executor.MustGetOneDatapoint(executor.MustCompile(packagesQuery))
codeBundle, results, err := sh.RunOnce(packagesQuery)
if err != nil {
log.Error().Err(err).Msg("failed to run query")
return
}

// render vulnerability report
var vulnReport mvd.VulnReport
value, ok := results[vulnReportDatapointChecksum]
value, ok := results[packagesDatapointChecksum]
if !ok {
log.Error().Msg("could not find advisory report\n\n")
log.Error().Msg("could not find packages data\n\n")
return
}

if value == nil || value.Data == nil {
log.Error().Msg("could not load advisory report\n\n")
log.Error().Msg("could not load packages data\n\n")
return
}

if value.Data.Error != nil {
err := value.Data.Error
log.Err(value.Data.Error).Msg("could not load packages data\n\n")
return
}

packagesJson := value.Data.JSON(packagesDatapointChecksum, codeBundle)

gqlPackages := []mondoogql.PackageInput{}
err = json.Unmarshal(packagesJson, &gqlPackages)
if err != nil {
log.Error().Err(err).Msg("failed to unmarshal packages")
return
}

client, err := runtime.UpstreamConfig.InitClient()
if err != nil {
if status, ok := status.FromError(err); ok {
code := status.Code()
switch code {
case codes.Unauthenticated:
log.Fatal().Msg(unauthedErrorMsg)
default:
log.Err(value.Data.Error).Msg("could not load advisory report")
log.Err(err).Msg("could not authenticate upstream")
return
}
}
}

rawData := value.Data.Value
cfg := &mapstructure.DecoderConfig{
Metadata: nil,
Result: &vulnReport,
TagName: "json",
mondooClient, err := gql.NewClient(*runtime.UpstreamConfig, client.HttpClient)
if err != nil {
log.Error().Err(err).Msg("could not initialize mondoo client")
return
}
decoder, _ := mapstructure.NewDecoder(cfg)
err = decoder.Decode(rawData)

platform := runtime.Provider.Connection.GetAsset().GetPlatform()
gqlVulnReport, err := mondooClient.GetIncognitoVulnReport(mondoogql.PlatformInput{
Name: mondoogql.NewStringPtr(mondoogql.String(platform.Name)),
Release: mondoogql.NewStringPtr(mondoogql.String(platform.Version)),
}, gqlPackages)
if err != nil {
log.Error().Msg("could not decode advisory report\n\n")
log.Error().Err(err).Msg("could not load advisory report")
return
}

vulnReport := gql.ConvertToMvdVulnReport(gqlVulnReport)

target := runtime.Provider.Connection.Asset.Name
if target == "" {
target = runtime.Provider.Connection.Asset.Mrn
}

printVulns(&vulnReport, conf, target)
printVulns(vulnReport, conf, target)
}

func printVulns(report *mvd.VulnReport, conf *scanConfig, target string) {
Expand Down
33 changes: 7 additions & 26 deletions cli/reporter/print_compact.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ import (
"strings"
"unicode/utf8"

"github.com/mitchellh/mapstructure"
"github.com/muesli/ansi"
"github.com/muesli/termenv"
"github.com/rs/zerolog/log"
Expand Down Expand Up @@ -362,7 +361,7 @@ func (r *defaultReporter) printAssetSections(orderedAssets []assetMrnName) {
r.printAssetQueries(resolved, report, queries, assetMrn, asset)
r.out.Write([]byte(NewLineCharacter))
// TODO: we should re-use the report results
r.printVulns(resolved, report, report.RawResults())
r.printVulns(report, assetMrn)

}
r.out.Write([]byte(NewLineCharacter))
Expand Down Expand Up @@ -586,39 +585,21 @@ 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) {
func (r *defaultReporter) printVulns(report *policy.Report, assetMrn string) {
print := r.Printer

value, _ := getVulnReport(results)
if value == nil || value.Data == nil {
return
}
if value.Data.Error != nil {
r.out.Write([]byte(print.Error("Could not load the vulnerability report: "+value.Data.Error.Error()) + NewLineCharacter + NewLineCharacter))
vulnReport := r.data.VulnReports[assetMrn]

if vulnReport == nil {
return
}

r.out.Write([]byte(print.Primary("Vulnerabilities:" + NewLineCharacter)))

score := report.Scores[advisoryPolicyMrn]
_ = score

rawData := value.Data.Value

var vulnReport mvd.VulnReport
cfg := &mapstructure.DecoderConfig{
Metadata: nil,
Result: &vulnReport,
TagName: "json",
}
decoder, _ := mapstructure.NewDecoder(cfg)
if err := decoder.Decode(rawData); err != nil {
r.out.Write([]byte(print.Error("could not decode advisory report" + NewLineCharacter + NewLineCharacter)))
return
}

r.printVulnList(&vulnReport)
r.printVulnSummary(&vulnReport)
r.printVulnList(vulnReport)
r.printVulnSummary(vulnReport)
}

func (r *defaultReporter) printVulnList(report *mvd.VulnReport) {
Expand Down
2 changes: 1 addition & 1 deletion cli/reporter/reporter.pb.go

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

6 changes: 4 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ go 1.21

toolchain go1.21.3

require go.mondoo.com/cnquery/v9 v9.11.0
require (
go.mondoo.com/cnquery/v9 v9.11.0
go.mondoo.com/mondoo-go v0.0.0-20231208095824-90b6fcd58afb
)

require (
github.com/Masterminds/semver v1.5.0
Expand Down Expand Up @@ -112,7 +115,6 @@ require (
github.com/xen0n/gosmopolitan v1.2.2 // indirect
github.com/ykadowak/zerologlint v0.1.4 // indirect
go-simpler.org/sloglint v0.3.0 // indirect
go.mondoo.com/mondoo-go v0.0.0-20231208095824-90b6fcd58afb // indirect
go.opentelemetry.io/otel/metric v1.21.0 // indirect
go.tmz.dev/musttag v0.7.2 // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20231127180814-3a041ad873d4 // indirect
Expand Down
Loading