-
Notifications
You must be signed in to change notification settings - Fork 581
Description
- Python Version: 3.5.5
- aliyunsdkkms Version: aliyun-python-sdk-kms==2.15.0
- oss2 Version: oss2==2.15.0
- API: DecryptRequest, EncryptRequest, GenerateDataKeyRequest
在使用阿里云 SDK 上传 OSS 文件时,用到了其中的客户端加密文件上传的功能(文档:https://help.aliyun.com/document_detail/74371.html ,文档中示例 V2版本客户端加密(推荐) --> 普通上传和下载文件),其中示例代码提供了使用主 access_key_id 和 access_key_secret 上传文件的方式。
我根据示例和 OSS2 的 SDK 源码将该示例修改为使用 STS 的方式进行上传,发现了两个问题:
oss2 SDK 中的文件 https://github.com/aliyun/aliyun-oss-python-sdk/blob/master/oss2/crypto.py 使用了 aliyun-python-sdk-kms 中的 GenerateDataKeyRequest, DecryptRequest, EncryptRequest 三个文件中的同名 class,并且使用了代码 req.set_STSToken(self.sts_token)
,如下:
# 文件:https://github.com/leafcoder/aliyun-oss-python-sdk/blob/master/oss2/crypto.py 第 350 行
def __generate_data_key(self):
req = GenerateDataKeyRequest.GenerateDataKeyRequest()
req.set_accept_format(format_type.JSON)
req.set_method(method_type.POST)
req.set_KeyId(self.custom_master_key_id)
req.set_KeySpec('AES_256')
req.set_NumberOfBytes(32)
req.set_EncryptionContext(self.context)
if self.sts_token:
req.set_STSToken(self.sts_token)
resp = self.__do(req)
return b64decode_from_string(resp['Plaintext']), resp['CiphertextBlob']
但是经过阅读 aliyun-python-sdk-kms 源码,发现 set_STSToken
和 get_STSToken
方法已于 leafcoder@6fa406f 被删除,提交的信息中包含内容 “Remove the optional parameter 'STSToken' and replace it with 'SecurityToken'.” ,但实际仅删除了 STSToken
参数的方法,未增加 get 和 set 参数 SecurityToken 的方法。
我发现以上问题使用的代码如下:
from aliyunsdkcore import client as aliyun_client
from aliyunsdkcore.acs_exception.exceptions import ServerException
from aliyunsdksts.request.v20150401 import AssumeRoleRequest
from oss2.crypto import AliKMSProvider
import json
import os
import oss2
AK = 'Your Access Key ID' # 需自行更换
AS = 'Your Access Key Secret' # 需自行更换
REGION = 'cn-shenzhen'
ENDPOINT = 'https://oss-cn-shenzhen.aliyuncs.com'
BUCKET_NAME = 'xxxxxx' # 需自行更换
ROLE_ARN = 'acs:ram::xxxxxx:role/xxxxxx' # 需自行更换
CMK_ID = 'xxxxxx' # 需自行更换(KMS 用户密钥 ID)
import json
clt = aliyun_client.AcsClient(AK, AS, REGION)
req = AssumeRoleRequest.AssumeRoleRequest()
req.set_accept_format('json')
req.set_RoleArn(ROLE_ARN)
req.set_RoleSessionName('test')
req.set_Policy(json.dumps({
"Version": "1",
"Statement": [
{
"Effect": "Allow",
"Action": [
"oss:PutObject",
"oss:GetObject",
"kms:Encrypt",
"kms:Decrypt",
"kms:GenerateDataKey"
],
"Resource": [
'acs:oss:*:*:%s/*' % BUCKET_NAME,
"acs:kms:cn-shenzhen:xxxxxxxxxxxx:key/%s" % CMK_ID
]
}
]
}))
body = clt.do_action_with_exception(req)
token = json.loads(body.decode('utf-8'))
credentials = token['Credentials']
print(credentials)
# STS 部分
auth = oss2.StsAuth(
credentials['AccessKeyId'],
credentials['AccessKeySecret'],
credentials['SecurityToken'])
# 使用StsAuth实例初始化存储空间。
kms_provider = AliKMSProvider(
credentials['AccessKeyId'],
credentials['AccessKeySecret'],
REGION,
CMK_ID,
sts_token=credentials['SecurityToken'])
bucket = oss2.CryptoBucket(
auth, endpoint, bucket_name, crypto_provider=kms_provider)
content = b'test kms'
content = open('/home/ubuntu/test.db', 'rb').read()
key = 'test.db'
bucket.put_object(key, content)
# 下载OSS文件到本地内存。
result = bucket.get_object(key)
# 验证获取到的文件内容跟上传时的文件内容是否一致。
content_got = b''
for chunk in result:
content_got += chunk
assert content_got == content
所以,经过如上回搠,需要修复 aliyun-python-sdk-kms 和 oss2 两个项目。
我已提交相关 pull-requests,请核对处理,谢谢。
注意:aliyun-python-sdk-kms 和 oss2 需同步修复 SecurityToken 的问题才行,aliyun-python-sdk-kms 的修复优先级需高于 oss2。