Cloudfront 与 S3 签名 URL 和 Boto3

问题描述 投票:0回答:3

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

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

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

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

python amazon-web-services amazon-s3 amazon-cloudfront boto3
3个回答
13
投票

boto3 文档中有一个部分显示 为 Amazon CloudFront 生成签名 URL:

以下示例演示如何为 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 不同,后者使用属于生成请求的用户的密钥来对请求进行身份验证。

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


3
投票

更新约翰的这个精彩答案,对于那些发现这个问题并看到来自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)

这只是更新答案,因此不会抛出弃用警告,并且不会考虑正在使用的部分的安全方面。


0
投票

如何签署 Cloudfront URL

CloudFrontSigner
文档字符串包含在 botocore GitHub 存储库中签署 Cloudfront URL 的这种方式。

第 1 步: 请务必

pip install rsa

第2步: 来自

CloudFrontSigner
文档字符串:

首先,您基于标准化 RSA 签名者创建一个云前端签名者:

import rsa


def rsa_signer(message):
    private_key = open('private_key.pem', 'r').read()
    return rsa.sign(
        message,
        rsa.PrivateKey.load_pkcs1(private_key.encode('utf8')),
        'SHA-1')  # CloudFront requires SHA-1 hash

然后你实际使用它:

from datetime import datetime
from botocore.signers import CloudFrontSigner


key_id = 'AKIAIOSFODNN7EXAMPLE'
cf_signer = CloudFrontSigner(key_id, rsa_signer)  # <- Use rsa_signer here

# Create a signed url that will be valid until the specfic expiry date
# provided using a canned policy.
expire_date = datetime(2017, 1, 1)

signed_url = cloudfront_signer.generate_presigned_url(
    url='http://d2949o5mkkp72v.cloudfront.net/hello.txt',
    date_less_than=expire_date)
print(signed_url)
© www.soinside.com 2019 - 2024. All rights reserved.