Skip to content

Commit c3447b8

Browse files
committed
更新至 3.21.8 版本
1 parent 076ff33 commit c3447b8

27 files changed

+2482
-809
lines changed

README.md

Lines changed: 185 additions & 177 deletions
Large diffs are not rendered by default.

README_CN.md

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,12 @@
1-
Version 3.21.4
1+
Version 3.21.8
2+
3+
新特性:
4+
5+
1. 新增客户端加密特性。
6+
7+
-------------------------------------------------------------------------------------------------
8+
9+
Version 3.21.4
210

311
新特性:
412

examples/crypto_client_sample.py

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
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+
"""
16+
This sample demonstrates how to using crypto client in OBS Python SDK.
17+
"""
18+
from obs import CompleteMultipartUploadRequest, CompletePart, CryptoObsClient
19+
from obs.obs_cipher_suite import CTRCipherGenerator, CtrRSACipherGenerator
20+
21+
AK = '*** Provide your Access Key ***'
22+
SK = '*** Provide your Secret Key ***'
23+
server = 'https://your-endpoint'
24+
25+
bucketName = 'my-obs-bucket-demo'
26+
test_file = "path/to/your/test/file"
27+
28+
# Construct a crypto obs client with CtrRSACipherGenerator
29+
# CtrRSACipherGenerator using public key
30+
public_g = CtrRSACipherGenerator("/path/to/public_key.pem", master_key_info="Test_Key22")
31+
public_client = CryptoObsClient(access_key_id=AK, secret_access_key=SK, server=server, cipher_generator=public_g)
32+
33+
# CtrRSACipherGenerator using private key
34+
private_g = CtrRSACipherGenerator("/path/to/private_key.pem", master_key_info="Test_Key22")
35+
private_client = CryptoObsClient(access_key_id=AK, secret_access_key=SK, server=server, cipher_generator=private_g)
36+
37+
# Construct a crypto obs client with CTRCipherGenerator
38+
# The byte length of master key mast equal 32
39+
ctr_g = CTRCipherGenerator("your-master-key")
40+
ctr_client = CryptoObsClient(access_key_id=AK, secret_access_key=SK, server=server, cipher_generator=ctr_g)
41+
42+
# Create bucket
43+
bucketClient = ctr_client.bucketClient(bucketName)
44+
45+
# Upload file
46+
# Uploading file in crypto obsClient is same as in normal obsClient
47+
upload_object_key = "upload_test_file_with_ctr_client"
48+
ctr_client_result = ctr_client.putFile(bucketName, upload_object_key, test_file)
49+
if ctr_client_result.status < 300:
50+
print('Upload finished\n')
51+
52+
# Multipart upload File
53+
54+
object_key = "Multipart_upload_File"
55+
56+
# Step 1: Generate a cipher using empty string
57+
print('Step 1: Generate a cipher using empty string \n')
58+
cipher = ctr_client.cipher_generator.new("")
59+
60+
# Step 2: initiate multipart upload
61+
print('Step 2: initiate multipart upload \n')
62+
init_result = ctr_client.initiateEncryptedMultipartUpload(bucketName, object_key, cipher)
63+
uploadId = init_result.body.uploadId
64+
65+
# Step 3: upload a part
66+
print('Step 3: upload a part\n')
67+
partNum = 1
68+
resp = ctr_client.uploadEncryptedPart(bucketName, object_key, partNumber=partNum, uploadId=uploadId,
69+
crypto_cipher=cipher, content='Hello OBS')
70+
etag = dict(resp.header).get('etag')
71+
72+
# Step 4: complete multipart upload
73+
print('Step 4: complete multipart upload\n')
74+
resp = ctr_client.completeMultipartUpload(bucketName, object_key, uploadId,
75+
CompleteMultipartUploadRequest([CompletePart(partNum=partNum, etag=etag)]))
76+
if resp.status < 300:
77+
print('Complete finished\n')
78+
79+
# Download file
80+
# Downloading file in crypto obsClient is same as in normal obsClient
81+
download_result = ctr_client.getObject(bucketName, upload_object_key, downloadPath="/path/to/save")
82+
if download_result.status < 300:
83+
print('Download finished\n')

