Reputation: 416
Im trying to use signed cookies for my cloudfront distribution.
Im using cookie-signer to generate signed cookies. And the below script to fetch a file from cloud front
import requests
cookies = {
'CloudFront-Key-Pair-Id': 'APKXXXXXXXXXXX',
'CloudFront-Policy': u'eyJTdGF0ZW1lbnQiOlt7IlJlc291cmNlIjoiaHR0cHM6Ly9kNXRpdXV2ZjdodDlpLmNsb3VkZnJvbnQubmV0L21lZGlhL3Byb2ZpbGVfcGljLmpwZyIsIkNvbmRpdGlvbiI6eyJEYXRlTGVzc1RoYW4iOnsiQVdTOkVwb2NoVGltZSI6MTQ5Mjc2ODcwMH19fV19',
'CloudFront-Signature': u'ZVG-Pi7x~edJqERf99O9und0wYedB-SHMNKuHd4UpEDaPckYekGoAJ~q8tU0vQI4mS9odXITzAKl4v7tmfDjG1y9FmWaSxgf9h2jrssIk25Mswk3UXOV7wRNs9DiHpA3~D70qAWXGS9GVN4z3SvZ3xQv9bM1P50y2shNPlOCV4o5nAH56sYdvdJNjxSFxdoOUMuhxyrzf-Gv5fjNSzv2Dy43WY6rmpEMfh6L9Eb-2kcrS9p5rsK9MtAwpN8Frobt4bCuduQleb~DXZ~O~hoBGdO3RdyYWgMdTa~02PQl3st8eisBiH7XYy2GbOwPIN~M4m-UAs3ihL0ZWUjbkVDFCA__',
'Secure': 'True',
'HTTPOnly': 'True',
}
headers = {}
s = requests.Session()
res = s.get('http://XXXXXXX.cloudfront.net/media/profile_pic.jpg',
headers=headers, cookies=cookies)
print res
print res.content
Output:
<Response [403]>
<?xml version="1.0" encoding="UTF-8"?>
<Error><Code>AccessDenied</Code><Message>Access Denied</Message>
<RequestId>BBDBA8E7FEDA7759</RequestId><HostId>7Pt2/REdiugH5Te555/v004J6skQs9+ccncmXM74yHwPhQrSMJ9pavIj2QmPW6g2QsnnEYGxitc=</HostId></Error>
Added user to trusted signer for the cloudfront distribution and generated a key-pair-id for cloudfront.
Can someone help me with this ? Thanks in advance
Upvotes: 4
Views: 3389
Reputation: 885
This worked for me with the GitHub gist in your link. The expiration time needs to be provided in epoch seconds and the url passed in must be the full CloudFront url (e.g. https://example.com/my/s3/object.png
)
import datetime
ex = datetime.datetime.utcnow() + datetime.timedelta(minutes=expire_min)
c = create_signed_cookies(url, int(ex.strftime('%s')))
Your S3 bucket policy needs to allow GetObject from the CloudFront Origin Access Identity assigned to your CloudFront distribution.
{
"Version": "2008-10-17",
"Id": "PolicyForCloudFrontPrivateContent",
"Statement": [
{
"Sid": "1",
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::cloudfront:user/CloudFront Origin Access Identity XXXXXXXXXXXXXXX"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::my-bucket/*"
}
]
}
Your key pair ID needs to refer to one you created like this (you must be signed in as the root account): https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-trusted-signers.html#private-content-creating-cloudfront-key-pairs-procedure
Upvotes: 2
Reputation: 724
Your error is actually an S3 error, not a Cloudfront (CF) error. Did you create a bucket policy that gives GetObject
access?
{
"Version":"2012-10-17",
"Statement":[
{
"Sid":"AddPerm",
"Effect":"Allow",
"Principal": "*",
"Action":["s3:GetObject"],
"Resource":["arn:aws:s3:::examplebucket/*"]
}
]
}
See http://docs.aws.amazon.com/AmazonS3/latest/dev/example-bucket-policies.html
If you're using S3 as the origin in CF then you'll want to create an Origin Access Identity and make sure to give access to it in your S3 Bucket Policy. (see http://docs.aws.amazon.com/AmazonS3/latest/dev/example-bucket-policies.html#example-bucket-policies-use-case-6)
If you're trying to serve the page using S3 static web hosting then I suggest either whitelisting Cloudfront IPs in your policy or adding an Origin Custom Header
in CF such as referer
and then looking for the header in your bucket policy. (see http://docs.aws.amazon.com/AmazonS3/latest/dev/example-bucket-policies.html#example-bucket-policies-use-case-4)
As a sanity check, you might want to try to generate a signed URL using the AWS-CLI. (see http://docs.aws.amazon.com/cli/latest/reference/cloudfront/sign.html)
Upvotes: 1