使用Ruby为CloudFront创建签名的URL

时间:2010-04-13 19:10:36

标签: ruby amazon-cloudfront

历史:

  1. 我在亚马逊上创建了一个密钥和pem文件。
  2. 我创建了一个私人存储桶
  3. 我创建了一个公共发行版并使用原始ID连接到私人存储桶:工作
  4. 我创建了一个私人发行版,并将它与#3相同 - 现在我被拒绝访问:预期
  5. 我很难生成一个可行的网址。我一直在尝试按照此处描述的说明进行操作:http://docs.amazonwebservices.com/AmazonCloudFront/latest/DeveloperGuide/index.html?PrivateContent.html

    这是我到目前为止所做的......虽然不起作用 - 仍然被拒绝访问:

    def url_safe(s)
      s.gsub('+','-').gsub('=','_').gsub('/','~').gsub(/\n/,'').gsub(' ','')
    end
    
    def policy_for_resource(resource, expires = Time.now + 1.hour)
      %({"Statement":[{"Resource":"#{resource}","Condition":{"DateLessThan":{"AWS:EpochTime":#{expires.to_i}}}}]})
    end
    
    def signature_for_resource(resource, key_id, private_key_file_name, expires = Time.now + 1.hour)
        policy = url_safe(policy_for_resource(resource, expires))
        key = OpenSSL::PKey::RSA.new(File.readlines(private_key_file_name).join("")) 
        url_safe(Base64.encode64(key.sign(OpenSSL::Digest::SHA1.new, (policy))))
    end
    
    def expiring_url_for_private_resource(resource, key_id, private_key_file_name, expires = Time.now + 1.hour)
      sig = signature_for_resource(resource, key_id, private_key_file_name, expires)
      "#{resource}?Expires=#{expires.to_i}&Signature=#{sig}&Key-Pair-Id=#{key_id}"
    end
    
    resource = "http://d27ss180g8tp83.cloudfront.net/iwantu.jpeg"
    key_id = "APKAIS6OBYQ253QOURZA"
    pk_file = "doc/pk-APKAIS6OBYQ253QOURZA.pem"
    puts expiring_url_for_private_resource(resource, key_id, pk_file)
    

    谁能告诉我这里我做错了什么?

6 个答案:

答案 0 :(得分:11)

全部,

我刚刚使用这个问题中的一些代码创建了一个可用于使用Ruby签署CF URL的小gem:

https://github.com/stlondemand/aws_cf_signer

我可能会在未来几周对其进行重大更改,因为我尝试在我的应用程序中实际使用它,但是想让你们知道,因为你在attributions部分列出了。 :)

谢谢!

答案 1 :(得分:2)

在设置策略之前删除url_safe: policy = policy_for_resource(resource,expires)

根据文档,只有Base64应该是安全的Url-Safe(m)= CharReplace(Base64(m),“+ = /”,“ - ~~”)

..并确保CloudFront配置正确如下: http://blog.cloudberrylab.com/2010/03/how-to-configure-private-content-for.html

答案 2 :(得分:1)

是的,保留policy = policy_for_resource(resource, expires)政策对我有用。

答案 3 :(得分:1)

我分叉right_aws(他们没有回复我的拉取请求)...我在他们的acf库中设置了cloudfront私有流和下载:http://github.com/wiseleyb/right_aws

答案 4 :(得分:1)

我同意迪伦的观点。他在签署网址方面做得很好。我遇到过同样的问题。我浏览了文档。有一件事我在那里找不到。当您创建私人分发时,您通常会提供文件,存储桶等的访问权限。

在我分配了Bucket Policy之前,我收到了拒绝访问错误。

您可以指定以下政策:

{
    "Version":"2008-10-17",
    "Id":"PolicyForCloudFrontPrivateContent",
    "Statement":[{
            "Sid":" Grant a CloudFront Origin Identity access to support private content",
            "Effect":"Allow",
            "Principal":{
            "CanonicalUser":"here-goes-your-canonical-name-you-attached-to-cloudfront79a59df900b949e55d96a1e698fbacedfd6e09d98eacf8f8d5218e7cd47ef2be"
            },
            "Action":"s3:GetObject",
            "Resource":"arn:aws:s3:::change-me-to-your-bucketname/*"
        }
    ]
}

答案 5 :(得分:0)

这是一个古老的问题,但是使用ruby sdk签名cloudfront url的方法还很少,因此添加了一些更新的帮助。现在有一个cloudfront sdk使这个过程变得非常简单:

signer = Aws::CloudFront::UrlSigner.new({
  key_pair_id: "my_key_pair_id"
  private_key_path: "./my_secret.pem" ,
  # Or, you can just provide the contents of the pem as string
  private_key = "--- long private key ---"
})

signed_url = signer.signed_url('http://my-cloudfront-domain.com/my/object/path', expires: 3600)