3

使用以下存储桶策略时,我看到它按预期限制了 PUT 访问 - 但是在创建的对象上允许 GET,即使没有任何东西应该允许此操作。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AllowPut",
            "Effect": "Allow",
            "Principal": {
                "AWS": "*"
            },
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::<BUCKET>/*",
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": [
                        "<IP ADDRESS>"
                    ]
                }
            }
        }
    ]
}

我可以使用 curl 将文件放入<BUCKET>如下<IP ADDRESS>

curl https://<BUCKET>.s3-<REGION>.amazonaws.com/ --upload-file test.txt

文件上传成功,并出现在 S3 控制台中。我现在由于某种原因能够从互联网上的任何地方获取文件。

curl https://<BUCKET>.s3-<REGION>.amazonaws.com/test.txt -XGET

这仅适用于使用上述方法上传的文件。在 S3 Web 控制台中上传文件时,我无法使用 curl 获取它(访问被拒绝)。所以我认为这是一个对象级别的权限问题。虽然我不明白为什么存储桶策略不会隐式拒绝此访问。

在控制台中查看对象级别权限时,通过控制台上传的文件(方法 1)和从允许上传<IP ADDRESS>的文件(方法 2)之间的唯一区别是方法 2 中的文件没有“所有者” 、权限或元数据 - 而方法 1 文件包含所有这些。

此外 - 当尝试使用 Lambda 脚本 (boto3 download_file()) 获取对象时,该脚本承担了对存储桶具有完全访问权限的角色,使用方法 2 上传的对象失败。尽管使用方法 1 上传的对象成功。

4

1 回答 1

3

问题摘要

总结一下这个问题:

  • 您有一个允许从给定源 IP 地址匿名上传对象的策略
  • 然后,您的经过身份验证的用户将无法读取这些对象(特别是您的 lambda 函数采用的 Iam 角色)
  • 未经身份验证的用户可以从任何 IP 读取这些对象

其他意见

  • 未经身份验证的用户无法删除对象

期望的结果是:

  • 对象可以由未经身份验证的用户从已知 IP 地址上传
  • 未经身份验证的用户无法从任何 IP 地址下载对象
  • 对象可由经过身份验证的 Iam 用户检索

根本原因

这是正在发生的事情:

  1. 匿名用户上传对象

    1. 匿名用户成为对象所有者
    2. 可通过检索对象 acl 进行验证(使用查询字符串对对象执行 GET 请求?acl) - 您将收到:

      <?xml version="1.0" encoding="UTF-8"?>
      <AccessControlPolicy xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
          <Owner>
              <ID>65a011a29cdf8ec533ec3d1ccaae921c</ID>
          </Owner>
          <AccessControlList>
              <Grant>
                  <Grantee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:type="CanonicalUser"><ID>65a011a29cdf8ec533ec3d1ccaae921c</ID></Grantee>
                  <Permission>FULL_CONTROL</Permission>
              </Grant>
          </AccessControlList>
      </AccessControlPolicy>
      

      所有者 ID 是匿名用户的通用 ID - 我在一些 AWS 论坛讨论中看到了相同的 ID。

  2. 成为对象所有者具有以下影响:
    1. 匿名用户有 FULL_CONTROL(参见上面的 acl)
    2. 匿名用户无法删除 - 这似乎是一个无法更改的 AWS 总括规则 - 永远不允许匿名用户删除任何内容,即使他们有 FULL_CONTROL
    3. 但是,由于 FULL_CONTROL,匿名用户能够在现有对象的顶部放置一个空对象
  3. 当存储桶包含不属于该存储桶账户的用户拥有的对象时:
    1. Bucket owner 对该对象没有权限(acl 中没有引用)
    2. 存储桶所有者无法读取对象
    3. 由于存储桶 acl,存储桶所有者能够在存储桶列表操作中看到对象
    4. 存储桶所有者可以删除对象 - 这是一个无法更改的总括规则 - 作为支付账单的人,您始终保留删除对象的权利 - 即使您无法阅读它

解析度

有一种方法可以实现您想要的结果 - 不幸的是,您必须引用您希望能够读取存储桶 acl 中的对象的特定 Iam 实体(用户、角色、组)的 arn。

该解决方案的关键要素是:

  • 要求匿名用户授予存储桶所有者完全访问权限
    • 这可确保存储桶所有者和所有者账户 Iam 用户不会被对象 acl 拒绝访问
  • 明确拒绝所有非您指定用户/角色的用户的所有非 PUT 访问
    • 这确保匿名用户无法读取对象

示例政策:

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "allow-anonymous-put",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:PutObject",
            "Resource": "arn:aws:s3:::<BUCKETNAME>/*",
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": "<IPADDRESS>"
                },
                "StringEquals": {
                    "s3:x-amz-acl": "bucket-owner-full-control"
                }
            }

        },
        {
            "Sid": "deny-not-my-user-everything-else",
            "Effect": "Deny",
            "NotPrincipal": {
                "AWS": "arn:aws:iam::<ACCOUNTNUMBER>:role/<ROLENAME>"
            },
            "NotAction": [
                "s3:PutObject",
                "s3:PutObjectAcl"
            ],
            "Resource": "arn:aws:s3:::<BUCKETNAME>/*"
        }
    ]
}

第二个语句的关键是使用NotPrincipaland NotAction

我已经在本地对此进行了测试,但只有普通的 Iam 用户被授予访问权限,而不是 Lamba 函数承担角色 - 但主体应该持有。祝你好运!

以下文章有助于理解正在发生的事情——它们都呈现了一个相似的场景,但与你的不太一样,但他们用来解决场景的方法引领了方向:

于 2016-08-22T03:06:44.347 回答