[英]How do I list all AWS S3 objects that are public?
我想列出我的 s3 存储桶中的所有公共对象。 使用 get-object-acl 会列出特定对象的受赠者,所以我想知道是否有更好的选择
依赖get-object-acl
可能不是您想做的,因为可以通过 ACL 以外的方式公开对象。 至少,这可以通过对象的 ACL 和存储桶的策略(参见例如https://havecamerawilltravel.com/photographer/how-allow-public-access-amazon-bucket/ )实现,也许还有其他意味着我不知道。
更聪明的测试是在没有凭据的情况下向每个对象发出 HEAD 请求。 如果你得到 200,它就是公开的。 如果您收到 403,则不是。
那么,步骤是:
使用ListBuckets端点获取存储桶列表。 在 CLI 中,这是:
aws2 s3api list-buckets
对于每个桶,获取其区域并列出其对象。 从 CLI(假设您已配置使用它的凭据),您可以分别使用这两个命令执行这两件事:
aws2 s3api get-bucket-location --bucket
aws2 s3api list-objects --bucket
对于每个对象,向 URL 发出 HEAD 请求,例如
https://bucketname.s3.us-east-1.amazonaws.com/objectname
将bucketname 、 us-east-1和objectname分别替换为您的存储桶名称、存储桶区域的实际名称和您的对象名称。
要使用 Curl 从 Unix 命令行执行此操作,请执行
curl -I https:// .s3. .amazonaws.com/
使用 Boto 3 和 Requests 在 Python 中实现上述逻辑的示例:
from typing import Iterator
import boto3
import requests
s3 = boto3.client('s3')
all_buckets = [
bucket_dict['Name'] for bucket_dict in
s3.list_buckets()['Buckets']
]
def list_objs(bucket: str) -> Iterator[str]:
"""
Generator yielding all object names in the bucket. Potentially requires
multiple requests for large buckets since list_objects is capped at 1000
objects returned per call.
"""
response = s3.list_objects_v2(Bucket=bucket)
while True:
if 'Contents' not in response:
# Happens if bucket is empty
return
for obj_dict in response['Contents']:
yield obj_dict['Key']
last_key = obj_dict['Key']
if response['IsTruncated']:
response = s3.list_objects_v2(Bucket=bucket, StartAfter=last_key)
else:
return
def is_public(bucket: str, region: str, obj: str) -> bool:
url = f'https://{bucket}.s3.{region}.amazonaws.com/{obj}'
resp = requests.head(url)
if resp.status_code == 200:
return True
elif resp.status_code == 403:
return False
else:
raise Exception(f'Unexpected HTTP code {resp.status_code} from {url}')
for bucket in all_buckets:
region = s3.get_bucket_location(Bucket=bucket)['LocationConstraint']
for obj in list_objs(bucket):
if is_public(bucket, region, obj):
print(f'{bucket}/{obj} is public')
请注意,每个对象大约需要一秒钟,如果您在 S3 中有很多东西,这并不理想。 不过,我不知道有更快的选择。
在使用 AWS CLI 一段时间后,您会发现最好的方法是同步具有结构化前缀下权限的 mv 或 cp 文件 Permission – 指定授予的权限,可以设置为 read、readacl、writeacl 或 full。
例如aws s3 sync. s3://my-bucket/path --acl public-read
aws s3 sync. s3://my-bucket/path --acl public-read
然后在需要的前缀下列出所有这些对象。
将存储桶的名称或存储桶列表放入“buckets.list”文件并运行下面的 bash 脚本。
该脚本在使用分页时支持无限 (.) 个对象。
#!/bin/bash
MAX_ITEMS=100
PAGE_SIZE=100
for BUCKET in $(cat buckets.list);
do
OBJECTS=$(aws s3api list-objects-v2 --bucket $BUCKET --max-items=$MAX_ITEMS --page-size=$PAGE_SIZE 2>/dev/null)
e1=$?
if [[ "OBJECTS" =~ "Could not connect to the endpoint URL" ]]; then
echo "Could not connect to the endpoint URL!"
echo -e "$BUCKET" "$OBJECT" "Could not connect to the endpoint URL" >> errors.log
fi
NEXT_TOKEN=$(echo $OBJECTS | jq -r '.NextToken')
while [[ "$NEXT_TOKEN" != "" ]]
do
OBJECTS=$(aws s3api list-objects-v2 --bucket $BUCKET --max-items=$MAX_ITEMS --page-size=$PAGE_SIZE --starting-token $NEXT_TOKEN | jq -r '.Contents | .[].Key' 2>/dev/null)
for OBJECT in $OBJECTS;
do
ACL=$(aws s3api get-object-acl --bucket $BUCKET --key $OBJECT --query "Grants[?Grantee.URI=='http://acs.amazonaws.com/groups/global/AllUsers']" --output=text 2>/dev/null)
e2=$?
if [[ "$ACL" =~ "Could not connect to the endpoint URL" ]]; then
echo "Could not connect to the endpoint URL!"
echo -e "$BUCKET" "$OBJECT" "Could not connect to the endpoint URL" >> errors.log
fi
if [[ ! "$ACL" == "" ]] && [[ $e1 == 0 ]] && [[ $e2 == 0 ]]; then
echo -e "$BUCKET" "$OBJECT" "Public object!!!" "$ACL"
echo -e "$BUCKET" "$OBJECT" "$ACL" >> public-objects.log
else
echo -e "$BUCKET" "$OBJECT" "not public"
fi
done
done
done
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.