go.mondoo.com/cnquery@v0.0.0-20231005093811-59568235f6ea/_motor/discovery/gcp/resolver_folder.go (about)

     1  // Copyright (c) Mondoo, Inc.
     2  // SPDX-License-Identifier: BUSL-1.1
     3  
     4  package gcp
     5  
     6  import (
     7  	"context"
     8  	"fmt"
     9  
    10  	"github.com/cockroachdb/errors"
    11  	"go.mondoo.com/cnquery/motor/asset"
    12  	"go.mondoo.com/cnquery/motor/discovery/common"
    13  	"go.mondoo.com/cnquery/motor/platform/detector"
    14  	"go.mondoo.com/cnquery/motor/providers"
    15  	gcp_provider "go.mondoo.com/cnquery/motor/providers/google"
    16  	"go.mondoo.com/cnquery/motor/providers/resolver"
    17  	"go.mondoo.com/cnquery/motor/vault"
    18  )
    19  
    20  var FolderDiscoveryTargets = append(ProjectDiscoveryTargets)
    21  
    22  type GcpFolderResolver struct{}
    23  
    24  func (k *GcpFolderResolver) Name() string {
    25  	return "GCP Folder Resolver"
    26  }
    27  
    28  func (r *GcpFolderResolver) AvailableDiscoveryTargets() []string {
    29  	return append(FolderDiscoveryTargets, common.DiscoveryAuto, common.DiscoveryAll, DiscoveryFolders)
    30  }
    31  
    32  func (r *GcpFolderResolver) Resolve(ctx context.Context, tc *providers.Config, credsResolver vault.Resolver, sfn common.QuerySecretFn, userIdDetectors ...providers.PlatformIdDetector) ([]*asset.Asset, error) {
    33  	resolved := []*asset.Asset{}
    34  	if tc == nil || tc.Options["folder-id"] == "" {
    35  		return resolved, nil
    36  	}
    37  
    38  	// Note: we use the resolver instead of the direct gcp_provider.New to resolve credentials properly
    39  	m, err := resolver.NewMotorConnection(ctx, tc, credsResolver)
    40  	if err != nil {
    41  		return nil, err
    42  	}
    43  	defer m.Close()
    44  	provider, ok := m.Provider.(*gcp_provider.Provider)
    45  	if !ok {
    46  		return nil, errors.New("could not create gcp provider")
    47  	}
    48  
    49  	identifier, err := provider.Identifier()
    50  	if err != nil {
    51  		return nil, err
    52  	}
    53  
    54  	// detect platform info for the asset
    55  	detector := detector.New(provider)
    56  	pf, err := detector.Platform()
    57  	if err != nil {
    58  		return nil, err
    59  	}
    60  
    61  	folderId := tc.Options["folder-id"]
    62  	md, err := NewMQLAssetsDiscovery(provider)
    63  	if err != nil {
    64  		return nil, err
    65  	}
    66  
    67  	folder, err := GetValue[string](md, fmt.Sprintf("return gcp.folder(id: '%s').name", folderId))
    68  	if err != nil {
    69  		return nil, err
    70  	}
    71  
    72  	var resolvedRoot *asset.Asset
    73  	if tc.IncludesOneOfDiscoveryTarget(DiscoveryFolders) {
    74  		pf.Name = "gcp-folder"
    75  		resolvedRoot = &asset.Asset{
    76  			PlatformIds: []string{identifier},
    77  			Name:        "GCP folder " + folder,
    78  			Platform:    pf,
    79  			Connections: []*providers.Config{tc}, // pass-in the current config
    80  		}
    81  		resolved = append(resolved, resolvedRoot)
    82  	}
    83  
    84  	if tc.IncludesOneOfDiscoveryTarget(common.DiscoveryAuto, common.DiscoveryAll,
    85  		DiscoveryInstances, DiscoveryComputeImages, DiscoveryComputeNetworks, DiscoveryComputeSubnetworks, DiscoveryComputeFirewalls,
    86  		DiscoveryGkeClusters,
    87  		DiscoveryStorageBuckets,
    88  		DiscoveryBigQueryDatasets) {
    89  		type project struct {
    90  			Id string
    91  		}
    92  		projects, err := GetList[project](md, fmt.Sprintf("return gcp.folder(id: '%s').projects { id }", folderId))
    93  		if err != nil {
    94  			return nil, err
    95  		}
    96  
    97  		for _, p := range projects {
    98  			projectConfig := tc.Clone()
    99  			projectConfig.Options = map[string]string{
   100  				"project-id": p.Id,
   101  			}
   102  
   103  			assets, err := (&GcpProjectResolver{}).Resolve(ctx, projectConfig, credsResolver, sfn, userIdDetectors...)
   104  			if err != nil {
   105  				return nil, err
   106  			}
   107  			for i := range assets {
   108  				a := assets[i]
   109  				if resolvedRoot != nil && a.Platform.Name == "gcp-project" {
   110  					a.RelatedAssets = append(a.RelatedAssets, resolvedRoot)
   111  				}
   112  				resolved = append(resolved, a)
   113  			}
   114  		}
   115  	}
   116  	return resolved, nil
   117  }