
## Set up S3 access with cross-account IAM role

URL: https://docs.atlan.com/apps/connectors/storage/amazon-s3/how-tos/set-up-s3-access-with-a-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.

:::note New to IAM?

Read [How cross-account access works](https://docs.atlan.com/llms/connectors/amazon-s3/how-cross-account-access-works/llms.txt) 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](https://docs.atlan.com/llms/connectors/amazon-s3/bucket-policies-kms-keys-and-prefix-scoping/llms.txt)).
- More than ~1 million objects? Set up [inventory reports](https://docs.atlan.com/llms/connectors/amazon-s3/special-cases/llms.txt) 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](https://docs.atlan.com/support/submit-request) from within Atlan with your tenant URL. Use the three-part ask from [Atlan identity details](https://docs.atlan.com/llms/connectors/amazon-s3/atlan-identity-details/llms.txt) - 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
```

:::danger This ARN never goes in the crawler form

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](https://docs.atlan.com/llms/connectors/amazon-s3/atlan-identity-details/llms.txt) if you're cataloging less:

```json
{
 "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](https://docs.atlan.com/llms/connectors/amazon-s3/special-cases/llms.txt).

:::caution The two rows people trim - and regret

`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:

```json
{
 "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" } }
 }]
}
```

:::info About the External ID

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](https://docs.atlan.com/llms/connectors/amazon-s3/special-cases/llms.txt) 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.

:::danger Do not skip this phase

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

1. In Atlan, open **New workflow → Amazon S3 Assets**.
2. 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**.
3. Click **Test Authentication**.
4. Configure bucket/prefix filters (see [prefix scoping](https://docs.atlan.com/llms/connectors/amazon-s3/bucket-policies-kms-keys-and-prefix-scoping/llms.txt)) 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](https://docs.atlan.com/llms/connectors/amazon-s3/troubleshooting-s3-connectivity/llms.txt) - it maps each verbatim error string to its door and fix.

## Next steps

[Crawl S3](https://docs.atlan.com/llms/connectors/amazon-s3/crawl-s3/llms.txt): Configure and run the crawler to extract metadata from Amazon S3

---
