简体   繁体   English

boto3:生成通配符 CloudFront 预签名 URL

[英]boto3: generate wildcard CloudFront presigned URL

I'm serving some private HLS content with CloudFront, stored in a S3 bucket.我正在使用 CloudFront 提供一些存储在 S3 存储桶中的私有 HLS 内容。 All the HLS content is stored in a /hls/ directory at the root of my bucket.所有 HLS 内容都存储在我的存储桶根目录下的/hls/目录中。

I'm using this code for generating a /hls/* (note the * wildcard) pre-signed URL to access (the otherwise inaccessible) content:我正在使用此代码生成/hls/* (注意*通配符)预签名 URL 以访问(否则无法访问)内容:

import datetime

from botocore.signers import CloudFrontSigner
from cryptography.hazmat.backends import default_backend
from cryptography.hazmat.primitives import hashes, serialization
from cryptography.hazmat.primitives.asymmetric import padding

from my_django_project.settings import (
    AWS_CLOUDFRONT_DOMAIN_NAME,
    AWS_CLOUDFRONT_KEY_ID,
    AWS_CLOUDFRONT_KEY_PATH,
)


def rsa_signer(message):
    with open(AWS_CLOUDFRONT_KEY_PATH, "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())


def get_signed_url():
    key_id = AWS_CLOUDFRONT_KEY_ID
    url = f"https://{AWS_CLOUDFRONT_DOMAIN_NAME}/hls/*"
    expire_datetime = datetime.datetime.now() + datetime.timedelta(minutes=5)
    cloudfront_signer = CloudFrontSigner(key_id, rsa_signer)
    signed_url = cloudfront_signer.generate_presigned_url(
        url,
        date_less_than=expire_datetime,
    )
    return signed_url

This code effectively generates a URL but CloudFront responds with a 403 Access Denied error when I try to access the https://{AWS_CLOUDFRONT_DOMAIN_NAME}/hls/index.m3u8 URL (which is one of the files stored in the /hls/ directory).此代码有效地生成了一个 URL,但当我尝试访问https://{AWS_CLOUDFRONT_DOMAIN_NAME}/hls/index.m3u8 URL(它是存储在/hls/目录中的文件之一)时,CloudFront 以 403 Access Denied 错误响应.

I have checked that I am following every guideline for configuring CloudFront and S3 for serving private content with pre-signed URLs.我已经检查过我是否遵循了配置 CloudFront 和 S3 以提供带有预签名 URL 的私有内容的所有指南。 I am starting to suspect that this wildcard thing is the problem.我开始怀疑这个通配符是问题所在。

I am not sure what I can do to solve the issue.我不确定我能做些什么来解决这个问题。 Any idea?任何的想法?

You need to be working in UTC timezone.您需要在 UTC 时区工作。 Replace datetime.datetime.now() with datetime.datetime.utcnow() and it should work properly.更换datetime.datetime.now()datetime.datetime.utcnow()它应该正常工作。

If you are using HLS, you cannot used presignedUrl, you must use a preSigned cookie:如果您使用 HLS,则不能使用 presignedUrl,您必须使用 preSigned cookie:

https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-choosing-signed-urls-cookies.html https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-choosing-signed-urls-cookies.html

Use signed cookies in the following cases:

You want to provide access to multiple restricted files, for example, all of the files for a video in HLS format or all of the files in the subscribers' area of website.

You don't want to change your current URLs.

PreSignedUrl is only for accessing a specific file, so it does not work for HLS. PreSignedUrl 仅用于访问特定文件,因此它不适用于 HLS。 You will have to specify a custom policy that includes the url you defined:您必须指定一个包含您定义的 url 的自定义策略:

https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-setting-signed-cookie-canned-policy.html https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-setting-signed-cookie-canned-policy.html

Here's some example code I found elsewhere on Stack Overflow that does this all in Python (since the example code from CF doesn't show this level of detail): Creating Signed URLs for Amazon CloudFront Although I ended up doing a hybrid;下面是我在 Stack Overflow 的其他地方找到的一些示例代码,它们全部使用 Python 完成(因为来自 CF 的示例代码没有显示这种详细程度): 为 Amazon CloudFront 创建签名 URL虽然我最终做了一个混合; I used the key/signing handling from the rsa_signer function in the canned policy example from Amazon in place of the sign_string function in the example I linked.我使用来自 Amazon 的罐头策略示例中的 rsa_signer 函数的密钥/签名处理代替了我链接的示例中的 sign_string 函数。

HOWEVER, if you want to use wildcards, be sure to make it a custom policy by including the base64-encoded policy statement thing as Policy=$policy in your signed url between Expires and Signature, as specified in the link Marc posted.但是,如果您想使用通配符,请确保将 base64 编码的策略声明内容作为 Policy=$policy 包含在 Expires 和 Signature 之间的签名 URL 中,使其成为自定义策略,如 Marc 发布的链接中所述。 I didn't originally read the docs closely enough and was getting pretty frustrated until I went back and read more carefully and included this.我最初没有足够仔细地阅读文档并且感到非常沮丧,直到我回去更仔细地阅读并将其包含在内。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM