默认情况下,如何将 AWS S3 存储桶中的所有对象设为公开?

Posted

技术标签:

【中文标题】默认情况下,如何将 AWS S3 存储桶中的所有对象设为公开?【英文标题】:How to make all Objects in AWS S3 bucket public by default? 【发布时间】:2013-10-11 04:45:30 【问题描述】:

我正在使用 php 库将文件上传到我的存储桶。我已将 ACL 设置为 public-read-write,它工作正常,但文件仍然是私有的。

我发现如果我将Grantee 更改为Everyone,它会使文件公开。我想知道的是如何将我存储桶中的所有对象的默认受让人设置为“Everyone”。或者是否有其他解决方案可以默认将文件公开

我使用的代码如下:

public static function putObject($input, $bucket, $uri, $acl = self::ACL_PRIVATE, $metaHeaders = array(), $requestHeaders = array()) 
    if ($input === false) return false;
    $rest = new S3Request('PUT', $bucket, $uri);

    if (is_string($input)) $input = array(
        'data' => $input, 'size' => strlen($input),
        'md5sum' => base64_encode(md5($input, true))
    );

    // Data
    if (isset($input['fp']))
        $rest->fp =& $input['fp'];
    elseif (isset($input['file']))
        $rest->fp = @fopen($input['file'], 'rb');
    elseif (isset($input['data']))
        $rest->data = $input['data'];

    // Content-Length (required)
    if (isset($input['size']) && $input['size'] >= 0)
        $rest->size = $input['size'];
    else 
        if (isset($input['file']))
            $rest->size = filesize($input['file']);
        elseif (isset($input['data']))
            $rest->size = strlen($input['data']);
    

    // Custom request headers (Content-Type, Content-Disposition, Content-Encoding)
    if (is_array($requestHeaders))
        foreach ($requestHeaders as $h => $v) $rest->setHeader($h, $v);
    elseif (is_string($requestHeaders)) // Support for legacy contentType parameter
        $input['type'] = $requestHeaders;

    // Content-Type
    if (!isset($input['type'])) 
        if (isset($requestHeaders['Content-Type']))
            $input['type'] =& $requestHeaders['Content-Type'];
        elseif (isset($input['file']))
            $input['type'] = self::__getMimeType($input['file']);
        else
            $input['type'] = 'application/octet-stream';
    

    // We need to post with Content-Length and Content-Type, MD5 is optional
    if ($rest->size >= 0 && ($rest->fp !== false || $rest->data !== false)) 
        $rest->setHeader('Content-Type', $input['type']);
        if (isset($input['md5sum'])) $rest->setHeader('Content-MD5', $input['md5sum']);

        $rest->setAmzHeader('x-amz-acl', $acl);
        foreach ($metaHeaders as $h => $v) $rest->setAmzHeader('x-amz-meta-'.$h, $v);
        $rest->getResponse();
     else
        $rest->response->error = array('code' => 0, 'message' => 'Missing input parameters');

    if ($rest->response->error === false && $rest->response->code !== 200)
        $rest->response->error = array('code' => $rest->response->code, 'message' => 'Unexpected HTTP status');
    if ($rest->response->error !== false) 
        trigger_error(sprintf("S3::putObject(): [%s] %s", $rest->response->error['code'], $rest->response->error['message']), E_USER_WARNING);
        return false;
    
    return true;

【问题讨论】:

【参考方案1】:

转到http://awspolicygen.s3.amazonaws.com/policygen.html 填写详细信息如: 在操作中选择“GetObject” 选择“添加语句” 然后选择“生成策略”

复制文本示例:


  "Id": "Policy1397632521960",
  "Statement": [
    
      "Sid": "Stmt1397633323327",
      "Action": [
        "s3:GetObject"
      ],
      "Effect": "Allow",
      "Resource": "arn:aws:s3:::bucketnm/*",
      "Principal": 
        "AWS": [
          "*"
        ]
      
    
  ]

现在转到您的 AWS S3 控制台,在存储桶级别,单击属性,展开权限,然后选择添加存储桶策略。将上面生成的代码粘贴到编辑器中并点击保存。

默认情况下,您存储桶中的所有项目都是公开的。

【讨论】:

