diff --git a/pkg/cmd/scan.go b/pkg/cmd/scan.go index 1b006992e..f518e1b71 100644 --- a/pkg/cmd/scan.go +++ b/pkg/cmd/scan.go @@ -62,6 +62,22 @@ func NewScanCmd(opts *pkg.ScanOptions) *cobra.Command { ) } + GCPScope, _ := cmd.Flags().GetStringSlice("gcp-scope") + limitScope := make([]string, 0) + + if to == common.RemoteGoogleTerraform && len(GCPScope) > 0 { + limitScope, err = parseScopeFlag(GCPScope) + if err != nil { + return err + } + } else if to != common.RemoteGoogleTerraform && len(GCPScope) > 0 { + return errors.New("gcp-scope can only be utilized when using " + common.RemoteGoogleTerraform + " flag") + } else if to == common.RemoteGoogleTerraform && len(GCPScope) == 0 { + return errors.New("gcp-scope must be specified when using " + common.RemoteGoogleTerraform + " flag") + } + + opts.GCPScope = limitScope + outputFlag, _ := cmd.Flags().GetStringSlice("output") out, err := parseOutputFlags(outputFlag) @@ -124,6 +140,11 @@ func NewScanCmd(opts *pkg.ScanOptions) *cobra.Command { false, "Do not display anything but scan results", ) + fl.StringSlice( + "gcp-scope", + []string{}, + "Set the GCP scope for search", + ) fl.StringArray( "filter", []string{}, @@ -239,7 +260,7 @@ func scanRun(opts *pkg.ScanOptions) error { resFactory := terraform.NewTerraformResourceFactory(resourceSchemaRepository) - err := remote.Activate(opts.To, opts.ProviderVersion, alerter, providerLibrary, remoteLibrary, scanProgress, resourceSchemaRepository, resFactory, opts.ConfigDir) + err := remote.Activate(opts.To, opts.ProviderVersion, opts.GCPScope, alerter, providerLibrary, remoteLibrary, scanProgress, resourceSchemaRepository, resFactory, opts.ConfigDir) if err != nil { return err } @@ -323,6 +344,26 @@ func scanRun(opts *pkg.ScanOptions) error { return nil } +func parseScopeFlag(scope []string) ([]string, error) { + + scopeRegex := `projects/\S*$|folders/\d*$|organizations/\d*$` + r := regexp.MustCompile(scopeRegex) + + for _, v := range scope { + if !r.MatchString(v) { + return nil, errors.Wrapf( + cmderrors.NewUsageError( + "\nAccepted formats are: projects/, folders/, organizations/", + ), + "Unable to parse GCP scope '%s'", + v, + ) + } + } + + return scope, nil +} + func parseFromFlag(from []string) ([]config.SupplierConfig, error) { configs := make([]config.SupplierConfig, 0, len(from)) diff --git a/pkg/cmd/scan_test.go b/pkg/cmd/scan_test.go index f562d73ca..c13062fc8 100644 --- a/pkg/cmd/scan_test.go +++ b/pkg/cmd/scan_test.go @@ -356,14 +356,14 @@ func Test_Options(t *testing.T) { }, { name: "should not find provider version in lockfile", - args: []string{"scan", "--to", "gcp+tf", "--tf-lockfile", "testdata/terraform_valid.lock.hcl"}, + args: []string{"scan", "--to", "gcp+tf", "--gcp-scope", "organizations/123", "--tf-lockfile", "testdata/terraform_valid.lock.hcl"}, assertOptions: func(t *testing.T, opts *pkg.ScanOptions) { assert.Equal(t, "", opts.ProviderVersion) }, }, { name: "should fail to read lockfile with silent error", - args: []string{"scan", "--to", "gcp+tf", "--tf-lockfile", "testdata/terraform_invalid.lock.hcl"}, + args: []string{"scan", "--to", "gcp+tf", "--gcp-scope", "organizations/123", "--tf-lockfile", "testdata/terraform_invalid.lock.hcl"}, assertOptions: func(t *testing.T, opts *pkg.ScanOptions) { assert.Equal(t, "", opts.ProviderVersion) }, diff --git a/pkg/driftctl.go b/pkg/driftctl.go index a7bf7b584..4bbe04f7c 100644 --- a/pkg/driftctl.go +++ b/pkg/driftctl.go @@ -24,6 +24,7 @@ type ScanOptions struct { Detect bool From []config.SupplierConfig To string + GCPScope []string Output []output.OutputConfig Filter *jmespath.JMESPath Quiet bool diff --git a/pkg/remote/google/config/config.go b/pkg/remote/google/config/config.go index e209a03ab..0ecbd4170 100644 --- a/pkg/remote/google/config/config.go +++ b/pkg/remote/google/config/config.go @@ -1,7 +1,5 @@ package config type GCPTerraformConfig struct { - Project string `cty:"project"` - Region string `cty:"region"` - Zone string `cty:"zone"` + Scopes []string `cty:"scopes"` } diff --git a/pkg/remote/google/init.go b/pkg/remote/google/init.go index 6e7646a40..64f727a26 100644 --- a/pkg/remote/google/init.go +++ b/pkg/remote/google/init.go @@ -16,7 +16,7 @@ import ( "google.golang.org/api/cloudresourcemanager/v1" ) -func Init(version string, alerter *alerter.Alerter, +func Init(version string, gcpScope []string, alerter *alerter.Alerter, providerLibrary *terraform.ProviderLibrary, remoteLibrary *common.RemoteLibrary, progress output.Progress, @@ -51,9 +51,9 @@ func Init(version string, alerter *alerter.Alerter, return err } - assetRepository := repository.NewAssetRepository(assetClient, provider.GetConfig(), repositoryCache) + assetRepository := repository.NewAssetRepository(assetClient, provider.SetConfig(gcpScope), repositoryCache) storageRepository := repository.NewStorageRepository(storageClient, repositoryCache) - iamRepository := repository.NewCloudResourceManagerRepository(crmService, provider.GetConfig(), repositoryCache) + iamRepository := repository.NewCloudResourceManagerRepository(crmService, provider.SetConfig(gcpScope), repositoryCache) providerLibrary.AddProvider(terraform.GOOGLE, provider) deserializer := resource.NewDeserializer(factory) diff --git a/pkg/remote/google/provider.go b/pkg/remote/google/provider.go index db7174bf2..06bd591c4 100644 --- a/pkg/remote/google/provider.go +++ b/pkg/remote/google/provider.go @@ -1,8 +1,6 @@ package google import ( - "os" - "github.com/snyk/driftctl/pkg/output" "github.com/snyk/driftctl/pkg/remote/google/config" "github.com/snyk/driftctl/pkg/remote/terraform" @@ -34,7 +32,7 @@ func NewGCPTerraformProvider(version string, progress output.Progress, configDir tfProvider, err := terraform.NewTerraformProvider(installer, terraform.TerraformProviderConfig{ Name: p.name, GetProviderConfig: func(alias string) interface{} { - return p.GetConfig() + return p.SetConfig(nil) }, }, progress) @@ -55,10 +53,8 @@ func (p *GCPTerraformProvider) Version() string { return p.version } -func (p *GCPTerraformProvider) GetConfig() config.GCPTerraformConfig { +func (p *GCPTerraformProvider) SetConfig(scopes []string) config.GCPTerraformConfig { return config.GCPTerraformConfig{ - Project: os.Getenv("CLOUDSDK_CORE_PROJECT"), - Region: os.Getenv("CLOUDSDK_COMPUTE_REGION"), - Zone: os.Getenv("CLOUDSDK_COMPUTE_ZONE"), + Scopes: scopes, } } diff --git a/pkg/remote/google/repository/asset.go b/pkg/remote/google/repository/asset.go index ff3b96a20..dddb39b3a 100644 --- a/pkg/remote/google/repository/asset.go +++ b/pkg/remote/google/repository/asset.go @@ -2,6 +2,7 @@ package repository import ( "context" + "errors" "fmt" asset "cloud.google.com/go/asset/apiv1" @@ -9,6 +10,8 @@ import ( "github.com/snyk/driftctl/pkg/remote/google/config" "google.golang.org/api/iterator" assetpb "google.golang.org/genproto/googleapis/cloud/asset/v1" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" ) // https://cloud.google.com/asset-inventory/docs/supported-asset-types#supported_resource_types @@ -75,102 +78,145 @@ func NewAssetRepository(client *asset.Client, config config.GCPTerraformConfig, } func (s assetRepository) listAllResources(ty string) ([]*assetpb.Asset, error) { - req := &assetpb.ListAssetsRequest{ - Parent: fmt.Sprintf("projects/%s", s.config.Project), - ContentType: assetpb.ContentType_RESOURCE, - AssetTypes: []string{ - cloudFunctionsFunction, - bigtableInstanceAssetType, - bigtableTableAssetType, - sqlDatabaseInstanceAssetType, - computeGlobalAddressAssetType, - nodeGroupAssetType, - }, - } - var results []*assetpb.Asset - cacheKey := "listAllResources" - cachedResults := s.cache.GetAndLock(cacheKey) - defer s.cache.Unlock(cacheKey) - if cachedResults != nil { - results = cachedResults.([]*assetpb.Asset) - } + filteredResults := []*assetpb.Asset{} + var errorString string + var errCode codes.Code + + for _, scope := range s.config.Scopes { + cacheKey := fmt.Sprintf("listAllResources_%s", scope) + cachedResults := s.cache.GetAndLock(cacheKey) + defer s.cache.Unlock(cacheKey) + + req := &assetpb.ListAssetsRequest{ + Parent: scope, + ContentType: assetpb.ContentType_RESOURCE, + AssetTypes: []string{ + cloudFunctionsFunction, + bigtableInstanceAssetType, + bigtableTableAssetType, + sqlDatabaseInstanceAssetType, + computeGlobalAddressAssetType, + nodeGroupAssetType, + }, + } + + var results []*assetpb.Asset + + if cachedResults != nil { + results = cachedResults.([]*assetpb.Asset) + } - if results == nil { - it := s.client.ListAssets(context.Background(), req) - for { - resource, err := it.Next() - if err == iterator.Done { - break + if results == nil { + it := s.client.ListAssets(context.Background(), req) + for { + resource, err := it.Next() + if err == iterator.Done { + break + } + if err != nil && resource != nil { + errorString = errorString + fmt.Sprintf("For scope %s on resource %s got error: %s; ", scope, resource.AssetType, err.Error()) + continue + } + if err != nil && resource == nil { + errorString = errorString + fmt.Sprintf("For scope %s got error: %s; ", scope, err.Error()) + errCode = status.Code(err) + break + } + results = append(results, resource) } - if err != nil { - return nil, err + s.cache.Put(cacheKey, results) + } + + for _, result := range results { + if result.AssetType == ty { + filteredResults = append(filteredResults, result) } - results = append(results, resource) } - s.cache.Put(cacheKey, results) } - filteredResults := []*assetpb.Asset{} - for _, result := range results { - if result.AssetType == ty { - filteredResults = append(filteredResults, result) - } + if len(errorString) > 0 && len(filteredResults) > 0 { + return filteredResults, errors.New(errorString) + } + + if len(errorString) > 0 && len(filteredResults) == 0 { + return nil, status.Error(errCode, errorString) } return filteredResults, nil } func (s assetRepository) searchAllResources(ty string) ([]*assetpb.ResourceSearchResult, error) { - req := &assetpb.SearchAllResourcesRequest{ - Scope: fmt.Sprintf("projects/%s", s.config.Project), - AssetTypes: []string{ - storageBucketAssetType, - computeFirewallAssetType, - computeRouterAssetType, - computeInstanceAssetType, - computeNetworkAssetType, - computeSubnetworkAssetType, - dnsManagedZoneAssetType, - computeInstanceGroupAssetType, - bigqueryDatasetAssetType, - bigqueryTableAssetType, - computeAddressAssetType, - computeDiskAssetType, - computeImageAssetType, - healthCheckAssetType, - cloudRunServiceAssetType, - }, - } - var results []*assetpb.ResourceSearchResult - cacheKey := "SearchAllResources" - cachedResults := s.cache.GetAndLock(cacheKey) - defer s.cache.Unlock(cacheKey) - if cachedResults != nil { - results = cachedResults.([]*assetpb.ResourceSearchResult) - } + filteredResults := []*assetpb.ResourceSearchResult{} + var errorString string + var errCode codes.Code + + for _, scope := range s.config.Scopes { + cacheKey := fmt.Sprintf("SearchAllResources_%s", scope) + cachedResults := s.cache.GetAndLock(cacheKey) + defer s.cache.Unlock(cacheKey) + + req := &assetpb.SearchAllResourcesRequest{ + Scope: scope, + AssetTypes: []string{ + storageBucketAssetType, + computeFirewallAssetType, + computeRouterAssetType, + computeInstanceAssetType, + computeNetworkAssetType, + computeSubnetworkAssetType, + dnsManagedZoneAssetType, + computeInstanceGroupAssetType, + bigqueryDatasetAssetType, + bigqueryTableAssetType, + computeAddressAssetType, + computeDiskAssetType, + computeImageAssetType, + healthCheckAssetType, + cloudRunServiceAssetType, + }, + } + var results []*assetpb.ResourceSearchResult + + if cachedResults != nil { + results = cachedResults.([]*assetpb.ResourceSearchResult) + } - if results == nil { - it := s.client.SearchAllResources(context.Background(), req) - for { - resource, err := it.Next() - if err == iterator.Done { - break + if results == nil { + it := s.client.SearchAllResources(context.Background(), req) + for { + resource, err := it.Next() + if err == iterator.Done { + break + } + if err != nil && resource != nil { + errorString = errorString + fmt.Sprintf("For scope %s on resource %s got error: %s; ", scope, resource.AssetType, err.Error()) + continue + } + if err != nil && resource == nil { + errorString = errorString + fmt.Sprintf("For scope %s got error: %s; ", scope, err.Error()) + errCode = status.Code(err) + break + } + results = append(results, resource) } - if err != nil { - return nil, err + s.cache.Put(cacheKey, results) + } + + for _, result := range results { + if result.AssetType == ty { + filteredResults = append(filteredResults, result) } - results = append(results, resource) } - s.cache.Put(cacheKey, results) } - filteredResults := []*assetpb.ResourceSearchResult{} - for _, result := range results { - if result.AssetType == ty { - filteredResults = append(filteredResults, result) - } + if len(errorString) > 0 && len(filteredResults) > 0 { + return filteredResults, errors.New(errorString) + } + + if len(errorString) > 0 && len(filteredResults) == 0 { + return nil, status.Error(errCode, errorString) } return filteredResults, nil diff --git a/pkg/remote/google/repository/asset_test.go b/pkg/remote/google/repository/asset_test.go index 4db980a60..cbaf793f7 100644 --- a/pkg/remote/google/repository/asset_test.go +++ b/pkg/remote/google/repository/asset_test.go @@ -25,9 +25,9 @@ func Test_assetRepository_searchAllResources_CacheHit(t *testing.T) { } c := &cache.MockCache{} - c.On("GetAndLock", "SearchAllResources").Return(expectedResults).Times(1) - c.On("Unlock", "SearchAllResources").Times(1) - repo := NewAssetRepository(nil, config.GCPTerraformConfig{Project: ""}, c) + c.On("GetAndLock", "SearchAllResources_folders/345612").Return(expectedResults).Times(1) + c.On("Unlock", "SearchAllResources_folders/345612").Times(1) + repo := NewAssetRepository(nil, config.GCPTerraformConfig{Scopes: []string{"folders/345612"}}, c) got, err := repo.searchAllResources("google_fake_type") c.AssertExpectations(t) @@ -52,10 +52,10 @@ func Test_assetRepository_searchAllResources_CacheMiss(t *testing.T) { t.Fatal(err) } c := &cache.MockCache{} - c.On("GetAndLock", "SearchAllResources").Return(nil).Times(1) - c.On("Unlock", "SearchAllResources").Times(1) - c.On("Put", "SearchAllResources", mock.IsType([]*assetpb.ResourceSearchResult{})).Return(false).Times(1) - repo := NewAssetRepository(assetClient, config.GCPTerraformConfig{Project: ""}, c) + c.On("GetAndLock", "SearchAllResources_folders/345612").Return(nil).Times(1) + c.On("Unlock", "SearchAllResources_folders/345612").Times(1) + c.On("Put", "SearchAllResources_folders/345612", mock.IsType([]*assetpb.ResourceSearchResult{})).Return(false).Times(1) + repo := NewAssetRepository(assetClient, config.GCPTerraformConfig{Scopes: []string{"folders/345612"}}, c) got, err := repo.searchAllResources("google_fake_type") c.AssertExpectations(t) diff --git a/pkg/remote/google/repository/cloudresourcemanager.go b/pkg/remote/google/repository/cloudresourcemanager.go index 1c7f4e3bb..4220e8cfb 100644 --- a/pkg/remote/google/repository/cloudresourcemanager.go +++ b/pkg/remote/google/repository/cloudresourcemanager.go @@ -1,6 +1,10 @@ package repository import ( + "errors" + "fmt" + "strings" + "github.com/snyk/driftctl/pkg/remote/cache" "github.com/snyk/driftctl/pkg/remote/google/config" "google.golang.org/api/cloudresourcemanager/v1" @@ -25,26 +29,40 @@ func NewCloudResourceManagerRepository(service *cloudresourcemanager.Service, co } func (s *cloudResourceManagerRepository) ListProjectsBindings() (map[string]map[string][]string, error) { - if cachedResults := s.cache.Get("ListProjectsBindings"); cachedResults != nil { - return cachedResults.(map[string]map[string][]string), nil - } - request := new(cloudresourcemanager.GetIamPolicyRequest) - policy, err := s.service.Projects.GetIamPolicy(s.config.Project, request).Do() - if err != nil { - return nil, err - } + bindingsByProject := make(map[string]map[string][]string) + errorsByProject := make(map[string]error) + var erorString string - bindings := make(map[string][]string) + for _, scope := range s.config.Scopes { + if strings.Contains(scope, "projects/") { + project := strings.Split(scope, "projects/")[1] + request := new(cloudresourcemanager.GetIamPolicyRequest) + policy, err := s.service.Projects.GetIamPolicy(project, request).Do() + if err != nil { + errorsByProject[project] = err + bindingsByProject[project] = nil + continue + } - for _, binding := range policy.Bindings { - bindings[binding.Role] = binding.Members - } + bindings := make(map[string][]string) + for _, binding := range policy.Bindings { + bindings[binding.Role] = binding.Members + } - bindingsByProject := make(map[string]map[string][]string) - bindingsByProject[s.config.Project] = bindings + bindingsByProject[project] = bindings + + s.cache.Put("ListProjectsBindings", bindingsByProject) - s.cache.Put("ListProjectsBindings", bindingsByProject) + } + } + + if len(errorsByProject) > 0 { + for project, errval := range errorsByProject { + erorString = erorString + fmt.Sprintf("Project: %s had the following error: %s; ", project, errval.Error()) + } + return bindingsByProject, errors.New(erorString) + } return bindingsByProject, nil } diff --git a/pkg/remote/google/repository/mock_AssetRepository.go b/pkg/remote/google/repository/mock_AssetRepository.go index db6f347df..3561a8e10 100644 --- a/pkg/remote/google/repository/mock_AssetRepository.go +++ b/pkg/remote/google/repository/mock_AssetRepository.go @@ -1,4 +1,4 @@ -// Code generated by mockery v0.0.0-dev. DO NOT EDIT. +// Code generated by mockery v2.9.4. DO NOT EDIT. package repository diff --git a/pkg/remote/google/repository/mock_CloudResourceManagerRepository.go b/pkg/remote/google/repository/mock_CloudResourceManagerRepository.go index 4b2a7658f..63f40c09e 100644 --- a/pkg/remote/google/repository/mock_CloudResourceManagerRepository.go +++ b/pkg/remote/google/repository/mock_CloudResourceManagerRepository.go @@ -1,4 +1,4 @@ -// Code generated by mockery v0.0.0-dev. DO NOT EDIT. +// Code generated by mockery v2.9.4. DO NOT EDIT. package repository diff --git a/pkg/remote/google_bigquery_scanner_test.go b/pkg/remote/google_bigquery_scanner_test.go index c37e42874..1b3daeb23 100644 --- a/pkg/remote/google_bigquery_scanner_test.go +++ b/pkg/remote/google_bigquery_scanner_test.go @@ -68,7 +68,7 @@ func TestGoogleBigqueryDataset(t *testing.T) { alerts.NewRemoteAccessDeniedAlert( common.RemoteGoogleTerraform, remoteerr.NewResourceListingError( - status.Error(codes.PermissionDenied, "The caller does not have permission"), + status.Error(codes.PermissionDenied, "For scope projects/123456 got error: "+status.Error(codes.PermissionDenied, "The caller does not have permission").Error()+"; "), "google_bigquery_dataset", ), alerts.EnumerationPhase, @@ -105,7 +105,7 @@ func TestGoogleBigqueryDataset(t *testing.T) { tt.Fatal(err) } - repo := repository.NewAssetRepository(assetClient, realProvider.GetConfig(), cache.New(0)) + repo := repository.NewAssetRepository(assetClient, realProvider.SetConfig([]string{"projects/123456"}), cache.New(0)) remoteLibrary.AddEnumerator(google.NewGoogleBigqueryDatasetEnumerator(repo, factory)) @@ -171,7 +171,7 @@ func TestGoogleBigqueryTable(t *testing.T) { alerts.NewRemoteAccessDeniedAlert( common.RemoteGoogleTerraform, remoteerr.NewResourceListingError( - status.Error(codes.PermissionDenied, "The caller does not have permission"), + status.Error(codes.PermissionDenied, "For scope projects/123456 got error: "+status.Error(codes.PermissionDenied, "The caller does not have permission").Error()+"; "), "google_bigquery_table", ), alerts.EnumerationPhase, @@ -208,7 +208,7 @@ func TestGoogleBigqueryTable(t *testing.T) { tt.Fatal(err) } - repo := repository.NewAssetRepository(assetClient, realProvider.GetConfig(), cache.New(0)) + repo := repository.NewAssetRepository(assetClient, realProvider.SetConfig([]string{"projects/123456"}), cache.New(0)) remoteLibrary.AddEnumerator(google.NewGoogleBigqueryTableEnumerator(repo, factory)) diff --git a/pkg/remote/google_bigtable_scanner_test.go b/pkg/remote/google_bigtable_scanner_test.go index f75798cda..765ebf130 100644 --- a/pkg/remote/google_bigtable_scanner_test.go +++ b/pkg/remote/google_bigtable_scanner_test.go @@ -105,7 +105,7 @@ func TestGoogleBigtableInstance(t *testing.T) { alerts.NewRemoteAccessDeniedAlert( common.RemoteGoogleTerraform, remoteerr.NewResourceListingError( - status.Error(codes.PermissionDenied, "The caller does not have permission"), + status.Error(codes.PermissionDenied, "For scope projects/123456 got error: "+status.Error(codes.PermissionDenied, "The caller does not have permission").Error()+"; "), "google_bigtable_instance", ), alerts.EnumerationPhase, @@ -142,7 +142,7 @@ func TestGoogleBigtableInstance(t *testing.T) { tt.Fatal(err) } - repo := repository.NewAssetRepository(assetClient, realProvider.GetConfig(), cache.New(0)) + repo := repository.NewAssetRepository(assetClient, realProvider.SetConfig([]string{"projects/123456"}), cache.New(0)) remoteLibrary.AddEnumerator(google.NewGoogleBigTableInstanceEnumerator(repo, factory)) @@ -231,7 +231,7 @@ func TestGoogleBigtableTable(t *testing.T) { alerts.NewRemoteAccessDeniedAlert( common.RemoteGoogleTerraform, remoteerr.NewResourceListingError( - status.Error(codes.PermissionDenied, "The caller does not have permission"), + status.Error(codes.PermissionDenied, "For scope projects/123456 got error: "+status.Error(codes.PermissionDenied, "The caller does not have permission").Error()+"; "), "google_bigtable_table", ), alerts.EnumerationPhase, @@ -268,7 +268,7 @@ func TestGoogleBigtableTable(t *testing.T) { tt.Fatal(err) } - repo := repository.NewAssetRepository(assetClient, realProvider.GetConfig(), cache.New(0)) + repo := repository.NewAssetRepository(assetClient, realProvider.SetConfig([]string{"projects/123456"}), cache.New(0)) remoteLibrary.AddEnumerator(google.NewGoogleBigtableTableEnumerator(repo, factory)) diff --git a/pkg/remote/google_cloudfunctions_scanner_test.go b/pkg/remote/google_cloudfunctions_scanner_test.go index bec5fb240..5c928b122 100644 --- a/pkg/remote/google_cloudfunctions_scanner_test.go +++ b/pkg/remote/google_cloudfunctions_scanner_test.go @@ -92,7 +92,7 @@ func TestGoogleCloudFunctionsFunction(t *testing.T) { alerts.NewRemoteAccessDeniedAlert( common.RemoteGoogleTerraform, remoteerr.NewResourceListingError( - status.Error(codes.PermissionDenied, "The caller does not have permission"), + status.Error(codes.PermissionDenied, "For scope projects/123456 got error: "+status.Error(codes.PermissionDenied, "The caller does not have permission").Error()+"; "), "google_cloudfunctions_function", ), alerts.EnumerationPhase, @@ -129,7 +129,7 @@ func TestGoogleCloudFunctionsFunction(t *testing.T) { tt.Fatal(err) } - repo := repository.NewAssetRepository(assetClient, realProvider.GetConfig(), cache.New(0)) + repo := repository.NewAssetRepository(assetClient, realProvider.SetConfig([]string{"projects/123456"}), cache.New(0)) remoteLibrary.AddEnumerator(google.NewGoogleCloudFunctionsFunctionEnumerator(repo, factory)) diff --git a/pkg/remote/google_cloudrun_scanner_test.go b/pkg/remote/google_cloudrun_scanner_test.go index 032752ec2..980d9aee1 100644 --- a/pkg/remote/google_cloudrun_scanner_test.go +++ b/pkg/remote/google_cloudrun_scanner_test.go @@ -84,7 +84,7 @@ func TestGoogleCloudRunService(t *testing.T) { alerts.NewRemoteAccessDeniedAlert( common.RemoteGoogleTerraform, remoteerr.NewResourceListingError( - status.Error(codes.PermissionDenied, "The caller does not have permission"), + status.Error(codes.PermissionDenied, "For scope projects/123456 got error: "+status.Error(codes.PermissionDenied, "The caller does not have permission").Error()+"; "), googleresource.GoogleCloudRunServiceResourceType, ), alerts.EnumerationPhase, @@ -124,7 +124,7 @@ func TestGoogleCloudRunService(t *testing.T) { tt.Fatal(err) } - repo := repository.NewAssetRepository(assetClient, realProvider.GetConfig(), cache.New(0)) + repo := repository.NewAssetRepository(assetClient, realProvider.SetConfig([]string{"projects/123456"}), cache.New(0)) remoteLibrary.AddEnumerator(google.NewGoogleCloudRunServiceEnumerator(repo, factory)) diff --git a/pkg/remote/google_compute_scanner_test.go b/pkg/remote/google_compute_scanner_test.go index c0b35bbe1..d4d90f8a1 100644 --- a/pkg/remote/google_compute_scanner_test.go +++ b/pkg/remote/google_compute_scanner_test.go @@ -76,7 +76,7 @@ func TestGoogleComputeFirewall(t *testing.T) { alerts.NewRemoteAccessDeniedAlert( common.RemoteGoogleTerraform, remoteerr.NewResourceListingError( - status.Error(codes.PermissionDenied, "The caller does not have permission"), + status.Error(codes.PermissionDenied, "For scope projects/123456 got error: "+status.Error(codes.PermissionDenied, "The caller does not have permission").Error()+"; "), "google_compute_firewall", ), alerts.EnumerationPhase, @@ -129,7 +129,7 @@ func TestGoogleComputeFirewall(t *testing.T) { provider.ShouldUpdate() } - repo := repository.NewAssetRepository(assetClient, realProvider.GetConfig(), cache.New(0)) + repo := repository.NewAssetRepository(assetClient, realProvider.SetConfig([]string{"projects/123456"}), cache.New(0)) remoteLibrary.AddEnumerator(google.NewGoogleComputeFirewallEnumerator(repo, factory)) remoteLibrary.AddDetailsFetcher(resType, common.NewGenericDetailsFetcher(resType, provider, deserializer)) @@ -212,7 +212,7 @@ func TestGoogleComputeRouter(t *testing.T) { alerts.NewRemoteAccessDeniedAlert( common.RemoteGoogleTerraform, remoteerr.NewResourceListingError( - status.Error(codes.PermissionDenied, "The caller does not have permission"), + status.Error(codes.PermissionDenied, "For scope projects/123456 got error: "+status.Error(codes.PermissionDenied, "The caller does not have permission").Error()+"; "), googleresource.GoogleComputeRouterResourceType, ), alerts.EnumerationPhase, @@ -252,7 +252,7 @@ func TestGoogleComputeRouter(t *testing.T) { tt.Fatal(err) } - repo := repository.NewAssetRepository(assetClient, realProvider.GetConfig(), cache.New(0)) + repo := repository.NewAssetRepository(assetClient, realProvider.SetConfig([]string{"projects/123456"}), cache.New(0)) remoteLibrary.AddEnumerator(google.NewGoogleComputeRouterEnumerator(repo, factory)) @@ -319,7 +319,7 @@ func TestGoogleComputeInstance(t *testing.T) { alerts.NewRemoteAccessDeniedAlert( common.RemoteGoogleTerraform, remoteerr.NewResourceListingError( - status.Error(codes.PermissionDenied, "The caller does not have permission"), + status.Error(codes.PermissionDenied, "For scope projects/123456 got error: "+status.Error(codes.PermissionDenied, "The caller does not have permission").Error()+"; "), "google_compute_instance", ), alerts.EnumerationPhase, @@ -356,7 +356,7 @@ func TestGoogleComputeInstance(t *testing.T) { tt.Fatal(err) } - repo := repository.NewAssetRepository(assetClient, realProvider.GetConfig(), cache.New(0)) + repo := repository.NewAssetRepository(assetClient, realProvider.SetConfig([]string{"projects/123456"}), cache.New(0)) remoteLibrary.AddEnumerator(google.NewGoogleComputeInstanceEnumerator(repo, factory)) @@ -427,7 +427,7 @@ func TestGoogleComputeNetwork(t *testing.T) { alerts.NewRemoteAccessDeniedAlert( common.RemoteGoogleTerraform, remoteerr.NewResourceListingError( - status.Error(codes.PermissionDenied, "The caller does not have permission"), + status.Error(codes.PermissionDenied, "For scope projects/123456 got error: "+status.Error(codes.PermissionDenied, "The caller does not have permission").Error()+"; "), "google_compute_network", ), alerts.EnumerationPhase, @@ -480,7 +480,7 @@ func TestGoogleComputeNetwork(t *testing.T) { provider.ShouldUpdate() } - repo := repository.NewAssetRepository(assetClient, realProvider.GetConfig(), cache.New(0)) + repo := repository.NewAssetRepository(assetClient, realProvider.SetConfig([]string{"projects/123456"}), cache.New(0)) remoteLibrary.AddEnumerator(google.NewGoogleComputeNetworkEnumerator(repo, factory)) remoteLibrary.AddDetailsFetcher(resType, common.NewGenericDetailsFetcher(resType, provider, deserializer)) @@ -549,7 +549,7 @@ func TestGoogleComputeInstanceGroup(t *testing.T) { alerts.NewRemoteAccessDeniedAlert( common.RemoteGoogleTerraform, remoteerr.NewResourceListingError( - status.Error(codes.PermissionDenied, "The caller does not have permission"), + status.Error(codes.PermissionDenied, "For scope projects/123456 got error: "+status.Error(codes.PermissionDenied, "The caller does not have permission").Error()+"; "), "google_compute_instance_group", ), alerts.EnumerationPhase, @@ -602,7 +602,7 @@ func TestGoogleComputeInstanceGroup(t *testing.T) { provider.ShouldUpdate() } - repo := repository.NewAssetRepository(assetClient, realProvider.GetConfig(), cache.New(0)) + repo := repository.NewAssetRepository(assetClient, realProvider.SetConfig([]string{"projects/123456"}), cache.New(0)) remoteLibrary.AddEnumerator(google.NewGoogleComputeInstanceGroupEnumerator(repo, factory)) remoteLibrary.AddDetailsFetcher(googleresource.GoogleComputeInstanceGroupResourceType, common.NewGenericDetailsFetcher(googleresource.GoogleComputeInstanceGroupResourceType, provider, deserializer)) @@ -686,7 +686,7 @@ func TestGoogleComputeAddress(t *testing.T) { alerts.NewRemoteAccessDeniedAlert( common.RemoteGoogleTerraform, remoteerr.NewResourceListingError( - status.Error(codes.PermissionDenied, "The caller does not have permission"), + status.Error(codes.PermissionDenied, "For scope projects/123456 got error: "+status.Error(codes.PermissionDenied, "The caller does not have permission").Error()+"; "), "google_compute_address", ), alerts.EnumerationPhase, @@ -723,7 +723,7 @@ func TestGoogleComputeAddress(t *testing.T) { tt.Fatal(err) } - repo := repository.NewAssetRepository(assetClient, realProvider.GetConfig(), cache.New(0)) + repo := repository.NewAssetRepository(assetClient, realProvider.SetConfig([]string{"projects/123456"}), cache.New(0)) remoteLibrary.AddEnumerator(google.NewGoogleComputeAddressEnumerator(repo, factory)) @@ -812,7 +812,7 @@ func TestGoogleComputeGlobalAddress(t *testing.T) { alerts.NewRemoteAccessDeniedAlert( common.RemoteGoogleTerraform, remoteerr.NewResourceListingError( - status.Error(codes.PermissionDenied, "The caller does not have permission"), + status.Error(codes.PermissionDenied, "For scope projects/123456 got error: "+status.Error(codes.PermissionDenied, "The caller does not have permission").Error()+"; "), "google_compute_global_address", ), alerts.EnumerationPhase, @@ -849,7 +849,7 @@ func TestGoogleComputeGlobalAddress(t *testing.T) { tt.Fatal(err) } - repo := repository.NewAssetRepository(assetClient, realProvider.GetConfig(), cache.New(0)) + repo := repository.NewAssetRepository(assetClient, realProvider.SetConfig([]string{"projects/123456"}), cache.New(0)) remoteLibrary.AddEnumerator(google.NewGoogleComputeGlobalAddressEnumerator(repo, factory)) @@ -920,7 +920,7 @@ func TestGoogleComputeSubnetwork(t *testing.T) { alerts.NewRemoteAccessDeniedAlert( common.RemoteGoogleTerraform, remoteerr.NewResourceListingError( - status.Error(codes.PermissionDenied, "The caller does not have permission"), + status.Error(codes.PermissionDenied, "For scope projects/123456 got error: "+status.Error(codes.PermissionDenied, "The caller does not have permission").Error()+"; "), "google_compute_subnetwork", ), alerts.EnumerationPhase, @@ -973,7 +973,7 @@ func TestGoogleComputeSubnetwork(t *testing.T) { provider.ShouldUpdate() } - repo := repository.NewAssetRepository(assetClient, realProvider.GetConfig(), cache.New(0)) + repo := repository.NewAssetRepository(assetClient, realProvider.SetConfig([]string{"projects/123456"}), cache.New(0)) remoteLibrary.AddEnumerator(google.NewGoogleComputeSubnetworkEnumerator(repo, factory)) remoteLibrary.AddDetailsFetcher(resType, common.NewGenericDetailsFetcher(resType, provider, deserializer)) @@ -1045,7 +1045,7 @@ func TestGoogleComputeDisk(t *testing.T) { alerts.NewRemoteAccessDeniedAlert( common.RemoteGoogleTerraform, remoteerr.NewResourceListingError( - status.Error(codes.PermissionDenied, "The caller does not have permission"), + status.Error(codes.PermissionDenied, "For scope projects/123456 got error: "+status.Error(codes.PermissionDenied, "The caller does not have permission").Error()+"; "), "google_compute_disk", ), alerts.EnumerationPhase, @@ -1082,7 +1082,7 @@ func TestGoogleComputeDisk(t *testing.T) { tt.Fatal(err) } - repo := repository.NewAssetRepository(assetClient, realProvider.GetConfig(), cache.New(0)) + repo := repository.NewAssetRepository(assetClient, realProvider.SetConfig([]string{"projects/123456"}), cache.New(0)) remoteLibrary.AddEnumerator(google.NewGoogleComputeDiskEnumerator(repo, factory)) @@ -1155,7 +1155,7 @@ func TestGoogleComputeImage(t *testing.T) { alerts.NewRemoteAccessDeniedAlert( common.RemoteGoogleTerraform, remoteerr.NewResourceListingError( - status.Error(codes.PermissionDenied, "The caller does not have permission"), + status.Error(codes.PermissionDenied, "For scope projects/123456 got error: "+status.Error(codes.PermissionDenied, "The caller does not have permission").Error()+"; "), "google_compute_image", ), alerts.EnumerationPhase, @@ -1192,7 +1192,7 @@ func TestGoogleComputeImage(t *testing.T) { tt.Fatal(err) } - repo := repository.NewAssetRepository(assetClient, realProvider.GetConfig(), cache.New(0)) + repo := repository.NewAssetRepository(assetClient, realProvider.SetConfig([]string{"projects/123456"}), cache.New(0)) remoteLibrary.AddEnumerator(google.NewGoogleComputeImageEnumerator(repo, factory)) @@ -1265,7 +1265,7 @@ func TestGoogleComputeHealthCheck(t *testing.T) { alerts.NewRemoteAccessDeniedAlert( common.RemoteGoogleTerraform, remoteerr.NewResourceListingError( - status.Error(codes.PermissionDenied, "The caller does not have permission"), + status.Error(codes.PermissionDenied, "For scope projects/123456 got error: "+status.Error(codes.PermissionDenied, "The caller does not have permission").Error()+"; "), "google_compute_health_check", ), alerts.EnumerationPhase, @@ -1302,7 +1302,7 @@ func TestGoogleComputeHealthCheck(t *testing.T) { tt.Fatal(err) } - repo := repository.NewAssetRepository(assetClient, realProvider.GetConfig(), cache.New(0)) + repo := repository.NewAssetRepository(assetClient, realProvider.SetConfig([]string{"projects/123456"}), cache.New(0)) remoteLibrary.AddEnumerator(google.NewGoogleComputeHealthCheckEnumerator(repo, factory)) @@ -1375,7 +1375,7 @@ func TestGoogleComputeNodeGroup(t *testing.T) { alerts.NewRemoteAccessDeniedAlert( common.RemoteGoogleTerraform, remoteerr.NewResourceListingError( - status.Error(codes.PermissionDenied, "The caller does not have permission"), + status.Error(codes.PermissionDenied, "For scope projects/123456 got error: "+status.Error(codes.PermissionDenied, "The caller does not have permission").Error()+"; "), "google_compute_node_group", ), alerts.EnumerationPhase, @@ -1412,7 +1412,7 @@ func TestGoogleComputeNodeGroup(t *testing.T) { tt.Fatal(err) } - repo := repository.NewAssetRepository(assetClient, realProvider.GetConfig(), cache.New(0)) + repo := repository.NewAssetRepository(assetClient, realProvider.SetConfig([]string{"projects/123456"}), cache.New(0)) remoteLibrary.AddEnumerator(google.NewGoogleComputeNodeGroupEnumerator(repo, factory)) diff --git a/pkg/remote/google_network_scanner_test.go b/pkg/remote/google_network_scanner_test.go index 08cf9332d..a1373e86d 100644 --- a/pkg/remote/google_network_scanner_test.go +++ b/pkg/remote/google_network_scanner_test.go @@ -90,7 +90,7 @@ func TestGoogleDNSNanagedZone(t *testing.T) { alerts.NewRemoteAccessDeniedAlert( common.RemoteGoogleTerraform, remoteerr.NewResourceListingError( - status.Error(codes.PermissionDenied, "The caller does not have permission"), + status.Error(codes.PermissionDenied, "For scope projects/123456 got error: "+status.Error(codes.PermissionDenied, "The caller does not have permission").Error()+"; "), googleresource.GoogleDNSManagedZoneResourceType, ), alerts.EnumerationPhase, @@ -130,7 +130,7 @@ func TestGoogleDNSNanagedZone(t *testing.T) { tt.Fatal(err) } - repo := repository.NewAssetRepository(assetClient, realProvider.GetConfig(), cache.New(0)) + repo := repository.NewAssetRepository(assetClient, realProvider.SetConfig([]string{"projects/123456"}), cache.New(0)) remoteLibrary.AddEnumerator(google.NewGoogleDNSManagedZoneEnumerator(repo, factory)) diff --git a/pkg/remote/google_project_scanner_test.go b/pkg/remote/google_project_iam_scanner_test.go similarity index 100% rename from pkg/remote/google_project_scanner_test.go rename to pkg/remote/google_project_iam_scanner_test.go diff --git a/pkg/remote/google_sql_scanner_test.go b/pkg/remote/google_sql_scanner_test.go index 650374428..1872d3d02 100644 --- a/pkg/remote/google_sql_scanner_test.go +++ b/pkg/remote/google_sql_scanner_test.go @@ -90,7 +90,7 @@ func TestGoogleSQLDatabaseInstance(t *testing.T) { alerts.NewRemoteAccessDeniedAlert( common.RemoteGoogleTerraform, remoteerr.NewResourceListingError( - status.Error(codes.PermissionDenied, "The caller does not have permission"), + status.Error(codes.PermissionDenied, "For scope projects/123456 got error: "+status.Error(codes.PermissionDenied, "The caller does not have permission").Error()+"; "), "google_sql_database_instance", ), alerts.EnumerationPhase, @@ -127,7 +127,7 @@ func TestGoogleSQLDatabaseInstance(t *testing.T) { tt.Fatal(err) } - repo := repository.NewAssetRepository(assetClient, realProvider.GetConfig(), cache.New(0)) + repo := repository.NewAssetRepository(assetClient, realProvider.SetConfig([]string{"projects/123456"}), cache.New(0)) remoteLibrary.AddEnumerator(google.NewGoogleSQLDatabaseInstanceEnumerator(repo, factory)) diff --git a/pkg/remote/google_storage_scanner_test.go b/pkg/remote/google_storage_scanner_test.go index cb7180164..b155464df 100644 --- a/pkg/remote/google_storage_scanner_test.go +++ b/pkg/remote/google_storage_scanner_test.go @@ -76,7 +76,7 @@ func TestGoogleStorageBucket(t *testing.T) { alerts.NewRemoteAccessDeniedAlert( common.RemoteGoogleTerraform, remoteerr.NewResourceListingError( - status.Error(codes.PermissionDenied, "The caller does not have permission"), + status.Error(codes.PermissionDenied, "For scope projects/123456 got error: "+status.Error(codes.PermissionDenied, "The caller does not have permission").Error()+"; "), "google_storage_bucket", ), alerts.EnumerationPhase, @@ -138,7 +138,7 @@ func TestGoogleStorageBucket(t *testing.T) { provider.ShouldUpdate() } - repo := repository.NewAssetRepository(assetClient, realProvider.GetConfig(), cache.New(0)) + repo := repository.NewAssetRepository(assetClient, realProvider.SetConfig([]string{"projects/123456"}), cache.New(0)) remoteLibrary.AddEnumerator(google.NewGoogleStorageBucketEnumerator(repo, factory)) remoteLibrary.AddDetailsFetcher(resType, common.NewGenericDetailsFetcher(resType, provider, deserializer)) diff --git a/pkg/remote/remote.go b/pkg/remote/remote.go index 30f4b1122..ac967a248 100644 --- a/pkg/remote/remote.go +++ b/pkg/remote/remote.go @@ -29,7 +29,7 @@ func IsSupported(remote string) bool { return false } -func Activate(remote, version string, alerter *alerter.Alerter, +func Activate(remote, version string, gcpScope []string, alerter *alerter.Alerter, providerLibrary *terraform.ProviderLibrary, remoteLibrary *common.RemoteLibrary, progress output.Progress, @@ -42,7 +42,7 @@ func Activate(remote, version string, alerter *alerter.Alerter, case common.RemoteGithubTerraform: return github.Init(version, alerter, providerLibrary, remoteLibrary, progress, resourceSchemaRepository, factory, configDir) case common.RemoteGoogleTerraform: - return google.Init(version, alerter, providerLibrary, remoteLibrary, progress, resourceSchemaRepository, factory, configDir) + return google.Init(version, gcpScope, alerter, providerLibrary, remoteLibrary, progress, resourceSchemaRepository, factory, configDir) case common.RemoteAzureTerraform: return azurerm.Init(version, alerter, providerLibrary, remoteLibrary, progress, resourceSchemaRepository, factory, configDir)