When working with multi-account AWS environments, a common challenge arises when you encounter an S3 object URL (e.g., s3://example-bucket/path/to/object
) but don't know which of your hundreds of AWS accounts has permissions to access it. Here's how to systematically identify the owning account.
The most reliable methods to identify bucket ownership:
import boto3
from botocore.exceptions import ClientError
def find_bucket_owner(bucket_name, account_profiles):
for profile in account_profiles:
try:
session = boto3.Session(profile_name=profile)
s3 = session.client('s3')
result = s3.get_bucket_acl(Bucket=bucket_name)
return {
'account_id': result['Owner']['ID'],
'account_profile': profile
}
except ClientError as e:
if e.response['Error']['Code'] != 'AccessDenied':
continue
return None
- First attempt read access with your default credentials
- If denied, iterate through your available AWS profiles/accounts
- Use the
get_bucket_acl
orget_bucket_location
API calls - Analyze response headers for ownership clues
For organizations with many accounts, consider these optimizations:
# Parallel account checking using GNU parallel
parallel -j 10 "aws s3api get-bucket-acl --bucket target-bucket \
--profile {} 2>&1 | grep -q 'Owner' && echo {}" ::: $(aws-profiles)
Key observations from response headers:
x-amz-owner-id
in API responses- Account ID patterns in error messages
- Bucket naming conventions (if standardized)
When API access isn't available:
# Check via S3 console URL patterns
console_url = f"https://s3.console.aws.amazon.com/s3/buckets/{bucket_name}"
# The URL will redirect to the owning account's console
Remember that bucket ownership transfer between accounts is complex and requires specific procedures.
Always ensure you have proper authorization before attempting to access buckets. This process should only be used:
- With legitimate cross-account permissions
- On buckets your organization owns
- For legitimate administrative purposes
When working with distributed AWS environments, a common scenario arises: you receive an S3 object URL (e.g., s3://bucket-name/path/to/object
) but don't know which AWS account owns the bucket. This becomes critical when you need to assume the correct IAM role across hundreds of potential accounts.
Here are three reliable methods to determine bucket ownership:
1. Using AWS CLI with HeadBucket
aws s3api head-bucket --bucket bucket-name
This will return the bucket's Region and account information if you have permissions. For cross-account scenarios:
{
"ResponseMetadata": {
"HTTPHeaders": {
"x-amz-bucket-region": "us-east-1",
"x-amz-id-2": "EXAMPLEID",
"x-amz-request-id": "EXAMPLEID"
}
}
}
2. Bucket Policy Inspection via API
The most definitive method is checking the bucket policy:
aws s3api get-bucket-policy --bucket bucket-name
Successful response will include the owner's account ID in the policy document:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::123456789012:root"
},
...
}
]
}
3. Resource Tagging Strategy
For organizations with proper tagging conventions:
aws s3api get-bucket-tagging --bucket bucket-name
Example response showing owner account:
{
"TagSet": [
{
"Key": "OwnerAccount",
"Value": "123456789012"
}
]
}
For bulk operations across multiple accounts, use AWS Organizations with the following Python script:
import boto3
def find_bucket_owner(bucket_name):
org_client = boto3.client('organizations')
accounts = org_client.list_accounts()
for account in accounts['Accounts']:
sts_client = boto3.client('sts')
assumed_role = sts_client.assume_role(
RoleArn=f"arn:aws:iam::{account['Id']}:role/OrganizationAccountAccessRole",
RoleSessionName="BucketDiscovery"
)
s3_client = boto3.client(
's3',
aws_access_key_id=assumed_role['Credentials']['AccessKeyId'],
aws_secret_access_key=assumed_role['Credentials']['SecretAccessKey'],
aws_session_token=assumed_role['Credentials']['SessionToken']
)
try:
s3_client.head_bucket(Bucket=bucket_name)
return account['Id']
except:
continue
return None
- Ensure your base role has
organizations:ListAccounts
permission - Limit the assumed role permissions to read-only S3 operations
- Implement proper error handling for permission denied scenarios
For organizations using AWS RAM, you can check shared resource associations:
aws ram get-resource-share-associations \
--association-type RESOURCE \
--resource-arn arn:aws:s3:::bucket-name