generate_presigned_url boto3 在使用 cloudfront 调用时生成相同的 URL 直到过期
Posted
技术标签:
【中文标题】generate_presigned_url boto3 在使用 cloudfront 调用时生成相同的 URL 直到过期【英文标题】:generate_presigned_url boto3 generates same URL until expiry when called using cloudfront 【发布时间】:2021-10-20 23:00:58 【问题描述】:我正在尝试生成 s3 预签名 URL。逻辑是用 Lambda@Edge, python 3.7 编写的
def lambda_handler(event, context):
request = event['Records'][0]['cf']['request']
headers = request['headers']
s3 = boto3.client('s3',config=Config(signature_version='s3v4'))
url = s3.generate_presigned_url(ClientMethod='get_object',
Params='Bucket': 'BUCKET_NAME',
'Key':'abc.jpeg'
,
ExpiresIn=3600)
response =
'status': '302',
'statusDescription': 'Found',
'headers':
'location': [
'key': 'Location',
'value': url
]
return response
当我仅在 Lambda 中测试此代码时,每次调用都会得到不同的 URL。但是,如果我添加 cloudfront 并调用 cloudfront 域名,则会生成相同的 URL,直到 URL 过期。 为什么我没有像案例 1 那样为每个调用获得不同的 URL?
【问题讨论】:
您能否展示一下您的 CloudFront 预签名 URL 生成例程?我可以使用 Boto3 获得不同的 URL。 【参考方案1】:您需要为 CloudFront 创建一个签名者,并使用签名者的generate_presigned_url
。这个 sn-p 每次尝试都会生成不同的 URL。
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import os
from datetime import datetime, timedelta
from botocore.signers import CloudFrontSigner
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import serialization, hashes
from cryptography.hazmat.primitives.asymmetric import padding
from cf_url_gen.config import Bucket, Operation, config
class CFClient(object):
"""CloudFront client class
Creates a CloudFront client object for generting S3 resource URLs.
"""
def __init__(
self,
cf_key_id: str = os.getenv("CF_KEY_ID"),
cf_key_path: str = os.getenv("CF_KEY_PATH"),
cf_ttl_sec: int = 300,
):
"""The __init__ method for CFClient class
Args:
cf_key_id (str, optional): CloudFront key id, can be set via environment variable `CF_KEY_ID`
cf_key_path (str, optional): CloudFront key path, can be set via environment variable `CF_KEY_PATH`
cf_ttl_sec (int, optional): URL validity duration from UTC timestamp, default value 300 seconds
"""
with open(cf_key_path, "rb") as key_file:
_key = serialization.load_pem_private_key(key_file.read(), password=None, backend=default_backend())
self.signer = CloudFrontSigner(cf_key_id, lambda m: _key.sign(m, padding.PKCS1v15(), hashes.SHA1()))
self.ttl = cf_ttl_sec
def get_url_with_prefix(self, file_path: str, url_prefix: str, is_signed: bool = True) -> str:
"""Method for generating CloudFront URLs for file paths with given url prefix
Args:
file_path (str): Full file path in S3 bucket excluding bucket name
url_prefix (str): URL prefix to use for signing or generating S3 resource URL
is_signed (bool): Flag indicating whether URL should be signed or not
Returns:
CloudFront url string based on provided signing options
"""
if not is_signed:
return os.path.join(url_prefix, file_path)
else:
end_date = datetime.utcnow() + timedelta(seconds=self.ttl)
file_url = os.path.join(url_prefix, file_path)
return self.signer.generate_presigned_url(file_url, date_less_than=end_date)
注意: URL 前缀应该是您的 S3 存储桶的 CloudFront 域 URL,通常类似于 https://bucketname.yourdomain.com 或类似的东西。
【讨论】:
以上是关于generate_presigned_url boto3 在使用 cloudfront 调用时生成相同的 URL 直到过期的主要内容,如果未能解决你的问题,请参考以下文章
Mybatis自动生成的BO对象继承公共父类(BO中过滤掉公共属性)