1

我希望有人能够解释为什么我在控制台登录和 api 登录之间出现授权错误。我有一个可以访问特定 S3 存储桶的客户端,该存储桶对存储桶具有完全 CRUD 访问权限,并且能够通过控制台执行下载、创建、删除,但是当通过 API 访问时,如果他们提前知道密钥,他们也可以下载视图但在尝试读取存储桶中对象的密钥时收到未经授权的错误。

以下策略与用户帐户相关联,试图将该用户隔离到一个 S3 存储桶。

 {
  "Statement": [
    {
      "Sid": "AllowGroupToSeeBucketListAndAlsoAllowGetBucketLocationRequiredForListBucket",
      "Effect": "Allow",
      "Action": [
        "s3:ListAllMyBuckets",
        "s3:GetBucketLocation"
      ],
      "Resource": "arn:aws:s3:::*",
      "Condition": {}
    },
    {
      "Sid": "AllowRootLevelListingOfCompanyBucket",
      "Effect": "Allow",
      "Action": "s3:ListBucket",
      "Resource": "arn:aws:s3:::mybucket",
      "Condition": {
        "StringEquals": {
          "s3:prefix": "",
          "s3:delimiter": "/"
        }
      }
    },
    {
      "Effect": "Allow",
      "Action": [
        "s3:GetObject",
        "s3:GetObjectVersion",
        "s3:PutObject",
        "s3:GetObjectAcl",
        "s3:GetObjectVersionAcl",
        "s3:PutObjectAcl",
        "s3:PutObjectVersionAcl",
        "s3:DeleteObject",
        "s3:DeleteObjectVersion"
      ],
      "Resource": "arn:aws:s3:::mybucket/*",
      "Condition": {}
    }
  ]
}

以下是因未经授权而失败的 api 调用:

-=-=-=-
import boto, boto.s3

s3conn = boto.s3.connection.S3Connection(aws_access_key_id=ACCESS_KEY,
                                         aws_secret_access_key=SECRET_KEY,
                                         is_secure=True,
                                         debug=0)

# This line fails with "403 Forbidden" b/c it tries to read the keys in # the bucket:
#s3bucket = s3conn.get_bucket('mybucket')

# This line does NOT try to read the keys and therefore succeeds:
s3bucket = s3conn.get_bucket('mybucket', validate=False)

# This loop fails with "403 Forbidden" on the very first iteration:
#for k in s3bucket.list():
#    print k

# This line works, but I had to use the webpage to learn the name of the # key first.
k = s3bucket.get_key('specificfilename.csv')
print k

# This line works.
print k.generate_url(expires_in=10) + '\n'
4

1 回答 1

3

正如 Bob Kinney 提到的,问题是由这种情况引起的:

  "Condition": {
    "StringEquals": {
      "s3:prefix": "",
      "s3:delimiter": "/"
    }
  }

您基本上将ListBucket操作限制为与该条件匹配的调用,但是当您尝试执行时:

s3bucket = s3conn.get_bucket('mybucket')

boto 将尝试执行没有前缀和分隔符的列表存储桶调用,以验证存储桶存在并且用户可以访问它。由于该调用不符合您的条件,因此它将失败。

以下确实有效:

s3bucket = s3conn.get_bucket('mybucket', validate=False)

因为在这种情况下,boto 只是跳过了我上面描述的验证。如果您跳过此验证并执行:

for k in s3bucket.list():

您最终会遇到同样的问题,因为list()您尝试运行的调用与您的条件不匹配(默认情况下,前缀和分隔符为空)。

要修复您的 IAM 策略,只需删除该ListBucket操作的条件即可。

于 2013-09-16T12:05:13.443 回答