src/obs/__init__.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@
2525
from obs.model import ListMultipartUploadsRequest, GetObjectRequest, UploadFileHeader, Payer
2626
from obs.model import ExtensionHeader, FetchStatus
2727
from obs.workflow import WorkflowClient
28+
from obs.crypto_client import CryptoObsClient
29+
from obs.obs_cipher_suite import CTRCipherGenerator
30+
from obs.obs_cipher_suite import CtrRSACipherGenerator
2831

2932
__all__ = [
3033
'LogConf',
@@ -85,5 +88,8 @@
8588
'Payer',
8689
'ExtensionHeader',
8790
'FetchStatus',
88-
'WorkflowClient'
91+
'WorkflowClient',
92+
'CryptoObsClient',
93+
'CTRCipherGenerator',
94+
'CtrRSACipherGenerator'
8995
]

src/obs/auth.py

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ def doAuth(self, method, bucket, key, path_args, headers, expires=None):
3737
}
3838

3939
def getSignature(self, method, bucket, key, path_args, headers, expires=None):
40-
canonical_string = self.__make_canonicalstring(method, bucket, key, path_args, headers, expires)
40+
canonical_string = self.__make_canonical_string(method, bucket, key, path_args, headers, expires)
4141
return {
4242
'Signature': self.hmacSha128(canonical_string),
4343
const.CANONICAL_STRING: canonical_string
@@ -53,10 +53,10 @@ def hmacSha128(self, canonical_string):
5353

5454
return encode_canonical
5555

56-
def __make_canonicalstring(self, method, bucket_name, key, path_args, headers, expires=None):
56+
def __make_canonical_string(self, method, bucket_name, key, path_args, headers, expires=None):
5757
interesting_headers = self.__make_canonicalstring_interesting_headers(headers, expires)
58-
keylist = sorted(interesting_headers.keys())
59-
str_list = self.__make_canonicalstring_str_list(keylist, method, interesting_headers)
58+
key_list = sorted(interesting_headers.keys())
59+
str_list = self.__make_canonicalstring_str_list(key_list, method, interesting_headers)
6060
URI = ''
6161
_bucket_name = self.server if self.is_cname else bucket_name
6262
if _bucket_name:
@@ -100,18 +100,18 @@ def __make_canonicalstring_interesting_headers(self, headers, expires):
100100
s = headers.get(hash_key)
101101
interesting_headers[lk] = ''.join(s)
102102

103-
keylist = interesting_headers.keys()
103+
key_list = interesting_headers.keys()
104104

105-
if self.ha.date_header() in keylist:
105+
if self.ha.date_header() in key_list:
106106
interesting_headers[const.DATE_HEADER.lower()] = ''
107107

108108
if expires:
109109
interesting_headers[const.DATE_HEADER.lower()] = expires
110110

111-
if const.CONTENT_TYPE_HEADER.lower() not in keylist:
111+
if const.CONTENT_TYPE_HEADER.lower() not in key_list:
112112
interesting_headers[const.CONTENT_TYPE_HEADER.lower()] = ''
113113

114-
if const.CONTENT_MD5_HEADER.lower() not in keylist:
114+
if const.CONTENT_MD5_HEADER.lower() not in key_list:
115115
interesting_headers[const.CONTENT_MD5_HEADER.lower()] = ''
116116

117117
return interesting_headers
@@ -148,24 +148,25 @@ def doAuth(self, method, bucket, key, args_path, headers):
148148
headers = headers if isinstance(headers, dict) else {}
149149
headers[self.ha.content_sha256_header()] = self.CONTENT_SHA256
150150

151-
credenttial = self.getCredenttial()
151+
credential = self.getCredential()
152152
headMap = self.setMapKeyLower(headers)
153153
signedHeaders = self.getSignedHeaders(headMap)
154154
ret = self.getSignature(method, bucket, key, args_path, headMap, signedHeaders)
155155
auth = 'AWS4-HMAC-SHA256 Credential=%s,SignedHeaders=%s,Signature=%s' % (
156-
credenttial, signedHeaders, ret['Signature'])
156+
credential, signedHeaders, ret['Signature'])
157157
return {
158158
const.AUTHORIZATION_HEADER: auth,
159159
const.CANONICAL_REQUEST: ret[const.CANONICAL_REQUEST]
160160
}
161161

