esdk-obs-python 3.25.3__tar.gz → 3.26.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (35) hide show
  1. {esdk-obs-python-3.25.3 → esdk-obs-python-3.26.2}/PKG-INFO +10 -11
  2. {esdk-obs-python-3.25.3 → esdk-obs-python-3.26.2}/esdk_obs_python.egg-info/PKG-INFO +10 -11
  3. {esdk-obs-python-3.25.3 → esdk-obs-python-3.26.2}/esdk_obs_python.egg-info/not-zip-safe +1 -1
  4. {esdk-obs-python-3.25.3 → esdk-obs-python-3.26.2}/obs/__init__.py +3 -2
  5. {esdk-obs-python-3.25.3 → esdk-obs-python-3.26.2}/obs/auth.py +278 -278
  6. {esdk-obs-python-3.25.3 → esdk-obs-python-3.26.2}/obs/bulktasks.py +218 -218
  7. {esdk-obs-python-3.25.3 → esdk-obs-python-3.26.2}/obs/cache.py +44 -44
  8. {esdk-obs-python-3.25.3 → esdk-obs-python-3.26.2}/obs/client.py +47 -31
  9. {esdk-obs-python-3.25.3 → esdk-obs-python-3.26.2}/obs/const.py +8 -5
  10. {esdk-obs-python-3.25.3 → esdk-obs-python-3.26.2}/obs/convertor.py +27 -9
  11. {esdk-obs-python-3.25.3 → esdk-obs-python-3.26.2}/obs/extension.py +152 -152
  12. {esdk-obs-python-3.25.3 → esdk-obs-python-3.26.2}/obs/http2.py +169 -169
  13. {esdk-obs-python-3.25.3 → esdk-obs-python-3.26.2}/obs/ilog.py +147 -147
  14. esdk-obs-python-3.26.2/obs/loadtoken.py +341 -0
  15. {esdk-obs-python-3.25.3 → esdk-obs-python-3.26.2}/obs/locks.py +28 -28
  16. {esdk-obs-python-3.25.3 → esdk-obs-python-3.26.2}/obs/model.py +37 -8
  17. {esdk-obs-python-3.25.3 → esdk-obs-python-3.26.2}/obs/obs_cipher_suite.py +358 -358
  18. {esdk-obs-python-3.25.3 → esdk-obs-python-3.26.2}/obs/posix_transfer.py +83 -83
  19. {esdk-obs-python-3.25.3 → esdk-obs-python-3.26.2}/obs/progress.py +83 -83
  20. {esdk-obs-python-3.25.3 → esdk-obs-python-3.26.2}/obs/scheduler.py +127 -127
  21. {esdk-obs-python-3.25.3 → esdk-obs-python-3.26.2}/obs/searchmethod.py +41 -41
  22. {esdk-obs-python-3.25.3 → esdk-obs-python-3.26.2}/obs/transfer.py +832 -830
  23. {esdk-obs-python-3.25.3 → esdk-obs-python-3.26.2}/obs/workflow.py +424 -424
  24. {esdk-obs-python-3.25.3 → esdk-obs-python-3.26.2}/setup.cfg +4 -4
  25. {esdk-obs-python-3.25.3 → esdk-obs-python-3.26.2}/setup.py +1 -1
  26. esdk-obs-python-3.25.3/obs/loadtoken.py +0 -184
  27. {esdk-obs-python-3.25.3 → esdk-obs-python-3.26.2}/esdk_obs_python.egg-info/SOURCES.txt +0 -0
  28. {esdk-obs-python-3.25.3 → esdk-obs-python-3.26.2}/esdk_obs_python.egg-info/dependency_links.txt +0 -0
  29. {esdk-obs-python-3.25.3 → esdk-obs-python-3.26.2}/esdk_obs_python.egg-info/requires.txt +0 -0
  30. {esdk-obs-python-3.25.3 → esdk-obs-python-3.26.2}/esdk_obs_python.egg-info/top_level.txt +0 -0
  31. {esdk-obs-python-3.25.3 → esdk-obs-python-3.26.2}/obs/bucket.py +0 -0
  32. {esdk-obs-python-3.25.3 → esdk-obs-python-3.26.2}/obs/crc64mod.py +0 -0
  33. {esdk-obs-python-3.25.3 → esdk-obs-python-3.26.2}/obs/crypto_client.py +0 -0
  34. {esdk-obs-python-3.25.3 → esdk-obs-python-3.26.2}/obs/http.py +0 -0
  35. {esdk-obs-python-3.25.3 → esdk-obs-python-3.26.2}/obs/util.py +0 -0
@@ -1,11 +1,10 @@
1
- Metadata-Version: 2.1
2
- Name: esdk-obs-python
3
- Version: 3.25.3
4
- Summary: OBS Python SDK
5
- Home-page: UNKNOWN
6
- License: Apache-2.0
7
- Keywords: obs,python
8
- Platform: Independant
9
-
10
- OBS Python SDK
11
-
1
+ Metadata-Version: 2.1
2
+ Name: esdk-obs-python
3
+ Version: 3.26.2
4
+ Summary: OBS Python SDK
5
+ Home-page:
6
+ License: Apache-2.0
7
+ Keywords: obs,python
8
+ Platform: Independant
9
+
10
+ OBS Python SDK
@@ -1,11 +1,10 @@
1
- Metadata-Version: 2.1
2
- Name: esdk-obs-python
3
- Version: 3.25.3
4
- Summary: OBS Python SDK
5
- Home-page: UNKNOWN
6
- License: Apache-2.0
7
- Keywords: obs,python
8
- Platform: Independant
9
-
10
- OBS Python SDK
11
-
1
+ Metadata-Version: 2.1
2
+ Name: esdk-obs-python
3
+ Version: 3.26.2
4
+ Summary: OBS Python SDK
5
+ Home-page:
6
+ License: Apache-2.0
7
+ Keywords: obs,python
8
+ Platform: Independant
9
+
10
+ OBS Python SDK
@@ -23,7 +23,7 @@ from obs.model import TopicConfiguration, FunctionGraphConfiguration, FilterRule
23
23
  from obs.model import Options, PutObjectHeader, AppendObjectHeader, AppendObjectContent, RedirectAllRequestTo
24
24
  from obs.model import Redirect, RoutingRule, Tag, TagInfo, Transition, NoncurrentVersionTransition, Rule, Versions, AbortIncompleteMultipartUpload
25
25
  from obs.model import Object, WebsiteConfiguration, Logging, CompleteMultipartUploadRequest, DeleteObjectsRequest,CustomDomainConfiguration
26
- from obs.model import ListMultipartUploadsRequest, GetObjectRequest, UploadFileHeader, Payer
26
+ from obs.model import ListMultipartUploadsRequest, GetObjectRequest, UploadFileHeader, Payer, ClientVerify
27
27
  from obs.model import ExtensionHeader, FetchStatus, BucketAliasModel, ListBucketAliasModel
28
28
  from obs.workflow import WorkflowClient
29
29
  from obs.crypto_client import CryptoObsClient
@@ -97,5 +97,6 @@ __all__ = [
97
97
  'CtrRSACipherGenerator',
98
98
  'BucketAliasModel',
99
99
  'ListBucketAliasModel',
100
- 'CustomDomainConfiguration'
100
+ 'CustomDomainConfiguration',
101
+ 'ClientVerify'
101
102
  ]
