【OSS 最佳實踐】OSS 操作權限控製
用戶操作 OSS 時是需要根據賬號的 AccessKeyId 和 AccessKeySecret (後續簡稱 AK 和 SK )進行權限驗證的,這裏的 AK 和 SK 包括有多種類型:主賬號的 AK 和 SK 、子賬號的 AK 和 SK 以及 STS 生成的臨時 AK 、 SK 和 Token 。那麼他們之間有什麼區別呢?具體應該如何配置使用呢?本文將帶大家一起認識相關概念。
1. 概念區別
主賬號的 AK 和 SK 是主賬號對應的權限標識,也就是說主賬號的每對 AK和 SK 是擁有賬號下的所有權限的,不僅僅可以操作 OSS,還包括 ECS 、 RDS 等其他產品都是可以操作的。因此該對 AK 和 SK 是必須要安全保管的,是不能隨便泄露出去的;並且主賬號的 AK 和 SK 盡量避免所有賬號使用者均知道,建議僅極少數的賬號管理者進行控製和知曉。
子賬號的 AK 和 SK 是主賬號將賬號內的部分權限通過賦權的方式提供給子賬號,後續子賬號即可以使用自己的賬號和密碼或者 AK 和 SK 操作允許的操作。該子賬號的 AK 和 SK 是有永久時效性的,也就是說在主賬號沒有取消權限之前都是有效的,因此子賬號建議提供給公司內部賬號的使用者或者開發人員。
STS 生成的臨時 AK 、 SK 和 Token 與子賬號類似,也是需要通過賦權的方式單獨賦權給該 Token 的,但是有一點和子賬號的 AK 和 SK 相區別的就是該 Token 是有有效時間的。該 Token 盡可以在有效時間內操作賦予的權限,超過該時間後即需要重新獲取新的 Token 才可以正常操作。
2. 獲取方法
2.1 主賬號的 AK 和 SK
主賬號的 AK 和 SK 可以主賬號登陸後直接查看到,如圖 1 中的截圖。主賬號可以創建五對 AK 和 SK ,每對 AK 和 SK 都是擁有賬號的所有權限的,使用時可直接應用其中的一對操作即可完成。主賬號的使用方法最為便捷。
圖 1. 主賬號 AK 和 SK 示意圖
**2.2 子賬號的 AK 和 SK **
子賬號的 AK 和 SK 是需要通過訪問控製控製台得到的。首先需要創建 RAM 子賬號,創建的方法請參考:訪問控製創建子賬號。
注意:
1. 子賬號的 AK 對應的 SK 是僅有在創建的時候可以查看到的,後續將無法再顯示;因此您需要自行記錄好對應的 AK 和 SK 的值。
2. 子賬號如果需要使用阿裏雲的控製台登陸的話是需要開啟該功能的,請您參考圖 2 。
圖 2. 子賬號開啟控製台登陸示意圖
在創建完成子賬號後該用戶需要操作 OSS 就需要將相關的權限賦權給該子賬號。授權的方法請您參考:子賬號賦權操作。配置完成後即可通過使用該對 AK 和 SK 操作 OSS 了。
2.3 STS 的 AK 、 SK 和 Token
STS 的 Token 相比於上麵的兩種方式來說更加的具有安全性但同時其獲取方法和處理邏輯都會更加複雜。具體的生成步驟包括以下幾步:
1. 創建生成 Token 的子賬號。因為 STS 的 Token 是需要子賬號調用 assumerole 接口,因此第一步即是創建 RAM 子賬號並且賦權 AliyunSTSAssumeRoleAccess 權限。該權限即是可以調用 assumerole 接口的權限。
圖 3. 子賬號賦權示意圖
2. 創建角色。角色是訪問控製的一種虛擬身份,當子賬號扮演 RAM 角色時即獲得 RAM 角色的臨時安全令牌,使用這個臨時安全令牌就能以角色身份訪問被授權的資源。而創建的步驟是創建用戶角色(如圖 4 )->選擇賬號,並填寫當前 UID (如圖 5 )->填寫用戶角色名稱。
圖 4. 創建用戶角色示意圖
圖 5. 角色選擇賬號示意圖
3. 給角色賦予 OSS 操作權限。由於子賬號扮演角色操作 OSS 是需要角色有操作 OSS 的權限的,這裏我們先賦予 AliyunOSSFullAccess 權限。配置如圖 6 所示。
圖 6. 角色賦權示意圖
4. 調用 STS 的 assumerole 接口,其中包括子賬號的 AK 和 SK ,角色的 Arn 以及用戶自定義 Policy 權限參數。示例代碼如下所示:
public class NewStsServiceSample {
// 目前隻有"cn-hangzhou"這個region可用, 不要使用填寫其他region的值
public static final String REGION_CN_HANGZHOU = "cn-hangzhou";
// 當前 STS API 版本
public static final String STS_API_VERSION = "2015-04-01";
static AssumeRoleResponse assumeRole(String accessKeyId, String accessKeySecret,
String roleArn, String roleSessionName, String policy,
ProtocolType protocolType) throws ClientException {
try {
// 創建一個 Aliyun Acs Client, 用於發起 OpenAPI 請求
IClientProfile profile = DefaultProfile.getProfile(REGION_CN_HANGZHOU, accessKeyId, accessKeySecret);
DefaultAcsClient client = new DefaultAcsClient(profile);
// 創建一個 AssumeRoleRequest 並設置請求參數
final AssumeRoleRequest request = new AssumeRoleRequest();
request.setVersion(STS_API_VERSION);
request.setMethod(MethodType.POST);
request.setProtocol(protocolType);
request.setRoleArn(roleArn);
request.setRoleSessionName(roleSessionName);
request.setPolicy(policy);
request.setDurationSeconds((long)900);
// 發起請求,並得到response
final AssumeRoleResponse response = client.getAcsResponse(request);
return response;
} catch (ClientException e) {
throw e;
}
}
public static void main(String[] args) throws MalformedURLException, IOException {
// 隻有 RAM用戶(子賬號)才能調用 AssumeRole 接口
// 阿裏雲主賬號的AccessKeys不能用於發起AssumeRole請求
// 請首先在RAM控製台創建一個RAM用戶,並為這個用戶創建AccessKeys
String accessKeyId = "";
String accessKeySecret = "";
// RoleArn 需要在 RAM 控製台上獲取
String roleArn = "";
// RoleSessionName 是臨時Token的會話名稱,自己指定用於標識你的用戶,主要用於審計,或者用於區分Token頒發給誰
// 但是注意RoleSessionName的長度和規則,不要有空格,隻能有'-' '_' 字母和數字等字符
// 具體規則請參考API文檔中的格式要求
String roleSessionName = "alice-001";
// 如何定製你的policy?
String policy = "{\n" +
" \"Version\": \"1\", \n" +
" \"Statement\": [\n" +
" {\n" +
" \"Action\": [\n" +
" \"oss:*\"\n" +
" ], \n" +
" \"Resource\": [\n" +
" \"acs:oss:*:*:*\" \n" +
" ], \n" +
" \"Effect\": \"Allow\"\n" +
" }\n" +
" ]\n" +
"}";
// 此處必須為 HTTPS
ProtocolType protocolType = ProtocolType.HTTPS;
try {
final AssumeRoleResponse response = assumeRole(accessKeyId, accessKeySecret,
roleArn, roleSessionName, policy, protocolType);
System.out.println("Expiration: " + response.getCredentials().getExpiration());
System.out.println("Access Key Id: " + response.getCredentials().getAccessKeyId());
System.out.println("Access Key Secret: " + response.getCredentials().getAccessKeySecret());
System.out.println("Security Token: " + response.getCredentials().getSecurityToken());
} catch (ClientException e) {
System.out.println("Failed to get a token.");
System.out.println("Error code: " + e.getErrCode());
System.out.println("Error message: " + e.getErrMsg());
}
}
}
5.生成 STS 的 AK 、 SK 和 Token 即可以創建 OSSclient 對象,特別需要注意的是最終生成的 AK 、 SK 和 Token 的權限是角色的權限以及 assumerole 接口的 policy 參數的交集。初始化代碼如下所示:
OSSClient Server = new OSSClient(endpoint, response.getCredentials().getAccessKeyId(), response.getCredentials().getAccessKeySecret(),response.getCredentials().getSecurityToken());
3. 權限設置
OSS 針對於所有的 API 接口都分別提供了對應的權限,詳細的 OSS 各接口權限請參考: OSS 接口權限,上麵提供的示例僅僅是所有的 OSS 權限。用戶可以根據具體需要的權限分別設置 Policy 的 Action 。
注意:如果需要子賬號可以通過可視化操作 OSS 的話是必須賦予 oss:ListBuckets 權限的,而該權限暫時僅支持賦權給所有的 Bucket ,因此可視化顯示僅支持顯示所有的 Bucket ,但是具體操作 Bucket 的權限可以根據其他的操作權限控製。
同樣 OSS 是可以限製該子賬號訪問的來源 IP ,在 Policy 中通過 Condition中進行限製,並且可以設置 IP 段限製。具體的示例如下:
"Condition":{
"IpAddress": {
"acs:SourceIp": ["42.120.88.0/24", "42.120.66.0/24"]
}
}
另外用戶可以進賦權給特定的子目錄設置單獨的訪問權限,並且根據不同的場景會有不同的設置方法,請參考: OSS 賦權目錄示例,其他更多的權限設置常見問題請參考: OSS 賦權常見問題。
最後更新:2017-09-16 16:04:30