Skip to content

修复无法在客户端加密方式下使用 STS 上传文件至 OSS 的问题 #457

@leafcoder

Description

@leafcoder
  • 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_STSTokenget_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。

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions