~tribaal/txaws/xss-hardening

« back to all changes in this revision

Viewing changes to txaws/storage/client.py

Merged 416109-arbitrary-endpoints [r=therve,jkakar] [f=416109].

The primary change of this branch is support of arbitrary endpoints (needed for
the support of Eucalyptus). In addition, the following was also performed:
 * Added a parse utility function from Twisted
 * Created a testing subpackage for use by txAWS unit tests
 * Created a service module for abstracting regions and associated
   serices/credentials

Show diffs side-by-side

added added

removed removed

Lines of Context:
7
7
functionality in this wrapper.
8
8
"""
9
9
 
10
 
from base64 import b64encode
11
 
from hashlib import md5
12
 
 
13
10
from epsilon.extime import Time
14
11
 
15
12
from twisted.web.client import getPage
16
13
from twisted.web.http import datetimeToString
17
14
 
18
 
from txaws.credentials import AWSCredentials
 
15
from txaws.service import AWSServiceEndpoint
19
16
from txaws.util import XML, calculate_md5
20
17
 
21
18
 
25
22
class S3Request(object):
26
23
 
27
24
    def __init__(self, verb, bucket=None, object_name=None, data='',
28
 
                 content_type=None,
29
 
        metadata={}, root_uri='https://s3.amazonaws.com',  creds=None):
 
25
                 content_type=None, metadata={}, creds=None, endpoint=None):
30
26
        self.verb = verb
31
27
        self.bucket = bucket
32
28
        self.object_name = object_name
33
29
        self.data = data
34
30
        self.content_type = content_type
35
31
        self.metadata = metadata
36
 
        self.root_uri = root_uri
37
32
        self.creds = creds
 
33
        self.endpoint = endpoint
38
34
        self.date = datetimeToString()
39
35
 
40
 
    def get_uri_path(self):
 
36
    def get_path(self):
41
37
        path = '/'
42
38
        if self.bucket is not None:
43
39
            path += self.bucket
46
42
        return path
47
43
 
48
44
    def get_uri(self):
49
 
        return self.root_uri + self.get_uri_path()
 
45
        if self.endpoint is None:
 
46
            self.endpoint = AWSServiceEndpoint()
 
47
        self.endpoint.set_path(self.get_path())
 
48
        return self.endpoint.get_uri()
50
49
 
51
50
    def get_headers(self):
52
51
        headers = {'Content-Length': len(self.data),
66
65
        return headers
67
66
 
68
67
    def get_canonicalized_resource(self):
69
 
        return self.get_uri_path()
 
68
        return self.get_path()
70
69
 
71
70
    def get_canonicalized_amz_headers(self, headers):
72
71
        result = ''
76
75
        return ''.join('%s:%s\n' % (name, value) for name, value in headers)
77
76
 
78
77
    def get_signature(self, headers):
79
 
        text = self.verb + '\n'
80
 
        text += headers.get('Content-MD5', '') + '\n'
81
 
        text += headers.get('Content-Type', '') + '\n'
82
 
        text += headers.get('Date', '') + '\n'
83
 
        text += self.get_canonicalized_amz_headers(headers)
84
 
        text += self.get_canonicalized_resource()
 
78
        text = (self.verb + '\n' + 
 
79
                headers.get('Content-MD5', '') + '\n' +
 
80
                headers.get('Content-Type', '') + '\n' +
 
81
                headers.get('Date', '') + '\n' +
 
82
                self.get_canonicalized_amz_headers(headers) +
 
83
                self.get_canonicalized_resource())
85
84
        return self.creds.sign(text)
86
85
 
87
86
    def submit(self):
94
93
 
95
94
class S3(object):
96
95
 
97
 
    root_uri = 'https://s3.amazonaws.com/'
98
96
    request_factory = S3Request
99
97
 
100
 
    def __init__(self, creds):
 
98
    def __init__(self, creds, endpoint):
101
99
        self.creds = creds
 
100
        self.endpoint = endpoint
102
101
 
103
102
    def make_request(self, *a, **kw):
104
103
        """
105
104
        Create a request with the arguments passed in.
106
105
 
107
 
        This uses the request_factory attribute, adding the credentials to the
108
 
        arguments passed in.
 
106
        This uses the request_factory attribute, adding the creds and endpoint
 
107
        to the arguments passed in.
109
108
        """
110
 
        return self.request_factory(creds=self.creds, *a, **kw)
 
109
        return self.request_factory(creds=self.creds, endpoint=self.endpoint,
 
110
                                    *a, **kw)
111
111
 
112
112
    def _parse_bucket_list(self, response):
113
113
        """