AWS Cloud Account
Connect an AWS account so DriftWise can scan live infrastructure and detect drift against your Terraform state.
Prerequisites
- AWS CLI installed and authenticated
- An AWS account with permission to create IAM resources
- A DriftWise API key or OIDC login
1. Enable Resource Explorer
DriftWise discovers AWS resources via Resource Explorer 2. It must be enabled in the account before your first scan — this is a one-time, free setup.
- Open the Resource Explorer console in the region you want as the aggregator index.
- Click Turn on Resource Explorer → Quick setup (recommended).
- Wait 5–15 minutes for the aggregator index to populate.
- Confirm the aggregator shows all of your regions in the Indexes tab.
The region where you enable the aggregator must match the region field on the DriftWise credential below. If Resource Explorer is not enabled, scans fail with an error containing IndexNotFound.
See Cloud Discovery for the full model, including how enrichment and resource categorization work.
2. Create an IAM Policy
DriftWise needs read-only access to Resource Explorer and CloudControl. Create a policy with the minimum permissions:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"resource-explorer-2:Search",
"cloudcontrol:GetResource",
"sts:GetCallerIdentity"
],
"Resource": "*"
}
]
}
The managed ReadOnlyAccess policy is a simpler alternative — it covers Resource Explorer, CloudControl, and STS, at the cost of broader visibility than the scanner strictly needs.
aws iam create-policy \
--policy-name DriftWiseScanner \
--policy-document file://driftwise-scanner-policy.json
CloudControl can return properties for most but not all AWS resource types. Resources whose ARN shape CloudControl does not support are still stored (identity and metadata) but their properties column stays empty. This is a permanent CloudControl limitation, not a DriftWise bug — it's tracked per-row via enrichment_status = failed / unsupported_identifier. See Cloud Discovery for the full failure-reason taxonomy.
3. Choose a Credential Type
Option A: Access Key (simple, for dev/test)
Create an IAM user with the policy attached:
aws iam create-user --user-name driftwise-scanner
aws iam attach-user-policy \
--user-name driftwise-scanner \
--policy-arn arn:aws:iam::<ACCOUNT_ID>:policy/DriftWiseScanner
aws iam create-access-key --user-name driftwise-scanner
Save the AccessKeyId and SecretAccessKey from the output.
Option B: OIDC Federation (recommended for production)
Create an IAM role that DriftWise can assume via OIDC. This avoids long-lived static credentials.
The trust policy below references arn:aws:iam::<ACCOUNT_ID>:oidc-provider/driftwise.ai, which must exist in your account before aws iam create-role succeeds. One-time setup:
aws iam create-open-id-connect-provider \
--url https://driftwise.ai \
--client-id-list https://driftwise.io/federation \
--thumbprint-list <see https://docs.driftwise.ai/security#oidc-thumbprint>
If the provider already exists (you've connected DriftWise from this account before), skip this step.
# Create trust policy for DriftWise's OIDC provider
cat > trust-policy.json << 'EOF'
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::<ACCOUNT_ID>:oidc-provider/driftwise.ai"
},
"Action": "sts:AssumeRoleWithWebIdentity",
"Condition": {
"StringEquals": {
"driftwise.ai:aud": "https://driftwise.io/federation"
}
}
}
]
}
EOF
aws iam create-role \
--role-name DriftWiseScanner \
--assume-role-policy-document file://trust-policy.json
aws iam attach-role-policy \
--role-name DriftWiseScanner \
--policy-arn arn:aws:iam::<ACCOUNT_ID>:policy/DriftWiseScanner
4. Add the Account in DriftWise
Via the UI
- Go to Accounts in the sidebar
- Click Add Account and select Amazon Web Services
- Enter your 12-digit AWS Account ID
- Select your credential type and fill in the fields
- Click Save
Via the API
Access Key:
curl -X POST "https://app.driftwise.ai/api/v2/orgs/$ORG_ID/accounts" \
-H "x-api-key: $DRIFTWISE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"display_name": "Production AWS",
"provider": "aws",
"external_account_id": "123456789012",
"credential_type": "aws_static",
"credential_ref": "{\"access_key_id\": \"AKIA...\", \"secret_access_key\": \"...\", \"region\": \"us-east-1\"}"
}'
OIDC Federation:
curl -X POST "https://app.driftwise.ai/api/v2/orgs/$ORG_ID/accounts" \
-H "x-api-key: $DRIFTWISE_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"display_name": "Production AWS",
"provider": "aws",
"external_account_id": "123456789012",
"credential_type": "aws_oidc",
"credential_ref": "{\"role_arn\": \"arn:aws:iam::123456789012:role/DriftWiseScanner\", \"region\": \"us-east-1\"}"
}'
Supported Resources
DriftWise discovers every resource Resource Explorer returns for the account — there is no per-type allowlist. Resources are normalized into eight broad categories (compute, storage, database, network, iam, serverless, messaging, other) regardless of provider. See Cloud Discovery for the full list with examples.
The underlying AWS resource type (for example AWS::EC2::Instance) is preserved alongside the category for exact-match drift detection.
Troubleshooting
Scan completes with 0 resources and errors
Every error maps to a resource type. Check the scan details in the UI or query the scan directly:
SELECT jsonb_pretty(scan_errors) FROM scan_runs WHERE id = '<scan_id>';
Common errors:
| Error | Cause | Fix |
|---|---|---|
IndexNotFound | Resource Explorer aggregator index not enabled in the credential's region | Follow step 1 above to enable Resource Explorer |
AccessDenied on resource-explorer-2:Search | IAM policy missing Resource Explorer permissions | Attach the DriftWiseScanner policy to the user/role |
AccessDenied on cloudcontrol:GetResource | IAM policy missing CloudControl permissions | Ensure cloudcontrol:GetResource is included |
ExpiredToken | Static access key was deactivated or deleted | Rotate the key and update the credential in DriftWise |
InvalidClientTokenId | Access key ID doesn't exist | Check for typos in the access key ID |
AssumeRoleWithWebIdentity failure | OIDC trust policy misconfigured | Verify the trust policy principal and condition match DriftWise's OIDC provider |
enrichment_status=failed / unsupported_identifier | CloudControl does not support this resource type's ARN shape | Permanent; resource identity is still tracked. See Cloud Discovery |
Scan completes with 0 resources and 0 errors
The credentials are valid but Resource Explorer returned nothing. Common causes:
- Aggregator index still populating — Resource Explorer takes 5–15 minutes to populate after initial setup. Wait and re-run.
- Wrong region — The
regionon your DriftWise credential must match the region where the Resource Explorer aggregator lives. Check the Indexes tab in the Resource Explorer console. - Empty account — The account genuinely has no resources.
- SCP restrictions — An Organization SCP may be blocking
resource-explorer-2:Searcheven though IAM allows it. Check with your AWS administrator.
Scan stuck in "pending"
The scan worker hasn't picked it up yet. Check that the scan worker is running:
kubectl logs -f deploy/scan-worker
If the worker is running but scans stay pending, check the database for stuck scans:
SELECT id, status, retry_count, started_at FROM scan_runs
WHERE status = 'running' AND started_at < NOW() - INTERVAL '10 minutes';
The sweeper automatically resets stuck scans after 10 minutes (up to 3 retries).