162-
def getCredenttial(self):
162+
def getCredential(self):
163163
return '%s/%s/%s/s3/aws4_request' % (self.ak, self.shortDate, self.region)
164164

165165
def getScope(self):
166166
return '%s/%s/s3/aws4_request' % (self.shortDate, self.region)
167167

168-
def getSignedHeaders(self, headMap):
168+
@staticmethod
169+
def getSignedHeaders(headMap):
169170
headList = sorted(headMap.items(), key=lambda d: d[0])
170171
signedHeaders = ''
171172
i = 0
@@ -194,7 +195,8 @@ def getSignature(self, method, bucket, key, args_path, headMap, signedHeaders, p
194195
const.CANONICAL_REQUEST: cannonicalRequest
195196
}
196197

197-
def hmacSha256(self, signingKey, stringToSign):
198+
@staticmethod
199+
def hmacSha256(signingKey, stringToSign):
198200
return hmac.new(signingKey, stringToSign, hashlib.sha256).hexdigest()
199201

200202
def getSigningKey_python2(self):
@@ -222,10 +224,12 @@ def getCanonicalRequest(self, method, bucket, key, args_path, headMap, signedHea
222224
output.append(self.CONTENT_SHA256 if payload is None else payload)
223225
return '\n'.join(output)
224226

225-
def __shaCannonicalRequest_python2(self, cannonicalRequest):
227+
@staticmethod
228+
def __shaCannonicalRequest_python2(cannonicalRequest):
226229
return hashlib.sha256(cannonicalRequest).hexdigest()
227230

228-
def __shaCannonicalRequest_python3(self, cannonicalRequest):
231+
@staticmethod
232+
def __shaCannonicalRequest_python3(cannonicalRequest):
229233
return hashlib.sha256(cannonicalRequest.encode('UTF-8')).hexdigest()
230234

231235
def getCanonicalURI(self, bucket=None, key=None):
@@ -238,7 +242,8 @@ def getCanonicalURI(self, bucket=None, key=None):
238242
URI = '/'
239243
return util.encode_object_key(URI)
240244

241-
def getCanonicalQueryString(self, args_path):
245+
@staticmethod
246+
def getCanonicalQueryString(args_path):
242247
canonMap = {}
243248
for key, value in args_path.items():
244249
canonMap[key] = value
@@ -252,7 +257,8 @@ def getCanonicalQueryString(self, args_path):
252257
i = 1
253258
return queryStr
254259

255-
def getCanonicalHeaders(self, headMap):
260+
@staticmethod
261+
def getCanonicalHeaders(headMap):
256262
headList = sorted(headMap.items(), key=lambda d: d[0])
257263
canonicalHeaderStr = ''
258264
for val in headList:
@@ -264,7 +270,8 @@ def getCanonicalHeaders(self, headMap):
264270
canonicalHeaderStr += val[0] + ':' + str(val[1]) + '\n'
265271
return canonicalHeaderStr
266272

267-
def setMapKeyLower(self, inputMap):
273+
@staticmethod
274+
def setMapKeyLower(inputMap):
268275
outputMap = {}
269276
for key in inputMap.keys():
270277
outputMap[key.lower()] = inputMap[key]

src/obs/bucket.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,8 @@ def __init__(self, obsClient, bucketName):
9191

9292
def __getattr__(self, key):
9393
if key in self.allowedMethod and hasattr(self.__obsClient, key):
94-
orignalMethod = getattr(self.__obsClient, key)
95-
if callable(orignalMethod):
94+
original_method = getattr(self.__obsClient, key)
95+
if callable(original_method):
9696
def delegate(*args, **kwargs):
9797
_args = list(args)
9898
if key == 'copyObject':
@@ -104,7 +104,7 @@ def delegate(*args, **kwargs):
104104
else:
105105
if 'bucketName' not in kwargs:
106106
_args.insert(0, self.__bucketName)
107-
return orignalMethod(*_args, **kwargs)
107+
return original_method(*_args, **kwargs)
108108

109109
return delegate
110110
return super(BucketClient, self).__getattribute__(key)

0 commit comments

Comments
 (0)