天天看點

STS Python_SDK授權臨時使用者讀寫OSS資源STS Python_SDK授權臨時使用者讀寫OSS資源

STS Python_SDK授權臨時使用者讀寫OSS資源

名詞解釋

RAM (Resource Access Management)

STS(Security Token Service)

是阿裡雲提供的

權限管理系統

RAM主要的作用是控制賬号系統的權限。您可以使用RAM在主賬号的權限範圍内建立子使用者,給不同的子使用者配置設定不同的權限進而達到授權管理的目的。STS是一個安全憑證(Token)的管理系統。您可以使用STS來完成對于臨時使用者的通路授權。

  • 子賬号(RAM account) :從阿裡雲的主賬号中建立出來的子賬号,在建立的時候可以配置設定獨立的密碼和權限,每個子賬号擁有自己AccessKey,可以和阿裡雲主賬号一樣正常的完成有權限的操作。一般來說,這裡的子賬号可以了解為具有某種權限的使用者,可以被認為是一個具有某些權限的操作發起者。
  • 角色(Role)

    :表示某種操作權限的虛拟概念,但是沒有獨立的登入密碼和AccessKey。

    說明 子賬号可以扮演角色,扮演角色時候的權限是該角色自身的權限。

  • 授權政策(Policy) :用來定義權限的規則,比如允許使用者讀取或寫入某些資源。
  • 資源(Resource):代表使用者可通路的雲資源,比如OSS所有的Bucket、OSS的某個Bucket,或OSS的某個Bucket下面的某個Object等。
  • 扮演角色(Assume role)扮演角色是實體使用者擷取角色身份的安全令牌的 方法。一個實體使用者調用STS API AssumeRole可以獲得角色的安全令牌,使用安全令牌可以通路雲服務API。

這裡将手動定義 授權政策(Policy),将 授權政策 授權給 角色 ,然後子賬号(RAM account)通過 扮演角色_方法 _擷取 角色 的 安全令牌 對 資源 進行操作.

RAM 使用者 可以使用 API 扮演 RAM 角色。當 RAM 使用者被授予

 AliyunSTSAssumeRoleAccess

 權限政策 之後,可以使用其通路密鑰調用 STS API 

AssumeRole

 接口,以擷取某個角色的 安全令牌,進而使用安全令牌通路資源。

建立使用者,角色,授權政策

建立RAM使用者

  1. 登入  RAM 控制台
  2. 在左側導航欄的人員管理菜單下,單擊使用者。
  3. 單擊建立使用者,輸入登入名稱和顯示名稱。

    說明 單擊添加使用者,可一次性建立多個 RAM 使用者。

  4. 在通路方式區域下,選擇控制台密碼登入或程式設計通路。
    • 控制台密碼登入:可以完成對登入安全的基本設定,包括自動生成或自定義登入密碼、是否要求下次登入時重置密碼以及是否要求開啟多因素認證。
    • 程式設計通路:将會自動為 RAM 使用者建立通路密鑰(AccessKey)。RAM 使用者可以通過 API 或其他開發工具通路阿裡雲。
  5. 說明 為了保障賬号安全,建議僅為 RAM 使用者選擇一種登入方式。避免 RAM 使用者離開組織後仍可以通過通路密鑰通路阿裡雲資源。
  6. 單擊确認。

授權RAM使用者AssumeRole接口權限

  1. 在使用者清單中找到剛才建立的使用者,單擊清單【操作】欄下的【添權重限】
  2. 在彈出對話框中的【系統權限政策】搜尋并添加 _AliyunSTSAssumeRoleAccess_

建立自定義權限政策test_policy

  1. 在左側導航欄的權限管理菜單下,單擊權限政策管理。
  2. 單擊建立權限政策。
  3. 填寫政策名稱和備注。
  4. 配置模式選擇可視化配置或腳本配置。
    • 若選擇可視化配置:單擊添加授權語句,根據界面提示,對權限效力、操作名稱和資源等進行配置。
    • 若選擇腳本配置,請參考 文法結構 編輯政策内容。

下面為OSS所有權限文法示例

{
    "Statement": [
        {
            "Action": "oss:*",
            "Effect": "Allow",
            "Resource": "*"
        }
    ],
    "Version": "1"
}           

建立角色testRole

注:這裡角色有三種類型,建立可信實體為阿裡雲賬号的RAM角色
  1. 雲賬号登入 RAM控制台
  2. 在左側導航欄,單擊RAM角色管理。
  3. 單擊建立RAM角色。
  4. 選擇可信實體類型為阿裡雲賬号,單擊下一步。
  5. 輸入角色名稱和備注。
  6. 選擇雲賬号後,單擊完成。

