discover() scans your live AWS environment using AWS Resource Explorer. Unlike static analysis, it finds cost issues in resources that are already running — even if they were never deployed through IaC.
Prerequisites
- Valid AWS credentials configured (see AWS Credentials)
- AWS Resource Explorer enabled in your account
How discovery works
Full example
import { CloudBurnClient } from '@cloudburn/sdk';
const client = new CloudBurnClient();
// Initialize Resource Explorer (first time only)
const init = await client.initializeDiscovery({ region: 'us-east-1' });
console.log(`Setup: ${init.status}, coverage: ${init.coverage}`);
// Check status
const status = await client.getDiscoveryStatus();
console.log(`Coverage: ${status.coverage}, regions: ${status.indexedRegionCount}`);
// Run discovery scan
const result = await client.discover();
for (const provider of result.providers) {
for (const finding of provider.rules) {
console.log(`[${finding.ruleId}] ${finding.message} (${finding.findings.length} resources)`);
}
}
Initialize once
initializeDiscovery() sets up AWS Resource Explorer with an aggregator index. You only need to call this once per AWS account. On subsequent runs, it detects the existing setup and returns status: 'EXISTING'.
After initialization, Resource Explorer takes a few minutes to index your resources before discovery scans return complete results.
Check coverage before scanning
getDiscoveryStatus() returns the current coverage level:
| Coverage | Meaning |
|---|---|
full | Aggregator index covers all regions |
partial | Some regions are indexed, some are not |
local_only | Only the local region is indexed |
none | No regions are indexed yet |
Scan specific regions
Target a single region:
const result = await client.discover({
target: { mode: 'region', region: 'eu-west-1' },
});
Scan all indexed regions:
const result = await client.discover({
target: { mode: 'all' },
});
Use the current region only:
const result = await client.discover({
target: { mode: 'current' },
});
Scan multiple specific regions:
const result = await client.discover({
target: { mode: 'regions', regions: ['us-east-1', 'eu-west-1'] },
});
Tracking progress
Discovery runs independent collection work in parallel and evaluates each rule as soon as its evidence is ready, so rules finish at different times. Pass onProgress to receive catalog, dataset, and provisional rule events while the run is still going:
const result = await client.discover({
onProgress: (event) => {
if (event.kind === 'catalog') console.log(`Catalog: ${event.resourceCount} resources`);
if (event.kind === 'dataset') console.log(`Dataset ${event.completedDatasets}/${event.totalDatasets}`);
if (event.kind === 'rule') console.log(`${event.ruleId}: ${event.status} (${event.findingCount} findings)`);
},
});
Rule events are provisional; the resolved ScanResult replaces them. See AwsDiscoveryProgressEvent.
Bounding the run
Raise the default deadline with timeoutMs, and cancel a run in flight with your own signal:
const controller = new AbortController();
const result = await client.discover({
target: { mode: 'all' },
timeoutMs: 600_000,
signal: controller.signal,
});
An expired deadline or a cancelled signal rejects without returning a partial ScanResult. See AwsDiscoveryExecutionOptions.
Scoping credentials
discover() accepts per-call AWS credentials for multi-account scans:
const result = await client.discover({
aws: { credentials: assumedRoleCredentials },
});
See AWS Credentials for the multi-account credential pattern.
Reusing evidence between scans
Evidence reuse is off unless you pass cache:
const result = await client.discover({
target: { mode: 'regions', regions: ['eu-west-1'] },
cache: {
directory: '/home/example/.cache/cloudburn/evidence',
mode: 'normal',
authorizationContext: 'production-readonly-policy-v3',
},
});
for (const artifact of result.evidence ?? []) {
console.log(`${artifact.datasetKey}: ${artifact.source}, collected ${artifact.collectedAt}`);
}
Rules and configuration are evaluated again on every run; only collected AWS evidence is reused. See Credentials and evidence reuse for which credentials can reuse evidence, and AwsEvidenceCacheOptions for every field and its default.
Auditing rules that did not produce findings
Set includeEvaluationResources: true to get result.evaluations, which records every selected rule as triggered, passed, unknown, or not_applicable alongside the resource identities it inspected:
const result = await client.discover({ includeEvaluationResources: true });
for (const evaluation of result.evaluations?.rules ?? []) {
console.log(`${evaluation.ruleId}: ${evaluation.status}`);
if (evaluation.coverage) {
console.log(` assessed ${evaluation.coverage.assessed.length}, unknown ${evaluation.coverage.unknown.length}`);
}
}
Code that validates status strings must accept unknown. A rule reports unknown when it ran but could not assess some resources, usually because a metric window was incomplete or a dependency was denied. Shared resource sets are emitted once in result.evaluations.resourceSets and referenced by RuleEvaluation.resourceSetId. See ScanEvaluations.
Handling diagnostics
If the SDK cannot access certain services or regions, it reports them in result.diagnostics rather than failing the entire scan. See Handling access errors for how to read a denial.
const result = await client.discover();
if (result.diagnostics?.length) {
for (const diag of result.diagnostics) {
console.warn(`[${diag.status}] ${diag.service} in ${diag.region}: ${diag.message}`);
}
}
What's next
| AWS Credentials | Configure credentials and IAM permissions |
| CloudBurnClient Reference | Full discover() API reference |
| Types Reference | AwsDiscoveryStatus and related types |