I'm serving some private HLS content with CloudFront, stored in a S3 bucket. All the HLS content is stored in a /hls/
directory at the root of my bucket.
I'm using this code for generating a /hls/*
(note the *
wildcard) pre-signed URL to access (the otherwise inaccessible) content:
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).
I have checked that I am following every guideline for configuring CloudFront and S3 for serving private content with pre-signed URLs. 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?
If you are using HLS, you cannot used presignedUrl, you must use a preSigned cookie:
https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-choosing-signed-urls-cookies.html
PreSignedUrl is only for accessing a specific file, so it does not work for HLS. You will have to specify a custom policy that includes the url you defined:
https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-setting-signed-cookie-canned-policy.html