这是正确的回答。与之前的答案不同,这篇文章还教我如何创建策略以及它们的作用。读完后,我可以手动编写策略。 我赞成这个答案的原因与@liyicky 相同,详细说明是一个很好的介绍,而不是仅仅得到答案。 这里也一样。 AWS 有时往往是不透明的,这可能是有充分理由的。这种形式的答案从零开始很有帮助。 这适用于您将新文件添加到存储桶但我需要更改存储桶中已存在的文件以公开。 注意:我需要将/* 附加到资源名称以避免错误“桶操作不适用于任何资源”:***.com/questions/44228422/…【参考方案2】:

如果您希望默认公开所有对象,最简单的方法是通过 Bucket Policy 而不是在每个单独对象上定义的访问控制列表 (ACL) 来实现。

您可以使用AWS Policy Generator 为您的存储桶生成存储桶策略。

例如,以下策略将允许任何人读取您的 S3 存储桶中的每个对象(只需将 <bucket-name> 替换为您的存储桶名称):


  "Id": "Policy1380877762691",
  "Statement": [
    
      "Sid": "Stmt1380877761162",
      "Action": [
        "s3:GetObject"
      ],
      "Effect": "Allow",
      "Resource": "arn:aws:s3:::<bucket-name>/*",
      "Principal": 
        "AWS": [
          "*"
        ]
      
    
  ]

存储桶策略包含Statements 的列表,每个语句都有一个EffectAllowDeny),用于Actions 的列表,由Principal(用户)在指定的Resource(由Amazon Resource NameARN 标识)。

Id 只是一个可选的策略 ID,Sid 是一个可选的唯一语句 ID。

对于 S3 存储桶策略,资源 ARN 采用以下形式:

arn:aws:s3:::<bucket_name>/<key_name>

以上示例允许 (Effect: Allow) 任何人 (Principal: *) 访问 (Action: s3:GetObject) 存储桶 (Resource: arn:aws:s3:::&lt;bucket-name&gt;/*) 中的任何对象。

【讨论】:

控制面板有办法吗? @ianaz 您可以通过 AWS 控制台(控制面板)将此存储桶策略添加到存储桶 @ianaz 在下面看到我的回答。 另请注意,上述链接中有一个“示例策略”链接,它提供了剪切和粘贴到策略生成器所需的确切信息。随着 aws 更新 API,这更有可能保持正确。今天早上对我来说就像一个魅力。 Principal: * 帮助了我很多。谢谢!【参考方案3】:

我的问题略有不同,但由于这个问题在谷歌搜索的顶部,我会留下我的解决方案,也许它会对某人有所帮助。

我之前已经拥有对 S3 存储桶的完全访问权限,但有一天它刚刚开始将 Access Denied 返回到我的所有文件。解决方案很简单。

    转到Services - S3 点击您的 S3 存储桶 切换到Permissions标签,然后转到Bucket Policy标签 然后点击Save按钮。

它应该重新分配所有文件的权限。

无论如何,这里是完整的bucket policy,它允许公开所有对象


    "Version": "2012-10-17",
    "Statement": [
        
            "Sid": "AllowPublicRead",
            "Effect": "Allow",
            "Principal": 
                "AWS": "*"
            ,
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::enter-here-your-media-bucket-name/*"
        
    ]

【讨论】:

这个答案对我有帮助,但它安全吗?应用此政策后,不怀好意的人会怎么做? @rom 如果您确实需要公开访问您的文件(也称为媒体、js、css、pdf 等),那么不会发生任何不好的事情,因为您只允许使用 s3:GetObject 操作进行读取访问。 【参考方案4】:

上面的 JSON 对我不起作用,但我发现它起作用了。我已经在多个存储桶上对其进行了测试。我可以通过编程方式写入存储桶并同时读取它们


    "Version": "2012-10-17",
    "Statement": [
        
            "Sid": "AddCannedAcl",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::<bucket_name>/*"
        
    ]

【讨论】:

【参考方案5】:

很简单...只需将其添加到您的存储桶策略中即可。这将使您的存储桶可公开访问。我这样做是因为我的存储桶仅包含图像和徽标,因此公开它是有意义的,因为没有敏感或用户特定的数据/资产。


    "Version": "2012-10-17",
    "Statement": [
        
            "Sid": "Stmt1380877761162",
            "Effect": "Allow",
            "Principal": 
                "AWS": "*"
            ,
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::my-bucket-assets/*"
        
    ]

【讨论】:

以上是关于默认情况下,如何将 AWS S3 存储桶中的所有对象设为公开?的主要内容,如果未能解决你的问题,请参考以下文章

如何让 AWS S3 存储桶中的 Angular 应用程序对 AWS Elastic Beanstalk 中的服务进行 API 调用

AWS S3 文件上传但存储桶中的文件没有大小?

如何强制删除 S3 存储桶中的所有对象版本,然后最终使用 aws-sdk-go 删除整个存储桶?

如何使用angular js将aws s3文件复制到同一个存储桶中的特定文件夹

如何将旧 S3 存储桶中的 Terraform 状态移动到新的 S3 存储桶?

从 AWS S3 存储桶访问文件