尝试设置完全签名和保护的 Cloudfront URL。 例如。我希望需要应用程序代码才能访问该资源。
通过 S3 直接分发,我可以简单地通过以下方式完成此操作:
s3 = boto3.client('s3')
s3.generate_presigned_url('get_object', Params={'Bucket': bucket, 'Key': unique_key}, ExpiresIn=186400)
但我似乎无法弄清楚如何在请求 Cloudfront URL 时创建等效的签名 URL。
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 的客户可能有用。但这只是猜测。
更新约翰的这个精彩答案,对于那些发现这个问题并看到来自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)
这只是更新答案,因此不会抛出弃用警告,并且不会考虑正在使用的部分的安全方面。
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)