aws / aws-sdk

Landing page for the AWS SDKs on GitHub
https://aws.amazon.com/tools/
Other
68 stars 13 forks source link

Created CloudFront signed cookies with boto3 #437

Open aBurmeseDev opened 1 year ago

aBurmeseDev commented 1 year ago

Original Issue: https://github.com/boto/boto3/issues/706

ronalddas commented 11 months ago

its 2023 now, can we expect this feature soon?

soccer99 commented 6 months ago

Please add this!

shonteag commented 6 months ago

I could also use this for video content distribution via CloudFront. Can we get this prioritized?

dschnabel commented 4 months ago

I could really use this now. I don't understand why it's taking so long.

dschnabel commented 4 months ago

I might have found a workaround until this is officially supported:

  1. Create a presigned url using boto3 similar to this example. This gives you a URL with three parameters: Signature, Key-Pair-Id, Expires (canned policy), Policy (custom policy)
  2. Extract the three values and use them to set these cookie attributes: CloudFront-Signature, CloudFront-Key-Pair-Id, CloudFront-Expires (canned policy), CloudFront-Policy (custom policy). See Using signed cookies.
convexset commented 3 months ago

Quite amazing that this is still not done... I was just goofing around with this, so here is the workaround articulated by @dschnabel in code:

from datetime import datetime, timedelta

policy = {
    'Statement': [
        {
            'Resource': 'https://dxxxxxxxxxx.cloudfront.net/path/to/stuff/*',
            'Condition': {
                'DateLessThan': {
                    'AWS:EpochTime': int((datetime.now() + timedelta(days = 1)).timestamp())
                }
            },
        }
    ]
}
# Most of https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/cloudfront.html#generate-a-signed-url-for-amazon-cloudfront

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'  # not important, but a required parameter
from urllib.parse import urlparse, parse_qs

signed_url = cloudfront_signer.generate_presigned_url(
    url=url,
    policy=json.dumps(policy)
)
print(signed_url)

parsed_url = urlparse(signed_url)
cookies = {
    f'CloudFront-{k}': v[0] for k,v in parse_qs(parsed_url.query).items()
}
cookies
import requests

headers = {
    'Cookie': '; '.join([f'{k}={v}' for k, v in cookies.items()])
}

r = requests.get('https://dxxxxxxxxxx.cloudfront.net/path/to/stuff/sketchy-stream.m3u8', headers=headers)
r.status_code