Skip to main content

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.

  1. Open the Resource Explorer console in the region you want as the aggregator index.
  2. Click Turn on Resource ExplorerQuick setup (recommended).
  3. Wait 5–15 minutes for the aggregator index to populate.
  4. 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:

driftwise-scanner-policy.json
{
"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 coverage

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.

Create an IAM role that DriftWise can assume via OIDC. This avoids long-lived static credentials.

Register the OIDC provider first

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

  1. Go to Accounts in the sidebar
  2. Click Add Account and select Amazon Web Services
  3. Enter your 12-digit AWS Account ID
  4. Select your credential type and fill in the fields
  5. 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:

Diagnostic query — internal schema, column names may change
SELECT jsonb_pretty(scan_errors) FROM scan_runs WHERE id = '<scan_id>';

Common errors:

ErrorCauseFix
IndexNotFoundResource Explorer aggregator index not enabled in the credential's regionFollow step 1 above to enable Resource Explorer
AccessDenied on resource-explorer-2:SearchIAM policy missing Resource Explorer permissionsAttach the DriftWiseScanner policy to the user/role
AccessDenied on cloudcontrol:GetResourceIAM policy missing CloudControl permissionsEnsure cloudcontrol:GetResource is included
ExpiredTokenStatic access key was deactivated or deletedRotate the key and update the credential in DriftWise
InvalidClientTokenIdAccess key ID doesn't existCheck for typos in the access key ID
AssumeRoleWithWebIdentity failureOIDC trust policy misconfiguredVerify the trust policy principal and condition match DriftWise's OIDC provider
enrichment_status=failed / unsupported_identifierCloudControl does not support this resource type's ARN shapePermanent; 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 region on 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:Search even 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:

Diagnostic query — internal schema, column names may change
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).