阿里云账号(主账号)可以通过创建并授权RAM角色的方式授权其他云账号一定的资源权限,其他阿里云账号扮演该角色,并为其名下的RAM用户授予AssumeRole权限之后,其他阿里云账号或RAM用户可以通过访问STS接口获取临时AK和Token令牌,调用日志服务API接口。
方案概览
假设企业A拥有阿里云账号A,企业B拥有阿里云账号B。出于业务隔离或项目外包等需求,企业A希望将部分日志服务业务授权给企业B维护。需求如下:
阿里云账号B拥有向阿里云账号A的日志服务中写入数据和使用消费组的权限。
阿里云账号B的指定RAM用户也拥有日志服务的写入和消费组权限。
阿里云账号B可获取STS临时凭证,访问日志服务API接口。具体操作,请参见什么是STS。
基于以上需求,您可按照以下步骤配置。
步骤一:阿里云账号A为阿里云账号B创建RAM角色并授权
步骤二:阿里云账号B创建RAM用户user-b并授权
步骤三:RAM用户user-b获取STS临时凭证访问日志服务
步骤一:阿里云账号A为阿里云账号B创建RAM角色并授权
在阿里云账号A创建RAM角色,指定阿里云账号B扮演该角色并为角色赋予日志服务的指定权限。
可以通过RAM控制台创建RAM角色。具体操作,请参见创建RAM用户及授权。您也可以通过RAM的API CreateRole创建RAM角色。具体操作,请参见CreateRole。以下以控制台创建为例进行详细步骤说明。
使用阿里云账号A登录RAM控制台。
创建RAM角色,并指定阿里云账号B扮演该角色。具体操作,请参见创建可信实体为阿里云账号的RAM角色。
创建一个自定义权限策略,其中在脚本编辑页签,请使用以下脚本替换配置框中的原有内容。具体操作,请参见通过脚本编辑模式创建自定义权限策略。
如果仅需要写数据,授权脚本如下所示:
{
"Version": "1",
"Statement": [
{
"Action": "log:PostLogStoreLogs",
"Resource": "*",
"Effect": "Allow"
}
]
}
如果需要通过协同消费库获取数据,授权脚本如下所示:
{
"Version": "1",
"Statement": [
{
"Action": [
"log:GetCursorOrData",
"log:CreateConsumerGroup",
"log:ListConsumerGroup",
"log:ConsumerGroupUpdateCheckPoint",
"log:ConsumerGroupHeartBeat",
"log:GetConsumerGroupCheckPoint",
"log:UpdateConsumerGroup"
],
"Resource": "*",
"Effect": "Allow"
}
]
}
重要 以上两类资源都是授权指定用户的所有Project和Logstore,如果您需要授权指定Project和Logstore,请参考如下内容:
完整的资源说明请参见资源列表。
为RAM角色添加创建的自定义权限。具体操作,请参见为RAM角色授权。
步骤二:阿里云账号B创建RAM用户user-b
并授权
在阿里云账号B创建RAM用户user-b
,并为其授予AliyunSTSAssumeRoleAccess
(调用STS AssumeRole接口)的系统策略。
使用阿里云账号B登录RAM控制台。
创建一个RAM用户user-b
,访问方式选择控制台访问和使用永久AccessKey访问。具体操作,请参见创建RAM用户。
为RAM用户添加AliyunSTSAssumeRoleAccess权限,使其可以通过扮演RAM角色来获取临时身份凭证。具体操作,请参见为RAM用户授权。
步骤三:RAM用户user-b
获取STS临时凭证访问日志服务
调用STS AssumeRole接口获取临时AK和Token。更多信息,请参见AssumeRole。
您可以选择以下方式调用该接口:
通过STS SDK调用。更多信息,请参见STS SDK概览。
调用日志服务接口,关于日志服务SDK请参见SDK参考。
示例代码
基于Java SDK,以RAM账号user-b
通过STS向阿里云账号A的Project写入数据为例。示例代码如下所示:
package com.aliyun.openservices.log.sample;
import java.util.Date;
import java.util.Vector;
import com.aliyun.openservices.log.Client;
import com.aliyun.openservices.log.common.LogItem;
import com.aliyun.openservices.log.exception.LogException;
import com.aliyun.openservices.log.request.PutLogsRequest;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.exceptions.ClientException;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.http.ProtocolType;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import com.aliyuncs.sts.model.v20150401.AssumeRoleRequest;
import com.aliyuncs.sts.model.v20150401.AssumeRoleResponse;
public class StsSample {
// now sts only support "cn-hangzhou"
public static final String REGION_CN_HANGZHOU = "cn-hangzhou";
// current sts api version
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 {
// construct Aliyun Acs Client to ivoke OpenAPI
IClientProfile profile = DefaultProfile.getProfile(REGION_CN_HANGZHOU, accessKeyId, accessKeySecret);
DefaultAcsClient client = new DefaultAcsClient(profile);
// create AssumeRoleRequest object
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);
// send request
final AssumeRoleResponse response = client.getAcsResponse(request);
return response;
} catch (ClientException e) {
throw e;
}
}
public static void main(String[] args) {
// only RAM user(sub account)can invoke AssumeRole interface
// Aliyun root account's AccessKeys can't invoke AssumeRole
// please create sub account in RAM web console(https://ram.console.aliyun.com), and create AK for this sub account
String accessKeyId = "<subaccountaccesskey>";
String accessKeySecret = "<subaccountaccesssecret>";
// AssumeRole API parameter: RoleArn, RoleSessionName, Policy, and DurationSeconds
// RoleArn can retrieve in RAM web console
// https://ram.console.aliyun.com/#/role/detail/< specifid rolename>/info
String roleArn = "<rolearn found in web console>";
// RoleSessionName is temporary Token(mainly used for audit)
String roleSessionName = "bluemix-001";
String policy = "{\n" +
" \"Version\": \"1\", \n" +
" \"Statement\": [\n" +
" {\n" +
" \"Action\": \"log:PostLogStoreLogs\",\n" +
" \"Resource\": \"*\",\n" +
" \"Effect\": \"Allow\"\n" +
" }\n" +
" ]\n" +
"}";
System.out.println(policy);
// only support HTTPS here
ProtocolType protocolType = ProtocolType.HTTPS;
AssumeRoleResponse response = new AssumeRoleResponse();
try {
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());
}
// log service parameter
// log service endpoint doc: https://help.aliyun.com/zh/sls/developer-reference/api-sls-2020-12-30-endpoint
String logServiceEndpoint = "cn-hangzhou.log.aliyuncs.com";
// means project region must be cn-hangzhou
String project = "<log service project name>";
String logstore = "<log service logstore name>";
// construct log service client object
Client client = new Client(logServiceEndpoint,
response.getCredentials().getAccessKeyId(),
response.getCredentials().getAccessKeySecret());
// notice: the AK & Security Token will be expire in 1hour
// so you must invoke asumeRole interface when expired
client.SetSecurityToken(response.getCredentials().getSecurityToken());
Vector<LogItem> logGroup = new Vector<LogItem>();
LogItem logItem = new LogItem((int) (new Date().getTime() / 1000));
logItem.PushBack("StsSample", "Send Data");
logGroup.add(logItem);
PutLogsRequest req2 = new PutLogsRequest(project, logstore, "", "", logGroup);
try {
client.PutLogs(req2);
} catch (LogException e) {
System.out.println("Failed to send data.");
System.out.println("Error code: " + e.GetErrorCode());
System.out.println("Error message: " + e.GetErrorMessage());
}
}
}