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

⭐️ new vuln mgmt api #1173

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
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
13 changes: 6 additions & 7 deletions apps/cnspec/cmd/policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import (
"go.mondoo.com/cnquery/v10/cli/theme"
"go.mondoo.com/cnquery/v10/providers"
"go.mondoo.com/cnquery/v10/providers-sdk/v1/upstream"
"go.mondoo.com/cnquery/v10/providers-sdk/v1/upstream/gql"
"go.mondoo.com/cnspec/v10/internal/bundle"
"go.mondoo.com/cnspec/v10/policy"
cnspec_upstream "go.mondoo.com/cnspec/v10/upstream"
Expand Down Expand Up @@ -115,8 +114,8 @@ var policyListCmd = &cobra.Command{
}

assignedOnly := !viper.GetBool("all")
policies, err = cnspec_upstream.SearchPolicy(
context.Background(), mondooClient, opts.GetParentMrn(), ptr.To(assignedOnly), ptr.To(true), ptr.To(true))
policies, err = mondooClient.SearchPolicy(
context.Background(), opts.GetParentMrn(), ptr.To(assignedOnly), ptr.To(true), ptr.To(true))
if err != nil {
return err
}
Expand Down Expand Up @@ -247,7 +246,7 @@ var policyUploadCmd = &cobra.Command{
fmt.Println(termenv.String(" " + getPolicyMrn(opts.GetParentMrn(), p.Uid)).Foreground(theme.DefaultTheme.Colors.Disabled))
}

space, err := cnspec_upstream.GetSpace(ctx, mondooClient, opts.GetParentMrn())
space, err := mondooClient.GetSpace(ctx, opts.GetParentMrn())
if err != nil {
log.Error().Msgf("failed to get space: %s", err)
os.Exit(1)
Expand Down Expand Up @@ -308,7 +307,7 @@ var policyDeleteCmd = &cobra.Command{
os.Exit(1)
}

space, err := cnspec_upstream.GetSpace(ctx, mondooClient, opts.GetParentMrn())
space, err := mondooClient.GetSpace(ctx, opts.GetParentMrn())
if err != nil {
log.Error().Msgf("failed to get space: %s", err)
os.Exit(1)
Expand Down Expand Up @@ -721,7 +720,7 @@ var policyDocsCmd = &cobra.Command{
},
}

func getGqlClient(opts *config.Config) (*gql.MondooClient, error) {
func getGqlClient(opts *config.Config) (*cnspec_upstream.MondooClient, error) {
serviceAccount := opts.GetServiceCredential()
if serviceAccount == nil {
return nil, fmt.Errorf("cnspec has no credentials. Log in with `cnspec login`")
Expand All @@ -739,7 +738,7 @@ func getGqlClient(opts *config.Config) (*gql.MondooClient, error) {
Creds: serviceAccount,
}

mondooClient, err := gql.NewClient(upstreamConfig, httpClient)
mondooClient, err := cnspec_upstream.NewClient(upstreamConfig, httpClient)
if err != nil {
return nil, err
}
Expand Down
175 changes: 60 additions & 115 deletions apps/cnspec/cmd/vuln.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,24 +4,19 @@
package cmd

import (
"context"
"encoding/json"
"strings"

"bytes"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"go.mondoo.com/cnquery/v10/cli/shell"
"go.mondoo.com/cnquery/v10/explorer/executor"
"go.mondoo.com/cnquery/v10/logger"
"go.mondoo.com/cnquery/v10/providers"
"go.mondoo.com/cnquery/v10/providers-sdk/v1/plugin"
"go.mondoo.com/cnquery/v10/providers-sdk/v1/upstream/gql"
"go.mondoo.com/cnquery/v10/providers-sdk/v1/upstream/mvd"
"go.mondoo.com/cnquery/v10/sbom"
"go.mondoo.com/cnquery/v10/shared"
"go.mondoo.com/cnspec/v10/cli/reporter"
mondoogql "go.mondoo.com/mondoo-go"
"go.mondoo.com/ranger-rpc/codes"
"go.mondoo.com/ranger-rpc/status"
"go.mondoo.com/cnspec/v10/policy"
"strings"
)

func init() {
Expand All @@ -43,147 +38,97 @@ var vulnCmd = &cobra.Command{
PreRun: func(cmd *cobra.Command, args []string) {
// for all assets
viper.BindPFlag("platform-id", cmd.Flags().Lookup("platform-id"))

viper.BindPFlag("inventory-file", cmd.Flags().Lookup("inventory-file"))
viper.BindPFlag("inventory-ansible", cmd.Flags().Lookup("inventory-ansible"))
viper.BindPFlag("inventory-domainlist", cmd.Flags().Lookup("inventory-domainlist"))
},
}

var vulnCmdRun = func(cmd *cobra.Command, runtime *providers.Runtime, cliRes *plugin.ParseCLIRes) {
conf, err := getCobraScanConfig(cmd, runtime, cliRes)
// conf := cnquery_app.ParseShellConfig(cmd, cliRes)
pb, err := sbom.QueryPack()
if err != nil {
log.Fatal().Err(err).Msg("failed to prepare config")
}

unauthedErrorMsg := "vulnerability scan requires authentication, login with `cnspec login --token`"
if runtime.UpstreamConfig == nil {
log.Fatal().Msg(unauthedErrorMsg)
log.Fatal().Err(err).Msg("failed to load sbom query pack")
}

err = runtime.Connect(&plugin.ConnectReq{
Features: conf.Features,
Asset: cliRes.Asset,
Upstream: runtime.UpstreamConfig,
})
conf, err := getCobraScanConfig(cmd, runtime, cliRes)
if err != nil {
log.Fatal().Err(err).Msg("could not load asset information")
log.Fatal().Err(err).Msg("failed to gather scan config")
}

// when we close the shell, we need to close the backend and store the recording
onCloseHandler := func() {
// close backend connection
runtime.Close()
}

shellOptions := []shell.ShellOption{}
shellOptions = append(shellOptions, shell.WithOnCloseListener(onCloseHandler))
shellOptions = append(shellOptions, shell.WithFeatures(conf.Features))

if conf.runtime.UpstreamConfig != nil {
shellOptions = append(shellOptions, shell.WithUpstreamConfig(conf.runtime.UpstreamConfig))
}
conf.PolicyNames = nil
conf.PolicyPaths = nil
conf.Bundle = policy.FromQueryPackBundle(pb)
conf.IsIncognito = true

sh, err := shell.New(runtime, shellOptions...)
report, err := RunScan(conf)
if err != nil {
log.Error().Err(err).Msg("failed to initialize cnspec shell")
log.Fatal().Err(err).Msg("error happened during package analysis")
}

packagesQuery := "packages { name version origin format }"
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
buf := bytes.Buffer{}
w := shared.IOWriter{Writer: &buf}
err = reporter.ReportCollectionToJSON(report, &w)
if err == nil {
logger.DebugDumpJSON("mondoo-sbom-report", buf.Bytes())
}

// render vulnerability report
value, ok := results[packagesDatapointChecksum]
if !ok {
log.Error().Msg("could not find packages data\n\n")
return
boms, err := sbom.NewBom(buf.Bytes())
if err != nil {
log.Fatal().Err(err).Msg("failed to parse sbom data")
}

if value == nil || value.Data == nil {
log.Error().Msg("could not load packages data\n\n")
return
if len(boms) != 1 {
log.Fatal().Msg("received data for more than one asset, this is not supported yet.")
}
bom := boms[0]

if value.Data.Error != nil {
log.Err(value.Data.Error).Msg("could not load packages data\n\n")
return
ctx := cmd.Context()
upstreamConf := conf.runtime.UpstreamConfig
if upstreamConf == nil {
log.Fatal().Err(err).Msg("run `cnspec login` to authenticate with Mondoo platform")
}

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

gqlPackages := []mondoogql.PackageInput{}
err = json.Unmarshal(packagesJson, &gqlPackages)
client, err := upstreamConf.InitClient(ctx)
if err != nil {
log.Error().Err(err).Msg("failed to unmarshal packages")
return
log.Fatal().Err(err).Msg("failed to initialize authentication with Mondoo platform")
}

client, err := runtime.UpstreamConfig.InitClient(context.Background())
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(err).Msg("could not authenticate upstream")
return
}
}
}
mondooClient, err := gql.NewClient(runtime.UpstreamConfig, client.HttpClient)
scannerClient, err := mvd.NewAdvisoryScannerClient(client.ApiEndpoint, client.HttpClient, client.Plugins...)
if err != nil {
log.Error().Err(err).Msg("could not initialize mondoo client")
return
}

platform := runtime.Provider.Connection.GetAsset().GetPlatform()
family := []*mondoogql.String{}
for _, f := range platform.Family {
family = append(family, mondoogql.NewStringPtr(mondoogql.String(f)))
}
inputPlatform := mondoogql.PlatformInput{
Name: mondoogql.NewStringPtr(mondoogql.String(platform.Name)),
Release: mondoogql.NewStringPtr(mondoogql.String(platform.Version)),
Build: mondoogql.NewStringPtr(mondoogql.String(platform.Build)),
Family: &family,
}
inputLabels := []*mondoogql.KeyValueInput{}
for k := range platform.Labels {
inputLabels = append(inputLabels, &mondoogql.KeyValueInput{
Key: mondoogql.String(k),
Value: mondoogql.NewStringPtr(mondoogql.String(platform.Labels[k])),
log.Fatal().Err(err).Msg("failed to initialize advisory scanner client")
}

req := &mvd.AnalyseAssetRequest{
Platform: &mvd.Platform{
Name: bom.Asset.Platform.Name,
Arch: bom.Asset.Platform.Arch,
Build: bom.Asset.Platform.Build,
Release: bom.Asset.Platform.Version,
Labels: bom.Asset.Platform.Labels,
Title: bom.Asset.Platform.Title,
},
Packages: make([]*mvd.Package, 0),
}

for i := range bom.Packages {
pkg := bom.Packages[i]
req.Packages = append(req.Packages, &mvd.Package{
Name: pkg.Name,
Version: pkg.Version,
Arch: pkg.Architecture,
Format: pkg.Type,
Origin: pkg.Origin,
})
}
inputPlatform.Labels = &inputLabels
gqlVulnReport, err := mondooClient.GetIncognitoVulnReport(inputPlatform, gqlPackages)
if err != nil {
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
vulnReport, err := scannerClient.AnalyseAsset(ctx, req)
if err != nil {
log.Fatal().Err(err).Msg("failed to analyse asset")
}

printVulns(vulnReport, conf, target)
}

func printVulns(report *mvd.VulnReport, conf *scanConfig, target string) {
// print the output using the specified output format
r := reporter.NewReporter(reporter.Formats[strings.ToLower(conf.OutputFormat)], false)

logger.DebugDumpJSON("vulnReport", report)
if err := r.PrintVulns(report, target); err != nil {
if err := r.PrintVulns(vulnReport, bom.Asset.Name); err != nil {
log.Fatal().Err(err).Msg("failed to print")
}
}
2 changes: 1 addition & 1 deletion cli/components/advisory_results.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
"github.com/olekukonko/tablewriter"
"go.mondoo.com/cnquery/v10/providers-sdk/v1/upstream/mvd"
"go.mondoo.com/cnquery/v10/providers-sdk/v1/upstream/mvd/cvss"
"go.mondoo.com/cnspec/v10/cli/components/advisories"
"go.mondoo.com/cnspec/v10/cli/reporter/vuln/advisories"
)

func NewAdvisoryResultTable() AdvisoryResultTable {
Expand Down
7 changes: 4 additions & 3 deletions cli/reporter/cli_reporter.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
"go.mondoo.com/cnquery/v10/providers-sdk/v1/upstream/mvd"
"go.mondoo.com/cnquery/v10/shared"
"go.mondoo.com/cnspec/v10/policy"
"go.mondoo.com/cnspec/v10/vuln"

Check failure on line 23 in cli/reporter/cli_reporter.go

View workflow job for this annotation

GitHub Actions / go-test

no required module provides package go.mondoo.com/cnspec/v10/vuln; to add it:

Check failure on line 23 in cli/reporter/cli_reporter.go

View workflow job for this annotation

GitHub Actions / go-test

no required module provides package go.mondoo.com/cnspec/v10/vuln; to add it:

Check failure on line 23 in cli/reporter/cli_reporter.go

View workflow job for this annotation

GitHub Actions / go-test

no required module provides package go.mondoo.com/cnspec/v10/vuln; to add it:
"sigs.k8s.io/yaml"
)

Expand Down Expand Up @@ -199,11 +200,11 @@
return errors.New("'junit' is not supported for vuln reports, please use one of the other formats")
case CSV:
writer := shared.IOWriter{Writer: r.out}
return VulnReportToCSV(data, &writer)
return vuln.VulnReportToCSV(data, &writer)
case YAML:
raw := bytes.Buffer{}
writer := shared.IOWriter{Writer: &raw}
err := VulnReportToJSON(target, data, &writer)
err := vuln.VulnReportToJSON(target, data, &writer)
if err != nil {
return err
}
Expand All @@ -216,7 +217,7 @@
return err
case JSON:
writer := shared.IOWriter{Writer: r.out}
return VulnReportToJSON(target, data, &writer)
return vuln.VulnReportToJSON(target, data, &writer)
default:
return errors.New("unknown reporter type, don't recognize this Format")
}
Expand Down
4 changes: 2 additions & 2 deletions cli/reporter/csv_vuln.go → cli/reporter/vuln/csv_vuln.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) Mondoo, Inc.
// SPDX-License-Identifier: BUSL-1.1

package reporter
package vuln

import (
"encoding/csv"
Expand All @@ -11,7 +11,7 @@ import (
"go.mondoo.com/cnquery/v10/providers-sdk/v1/upstream/mvd"
"go.mondoo.com/cnquery/v10/shared"
"go.mondoo.com/cnspec/v10/cli/components"
"go.mondoo.com/cnspec/v10/cli/components/advisories"
"go.mondoo.com/cnspec/v10/cli/reporter/vuln/advisories"
)

type csvStruct struct {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) Mondoo, Inc.
// SPDX-License-Identifier: BUSL-1.1

package reporter
package vuln

import (
"bytes"
Expand Down
4 changes: 2 additions & 2 deletions cli/reporter/json_vuln.go → cli/reporter/vuln/json_vuln.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) Mondoo, Inc.
// SPDX-License-Identifier: BUSL-1.1

package reporter
package vuln

import (
"encoding/json"
Expand All @@ -13,7 +13,7 @@ import (
"go.mondoo.com/cnquery/v10/providers-sdk/v1/upstream/mvd"
"go.mondoo.com/cnquery/v10/shared"
"go.mondoo.com/cnspec/v10/cli/components"
"go.mondoo.com/cnspec/v10/cli/components/advisories"
"go.mondoo.com/cnspec/v10/cli/reporter/vuln/advisories"
)

// advisoryPrintable is a snapshot of the fields that get exported
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Copyright (c) Mondoo, Inc.
// SPDX-License-Identifier: BUSL-1.1

package reporter
package vuln

import (
"bytes"
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ require (
github.com/spf13/pflag v1.0.6-0.20201009195203-85dd5c8bc61c
github.com/spf13/viper v1.18.2
github.com/stretchr/testify v1.9.0
go.mondoo.com/cnquery/v10 v10.7.1
go.mondoo.com/cnquery/v10 v10.7.2-0.20240313135139-202e991e6f97
go.mondoo.com/mondoo-go v0.0.0-20240312054001-2ab23a39b500
go.mondoo.com/ranger-rpc v0.6.0
go.opentelemetry.io/otel v1.24.0
Expand Down
Loading
Loading