尽管策略允许我的网站引荐来源,但S3存储桶上的copyObject访问被拒绝

时间:2019-03-23 09:32:06

标签: php amazon-s3 policy referrer bucket

我正在使用适用于PHP的AWS开发工具包从我的S3存储桶上传文件并显示文件。

只能通过我的网站访问这些文件,不允许使用其他引荐来源-不允许进行热链接等。

我还需要能够复制存储桶中的对象。

我正常创建并连接:

    $s3Client = new Aws\S3\S3Client([
        'version'       => 'latest',
        'region'        => 'eu-west-2'
    ]);

    $s3 = $s3Client::factory(array(
        'version'       => 'latest',
        'region'        => 'eu-west-2',
        'credentials'   => array(
        'provider'      => $provider,
        'key'           => $key,
        'secret'        => $secret
        )
    ));

并执行复制对象命令:

    $s3->copyObject([
        'Bucket'     => "{$targetBucket}",
        'Key'        => "{$targetKeyname}",
        'CopySource' => "{$sourceBucket}/{$sourceKeyname}",
    ]);

我尝试了使用“允许类似引用字符串的字符串”的策略,但是AWS告诉我我允许公共访问?!?!? 即使执行copyObject操作,一切也都很好,但是仍然可以直接从任何地方访问文件!

我尝试使用“ Deny if string not like Referrer”,它的工作原理大致符合预期-我可以上传和显示文件,而直接链接时文件却不显示(这是我想要的)-但是,copyObject操作不再起作用,并且出现访问被拒绝错误。

我已经尝试了我能想到的所有其他方法,并花了几个小时搜索和寻找答案,但无济于事。

这里是每个单独的政策...

仅允许使用LIKE引荐来源的字符串访问文件(GetObject)

{
"Version": "2008-10-17",
"Id": "",
"Statement": [
    {
        "Sid": "Deny access if referer is not my site",
        "Effect": "Deny",
        "Principal": {
            "AWS": "*"
        },
        "Action": "s3:GetObject",
        "Resource": [
            "arn:aws:s3:::MY-BUCKET/*"
        ],
        "Condition": {
            "StringLike": {
                "aws:Referer": [
                    "http://MY-SITE/*",
                    "https://MY-SITE/*"
                    ]
                }
            }
        }
    ]
}

结果:上传和copyObject工作正常,但仍然可以在任何地方访问文件


如果字符串不像引荐来源网址,则拒绝所有操作(*):

{
"Version": "2008-10-17",
"Id": "",
"Statement": [
    {
        "Sid": "Deny access if referer is not my site",
        "Effect": "Deny",
        "Principal": {
            "AWS": "*"
        },
        "Action": "s3:GetObject",
        "Resource": [
            "arn:aws:s3:::MY-BUCKET/*"
        ],
        "Condition": {
            "StringNotLike": {
                "aws:Referer": [
                    "http://MY-SITE/*",
                    "https://MY-SITE/*"
                    ]
                }
            }
        }
    ]
}

结果:copyObject操作不再起作用,并且出现访问被拒绝错误

2 个答案:

答案 0 :(得分:1)

AWS可能会警告您它是公开的,因为出于所有实际目的,它仍然是公开的。

  

警告

     

应谨慎使用此密钥:aws:referer允许Amazon S3存储桶所有者防止未经授权的第三方网站将其内容提供给标准Web浏览器。 [...]由于aws:referer值是由调用方在HTTP标头中提供的,因此未经授权的各方可以使用经过修改或自定义的浏览器来提供他们选择的任何aws:referer值。因此,不应使用aws:referer来防止未经授权的方发出直接的AWS请求。提供此服务仅是为了让客户保护其存储在Amazon S3中的数字内容,以免在未经授权的第三方站点上被引用。

     

https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_condition-keys.html

如果您对这种原始机制感到满意,请使用它,但请注意,它所做的只是信任浏览器的主张。

这是copyObject()的问题-浏览器没有发出请求 ,因此没有Referer标头可以验证。

您可以使用StringLikeIfExists条件测试来仅对Deny个错误的引荐来源网址进行使用(忽略不存在引荐来源,就像对象副本一样),或者-更好-只需向s3:GetObject授予StringLike您的推荐人,就可以知道公共警告是正确的–这允许未经身份验证的访问,这就是引用人检查的作用。您的内容仍可公开访问,但如果从另一个站点进行热链接,则无法通过标准的,未经修改的Web浏览器访问。

为了获得更好的安全性,您将希望使用S3资产的预签名URL(具有较短的到期时间)呈现HTML,或者使用Amazon Cognito进行完全适当的授权。

答案 1 :(得分:0)

Amazon S3中的对象默认为私有。除非以某种方式被授予(例如,在IAM用户,IAM组或S3存储桶策略上),否则无法进行访问。

以上策略都是 Deny 策略,可以覆盖 Allow 策略。因此,它们不是 可以访问的原因。

您应该先找到授予访问权限的内容,然后删除该访问权限。一旦这些对象再次成为私有对象,则应使用Allow语句创建一个存储桶策略,该语句定义在什么情况下允许访问。