将自定義權限政策授權給角色

  1. 在左側導航欄的權限管理菜單下,單擊授權。
  2. 單擊新增授權。
  3. 在被授權主體區域下,輸入 RAM 角色名稱後,單擊需要授權的 RAM 角色。
  4. 在左側權限政策名稱清單下,單擊需要授予 RAM 角色的權限政策。

    說明 在右側區域框,選擇某條政策并單擊 ×,可撤銷該政策。

  5. 單擊确定。

完成授權後可在角色管理中檢視授權詳情

STS Python_SDK授權臨時使用者讀寫OSS資源STS Python_SDK授權臨時使用者讀寫OSS資源
注:這裡政策主體類型有兩種,權限政策也可直接授權給使用者    
STS Python_SDK授權臨時使用者讀寫OSS資源STS Python_SDK授權臨時使用者讀寫OSS資源

通過STS完成臨時授權

STS基本概念

阿裡雲臨時安全令牌

(Security Token Service,STS)

是阿裡雲提供的一種臨時通路權限管理服務。

  • RAM角色(RAM role)一種虛拟的RAM使用者。RAM角色的全局資源描述符(Role ARN)Role ARN是角色的全局資源描述符(Aliyun Resource Name,簡稱ARN),用來指定具體角色。每個角色都有一個唯一的全局資源描述符。格式:

    acs:ram::$accountID:role/$roleName

  • 可信實體(Trusted entity)角色的可信實體是指可以扮演角色的實體使用者身份。建立角色時必須指定可信實體,角色隻能被受信的主體扮演。可信實體可以是受信的阿裡雲賬号、受信的阿裡雲服務或身份提供商。
  • 扮演角色(Assume role)扮演角色是實體使用者擷取角色身份的安全令牌的方法。一個實體使用者調用STS API AssumeRole可以獲得角色的安全令牌,使用安全令牌可以通路雲服務API。

注:這裡需要區分下RAM角色與扮演角色的差別,可信實體 通過 扮演角色 _方法__  _擷取 RAM角色 的安全令牌

扮演角色的API接口概覽

STS提供API調用接口每個請求都需要指定如下資訊:

  • 要執行的操作:Action參數。
  • 每個操作接口都需要包含的公共請求參數。
  • 操作接口所特有的請求參數。

調用AssumeRole接口擷取一個臨時身份。參考

API
  • RoleArn表示的是需要扮演的角色ID,角色的ID可以在角色管理 > 角色詳情中找到。
  • RoleSessionName是一個用來标示臨時憑證的名稱,一般來說建議使用不同的應用程式使用者來區分。
  • Policy表示的是在扮演角色的時候額外加上的一個權限限制。此參數可以限制生成的STS token的權限,若不指定則傳回的token擁有指定角色的所有權限。
  • DurationSeconds指的是臨時憑證的有效期,機關是s,最小為900,最大為3600。
  • id和secret表示的是需要扮演角色的子賬号的AccessKey。

AssumeRole接口請求示例

https://sts.aliyuncs.com?Action=AssumeRole
&RoleArn=acs:ram::123456789012****:role/adminrole
&RoleSessionName=alice
&DurationSeconds=3600
&Policy=<url_encoded_policy>
&<公共請求參數>           

AssumeRole接口傳回格式(json)

{
    "Credentials": {
        "AccessKeyId": "STS.L4aBSCSJVMuKg5U1****",
        "AccessKeySecret": "wyLTSmsyPGP1ohvvw8xYgB29dlGI8KMiH2pK****",
        "Expiration": "2015-04-09T11:52:19Z",
        "SecurityToken": "********"
    },
    "AssumedRoleUser": {
        "arn": "acs:sts::123456789012****:assumed-role/AdminRole/alice",
        "AssumedRoleUserId":"34458433936495****:alice"
        },
    "RequestId": "6894B13B-6D71-4EF5-88FA-F32781734A7F"
}           

通過STS_SDK完成角色扮演

這裡将通過官方提供的SDK子產品進行具體的角色扮演

 安裝相關SDK包

pip install oss2

pip install aliyun-python-sdk-core

pip install aliyun-python-sdk-sts

sts

sdk

 github 位址

 擷取臨時身份資訊

