簡體   English   中英

如何列出所有公開的 AWS S3 對象?

[英]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,則不是。

那么,步驟是:

  1. 使用ListBuckets端點獲取存儲桶列表。 在 CLI 中,這是:

     aws2 s3api list-buckets
  2. 對於每個桶,獲取其區域並列出其對象。 從 CLI(假設您已配置使用它的憑據),您可以分別使用這兩個命令執行這兩件事:

     aws2 s3api get-bucket-location --bucket 
     aws2 s3api list-objects --bucket 
  3. 對於每個對象,向 URL 發出 HEAD 請求,例如

    https://bucketname.s3.us-east-1.amazonaws.com/objectname

    bucketnameus-east-1objectname分別替換為您的存儲桶名稱、存儲桶區域的實際名稱和您的對象名稱。

    要使用 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM