When your data lives in one AWS account and your Glue Crawler runs in another, you need to set up cross-account permissions on both sides. This guide shows you how to grant a Glue Crawler cross-account S3 bucket access by configuring the S3 bucket policy in the source account and the IAM role in the Glue account.
Architecture Overview
| Account A (Glue) | Account B (S3 Data) | |
|---|---|---|
| Account ID | 111111111111 |
222222222222 |
| What it has | Glue Crawler, Glue Data Catalog, IAM role | S3 bucket with the source data |
| What you configure | IAM role with S3 + Glue permissions | S3 bucket policy allowing Account A |
Both sides need to allow the access — the bucket policy in Account B grants permission, and the IAM role in Account A gives the Glue Crawler the ability to use it.
Step 1: Add a Bucket Policy in Account B
In Account B (the account that owns the S3 bucket), add a bucket policy that allows Account A to read the data. Go to the S3 bucket > Permissions > Bucket policy and add:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "AllowGlueAccountAccess",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::111111111111:root"
},
"Action": [
"s3:GetObject",
"s3:GetObjectVersion",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::your-data-bucket",
"arn:aws:s3:::your-data-bucket/*"
]
}
]
}
- Replace
111111111111with Account A’s actual account ID - Replace
your-data-bucketwith your S3 bucket name s3:ListBucketapplies to the bucket itself — the Crawler needs it to list objectss3:GetObjectapplies to/*— the Crawler needs it to read the actual files
A Glue Crawler only reads data. It doesn’t need s3:PutObject unless you also run Glue jobs that write back to this bucket.
For a tighter policy, you can scope the Principal to the specific Glue role ARN instead of the account root:
"Principal": {
"AWS": "arn:aws:iam::111111111111:role/AWSGlueServiceRole-crawler"
}
Step 2: Create the Glue IAM Role in Account A
In Account A (where the Glue Crawler runs), create an IAM role that the Glue service can assume.
Trust policy
This trust policy allows the Glue service to assume the role:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "glue.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
Permissions policy
Attach an inline or managed policy that grants the role access to the cross-account S3 bucket and the Glue Data Catalog:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "CrossAccountS3Access",
"Effect": "Allow",
"Action": [
"s3:GetObject",
"s3:GetObjectVersion",
"s3:ListBucket"
],
"Resource": [
"arn:aws:s3:::your-data-bucket",
"arn:aws:s3:::your-data-bucket/*"
]
},
{
"Sid": "GlueCatalogAccess",
"Effect": "Allow",
"Action": [
"glue:GetDatabase",
"glue:CreateDatabase",
"glue:GetTable",
"glue:CreateTable",
"glue:UpdateTable",
"glue:BatchCreatePartition",
"glue:GetPartition",
"glue:BatchGetPartition"
],
"Resource": "*"
},
{
"Sid": "CloudWatchLogs",
"Effect": "Allow",
"Action": [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
],
"Resource": "arn:aws:logs:*:111111111111:log-group:/aws-glue/*"
}
]
}
This policy has three parts:
- S3 access — matches the actions allowed in the bucket policy. Both sides must allow the same actions for cross-account access to work.
- Glue Data Catalog — lets the Crawler create and update tables/partitions in the catalog
- CloudWatch Logs — lets the Crawler write logs for debugging (optional but recommended)
Step 3: Create the Glue Crawler
In the AWS Glue console in Account A:
- Go to Crawlers > Create crawler
- Set the data source to S3 and enter the path:
s3://your-data-bucket/path/to/data/ - For the IAM role, select the role you created in Step 2
- Choose the target database in the Glue Data Catalog (or create a new one)
- Run the crawler
If the crawler fails with an “Access Denied” error, double-check that both the bucket policy and the IAM role policy use the same S3 actions and resource ARNs.
Troubleshooting
| Error | Likely Cause |
|---|---|
| Access Denied on S3 | Bucket policy in Account B doesn’t allow the Glue role or account root from Account A |
| Access Denied on S3 (role is correct) | The IAM role in Account A is missing the S3 permissions — both sides must allow |
| Crawler runs but finds no tables | The S3 path is wrong, or the data format isn’t recognized by Glue classifiers |
| Crawler can’t write to Data Catalog | The IAM role is missing glue:CreateTable or glue:UpdateTable permissions |
| KMS decrypt error | The S3 bucket uses SSE-KMS encryption — add kms:Decrypt to the role and the KMS key policy |
Conclusion
Cross-account Glue Crawler access requires matching permissions on both sides: a bucket policy in the data account and an IAM role with S3 + Glue permissions in the crawler account. Keep the policies scoped to the minimum actions the crawler needs.
For other cross-account patterns, see How to Copy S3 Bucket Objects Across AWS Accounts or How to Set Up Cross-Account Access in AWS with AssumeRole.


