Cloudlist supports two distinct approaches for GCP asset discovery:
- Organization-Level Asset API - Uses Cloud Asset Inventory API for comprehensive organization-wide discovery
- Individual Service APIs - Uses individual GCP service APIs for project-specific discovery
| Feature | Organization-Level Asset API | Individual Service APIs |
|---|---|---|
| Scope | All projects in organization | Accessible projects only |
| Speed | Slower (~45s) | Faster (~23s) |
| Coverage | 220+ resources across org | 67 resources per project |
| Required Permissions | Cloud Asset Inventory roles | Individual service permissions |
| Best For | Comprehensive org audits | Fast project-specific scans |
| Extended Metadata | Optional with additional permissions | Always available |
The service account needs organization-level permissions:
# Required IAM roles for Asset API approach
roles:
- roles/cloudasset.viewer # Core Asset API access
- roles/resourcemanager.viewer # List projects in organization
# Optional roles for extended metadata (new feature):
- roles/compute.viewer # Extended metadata for compute instances
- roles/dns.reader # Extended metadata for DNS records (coming soon)
- roles/storage.objectViewer # Extended metadata for storage buckets (coming soon)
- roles/cloudfunctions.viewer # Extended metadata for functions (coming soon)
- roles/run.viewer # Extended metadata for Cloud Run (coming soon)
- roles/container.viewer # Extended metadata for GKE (coming soon)The Asset API integration now supports fetching extended metadata for resources. This feature:
- Is optional: Works without additional permissions, but provides basic data only
- Graceful degradation: If permissions are missing, it falls back to basic Asset API data
- Per-service permissions: Each service requires its specific viewer role
- Performance impact: Extended metadata requires additional API calls per resource
# Create service account in a project
gcloud iam service-accounts create asset-viewer-sa \
--display-name="CloudList Asset Viewer" \
--description="Service account for organization-level asset discovery"
# Get the service account email
SA_EMAIL="asset-viewer-sa@YOUR-PROJECT-ID.iam.gserviceaccount.com"
ORG_ID="YOUR-ORGANIZATION-ID"# Core Asset API permission (REQUIRED)
gcloud organizations add-iam-policy-binding $ORG_ID \
--member="serviceAccount:$SA_EMAIL" \
--role="roles/cloudasset.viewer"
# Resource manager permission (REQUIRED)
gcloud organizations add-iam-policy-binding $ORG_ID \
--member="serviceAccount:$SA_EMAIL" \
--role="roles/resourcemanager.viewer"
# Optional: Extended metadata permissions (add as needed)
# For compute instances
gcloud organizations add-iam-policy-binding $ORG_ID \
--member="serviceAccount:$SA_EMAIL" \
--role="roles/compute.viewer"
# For Cloud Functions
gcloud organizations add-iam-policy-binding $ORG_ID \
--member="serviceAccount:$SA_EMAIL" \
--role="roles/cloudfunctions.viewer"
# For Cloud Storage
gcloud organizations add-iam-policy-binding $ORG_ID \
--member="serviceAccount:$SA_EMAIL" \
--role="roles/storage.objectViewer"
# For Cloud Run
gcloud organizations add-iam-policy-binding $ORG_ID \
--member="serviceAccount:$SA_EMAIL" \
--role="roles/run.viewer"
# For DNS
gcloud organizations add-iam-policy-binding $ORG_ID \
--member="serviceAccount:$SA_EMAIL" \
--role="roles/dns.reader"
# For GKE
gcloud organizations add-iam-policy-binding $ORG_ID \
--member="serviceAccount:$SA_EMAIL" \
--role="roles/container.viewer"gcloud iam service-accounts keys create asset-viewer-key.json \
--iam-account=$SA_EMAIL- provider: gcp
id: org-discovery
organization_id: "123456789012" # Your organization ID (REQUIRED)
extended_metadata: true # Enable extended metadata collection
gcp_service_account_key: |
{
"type": "service_account",
"project_id": "your-project-id",
"private_key_id": "...",
"private_key": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n",
"client_email": "asset-viewer-sa@your-project-id.iam.gserviceaccount.com",
"client_id": "...",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/asset-viewer-sa%40your-project-id.iam.gserviceaccount.com",
"universe_domain": "googleapis.com"
}# Discover all assets across organization
./cloudlist -pc config.yaml -id org-discovery
# Discover specific services only
./cloudlist -pc config.yaml -id org-discovery -s compute,dns,s3
# Verbose output with discovery details
./cloudlist -pc config.yaml -id org-discovery -v
# Output only IP addresses
./cloudlist -pc config.yaml -id org-discovery | grep -E "^[0-9]+\."The Asset API approach queries the following asset types that provide IP addresses or DNS names:
| Asset Type | Service | Description |
|---|---|---|
compute.googleapis.com/Instance |
compute | Compute Engine instances |
compute.googleapis.com/GlobalAddress |
compute | Global static IP addresses |
compute.googleapis.com/Address |
compute | Regional static IP addresses |
compute.googleapis.com/ForwardingRule |
compute | Load balancer forwarding rules |
dns.googleapis.com/ManagedZone |
dns | DNS managed zones |
dns.googleapis.com/ResourceRecordSet |
dns | DNS resource record sets |
storage.googleapis.com/Bucket |
s3 | Cloud Storage buckets |
run.googleapis.com/Service |
cloud-run | Cloud Run services |
cloudfunctions.googleapis.com/CloudFunction |
cloud-function | Cloud Functions |
container.googleapis.com/Cluster |
gke | GKE clusters |
tpu.googleapis.com/Node |
tpu | Cloud TPU nodes |
file.googleapis.com/Instance |
filestore | Filestore instances |
You can specify individual services or use 'all' for comprehensive discovery:
# Individual services
./cloudlist -pc config.yaml -id org-discovery -s compute,dns,gke
# New services added
./cloudlist -pc config.yaml -id org-discovery -s tpu,filestore
# All services (comprehensive discovery)
./cloudlist -pc config.yaml -id org-discovery -s all| Service | Asset Types |
|---|---|
compute |
Instance, GlobalAddress, Address, ForwardingRule |
dns |
ManagedZone, ResourceRecordSet |
s3 |
Bucket |
cloud-run |
Service |
cloud-function |
CloudFunction |
gke |
Cluster |
tpu |
Node |
filestore |
Instance |
all |
All asset types above |
The service account needs project-level permissions for each service:
# Required IAM roles for Individual API approach
roles:
- roles/compute.viewer # Compute instances
- roles/dns.reader # DNS records
- roles/storage.objectViewer # Storage buckets
- roles/run.viewer # Cloud Run services
- roles/cloudfunctions.viewer # Cloud Functions
- roles/container.viewer # GKE clusters
- roles/resourcemanager.viewer # List projects# Create service account
gcloud iam service-accounts create cloudlist-sa \
--display-name="CloudList Individual Services" \
--description="Service account for individual service API discovery"
SA_EMAIL="cloudlist-sa@YOUR-PROJECT-ID.iam.gserviceaccount.com"
PROJECT_ID="YOUR-PROJECT-ID"
# Grant project-level permissions
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SA_EMAIL" \
--role="roles/compute.viewer"
gcloud projects add-iam-policy-binding $PROJECT_ID \
--member="serviceAccount:$SA_EMAIL" \
--role="roles/dns.reader"
# ... repeat for other services- provider: gcp
id: project-discovery
# No organization_id = uses individual service APIs
gcp_service_account_key: |
{
"type": "service_account",
"project_id": "your-project-id",
"private_key_id": "...",
"private_key": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n",
"client_email": "cloudlist-sa@your-project-id.iam.gserviceaccount.com",
"client_id": "...",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/cloudlist-sa%40your-project-id.iam.gserviceaccount.com",
"universe_domain": "googleapis.com"
}# Method 1: Using gcloud
gcloud organizations list
# Method 2: Using Cloud Console
# Navigate to: IAM & Admin > Settings
# Organization ID is displayed at the top
# Method 3: Using Asset API (if you have access)
gcloud asset search-all-resources \
--scope=organizations/YOUR-ORG-ID \
--asset-types=cloudresourcemanager.googleapis.com/OrganizationError: "The caller does not have permission"
# Verify organization-level permissions
gcloud organizations get-iam-policy YOUR-ORG-ID \
--filter="bindings.members:serviceAccount:your-sa@project.iam.gserviceaccount.com"
# Check if Cloud Asset API is enabled
gcloud services list --enabled --filter="name:cloudasset.googleapis.com"Error: "No RESOURCE found that matches asset type"
# Some asset types may not exist in your organization
# This is normal and can be ignored - the tool continues with other types- Asset API: 100 requests per 100 seconds per user
- Rate Limiting: Tool automatically batches requests to avoid quota issues
- Timeout: Organization discovery may take 30-60 seconds for large organizations
# Enable verbose logging
./cloudlist -pc config.yaml -id org-discovery -v
# Test Asset API access directly
gcloud asset list --organization=YOUR-ORG-ID --limit=5
# Verify service account permissions
gcloud auth activate-service-account --key-file=service-account-key.json
gcloud asset list --organization=YOUR-ORG-ID --limit=1- Asset API: Grant only
cloudasset.viewerandresourcemanager.viewer - Individual APIs: Grant only the specific service viewer roles needed
- Scope: Prefer project-level permissions when organization-wide access isn't required
# Rotate service account keys regularly
gcloud iam service-accounts keys list --iam-account=$SA_EMAIL
# Delete old keys
gcloud iam service-accounts keys delete KEY-ID --iam-account=$SA_EMAIL
# Generate new key
gcloud iam service-accounts keys create new-key.json --iam-account=$SA_EMAILCloudlist supports discovering assets from multiple GCP organizations simultaneously by configuring multiple provider blocks in the same configuration file.
# Multiple Organizations Configuration
- provider: gcp
id: org-production
organization_id: "111111111111" # Production organization
gcp_service_account_key: |
{
"type": "service_account",
"project_id": "prod-project",
"private_key_id": "...",
"private_key": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n",
"client_email": "asset-viewer-sa@prod-project.iam.gserviceaccount.com",
"client_id": "...",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/asset-viewer-sa%40prod-project.iam.gserviceaccount.com",
"universe_domain": "googleapis.com"
}
- provider: gcp
id: org-staging
organization_id: "222222222222" # Staging organization
gcp_service_account_key: |
{
"type": "service_account",
"project_id": "staging-project",
"private_key_id": "...",
"private_key": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n",
"client_email": "asset-viewer-sa@staging-project.iam.gserviceaccount.com",
"client_id": "...",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/asset-viewer-sa%40staging-project.iam.gserviceaccount.com",
"universe_domain": "googleapis.com"
}
- provider: gcp
id: org-development
organization_id: "333333333333" # Development organization
gcp_service_account_key: |
{
"type": "service_account",
"project_id": "dev-project",
"private_key_id": "...",
"private_key": "-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n",
"client_email": "asset-viewer-sa@dev-project.iam.gserviceaccount.com",
"client_id": "...",
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/asset-viewer-sa%40dev-project.iam.gserviceaccount.com",
"universe_domain": "googleapis.com"
}# Discover assets from ALL organizations
./cloudlist -pc config.yaml -s all
# Discover assets from specific organization
./cloudlist -pc config.yaml -id org-production -s compute
# Discover assets from multiple specific organizations
./cloudlist -pc config.yaml -id org-production,org-staging -s compute
# Compare production vs staging environments
./cloudlist -pc config.yaml -id org-production -s all > prod-assets.txt
./cloudlist -pc config.yaml -id org-staging -s all > staging-assets.txt
diff prod-assets.txt staging-assets.txtEach organization requires its own service account with appropriate permissions:
- Organization-Level Permissions:
roles/cloudasset.viewer+roles/resourcemanager.viewer - Cross-Organization Setup: Service accounts can be in different projects/organizations
- Permission Inheritance: Each service account only accesses its configured organization