企業(yè)上云首當其沖的就是要考量安全性的問題。為了保證系統(tǒng)的安全,和數(shù)據(jù)的安全,公司必須制定訪問控制策略。首先看看現(xiàn)在的云平臺對于身份認證與訪問控制的設(shè)計。
Microsoft Azure
Azure 資源的基于角色的訪問控制 (RBAC)
Role-Based Access Control :其基本思想是,對系統(tǒng)操作的各種權(quán)限不是直接授予具體的用戶,而是在用戶集合與權(quán)限集合之間建立一個角色集合。每一種角色對應(yīng)一組相應(yīng)的權(quán)限。一旦用戶被分配了適當?shù)慕巧?,該用戶就擁有此角色的所有操作?quán)限。
RBAC 的作用示例
- 讓一個用戶管理訂閱中的虛擬機,另一個用戶管理虛擬網(wǎng)絡(luò)
- 讓 DBA 組管理訂閱中的 SQL 數(shù)據(jù)庫
- 讓某個用戶管理資源組中的所有資源,例如虛擬機、網(wǎng)站和子網(wǎng)
- 允許某個應(yīng)用程序訪問資源組中的所有資源
Azure提到使用RBAC的最佳做法是授予用戶完成工作所需的最低權(quán)限。使用 RBAC,可以在團隊中實現(xiàn)職責分離,僅向用戶授予執(zhí)行作業(yè)所需的訪問權(quán)限。 無需向每個人授予 Azure 訂閱或資源的無限制權(quán)限,可以僅允許在特定的范圍執(zhí)行某些操作。
RBAC 的工作原理
RBAC 控制資源訪問權(quán)限的方式是創(chuàng)建角色分配。角色分配包含三個要素:安全主體(Security Principal)、角色定義(Role Definition)和范圍(Scope)。
安全主體(Security Principal)
安全主體是一個對象,表示請求訪問 Azure 資源的用戶、組、服務(wù)主體或托管標識。
- 用戶(User) - 在 Azure Active Directory 中具有配置文件的人員。
- 組(Group) - 在 Azure Active Directory 中創(chuàng)建的一組用戶。 將某個角色分配到某個組時,該組中的所有用戶都擁有該角色。
- 服務(wù)主體(Service principal) - 應(yīng)用程序或服務(wù)用來訪問特定 Azure 資源的安全標識。 可將服務(wù)主體視為應(yīng)用程序的用戶標識(用戶名和密碼或證書)。
- 托管標識(Managed identity) - Azure Active Directory 中由 Azure 自動托管的標識。 在開發(fā)云應(yīng)用程序時,通常使用托管標識來管理用于向 Azure 服務(wù)進行身份驗證的憑據(jù)。
角色定義(Role Definition)
角色定義是權(quán)限的集合。角色定義列出可以執(zhí)行的操作,例如讀取、寫入和刪除。
Azure 包含多個可用的內(nèi)置角色。分別擁有相應(yīng)的權(quán)限。例如下面四個基本的內(nèi)置角色。
范圍(Scope)
角色分配是出于授予訪問權(quán)限的目的,將角色定義附加到特定范圍內(nèi)的用戶、組、服務(wù)主體或托管標識的過程。 通過創(chuàng)建角色分配來授予訪問權(quán)限,通過刪除角色分配來撤銷訪問權(quán)限。
下圖顯示了角色分配的示例。 在此示例中,為“營銷”組分配了醫(yī)藥銷售資源組的參與者角色。 這意味著,“營銷”組中的用戶可以在醫(yī)藥銷售資源組中創(chuàng)建或管理任何 Azure 資源。
RBAC 是一個加法模型,生效的權(quán)限是角色分配相加。其中在訂閱范圍內(nèi)向用戶授予了“參與者”角色,并且授予了對資源組的“讀者”角色。 “參與者”權(quán)限與“讀者”權(quán)限相加實際上是資源組的“參與者”角色。 因此,在這種情況下,“讀者”角色分配沒有任何影響。
更加重要是Azue RBAC是如何確定用戶是否有權(quán)限訪問資源
步驟:
- 用戶(或服務(wù)主體)獲取 Azure 資源管理器的令牌。令牌包含用戶的組成員身份(包括可傳遞的組成員身份)。
- 用戶使用附加的令牌對 Azure 資源管理器發(fā)出 REST API 調(diào)用。
- Azure 資源管理器檢索適用于對其執(zhí)行操作的資源的所有角色分配和拒絕分配。
- Azure 資源管理器縮小適用于此用戶或其組的角色分配范圍,并確定用戶針對此資源擁有的角色。
- Azure 資源管理器確定 API 調(diào)用中的操作是否包含在用戶針對此資源擁有的角色中。
- 如果用戶在請求的范圍內(nèi)沒有具有該操作的角色,則不授予訪問權(quán)限。 否則,Azure 資源管理器會檢查是否適用拒絕分配。
- 如果拒絕分配適用,則阻止訪問。 否則授予訪問權(quán)限。
阿里云
訪問控制(RAM)
訪問控制(Resource Access Management)是阿里云提供的管理用戶身份與資源訪問權(quán)限的服務(wù)。RAM也是按需為用戶分配最小權(quán)限。
RAM的功能特性如下:
- 集中控制RAM用戶及其密鑰:管理每個RAM用戶及其訪問密鑰,為用戶綁定多因素認證(MFA)設(shè)備。
- 集中控制RAM用戶的訪問權(quán)限:控制每個RAM用戶訪問資源的權(quán)限。
- 集中控制RAM用戶的資源訪問方式:確保RAM用戶在指定的時間和網(wǎng)絡(luò)環(huán)境下,通過安全信道訪問特定的阿里云資源。
- 集中控制云資源:對RAM用戶創(chuàng)建的實例或數(shù)據(jù)進行集中控制。當用戶離開組織時,實例或數(shù)據(jù)不會丟失。
- 單點登錄管理(SSO):支持與企業(yè)身份提供商(IdP)進行用戶SSO或角色SSO。
RAM 的工作原理
RAM的主要要素是RAM用戶,用戶組,RAM角色。
RAM用戶
RAM用戶是RAM中的一種身份,對應(yīng)某一個操作實體(運維操作人員或應(yīng)用程序)。通過創(chuàng)建新的RAM用戶并授權(quán),RAM用戶便可以訪問相關(guān)資源。有確定的身份ID和身份憑證,它通常與某個確定的人或應(yīng)用程序一一對應(yīng)。
-
用戶管理與分權(quán)
當企業(yè)有多種云資源時,使用RAM的身份管理與權(quán)限管理功能,實現(xiàn)用戶分權(quán)及資源統(tǒng)一管理。
用戶管理與分權(quán)
用戶組
若云賬號下有多個RAM用戶,通過創(chuàng)建用戶組對職責相同的RAM用戶進行分類并授權(quán),從而更好的管理用戶及其權(quán)限。
RAM角色
RAM角色有確定的身份,可以被賦予一組權(quán)限策略,但沒有確定的登錄密碼或訪問密鑰。RAM角色需要被一個受信的實體用戶扮演,扮演成功后實體用戶將獲得RAM角色的安全令牌,使用這個安全令牌就能以角色身份訪問被授權(quán)的資源。
角色ARN(Role ARN)
ARN是角色的全局資源描述符,用來指定具體角色。ARN遵循阿里云ARN的命名規(guī)范。例如,某個云賬號下的devops角色的ARN為:acs:ram::123456789012****:role/samplerole。可信實體(Trusted entity)
角色的可信實體是指可以扮演角色的實體用戶身份。創(chuàng)建角色時必須指定可信實體,角色只能被受信的實體扮演??尚艑嶓w可以是受信的阿里云賬號、受信的阿里云服務(wù)或身份提供商。-
權(quán)限策略(Policy)
一個角色可以綁定一組權(quán)限策略。沒有綁定權(quán)限策略的角色也可以存在,但不能訪問資源。
RAM中權(quán)限策略的語法和結(jié)構(gòu) 可以自己查看
其中權(quán)限策略結(jié)構(gòu)包括:版本號,授權(quán)語句列表。每條授權(quán)語句包括授權(quán)效力(Effect)、操作(Action)、資源(Resource)以及限制條件(Condition,可選項)。
image.png
權(quán)限策略模型可以分為兩種:
云賬號內(nèi)授權(quán)模型
image.png
資源組內(nèi)授權(quán)模型
image.png 扮演角色(Assume role)
扮演角色是實體用戶獲取角色身份的安全令牌的方法。一個實體用戶調(diào)用STS API AssumeRole可以獲得角色的安全令牌,使用安全令牌可以訪問云服務(wù)API。角色令牌(Role token)
角色令牌是角色身份的一種臨時訪問密鑰。角色身份沒有確定的訪問密鑰,當一個實體用戶要使用角色時,必須通過扮演角色來獲取對應(yīng)的角色令牌,然后使用角色令牌來調(diào)用阿里云服務(wù)API。
RAM角色的使用方法
RAM角色指定可信實體,即指定可以扮演角色的實體用戶身份。
-
可信實體通過控制臺或調(diào)用API扮演角色并獲取角色令牌。
說明 扮演角色是實體用戶獲取RAM角色令牌的方法,角色令牌是角色身份的一種臨時訪問憑證,使用角色令牌可以訪問阿里云資源。 -
為RAM角色綁定權(quán)限策略
說明 一個RAM角色可以綁定一組權(quán)限策略,沒有綁定權(quán)限策略的角色也可以存在,但不能訪問資源。
受信實體通過扮演角色,使用角色令牌訪問阿里云資源。
可以看出Azure 與阿里云 實現(xiàn)訪問控制的模型上大同小異
訪問控制身份認證實現(xiàn)
阿里云
阿里云的訪問控制:單點登錄(SSO),開放授權(quán)管理(OAuth);
點擊可以參考 SSO 和 OAuth 原理
無論哪種方式登錄的API,RAM服務(wù)會對每個訪問的請求進行身份驗證,無論使用HTTP還是HTTPS協(xié)議提交請求,都需要在請求中包含簽名信息。
RAM計算簽名
RAM通過使用AccessKey ID和AccessKeySecret進行對稱加密的方法來驗證請求的發(fā)送者身份。AccessKey ID和AccessKeySecret由阿里云頒發(fā)給訪問者,其中AccessKey ID用于標識訪問者的身份,AccessKeySecret用于加密簽名字符串和服務(wù)器端驗證簽名字符串的密鑰,必須嚴格保密謹防泄露。API網(wǎng)關(guān)計算簽名例子
計算簽名可以
- 校驗請求參數(shù)是否被篡改。
- 請求來源是否合法。
- 請求是否具有唯一性。
它要求調(diào)用方按照約定好的算法生成簽名字符串,作為請求的一部分,接口提供方驗算簽名即可知是否合法。
那么如果一個系統(tǒng)也要實現(xiàn)計算簽名該怎么做呢?
主要步驟:
- 接口提供方給出appKey和appSecret
- 調(diào)用方根據(jù)appId和appSecret以及請求參數(shù),按照一定算法生成簽名sign
- 接口提供方驗證簽名
生成簽名的步驟如下:
1.將所有業(yè)務(wù)請求參數(shù)按字母先后順序排序
2.參數(shù)名稱和參數(shù)值鏈接成一個字符串A
3.在字符串A的首尾加上appSecret組成一個新字符串B
4.對字符串進行HmacSHA256得到簽名sign
5.使用Base64生產(chǎn)簽名字符串
看看阿里云API網(wǎng)關(guān)設(shè)置的簽名的元素有哪些
系統(tǒng)級 Header
【必選】X-Ca-Key:AppKey。
【必選】X-Ca-Signature:簽名字符串。
【可選】X-Ca-Timestamp:API 調(diào)用者傳遞時間戳,值為當前時間的毫秒數(shù),也就是從1970年1月1日起至今的時間轉(zhuǎn)換為毫秒,時間戳有效時間為15分鐘。(保證請求的唯一性)
【可選】X-Ca-Nonce:API 調(diào)用者生成的 UUID,結(jié)合時間戳防重放。
【可選】Content-MD5 當請求 Body 非 Form 表單時,可以計算 Body 的 MD5 值傳遞給云網(wǎng)關(guān)進行 Body MD5 校驗。(防止內(nèi)容別篡改)
【可選】X-Ca-Stage請求 API 所屬 Stage,目前僅支持 TEST 、PRE 和 RELEASE,默認RELEASE,若您調(diào)用的 API 不在線上環(huán)境,請一定要指定該參數(shù)的值,否則會報 URL 錯誤。
Example:
httpget
public static Response httpGet(String host, String path, int connectTimeout, Map<String, String> headers, Map<String, String> querys, List<String> signHeaderPrefixList, String appKey, String appSecret)
throws Exception {
headers = initialBasicHeader(HttpMethod.GET, path, headers, querys, null, signHeaderPrefixList, appKey, appSecret);
HttpClient httpClient = wrapClient(host);
httpClient.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT, getTimeout(connectTimeout));
HttpGet get = new HttpGet(initUrl(host, path, querys));
for (Map.Entry<String, String> e : headers.entrySet()) {
get.addHeader(e.getKey(), MessageDigestUtil.utf8ToIso88591(e.getValue()));
}
return convert(httpClient.execute(get));
}
initialBasicHeader
private static Map<String, String> initialBasicHeader(String method, String path,
Map<String, String> headers,
Map<String, String> querys,
Map<String, String> bodys,
List<String> signHeaderPrefixList,
String appKey, String appSecret)
throws MalformedURLException {
if (headers == null) {
headers = new HashMap<String, String>();
}
headers.put(SystemHeader.X_CA_TIMESTAMP, String.valueOf(new Date().getTime()));
//headers.put(SystemHeader.X_CA_X_CA_TIMESTAMPNONCE, UUID.randomUUID().toString());
headers.put(SystemHeader.X_CA_KEY, appKey);
headers.put(SystemHeader.X_CA_SIGNATURE,
SignUtil.sign(appSecret, method, path, headers, querys, bodys, signHeaderPrefixList));
return headers;
}
sign
public static String sign(String secret, String method, String path,
Map<String, String> headers,
Map<String, String> querys,
Map<String, String> bodys,
List<String> signHeaderPrefixList) {
try {
Mac hmacSha256 = Mac.getInstance(Constants.HMAC_SHA256);
byte[] keyBytes = secret.getBytes(Constants.ENCODING);
hmacSha256.init(new SecretKeySpec(keyBytes, 0, keyBytes.length, Constants.HMAC_SHA256));
hmacSha256.
return new String(Base64.encodeBase64(
hmacSha256.doFinal(buildStringToSign(method, path, headers, querys, bodys, signHeaderPrefixList)
.getBytes(Constants.ENCODING))),
Constants.ENCODING);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
從而進行計算簽名
那么后端如何校驗簽名呢?
主要步驟如下:
- 得到請求方攜帶的API簽名。
- 將所有業(yè)務(wù)請求參數(shù)按字母先后順序排序。
- 參數(shù)名稱和參數(shù)值鏈接成一個字符串A。
- 在字符串A的首尾加上apiSecret接口密匙組成一個新字符串B。
- 對新字符串B進行HMAC_SHA256散列運算生成服務(wù)器端的API簽名,將客戶端的API簽名進行Base64解碼,然后開始驗證簽名。
- 如果服務(wù)器端生成的API簽名與客戶端請求的API簽名是一致的,則請求是可信的,否則就是不可信的。
API鑒權(quán)
先看看阿里云的RAM鑒權(quán)
阿里云使用權(quán)限來描述用戶、用戶組、角色對具體資源的訪問能力。
權(quán)限策略(Policy)
權(quán)限策略是用語法結(jié)構(gòu)描述的一組權(quán)限的集合,可以精確地描述被授權(quán)的資源集、操作集以及授權(quán)條件。
通過為RAM用戶、用戶組或RAM角色綁定權(quán)限策略,可以獲得權(quán)限策略中指定的訪問權(quán)限。
-
- 效力(Effect):授權(quán)效力包括兩種:允許(Allow)和拒絕(Deny)。
- 操作(Action):操作是指對具體資源的操作。
- 資源(Resource):資源是指被授權(quán)的具體對象。
- 限制條件(Condition): 限制條件是指授權(quán)生效的限制條件。
-
策略結(jié)構(gòu)
Example:
- 通過指定的IP地址訪問阿里云
{
"Statement": [
{
"Action": "ecs:*",
"Effect": "Allow",
"Resource": "*",
"Condition": {
"IpAddress": {
"acs:SourceIp": "192.168.0.0/16"
}
}
}
],
"Version": "1"
}
- 在指定的時間段訪問阿里云。
{
"Statement": [
{
"Action": "ecs:*",
"Effect": "Allow",
"Resource": "*",
"Condition": {
"DateLessThan": {
"acs:CurrentTime": "2019-08-12T17:00:00+08:00"
}
}
}
],
"Version": "1"
}
- 列出并讀取一個存儲空間中的資源。
{
"Version": "1",
"Statement": [
{
"Effect": "Allow",
"Action": "oss:ListObjects",
"Resource": "acs:oss:*:*:myphotos"
},
{
"Effect": "Allow",
"Action": "oss:GetObject",
"Resource": "acs:oss:*:*:myphotos/*"
}
]
}
RAM鑒權(quán)
規(guī)則
- 以主賬號身份訪問
- 以RAM用戶身份訪問
- 以RAM角色身份訪問
主要講一下RAM角色身份訪問
訪問令牌
阿里云臨時安全令牌(Security Token Service,STS)是阿里云提供的一種臨時訪問權(quán)限管理服務(wù)。
接下來是,“阿里云讓你模仿,但沒有讓你超越”
假如我們有一個菜單API如下:
- API1: http://localhost:8001/cargosmart/ssm2014/city/listCitys
- API2: http://localhost:8002/cargosmart/ssm2014/port/createPort
- API3: http://localhost:8003/cargosmart/ssm2014/carrier/deteleCarrier
我需要這個三個接口進行安全訪問控制;
1.API保護,可以設(shè)計自己的計算簽名
2.API鑒權(quán)
需要的元素:
-
身份類別
身份類別
2.權(quán)限策略結(jié)構(gòu)
json格式:
API1: http://localhost:8001/cargosmart/ssm2014/city/listCitys
{
"Statement": [
{
"Action": "ssm2014:listCitys",
"Effect": "Allow",
"Resource": [
"cs:ssm2014:123456:user/UserName",
"cs:ssm2014:123456:group/groupName" ,
"cs:ssm2014:123456:role/roleName"],
"Condition": {
"DateLessThan": {
"acs:CurrentTime": "2020-04-10T17:00:00+08:00"
}
}
}
],
}
API2: http://localhost:8002/cargosmart/ssm2014/port/createPort
{
"Statement": [
{
"Action": "ssm2014:createPort",
"Effect": "Deny",
"Resource": [
"cs:ssm2014:23456:user/UserName",
"cs:ssm2014:*:group/groupName" ,
"cs:ssm2014:23456:role/roleName"],
"Condition": {
"DateLessThan": {
"acs:CurrentTime": "2020-04-10T17:00:00+08:00"
}
}
}
],
}