# 在控制台将 AliyunSTSAssumeRoleAccess 權限授權給子使用者testRole,testRole操作AssumeRole接口,擷取臨時身份
def fetch_sts_info(access_key_id, access_key_secret, sts_role_arn):
    """子使用者角色扮演擷取臨時身份的資訊
    :param access_key_id: 子使用者的 access key id
    :param access_key_secret: 子使用者的 access key secret
    :param sts_role_arn: STS角色的Arn
    :return StsInfo 傳回臨時身份資訊對象
    """
    # 配置要通路的STS endpoint
    REGIONID = 'cn-hongkong'
    ENDPOINT = 'sts.cn-hongkong.aliyuncs.com'
    region_provider.add_endpoint('Sts', REGIONID, ENDPOINT)

    clt = client.AcsClient(access_key_id, access_key_secret, 'cn-hongkong')
    request = AssumeRoleRequest.AssumeRoleRequest()

    #request.set_accept_format('json')
    #指定角色ARN
    request.set_RoleArn(sts_role_arn)
    #設定會話名稱,審計服務使用此名稱區分調用者
    request.set_RoleSessionName('oss-python-sdk-example')
    #發起請求,并得到response
    response = clt.do_action_with_exception(request)
    #格式化輸出傳回結果,将字元串結果轉化為字典類型
    i = json.loads(oss2.to_unicode(response))
    #執行個體化StsInfo類,并将通過sts擷取的臨時身份資訊存入
    global StsInfo
    StsInfo = StsInfo()
    StsInfo.access_key_id = i['Credentials']['AccessKeyId']
    StsInfo.access_key_secret = i['Credentials']['AccessKeySecret']
    StsInfo.security_token = i['Credentials']['SecurityToken']
    StsInfo.request_id = i['RequestId']
    StsInfo.expiration = oss2.utils.to_unixtime(i['Credentials']['Expiration'], '%Y-%m-%dT%H:%M:%SZ')

    #傳回StsInfo對象
    return StsInfo
               

将臨時身份資訊存入json檔案

根據需求,可将臨時身份資訊存儲到json檔案中,等到臨時身份過期後再重新請求,避免重複請求,造成臨時身份泛濫,引發資源匮乏與安全隐患

def save_info():
    #存儲臨時身份資訊
    with open('StsInfo.json','w',encoding='utf-8') as f:
        data = {'sts_key_id':StsInfo.access_key_id,'sts_key_secret':StsInfo.access_key_secret,'sts_secrity_token':StsInfo.security_token,'sts_expire_date':StsInfo.expiration,'sts_reques_id':StsInfo.request_id}
        json.dump(data,f,ensure_ascii=False)
        f.close
        
def open_info():
    #讀取臨時身份資訊
    with open('./StsInfo.json','r',encoding='utf-8') as f:
        global STSINFO
        STSINFO = json.load(f)
        return STSINFO           

通過臨時身份操作Bucket資源

def buck_put_object():
    #列印驗證臨時身份資訊
    print(StsInfo)
    print('key id:',StsInfo.access_key_id)
    print("key_secret:",StsInfo.access_key_secret)
    print("secrity_token:",StsInfo.security_token)
    print("request_id:",StsInfo.request_id)
    print("expiration:",StsInfo.expiration)
    
    #執行個體化Bucket對象,并上傳字元串
    auth = oss2.StsAuth(StsInfo.access_key_id, StsInfo.access_key_secret, StsInfo.security_token)
    bucket = oss2.Bucket(auth,endpoint,'fralychen')
    result = bucket.put_object('fralychen','good good study day day up')           

全部代碼

# -*- conding:utf-8 -*-
import json
import os

import oss2

from aliyunsdkcore import client
from aliyunsdkcore.profile import region_provider
from aliyunsdksts.request.v20150401 import AssumeRoleRequest

##定義一些變量
access_key_id = 'LTAI4FoMe6umpCSFQdEC9neg' 
access_key_secret = 'jgEvtFOqIAGqKZve7zMvg8dJhSZv9J'
bucket_name = 'fralychen'
endpoint = 'oss-cn-hongkong.aliyuncs.com'
sts_role_arn = 'acs:ram::1149877324567510:role/testrole'



# 确認上面的參數都填寫正确了
for param in (access_key_id, access_key_secret, bucket_name, endpoint, sts_role_arn):
    assert '<' not in param, '請設定參數:' + param

#建立StsToken類友善用來存儲臨時身份資訊
class StsInfo(object):
    """AssumeRole傳回的臨時身份資訊
    :param str access_key_id: 臨時身份的access key id
    :param str access_key_secret: 臨時身份的access key secret
    :param int expiration: 過期時間,UNIX時間,自1970年1月1日UTC零點的秒數
    :param str security_token: 臨時身份Token
    :param str request_id: 請求ID
    """
    def __init__(self):
        self.access_key_id = ''
        self.access_key_secret = ''
        self.expiration = 0
        self.security_token = ''
        self.request_id = ''

