GCP Cloud Discovery
Discover all GCP resources across your projects, identify unmanaged infrastructure, and bring it under Terraform management.
Prerequisites
- GCP credentials configured in Settings > Cloud
- Self-hosted runner (required) — must be online and connected to your organization
- Viewer role (
roles/viewer) on each project you want to scan
Self-Hosted Runner Required
GCP cloud discovery requires a self-hosted runner with access to your GCP environment. The runner queries GCP APIs, scans Terraform state files from GCS, and reports results back to Controlinfra.
Set up a runner in Settings > Runners before running a GCP discovery scan.
Required Permissions
The service account used for discovery needs:
| Role | Scope | Purpose |
|---|---|---|
| roles/viewer | Project(s) | Read-only access to all GCP resources |
| roles/storage.objectViewer | State bucket | Read Terraform state files from GCS |
# Grant Viewer on a project
gcloud projects add-iam-policy-binding YOUR_PROJECT_ID \
--member="serviceAccount:YOUR_SA@YOUR_PROJECT.iam.gserviceaccount.com" \
--role="roles/viewer"
# Grant Storage Object Viewer on state bucket
gcloud storage buckets add-iam-policy-binding gs://YOUR_STATE_BUCKET \
--member="serviceAccount:YOUR_SA@YOUR_PROJECT.iam.gserviceaccount.com" \
--role="roles/storage.objectViewer"Multi-Project Access
Grant the Viewer role on each project you want to discover. When using a service account from a central project, grant it cross-project access using IAM bindings on each target project.
Required GCP APIs
Ensure these APIs are enabled on each project you want to scan:
gcloud services enable \
compute.googleapis.com \
container.googleapis.com \
sqladmin.googleapis.com \
storage.googleapis.com \
cloudfunctions.googleapis.com \
run.googleapis.com \
pubsub.googleapis.com \
dns.googleapis.com \
cloudkms.googleapis.com \
redis.googleapis.com \
iam.googleapis.com \
cloudresourcemanager.googleapis.com \
--project=YOUR_PROJECT_IDRunning a Discovery Scan
- Go to Cloud Discovery in the sidebar
- Click Run Discovery
- Select GCP as the provider
- Configure scan options:
- Projects — select which GCP projects to scan (all accessible projects are listed)
- Services — choose which GCP services to scan (Compute, Networking, Storage, Database, etc.)
- Regions — select GCP regions to include (e.g.,
us-central1,europe-west1) - State Files (optional) — enter your GCS bucket and prefix where
.tfstatefiles are stored
- Click Start Scan
INFO
The Projects tab lists every project your GCP credential can access. If a project is missing, ensure the service account has the Viewer role assigned on it and that the Cloud Resource Manager API is enabled.
How It Works
Phase 1: Resource Discovery
Controlinfra queries GCP APIs for each selected service and region. Resources are enumerated using the standard list methods for each resource type.
Phase 2: Enrichment
For key resource types, additional API calls capture detailed configuration:
| Service | Details Captured |
|---|---|
| Compute Instances | Machine type, zone, disks, network interfaces, labels, status |
| GKE Clusters | Kubernetes version, node pools (machine types, autoscaling), network config |
| Cloud SQL | Database version, tier, HA config, backup settings, storage |
| Cloud Storage | Location, storage class, versioning, lifecycle rules, IAM |
| VPC Networks | Subnets, firewall rules, routes, peering connections |
| Cloud Functions | Runtime, memory, trigger type, environment variables |
| Cloud Run | Image, CPU/memory limits, scaling config, traffic splits |
Phase 3: State Matching
If you provided a GCS state file location, Controlinfra downloads and parses .tfstate files from the bucket. Each discovered resource is matched against the state index using GCP resource self-links and IDs.
Phase 4: Cost Estimation
Orphaned (unmanaged) resources are priced using the GCP Cloud Billing Catalog API with static fallbacks for common machine types:
| Resource Type | Pricing Basis |
|---|---|
| Compute Instances | Machine type + region + sustained use discount |
| Cloud SQL | Tier + storage + HA multiplier |
| GKE Clusters | Management fee + node pool instance costs |
| Cloud Storage | Storage class + size + operations |
| Persistent Disks | Disk type + size + region |
Phase 5: AI Analysis
Claude AI analyzes orphaned resources to identify:
- Cost savings from unused or idle resources
- Security risks (public buckets, permissive firewall rules)
- Patterns (abandoned projects, orphaned disks, unused static IPs)
Supported Resource Types
Controlinfra discovers 17+ GCP resource types and maps them to Terraform equivalents:
| Category | Resource Types | Terraform Resources |
|---|---|---|
| Compute | Instances, Instance Groups, Disks, Images, Snapshots | google_compute_instance, google_compute_disk, etc. |
| Containers | GKE Clusters, Artifact Registry | google_container_cluster, google_artifact_registry_repository |
| Networking | VPC Networks, Subnets, Firewall Rules, Cloud NAT, Load Balancers, Cloud DNS Zones | google_compute_network, google_compute_firewall, etc. |
| Storage | Cloud Storage Buckets | google_storage_bucket |
| Database | Cloud SQL Instances, Cloud Spanner, Memorystore (Redis) | google_sql_database_instance, google_redis_instance |
| Serverless | Cloud Functions, Cloud Run Services | google_cloudfunctions_function, google_cloud_run_service |
| Security | Cloud KMS Key Rings and Keys | google_kms_key_ring, google_kms_crypto_key |
| Messaging | Pub/Sub Topics and Subscriptions | google_pubsub_topic, google_pubsub_subscription |
| IAM | Service Accounts | google_service_account |
GCS State Backend Configuration
When your Terraform state is stored in GCS, configure the state file location during scan setup:
- Bucket — The GCS bucket name (e.g.,
my-terraform-state) - Prefix (optional) — Path prefix within the bucket (e.g.,
prod/)
The backend configuration in your Terraform code typically looks like:
terraform {
backend "gcs" {
bucket = "my-terraform-state"
prefix = "prod"
}
}Controlinfra reads all .tfstate files under the specified bucket and prefix, then matches discovered resources against the state index.
GCP Project Selection
The scan configuration modal shows a Projects tab listing all projects your credential has access to. For each project:
- Project ID and Project Name are displayed
- Toggle projects on/off to include or exclude them from the scan
- A Select All / Deselect All button is available for convenience
TIP
If you manage many GCP projects, use the search bar in the Projects tab to filter by project ID or name.
Terraform Code Generation
For orphaned (unmanaged) resources, Controlinfra generates:
- HCL resource blocks with actual configuration from the discovered resource
terraform importcommands using the GCP resource self-link- Provider configuration with
googleprovider and GCS backend
Example generated import command:
terraform import google_compute_instance.my_vm \
projects/my-project/zones/us-central1-a/instances/my-vmTroubleshooting
"GCP credentials not configured"
Add GCP credentials in Settings > Cloud > Add Account using a Service Account JSON key or Workload Identity. See the GCP Credentials Guide.
"Permission Denied" or "Viewer role required"
The service account needs roles/viewer on each project. Assign via gcloud:
gcloud projects add-iam-policy-binding YOUR_PROJECT \
--member="serviceAccount:YOUR_SA@YOUR_PROJECT.iam.gserviceaccount.com" \
--role="roles/viewer"Project not showing in the dropdown
The Projects dropdown only shows projects where your credential has at least Viewer access. To add a project:
- Go to the GCP Console > IAM & Admin > select the target project
- Click Grant Access
- Add your service account email and assign the Viewer role
- Wait ~1 minute for propagation, then re-open the scan modal
API not enabled errors
If you see 403 ... has not been used in project errors, enable the required API:
gcloud services enable compute.googleapis.com --project=YOUR_PROJECTEmpty state file results
Ensure the GCS bucket name and prefix are correct, and the service account has roles/storage.objectViewer on the bucket.
Missing resource types
Not all GCP resource types have Terraform equivalents. Resources without a mapping are still discovered but shown as "unknown" type.
Next Steps
- GCP Credentials - Authentication setup
- Azure Cloud Discovery - Azure discovery guide
- Self-Hosted Runners - Runner deployment
- Cost Management - Analyze cloud spend