Cloudfront 与 S3 签名 URL 和 Boto3

Cloudfront vs S3 signed URL and Boto3

尝试设置一个完全签名和保护的云端URL。 例如。我想要一个应用程序代码来访问资源。

通过 S3 直接分发,我可以通过以下方式轻松完成此操作:

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

但我似乎无法弄清楚如何在请求云端 URL 时创建等效的签名 URL。

boto3 文档中有一节显示 Generate a signed URL for Amazon CloudFront:

The following example shows how to generate a signed URL for Amazon CloudFront. Note that you will need the cryptography library to follow this example:

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

您会注意到上面的代码使用 Public/Private 密钥对创建 CloudFront 签名 URL。这意味着只要知道密钥对,任何应用程序都可以生成签名的 URL。

这与在 Amazon S3 中创建 Signed URLs 不同,后者使用属于生成请求的用户的密钥来验证请求。

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

更新 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)

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