# 在控制台将 AliyunSTSAssumeRoleAccess 權限授權給RAM子使用者之後才能通過RAM使用者擷取臨時身份資訊
def fetch_sts_info(access_key_id, access_key_secret, sts_role_arn):
    """子使用者角色扮演擷取臨時身份的資訊
    :param access_key_id: 子使用者的 access key id
    :param access_key_secret: 子使用者的 access key secret
    :param sts_role_arn: STS角色的Arn
    :return StsInfo 傳回臨時身份資訊對象
    """
    # 配置要通路的STS endpoint
    _REGIONID = 'cn-hongkong'
    _ENDPOINT = 'sts.cn-hongkong.aliyuncs.com'
    region_provider.add_endpoint('Sts', _REGIONID, _ENDPOINT)

    clt = client.AcsClient(access_key_id, access_key_secret, 'cn-hongkong')
    request = AssumeRoleRequest.AssumeRoleRequest()

    #request.set_accept_format('json')
    #指定角色ARN
    request.set_RoleArn(sts_role_arn)
    #設定會話名稱,審計服務使用此名稱區分調用者
    request.set_RoleSessionName('oss-python-sdk-example')
    #設定臨時身份過期時間
    request.set_DurationSeconds(DurationSeconds)
    #發起請求,并得到response
    response = clt.do_action_with_exception(request)
    #格式化輸出傳回結果,将字元串結果轉化為字典類型
    i = json.loads(oss2.to_unicode(response))
    #執行個體化StsInfo類并将臨時身份資訊存入對象
    global StsInfo
    StsInfo = StsInfo()
    StsInfo.access_key_id = i['Credentials']['AccessKeyId']
    StsInfo.access_key_secret = i['Credentials']['AccessKeySecret']
    StsInfo.security_token = i['Credentials']['SecurityToken']
    StsInfo.request_id = i['RequestId']
    StsInfo.expiration = oss2.utils.to_unixtime(i['Credentials']['Expiration'], '%Y-%m-%dT%H:%M:%SZ')
    

    #存儲臨時身份資訊
    save_info()


#使用sts授權的臨時身份上傳檔案到bucket
def buck_put_object(sts_key_id, sts_key_secret, sts_secrity_token):
    """上傳字元串到資源
    :param sts_key_id: 臨時身份的 access key id
    :param sts_key_secret: 臨時身份的 access key secret
    :param sts_secrity_token: 臨時身份的 secrity token
    :retu
    """ 
    #執行個體化Bucket對象,并上傳字元串
    auth = oss2.StsAuth(sts_key_id, sts_key_secret, sts_secrity_token)
    bucket = oss2.Bucket(auth,endpoint,'fralychen')
    result = bucket.put_object('fralychen','good good study day day up')

#根據需求,可将臨時身份資訊存儲到json檔案中,等到臨時身份過期後再重新請求,避免重複請求,使用者泛濫
def save_info():
    #存儲臨時身份資訊
    with open('StsInfo.json','w',encoding='utf-8') as f:
        data = {'sts_key_id':StsInfo.access_key_id,'sts_key_secret':StsInfo.access_key_secret,'sts_secrity_token':StsInfo.security_token,'sts_expire_date':StsInfo.expiration,'sts_reques_id':StsInfo.request_id}
        json.dump(data,f,ensure_ascii=False)
        f.close


def open_info():
    #讀取臨時身份資訊
    with open('./StsInfo.json','r',encoding='utf-8') as f:
        global STSINFO
        STSINFO = json.load(f)
        return STSINFO


#定義臨時身份過期時間
DurationSeconds = 900

try:
    open_info()
except IOError:
    print("Error: 沒有使用者資訊檔案或檔案讀取失敗")
    print("初始化身份資訊,臨時身份資訊存儲中....")
    fetch_sts_info(access_key_id, access_key_secret, sts_role_arn)
    print("臨時身份資訊存儲完畢,目前目錄下StsInfo.json")
else:
    if oss2.utils.http_to_unixtime(oss2.utils.http_date()) + DurationSeconds > STSINFO["sts_expire_date"]:
        buck_put_object(sts_key_id = STSINFO["sts_key_id"],sts_key_secret = STSINFO["sts_key_secret"], sts_secrity_token = STSINFO["sts_secrity_token"])
        print("上傳成功,good_lucky")
    else:
        print("更新臨時使用者資訊,請稍後")
        fetch_sts_info(access_key_id, access_key_secret, sts_role_arn)
        buck_put_object(sts_key_id = STSINFO["sts_key_id"],sts_key_secret = STSINFO["sts_key_secret"], sts_secrity_token = STSINFO["sts_secrity_token"])
        print("上傳成功,good_lucky")           

join US

STS Python_SDK授權臨時使用者讀寫OSS資源STS Python_SDK授權臨時使用者讀寫OSS資源

STS Python_SDK授權臨時使用者讀寫OSS資源STS Python_SDK授權臨時使用者讀寫OSS資源

暴走小二官方群,歡迎來躁