From bd358fcc52c2dbcdf7d9cbb48ceec67672e411fb Mon Sep 17 00:00:00 2001 From: Mikita Iwanowski Date: Mon, 12 Aug 2024 18:59:37 +0200 Subject: [PATCH 1/7] feat: add serialnumber to asset ids --- providers/os/id/ids/ids.go | 11 ++++++----- providers/os/id/platform.go | 14 +++++++++++++- providers/os/id/serialnumber/serial.go | 25 +++++++++++++++++++++++++ 3 files changed, 44 insertions(+), 6 deletions(-) create mode 100644 providers/os/id/serialnumber/serial.go diff --git a/providers/os/id/ids/ids.go b/providers/os/id/ids/ids.go index 94f14597c1..1d0ff3c9c7 100644 --- a/providers/os/id/ids/ids.go +++ b/providers/os/id/ids/ids.go @@ -4,11 +4,12 @@ package ids const ( - IdDetector_Hostname = "hostname" - IdDetector_MachineID = "machine-id" - IdDetector_CloudDetect = "cloud-detect" - IdDetector_SshHostkey = "ssh-host-key" - IdDetector_AwsEcs = "aws-ecs" + IdDetector_Hostname = "hostname" + IdDetector_MachineID = "machine-id" + IdDetector_MachineSerial = "serialnumber" + IdDetector_CloudDetect = "cloud-detect" + IdDetector_SshHostkey = "ssh-host-key" + IdDetector_AwsEcs = "aws-ecs" // IdDetector_PlatformID = "transport-platform-id" // TODO: how does this work? ) diff --git a/providers/os/id/platform.go b/providers/os/id/platform.go index ed44fdc99a..3272c80a46 100644 --- a/providers/os/id/platform.go +++ b/providers/os/id/platform.go @@ -17,6 +17,7 @@ import ( "go.mondoo.com/cnquery/v11/providers/os/id/hostname" "go.mondoo.com/cnquery/v11/providers/os/id/ids" "go.mondoo.com/cnquery/v11/providers/os/id/machineid" + "go.mondoo.com/cnquery/v11/providers/os/id/serialnumber" "go.mondoo.com/cnquery/v11/providers/os/id/sshhostkey" ) @@ -52,7 +53,7 @@ func IdentifyPlatform(conn shared.Connection, p *inventory.Platform, idDetectors // fallback to default id detectors switch conn.Type() { case shared.Type_Local: - idDetectors = []string{ids.IdDetector_Hostname, ids.IdDetector_CloudDetect} + idDetectors = []string{ids.IdDetector_Hostname, ids.IdDetector_MachineSerial, ids.IdDetector_CloudDetect} case shared.Type_SSH: idDetectors = []string{ids.IdDetector_Hostname, ids.IdDetector_CloudDetect, ids.IdDetector_SshHostkey} case shared.Type_Tar, shared.Type_FileSystem, shared.Type_DockerSnapshot: @@ -161,6 +162,17 @@ func GatherPlatformInfo(conn shared.Connection, pf *inventory.Platform, idDetect }, hostErr } return &PlatformInfo{}, nil + case idDetector == ids.IdDetector_MachineSerial: + serial, err := serialnumber.SerialNumber(conn, pf) + if err == nil && len(serial) > 0 { + identifier = "//platformid.api.mondoo.app/serialnumber/" + serial + return &PlatformInfo{ + IDs: []string{identifier}, + Name: "", + RelatedPlatformIDs: []string{}, + }, nil + } + return &PlatformInfo{}, nil case idDetector == ids.IdDetector_AwsEcs: metadata, err := awsecs.Resolve(conn, pf) if err != nil { diff --git a/providers/os/id/serialnumber/serial.go b/providers/os/id/serialnumber/serial.go new file mode 100644 index 0000000000..36d2fc07ee --- /dev/null +++ b/providers/os/id/serialnumber/serial.go @@ -0,0 +1,25 @@ +package serialnumber + +import ( + "github.com/pkg/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/smbios" +) + +func SerialNumber(conn shared.Connection, p *inventory.Platform) (string, error) { + mgr, err := smbios.ResolveManager(conn, p) + if err != nil { + return "", errors.Wrap(err, "cannot determine platform serial number") + } + if mgr == nil { + return "", errors.New("cannot determine platform serial number") + } + + info, err := mgr.Info() + if err != nil { + return "", errors.New("cannot determine platform serial number") + } + + return info.SysInfo.SerialNumber, nil +} From 19e778069ed79ab4353ff80462501524a763ef3a Mon Sep 17 00:00:00 2001 From: Mikita Iwanowski Date: Mon, 12 Aug 2024 19:00:33 +0200 Subject: [PATCH 2/7] license --- providers/os/id/serialnumber/serial.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/providers/os/id/serialnumber/serial.go b/providers/os/id/serialnumber/serial.go index 36d2fc07ee..4275de664c 100644 --- a/providers/os/id/serialnumber/serial.go +++ b/providers/os/id/serialnumber/serial.go @@ -1,3 +1,6 @@ +// Copyright (c) Mondoo, Inc. +// SPDX-License-Identifier: BUSL-1.1 + package serialnumber import ( From 56f366fce2892e2733fbf5efb3dfb7eff12d8654 Mon Sep 17 00:00:00 2001 From: Mikita Iwanowski Date: Mon, 12 Aug 2024 19:07:35 +0200 Subject: [PATCH 3/7] fix: test + rename IdDetector to match package and function --- providers/os/id/ids/ids.go | 12 ++++++------ providers/os/id/platform.go | 4 ++-- providers/os/provider/provider_test.go | 3 ++- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/providers/os/id/ids/ids.go b/providers/os/id/ids/ids.go index 1d0ff3c9c7..b6c606a3c0 100644 --- a/providers/os/id/ids/ids.go +++ b/providers/os/id/ids/ids.go @@ -4,12 +4,12 @@ package ids const ( - IdDetector_Hostname = "hostname" - IdDetector_MachineID = "machine-id" - IdDetector_MachineSerial = "serialnumber" - IdDetector_CloudDetect = "cloud-detect" - IdDetector_SshHostkey = "ssh-host-key" - IdDetector_AwsEcs = "aws-ecs" + IdDetector_Hostname = "hostname" + IdDetector_MachineID = "machine-id" + IdDetector_SerialNumber = "serialnumber" + IdDetector_CloudDetect = "cloud-detect" + IdDetector_SshHostkey = "ssh-host-key" + IdDetector_AwsEcs = "aws-ecs" // IdDetector_PlatformID = "transport-platform-id" // TODO: how does this work? ) diff --git a/providers/os/id/platform.go b/providers/os/id/platform.go index 3272c80a46..be24c06f6a 100644 --- a/providers/os/id/platform.go +++ b/providers/os/id/platform.go @@ -53,7 +53,7 @@ func IdentifyPlatform(conn shared.Connection, p *inventory.Platform, idDetectors // fallback to default id detectors switch conn.Type() { case shared.Type_Local: - idDetectors = []string{ids.IdDetector_Hostname, ids.IdDetector_MachineSerial, ids.IdDetector_CloudDetect} + idDetectors = []string{ids.IdDetector_Hostname, ids.IdDetector_SerialNumber, ids.IdDetector_CloudDetect} case shared.Type_SSH: idDetectors = []string{ids.IdDetector_Hostname, ids.IdDetector_CloudDetect, ids.IdDetector_SshHostkey} case shared.Type_Tar, shared.Type_FileSystem, shared.Type_DockerSnapshot: @@ -162,7 +162,7 @@ func GatherPlatformInfo(conn shared.Connection, pf *inventory.Platform, idDetect }, hostErr } return &PlatformInfo{}, nil - case idDetector == ids.IdDetector_MachineSerial: + case idDetector == ids.IdDetector_SerialNumber: serial, err := serialnumber.SerialNumber(conn, pf) if err == nil && len(serial) > 0 { identifier = "//platformid.api.mondoo.app/serialnumber/" + serial diff --git a/providers/os/provider/provider_test.go b/providers/os/provider/provider_test.go index 00986a428b..53a36526be 100644 --- a/providers/os/provider/provider_test.go +++ b/providers/os/provider/provider_test.go @@ -35,8 +35,9 @@ func TestLocalConnectionIdDetectors(t *testing.T) { require.NoError(t, err) require.NotNil(t, connectResp) - require.Len(t, connectResp.Asset.IdDetector, 2) + require.Len(t, connectResp.Asset.IdDetector, 3) require.Contains(t, connectResp.Asset.IdDetector, ids.IdDetector_Hostname) + require.Contains(t, connectResp.Asset.IdDetector, ids.IdDetector_SerialNumber) require.Contains(t, connectResp.Asset.IdDetector, ids.IdDetector_CloudDetect) require.NotContains(t, connectResp.Asset.IdDetector, ids.IdDetector_SshHostkey) From d2f274bb08d467bd9da3f4359c948223c053978b Mon Sep 17 00:00:00 2001 From: Mikita Iwanowski Date: Mon, 12 Aug 2024 19:09:14 +0200 Subject: [PATCH 4/7] fix test --- providers/os/provider/provider_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/providers/os/provider/provider_test.go b/providers/os/provider/provider_test.go index 53a36526be..34d20a26b1 100644 --- a/providers/os/provider/provider_test.go +++ b/providers/os/provider/provider_test.go @@ -41,7 +41,7 @@ func TestLocalConnectionIdDetectors(t *testing.T) { require.Contains(t, connectResp.Asset.IdDetector, ids.IdDetector_CloudDetect) require.NotContains(t, connectResp.Asset.IdDetector, ids.IdDetector_SshHostkey) - require.Len(t, connectResp.Asset.PlatformIds, 1) + require.Len(t, connectResp.Asset.PlatformIds, 2) shutdownconnectResp, err := srv.Shutdown(&plugin.ShutdownReq{}) require.NoError(t, err) @@ -56,12 +56,12 @@ func TestLocalConnectionIdDetectors(t *testing.T) { require.NoError(t, err) require.NotNil(t, connectResp) - require.Len(t, connectResp.Asset.IdDetector, 2) + require.Len(t, connectResp.Asset.IdDetector, 3) require.Contains(t, connectResp.Asset.IdDetector, ids.IdDetector_Hostname) require.Contains(t, connectResp.Asset.IdDetector, ids.IdDetector_CloudDetect) require.NotContains(t, connectResp.Asset.IdDetector, ids.IdDetector_SshHostkey) // Now the platformIDs are cleaned up - require.Len(t, connectResp.Asset.PlatformIds, 1) + require.Len(t, connectResp.Asset.PlatformIds, 2) shutdownconnectResp, err = srv.Shutdown(&plugin.ShutdownReq{}) require.NoError(t, err) From 97943a934f8a06710baeb71980883a0e2e8eaf41 Mon Sep 17 00:00:00 2001 From: Mikita Iwanowski Date: Mon, 12 Aug 2024 19:15:23 +0200 Subject: [PATCH 5/7] revert expected platformids (CI runners don't have serial numbers (bios) info) --- providers/os/provider/provider_test.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/providers/os/provider/provider_test.go b/providers/os/provider/provider_test.go index 34d20a26b1..723d920ff3 100644 --- a/providers/os/provider/provider_test.go +++ b/providers/os/provider/provider_test.go @@ -41,7 +41,7 @@ func TestLocalConnectionIdDetectors(t *testing.T) { require.Contains(t, connectResp.Asset.IdDetector, ids.IdDetector_CloudDetect) require.NotContains(t, connectResp.Asset.IdDetector, ids.IdDetector_SshHostkey) - require.Len(t, connectResp.Asset.PlatformIds, 2) + require.Len(t, connectResp.Asset.PlatformIds, 1) shutdownconnectResp, err := srv.Shutdown(&plugin.ShutdownReq{}) require.NoError(t, err) @@ -61,7 +61,7 @@ func TestLocalConnectionIdDetectors(t *testing.T) { require.Contains(t, connectResp.Asset.IdDetector, ids.IdDetector_CloudDetect) require.NotContains(t, connectResp.Asset.IdDetector, ids.IdDetector_SshHostkey) // Now the platformIDs are cleaned up - require.Len(t, connectResp.Asset.PlatformIds, 2) + require.Len(t, connectResp.Asset.PlatformIds, 1) shutdownconnectResp, err = srv.Shutdown(&plugin.ShutdownReq{}) require.NoError(t, err) From 591d7264902cd9b3e63be8ab4963bd575d106dec Mon Sep 17 00:00:00 2001 From: Mikita Iwanowski Date: Wed, 18 Sep 2024 15:55:06 +0200 Subject: [PATCH 6/7] feat: add feature flag for SerialNumber id detector --- feature_string.go | 5 +++-- featureflags.go | 7 +++++++ providers-sdk/v1/sysinfo/sysinfo.go | 3 ++- providers/os/connection/device/device_connection.go | 2 +- providers/os/id/platform.go | 9 +++++++-- providers/os/provider/provider.go | 12 ++++++------ 6 files changed, 26 insertions(+), 12 deletions(-) diff --git a/feature_string.go b/feature_string.go index 16b3aec562..c2e0695fdf 100644 --- a/feature_string.go +++ b/feature_string.go @@ -16,11 +16,12 @@ func _() { _ = x[ErrorsAsFailures-6] _ = x[StoreResourcesData-7] _ = x[FineGrainedAssets-8] + _ = x[SerialNumberAsID-9] } -const _Feature_name = "MassQueriesPiperCodeBoolAssertionsK8sNodeDiscoveryMQLAssetContextErrorsAsFailuresStoreResourcesDataFineGrainedAssets" +const _Feature_name = "MassQueriesPiperCodeBoolAssertionsK8sNodeDiscoveryMQLAssetContextErrorsAsFailuresStoreResourcesDataFineGrainedAssetsSerialNumberAsID" -var _Feature_index = [...]uint8{0, 11, 20, 34, 50, 65, 81, 99, 116} +var _Feature_index = [...]uint8{0, 11, 20, 34, 50, 65, 81, 99, 116, 132} func (i Feature) String() string { i -= 1 diff --git a/featureflags.go b/featureflags.go index 947ad629fb..0595c3cc6d 100644 --- a/featureflags.go +++ b/featureflags.go @@ -88,6 +88,12 @@ const ( // start: v11.x // end: tbd (candidate: v12.0) FineGrainedAssets + + // SerialNumberAsID feature flag + // desc: Use serial number as the asset ID + // start: v11.x + // end: tbd (candidate: v12.0) + SerialNumberAsID ) // FeaturesValue is a map from feature name to feature flag @@ -99,6 +105,7 @@ var FeaturesValue = map[string]Feature{ ErrorsAsFailures.String(): ErrorsAsFailures, StoreResourcesData.String(): StoreResourcesData, FineGrainedAssets.String(): FineGrainedAssets, + SerialNumberAsID.String(): SerialNumberAsID, } // DefaultFeatures are a set of default flags that are active diff --git a/providers-sdk/v1/sysinfo/sysinfo.go b/providers-sdk/v1/sysinfo/sysinfo.go index 4e5aa72fe3..0ae78eeb84 100644 --- a/providers-sdk/v1/sysinfo/sysinfo.go +++ b/providers-sdk/v1/sysinfo/sysinfo.go @@ -11,6 +11,7 @@ import ( "go.mondoo.com/cnquery/v11" "go.mondoo.com/cnquery/v11/cli/execruntime" "go.mondoo.com/cnquery/v11/providers-sdk/v1/inventory" + "go.mondoo.com/cnquery/v11/providers-sdk/v1/plugin" "go.mondoo.com/cnquery/v11/providers/os/connection/local" "go.mondoo.com/cnquery/v11/providers/os/id" "go.mondoo.com/cnquery/v11/providers/os/id/hostname" @@ -46,7 +47,7 @@ func Get() (*SystemInfo, error) { Type: "local", }, &asset) - fingerprint, platform, _ := id.IdentifyPlatform(conn, asset.Platform, asset.IdDetector) + fingerprint, platform, _ := id.IdentifyPlatform(conn, &plugin.ConnectReq{}, asset.Platform, asset.IdDetector) if fingerprint != nil { if len(fingerprint.PlatformIDs) > 0 { sysInfo.PlatformId = fingerprint.PlatformIDs[0] diff --git a/providers/os/connection/device/device_connection.go b/providers/os/connection/device/device_connection.go index da236f4a51..e484124964 100644 --- a/providers/os/connection/device/device_connection.go +++ b/providers/os/connection/device/device_connection.go @@ -111,7 +111,7 @@ func NewDeviceConnection(connId uint32, conf *inventory.Config, asset *inventory } asset.Platform = p asset.IdDetector = []string{ids.IdDetector_Hostname} - fingerprint, p, err := id.IdentifyPlatform(res, asset.Platform, asset.IdDetector) + fingerprint, p, err := id.IdentifyPlatform(res, &plugin.ConnectReq{}, asset.Platform, asset.IdDetector) if err == nil { if asset.Name == "" { asset.Name = fingerprint.Name diff --git a/providers/os/id/platform.go b/providers/os/id/platform.go index be24c06f6a..a52ea6ab7a 100644 --- a/providers/os/id/platform.go +++ b/providers/os/id/platform.go @@ -8,7 +8,9 @@ import ( "fmt" "github.com/rs/zerolog/log" + "go.mondoo.com/cnquery/v11" "go.mondoo.com/cnquery/v11/providers-sdk/v1/inventory" + "go.mondoo.com/cnquery/v11/providers-sdk/v1/plugin" "go.mondoo.com/cnquery/v11/providers/os/connection/shared" "go.mondoo.com/cnquery/v11/providers/os/detector" "go.mondoo.com/cnquery/v11/providers/os/id/awsec2" @@ -36,7 +38,7 @@ type PlatformInfo struct { RelatedPlatformIDs []string } -func IdentifyPlatform(conn shared.Connection, p *inventory.Platform, idDetectors []string) (*PlatformFingerprint, *inventory.Platform, error) { +func IdentifyPlatform(conn shared.Connection, req *plugin.ConnectReq, p *inventory.Platform, idDetectors []string) (*PlatformFingerprint, *inventory.Platform, error) { var ok bool if p == nil { p, ok = detector.DetectOS(conn) @@ -53,7 +55,10 @@ func IdentifyPlatform(conn shared.Connection, p *inventory.Platform, idDetectors // fallback to default id detectors switch conn.Type() { case shared.Type_Local: - idDetectors = []string{ids.IdDetector_Hostname, ids.IdDetector_SerialNumber, ids.IdDetector_CloudDetect} + idDetectors = []string{ids.IdDetector_Hostname, ids.IdDetector_CloudDetect} + if cnquery.Features(req.Features).IsActive(cnquery.SerialNumberAsID) { + idDetectors = append(idDetectors, ids.IdDetector_SerialNumber) + } case shared.Type_SSH: idDetectors = []string{ids.IdDetector_Hostname, ids.IdDetector_CloudDetect, ids.IdDetector_SshHostkey} case shared.Type_Tar, shared.Type_FileSystem, shared.Type_DockerSnapshot: diff --git a/providers/os/provider/provider.go b/providers/os/provider/provider.go index 891b46380a..a2b935d885 100644 --- a/providers/os/provider/provider.go +++ b/providers/os/provider/provider.go @@ -350,7 +350,7 @@ func (s *Service) connect(req *plugin.ConnectReq, callback plugin.ProviderCallba case shared.Type_Local.String(), "k8s": // FIXME: k8s is a temp workaround for cross-provider resources conn = local.NewConnection(connId, conf, asset) - fingerprint, p, err := id.IdentifyPlatform(conn, asset.Platform, asset.IdDetector) + fingerprint, p, err := id.IdentifyPlatform(conn, req, asset.Platform, asset.IdDetector) if err == nil { if asset.Name == "" { asset.Name = fingerprint.Name @@ -368,7 +368,7 @@ func (s *Service) connect(req *plugin.ConnectReq, callback plugin.ProviderCallba return nil, err } - fingerprint, p, err := id.IdentifyPlatform(conn, asset.Platform, asset.IdDetector) + fingerprint, p, err := id.IdentifyPlatform(conn, req, asset.Platform, asset.IdDetector) if err == nil { if conn.Asset().Connections[0].Runtime != "vagrant" { asset.Name = fingerprint.Name @@ -385,7 +385,7 @@ func (s *Service) connect(req *plugin.ConnectReq, callback plugin.ProviderCallba return nil, err } - fingerprint, p, err := id.IdentifyPlatform(conn, asset.Platform, asset.IdDetector) + fingerprint, p, err := id.IdentifyPlatform(conn, req, asset.Platform, asset.IdDetector) if err == nil { asset.Name = fingerprint.Name asset.PlatformIds = fingerprint.PlatformIDs @@ -400,7 +400,7 @@ func (s *Service) connect(req *plugin.ConnectReq, callback plugin.ProviderCallba return nil, err } - fingerprint, p, err := id.IdentifyPlatform(conn, asset.Platform, asset.IdDetector) + fingerprint, p, err := id.IdentifyPlatform(conn, req, asset.Platform, asset.IdDetector) if err == nil { asset.Name = fingerprint.Name asset.PlatformIds = fingerprint.PlatformIDs @@ -415,7 +415,7 @@ func (s *Service) connect(req *plugin.ConnectReq, callback plugin.ProviderCallba return nil, err } - fingerprint, p, err := id.IdentifyPlatform(conn, asset.Platform, asset.IdDetector) + fingerprint, p, err := id.IdentifyPlatform(conn, req, asset.Platform, asset.IdDetector) if err == nil { asset.Name = fingerprint.Name asset.PlatformIds = fingerprint.PlatformIDs @@ -467,7 +467,7 @@ func (s *Service) connect(req *plugin.ConnectReq, callback plugin.ProviderCallba // This is a workaround to set Google COS platform IDs when scanned from inside k8s pID, err := conn.(*fs.FileSystemConnection).Identifier() if err != nil { - fingerprint, p, err := id.IdentifyPlatform(conn, asset.Platform, asset.IdDetector) + fingerprint, p, err := id.IdentifyPlatform(conn, req, asset.Platform, asset.IdDetector) if err == nil { asset.Name = fingerprint.Name asset.PlatformIds = fingerprint.PlatformIDs From ff8c8a671f1ce40e4342327a15deae34bd482499 Mon Sep 17 00:00:00 2001 From: Mikita Iwanowski Date: Wed, 18 Sep 2024 18:10:15 +0200 Subject: [PATCH 7/7] fix: revert test --- providers/os/provider/provider_test.go | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/providers/os/provider/provider_test.go b/providers/os/provider/provider_test.go index 723d920ff3..00986a428b 100644 --- a/providers/os/provider/provider_test.go +++ b/providers/os/provider/provider_test.go @@ -35,9 +35,8 @@ func TestLocalConnectionIdDetectors(t *testing.T) { require.NoError(t, err) require.NotNil(t, connectResp) - require.Len(t, connectResp.Asset.IdDetector, 3) + require.Len(t, connectResp.Asset.IdDetector, 2) require.Contains(t, connectResp.Asset.IdDetector, ids.IdDetector_Hostname) - require.Contains(t, connectResp.Asset.IdDetector, ids.IdDetector_SerialNumber) require.Contains(t, connectResp.Asset.IdDetector, ids.IdDetector_CloudDetect) require.NotContains(t, connectResp.Asset.IdDetector, ids.IdDetector_SshHostkey) @@ -56,7 +55,7 @@ func TestLocalConnectionIdDetectors(t *testing.T) { require.NoError(t, err) require.NotNil(t, connectResp) - require.Len(t, connectResp.Asset.IdDetector, 3) + require.Len(t, connectResp.Asset.IdDetector, 2) require.Contains(t, connectResp.Asset.IdDetector, ids.IdDetector_Hostname) require.Contains(t, connectResp.Asset.IdDetector, ids.IdDetector_CloudDetect) require.NotContains(t, connectResp.Asset.IdDetector, ids.IdDetector_SshHostkey)