diff --git a/cli/reporter/cnquery_report.pb.go b/cli/reporter/cnquery_report.pb.go index aa90de6129..f2fe7e78ca 100644 --- a/cli/reporter/cnquery_report.pb.go +++ b/cli/reporter/cnquery_report.pb.go @@ -3,8 +3,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.35.1 -// protoc v5.28.3 +// protoc-gen-go v1.35.2 +// protoc v5.29.0 // source: cnquery_report.proto package reporter diff --git a/explorer/cnquery_explorer.pb.go b/explorer/cnquery_explorer.pb.go index bd802cfe5b..69e9c55056 100644 --- a/explorer/cnquery_explorer.pb.go +++ b/explorer/cnquery_explorer.pb.go @@ -4,7 +4,7 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: // protoc-gen-go v1.35.2 -// protoc v5.28.3 +// protoc v5.29.0 // source: cnquery_explorer.proto package explorer diff --git a/explorer/resources/cnquery_resources_explorer.pb.go b/explorer/resources/cnquery_resources_explorer.pb.go index 958e593f48..37fd0827c0 100644 --- a/explorer/resources/cnquery_resources_explorer.pb.go +++ b/explorer/resources/cnquery_resources_explorer.pb.go @@ -3,8 +3,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.35.1 -// protoc v5.28.3 +// protoc-gen-go v1.35.2 +// protoc v5.29.0 // source: cnquery_resources_explorer.proto package resources diff --git a/explorer/scan/cnquery_explorer_scan.pb.go b/explorer/scan/cnquery_explorer_scan.pb.go index a4d84dbb1c..c697805d24 100644 --- a/explorer/scan/cnquery_explorer_scan.pb.go +++ b/explorer/scan/cnquery_explorer_scan.pb.go @@ -3,8 +3,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.35.1 -// protoc v5.28.3 +// protoc-gen-go v1.35.2 +// protoc v5.29.0 // source: cnquery_explorer_scan.proto package scan diff --git a/llx/llx.pb.go b/llx/llx.pb.go index 71f7ab2fe6..fd9b1d00b4 100644 --- a/llx/llx.pb.go +++ b/llx/llx.pb.go @@ -3,8 +3,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.35.1 -// protoc v5.28.3 +// protoc-gen-go v1.35.2 +// protoc v5.29.0 // source: llx.proto package llx diff --git a/providers-sdk/v1/plugin/plugin_grpc.pb.go b/providers-sdk/v1/plugin/plugin_grpc.pb.go index 81b221fc9e..63e57fc937 100644 --- a/providers-sdk/v1/plugin/plugin_grpc.pb.go +++ b/providers-sdk/v1/plugin/plugin_grpc.pb.go @@ -3,7 +3,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: -// - protoc-gen-go-grpc v1.4.0 +// - protoc-gen-go-grpc v1.5.1 // - protoc v5.29.0 // source: plugin.proto @@ -18,8 +18,8 @@ import ( // This is a compile-time assertion to ensure that this generated file // is compatible with the grpc package it is being compiled against. -// Requires gRPC-Go v1.62.0 or later. -const _ = grpc.SupportPackageIsVersion8 +// Requires gRPC-Go v1.64.0 or later. +const _ = grpc.SupportPackageIsVersion9 const ( ProviderPlugin_Heartbeat_FullMethodName = "/cnquery.providers.v1.ProviderPlugin/Heartbeat" @@ -136,7 +136,7 @@ func (c *providerPluginClient) StoreData(ctx context.Context, in *StoreReq, opts // ProviderPluginServer is the server API for ProviderPlugin service. // All implementations must embed UnimplementedProviderPluginServer -// for forward compatibility +// for forward compatibility. type ProviderPluginServer interface { Heartbeat(context.Context, *HeartbeatReq) (*HeartbeatRes, error) ParseCLI(context.Context, *ParseCLIReq) (*ParseCLIRes, error) @@ -149,9 +149,12 @@ type ProviderPluginServer interface { mustEmbedUnimplementedProviderPluginServer() } -// UnimplementedProviderPluginServer must be embedded to have forward compatible implementations. -type UnimplementedProviderPluginServer struct { -} +// UnimplementedProviderPluginServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedProviderPluginServer struct{} func (UnimplementedProviderPluginServer) Heartbeat(context.Context, *HeartbeatReq) (*HeartbeatRes, error) { return nil, status.Errorf(codes.Unimplemented, "method Heartbeat not implemented") @@ -178,6 +181,7 @@ func (UnimplementedProviderPluginServer) StoreData(context.Context, *StoreReq) ( return nil, status.Errorf(codes.Unimplemented, "method StoreData not implemented") } func (UnimplementedProviderPluginServer) mustEmbedUnimplementedProviderPluginServer() {} +func (UnimplementedProviderPluginServer) testEmbeddedByValue() {} // UnsafeProviderPluginServer may be embedded to opt out of forward compatibility for this service. // Use of this interface is not recommended, as added methods to ProviderPluginServer will @@ -187,6 +191,13 @@ type UnsafeProviderPluginServer interface { } func RegisterProviderPluginServer(s grpc.ServiceRegistrar, srv ProviderPluginServer) { + // If the following call pancis, it indicates UnimplementedProviderPluginServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } s.RegisterService(&ProviderPlugin_ServiceDesc, srv) } @@ -433,7 +444,7 @@ func (c *providerCallbackClient) GetData(ctx context.Context, in *DataReq, opts // ProviderCallbackServer is the server API for ProviderCallback service. // All implementations must embed UnimplementedProviderCallbackServer -// for forward compatibility +// for forward compatibility. type ProviderCallbackServer interface { Collect(context.Context, *DataRes) (*CollectRes, error) GetRecording(context.Context, *DataReq) (*ResourceData, error) @@ -441,9 +452,12 @@ type ProviderCallbackServer interface { mustEmbedUnimplementedProviderCallbackServer() } -// UnimplementedProviderCallbackServer must be embedded to have forward compatible implementations. -type UnimplementedProviderCallbackServer struct { -} +// UnimplementedProviderCallbackServer must be embedded to have +// forward compatible implementations. +// +// NOTE: this should be embedded by value instead of pointer to avoid a nil +// pointer dereference when methods are called. +type UnimplementedProviderCallbackServer struct{} func (UnimplementedProviderCallbackServer) Collect(context.Context, *DataRes) (*CollectRes, error) { return nil, status.Errorf(codes.Unimplemented, "method Collect not implemented") @@ -455,6 +469,7 @@ func (UnimplementedProviderCallbackServer) GetData(context.Context, *DataReq) (* return nil, status.Errorf(codes.Unimplemented, "method GetData not implemented") } func (UnimplementedProviderCallbackServer) mustEmbedUnimplementedProviderCallbackServer() {} +func (UnimplementedProviderCallbackServer) testEmbeddedByValue() {} // UnsafeProviderCallbackServer may be embedded to opt out of forward compatibility for this service. // Use of this interface is not recommended, as added methods to ProviderCallbackServer will @@ -464,6 +479,13 @@ type UnsafeProviderCallbackServer interface { } func RegisterProviderCallbackServer(s grpc.ServiceRegistrar, srv ProviderCallbackServer) { + // If the following call pancis, it indicates UnimplementedProviderCallbackServer was + // embedded by pointer and is nil. This will cause panics if an + // unimplemented method is ever invoked, so we test this at initialization + // time to prevent it from happening at runtime later due to I/O. + if t, ok := srv.(interface{ testEmbeddedByValue() }); ok { + t.testEmbeddedByValue() + } s.RegisterService(&ProviderCallback_ServiceDesc, srv) } diff --git a/providers-sdk/v1/upstream/health/errors.pb.go b/providers-sdk/v1/upstream/health/errors.pb.go index 3b3906c226..392f24e7d2 100644 --- a/providers-sdk/v1/upstream/health/errors.pb.go +++ b/providers-sdk/v1/upstream/health/errors.pb.go @@ -3,8 +3,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.35.1 -// protoc v5.28.3 +// protoc-gen-go v1.35.2 +// protoc v5.29.0 // source: errors.proto package health diff --git a/providers-sdk/v1/upstream/health/health.pb.go b/providers-sdk/v1/upstream/health/health.pb.go index 4d5917bb30..01526cf4d8 100644 --- a/providers-sdk/v1/upstream/health/health.pb.go +++ b/providers-sdk/v1/upstream/health/health.pb.go @@ -17,8 +17,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.35.1 -// protoc v5.28.3 +// protoc-gen-go v1.35.2 +// protoc v5.29.0 // source: health.proto package health diff --git a/providers-sdk/v1/upstream/mvd/cvss/cvss.pb.go b/providers-sdk/v1/upstream/mvd/cvss/cvss.pb.go index 411934c581..99a0e3505b 100644 --- a/providers-sdk/v1/upstream/mvd/cvss/cvss.pb.go +++ b/providers-sdk/v1/upstream/mvd/cvss/cvss.pb.go @@ -3,8 +3,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.35.1 -// protoc v5.28.3 +// protoc-gen-go v1.35.2 +// protoc v5.29.0 // source: cvss.proto package cvss diff --git a/providers-sdk/v1/upstream/mvd/mvd.pb.go b/providers-sdk/v1/upstream/mvd/mvd.pb.go index a7c631b812..9c87f8e8fd 100644 --- a/providers-sdk/v1/upstream/mvd/mvd.pb.go +++ b/providers-sdk/v1/upstream/mvd/mvd.pb.go @@ -3,8 +3,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.35.1 -// protoc v5.28.3 +// protoc-gen-go v1.35.2 +// protoc v5.29.0 // source: mvd.proto package mvd diff --git a/providers-sdk/v1/upstream/upstream.pb.go b/providers-sdk/v1/upstream/upstream.pb.go index 699653e03a..39d7475118 100644 --- a/providers-sdk/v1/upstream/upstream.pb.go +++ b/providers-sdk/v1/upstream/upstream.pb.go @@ -3,8 +3,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.35.1 -// protoc v5.28.3 +// protoc-gen-go v1.35.2 +// protoc v5.29.0 // source: upstream.proto package upstream diff --git a/providers/os/resources/packages/macos_packages.go b/providers/os/resources/packages/macos_packages.go index 8cfbf1406a..c4feb4da07 100644 --- a/providers/os/resources/packages/macos_packages.go +++ b/providers/os/resources/packages/macos_packages.go @@ -9,7 +9,9 @@ import ( "strings" "github.com/cockroachdb/errors" + "go.mondoo.com/cnquery/v11/providers-sdk/v1/inventory" "go.mondoo.com/cnquery/v11/providers/os/connection/shared" + "go.mondoo.com/cnquery/v11/providers/os/resources/purl" plist "howett.net/plist" ) @@ -18,7 +20,7 @@ const ( ) // parse macos system version property list -func ParseMacOSPackages(input io.Reader) ([]Package, error) { +func ParseMacOSPackages(platform *inventory.Platform, input io.Reader) ([]Package, error) { var r io.ReadSeeker r, ok := input.(io.ReadSeeker) @@ -58,6 +60,9 @@ func ParseMacOSPackages(input io.Reader) ([]Package, error) { pkgs[i].Version = entry.Version pkgs[i].Format = MacosPkgFormat pkgs[i].FilesAvailable = PkgFilesIncluded + pkgs[i].PUrl = purl.NewPackageUrl( + platform, entry.Name, entry.Version, platform.Arch, "", purl.TypeMacos, + ) if entry.Path != "" { pkgs[i].Files = []FileRecord{ { @@ -72,7 +77,8 @@ func ParseMacOSPackages(input io.Reader) ([]Package, error) { // MacOS type MacOSPkgManager struct { - conn shared.Connection + conn shared.Connection + platform *inventory.Platform } func (mpm *MacOSPkgManager) Name() string { @@ -89,7 +95,7 @@ func (mpm *MacOSPkgManager) List() ([]Package, error) { return nil, fmt.Errorf("could not read package list") } - return ParseMacOSPackages(cmd.Stdout) + return ParseMacOSPackages(mpm.platform, cmd.Stdout) } func (mpm *MacOSPkgManager) Available() (map[string]PackageUpdate, error) { diff --git a/providers/os/resources/packages/macos_packages_test.go b/providers/os/resources/packages/macos_packages_test.go index 6c147c17ed..309faffa6b 100644 --- a/providers/os/resources/packages/macos_packages_test.go +++ b/providers/os/resources/packages/macos_packages_test.go @@ -23,7 +23,13 @@ func TestMacOsXPackageParser(t *testing.T) { } assert.Nil(t, err) - m, err := packages.ParseMacOSPackages(c.Stdout) + pf := &inventory.Platform{ + Name: "macos", + Version: "15.2", + Arch: "x86_64", + Family: []string{"darwin", "bsd", "unix", "os"}, + } + m, err := packages.ParseMacOSPackages(pf, c.Stdout) assert.Nil(t, err) assert.Equal(t, 2, len(m), "detected the right amount of packages") @@ -31,11 +37,13 @@ func TestMacOsXPackageParser(t *testing.T) { assert.Equal(t, "10.0", m[0].Version, "pkg version detected") assert.Equal(t, packages.MacosPkgFormat, m[0].Format, "pkg format detected") assert.Equal(t, packages.PkgFilesIncluded, m[0].FilesAvailable) + assert.Equal(t, "pkg:macos/Preview@10.0?arch=x86_64&distro=macos-15.2", m[0].PUrl) assert.Equal(t, []packages.FileRecord{{Path: "/Applications/Preview.app"}}, m[0].Files) assert.Equal(t, "Contacts", m[1].Name, "pkg name detected") assert.Equal(t, "11.0", m[1].Version, "pkg version detected") assert.Equal(t, packages.MacosPkgFormat, m[1].Format, "pkg format detected") assert.Equal(t, packages.PkgFilesIncluded, m[1].FilesAvailable) + assert.Equal(t, "pkg:macos/Contacts@11.0?arch=x86_64&distro=macos-15.2", m[1].PUrl) assert.Equal(t, []packages.FileRecord{{Path: "/Applications/Contacts.app"}}, m[1].Files) } diff --git a/providers/os/resources/packages/packages.go b/providers/os/resources/packages/packages.go index 1867b45266..b9c965f18f 100644 --- a/providers/os/resources/packages/packages.go +++ b/providers/os/resources/packages/packages.go @@ -111,7 +111,7 @@ func ResolveSystemPkgManager(conn shared.Connection) (OperatingSystemPkgManager, case asset.Platform.Name == "alpine" || asset.Platform.Name == "wolfi": // alpine & wolfi share apk pm = &AlpinePkgManager{conn: conn, platform: asset.Platform} case asset.Platform.Name == "macos": // mac os family - pm = &MacOSPkgManager{conn: conn} + pm = &MacOSPkgManager{conn: conn, platform: asset.Platform} case asset.Platform.Name == "windows": pm = &WinPkgManager{conn: conn, platform: asset.Platform} case asset.Platform.Name == "scratch" || asset.Platform.Name == "coreos": diff --git a/providers/os/resources/packages/windows_packages.go b/providers/os/resources/packages/windows_packages.go index 714b8df191..889a3e8f07 100644 --- a/providers/os/resources/packages/windows_packages.go +++ b/providers/os/resources/packages/windows_packages.go @@ -22,6 +22,7 @@ import ( "go.mondoo.com/cnquery/v11/providers/os/registry" "go.mondoo.com/cnquery/v11/providers/os/resources/cpe" "go.mondoo.com/cnquery/v11/providers/os/resources/powershell" + "go.mondoo.com/cnquery/v11/providers/os/resources/purl" ) // ProcessorArchitecture Enum @@ -112,7 +113,7 @@ type winAppxPackages struct { arch string `json:"-"` } -func (p winAppxPackages) toPackage() Package { +func (p winAppxPackages) toPackage(platform *inventory.Platform) Package { if p.arch == "" { arch, ok := appxArchitecture[p.Architecture] if !ok { @@ -128,12 +129,18 @@ func (p winAppxPackages) toPackage() Package { Arch: p.arch, Format: "windows/appx", Vendor: p.Publisher, + PUrl: purl.NewPackageUrl( + platform, p.Name, p.Version, platform.Arch, "", purl.TypeWindowsAppx, + ), } if p.Name != "" && p.Version != "" { cpeWfns, err := cpe.NewPackage2Cpe(p.Publisher, p.Name, p.Version, "", "") if err != nil { - log.Debug().Err(err).Str("name", p.Name).Str("version", p.Version).Msg("could not create cpe for windows appx package") + log.Debug().Err(err). + Str("name", p.Name). + Str("version", p.Version). + Msg("could not create cpe for windows appx package") } else { pkg.CPEs = cpeWfns } @@ -145,7 +152,7 @@ func (p winAppxPackages) toPackage() Package { } // Good read: https://www.wintips.org/view-installed-apps-and-packages-in-windows-10-8-1-8-from-powershell/ -func ParseWindowsAppxPackages(input io.Reader) ([]Package, error) { +func ParseWindowsAppxPackages(platform *inventory.Platform, input io.Reader) ([]Package, error) { data, err := io.ReadAll(input) if err != nil { return nil, err @@ -165,8 +172,7 @@ func ParseWindowsAppxPackages(input io.Reader) ([]Package, error) { pkgs := make([]Package, len(appxPackages)) for i, p := range appxPackages { - pkg := p.toPackage() - pkgs[i] = pkg + pkgs[i] = p.toPackage(platform) } return pkgs, nil } @@ -281,7 +287,7 @@ func (w *WinPkgManager) getInstalledApps() ([]Package, error) { return nil, errors.New("failed to retrieve installed apps: " + string(stderr)) } - return ParseWindowsAppPackages(cmd.Stdout) + return ParseWindowsAppPackages(w.platform, cmd.Stdout) } func (w *WinPkgManager) getAppxPackages() ([]Package, error) { @@ -309,7 +315,7 @@ func (w *WinPkgManager) getPwshAppxPackages() ([]Package, error) { if err != nil { return nil, fmt.Errorf("could not read appx package list") } - return ParseWindowsAppxPackages(cmd.Stdout) + return ParseWindowsAppxPackages(w.platform, cmd.Stdout) } func (w *WinPkgManager) getFsInstalledApps() ([]Package, error) { @@ -394,7 +400,7 @@ func (w *WinPkgManager) getFsAppxPackages() ([]Package, error) { log.Debug().Err(err).Str("path", p).Msg("could not parse appx manifest") continue } - pkg := winAppxPkg.toPackage() + pkg := winAppxPkg.toPackage(w.platform) pkgs = append(pkgs, pkg) } @@ -504,7 +510,7 @@ func (w *WinPkgManager) List() ([]Package, error) { return pkgs, nil } -func ParseWindowsAppPackages(input io.Reader) ([]Package, error) { +func ParseWindowsAppPackages(platform *inventory.Platform, input io.Reader) ([]Package, error) { data, err := io.ReadAll(input) if err != nil { return nil, err @@ -540,7 +546,10 @@ func ParseWindowsAppPackages(input io.Reader) ([]Package, error) { if entry.DisplayName != "" && entry.DisplayVersion != "" { cpeWfns, err = cpe.NewPackage2Cpe(entry.Publisher, entry.DisplayName, entry.DisplayVersion, "", "") if err != nil { - log.Debug().Err(err).Str("name", entry.DisplayName).Str("version", entry.DisplayVersion).Msg("could not create cpe for windows app package") + log.Debug().Err(err). + Str("name", entry.DisplayName). + Str("version", entry.DisplayVersion). + Msg("could not create cpe for windows app package") } } else { log.Debug().Msg("ignored package since information is missing") @@ -551,6 +560,9 @@ func ParseWindowsAppPackages(input io.Reader) ([]Package, error) { Format: "windows/app", CPEs: cpeWfns, Vendor: entry.Publisher, + PUrl: purl.NewPackageUrl( + platform, entry.DisplayName, entry.DisplayVersion, platform.Arch, "", purl.TypeWindows, + ), }) } diff --git a/providers/os/resources/packages/windows_packages_test.go b/providers/os/resources/packages/windows_packages_test.go index 3feb0f4414..9c98928030 100644 --- a/providers/os/resources/packages/windows_packages_test.go +++ b/providers/os/resources/packages/windows_packages_test.go @@ -22,7 +22,13 @@ func TestWindowsAppPackagesParser(t *testing.T) { require.NoError(t, err) defer f.Close() - pkgs, err := ParseWindowsAppPackages(f) + pf := &inventory.Platform{ + Name: "windows", + Version: "10.0.18363", + Arch: "x86", + Family: []string{"windows"}, + } + pkgs, err := ParseWindowsAppPackages(pf, f) assert.Nil(t, err) assert.Equal(t, 19, len(pkgs), "detected the right amount of packages") @@ -32,6 +38,7 @@ func TestWindowsAppPackagesParser(t *testing.T) { Version: "14.28.29913.0", Arch: "", Format: "windows/app", + PUrl: `pkg:windows/Microsoft%20Visual%20C%2B%2B%202015-2019%20Redistributable%20%28x86%29%20-%2014.28.29913@14.28.29913.0?arch=x86&distro=windows-10.0.18363`, CPEs: []string{ "cpe:2.3:a:microsoft_corporation:microsoft_visual_c\\+\\+_2015-2019_redistributable_\\(x86\\)_-_14.28.29913:14.28.29913.0:*:*:*:*:*:*:*", "cpe:2.3:a:microsoft:microsoft_visual_c\\+\\+_2015-2019_redistributable_\\(x86\\)_-_14.28.29913:14.28.29913.0:*:*:*:*:*:*:*", @@ -41,7 +48,7 @@ func TestWindowsAppPackagesParser(t *testing.T) { }, p) // check empty return - pkgs, err = ParseWindowsAppxPackages(strings.NewReader("")) + pkgs, err = ParseWindowsAppxPackages(pf, strings.NewReader("")) assert.Nil(t, err) assert.Equal(t, 0, len(pkgs), "detected the right amount of packages") } @@ -61,7 +68,14 @@ func TestWindowsAppxPackagesParser(t *testing.T) { t.Fatal(err) } - pkgs, err := ParseWindowsAppxPackages(c.Stdout) + pf := &inventory.Platform{ + Name: "windows", + Version: "10.0.18363", + Arch: "x86", + Family: []string{"windows"}, + } + + pkgs, err := ParseWindowsAppxPackages(pf, c.Stdout) assert.Nil(t, err) assert.Equal(t, 28, len(pkgs), "detected the right amount of packages") @@ -71,6 +85,7 @@ func TestWindowsAppxPackagesParser(t *testing.T) { Version: "1.11.5.17763", Arch: "neutral", Format: "windows/appx", + PUrl: "pkg:appx/windows/Microsoft.Windows.Cortana@1.11.5.17763?arch=x86&distro=windows-10.0.18363", // TODO: this is a bug in the CPE generation, we need to extract the publisher from the package CPEs: []string{ "cpe:2.3:a:cn\\=microsoft_corporation\\,_o\\=microsoft_corporation\\,_l\\=redmond\\,_s\\=washington\\,_c\\=us:microsoft.windows.cortana:1.11.5.17763:*:*:*:*:*:*:*", @@ -80,7 +95,7 @@ func TestWindowsAppxPackagesParser(t *testing.T) { }, p) // check empty return - pkgs, err = ParseWindowsAppxPackages(strings.NewReader("")) + pkgs, err = ParseWindowsAppxPackages(pf, strings.NewReader("")) assert.Nil(t, err) assert.Equal(t, 0, len(pkgs), "detected the right amount of packages") } @@ -203,13 +218,21 @@ func TestToPackage(t *testing.T) { Architecture: 0, } - pkg := winAppxPkg.toPackage() + pf := &inventory.Platform{ + Name: "windows", + Version: "10.0.18363", + Arch: "x86", + Family: []string{"windows"}, + } + + pkg := winAppxPkg.toPackage(pf) expected := Package{ Name: "Microsoft.Windows.Cortana", Version: "1.11.5.17763", Arch: "x86", Format: "windows/appx", + PUrl: "pkg:appx/windows/Microsoft.Windows.Cortana@1.11.5.17763?arch=x86&distro=windows-10.0.18363", Vendor: "CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US", CPEs: []string{ "cpe:2.3:a:cn\\=microsoft_corporation\\,_o\\=microsoft_corporation\\,_l\\=redmond\\,_s\\=washington\\,_c\\=us:microsoft.windows.cortana:1.11.5.17763:*:*:*:*:*:*:*", diff --git a/providers/os/resources/purl/purl.go b/providers/os/resources/purl/purl.go index 1ec4146d63..26b481c6f2 100644 --- a/providers/os/resources/purl/purl.go +++ b/providers/os/resources/purl/purl.go @@ -4,11 +4,12 @@ package purl import ( + "sort" + "strings" + "github.com/package-url/packageurl-go" "go.mondoo.com/cnquery/v11/providers-sdk/v1/inventory" "go.mondoo.com/cnquery/v11/providers/os/detector" - "sort" - "strings" ) const ( @@ -69,6 +70,11 @@ func NewPackageUrl(pf *inventory.Platform, name string, version string, arch str } qualifiers[QualifierDistro] = strings.Join(distroQualifiers, "-") + // Avoids creating purl's like: 'pkg:macos/macos/Package' + if namespace == purlType { + namespace = "" + } + return packageurl.NewPackageURL( purlType, namespace, diff --git a/providers/os/resources/purl/purl_types.go b/providers/os/resources/purl/purl_types.go new file mode 100644 index 0000000000..48bebdc938 --- /dev/null +++ b/providers/os/resources/purl/purl_types.go @@ -0,0 +1,37 @@ +// Copyright (c) Mondoo, Inc. +// SPDX-License-Identifier: BUSL-1.1 + +package purl + +import "github.com/package-url/packageurl-go" + +type Type string + +// These are only an extension of the known purl types defined at: +// +// https://github.com/package-url/packageurl-go/blob/master/packageurl.go#L54 +// https://github.com/package-url/purl-spec#known-purl-types +var ( + // TypeWindows is a pkg:windows purl. + TypeWindows = "windows" + TypeWindowsAppx = "appx" + // TypeMacos is a pkg:macos purl. + TypeMacos = "macos" + + KnownTypes = map[string]struct{}{ + TypeWindows: {}, + TypeMacos: {}, + } +) + +func init() { + // merge packageurl.KnownTypes and the extension types + for t := range packageurl.KnownTypes { + KnownTypes[t] = struct{}{} + } +} + +func ValidType(t string) bool { + _, ok := KnownTypes[t] + return ok +} diff --git a/sbom/sbom.pb.go b/sbom/sbom.pb.go index 236d147cea..c07a8f5b95 100644 --- a/sbom/sbom.pb.go +++ b/sbom/sbom.pb.go @@ -3,8 +3,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.35.1 -// protoc v5.28.3 +// protoc-gen-go v1.35.2 +// protoc v5.29.0 // source: sbom.proto package sbom diff --git a/shared/proto/cnquery.pb.go b/shared/proto/cnquery.pb.go index 7a88682d30..0ecb330e8a 100644 --- a/shared/proto/cnquery.pb.go +++ b/shared/proto/cnquery.pb.go @@ -3,8 +3,8 @@ // Code generated by protoc-gen-go. DO NOT EDIT. // versions: -// protoc-gen-go v1.35.1 -// protoc v5.28.3 +// protoc-gen-go v1.35.2 +// protoc v5.29.0 // source: cnquery.proto package proto diff --git a/shared/proto/cnquery_grpc.pb.go b/shared/proto/cnquery_grpc.pb.go index 3ef3aece8c..6c9d541e29 100644 --- a/shared/proto/cnquery_grpc.pb.go +++ b/shared/proto/cnquery_grpc.pb.go @@ -4,7 +4,7 @@ // Code generated by protoc-gen-go-grpc. DO NOT EDIT. // versions: // - protoc-gen-go-grpc v1.5.1 -// - protoc v5.28.3 +// - protoc v5.29.0 // source: cnquery.proto package proto