go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/providers/assets.go (about)

     1  // Copyright (c) Mondoo, Inc.
     2  // SPDX-License-Identifier: BUSL-1.1
     3  
     4  package providers
     5  
     6  import (
     7  	"github.com/cockroachdb/errors"
     8  	"github.com/rs/zerolog/log"
     9  	"go.mondoo.com/cnquery/cli/config"
    10  	"go.mondoo.com/cnquery/logger"
    11  	"go.mondoo.com/cnquery/providers-sdk/v1/inventory"
    12  	pp "go.mondoo.com/cnquery/providers-sdk/v1/plugin"
    13  	"go.mondoo.com/cnquery/providers-sdk/v1/upstream"
    14  )
    15  
    16  func ProcessAssetCandidates(runtime *Runtime, connectRes *pp.ConnectRes, upstreamConfig *upstream.UpstreamConfig, platformID string) ([]*inventory.Asset, error) {
    17  	var assetCandidates []*inventory.Asset
    18  	if connectRes.Inventory == nil || connectRes.Inventory.Spec == nil {
    19  		return []*inventory.Asset{connectRes.Asset}, nil
    20  	} else {
    21  		logger.DebugDumpJSON("inventory-resolved", connectRes.Inventory)
    22  		assetCandidates = connectRes.Inventory.Spec.Assets
    23  	}
    24  	log.Debug().Msgf("resolved %d assets", len(assetCandidates))
    25  
    26  	if err := detectAssets(runtime, assetCandidates, upstreamConfig); err != nil {
    27  		return nil, err
    28  	}
    29  
    30  	if platformID != "" {
    31  		res, err := filterAssetByPlatformID(assetCandidates, platformID)
    32  		if err != nil {
    33  			return nil, err
    34  		}
    35  		return []*inventory.Asset{res}, nil
    36  	}
    37  
    38  	return filterUniqueAssets(assetCandidates), nil
    39  }
    40  
    41  // detectAssets connects to all assets that do not have a platform ID yet
    42  func detectAssets(runtime *Runtime, assetCandidates []*inventory.Asset, upstreamConfig *upstream.UpstreamConfig) error {
    43  	for i := range assetCandidates {
    44  		asset := assetCandidates[i]
    45  		// If the assets have platform IDs, then we have already connected to them via the
    46  		// current provider.
    47  		if len(asset.PlatformIds) > 0 {
    48  			continue
    49  		}
    50  
    51  		// Make sure the provider for the asset is present
    52  		if err := runtime.DetectProvider(asset); err != nil {
    53  			return err
    54  		}
    55  
    56  		err := runtime.Connect(&pp.ConnectReq{
    57  			Features: config.Features,
    58  			Asset:    asset,
    59  			Upstream: upstreamConfig,
    60  		})
    61  		if err != nil {
    62  			continue
    63  		}
    64  		// Use the updated asset
    65  		assetCandidates[i] = runtime.Provider.Connection.Asset
    66  	}
    67  	return nil
    68  }
    69  
    70  func filterAssetByPlatformID(assetList []*inventory.Asset, selectionID string) (*inventory.Asset, error) {
    71  	var foundAsset *inventory.Asset
    72  	for i := range assetList {
    73  		assetObj := assetList[i]
    74  		for j := range assetObj.PlatformIds {
    75  			if assetObj.PlatformIds[j] == selectionID {
    76  				return assetObj, nil
    77  			}
    78  		}
    79  	}
    80  
    81  	if foundAsset == nil {
    82  		return nil, errors.New("could not find an asset with the provided identifier: " + selectionID)
    83  	}
    84  	return foundAsset, nil
    85  }
    86  
    87  // filterUniqueAssets filters assets with duplicate platform IDs
    88  func filterUniqueAssets(assetCandidates []*inventory.Asset) []*inventory.Asset {
    89  	uniqueAssets := []*inventory.Asset{}
    90  	platformIds := map[string]struct{}{}
    91  	for _, asset := range assetCandidates {
    92  		found := false
    93  		for _, platformId := range asset.PlatformIds {
    94  			if _, ok := platformIds[platformId]; ok {
    95  				found = true
    96  				log.Debug().Msgf("skipping asset %s with duplicate platform ID %s", asset.Name, platformId)
    97  				break
    98  			}
    99  		}
   100  		if found {
   101  			continue
   102  		}
   103  
   104  		uniqueAssets = append(uniqueAssets, asset)
   105  		for _, platformId := range asset.PlatformIds {
   106  			platformIds[platformId] = struct{}{}
   107  		}
   108  	}
   109  	return uniqueAssets
   110  }