Set up S3 access with cross-account IAM role
The production-recommended way to connect Atlan to Amazon S3 - Atlan temporarily assumes a role in your AWS account, with no secret created or exchanged.
The production-recommended method: Atlan temporarily assumes a role in your AWS account. Five phases, each labeled with who performs it. No secret is created or exchanged.
Read How cross-account access works first (5 minutes). It explains every term below - role, trust policy, External ID, AssumeRole - and the two-sided handshake this guide walks through.
Prerequisites
- Someone with rights to create IAM roles and policies in the AWS account that owns the buckets.
- The list of buckets (and prefixes, if you're scoping) you want cataloged, and each bucket's region.
- If buckets use SSE-KMS encryption: someone who can edit the KMS key policy (Door 4).
- More than ~1 million objects? Set up inventory reports first.
Five phases at glance
| Phase | What happens | Owner | Typical time |
|---|---|---|---|
| 1. Gather | Get Atlan's Node Instance Role ARN + account ID | Atlan User + Atlan support | 1 business day (ticket) |
| 2. Policy | Create the S3 permission policy | Your AWS admin | 15 minutes |
| 3. Role | Create the role: trust policy + External ID | Your AWS admin | 15 minutes |
| 4. Allowlist | Atlan configures its side to assume your role | Atlan support | 1 business day (same ticket) |
| 5. Connect & verify | Enter role ARN + External ID + region in the crawler; test | Atlan User | 30 minutes |
Phase 1 - Gather Atlan's identity
Owner: Atlan User + Atlan support
Raise a support request from within Atlan with your tenant URL. Use the three-part ask from Atlan identity details - ARN, account ID, and a heads-up that your role ARN is coming in Phase 4. Support replies with the Node Instance Role ARN, e.g. (illustrative):
arn:aws:iam::999988887777:role/example-tenant-nodeinstance-role
Atlan's Node Instance Role ARN belongs in your trust policy only (Phase 3). In the crawler's "IAM Role" field you will enter your own role's ARN (Phase 5). Pasting Atlan's ARN into the crawler field makes the connection catalog Atlan's internal buckets instead of yours.
Phase 2 - Create permission policy
Owner: Your AWS admin
In the AWS IAM console, create a policy (suggested name: AtlanS3CrawlerPolicy). This variant covers buckets, folders, and objects - trim per the scope table if you're cataloging less:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AtlanListAllBuckets",
"Effect": "Allow",
"Action": ["s3:ListAllMyBuckets"],
"Resource": "*"
},
{
"Sid": "AtlanReadBucketAndObjects",
"Effect": "Allow",
"Action": [
"s3:GetBucketLocation", "s3:GetBucketTagging",
"s3:GetEncryptionConfiguration", "s3:GetBucketVersioning",
"s3:ListBucket",
"s3:GetObject", "s3:GetObjectTagging",
"s3:GetObjectRetention", "s3:GetObjectLegalHold"
],
"Resource": [
"arn:aws:s3:::example-data-bucket",
"arn:aws:s3:::example-data-bucket/*"
]
}
]
}
The ListAllMyBuckets statement must stay on "Resource": "*" - AWS ignores it when scoped to a bucket. Add s3:SelectObjectContent on the inventory destination bucket if using inventory ingestion.
s3:GetObjectRetention and s3:GetObjectLegalHold look exotic, but the crawler requests them for object metadata. Removing them produces mid-crawl AccessDenied errors even though Test connection passed.
Phase 3 - Create role and its trust policy
Owner: Your AWS admin
Create a role (suggested name: AtlanS3CrawlerRole), attach the Phase 2 policy, and set the trust policy to Atlan's Node Instance Role from Phase 1, with an External ID your team invents:
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": { "AWS": "arn:aws:iam::999988887777:role/example-tenant-nodeinstance-role" },
"Action": "sts:AssumeRole",
"Condition": { "StringEquals": { "sts:ExternalId": "example-corp-atlan-2026" } }
}]
}
You choose the string - treat it like a shared passphrase, not a secret. It's strongly recommended for production (it prevents the "confused deputy" problem). Caveat: the S3 crawler form accepts an External ID, but some package workflows (e.g. Asset Import) cannot send one today - if you'll use those with the same role, see Special cases before adding the condition.
Phase 4 - Atlan allowlists your role
Owner: Atlan support
Reply on your Phase 1 ticket with your role ARN (e.g. arn:aws:iam::111122223333:role/AtlanS3CrawlerRole), your AWS account ID, and your External ID. Atlan grants its Node Instance Role permission to assume exactly your role, and confirms on the ticket.
If Atlan's side isn't configured, the role borrow fails silently and Test connection shows AuthorizationHeaderMalformed: ... a non-empty Access Key (AKID) must be provided - an error that looks like your fault but isn't. This is among the most-misdiagnosed S3 failures.
Phase 5 - Connect and verify
Owner: Atlan User
- In Atlan, open New workflow → Amazon S3 Assets.
- Choose IAM Role authentication. Enter your role's ARN (not Atlan's!), your External ID (must match Phase 3 exactly), and the AWS region of your buckets.
- Click Test Authentication.
- Configure bucket/prefix filters (see prefix scoping) and choose direct or inventory ingestion.
Success checklist
- Test Authentication passes in the Atlan UI
- Preflight checks pass when you configure the crawler
- A crawl scoped to one small bucket or prefix completes
- A full crawl completes - the first real exercise of the
GetObject*permissions and (if applicable) the KMS key
All four green? Done. If any step fails, see Troubleshooting S3 connectivity - it maps each verbatim error string to its door and fix.
Next steps
Crawl S3: Configure and run the crawler to extract metadata from Amazon S3