From 31170b9422d55b72979aace22ee42f152b940f3f Mon Sep 17 00:00:00 2001 From: Christian Zunker Date: Fri, 24 Nov 2023 12:02:13 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20New=20vulnmgmt=20resources?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Christian Zunker --- .vscode/launch.json | 5 +- Makefile | 2 + go.mod | 8 +- go.sum | 10 +- providers-sdk/v1/upstream/gql/client.go | 35 ++ providers-sdk/v1/upstream/gql/vulnmgmt_gql.go | 211 ++++++++ providers/atlassian/config/config.go | 2 +- providers/atlassian/go.mod | 4 +- providers/atlassian/go.sum | 4 + providers/core/resources/core.lr | 3 + providers/core/resources/core.lr.go | 47 ++ .../core/resources/core.lr.manifest.yaml | 54 ++ providers/core/resources/core.resources.json | 2 +- providers/os/resources/os.lr | 63 ++- providers/os/resources/os.lr.go | 478 ++++++++++++++++++ providers/os/resources/os.lr.manifest.yaml | 42 ++ providers/os/resources/vulnmgmt.go | 195 +++++++ providers/vsphere/resources/vsphere.lr | 1 + 18 files changed, 1153 insertions(+), 13 deletions(-) create mode 100644 providers-sdk/v1/upstream/gql/client.go create mode 100644 providers-sdk/v1/upstream/gql/vulnmgmt_gql.go create mode 100644 providers/os/resources/vulnmgmt.go diff --git a/.vscode/launch.json b/.vscode/launch.json index 3f02d20160..c591d8be22 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -44,9 +44,10 @@ "cwd": "${workspaceRoot}/", "args": [ "run", - // "local", "-c", - "asset.eol" + "vulnmgmt.advisories", + "--config", + "/home/christian/demo.agent.credentials.json" ], }, { diff --git a/Makefile b/Makefile index 5a672613ef..68f52c0a3b 100644 --- a/Makefile +++ b/Makefile @@ -74,6 +74,8 @@ prep/tools: prep/tools/protolint cnquery/generate: clean/proto llx/generate shared/generate providers explorer/generate sbom/generate +cnquery/generate/core: clean/proto llx/generate shared/generate providers/proto providers/build/mock providers/build/core explorer/generate + define buildProvider $(eval $@_HOME = $(1)) $(eval $@_NAME = $(shell basename ${$@_HOME})) diff --git a/go.mod b/go.mod index 042571db1c..53da8988ef 100644 --- a/go.mod +++ b/go.mod @@ -141,6 +141,7 @@ require ( github.com/sagikazarmark/locafero v0.3.0 // indirect github.com/sagikazarmark/slog-shim v0.1.0 // indirect github.com/sergi/go-diff v1.3.1 // indirect + github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466 // indirect github.com/skeema/knownhosts v1.2.1 // indirect github.com/smarty/assertions v1.15.1 // indirect github.com/sourcegraph/conc v0.3.0 // indirect @@ -224,7 +225,7 @@ require ( github.com/fzipp/gocyclo v0.6.0 // indirect github.com/getsentry/sentry-go v0.25.0 // indirect github.com/go-critic/go-critic v0.9.0 // indirect - github.com/go-jose/go-jose/v3 v3.0.0 // indirect + github.com/go-jose/go-jose/v3 v3.0.1 // indirect github.com/go-logr/logr v1.3.0 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-ole/go-ole v1.3.0 // indirect @@ -367,6 +368,7 @@ require ( github.com/yeya24/promlinter v0.2.0 // indirect github.com/ykadowak/zerologlint v0.1.3 // indirect gitlab.com/bosi/decorder v0.4.1 // indirect + go.mondoo.com/mondoo-go v0.0.0-20231115081401-e27ff48607b6 go.opencensus.io v0.24.0 // indirect go.opentelemetry.io/otel/trace v1.21.0 // indirect go.tmz.dev/musttag v0.7.2 // indirect @@ -375,7 +377,7 @@ require ( golang.org/x/exp v0.0.0-20231006140011-7918f672742d golang.org/x/exp/typeparams v0.0.0-20231006140011-7918f672742d // indirect golang.org/x/mod v0.14.0 - golang.org/x/oauth2 v0.13.0 // indirect + golang.org/x/oauth2 v0.14.0 // indirect golang.org/x/time v0.3.0 // indirect golang.org/x/xerrors v0.0.0-20231012003039-104605ab7028 // indirect google.golang.org/api v0.149.0 // indirect @@ -398,3 +400,5 @@ require ( sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/structured-merge-diff/v4 v4.3.0 // indirect ) + +replace go.mondoo.com/mondoo-go => /home/christian/workspace/mondoo/github.com/mondoo-go diff --git a/go.sum b/go.sum index 21175e9d4c..181b1725a0 100644 --- a/go.sum +++ b/go.sum @@ -390,8 +390,8 @@ github.com/go-git/go-git/v5 v5.10.0/go.mod h1:1FOZ/pQnqw24ghP2n7cunVl0ON55BsjPYv github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= -github.com/go-jose/go-jose/v3 v3.0.0 h1:s6rrhirfEP/CGIoc6p+PZAeogN2SxKav6Wp7+dyMWVo= -github.com/go-jose/go-jose/v3 v3.0.0/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8= +github.com/go-jose/go-jose/v3 v3.0.1 h1:pWmKFVtt+Jl0vBZTIpz/eAKwsm6LkIxDVVbFHKkchhA= +github.com/go-jose/go-jose/v3 v3.0.1/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/log v0.1.0/go.mod h1:zbhenjAZHb184qTLMA9ZjW7ThYL0H2mk7Q6pNt4vbaY= @@ -985,6 +985,8 @@ github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c h1:W65qqJCIOVP4jpqP github.com/shazow/go-diff v0.0.0-20160112020656-b6b7b6733b8c/go.mod h1:/PevMnwAxekIXwN8qQyfc5gl2NlkB3CQlkizAbOkeBs= github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk= github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ= +github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466 h1:17JxqqJY66GmZVHkmAsGEkcIu0oCe3AM420QDgGwZx0= +github.com/shurcooL/graphql v0.0.0-20230722043721-ed46e5a46466/go.mod h1:9dIRpgIY7hVhoqfe0/FcYp0bpInZaT7dc3BYOprrIUE= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88= @@ -1291,8 +1293,8 @@ golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY= -golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0= +golang.org/x/oauth2 v0.14.0 h1:P0Vrf/2538nmC0H+pEQ3MNFRRnVR7RlqyVw+bvm26z0= +golang.org/x/oauth2 v0.14.0/go.mod h1:lAtNWgaWfL4cm7j2OV8TxGi9Qb7ECORx8DktCY74OwM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= diff --git a/providers-sdk/v1/upstream/gql/client.go b/providers-sdk/v1/upstream/gql/client.go new file mode 100644 index 0000000000..2f3bac75cb --- /dev/null +++ b/providers-sdk/v1/upstream/gql/client.go @@ -0,0 +1,35 @@ +package gql + +import ( + "encoding/json" + "net/http" + + "go.mondoo.com/cnquery/v9/providers-sdk/v1/upstream" + mondoogql "go.mondoo.com/mondoo-go" + "go.mondoo.com/mondoo-go/option" +) + +type MondooClient struct { + *mondoogql.Client +} + +// NewClient creates a new GraphQL client for the Mondoo API +// provide the http client used for rpc, to also pass in the proxy settings +func NewClient(upstream upstream.UpstreamConfig, httpClient *http.Client) (*MondooClient, error) { + gqlEndpoint := upstream.ApiEndpoint + "/query" + creds, err := json.Marshal(upstream.Creds) + if err != nil { + return nil, err + } + // Initialize the client + mondooClient, err := mondoogql.NewClient( + option.WithEndpoint(gqlEndpoint), + option.WithHTTPClient(httpClient), + option.WithServiceAccount(creds), + ) + if err != nil { + return nil, err + } + + return &MondooClient{mondooClient}, nil +} diff --git a/providers-sdk/v1/upstream/gql/vulnmgmt_gql.go b/providers-sdk/v1/upstream/gql/vulnmgmt_gql.go new file mode 100644 index 0000000000..97bb4c79a2 --- /dev/null +++ b/providers-sdk/v1/upstream/gql/vulnmgmt_gql.go @@ -0,0 +1,211 @@ +// FIXME: ??? should this file move to the resources inside the provider ??? +package gql + +import ( + "context" + + mondoogql "go.mondoo.com/mondoo-go" +) + +// FIXME: move these to the provider + +// LastAssessment fetches the las update time of the packages query +// This is also the lst time the vuln report was updated +func (c *MondooClient) LastAssessment(mrn string) (string, error) { + var m struct { + AssetLastPackageUpdateTime struct { + LastUpdated string + } `graphql:"assetLastPackageUpdateTime(input: $input)"` + } + err := c.Query(context.Background(), &m, map[string]interface{}{"input": mondoogql.AssetLastPackageUpdateTimeInput{Mrn: mondoogql.String(mrn)}}) + if err != nil { + return "", err + } + return m.AssetLastPackageUpdateTime.LastUpdated, nil +} + +type VulnReport struct { + AssetMrn string + Advisories []*Advisory + Cves []*Cve + Packages []*Package +} + +type Cve struct { + Id string + Source struct { + Id string + Name string + Url string + } + Title string + Description string + Summary string + PublishedAt string + ModifiedAt string + Url string + CvssScore struct { + Id string + Value int + Type int + Vector string + Source string + } + CvssScores []struct { + Id string + Value int + Type int + Vector string + Source string + } + Cwe string + State string +} + +type Advisory struct { + Id string + Source struct { + Id string + Name string + Url string + } + Title string + Description string + + Cves []struct { + Cve + } + CvssScore struct { + Id string + Value int + Type int + Vector string + Source string + } + Vendorscore int + PublishedAt string + ModifiedAt string +} + +type Package struct { + Id string + Name string + Version string + Arch string + Format string + + Namespace string + Description string + Status string + Available string + Origin string + + Score struct { + Id string + Value int + Type int + Vector string + Source string + } + + Advisories []struct { + Advisory + } + Cves []struct { + Cve + } +} + +// GetVulnReport fetches the vuln report for a given asset +func (c *MondooClient) GetVulnReport(mrn string) (*VulnReport, error) { + var m struct { + AssetVulnerabilityReportResponse struct { + AssetVulnerabilityCompactReport struct { + AssetMrn string + Advisories []struct { + Advisory + } + Cves []struct { + Cve + } + Packages []struct { + Package + } + } `graphql:"... on AssetVulnerabilityCompactReport"` + } `graphql:"assetVulnerabilityCompactReport(input: $input)"` + } + err := c.Query(context.Background(), &m, map[string]interface{}{"input": mondoogql.AssetVulnerabilityReportInput{AssetMrn: mondoogql.String(mrn)}}) + if err != nil { + return nil, err + } + + gqlVulnReport := &VulnReport{ + AssetMrn: m.AssetVulnerabilityReportResponse.AssetVulnerabilityCompactReport.AssetMrn, + Advisories: make([]*Advisory, len(m.AssetVulnerabilityReportResponse.AssetVulnerabilityCompactReport.Advisories)), + Cves: make([]*Cve, len(m.AssetVulnerabilityReportResponse.AssetVulnerabilityCompactReport.Cves)), + Packages: make([]*Package, len(m.AssetVulnerabilityReportResponse.AssetVulnerabilityCompactReport.Packages)), + } + + for i, a := range m.AssetVulnerabilityReportResponse.AssetVulnerabilityCompactReport.Advisories { + gqlVulnReport.Advisories[i] = &a.Advisory + } + + for i, c := range m.AssetVulnerabilityReportResponse.AssetVulnerabilityCompactReport.Cves { + gqlVulnReport.Cves[i] = &c.Cve + } + + for i, p := range m.AssetVulnerabilityReportResponse.AssetVulnerabilityCompactReport.Packages { + gqlVulnReport.Packages[i] = &p.Package + } + + return gqlVulnReport, nil +} + +// GetIncognitoVulnReport fetches the vuln report for an anonymous asset +// This is a special case were we don't have an MRN, like in cnspec shell +func (c *MondooClient) GetIncognitoVulnReport(platform mondoogql.PlatformInput, pkgs []mondoogql.PackageInput) (*VulnReport, error) { + var m struct { + AssetVulnerabilityReportResponse struct { + AssetIncognitoVulnerabilityReport struct { + Advisories []struct { + Advisory + } + Cves []struct { + Cve + } + Packages []struct { + Package + } + } `graphql:"... on AssetIncognitoVulnerabilityReport"` + } `graphql:"analyseIncognitoAssetVulnerabilities(input: $input)"` + } + gqlInput := mondoogql.AnalyseIncognitoAssetInput{ + Platform: platform, + Packages: pkgs, + } + + err := c.Query(context.Background(), &m, map[string]interface{}{"input": gqlInput}) + if err != nil { + return nil, err + } + + gqlVulnReport := &VulnReport{ + Advisories: make([]*Advisory, len(m.AssetVulnerabilityReportResponse.AssetIncognitoVulnerabilityReport.Advisories)), + Cves: make([]*Cve, len(m.AssetVulnerabilityReportResponse.AssetIncognitoVulnerabilityReport.Cves)), + Packages: make([]*Package, len(m.AssetVulnerabilityReportResponse.AssetIncognitoVulnerabilityReport.Packages)), + } + + for i, a := range m.AssetVulnerabilityReportResponse.AssetIncognitoVulnerabilityReport.Advisories { + gqlVulnReport.Advisories[i] = &a.Advisory + } + + for i, c := range m.AssetVulnerabilityReportResponse.AssetIncognitoVulnerabilityReport.Cves { + gqlVulnReport.Cves[i] = &c.Cve + } + + for i, p := range m.AssetVulnerabilityReportResponse.AssetIncognitoVulnerabilityReport.Packages { + gqlVulnReport.Packages[i] = &p.Package + } + + return gqlVulnReport, nil +} diff --git a/providers/atlassian/config/config.go b/providers/atlassian/config/config.go index f1624c32fe..ed60f967f0 100644 --- a/providers/atlassian/config/config.go +++ b/providers/atlassian/config/config.go @@ -10,7 +10,7 @@ import ( var Config = plugin.Provider{ Name: "atlassian", - ID: "go.mondoo.com/cnquery/providers/atlassian", + ID: "go.mondoo.com/cnquery/v9/providers/atlassian", Version: "9.1.4", ConnectionTypes: []string{ provider.DefaultConnectionType, diff --git a/providers/atlassian/go.mod b/providers/atlassian/go.mod index 5f12cc1aed..969489a784 100644 --- a/providers/atlassian/go.mod +++ b/providers/atlassian/go.mod @@ -49,7 +49,7 @@ require ( github.com/dvsekhvalnov/jose2go v1.5.0 // indirect github.com/fatih/color v1.16.0 // indirect github.com/getsentry/sentry-go v0.25.0 // indirect - github.com/go-jose/go-jose/v3 v3.0.0 // indirect + github.com/go-jose/go-jose/v3 v3.0.1 // indirect github.com/godbus/dbus v0.0.0-20190726142602-4481cbc300e2 // indirect github.com/gofrs/uuid v4.4.0+incompatible // indirect github.com/gogo/protobuf v1.3.2 // indirect @@ -108,7 +108,7 @@ require ( go.opencensus.io v0.24.0 // indirect golang.org/x/crypto v0.15.0 // indirect golang.org/x/net v0.18.0 // indirect - golang.org/x/oauth2 v0.13.0 // indirect + golang.org/x/oauth2 v0.14.0 // indirect golang.org/x/sync v0.5.0 // indirect golang.org/x/sys v0.14.0 // indirect golang.org/x/term v0.14.0 // indirect diff --git a/providers/atlassian/go.sum b/providers/atlassian/go.sum index a21d7f0aa7..c241b17627 100644 --- a/providers/atlassian/go.sum +++ b/providers/atlassian/go.sum @@ -142,6 +142,8 @@ github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2 github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8= github.com/go-jose/go-jose/v3 v3.0.0 h1:s6rrhirfEP/CGIoc6p+PZAeogN2SxKav6Wp7+dyMWVo= github.com/go-jose/go-jose/v3 v3.0.0/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8= +github.com/go-jose/go-jose/v3 v3.0.1 h1:pWmKFVtt+Jl0vBZTIpz/eAKwsm6LkIxDVVbFHKkchhA= +github.com/go-jose/go-jose/v3 v3.0.1/go.mod h1:RNkWWRld676jZEYoV3+XK8L2ZnNSvIsxFMht0mSX+u8= github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY= github.com/go-logr/logr v1.3.0/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= @@ -505,6 +507,8 @@ golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.13.0 h1:jDDenyj+WgFtmV3zYVoi8aE2BwtXFLWOA67ZfNWftiY= golang.org/x/oauth2 v0.13.0/go.mod h1:/JMhi4ZRXAf4HG9LiNmxvk+45+96RUlVThiH8FzNBn0= +golang.org/x/oauth2 v0.14.0 h1:P0Vrf/2538nmC0H+pEQ3MNFRRnVR7RlqyVw+bvm26z0= +golang.org/x/oauth2 v0.14.0/go.mod h1:lAtNWgaWfL4cm7j2OV8TxGi9Qb7ECORx8DktCY74OwM= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= diff --git a/providers/core/resources/core.lr b/providers/core/resources/core.lr index 478161c364..49492a39cc 100644 --- a/providers/core/resources/core.lr +++ b/providers/core/resources/core.lr @@ -58,6 +58,9 @@ asset.eol @defaults("date") { date time } +// Vulnerability Information +vulnmgmt {} + // Date and time functions time { // The current time on the local system diff --git a/providers/core/resources/core.lr.go b/providers/core/resources/core.lr.go index 40f40a9dd4..42a2c6003b 100644 --- a/providers/core/resources/core.lr.go +++ b/providers/core/resources/core.lr.go @@ -30,6 +30,10 @@ func init() { Init: initAssetEol, Create: createAssetEol, }, + "vulnmgmt": { + // to override args, implement: initVulnmgmt(runtime *plugin.Runtime, args map[string]*llx.RawData) (map[string]*llx.RawData, plugin.Resource, error) + Create: createVulnmgmt, + }, "time": { // to override args, implement: initTime(runtime *plugin.Runtime, args map[string]*llx.RawData) (map[string]*llx.RawData, plugin.Resource, error) Create: createTime, @@ -378,6 +382,10 @@ var setDataFields = map[string]func(r plugin.Resource, v *llx.RawData) bool { r.(*mqlAssetEol).Date, ok = plugin.RawToTValue[*time.Time](v.Value, v.Error) return }, + "vulnmgmt.__id": func(r plugin.Resource, v *llx.RawData) (ok bool) { + r.(*mqlVulnmgmt).__id, ok = v.Value.(string) + return + }, "time.__id": func(r plugin.Resource, v *llx.RawData) (ok bool) { r.(*mqlTime).__id, ok = v.Value.(string) return @@ -777,6 +785,45 @@ func (c *mqlAssetEol) GetDate() *plugin.TValue[*time.Time] { return &c.Date } +// mqlVulnmgmt for the vulnmgmt resource +type mqlVulnmgmt struct { + MqlRuntime *plugin.Runtime + __id string + // optional: if you define mqlVulnmgmtInternal it will be used here +} + +// createVulnmgmt creates a new instance of this resource +func createVulnmgmt(runtime *plugin.Runtime, args map[string]*llx.RawData) (plugin.Resource, error) { + res := &mqlVulnmgmt{ + MqlRuntime: runtime, + } + + err := SetAllData(res, args) + if err != nil { + return res, err + } + + // to override __id implement: id() (string, error) + + if runtime.HasRecording { + args, err = runtime.ResourceFromRecording("vulnmgmt", res.__id) + if err != nil || args == nil { + return res, err + } + return res, SetAllData(res, args) + } + + return res, nil +} + +func (c *mqlVulnmgmt) MqlName() string { + return "vulnmgmt" +} + +func (c *mqlVulnmgmt) MqlID() string { + return c.__id +} + // mqlTime for the time resource type mqlTime struct { MqlRuntime *plugin.Runtime diff --git a/providers/core/resources/core.lr.manifest.yaml b/providers/core/resources/core.lr.manifest.yaml index 3a1f3c2bb3..1d9c67db09 100644 --- a/providers/core/resources/core.lr.manifest.yaml +++ b/providers/core/resources/core.lr.manifest.yaml @@ -411,6 +411,60 @@ resources: variant: {} version: {} min_mondoo_version: 5.15.0 + vuln.advisory: + fields: + description: {} + id: {} + modified: {} + published: {} + title: {} + worstScore: {} + min_mondoo_version: latest + vuln.cve: + fields: + id: {} + modified: {} + published: {} + state: {} + summary: {} + unscored: {} + worstScore: {} + min_mondoo_version: latest + vuln.package: + fields: + arch: {} + available: {} + name: {} + version: {} + min_mondoo_version: latest + vulnadvisory: + fields: + cve: {} + cvss: {} + cvssVector: {} + description: {} + id: {} + severity: {} + title: {} + min_mondoo_version: latest + vulncve: + fields: + cvss: {} + cvssVector: {} + id: {} + min_mondoo_version: latest + vulnmgmt: + fields: + advisories: {} + cves: {} + lastAssessment: {} + packages: {} + min_mondoo_version: latest + vulnpackage: + fields: + name: {} + version: {} + min_mondoo_version: latest yaml.path: fields: filepath: {} diff --git a/providers/core/resources/core.resources.json b/providers/core/resources/core.resources.json index 0a6ed36117..1212447ca4 100644 --- a/providers/core/resources/core.resources.json +++ b/providers/core/resources/core.resources.json @@ -1 +1 @@ -{"resources":{"asset":{"id":"asset","name":"asset","fields":{"arch":{"name":"arch","type":"\u0007","is_mandatory":true,"title":"Architecture this OS is running on","provider":"go.mondoo.com/cnquery/v9/providers/core"},"build":{"name":"build","type":"\u0007","is_mandatory":true,"title":"Build version of the platform (optional)","provider":"go.mondoo.com/cnquery/v9/providers/core"},"eol":{"name":"eol","type":"\u001basset.eol","title":"Information about the assets platform end-of-life.","is_implicit_resource":true,"provider":"go.mondoo.com/cnquery/v9/providers/core"},"family":{"name":"family","type":"\u0019\u0007","is_mandatory":true,"title":"List of platform families that this platform belongs to","provider":"go.mondoo.com/cnquery/v9/providers/core"},"fqdn":{"name":"fqdn","type":"\u0007","is_mandatory":true,"title":"Fully qualified domain name (optional)","provider":"go.mondoo.com/cnquery/v9/providers/core"},"ids":{"name":"ids","type":"\u0019\u0007","is_mandatory":true,"title":"All identifiers for this asset","provider":"go.mondoo.com/cnquery/v9/providers/core"},"kind":{"name":"kind","type":"\u0007","is_mandatory":true,"title":"Kind of platform, for example:","desc":"api, baremetal, vm, vm-image, container, container-image, network, ...","provider":"go.mondoo.com/cnquery/v9/providers/core"},"labels":{"name":"labels","type":"\u001a\u0007\u0007","is_mandatory":true,"title":"Optional platform information","provider":"go.mondoo.com/cnquery/v9/providers/core"},"name":{"name":"name","type":"\u0007","is_mandatory":true,"title":"Human readable name of the asset","provider":"go.mondoo.com/cnquery/v9/providers/core"},"platform":{"name":"platform","type":"\u0007","is_mandatory":true,"title":"Platform for this asset (redhat, windows, k8s-pod)","provider":"go.mondoo.com/cnquery/v9/providers/core"},"runtime":{"name":"runtime","type":"\u0007","is_mandatory":true,"title":"Runtime is the specific kind of the platform. Examples include:","desc":"docker-container, podman-container, aws-ec2-instance, ...","provider":"go.mondoo.com/cnquery/v9/providers/core"},"title":{"name":"title","type":"\u0007","is_mandatory":true,"title":"Human-readable title of the platform (e.g., \"Red Hat 8, Container\")","provider":"go.mondoo.com/cnquery/v9/providers/core"},"version":{"name":"version","type":"\u0007","is_mandatory":true,"title":"Version of the platform","provider":"go.mondoo.com/cnquery/v9/providers/core"}},"title":"General asset information","min_mondoo_version":"6.13.0","defaults":"name platform version","provider":"go.mondoo.com/cnquery/v9/providers/core"},"asset.eol":{"id":"asset.eol","name":"asset.eol","fields":{"date":{"name":"date","type":"\t","is_mandatory":true,"title":"End-of-Life date","provider":"go.mondoo.com/cnquery/v9/providers/core"},"docsUrl":{"name":"docsUrl","type":"\u0007","is_mandatory":true,"title":"Documentation URL","provider":"go.mondoo.com/cnquery/v9/providers/core"},"productUrl":{"name":"productUrl","type":"\u0007","is_mandatory":true,"title":"Product URL","provider":"go.mondoo.com/cnquery/v9/providers/core"}},"title":"Information about the assets platform end-of-life.","min_mondoo_version":"latest","defaults":"date","provider":"go.mondoo.com/cnquery/v9/providers/core"},"cpe":{"id":"cpe","name":"cpe","fields":{"edition":{"name":"edition","type":"\u0007","title":"Edition of the CPE","provider":"go.mondoo.com/cnquery/v9/providers/core"},"language":{"name":"language","type":"\u0007","title":"Language of the CPE","provider":"go.mondoo.com/cnquery/v9/providers/core"},"other":{"name":"other","type":"\u0007","title":"Other of the CPE","provider":"go.mondoo.com/cnquery/v9/providers/core"},"part":{"name":"part","type":"\u0007","title":"Part of the CPE","provider":"go.mondoo.com/cnquery/v9/providers/core"},"product":{"name":"product","type":"\u0007","title":"Product of the CPE","provider":"go.mondoo.com/cnquery/v9/providers/core"},"swEdition":{"name":"swEdition","type":"\u0007","title":"Software edition of the CPE","provider":"go.mondoo.com/cnquery/v9/providers/core"},"targetHw":{"name":"targetHw","type":"\u0007","title":"Target hardware of the CPE","provider":"go.mondoo.com/cnquery/v9/providers/core"},"targetSw":{"name":"targetSw","type":"\u0007","title":"Target software of the CPE","provider":"go.mondoo.com/cnquery/v9/providers/core"},"update":{"name":"update","type":"\u0007","title":"Update of the CPE","provider":"go.mondoo.com/cnquery/v9/providers/core"},"uri":{"name":"uri","type":"\u0007","is_mandatory":true,"title":"URI binding of the CPE","provider":"go.mondoo.com/cnquery/v9/providers/core"},"vendor":{"name":"vendor","type":"\u0007","title":"Vendor of the CPE","provider":"go.mondoo.com/cnquery/v9/providers/core"},"version":{"name":"version","type":"\u0007","title":"Version of the CPE","provider":"go.mondoo.com/cnquery/v9/providers/core"}},"init":{"args":[{"name":"uri","type":"\u0007"}]},"title":"Common Platform Enumeration (CPE) identifiers","min_mondoo_version":"latest","defaults":"uri","provider":"go.mondoo.com/cnquery/v9/providers/core"},"mondoo":{"id":"mondoo","name":"mondoo","fields":{"arch":{"name":"arch","type":"\u0007","title":"Architecture of this client (e.g., linux-amd64)","min_mondoo_version":"latest","provider":"go.mondoo.com/cnquery/v9/providers/core"},"build":{"name":"build","type":"\u0007","title":"Build of the client (e.g., production, development)","provider":"go.mondoo.com/cnquery/v9/providers/core"},"capabilities":{"name":"capabilities","type":"\u0019\u0007","title":"Connection capabilities","provider":"go.mondoo.com/cnquery/v9/providers/core"},"jobEnvironment":{"name":"jobEnvironment","type":"\n","title":"Agent execution environment","provider":"go.mondoo.com/cnquery/v9/providers/core"},"version":{"name":"version","type":"\u0007","title":"Version of the client running on the asset","provider":"go.mondoo.com/cnquery/v9/providers/core"}},"title":"Contextual information about MQL runtime and environment","min_mondoo_version":"5.15.0","defaults":"version","provider":"go.mondoo.com/cnquery/v9/providers/core"},"parse":{"id":"parse","name":"parse","title":"Provides common parsers (json, ini, certs, etc)","min_mondoo_version":"5.15.0","provider":"go.mondoo.com/cnquery/v9/providers/core"},"regex":{"id":"regex","name":"regex","fields":{"creditCard":{"name":"creditCard","type":"\u0008","title":"Matches credit card numbers","provider":"go.mondoo.com/cnquery/v9/providers/core"},"email":{"name":"email","type":"\u0008","title":"Matches email addresses","provider":"go.mondoo.com/cnquery/v9/providers/core"},"emoji":{"name":"emoji","type":"\u0008","title":"Matches emojis","provider":"go.mondoo.com/cnquery/v9/providers/core"},"ipv4":{"name":"ipv4","type":"\u0008","title":"Matches IPv4 addresses","provider":"go.mondoo.com/cnquery/v9/providers/core"},"ipv6":{"name":"ipv6","type":"\u0008","title":"Matches IPv6 addresses","provider":"go.mondoo.com/cnquery/v9/providers/core"},"mac":{"name":"mac","type":"\u0008","title":"Matches MAC addresses","provider":"go.mondoo.com/cnquery/v9/providers/core"},"semver":{"name":"semver","type":"\u0008","title":"Matches semantic version numbers","provider":"go.mondoo.com/cnquery/v9/providers/core"},"url":{"name":"url","type":"\u0008","title":"Matches URL addresses (HTTP/HTTPS)","provider":"go.mondoo.com/cnquery/v9/providers/core"},"uuid":{"name":"uuid","type":"\u0008","title":"Matches hyphen-deliminated UUIDs","provider":"go.mondoo.com/cnquery/v9/providers/core"}},"title":"Built-in regular expression functions","min_mondoo_version":"5.15.0","provider":"go.mondoo.com/cnquery/v9/providers/core"},"time":{"id":"time","name":"time","fields":{"day":{"name":"day","type":"\t","title":"One day, used for durations","provider":"go.mondoo.com/cnquery/v9/providers/core"},"hour":{"name":"hour","type":"\t","title":"One hour, used for durations","provider":"go.mondoo.com/cnquery/v9/providers/core"},"minute":{"name":"minute","type":"\t","title":"One minute, used for durations","provider":"go.mondoo.com/cnquery/v9/providers/core"},"now":{"name":"now","type":"\t","title":"The current time on the local system","provider":"go.mondoo.com/cnquery/v9/providers/core"},"second":{"name":"second","type":"\t","title":"One second, used for durations","provider":"go.mondoo.com/cnquery/v9/providers/core"},"today":{"name":"today","type":"\t","title":"The current day starting at midnight","provider":"go.mondoo.com/cnquery/v9/providers/core"},"tomorrow":{"name":"tomorrow","type":"\t","title":"The next day starting at midnight","provider":"go.mondoo.com/cnquery/v9/providers/core"}},"title":"Date and time functions","min_mondoo_version":"5.15.0","provider":"go.mondoo.com/cnquery/v9/providers/core"},"uuid":{"id":"uuid","name":"uuid","fields":{"urn":{"name":"urn","type":"\u0007","title":"URN returns the RFC 2141 URN form of uuid","provider":"go.mondoo.com/cnquery/v9/providers/core"},"value":{"name":"value","type":"\u0007","is_mandatory":true,"title":"Canonical string representation xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx","provider":"go.mondoo.com/cnquery/v9/providers/core"},"variant":{"name":"variant","type":"\u0007","title":"Variant encoded in UUID","provider":"go.mondoo.com/cnquery/v9/providers/core"},"version":{"name":"version","type":"\u0005","title":"Version of UUID","provider":"go.mondoo.com/cnquery/v9/providers/core"}},"init":{"args":[{"name":"value","type":"\u0007"}]},"title":"UUIDs based on RFC 4122 and DCE 1.1","min_mondoo_version":"5.15.0","defaults":"value","provider":"go.mondoo.com/cnquery/v9/providers/core"}}} \ No newline at end of file +{"resources":{"asset":{"id":"asset","name":"asset","fields":{"arch":{"name":"arch","type":"\u0007","is_mandatory":true,"title":"Architecture this OS is running on","provider":"go.mondoo.com/cnquery/v9/providers/core"},"build":{"name":"build","type":"\u0007","is_mandatory":true,"title":"Build version of the platform (optional)","provider":"go.mondoo.com/cnquery/v9/providers/core"},"eol":{"name":"eol","type":"\u001basset.eol","title":"Information about the assets platform end-of-life.","is_implicit_resource":true,"provider":"go.mondoo.com/cnquery/v9/providers/core"},"family":{"name":"family","type":"\u0019\u0007","is_mandatory":true,"title":"List of platform families that this platform belongs to","provider":"go.mondoo.com/cnquery/v9/providers/core"},"fqdn":{"name":"fqdn","type":"\u0007","is_mandatory":true,"title":"Fully qualified domain name (optional)","provider":"go.mondoo.com/cnquery/v9/providers/core"},"ids":{"name":"ids","type":"\u0019\u0007","is_mandatory":true,"title":"All identifiers for this asset","provider":"go.mondoo.com/cnquery/v9/providers/core"},"kind":{"name":"kind","type":"\u0007","is_mandatory":true,"title":"Kind of platform, for example:","desc":"api, baremetal, vm, vm-image, container, container-image, network, ...","provider":"go.mondoo.com/cnquery/v9/providers/core"},"labels":{"name":"labels","type":"\u001a\u0007\u0007","is_mandatory":true,"title":"Optional platform information","provider":"go.mondoo.com/cnquery/v9/providers/core"},"name":{"name":"name","type":"\u0007","is_mandatory":true,"title":"Human readable name of the asset","provider":"go.mondoo.com/cnquery/v9/providers/core"},"platform":{"name":"platform","type":"\u0007","is_mandatory":true,"title":"Platform for this asset (redhat, windows, k8s-pod)","provider":"go.mondoo.com/cnquery/v9/providers/core"},"runtime":{"name":"runtime","type":"\u0007","is_mandatory":true,"title":"Runtime is the specific kind of the platform. Examples include:","desc":"docker-container, podman-container, aws-ec2-instance, ...","provider":"go.mondoo.com/cnquery/v9/providers/core"},"title":{"name":"title","type":"\u0007","is_mandatory":true,"title":"Human-readable title of the platform (e.g., \"Red Hat 8, Container\")","provider":"go.mondoo.com/cnquery/v9/providers/core"},"version":{"name":"version","type":"\u0007","is_mandatory":true,"title":"Version of the platform","provider":"go.mondoo.com/cnquery/v9/providers/core"}},"title":"General asset information","min_mondoo_version":"6.13.0","defaults":"name platform version","provider":"go.mondoo.com/cnquery/v9/providers/core"},"asset.eol":{"id":"asset.eol","name":"asset.eol","fields":{"date":{"name":"date","type":"\t","is_mandatory":true,"title":"End-of-Life date","provider":"go.mondoo.com/cnquery/v9/providers/core"},"docsUrl":{"name":"docsUrl","type":"\u0007","is_mandatory":true,"title":"Documentation URL","provider":"go.mondoo.com/cnquery/v9/providers/core"},"productUrl":{"name":"productUrl","type":"\u0007","is_mandatory":true,"title":"Product URL","provider":"go.mondoo.com/cnquery/v9/providers/core"}},"title":"Information about the assets platform end-of-life.","min_mondoo_version":"latest","defaults":"date","provider":"go.mondoo.com/cnquery/v9/providers/core"},"cpe":{"id":"cpe","name":"cpe","fields":{"edition":{"name":"edition","type":"\u0007","title":"Edition of the CPE","provider":"go.mondoo.com/cnquery/v9/providers/core"},"language":{"name":"language","type":"\u0007","title":"Language of the CPE","provider":"go.mondoo.com/cnquery/v9/providers/core"},"other":{"name":"other","type":"\u0007","title":"Other of the CPE","provider":"go.mondoo.com/cnquery/v9/providers/core"},"part":{"name":"part","type":"\u0007","title":"Part of the CPE","provider":"go.mondoo.com/cnquery/v9/providers/core"},"product":{"name":"product","type":"\u0007","title":"Product of the CPE","provider":"go.mondoo.com/cnquery/v9/providers/core"},"swEdition":{"name":"swEdition","type":"\u0007","title":"Software edition of the CPE","provider":"go.mondoo.com/cnquery/v9/providers/core"},"targetHw":{"name":"targetHw","type":"\u0007","title":"Target hardware of the CPE","provider":"go.mondoo.com/cnquery/v9/providers/core"},"targetSw":{"name":"targetSw","type":"\u0007","title":"Target software of the CPE","provider":"go.mondoo.com/cnquery/v9/providers/core"},"update":{"name":"update","type":"\u0007","title":"Update of the CPE","provider":"go.mondoo.com/cnquery/v9/providers/core"},"uri":{"name":"uri","type":"\u0007","is_mandatory":true,"title":"URI binding of the CPE","provider":"go.mondoo.com/cnquery/v9/providers/core"},"vendor":{"name":"vendor","type":"\u0007","title":"Vendor of the CPE","provider":"go.mondoo.com/cnquery/v9/providers/core"},"version":{"name":"version","type":"\u0007","title":"Version of the CPE","provider":"go.mondoo.com/cnquery/v9/providers/core"}},"init":{"args":[{"name":"uri","type":"\u0007"}]},"title":"Common Platform Enumeration (CPE) identifiers","min_mondoo_version":"latest","defaults":"uri","provider":"go.mondoo.com/cnquery/v9/providers/core"},"mondoo":{"id":"mondoo","name":"mondoo","fields":{"arch":{"name":"arch","type":"\u0007","title":"Architecture of this client (e.g., linux-amd64)","min_mondoo_version":"latest","provider":"go.mondoo.com/cnquery/v9/providers/core"},"build":{"name":"build","type":"\u0007","title":"Build of the client (e.g., production, development)","provider":"go.mondoo.com/cnquery/v9/providers/core"},"capabilities":{"name":"capabilities","type":"\u0019\u0007","title":"Connection capabilities","provider":"go.mondoo.com/cnquery/v9/providers/core"},"jobEnvironment":{"name":"jobEnvironment","type":"\n","title":"Agent execution environment","provider":"go.mondoo.com/cnquery/v9/providers/core"},"version":{"name":"version","type":"\u0007","title":"Version of the client running on the asset","provider":"go.mondoo.com/cnquery/v9/providers/core"}},"title":"Contextual information about MQL runtime and environment","min_mondoo_version":"5.15.0","defaults":"version","provider":"go.mondoo.com/cnquery/v9/providers/core"},"parse":{"id":"parse","name":"parse","title":"Provides common parsers (json, ini, certs, etc)","min_mondoo_version":"5.15.0","provider":"go.mondoo.com/cnquery/v9/providers/core"},"regex":{"id":"regex","name":"regex","fields":{"creditCard":{"name":"creditCard","type":"\u0008","title":"Matches credit card numbers","provider":"go.mondoo.com/cnquery/v9/providers/core"},"email":{"name":"email","type":"\u0008","title":"Matches email addresses","provider":"go.mondoo.com/cnquery/v9/providers/core"},"emoji":{"name":"emoji","type":"\u0008","title":"Matches emojis","provider":"go.mondoo.com/cnquery/v9/providers/core"},"ipv4":{"name":"ipv4","type":"\u0008","title":"Matches IPv4 addresses","provider":"go.mondoo.com/cnquery/v9/providers/core"},"ipv6":{"name":"ipv6","type":"\u0008","title":"Matches IPv6 addresses","provider":"go.mondoo.com/cnquery/v9/providers/core"},"mac":{"name":"mac","type":"\u0008","title":"Matches MAC addresses","provider":"go.mondoo.com/cnquery/v9/providers/core"},"semver":{"name":"semver","type":"\u0008","title":"Matches semantic version numbers","provider":"go.mondoo.com/cnquery/v9/providers/core"},"url":{"name":"url","type":"\u0008","title":"Matches URL addresses (HTTP/HTTPS)","provider":"go.mondoo.com/cnquery/v9/providers/core"},"uuid":{"name":"uuid","type":"\u0008","title":"Matches hyphen-deliminated UUIDs","provider":"go.mondoo.com/cnquery/v9/providers/core"}},"title":"Built-in regular expression functions","min_mondoo_version":"5.15.0","provider":"go.mondoo.com/cnquery/v9/providers/core"},"time":{"id":"time","name":"time","fields":{"day":{"name":"day","type":"\t","title":"One day, used for durations","provider":"go.mondoo.com/cnquery/v9/providers/core"},"hour":{"name":"hour","type":"\t","title":"One hour, used for durations","provider":"go.mondoo.com/cnquery/v9/providers/core"},"minute":{"name":"minute","type":"\t","title":"One minute, used for durations","provider":"go.mondoo.com/cnquery/v9/providers/core"},"now":{"name":"now","type":"\t","title":"The current time on the local system","provider":"go.mondoo.com/cnquery/v9/providers/core"},"second":{"name":"second","type":"\t","title":"One second, used for durations","provider":"go.mondoo.com/cnquery/v9/providers/core"},"today":{"name":"today","type":"\t","title":"The current day starting at midnight","provider":"go.mondoo.com/cnquery/v9/providers/core"},"tomorrow":{"name":"tomorrow","type":"\t","title":"The next day starting at midnight","provider":"go.mondoo.com/cnquery/v9/providers/core"}},"title":"Date and time functions","min_mondoo_version":"5.15.0","provider":"go.mondoo.com/cnquery/v9/providers/core"},"uuid":{"id":"uuid","name":"uuid","fields":{"urn":{"name":"urn","type":"\u0007","title":"URN returns the RFC 2141 URN form of uuid","provider":"go.mondoo.com/cnquery/v9/providers/core"},"value":{"name":"value","type":"\u0007","is_mandatory":true,"title":"Canonical string representation xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx","provider":"go.mondoo.com/cnquery/v9/providers/core"},"variant":{"name":"variant","type":"\u0007","title":"Variant encoded in UUID","provider":"go.mondoo.com/cnquery/v9/providers/core"},"version":{"name":"version","type":"\u0005","title":"Version of UUID","provider":"go.mondoo.com/cnquery/v9/providers/core"}},"init":{"args":[{"name":"value","type":"\u0007"}]},"title":"UUIDs based on RFC 4122 and DCE 1.1","min_mondoo_version":"5.15.0","defaults":"value","provider":"go.mondoo.com/cnquery/v9/providers/core"},"vulnmgmt":{"id":"vulnmgmt","name":"vulnmgmt","title":"Vulnerability Information","min_mondoo_version":"latest","provider":"go.mondoo.com/cnquery/v9/providers/core"}}} \ No newline at end of file diff --git a/providers/os/resources/os.lr b/providers/os/resources/os.lr index 6adb85be1b..13a86da510 100644 --- a/providers/os/resources/os.lr +++ b/providers/os/resources/os.lr @@ -21,6 +21,8 @@ extend asset { // Common Platform Enumeration (CPE) for the asset cpes() []core.cpe // Advisory & vulnerability report + // Deprecated; will be removed in version 10.0 + // use vulnmgmt instead vulnerabilityReport() dict } @@ -55,10 +57,69 @@ platform.eol @defaults("date") { } platform { - // deprecated; use asset.vulnerabilityReport instead + // Deprecated; will be removed in version 10.0 + // use vulnmgmt instead vulnerabilityReport() dict } +extend vulnmgmt { + // TODO: fill all the fields at once, see os stdout, stderr example + // List of all CVEs affecting the asset + cves() []vuln.cve + // List of all Advisories affecting the asset + advisories() []vuln.advisory + // List of all packages affected by vulnerabilities + packages() []vuln.package + // Last time the vulnerability information was updated + lastAssessment() time +} + +// CVE information +private vuln.cve @defaults("id") { + // CVE ID + id string + // CVE state + state string + // Summary description + summary string + // Whether the CVE has a CVSS score + unscored bool + // Publication date + published time + // Last modification date + modified time + // Worst CVSS score of all assigned CVEs + worstScore audit.cvss +} + +// Advisory information +private vuln.advisory @defaults("id") { + // Advisory ID + id string + // Title of the advisory + title string + // Description of the advisory + description string + // Advisory publication date + published time + // Last modification date + modified time + // Worst CVSS score of all assigned CVEs + worstScore audit.cvss +} + +// Package information relevant for vulnerability management +private vuln.package @defaults("name version") { + // Package name + name string + // Package version + version string + // Available package version + available string + // Architecture of this package + arch string +} + // All platform/package advisories platform.advisories { []audit.advisory diff --git a/providers/os/resources/os.lr.go b/providers/os/resources/os.lr.go index 3995e1549d..523ec4d5e5 100644 --- a/providers/os/resources/os.lr.go +++ b/providers/os/resources/os.lr.go @@ -38,6 +38,22 @@ func init() { // to override args, implement: initPlatform(runtime *plugin.Runtime, args map[string]*llx.RawData) (map[string]*llx.RawData, plugin.Resource, error) Create: createPlatform, }, + "vulnmgmt": { + // to override args, implement: initVulnmgmt(runtime *plugin.Runtime, args map[string]*llx.RawData) (map[string]*llx.RawData, plugin.Resource, error) + Create: createVulnmgmt, + }, + "vuln.cve": { + // to override args, implement: initVulnCve(runtime *plugin.Runtime, args map[string]*llx.RawData) (map[string]*llx.RawData, plugin.Resource, error) + Create: createVulnCve, + }, + "vuln.advisory": { + // to override args, implement: initVulnAdvisory(runtime *plugin.Runtime, args map[string]*llx.RawData) (map[string]*llx.RawData, plugin.Resource, error) + Create: createVulnAdvisory, + }, + "vuln.package": { + // to override args, implement: initVulnPackage(runtime *plugin.Runtime, args map[string]*llx.RawData) (map[string]*llx.RawData, plugin.Resource, error) + Create: createVulnPackage, + }, "platform.advisories": { // to override args, implement: initPlatformAdvisories(runtime *plugin.Runtime, args map[string]*llx.RawData) (map[string]*llx.RawData, plugin.Resource, error) Create: createPlatformAdvisories, @@ -506,6 +522,69 @@ var getDataFields = map[string]func(r plugin.Resource) *plugin.DataRes{ "platform.vulnerabilityReport": func(r plugin.Resource) *plugin.DataRes { return (r.(*mqlPlatform).GetVulnerabilityReport()).ToDataRes(types.Dict) }, + "vulnmgmt.cves": func(r plugin.Resource) *plugin.DataRes { + return (r.(*mqlVulnmgmt).GetCves()).ToDataRes(types.Array(types.Resource("vuln.cve"))) + }, + "vulnmgmt.advisories": func(r plugin.Resource) *plugin.DataRes { + return (r.(*mqlVulnmgmt).GetAdvisories()).ToDataRes(types.Array(types.Resource("vuln.advisory"))) + }, + "vulnmgmt.packages": func(r plugin.Resource) *plugin.DataRes { + return (r.(*mqlVulnmgmt).GetPackages()).ToDataRes(types.Array(types.Resource("vuln.package"))) + }, + "vulnmgmt.lastAssessment": func(r plugin.Resource) *plugin.DataRes { + return (r.(*mqlVulnmgmt).GetLastAssessment()).ToDataRes(types.Time) + }, + "vuln.cve.id": func(r plugin.Resource) *plugin.DataRes { + return (r.(*mqlVulnCve).GetId()).ToDataRes(types.String) + }, + "vuln.cve.state": func(r plugin.Resource) *plugin.DataRes { + return (r.(*mqlVulnCve).GetState()).ToDataRes(types.String) + }, + "vuln.cve.summary": func(r plugin.Resource) *plugin.DataRes { + return (r.(*mqlVulnCve).GetSummary()).ToDataRes(types.String) + }, + "vuln.cve.unscored": func(r plugin.Resource) *plugin.DataRes { + return (r.(*mqlVulnCve).GetUnscored()).ToDataRes(types.Bool) + }, + "vuln.cve.published": func(r plugin.Resource) *plugin.DataRes { + return (r.(*mqlVulnCve).GetPublished()).ToDataRes(types.Time) + }, + "vuln.cve.modified": func(r plugin.Resource) *plugin.DataRes { + return (r.(*mqlVulnCve).GetModified()).ToDataRes(types.Time) + }, + "vuln.cve.worstScore": func(r plugin.Resource) *plugin.DataRes { + return (r.(*mqlVulnCve).GetWorstScore()).ToDataRes(types.Resource("audit.cvss")) + }, + "vuln.advisory.id": func(r plugin.Resource) *plugin.DataRes { + return (r.(*mqlVulnAdvisory).GetId()).ToDataRes(types.String) + }, + "vuln.advisory.title": func(r plugin.Resource) *plugin.DataRes { + return (r.(*mqlVulnAdvisory).GetTitle()).ToDataRes(types.String) + }, + "vuln.advisory.description": func(r plugin.Resource) *plugin.DataRes { + return (r.(*mqlVulnAdvisory).GetDescription()).ToDataRes(types.String) + }, + "vuln.advisory.published": func(r plugin.Resource) *plugin.DataRes { + return (r.(*mqlVulnAdvisory).GetPublished()).ToDataRes(types.Time) + }, + "vuln.advisory.modified": func(r plugin.Resource) *plugin.DataRes { + return (r.(*mqlVulnAdvisory).GetModified()).ToDataRes(types.Time) + }, + "vuln.advisory.worstScore": func(r plugin.Resource) *plugin.DataRes { + return (r.(*mqlVulnAdvisory).GetWorstScore()).ToDataRes(types.Resource("audit.cvss")) + }, + "vuln.package.name": func(r plugin.Resource) *plugin.DataRes { + return (r.(*mqlVulnPackage).GetName()).ToDataRes(types.String) + }, + "vuln.package.version": func(r plugin.Resource) *plugin.DataRes { + return (r.(*mqlVulnPackage).GetVersion()).ToDataRes(types.String) + }, + "vuln.package.available": func(r plugin.Resource) *plugin.DataRes { + return (r.(*mqlVulnPackage).GetAvailable()).ToDataRes(types.String) + }, + "vuln.package.arch": func(r plugin.Resource) *plugin.DataRes { + return (r.(*mqlVulnPackage).GetArch()).ToDataRes(types.String) + }, "platform.advisories.cvss": func(r plugin.Resource) *plugin.DataRes { return (r.(*mqlPlatformAdvisories).GetCvss()).ToDataRes(types.Resource("audit.cvss")) }, @@ -1993,6 +2072,106 @@ var setDataFields = map[string]func(r plugin.Resource, v *llx.RawData) bool { r.(*mqlPlatform).VulnerabilityReport, ok = plugin.RawToTValue[interface{}](v.Value, v.Error) return }, + "vulnmgmt.__id": func(r plugin.Resource, v *llx.RawData) (ok bool) { + r.(*mqlVulnmgmt).__id, ok = v.Value.(string) + return + }, + "vulnmgmt.cves": func(r plugin.Resource, v *llx.RawData) (ok bool) { + r.(*mqlVulnmgmt).Cves, ok = plugin.RawToTValue[[]interface{}](v.Value, v.Error) + return + }, + "vulnmgmt.advisories": func(r plugin.Resource, v *llx.RawData) (ok bool) { + r.(*mqlVulnmgmt).Advisories, ok = plugin.RawToTValue[[]interface{}](v.Value, v.Error) + return + }, + "vulnmgmt.packages": func(r plugin.Resource, v *llx.RawData) (ok bool) { + r.(*mqlVulnmgmt).Packages, ok = plugin.RawToTValue[[]interface{}](v.Value, v.Error) + return + }, + "vulnmgmt.lastAssessment": func(r plugin.Resource, v *llx.RawData) (ok bool) { + r.(*mqlVulnmgmt).LastAssessment, ok = plugin.RawToTValue[*time.Time](v.Value, v.Error) + return + }, + "vuln.cve.__id": func(r plugin.Resource, v *llx.RawData) (ok bool) { + r.(*mqlVulnCve).__id, ok = v.Value.(string) + return + }, + "vuln.cve.id": func(r plugin.Resource, v *llx.RawData) (ok bool) { + r.(*mqlVulnCve).Id, ok = plugin.RawToTValue[string](v.Value, v.Error) + return + }, + "vuln.cve.state": func(r plugin.Resource, v *llx.RawData) (ok bool) { + r.(*mqlVulnCve).State, ok = plugin.RawToTValue[string](v.Value, v.Error) + return + }, + "vuln.cve.summary": func(r plugin.Resource, v *llx.RawData) (ok bool) { + r.(*mqlVulnCve).Summary, ok = plugin.RawToTValue[string](v.Value, v.Error) + return + }, + "vuln.cve.unscored": func(r plugin.Resource, v *llx.RawData) (ok bool) { + r.(*mqlVulnCve).Unscored, ok = plugin.RawToTValue[bool](v.Value, v.Error) + return + }, + "vuln.cve.published": func(r plugin.Resource, v *llx.RawData) (ok bool) { + r.(*mqlVulnCve).Published, ok = plugin.RawToTValue[*time.Time](v.Value, v.Error) + return + }, + "vuln.cve.modified": func(r plugin.Resource, v *llx.RawData) (ok bool) { + r.(*mqlVulnCve).Modified, ok = plugin.RawToTValue[*time.Time](v.Value, v.Error) + return + }, + "vuln.cve.worstScore": func(r plugin.Resource, v *llx.RawData) (ok bool) { + r.(*mqlVulnCve).WorstScore, ok = plugin.RawToTValue[*mqlAuditCvss](v.Value, v.Error) + return + }, + "vuln.advisory.__id": func(r plugin.Resource, v *llx.RawData) (ok bool) { + r.(*mqlVulnAdvisory).__id, ok = v.Value.(string) + return + }, + "vuln.advisory.id": func(r plugin.Resource, v *llx.RawData) (ok bool) { + r.(*mqlVulnAdvisory).Id, ok = plugin.RawToTValue[string](v.Value, v.Error) + return + }, + "vuln.advisory.title": func(r plugin.Resource, v *llx.RawData) (ok bool) { + r.(*mqlVulnAdvisory).Title, ok = plugin.RawToTValue[string](v.Value, v.Error) + return + }, + "vuln.advisory.description": func(r plugin.Resource, v *llx.RawData) (ok bool) { + r.(*mqlVulnAdvisory).Description, ok = plugin.RawToTValue[string](v.Value, v.Error) + return + }, + "vuln.advisory.published": func(r plugin.Resource, v *llx.RawData) (ok bool) { + r.(*mqlVulnAdvisory).Published, ok = plugin.RawToTValue[*time.Time](v.Value, v.Error) + return + }, + "vuln.advisory.modified": func(r plugin.Resource, v *llx.RawData) (ok bool) { + r.(*mqlVulnAdvisory).Modified, ok = plugin.RawToTValue[*time.Time](v.Value, v.Error) + return + }, + "vuln.advisory.worstScore": func(r plugin.Resource, v *llx.RawData) (ok bool) { + r.(*mqlVulnAdvisory).WorstScore, ok = plugin.RawToTValue[*mqlAuditCvss](v.Value, v.Error) + return + }, + "vuln.package.__id": func(r plugin.Resource, v *llx.RawData) (ok bool) { + r.(*mqlVulnPackage).__id, ok = v.Value.(string) + return + }, + "vuln.package.name": func(r plugin.Resource, v *llx.RawData) (ok bool) { + r.(*mqlVulnPackage).Name, ok = plugin.RawToTValue[string](v.Value, v.Error) + return + }, + "vuln.package.version": func(r plugin.Resource, v *llx.RawData) (ok bool) { + r.(*mqlVulnPackage).Version, ok = plugin.RawToTValue[string](v.Value, v.Error) + return + }, + "vuln.package.available": func(r plugin.Resource, v *llx.RawData) (ok bool) { + r.(*mqlVulnPackage).Available, ok = plugin.RawToTValue[string](v.Value, v.Error) + return + }, + "vuln.package.arch": func(r plugin.Resource, v *llx.RawData) (ok bool) { + r.(*mqlVulnPackage).Arch, ok = plugin.RawToTValue[string](v.Value, v.Error) + return + }, "platform.advisories.__id": func(r plugin.Resource, v *llx.RawData) (ok bool) { r.(*mqlPlatformAdvisories).__id, ok = v.Value.(string) return @@ -4535,6 +4714,305 @@ func (c *mqlPlatform) GetVulnerabilityReport() *plugin.TValue[interface{}] { }) } +// mqlVulnmgmt for the vulnmgmt resource +type mqlVulnmgmt struct { + MqlRuntime *plugin.Runtime + __id string + // optional: if you define mqlVulnmgmtInternal it will be used here + Cves plugin.TValue[[]interface{}] + Advisories plugin.TValue[[]interface{}] + Packages plugin.TValue[[]interface{}] + LastAssessment plugin.TValue[*time.Time] +} + +// createVulnmgmt creates a new instance of this resource +func createVulnmgmt(runtime *plugin.Runtime, args map[string]*llx.RawData) (plugin.Resource, error) { + res := &mqlVulnmgmt{ + MqlRuntime: runtime, + } + + err := SetAllData(res, args) + if err != nil { + return res, err + } + + // to override __id implement: id() (string, error) + + if runtime.HasRecording { + args, err = runtime.ResourceFromRecording("vulnmgmt", res.__id) + if err != nil || args == nil { + return res, err + } + return res, SetAllData(res, args) + } + + return res, nil +} + +func (c *mqlVulnmgmt) MqlName() string { + return "vulnmgmt" +} + +func (c *mqlVulnmgmt) MqlID() string { + return c.__id +} + +func (c *mqlVulnmgmt) GetCves() *plugin.TValue[[]interface{}] { + return plugin.GetOrCompute[[]interface{}](&c.Cves, func() ([]interface{}, error) { + if c.MqlRuntime.HasRecording { + d, err := c.MqlRuntime.FieldResourceFromRecording("vulnmgmt", c.__id, "cves") + if err != nil { + return nil, err + } + if d != nil { + return d.Value.([]interface{}), nil + } + } + + return c.cves() + }) +} + +func (c *mqlVulnmgmt) GetAdvisories() *plugin.TValue[[]interface{}] { + return plugin.GetOrCompute[[]interface{}](&c.Advisories, func() ([]interface{}, error) { + if c.MqlRuntime.HasRecording { + d, err := c.MqlRuntime.FieldResourceFromRecording("vulnmgmt", c.__id, "advisories") + if err != nil { + return nil, err + } + if d != nil { + return d.Value.([]interface{}), nil + } + } + + return c.advisories() + }) +} + +func (c *mqlVulnmgmt) GetPackages() *plugin.TValue[[]interface{}] { + return plugin.GetOrCompute[[]interface{}](&c.Packages, func() ([]interface{}, error) { + if c.MqlRuntime.HasRecording { + d, err := c.MqlRuntime.FieldResourceFromRecording("vulnmgmt", c.__id, "packages") + if err != nil { + return nil, err + } + if d != nil { + return d.Value.([]interface{}), nil + } + } + + return c.packages() + }) +} + +func (c *mqlVulnmgmt) GetLastAssessment() *plugin.TValue[*time.Time] { + return plugin.GetOrCompute[*time.Time](&c.LastAssessment, func() (*time.Time, error) { + return c.lastAssessment() + }) +} + +// mqlVulnCve for the vuln.cve resource +type mqlVulnCve struct { + MqlRuntime *plugin.Runtime + __id string + // optional: if you define mqlVulnCveInternal it will be used here + Id plugin.TValue[string] + State plugin.TValue[string] + Summary plugin.TValue[string] + Unscored plugin.TValue[bool] + Published plugin.TValue[*time.Time] + Modified plugin.TValue[*time.Time] + WorstScore plugin.TValue[*mqlAuditCvss] +} + +// createVulnCve creates a new instance of this resource +func createVulnCve(runtime *plugin.Runtime, args map[string]*llx.RawData) (plugin.Resource, error) { + res := &mqlVulnCve{ + MqlRuntime: runtime, + } + + err := SetAllData(res, args) + if err != nil { + return res, err + } + + // to override __id implement: id() (string, error) + + if runtime.HasRecording { + args, err = runtime.ResourceFromRecording("vuln.cve", res.__id) + if err != nil || args == nil { + return res, err + } + return res, SetAllData(res, args) + } + + return res, nil +} + +func (c *mqlVulnCve) MqlName() string { + return "vuln.cve" +} + +func (c *mqlVulnCve) MqlID() string { + return c.__id +} + +func (c *mqlVulnCve) GetId() *plugin.TValue[string] { + return &c.Id +} + +func (c *mqlVulnCve) GetState() *plugin.TValue[string] { + return &c.State +} + +func (c *mqlVulnCve) GetSummary() *plugin.TValue[string] { + return &c.Summary +} + +func (c *mqlVulnCve) GetUnscored() *plugin.TValue[bool] { + return &c.Unscored +} + +func (c *mqlVulnCve) GetPublished() *plugin.TValue[*time.Time] { + return &c.Published +} + +func (c *mqlVulnCve) GetModified() *plugin.TValue[*time.Time] { + return &c.Modified +} + +func (c *mqlVulnCve) GetWorstScore() *plugin.TValue[*mqlAuditCvss] { + return &c.WorstScore +} + +// mqlVulnAdvisory for the vuln.advisory resource +type mqlVulnAdvisory struct { + MqlRuntime *plugin.Runtime + __id string + // optional: if you define mqlVulnAdvisoryInternal it will be used here + Id plugin.TValue[string] + Title plugin.TValue[string] + Description plugin.TValue[string] + Published plugin.TValue[*time.Time] + Modified plugin.TValue[*time.Time] + WorstScore plugin.TValue[*mqlAuditCvss] +} + +// createVulnAdvisory creates a new instance of this resource +func createVulnAdvisory(runtime *plugin.Runtime, args map[string]*llx.RawData) (plugin.Resource, error) { + res := &mqlVulnAdvisory{ + MqlRuntime: runtime, + } + + err := SetAllData(res, args) + if err != nil { + return res, err + } + + // to override __id implement: id() (string, error) + + if runtime.HasRecording { + args, err = runtime.ResourceFromRecording("vuln.advisory", res.__id) + if err != nil || args == nil { + return res, err + } + return res, SetAllData(res, args) + } + + return res, nil +} + +func (c *mqlVulnAdvisory) MqlName() string { + return "vuln.advisory" +} + +func (c *mqlVulnAdvisory) MqlID() string { + return c.__id +} + +func (c *mqlVulnAdvisory) GetId() *plugin.TValue[string] { + return &c.Id +} + +func (c *mqlVulnAdvisory) GetTitle() *plugin.TValue[string] { + return &c.Title +} + +func (c *mqlVulnAdvisory) GetDescription() *plugin.TValue[string] { + return &c.Description +} + +func (c *mqlVulnAdvisory) GetPublished() *plugin.TValue[*time.Time] { + return &c.Published +} + +func (c *mqlVulnAdvisory) GetModified() *plugin.TValue[*time.Time] { + return &c.Modified +} + +func (c *mqlVulnAdvisory) GetWorstScore() *plugin.TValue[*mqlAuditCvss] { + return &c.WorstScore +} + +// mqlVulnPackage for the vuln.package resource +type mqlVulnPackage struct { + MqlRuntime *plugin.Runtime + __id string + // optional: if you define mqlVulnPackageInternal it will be used here + Name plugin.TValue[string] + Version plugin.TValue[string] + Available plugin.TValue[string] + Arch plugin.TValue[string] +} + +// createVulnPackage creates a new instance of this resource +func createVulnPackage(runtime *plugin.Runtime, args map[string]*llx.RawData) (plugin.Resource, error) { + res := &mqlVulnPackage{ + MqlRuntime: runtime, + } + + err := SetAllData(res, args) + if err != nil { + return res, err + } + + // to override __id implement: id() (string, error) + + if runtime.HasRecording { + args, err = runtime.ResourceFromRecording("vuln.package", res.__id) + if err != nil || args == nil { + return res, err + } + return res, SetAllData(res, args) + } + + return res, nil +} + +func (c *mqlVulnPackage) MqlName() string { + return "vuln.package" +} + +func (c *mqlVulnPackage) MqlID() string { + return c.__id +} + +func (c *mqlVulnPackage) GetName() *plugin.TValue[string] { + return &c.Name +} + +func (c *mqlVulnPackage) GetVersion() *plugin.TValue[string] { + return &c.Version +} + +func (c *mqlVulnPackage) GetAvailable() *plugin.TValue[string] { + return &c.Available +} + +func (c *mqlVulnPackage) GetArch() *plugin.TValue[string] { + return &c.Arch +} + // mqlPlatformAdvisories for the platform.advisories resource type mqlPlatformAdvisories struct { MqlRuntime *plugin.Runtime diff --git a/providers/os/resources/os.lr.manifest.yaml b/providers/os/resources/os.lr.manifest.yaml index 82eac5a9fa..d4aae8728b 100644 --- a/providers/os/resources/os.lr.manifest.yaml +++ b/providers/os/resources/os.lr.manifest.yaml @@ -884,6 +884,48 @@ resources: name != "Guest" } title: Search for a specific SID and check for its values + vuln.advisory: + fields: + cve: {} + cvss: {} + cvssVector: {} + description: {} + id: {} + modified: {} + published: {} + severity: {} + title: {} + worstScore: {} + is_private: true + min_mondoo_version: latest + vuln.cve: + fields: + cvss: {} + cvssVector: {} + id: {} + modified: {} + published: {} + state: {} + summary: {} + unscored: {} + worstScore: {} + is_private: true + min_mondoo_version: latest + vuln.package: + fields: + arch: {} + available: {} + name: {} + version: {} + is_private: true + min_mondoo_version: latest + vulnmgmt: + fields: + advisories: {} + cves: {} + lastAssessment: {} + packages: {} + min_mondoo_version: latest windows: fields: computerInfo: {} diff --git a/providers/os/resources/vulnmgmt.go b/providers/os/resources/vulnmgmt.go new file mode 100644 index 0000000000..2a1a1a2bbe --- /dev/null +++ b/providers/os/resources/vulnmgmt.go @@ -0,0 +1,195 @@ +// Copyright (c) Mondoo, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package resources + +import ( + "errors" + "time" + + "github.com/rs/zerolog/log" + "go.mondoo.com/cnquery/v9/llx" + "go.mondoo.com/cnquery/v9/providers-sdk/v1/resources" + "go.mondoo.com/cnquery/v9/providers-sdk/v1/upstream/gql" + "go.mondoo.com/cnquery/v9/providers/os/connection/shared" + mondoogql "go.mondoo.com/mondoo-go" +) + +func (v *mqlVulnmgmt) lastAssessment() (*time.Time, error) { + mcc := v.MqlRuntime.Upstream + if mcc == nil || mcc.ApiEndpoint == "" { + return nil, resources.MissingUpstreamError{} + } + + // get new gql client + mondooClient, err := gql.NewClient(mcc.UpstreamConfig, mcc.HttpClient) + if err != nil { + return nil, err + } + + if v.MqlRuntime.Upstream.AssetMrn == "" { + return nil, errors.New("no asset mrn available") + } + lastUpdate, err := mondooClient.LastAssessment(v.MqlRuntime.Upstream.AssetMrn) + if err != nil { + return nil, err + } + + log.Debug().Str("time", lastUpdate).Msg("search for package last update") + if lastUpdate == "" { + return nil, errors.New("no update time available") + } + + var lastUpdateTime *time.Time + if lastUpdate != "" { + parsedLastUpdateTime, err := time.Parse(time.RFC3339, lastUpdate) + if err != nil { + return nil, errors.New("could not parse last update time: " + lastUpdate) + } + lastUpdateTime = &parsedLastUpdateTime + } else { + lastUpdateTime = &llx.NeverFutureTime + } + + return lastUpdateTime, nil +} + +func (v *mqlVulnmgmt) cves() ([]interface{}, error) { + vulnReport, err := v.getReport() + if err != nil { + return nil, err + } + + mqlVulnCves := make([]interface{}, len(vulnReport.Cves)) + for i, c := range vulnReport.Cves { + mqlVulnCve, err := CreateResource(v.MqlRuntime, "vuln.cve", map[string]*llx.RawData{ + "id": llx.StringData(c.Id), + "cvss": llx.IntData(int64(c.CvssScore.Value)), + "cvssVector": llx.StringData(c.CvssScore.Vector), + }) + if err != nil { + return nil, err + } + mqlVulnCves[i] = mqlVulnCve + } + + return mqlVulnCves, nil +} + +func (v *mqlVulnmgmt) advisories() ([]interface{}, error) { + vulnReport, err := v.getReport() + if err != nil { + return nil, err + } + + mqlVulAdvisories := make([]interface{}, len(vulnReport.Advisories)) + for i, a := range vulnReport.Advisories { + mqlVulnAdvisory, err := CreateResource(v.MqlRuntime, "vuln.advisory", map[string]*llx.RawData{ + "id": llx.StringData(a.Id), + "title": llx.StringData(a.Title), + "description": llx.StringData(a.Description), + }) + if err != nil { + return nil, err + } + mqlVulAdvisories[i] = mqlVulnAdvisory + } + + return mqlVulAdvisories, nil +} + +func (v *mqlVulnmgmt) packages() ([]interface{}, error) { + vulnReport, err := v.getReport() + if err != nil { + return nil, err + } + + mqlVulnPackages := make([]interface{}, len(vulnReport.Packages)) + for i, p := range vulnReport.Packages { + mqlVulnPackage, err := CreateResource(v.MqlRuntime, "vuln.package", map[string]*llx.RawData{ + "name": llx.StringData(p.Name), + "version": llx.StringData(p.Version), + "available": llx.StringData(p.Available), + "arch": llx.StringData(p.Arch), + }) + if err != nil { + return nil, err + } + mqlVulnPackages[i] = mqlVulnPackage + } + + return mqlVulnPackages, nil +} + +func (v *mqlVulnmgmt) getReport() (*gql.VulnReport, error) { + mcc := v.MqlRuntime.Upstream + if mcc == nil || mcc.ApiEndpoint == "" { + return nil, resources.MissingUpstreamError{} + } + + // get new gql client + mondooClient, err := gql.NewClient(mcc.UpstreamConfig, mcc.HttpClient) + if err != nil { + return nil, err + } + + if v.MqlRuntime.Upstream.AssetMrn == "" { + log.Debug().Msg("no asset mrn available") + return v.getIncognitoReport(mondooClient) + } + // gqlVulnReport, err := GetVulnReport("//assets.api.mondoo.app/spaces/test-infallible-taussig-796596/assets/2YTpHJnJXnfmuBtQde2HQgWqX1n") + gqlVulnReport, err := mondooClient.GetVulnReport(v.MqlRuntime.Upstream.AssetMrn) + if err != nil { + return nil, err + } + + log.Debug().Interface("gqlReport", gqlVulnReport).Msg("search for asset vuln report") + if gqlVulnReport == nil { + return nil, errors.New("no vulnerability report available") + } + + return gqlVulnReport, nil +} + +func (v *mqlVulnmgmt) getIncognitoReport(mondooClient *gql.MondooClient) (*gql.VulnReport, error) { + // FIXCME: when we don't have a MRN, we need to: + // - creeate asset + // - create packages + // - get "incognito" vulnReport + // - procede as usual + + conn := v.MqlRuntime.Connection.(shared.Connection) + platform := conn.Asset().Platform + + pkgsRes, err := CreateResource(v.MqlRuntime, "packages", nil) + if err != nil { + return nil, err + } + pkgs := pkgsRes.(*mqlPackages) + pkgsList := pkgs.GetList().Data + + gqlPackages := make([]mondoogql.PackageInput, len(pkgsList)) + for i, p := range pkgs.GetList().Data { + mqlPkg := p.(*mqlPackage) + gqlPackages[i] = mondoogql.PackageInput{ + Name: mondoogql.String(mqlPkg.Name.Data), + Version: mondoogql.String(mqlPkg.Version.Data), + Arch: mondoogql.NewStringPtr(mondoogql.String(mqlPkg.Arch.Data)), + } + } + + gqlVulnReport, err := mondooClient.GetIncognitoVulnReport(mondoogql.PlatformInput{ + Name: mondoogql.NewStringPtr(mondoogql.String(platform.Name)), + Release: mondoogql.NewStringPtr(mondoogql.String(platform.Version)), + }, gqlPackages) + if err != nil { + return nil, err + } + + log.Debug().Interface("gqlReport", gqlVulnReport).Msg("search for asset vuln report") + if gqlVulnReport == nil { + return nil, errors.New("no vulnerability report available") + } + + return gqlVulnReport, nil +} diff --git a/providers/vsphere/resources/vsphere.lr b/providers/vsphere/resources/vsphere.lr index 96a7140f6f..f6d61fa232 100644 --- a/providers/vsphere/resources/vsphere.lr +++ b/providers/vsphere/resources/vsphere.lr @@ -9,6 +9,7 @@ extend asset { // Common Platform Enumeration (CPE) for the asset cpes() []core.cpe // Advisory & vulnerability report + // Will be deprecated; Full advisory & vulnerability report vulnerabilityReport() dict }