Cloud Discovery
When DriftWise scans a cloud account, it uses each provider's native inventory API to enumerate every resource in one pass. You no longer choose which resource types to scan — DriftWise discovers the whole account, then classifies results into broad categories.
How It Works
Every scan goes through up to two phases:
| Phase | What it does | When it runs |
|---|---|---|
| Discovery | Single API call (paginated internally) that lists every resource visible to the account credentials. | Always |
| Enrichment | Fetches full per-resource properties. Required only when the discovery API returns identity without properties. | AWS only |
For GCP and Azure the discovery API returns full resource properties, so enrichment is skipped and resources are stored with enrichment_status = n/a.
Provider APIs
| Provider | Discovery API | Enrichment API |
|---|---|---|
| AWS | Resource Explorer 2 Search("*") | CloudControl GetResource |
| GCP | Cloud Asset Inventory SearchAllResources | — (properties returned from discovery) |
| Azure | Resource Graph Resources query | — (properties returned from discovery) |
All three APIs are account-wide and span every region and service the credential can see. Pagination is handled inside DriftWise — the scan worker makes as many calls as necessary and you receive the full result set.
AWS: Enabling Resource Explorer
Resource Explorer 2 must be enabled in the AWS account before DriftWise can discover resources. It's free to enable but requires a one-time setup.
- Open the Resource Explorer console in the region you want to use as the aggregator index.
- Click Turn on Resource Explorer → Quick setup (recommended).
- Wait for indexing to complete. Initial results typically appear within minutes; full indexing of a large account can take several hours.
- Confirm the aggregator shows all of your regions in the Indexes tab.
The region hosting the aggregator index must match the region field on the DriftWise credential — only the aggregator region can serve cross-region searches. If the credential points at a different region, the scan fails with a region-mismatch error that names the aggregator region. If Resource Explorer has not been enabled at all, the scan fails with Resource Explorer 2 is not enabled or has no default view.
Required IAM Permissions
DriftWise's AWS scanner needs:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"resource-explorer-2:Search",
"resource-explorer-2:ListIndexes",
"cloudformation:GetResource",
"sts:GetCallerIdentity"
],
"Resource": "*"
}
]
}
resource-explorer-2:ListIndexes is used on the error path to diagnose whether the aggregator lives in a different region than the credential — without it, a region mismatch degrades to a generic "not enabled" error.
cloudformation:GetResource, not cloudcontrol:GetResourceThe Cloud Control API shares IAM namespace with CloudFormation — its service prefix is cloudformation. There is no cloudcontrol: IAM namespace. This policy also does not cover the per-service read permissions (s3:GetBucket*, ec2:DescribeInstances, etc.) that CloudControl re-checks when dispatching to each resource type's handler; attach ReadOnlyAccess or extend the statement above with the per-service Describe*/Get*/List* actions for every resource type you expect to enrich.
The managed ReadOnlyAccess policy is the easiest alternative — it covers all of the above plus the underlying per-service read actions. See AWS Cloud Account for the full credential setup.
GCP: Required Roles
Grant the DriftWise service account the Cloud Asset Viewer role at the project (or folder / organization) level:
gcloud projects add-iam-policy-binding $GCP_PROJECT \
--member="serviceAccount:<SA_EMAIL>" \
--role="roles/cloudasset.viewer"
roles/cloudasset.viewer covers the cloudasset.assets.searchAllResources permission used by discovery. See GCP Cloud Account for the full credential setup.
Azure: Required Roles
The service principal's Reader role at the subscription scope covers Resource Graph reads — no additional permissions are needed. A resource-group-scoped Reader will only return resources inside that group. See Azure Cloud Account for the full credential setup.
Resource Categories
Resources are normalized to one of eight broad categories, regardless of provider. Examples in the table below are grouped as AWS / GCP / Azure.
| Category | Examples |
|---|---|
compute | EC2, ECS, EKS / Compute Engine, GKE / Virtual Machines, AKS, Managed Disks |
storage | S3, EFS / Cloud Storage, Persistent Disk / Storage Accounts |
database | RDS, DynamoDB, ElastiCache, Redshift / Cloud SQL, Spanner, Bigtable, Memorystore / SQL Database, Cosmos DB, Azure Cache |
network | VPC, Subnet, Security Group, ELB, Route 53, CloudFront / VPC Network, Firewall, Load Balancer / VNet, NSG, Load Balancer |
iam | IAM Role, IAM Policy, KMS Key, Secrets Manager, ACM / Service Account / RBAC, Managed Identity |
serverless | Lambda, Step Functions / Cloud Functions, Cloud Run / App Service, Azure Functions |
messaging | SQS, SNS, EventBridge, Kinesis / Pub/Sub / Service Bus, Event Hubs |
other | Anything that does not match above — still stored and compared |
Resource types outside the explicit mappings above (for example Azure Key Vault, Azure Event Grid, or Google Cloud KMS) currently fall under other. They are still tracked and drift-compared using their exact provider type — the category only affects filtering and risk classification.
Categories are used for filtering, risk classification, and plan noise matching. The underlying provider-specific type (for example AWS::EC2::Instance) is preserved alongside the category for exact-match drift detection.
Kubernetes Resources
Resources reported by the Kubernetes operator retain their fine-grained k8s/<kind> normalized type (for example k8s/deployment, k8s/service). They are not collapsed into the broad categories above — fine-grained typing is required for drift matching against K8s manifests.
Region Filtering
To scan only specific regions, pass filter_regions in the
POST /orgs/:id/scans body (see the
scans tag of the API reference
for the full shape). Empty or omitted = scan every region the
credential can see.
Behaviour by provider:
- AWS — Resource Explorer returns every region visible to the aggregator index; DriftWise filters the result list to the requested regions before storage.
- GCP — Cloud Asset Inventory returns every location; resources in a region or any zone within that region match the filter.
- Azure — Resource Graph returns every location; results are filtered to the requested regions.
Pass an empty array or omit the field to scan every region the credential can see.
Enrichment Status
Every stored resource carries an enrichment_status:
| Status | Meaning |
|---|---|
none | Discovered, not yet enriched. Transient — AWS only. |
enriched | Properties populated from enrichment (AWS) or from discovery (GCP / Azure). |
n/a | Provider does not need enrichment. Default for GCP and Azure. |
failed | Enrichment was attempted but failed. The enrichment_failure_reason column explains why. |
failed rows keep whatever identity data the discoverer returned — drift detection still works, but property-based checks may return incomplete results.
Failure Reasons
| Reason | Scope | Meaning |
|---|---|---|
unsupported_identifier | Per-resource | CloudControl does not support the resource's identifier shape. Permanent until AWS adds support. |
get_resource_failed | Per-resource | CloudControl returned an error (throttling, permission drift, resource deleted mid-scan). Usually transient. |
scrub_failed | Per-resource | The property blob could not be safely redacted. Fail-closed: properties are dropped rather than risk leaking secrets. |
credential_decrypt_failed | Batch-wide | The credential blob could not be decrypted. Operator action needed. |
credential_parse_failed | Batch-wide | Credential decrypted OK but failed provider-specific parsing. |
enricher_call_failed | Batch-wide | The enricher returned a fatal error for the whole batch. |
marshal_failed | Batch-wide | Enrichment returned valid data but marshaling for storage failed. |
Redaction (Scrubbing)
Cloud provider responses can contain embedded secrets — passwords in environment variables, API keys in tag values, bearer tokens in launch templates. Before property blobs are stored, DriftWise runs them through a pattern-based scrubber that redacts sensitive key names (password, api_key, secret, ...) and sensitive value shapes (AWS access key IDs, JWTs, bearer tokens). If the scrubber cannot parse the payload — usually because the JSON shape is unexpected — the resource is marked enrichment_status = failed with reason scrub_failed and the properties are dropped entirely. This is fail-closed on purpose: a resource with empty properties is a minor usability issue, a leaked secret is not.
Troubleshooting
AWS: Resource Explorer 2 is not enabled or has no default view
Resource Explorer has not been turned on in any region of the account, or the account has an index but no default view has been published. See AWS: Enabling Resource Explorer above — Quick setup creates both the aggregator index and a default view.
AWS: Resource Explorer is enabled in region X but the credential region is Y
The aggregator index lives in a different region than the one you configured on the DriftWise credential. Resource Explorer only serves cross-region searches from the aggregator region. Two options:
- Re-create the DriftWise credential with
regionset to the aggregator region (recommended). - Publish a default view in the credential's region — this restricts results to that single region.
AWS: Many resources show enrichment_status = failed with reason unsupported_identifier
CloudControl does not support the ARN shape for that resource type. The resource is still tracked (identity and metadata) but its properties column will be empty. Permanent until AWS adds CloudControl support.
AWS: Resources show failed with reason get_resource_failed
Usually CloudControl throttling or a permission gap. The scan worker retries failed resources on the next scan. If it persists, confirm the credential has cloudformation:GetResource (the IAM prefix for Cloud Control API — there is no cloudcontrol: namespace) and the per-service read permission that CloudControl dispatches into (e.g. s3:GetBucket* for S3 buckets, ec2:DescribeInstances for EC2 instances). ReadOnlyAccess covers both.
GCP: Some resources missing from scan results
Cloud Asset Inventory has a propagation delay of up to several minutes after a resource is created. Re-run the scan, or let the next scheduled scan pick them up.
Azure: Scan returns 0 resources
The service principal's Reader role must be granted at the subscription (or management group) level — a resource-group-scoped Reader will only return resources inside that group.