@@ -1,278 +1,278 @@
1
- #!/usr/bin/python
2
- # -*- coding:utf-8 -*-
3
- # Copyright 2019 Huawei Technologies Co.,Ltd.
4
- # Licensed under the Apache License, Version 2.0 (the "License"); you may not use
5
- # this file except in compliance with the License. You may obtain a copy of the
6
- # License at
7
-
8
- # http://www.apache.org/licenses/LICENSE-2.0
9
-
10
- # Unless required by applicable law or agreed to in writing, software distributed
11
- # under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12
- # CONDITIONS OF ANY KIND, either express or implied. See the License for the
13
- # specific language governing permissions and limitations under the License.
14
-
15
- import hashlib
16
- import hmac
17
- import binascii
18
- from obs import util
19
- from obs import const
20
-
21
-
22
- class Authentication(object):
23
-
24
- def __init__(self, ak, sk, path_style, ha, server, is_cname):
25
- self.ak = ak
26
- self.sk = sk
27
- self.path_style = path_style
28
- self.ha = ha
29
- self.server = server
30
- self.is_cname = is_cname
31
-
32
- def doAuth(self, method, bucket, key, path_args, headers, expires=None):
33
- ret = self.getSignature(method, bucket, key, path_args, headers, expires)
34
- return {
35
- const.AUTHORIZATION_HEADER: '%s %s:%s' % (self.ha.auth_prefix(), self.ak, ret['Signature']),
36
- const.CANONICAL_STRING: ret[const.CANONICAL_STRING]
37
- }
38
-
39
- def getSignature(self, method, bucket, key, path_args, headers, expires=None):
40
- canonical_string = self.__make_canonical_string(method, bucket, key, path_args, headers, expires)
41
- return {
42
- 'Signature': self.hmacSha128(canonical_string),
43
- const.CANONICAL_STRING: canonical_string
44
- }
45
-
46
- def hmacSha128(self, canonical_string):
47
- if const.IS_PYTHON2:
48
- hashed = hmac.new(self.sk, canonical_string, hashlib.sha1)
49
- encode_canonical = binascii.b2a_base64(hashed.digest())[:-1]
50
- else:
51
- hashed = hmac.new(self.sk.encode('UTF-8'), canonical_string.encode('UTF-8'), hashlib.sha1)
52
- encode_canonical = binascii.b2a_base64(hashed.digest())[:-1].decode('UTF-8')
53
-
54
- return encode_canonical
55
-
56
- def __make_canonical_string(self, method, bucket_name, key, path_args, headers, expires=None):
57
- interesting_headers = self.__make_canonicalstring_interesting_headers(headers, expires)
58
- key_list = sorted(interesting_headers.keys())
59
- str_list = self.__make_canonicalstring_str_list(key_list, method, interesting_headers)
60
- URI = ''
61
- _bucket_name = self.server if self.is_cname else bucket_name
62
- if _bucket_name:
63
- URI += '/'
64
- URI += _bucket_name
65
- if not self.path_style or self.is_cname:
66
- URI += '/'
67
-
68
- if key:
69
- if not URI.endswith('/'):
70
- URI += '/'
71
- URI += util.encode_object_key(key)
72
-
73
- if URI:
74
- str_list.append(URI)
75
- else:
76
- str_list.append('/')
77
-
78
- if path_args:
79
- e = '?'
80
- cannoList = sorted(path_args.items(), key=lambda d: d[0])
81
- for path_key, path_value in cannoList:
82
- if path_key.lower() in const.ALLOWED_RESOURCE_PARAMTER_NAMES or path_key.lower().startswith(
83
- self.ha._get_header_prefix()):
84
- path_key = util.encode_item(path_key, '/')
85
- if path_value is None:
86
- e += path_key + '&'
87
- continue
88
- e += path_key + '=' + util.to_string(path_value) + '&'
89
-
90
- e = e[:-1]
91
- str_list.append(e)
92
- return ''.join(str_list)
93
-
94
- def __make_canonicalstring_interesting_headers(self, headers, expires):
95
- interesting_headers = {}
96
- if isinstance(headers, dict):
97
- for hash_key in headers.keys():
98
- lk = hash_key.lower()
99
- if lk in const.CONTENT_LIST or lk.startswith(self.ha._get_header_prefix()):
100
- s = headers.get(hash_key)
101
- interesting_headers[lk] = ''.join(s)
102
-
103
- key_list = interesting_headers.keys()
104
-
105
- if self.ha.date_header() in key_list:
106
- interesting_headers[const.DATE_HEADER.lower()] = ''
107
-
108
- if expires:
109
- interesting_headers[const.DATE_HEADER.lower()] = expires
110
-
111
- if const.CONTENT_TYPE_HEADER.lower() not in key_list:
112
- interesting_headers[const.CONTENT_TYPE_HEADER.lower()] = ''
113
-
114
- if const.CONTENT_MD5_HEADER.lower() not in key_list:
115
- interesting_headers[const.CONTENT_MD5_HEADER.lower()] = ''
116
-
117
- return interesting_headers
118
-
119
- def __make_canonicalstring_str_list(self, keylist, method, interesting_headers):
120
- str_list = [method + '\n']
121
- for k in keylist:
122
- header_key = util.to_string(k)
123
- val = '' if interesting_headers[header_key] is None else interesting_headers[header_key]
124
- if header_key.startswith(self.ha._get_meta_header_prefix()):
125
- str_list.append(header_key + ':' + util.to_string(val).strip())
126
- elif header_key.startswith(self.ha._get_header_prefix()):
127
- str_list.append(header_key + ':' + val)
128
- else:
129
- str_list.append(val)
130
- str_list.append('\n')
131
- return str_list
132
-
133
-
134
- class V4Authentication(object):
135
- CONTENT_SHA256 = 'UNSIGNED-PAYLOAD'
136
-
137
- def __init__(self, ak, sk, region, shortDate, longDate, path_style, ha):
138
- self.ak = ak
139
- self.sk = sk
140
- self.region = region
141
- self.shortDate = shortDate
142
- self.longDate = longDate
143
- self.path_style = path_style
144
- self.ha = ha
145
-
146
- def doAuth(self, method, bucket, key, args_path, headers):
147
- args_path = args_path if isinstance(args_path, dict) else {}
148
- headers = headers if isinstance(headers, dict) else {}
149
- headers[self.ha.content_sha256_header()] = self.CONTENT_SHA256
150
-
151
- credential = self.getCredential()
152
- headMap = self.setMapKeyLower(headers)
153
- signedHeaders = self.getSignedHeaders(headMap)
154
- ret = self.getSignature(method, bucket, key, args_path, headMap, signedHeaders)
155
- auth = 'AWS4-HMAC-SHA256 Credential=%s,SignedHeaders=%s,Signature=%s' % (
156
- credential, signedHeaders, ret['Signature'])
157
- return {
158
- const.AUTHORIZATION_HEADER: auth,
159
- const.CANONICAL_REQUEST: ret[const.CANONICAL_REQUEST]
160
- }
161
-
162
- def getCredential(self):
163
- return '%s/%s/%s/s3/aws4_request' % (self.ak, self.shortDate, self.region)
164
-
165
- def getScope(self):
166
- return '%s/%s/s3/aws4_request' % (self.shortDate, self.region)
167
-
168
- @staticmethod
169
- def getSignedHeaders(headMap):
170
- headList = sorted(headMap.items(), key=lambda d: d[0])
171
- signedHeaders = ''
172
- i = 0
173
- for val in headList:
174
- if i != 0:
175
- signedHeaders += ';'
176
- signedHeaders += val[0]
177
- i = 1
178
- return signedHeaders
179
-
180
- def getSignature(self, method, bucket, key, args_path, headMap, signedHeaders, payload=None):
181
- outPut = 'AWS4-HMAC-SHA256' + '\n'
182
- outPut += self.longDate + '\n'
183
- outPut += self.getScope() + '\n'
184
- cannonicalRequest = self.getCanonicalRequest(method, bucket, key, args_path, headMap, signedHeaders, payload)
185
-
186
- if const.IS_PYTHON2:
187
- stringToSign = outPut + self.__shaCannonicalRequest_python2(cannonicalRequest)
188
- signingKey = self.getSigningKey_python2()
189
- else:
190
- stringToSign = outPut + self.__shaCannonicalRequest_python3(cannonicalRequest)
191
- stringToSign = stringToSign.encode('UTF-8')
192
- signingKey = self.getSigningKey_python3()
193
- return {
194
- 'Signature': self.hmacSha256(signingKey, stringToSign),
195
- const.CANONICAL_REQUEST: cannonicalRequest
196
- }
197
-
198
- @staticmethod
199
- def hmacSha256(signingKey, stringToSign):
200
- return hmac.new(signingKey, stringToSign, hashlib.sha256).hexdigest()
201
-
202
- def getSigningKey_python2(self):
203
- key = 'AWS4' + self.sk
204
- dateKey = hmac.new(key, self.shortDate, hashlib.sha256).digest()
205
- dateRegionKey = hmac.new(dateKey, self.region, hashlib.sha256).digest()
206
- dateRegionServiceKey = hmac.new(dateRegionKey, 's3', hashlib.sha256).digest()
207
- signingKey = hmac.new(dateRegionServiceKey, 'aws4_request', hashlib.sha256).digest()
208
- return signingKey
209
-
210
- def getSigningKey_python3(self):
211
- key = 'AWS4' + self.sk
212
- dateKey = hmac.new(key.encode('UTF-8'), self.shortDate.encode('UTF-8'), hashlib.sha256).digest()
213
- dateRegionKey = hmac.new(dateKey, self.region.encode('UTF-8'), hashlib.sha256).digest()
214
- dateRegionServiceKey = hmac.new(dateRegionKey, 's3'.encode('UTF-8'), hashlib.sha256).digest()
215
- signingKey = hmac.new(dateRegionServiceKey, 'aws4_request'.encode('UTF-8'), hashlib.sha256).digest()
216
- return signingKey
217
-
218
- def getCanonicalRequest(self, method, bucket, key, args_path, headMap, signedHeaders, payload=None):
219
- output = [method]
220
- output.append(self.getCanonicalURI(bucket, key))
221
- output.append(self.getCanonicalQueryString(args_path))
222
- output.append(self.getCanonicalHeaders(headMap))
223
- output.append(signedHeaders)
224
- output.append(self.CONTENT_SHA256 if payload is None else payload)
225
- return '\n'.join(output)
226
-
227
- @staticmethod
228
- def __shaCannonicalRequest_python2(cannonicalRequest):
229
- return hashlib.sha256(cannonicalRequest).hexdigest()
230
-
231
- @staticmethod
232
- def __shaCannonicalRequest_python3(cannonicalRequest):
233
- return hashlib.sha256(cannonicalRequest.encode('UTF-8')).hexdigest()
234
-
235
- def getCanonicalURI(self, bucket=None, key=None):
236
- URI = ''
237
- if self.path_style and bucket:
238
- URI += '/' + bucket
239
- if key:
240
- URI += '/' + key
241
- if not URI:
242
- URI = '/'
243
- return util.encode_object_key(URI)
244
-
245
- @staticmethod
246
- def getCanonicalQueryString(args_path):
247
- canonMap = {}
248
- for key, value in args_path.items():
249
- canonMap[key] = value
250
- cannoList = sorted(canonMap.items(), key=lambda d: d[0])
251
- queryStr = ''
252
- i = 0
253
- for val in cannoList:
254
- if i != 0:
255
- queryStr += '&'
256
- queryStr += '%s=%s' % (util.encode_item(val[0], '/'), util.encode_item(val[1], ''))
257
- i = 1
258
- return queryStr
259
-
260
- @staticmethod
261
- def getCanonicalHeaders(headMap):
262
- headList = sorted(headMap.items(), key=lambda d: d[0])
263
- canonicalHeaderStr = ''
264
- for val in headList:
265
- if isinstance(val[1], list):
266
- tlist = sorted(val[1])
267
- for v in tlist:
268
- canonicalHeaderStr += val[0] + ':' + v + '\n'
269
- else:
270
- canonicalHeaderStr += val[0] + ':' + str(val[1]) + '\n'
271
- return canonicalHeaderStr
272
-
273
- @staticmethod
274
- def setMapKeyLower(inputMap):
275
- outputMap = {}
276
- for key in inputMap.keys():
277
- outputMap[key.lower()] = inputMap[key]
278
- return outputMap
1
+ #!/usr/bin/python
2
+ # -*- coding:utf-8 -*-
3
+ # Copyright 2019 Huawei Technologies Co.,Ltd.
4
+ # Licensed under the Apache License, Version 2.0 (the "License"); you may not use
5
+ # this file except in compliance with the License. You may obtain a copy of the
6
+ # License at
7
+
8
+ # http://www.apache.org/licenses/LICENSE-2.0
9
+
10
+ # Unless required by applicable law or agreed to in writing, software distributed
11
+ # under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
12
+ # CONDITIONS OF ANY KIND, either express or implied. See the License for the
13
+ # specific language governing permissions and limitations under the License.
14
+
15
+ import hashlib
16
+ import hmac
17
+ import binascii
18
+ from obs import util
19
+ from obs import const
20
+
21
+
22
+ class Authentication(object):
23
+
24
+ def __init__(self, ak, sk, path_style, ha, server, is_cname):
25
+ self.ak = ak
26
+ self.sk = sk
27
+ self.path_style = path_style
28
+ self.ha = ha
29
+ self.server = server
30
+ self.is_cname = is_cname
31
+
32
+ def doAuth(self, method, bucket, key, path_args, headers, expires=None):
33
+ ret = self.getSignature(method, bucket, key, path_args, headers, expires)
34
+ return {
35
+ const.AUTHORIZATION_HEADER: '%s %s:%s' % (self.ha.auth_prefix(), self.ak, ret['Signature']),
36
+ const.CANONICAL_STRING: ret[const.CANONICAL_STRING]
37
+ }
38
+
39
+ def getSignature(self, method, bucket, key, path_args, headers, expires=None):
40
+ canonical_string = self.__make_canonical_string(method, bucket, key, path_args, headers, expires)
41
+ return {
42
+ 'Signature': self.hmacSha128(canonical_string),
43
+ const.CANONICAL_STRING: canonical_string
44
+ }
45
+
46
+ def hmacSha128(self, canonical_string):
47
+ if const.IS_PYTHON2:
48
+ hashed = hmac.new(self.sk, canonical_string, hashlib.sha1)
49
+ encode_canonical = binascii.b2a_base64(hashed.digest())[:-1]
50
+ else:
51
+ hashed = hmac.new(self.sk.encode('UTF-8'), canonical_string.encode('UTF-8'), hashlib.sha1)
52
+ encode_canonical = binascii.b2a_base64(hashed.digest())[:-1].decode('UTF-8')
53
+
54
+ return encode_canonical
55
+
56
+ def __make_canonical_string(self, method, bucket_name, key, path_args, headers, expires=None):
57
+ interesting_headers = self.__make_canonicalstring_interesting_headers(headers, expires)
58
+ key_list = sorted(interesting_headers.keys())
59
+ str_list = self.__make_canonicalstring_str_list(key_list, method, interesting_headers)
60
+ URI = ''
61
+ _bucket_name = self.server if self.is_cname else bucket_name
62
+ if _bucket_name:
63
+ URI += '/'
64
+ URI += _bucket_name
65
+ if not self.path_style or self.is_cname:
66
+ URI += '/'
67
+
68
+ if key:
69
+ if not URI.endswith('/'):
70
+ URI += '/'
71
+ URI += util.encode_object_key(key)
72
+
73
+ if URI:
74
+ str_list.append(URI)
75
+ else:
76
+ str_list.append('/')
77
+
78
+ if path_args:
79
+ e = '?'
80
+ cannoList = sorted(path_args.items(), key=lambda d: d[0])
81
+ for path_key, path_value in cannoList:
82
+ if path_key.lower() in const.ALLOWED_RESOURCE_PARAMTER_NAMES or path_key.lower().startswith(
83
+ self.ha._get_header_prefix()):
84
+ path_key = util.encode_item(path_key, '/')
85
+ if path_value is None:
86
+ e += path_key + '&'
87
+ continue
88
+ e += path_key + '=' + util.to_string(path_value) + '&'
89
+
90
+ e = e[:-1]
91
+ str_list.append(e)
92
+ return ''.join(str_list)
93
+
94
+ def __make_canonicalstring_interesting_headers(self, headers, expires):
95
+ interesting_headers = {}
96
+ if isinstance(headers, dict):
97
+ for hash_key in headers.keys():
98
+ lk = hash_key.lower()
99
+ if lk in const.CONTENT_LIST or lk.startswith(self.ha._get_header_prefix()):
100
+ s = headers.get(hash_key)
101
+ interesting_headers[lk] = ''.join(s)
102
+
103
+ key_list = interesting_headers.keys()
104
+
105
+ if self.ha.date_header() in key_list:
106
+ interesting_headers[const.DATE_HEADER.lower()] = ''
107
+
108
+ if expires:
109
+ interesting_headers[const.DATE_HEADER.lower()] = expires
110
+
111
+ if const.CONTENT_TYPE_HEADER.lower() not in key_list:
112
+ interesting_headers[const.CONTENT_TYPE_HEADER.lower()] = ''
113
+
114
+ if const.CONTENT_MD5_HEADER.lower() not in key_list:
115
+ interesting_headers[const.CONTENT_MD5_HEADER.lower()] = ''
116
+
117
+ return interesting_headers
118
+
119
+ def __make_canonicalstring_str_list(self, keylist, method, interesting_headers):
120
+ str_list = [method + '\n']
121
+ for k in keylist:
122
+ header_key = util.to_string(k)
123
+ val = '' if interesting_headers[header_key] is None else interesting_headers[header_key]
124
+ if header_key.startswith(self.ha._get_meta_header_prefix()):
125
+ str_list.append(header_key + ':' + util.to_string(val).strip())
126
+ elif header_key.startswith(self.ha._get_header_prefix()):
127
+ str_list.append(header_key + ':' + val)
128
+ else:
129
+ str_list.append(val)
130
+ str_list.append('\n')
131
+ return str_list
132
+
133
+
134
+ class V4Authentication(object):
135
+ CONTENT_SHA256 = 'UNSIGNED-PAYLOAD'
136
+
137
+ def __init__(self, ak, sk, region, shortDate, longDate, path_style, ha):
138
+ self.ak = ak
139
+ self.sk = sk
140
+ self.region = region
141
+ self.shortDate = shortDate
142
+ self.longDate = longDate
143
+ self.path_style = path_style
144
+ self.ha = ha
145
+
146
+ def doAuth(self, method, bucket, key, args_path, headers):
147
+ args_path = args_path if isinstance(args_path, dict) else {}
148
+ headers = headers if isinstance(headers, dict) else {}
149
+ headers[self.ha.content_sha256_header()] = self.CONTENT_SHA256
150
+
151
+ credential = self.getCredential()
152
+ headMap = self.setMapKeyLower(headers)
153
+ signedHeaders = self.getSignedHeaders(headMap)
154
+ ret = self.getSignature(method, bucket, key, args_path, headMap, signedHeaders)
155
+ auth = 'AWS4-HMAC-SHA256 Credential=%s,SignedHeaders=%s,Signature=%s' % (
156
+ credential, signedHeaders, ret['Signature'])
157
+ return {
158
+ const.AUTHORIZATION_HEADER: auth,
159
+ const.CANONICAL_REQUEST: ret[const.CANONICAL_REQUEST]
160
+ }
161
+
162
+ def getCredential(self):
163
+ return '%s/%s/%s/s3/aws4_request' % (self.ak, self.shortDate, self.region)
164
+
165
+ def getScope(self):
166
+ return '%s/%s/s3/aws4_request' % (self.shortDate, self.region)
167
+
168
+ @staticmethod
169
+ def getSignedHeaders(headMap):
170
+ headList = sorted(headMap.items(), key=lambda d: d[0])
171
+ signedHeaders = ''
172
+ i = 0
173
+ for val in headList:
174
+ if i != 0:
175
+ signedHeaders += ';'
176
+ signedHeaders += val[0]
177
+ i = 1
178
+ return signedHeaders
179
+
180
+ def getSignature(self, method, bucket, key, args_path, headMap, signedHeaders, payload=None):
181
+ outPut = 'AWS4-HMAC-SHA256' + '\n'
182
+ outPut += self.longDate + '\n'
183
+ outPut += self.getScope() + '\n'
184
+ cannonicalRequest = self.getCanonicalRequest(method, bucket, key, args_path, headMap, signedHeaders, payload)
185
+
186
+ if const.IS_PYTHON2:
187
+ stringToSign = outPut + self.__shaCannonicalRequest_python2(cannonicalRequest)
188
+ signingKey = self.getSigningKey_python2()
189
+ else:
190
+ stringToSign = outPut + self.__shaCannonicalRequest_python3(cannonicalRequest)
191
+ stringToSign = stringToSign.encode('UTF-8')
192
+ signingKey = self.getSigningKey_python3()
193
+ return {
194
+ 'Signature': self.hmacSha256(signingKey, stringToSign),
195
+ const.CANONICAL_REQUEST: cannonicalRequest
196
+ }
197
+
198
+ @staticmethod
199
+ def hmacSha256(signingKey, stringToSign):
200
+ return hmac.new(signingKey, stringToSign, hashlib.sha256).hexdigest()
201
+
202
+ def getSigningKey_python2(self):
203
+ key = 'AWS4' + self.sk
204
+ dateKey = hmac.new(key, self.shortDate, hashlib.sha256).digest()
205
+ dateRegionKey = hmac.new(dateKey, self.region, hashlib.sha256).digest()
206
+ dateRegionServiceKey = hmac.new(dateRegionKey, 's3', hashlib.sha256).digest()
207
+ signingKey = hmac.new(dateRegionServiceKey, 'aws4_request', hashlib.sha256).digest()
208
+ return signingKey
209
+
210
+ def getSigningKey_python3(self):
211
+ key = 'AWS4' + self.sk
212
+ dateKey = hmac.new(key.encode('UTF-8'), self.shortDate.encode('UTF-8'), hashlib.sha256).digest()
213
+ dateRegionKey = hmac.new(dateKey, self.region.encode('UTF-8'), hashlib.sha256).digest()
214
+ dateRegionServiceKey = hmac.new(dateRegionKey, 's3'.encode('UTF-8'), hashlib.sha256).digest()
215
+ signingKey = hmac.new(dateRegionServiceKey, 'aws4_request'.encode('UTF-8'), hashlib.sha256).digest()
216
+ return signingKey
217
+
218
+ def getCanonicalRequest(self, method, bucket, key, args_path, headMap, signedHeaders, payload=None):
219
+ output = [method]
220
+ output.append(self.getCanonicalURI(bucket, key))
221
+ output.append(self.getCanonicalQueryString(args_path))
222
+ output.append(self.getCanonicalHeaders(headMap))
223
+ output.append(signedHeaders)
224
+ output.append(self.CONTENT_SHA256 if payload is None else payload)
225
+ return '\n'.join(output)
226
+
227
+ @staticmethod
228
+ def __shaCannonicalRequest_python2(cannonicalRequest):
229
+ return hashlib.sha256(cannonicalRequest).hexdigest()
230
+
231
+ @staticmethod
232
+ def __shaCannonicalRequest_python3(cannonicalRequest):
233
+ return hashlib.sha256(cannonicalRequest.encode('UTF-8')).hexdigest()
234
+
235
+ def getCanonicalURI(self, bucket=None, key=None):
236
+ URI = ''
237
+ if self.path_style and bucket:
238
+ URI += '/' + bucket
239
+ if key:
240
+ URI += '/' + key
241
+ if not URI:
242
+ URI = '/'
243
+ return util.encode_object_key(URI)
244
+
245
+ @staticmethod
246
+ def getCanonicalQueryString(args_path):
247
+ canonMap = {}
248
+ for key, value in args_path.items():
249
+ canonMap[key] = value
250
+ cannoList = sorted(canonMap.items(), key=lambda d: d[0])
251
+ queryStr = ''
252
+ i = 0
253
+ for val in cannoList:
254
+ if i != 0:
255
+ queryStr += '&'
256
+ queryStr += '%s=%s' % (util.encode_item(val[0], '/'), util.encode_item(val[1], ''))
257
+ i = 1
258
+ return queryStr
259
+
260
+ @staticmethod
261
+ def getCanonicalHeaders(headMap):
262
+ headList = sorted(headMap.items(), key=lambda d: d[0])
263
+ canonicalHeaderStr = ''
264
+ for val in headList:
265
+ if isinstance(val[1], list):
266
+ tlist = sorted(val[1])
267
+ for v in tlist:
268
+ canonicalHeaderStr += val[0] + ':' + v + '\n'
269
+ else:
270
+ canonicalHeaderStr += val[0] + ':' + str(val[1]) + '\n'
271
+ return canonicalHeaderStr
272
+
273
+ @staticmethod
274
+ def setMapKeyLower(inputMap):
275
+ outputMap = {}
276
+ for key in inputMap.keys():
277
+ outputMap[key.lower()] = inputMap[key]
278
+ return outputMap