Skip to content
11 changes: 11 additions & 0 deletions providers-sdk/v1/inventory/asset_kinds.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Copyright (c) Mondoo, Inc.
// SPDX-License-Identifier: BUSL-1.1

package inventory

// Use this file to define kinds of assets that are used widely.

const (
AssetKindCloudVM = "virtualmachine"
AssetKindBaremetal = "baremetal"
)
4 changes: 2 additions & 2 deletions providers-sdk/v1/inventory/inventory.go
Original file line number Diff line number Diff line change
Expand Up @@ -361,13 +361,13 @@ func (p *Platform) PrettyTitle() string {
} else {
runtimeKind := p.Kind
switch runtimeKind {
case "baremetal":
case AssetKindBaremetal:
runtimeNiceName = "bare metal"
case "container":
runtimeNiceName = "Container"
case "container-image":
runtimeNiceName = "Container Image"
case "virtualmachine":
case AssetKindCloudVM:
runtimeNiceName = "Virtual Machine"
case "virtualmachine-image":
runtimeNiceName = "Virtual Machine Image"
Expand Down
4 changes: 2 additions & 2 deletions providers/aws/resources/discovery_conversion.go
Original file line number Diff line number Diff line change
Expand Up @@ -285,7 +285,7 @@ func addConnectionInfoToEc2Asset(instance *mqlAwsEc2Instance, accountId string,
asset.PlatformIds = []string{awsec2.MondooInstanceID(accountId, instance.Region.Data, instance.InstanceId.Data)}
asset.IdDetector = []string{ids.IdDetector_Hostname, ids.IdDetector_CloudDetect, ids.IdDetector_SshHostkey}
asset.Platform = &inventory.Platform{
Kind: "virtual_machine",
Kind: inventory.AssetKindCloudVM,
Runtime: "aws-ec2-instance",
Family: getPlatformFamily(instance.PlatformDetails.Data),
}
Expand Down Expand Up @@ -432,7 +432,7 @@ func addConnectionInfoToSSMAsset(instance *mqlAwsSsmInstance, accountId string,
asset.Options = conn.ConnectionOptions()
asset.PlatformIds = []string{awsec2.MondooInstanceID(accountId, instance.Region.Data, instance.InstanceId.Data)}
asset.Platform = &inventory.Platform{
Kind: "virtual_machine",
Kind: inventory.AssetKindCloudVM,
Runtime: "aws-ssm-instance",
Family: getPlatformFamily(instance.PlatformName.Data),
}
Expand Down
2 changes: 1 addition & 1 deletion providers/azure/resources/discovery.go
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ func discoverInstances(runtime *plugin.Runtime, subsWithConfigs []subWithConfig)
enrichWithLabels(asset, labels)
asset.PlatformIds = []string{MondooAzureInstanceID(vm.Id.Data)}
asset.Platform.Runtime = "azure"
asset.Platform.Kind = "virtualmachine"
asset.Platform.Kind = inventory.AssetKindCloudVM
assets = append(assets, asset)
}
}
Expand Down
2 changes: 1 addition & 1 deletion providers/mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ func assetinfo2providerName(asset *inventory.Asset) (string, error) {
}

switch asset.Platform.Kind {
case "container-image", "baremetal":
case "container-image", inventory.AssetKindBaremetal:
return "os", nil
}

Expand Down
7 changes: 3 additions & 4 deletions providers/os/id/aws/aws.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,10 @@ func Detect(conn shared.Connection, p *inventory.Platform, smbiosMgr smbios.SmBi
idEcs, err := mdsvcEcs.Identify()
if err == nil {
return idEcs.PlatformIds[0], idEcs.Name, []string{idEcs.AccountPlatformID}
} else {
log.Debug().Err(err).
Strs("platform", p.GetFamily()).
Msg("failed to get AWS platform id")
}
log.Debug().Err(err).
Strs("platform", p.GetFamily()).
Msg("failed to get AWS platform id")
}

return "", "", nil
Expand Down
11 changes: 5 additions & 6 deletions providers/os/id/azure/azure.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,13 +48,12 @@ func Detect(conn shared.Connection, pf *inventory.Platform, smbiosMgr smbios.SmB
return "", "", nil
}
id, err := mdsvc.Identify()
if err != nil {
log.Debug().Err(err).
Strs("platform", pf.GetFamily()).
Msg("failed to get Azure platform id")
return "", "", nil
if err == nil {
return id.InstanceID, "", []string{id.AccountID}
}
return id.InstanceID, "", []string{id.AccountID}
log.Debug().Err(err).
Strs("platform", pf.GetFamily()).
Msg("failed to get Azure platform id")
}

return "", "", nil
Expand Down
20 changes: 15 additions & 5 deletions providers/os/id/clouddetect/clouddetect.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,20 @@ type detectResult struct {
relatedPlatformIds []string
}

func Detect(conn shared.Connection, p *inventory.Platform) (PlatformID, PlatformName, []RelatedPlatformID) {
// PlatformInfo contains platform information gathered from one of our cloud detectors.
type PlatformInfo struct {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: add comments

ID string
Name string
Kind string
RelatedPlatformIDs []string
}

// Detect tried to detect if we are running on a cloud asset, and if so, it returns
// the platform information, otherwise it returns a `nil` pointer.
func Detect(conn shared.Connection, p *inventory.Platform) *PlatformInfo {
mgr, err := smbios.ResolveManager(conn, p)
if err != nil {
return "", "", nil
return nil
}

wg := sync.WaitGroup{}
Expand Down Expand Up @@ -73,11 +83,11 @@ func Detect(conn shared.Connection, p *inventory.Platform) (PlatformID, Platform
}

if len(platformIds) == 0 {
return "", "", nil
return nil
} else if len(platformIds) > 1 {
log.Error().Strs("detected", platformIds).Msg("multiple cloud platform ids detected")
return "", "", nil
return nil
}

return platformIds[0], name, relatedPlatformIds
return &PlatformInfo{platformIds[0], name, inventory.AssetKindCloudVM, relatedPlatformIds}
}
55 changes: 33 additions & 22 deletions providers/os/id/platform.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,10 @@ type PlatformFingerprint struct {
ActiveIdDetectors []string
}

type PlatformInfo struct {
type platformInfo struct {
IDs []string
Name string
Kind string
RelatedPlatformIDs []string
}

Expand All @@ -53,14 +54,18 @@ func IdentifyPlatform(conn shared.Connection, req *plugin.ConnectReq, p *invento

if len(idDetectors) == 0 {
// fallback to default id detectors
//
// we want to make sure that we mark assets running in the cloud to `virtualmachine`,
// therefore we use the cloud detect detector as our first option.

switch conn.Type() {
case shared.Type_Local:
idDetectors = []string{ids.IdDetector_Hostname, ids.IdDetector_CloudDetect}
idDetectors = []string{ids.IdDetector_CloudDetect, ids.IdDetector_Hostname}
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}
idDetectors = []string{ids.IdDetector_CloudDetect, ids.IdDetector_Hostname, ids.IdDetector_SshHostkey}
case shared.Type_Tar, shared.Type_FileSystem, shared.Type_DockerSnapshot:
idDetectors = []string{ids.IdDetector_Hostname}
}
Expand All @@ -69,7 +74,7 @@ func IdentifyPlatform(conn shared.Connection, req *plugin.ConnectReq, p *invento

for i := range idDetectors {
idDetector := idDetectors[i]
platformInfo, err := GatherPlatformInfo(conn, p, idDetector)
platformInfo, err := gatherPlatformInfo(conn, p, idDetector)
if err != nil {
// we only err if we found zero platform ids, if we try multiple, a fail of an individual one is okay
log.Debug().Err(err).Str("detector", string(idDetector)).Msg("could not determine platform info")
Expand All @@ -93,6 +98,11 @@ func IdentifyPlatform(conn shared.Connection, req *plugin.ConnectReq, p *invento
}
}
}

if len(platformInfo.Kind) > 0 {
p.Kind = platformInfo.Kind
}

// check whether we can extract runtime and kind information
for _, id := range platformInfo.IDs {
runtime, kind := ExtractPlatformAndKindFromPlatformId(id)
Expand Down Expand Up @@ -132,7 +142,7 @@ func GatherNameForPlatformId(id string) string {

func ExtractPlatformAndKindFromPlatformId(id string) (string, string) {
if awsec2.ParseEc2PlatformID(id) != nil {
return "aws-ec2", "virtual-machine"
return "aws-ec2", inventory.AssetKindCloudVM
} else if awsec2.IsValidMondooAccountId(id) {
return "aws", "api"
} else if awsecs.IsValidMondooECSContainerId(id) {
Expand All @@ -141,43 +151,43 @@ func ExtractPlatformAndKindFromPlatformId(id string) (string, string) {
return "", ""
}

func GatherPlatformInfo(conn shared.Connection, pf *inventory.Platform, idDetector string) (*PlatformInfo, error) {
func gatherPlatformInfo(conn shared.Connection, pf *inventory.Platform, idDetector string) (*platformInfo, error) {
var identifier string
switch {
case idDetector == ids.IdDetector_Hostname:
// NOTE: we need to be careful with hostname's since they are not required to be unique
hostname, ok := hostname.Hostname(conn, pf)
if ok && len(hostname) > 0 {
identifier = "//platformid.api.mondoo.app/hostname/" + hostname
return &PlatformInfo{
return &platformInfo{
IDs: []string{identifier},
Name: hostname,
RelatedPlatformIDs: []string{},
}, nil
}
return &PlatformInfo{}, nil
return &platformInfo{}, nil
case idDetector == ids.IdDetector_MachineID:
guid, hostErr := machineid.MachineId(conn, pf)
if hostErr == nil && len(guid) > 0 {
identifier = "//platformid.api.mondoo.app/machineid/" + guid
return &PlatformInfo{
return &platformInfo{
IDs: []string{identifier},
Name: "",
RelatedPlatformIDs: []string{},
}, hostErr
}
return &PlatformInfo{}, nil
return &platformInfo{}, nil
case idDetector == ids.IdDetector_SerialNumber:
serial, err := serialnumber.SerialNumber(conn, pf)
if err == nil && len(serial) > 0 {
identifier = "//platformid.api.mondoo.app/serialnumber/" + serial
return &PlatformInfo{
return &platformInfo{
IDs: []string{identifier},
Name: "",
RelatedPlatformIDs: []string{},
}, nil
}
return &PlatformInfo{}, nil
return &platformInfo{}, nil
case idDetector == ids.IdDetector_AwsEcs:
metadata, err := awsecs.Resolve(conn, pf)
if err != nil {
Expand All @@ -188,29 +198,30 @@ func GatherPlatformInfo(conn shared.Connection, pf *inventory.Platform, idDetect
return nil, err
}
if len(ident.PlatformIds) != 0 {
return &PlatformInfo{
return &platformInfo{
IDs: ident.PlatformIds,
Name: ident.Name,
RelatedPlatformIDs: []string{ident.AccountPlatformID},
}, nil
}
return &PlatformInfo{}, nil
return &platformInfo{}, nil
case idDetector == ids.IdDetector_CloudDetect:
identifier, name, relatedIdentifiers := clouddetect.Detect(conn, pf)
if identifier != "" {
return &PlatformInfo{
IDs: []string{identifier},
Name: name,
RelatedPlatformIDs: relatedIdentifiers,
cloudPlatformInfo := clouddetect.Detect(conn, pf)
if cloudPlatformInfo != nil {
return &platformInfo{
IDs: []string{cloudPlatformInfo.ID},
Name: cloudPlatformInfo.Name,
RelatedPlatformIDs: cloudPlatformInfo.RelatedPlatformIDs,
Kind: cloudPlatformInfo.Kind,
}, nil
}
return &PlatformInfo{}, nil
return &platformInfo{}, nil
case idDetector == ids.IdDetector_SshHostkey:
identifier, err := sshhostkey.Detect(conn, pf)
if err != nil {
return nil, err
}
return &PlatformInfo{
return &platformInfo{
IDs: identifier,
Name: "",
RelatedPlatformIDs: []string{},
Expand Down
37 changes: 11 additions & 26 deletions providers/os/provider/detector.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,11 @@ import (
"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"
"go.mondoo.com/cnquery/v11/providers/os/id/aws"
"go.mondoo.com/cnquery/v11/providers/os/id/azure"
"go.mondoo.com/cnquery/v11/providers/os/id/gcp"
"go.mondoo.com/cnquery/v11/providers/os/id/clouddetect"
"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/sshhostkey"
"go.mondoo.com/cnquery/v11/providers/os/resources/smbios"
)

// default id detectors
Expand Down Expand Up @@ -56,11 +53,11 @@ func (s *Service) detect(asset *inventory.Asset, conn shared.Connection) error {
return errors.New("failed to detect OS")
}
if asset.Platform.Kind == "" {
asset.Platform.Kind = "baremetal"
asset.Platform.Kind = inventory.AssetKindBaremetal
}
if asset.Connections[0].Runtime == "vagrant" {
// detect overrides this
asset.Platform.Kind = "virtualmachine"
asset.Platform.Kind = inventory.AssetKindCloudVM
}

var detectors map[string]struct{}
Expand All @@ -76,29 +73,17 @@ func (s *Service) detect(asset *inventory.Asset, conn shared.Connection) error {
}

if hasDetector(detectors, ids.IdDetector_CloudDetect) {
mgr, err := smbios.ResolveManager(conn, asset.Platform)
if err != nil {
return err
}

log.Debug().Msg("run cloud platform detector")
if id, name, related := aws.Detect(conn, asset.Platform, mgr); id != "" {
asset.PlatformIds = append(asset.PlatformIds, id)
if name != "" {
cloudPlatformInfo := clouddetect.Detect(conn, asset.Platform)
if cloudPlatformInfo != nil {
log.Debug().Interface("info", cloudPlatformInfo).Msg("cloud platform detected")
asset.PlatformIds = append(asset.PlatformIds, cloudPlatformInfo.ID)
if cloudPlatformInfo.Name != "" {
// if we weren't able to detect a name for this asset, don't update to an empty value
asset.Name = name
asset.Name = cloudPlatformInfo.Name
}
asset.RelatedAssets = append(asset.RelatedAssets, relatedIds2assets(related)...)
}

if id, _, related := azure.Detect(conn, asset.Platform, mgr); id != "" {
asset.PlatformIds = append(asset.PlatformIds, id)
asset.RelatedAssets = append(asset.RelatedAssets, relatedIds2assets(related)...)
}

if id, _, related := gcp.Detect(conn, asset.Platform, mgr); id != "" {
asset.PlatformIds = append(asset.PlatformIds, id)
asset.RelatedAssets = append(asset.RelatedAssets, relatedIds2assets(related)...)
asset.Platform.Kind = cloudPlatformInfo.Kind
asset.RelatedAssets = append(asset.RelatedAssets, relatedIds2assets(cloudPlatformInfo.RelatedPlatformIDs)...)
}
}

Expand Down
2 changes: 1 addition & 1 deletion providers/os/provider/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -539,7 +539,7 @@ func (s *Service) connect(req *plugin.ConnectReq, callback plugin.ProviderCallba
}

if asset.Platform != nil && asset.Platform.Kind == "" {
asset.Platform.Kind = "baremetal"
asset.Platform.Kind = inventory.AssetKindBaremetal
}

return runtime.Connection.(shared.Connection), nil
Expand Down
2 changes: 1 addition & 1 deletion providers/vsphere/resources/discovery.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ func discoverDatacenter(conn *connection.VsphereConnection, datacenterResource *
Name: connection.EsxiPlatform,
Version: esxiVersion.Version,
Build: esxiVersion.Build,
Kind: "baremetal",
Kind: inventory.AssetKindBaremetal,
Runtime: "vsphere-host",
Family: []string{connection.Family},
TechnologyUrlSegments: []string{"vmware", "esxi", esxiVersion.Version + "-" + esxiVersion.Build},
Expand Down