Discovery scans require AWS credentials to query Resource Explorer and describe live resources. The SDK uses the AWS SDK v3 default credential chain — you do not configure credentials in your code.
Credential resolution order
The SDK resolves credentials in this order, stopping at the first match:
- Environment variables —
AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY, and optionallyAWS_SESSION_TOKEN - Shared credentials file —
~/.aws/credentials, profile selected viaAWS_PROFILE - SSO credentials — configured via
aws sso login - IAM instance profile / ECS task role — when running on EC2 or in an ECS task
- EC2 instance metadata (IMDS) — when running on EC2
Region resolution
Region resolves in this order:
AWS_REGIONenvironment variableAWS_DEFAULT_REGIONenvironment variable- AWS SDK chain (shared config file, instance metadata)
Using environment variables
export AWS_ACCESS_KEY_ID=AKIA...
export AWS_SECRET_ACCESS_KEY=...
export AWS_REGION=us-east-1
Using AWS profiles
export AWS_PROFILE=my-profile
Then run your SDK code. The SDK picks up the profile automatically.
For SSO profiles:
aws sso login --profile my-sso-profile
export AWS_PROFILE=my-sso-profile
Using IAM roles
When running in AWS (EC2, ECS, Lambda, CodeBuild), attach an IAM role to the compute resource. The SDK picks up the role credentials from the instance metadata or task role endpoint with no additional configuration.
Minimum IAM permissions
For discovery scans, the IAM principal needs read-only access to Resource Explorer and the services you want to scan. At minimum:
{
"Effect": "Allow",
"Action": [
"resource-explorer-2:Search",
"resource-explorer-2:GetView",
"resource-explorer-2:ListViews",
"resource-explorer-2:ListIndexes",
"ec2:Describe*",
"rds:Describe*",
"elasticache:Describe*"
],
"Resource": "*"
}
For initializeDiscovery(), additional write permissions are required:
{
"Effect": "Allow",
"Action": [
"resource-explorer-2:CreateIndex",
"resource-explorer-2:CreateView",
"resource-explorer-2:AssociateDefaultView",
"iam:CreateServiceLinkedRole"
],
"Resource": "*"
}
Scoping credentials per call
By default, discover() resolves credentials from the ambient AWS SDK v3 credential chain described above. Pass options.aws.credentials to use specific credentials for one call instead — useful when a single process scans multiple AWS accounts, such as assumed roles in a multi-account organization.
The example below uses fromTemporaryCredentials from @aws-sdk/credential-providers, which is not a dependency of @cloudburn/sdk — install it in your project first (npm install @aws-sdk/credential-providers):
import { CloudBurnClient } from '@cloudburn/sdk';
import { fromTemporaryCredentials } from '@aws-sdk/credential-providers';
const client = new CloudBurnClient();
const accountRoleArns = [
'arn:aws:iam::111111111111:role/cloudburn-readonly',
'arn:aws:iam::222222222222:role/cloudburn-readonly',
];
for (const roleArn of accountRoleArns) {
const result = await client.discover({
target: { mode: 'current' },
aws: { credentials: fromTemporaryCredentials({ params: { RoleArn: roleArn } }) },
});
console.log(`${roleArn}: ${result.providers.flatMap((p) => p.rules).length} rule groups with findings`);
}
options.aws.credentials accepts anything typed AwsClientCredentials — a static AwsCredentialIdentity object or an AwsCredentialIdentityProvider function, both re-exported from @aws-sdk/types. Only discover() accepts this option directly; getDiscoveryStatus(), initializeDiscovery(), and listSupportedDiscoveryResourceTypes() always use the ambient credential chain unless the call itself runs inside a withAwsClientCredentials() callback.
To scope credentials across code that calls multiple SDK methods, wrap the calls in withAwsClientCredentials() instead of passing aws.credentials to discover() alone:
import { withAwsClientCredentials } from '@cloudburn/sdk';
const result = await withAwsClientCredentials(credentials, async () => {
await client.initializeDiscovery();
return client.discover({ target: { mode: 'current' } });
});
See withAwsClientCredentials for the full reference.
Handling access errors
If the SDK cannot access certain services or regions, it records them as diagnostics rather than failing the scan:
const result = await client.discover();
for (const diag of result.diagnostics ?? []) {
if (diag.status === 'access_denied') {
console.warn(`No access to ${diag.service} in ${diag.region}: ${diag.message}`);
}
}
This lets you get results for what you can access while identifying gaps in permissions.
What's next
| Quickstart: Discovery Scan | Run your first discovery scan |
| CloudBurnClient Reference | initializeDiscovery() and discover() reference |
| Types Reference | ScanDiagnostic type |