【问题标题】:Cloudfront vs S3 signed URL and Boto3Cloudfront vs S3 签名 URL 和 Boto3
【发布时间】:2017-11-20 14:57:46
【问题描述】:

尝试设置完全签名和受保护的云端 URL。 例如。我希望需要一个应用程序代码才能访问该资源。

使用 S3 直接分发,我可以简单地做到这一点:

s3 = boto3.client('s3')    
s3.generate_presigned_url('get_object', Params={'Bucket': bucket, 'Key': unique_key}, ExpiresIn=186400)

但在请求云端 URL 时,我似乎不知道如何创建等效的签名 URL。

【问题讨论】:

    标签: python amazon-web-services amazon-s3 amazon-cloudfront boto3


    【解决方案1】:

    boto3 文档有一个部分显示Generate a signed URL for Amazon CloudFront:

    以下示例显示了如何为 Amazon CloudFront 生成签名 URL。请注意,您将需要密码库来遵循此示例:

    import datetime
    
    from cryptography.hazmat.backends import default_backend
    from cryptography.hazmat.primitives import hashes
    from cryptography.hazmat.primitives import serialization
    from cryptography.hazmat.primitives.asymmetric import padding
    from botocore.signers import CloudFrontSigner
    def rsa_signer(message):
        with open('path/to/key.pem', 'rb') as key_file:
            private_key = serialization.load_pem_private_key(
                key_file.read(),
                password=None,
                backend=default_backend()
            )
        return private_key.sign(message, padding.PKCS1v15(), hashes.SHA1())
    
    key_id = 'AKIAIOSFODNN7EXAMPLE'
    url = 'http://d2949o5mkkp72v.cloudfront.net/hello.txt'
    expire_date = datetime.datetime(2017, 1, 1)
    
    cloudfront_signer = CloudFrontSigner(key_id, rsa_signer)
    
    # Create a signed url that will be valid until the specfic expiry date
    # provided using a canned policy.
    signed_url = cloudfront_signer.generate_presigned_url(
        url, date_less_than=expire_date)
    print(signed_url)
    

    Cloudfront 与 S3

    您会注意到上述代码使用公钥/私钥对来创建 CloudFront 签名 URL。这意味着任何应用程序只要知道密钥对就可以生成签名 URL。

    这与在 Amazon S3 中创建签名 URL 不同,后者使用属于生成请求的用户的密钥对请求进行身份验证。

    为什么它们不同?我不知道,但密钥对选项允许在不需要任何 IAM 用户的情况下使用 CloudFront,这可能对只使用 CloudFront 的客户有用。但这只是猜测。

    【讨论】:

    • 谢谢,我当然看到了。但这与直接 S3 URL 不同,需要使用我的私有 RSA 签名密钥。这是唯一的方法吗?为什么 S3 和 Cloudfront 之间存在差异?这对我来说毫无意义,也许你可以解释一下差异。
    • 我不知道为什么,但我已经添加了关于差异的文字。
    • 但是boto3在通过签名的url访问文件上传时得到403。
    • @JAR.JAR.beans s3 和 cloudfront 的区别在于 cloudfront 将 s3 的内容缓存在边缘位置,以减少获取对象的延迟。使用签名 url 的原因是因为您不想随时向用户提供到 s3 的直接链接。因此,您创建一个指向 s3 存储桶的云端分发,创建一个签名的 url(签名的 url 在几分钟或几小时内到期,并且在对象的整个生命周期内都无效)。您可以在他们的文档中了解更多信息:docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/…
    • @jiamo s3 bucket 中的对象默认是私有的。您需要确保写入的对象具有公共 ACL,并启用允许在存储桶中创建公共对象的选项。
    【解决方案2】:

    由 John 更新这个精彩的答案,对于那些发现此问题并看到来自 Python 中的密码学模块的警告消息的人。根据文档,signer 已被弃用,取而代之的是序列化对象上的sign 函数.

    import datetime
    
    from cryptography.hazmat.backends import default_backend
    from cryptography.hazmat.primitives import hashes
    from cryptography.hazmat.primitives import serialization
    from cryptography.hazmat.primitives.asymmetric import padding
    from botocore.signers import CloudFrontSigner
    def rsa_signer(message):
       with open('path/to/key.pem', 'rb') as key_file:
           private_key = serialization.load_pem_private_key(
               key_file.read(),
               password=None,
               backend=default_backend()
           )
       return private_key.sign(message, padding.PKCS1v15(), hashes.SHA1())
    
    key_id = 'AKIAIOSFODNN7EXAMPLE'
    url = 'http://d2949o5mkkp72v.cloudfront.net/hello.txt'
    expire_date = datetime.datetime(2017, 1, 1)
    
    cloudfront_signer = CloudFrontSigner(key_id, rsa_signer)
    
    # Create a signed url that will be valid until the specfic expiry date
    # provided using a canned policy.
    signed_url = cloudfront_signer.generate_presigned_url(
         url, date_less_than=expire_date)
    print(signed_url)
    

    这只是更新答案,因此它不会抛出弃用警告,也不会查看正在使用的部件的安全方面。

    【讨论】:

    • 请不要添加新答案,请编辑现有答案。
    • 明白,没有意识到我可以选择成为新的贡献者..
    猜你喜欢
    • 2017-09-28
    • 2015-10-10
    • 2015-05-21
    • 2021-02-03
    • 2018-12-25
    • 2023-03-21
    • 2017-02-26
    • 2018-12-06
    • 1970-01-01
    相关资源
    最近更新 更多