名詞解釋
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使用者
- 登入 RAM 控制台
- 在左側導航欄的人員管理菜單下,單擊使用者。
-
單擊建立使用者,輸入登入名稱和顯示名稱。
說明 單擊添加使用者,可一次性建立多個 RAM 使用者。
- 在通路方式區域下,選擇控制台密碼登入或程式設計通路。
- 控制台密碼登入:可以完成對登入安全的基本設定,包括自動生成或自定義登入密碼、是否要求下次登入時重置密碼以及是否要求開啟多因素認證。
- 程式設計通路:将會自動為 RAM 使用者建立通路密鑰(AccessKey)。RAM 使用者可以通過 API 或其他開發工具通路阿裡雲。
- 說明 為了保障賬号安全,建議僅為 RAM 使用者選擇一種登入方式。避免 RAM 使用者離開組織後仍可以通過通路密鑰通路阿裡雲資源。
- 單擊确認。
授權RAM使用者AssumeRole接口權限
建立自定義權限政策test_policy
- 在左側導航欄的權限管理菜單下,單擊權限政策管理。
- 單擊建立權限政策。
- 填寫政策名稱和備注。
- 配置模式選擇可視化配置或腳本配置。
- 若選擇可視化配置:單擊添加授權語句,根據界面提示,對權限效力、操作名稱和資源等進行配置。
- 若選擇腳本配置,請參考 文法結構 編輯政策内容。
下面為OSS所有權限文法示例
{
"Statement": [
{
"Action": "oss:*",
"Effect": "Allow",
"Resource": "*"
}
],
"Version": "1"
}
建立角色testRole
注:這裡角色有三種類型,建立可信實體為阿裡雲賬号的RAM角色
- 雲賬号登入 RAM控制台
- 在左側導航欄,單擊RAM角色管理。
- 單擊建立RAM角色。
- 選擇可信實體類型為阿裡雲賬号,單擊下一步。
- 輸入角色名稱和備注。
- 選擇雲賬号後,單擊完成。
将自定義權限政策授權給角色
- 在左側導航欄的權限管理菜單下,單擊授權。
- 單擊新增授權。
- 在被授權主體區域下,輸入 RAM 角色名稱後,單擊需要授權的 RAM 角色。
-
在左側權限政策名稱清單下,單擊需要授予 RAM 角色的權限政策。
說明 在右側區域框,選擇某條政策并單擊 ×,可撤銷該政策。
- 單擊确定。
完成授權後可在角色管理中檢視授權詳情

注:這裡政策主體類型有兩種,權限政策也可直接授權給使用者
通過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
sdkgithub 位址
擷取臨時身份資訊
# 在控制台将 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")