尝试设置完全签名和保护的云端URL。 例如。我想要一个应用程序代码来访问资源。
使用S3直接分发,我可以简单地使用:
s3 = boto3.client('s3')
s3.generate_presigned_url('get_object', Params={'Bucket': bucket, 'Key': unique_key}, ExpiresIn=186400)
但我似乎无法弄清楚在请求云端网址时如何创建等效的签名网址。
答案 0 :(得分:6)
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()
)
signer = private_key.signer(padding.PKCS1v15(), hashes.SHA1())
signer.update(message)
return signer.finalize()
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 vs S3
您会注意到上述代码使用公钥/私钥对来创建CloudFront签名URL。这意味着只要知道密钥对,任何应用程序都可以生成签名URL。
这与在Amazon S3中创建签名URL不同,后者使用属于生成请求的用户的密钥来验证请求。
为什么他们不一样?我不知道,但是keypair选项允许使用CloudFront而不需要任何IAM用户,这对仅使用CloudFront的客户可能很有用。但这只是猜测。
答案 1 :(得分:0)
对于那些发现此错误并看到来自Python加密模块的警告消息的人,请更新John的精彩回答。不推荐使用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)
这只会更新答案,因此不会引发弃用警告,也不会关注所使用部件的安全性。