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 }