设置S3存储桶中对象的所有者

时间:2011-12-21 15:15:03

标签: ruby-on-rails-3 permissions amazon-s3 right-aws

我一直在尝试使用S3,他们有这个很酷的功能,您可以通过存储桶策略在存储桶的内容上设置ACL。因此,例如,您可以将一堆文件中的实际ACL设置为私有,但该文件可通过覆盖策略提供给某些用户/ IP地址/引用。

在我的情况下,我在一个存储桶中有一堆私人内容,但我想让我的网站上的特定目录中的文件可用(例如图像)。所以我有这样的事情:

{
    "Version": "2008-10-17",
    "Id": "",
    "Statement": [
        {
            "Sid": "AddPerm",
            "Effect": "Allow",
            "Principal": {
                "AWS": "*"
            },
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::content-racket-fm/uploaded/images/*"
        }
    ]
}

现在我们有一些背景可以解决这个问题。我最近在这里找到了:

https://forums.aws.amazon.com/thread.jspa?threadID=78294

该存储桶策略仅适用于存储桶拥有者拥有的文件。因此,例如,如果文件通过某些外部服务(如encoding.com或panda流)进入存储桶,他们在S3存储桶上拥有自己的用户,那么您将遇到问题,因为您的存储桶策略不会应用于这些文件(在我看来这似乎是亚马逊的疏忽,但我确信有一个很好的理由我没有想到)

我正在使用rails,有没有办法在桶中设置对象的所有者。

修改

我想一个更好的问题可能是......

是否有办法设置亚马逊存储桶,因此它会将存储桶策略应用于所有文件,而不管所有者。

1 个答案:

答案 0 :(得分:2)

事实证明,S3的另一个限制是,您似乎无法更改存储桶中对象的所有者。这使得存储桶策略在这种情况下毫无用处。作为一种解决方法,我不得不重新使用ACL。您可以使用rails AWS-SDK gem设置公共ACL,如下所示..

class AwsHelper

  # This method can be used to set a public acl on any object. The parameter file_path
  # will be the path to the file in the bucket minus the domain info, so if your full url was
  # http://s3.amazonaws.com/<your-bucket>/images/image1.png, file path would be
  # images/image1.png
  def self.set_public_acl(file_path)

    @bucket_path = ENV['S3_BUCKET']

    Rails.logger.warn "===> Loading S3"
    s3 = AWS::S3.new

    if(s3)
      bucket = s3.buckets[@bucket_path]

      if(bucket.exists?)
        Rails.logger.warn "===> Bucket '#{@bucket_path}' FOUND"

        key = bucket.objects[file_path]

        if(key.exists?)
          Rails.logger.warn "===> Key '#{file_path}' FOUND"

          key.acl = :public_read

          Rails.logger.warn "===> ACL Set to public read:"
          key.acl.grants.each { |grant| Rails.logger.warn "grantee => #{grant.grantee.group_uri}, permission => #{grant.permission.name}"}

          return key
        end
      end
    end
  end

end

如果您无法控制创建内容的用户但仍希望将其设为私有(例如,使用某些品牌的基于网络的视频编码时),则可以通过复制文件来实现此目的创建后(您的帐户将拥有该副本),删除旧的,然后将其复制回来。不理想,但它有效。