Login

Securely Signed S3 Links With Expiration

Author:
pjs
Posted:
November 8, 2008
Language:
Python
Version:
1.0
Score:
1 (after 1 ratings)

I couldn't find a Python implementation of this, so I threw this class together real quick.

This will let you share "private" files on S3 via a signed request. It will also have an expiration on the link, so it is only valid until a certain time period.

Example Usage:

s3 = SecureS3('AWS_ACCESS_KEY', 'AWS_SECRET_ACCESS_KEY')
s3.get_auth_link('your_bucket', 'your_file')

That would return your secure link. eg,

http://your_bucket.s3.amazonaws.com/your_file?AWSAccessKeyId=AWS_ACCESS_KEY&Expires=1226198694&Signature=IC5ifWgiuOZ1IcWXRltHoETYP1A%3D

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import hmac
import time
import base64
import urllib
import hashlib


class SecureS3(object):
    def __init__(self, key, secret_key):
        ''' key: S3 Access Key (login)
            secret_key: S3 Secret Access Key (password)
        '''
        self.key = key
        self.secret_key = secret_key

    def gen_signature(self, string_to_sign):
        return base64.encodestring(
            hmac.new(
                self.secret_key,
                string_to_sign,
                hashlib.sha1
            ).digest()
        ).strip()

    def get_auth_link(self, bucket, filename, expires=300, timestamp=None):
        ''' Return a secure S3 link with an expiration on the download.

            bucket: Bucket name
            filename: file path
            expires: Seconds from NOW the link expires
            timestamp: Epoch timestamp. If present, "expires" will not be used.
        '''
        filename = urllib.quote_plus(filename)
        filename = filename.replace('%2F', '/')
        path = '/%s/%s' % (bucket, filename)

        if timestamp is not None:
            expire_time = float(timestamp)
        else:
            expire_time = time.time() + expires

        expire_str = '%.0f' % (expire_time)
        string_to_sign = u'GET\n\n\n%s\n%s' % (expire_str, path)
        params = {
            'AWSAccessKeyId': self.key,
            'Expires': expire_str,
            'Signature': self.gen_signature(string_to_sign.encode('utf-8')),
        }

        return 'http://%s.s3.amazonaws.com/%s?%s' % (
                                    bucket, filename, urllib.urlencode(params))

More like this

  1. Template tag - list punctuation for a list of items by shapiromatron 3 months, 1 week ago
  2. JSONRequestMiddleware adds a .json() method to your HttpRequests by cdcarter 3 months, 2 weeks ago
  3. Serializer factory with Django Rest Framework by julio 10 months, 1 week ago
  4. Image compression before saving the new model / work with JPG, PNG by Schleidens 11 months ago
  5. Help text hyperlinks by sa2812 11 months, 3 weeks ago

Comments

Please login first before commenting.