全部產品
Search
文件中心

Simple Log Service:通過STS實現跨帳號訪問Log Service資源

更新時間:Oct 17, 2024

阿里雲帳號(主帳號)可以通過建立並授權RAM角色的方式授權其他雲帳號一定的資源許可權,其他雲帳號扮演該角色,並為其名下的RAM使用者授予AssumeRole許可權之後,其他雲帳號或RAM使用者可以通過訪問STS介面擷取臨時AK和Token令牌,調用Log ServiceAPI介面。

背景資訊

出於業務隔離或專案外包等需求,雲帳號A希望將部分Log Service業務授權給雲帳號B,由雲帳號B操作維護這部分業務。基本需求如下:

  • 雲帳號B擁有向企業A的Log Service中寫入資料和使用消費組的許可權。

  • 雲帳號B的指定RAM使用者也擁有Log Service的寫入和消費組許可權。

  • 雲帳號B可擷取STS臨時憑證,訪問Log ServiceAPI介面。具體操作,請參見STS

操作流程

  1. 雲帳號A建立RAM角色,並指定雲帳號B扮演該角色並賦予Log Service的指定許可權。

  2. 雲帳號B建立RAM使用者B1,並為其賦予AliyunSTSAssumeRoleAccess(調用STS AssumeRole介面)的系統策略。

  3. RAM帳號B1調用STS AssumeRole介面訪問Log ServiceAPI介面,動作記錄服務資源。

步驟1:雲帳號A為雲帳號B建立RAM角色並授權

雲帳號A建立RAM角色,並指定雲帳號B扮演該角色並為角色賦予Log Service的指定許可權。

可以通過RAM控制台建立RAM角色。具體操作,請參見建立RAM使用者及授權。您也可以通過RAM的API CreateRole建立RAM角色。具體操作,請參見CreateRole。以下以控制台建立為例進行詳細步驟說明。

  1. 使用阿里雲帳號(主帳號)或Resource Access Management員登入RAM控制台

  2. 雲帳號A建立RAM角色,並指定雲帳號B扮演該角色。

    1. 在左側導覽列,選擇身份管理 > 角色

    2. 在角色頁面,單擊建立角色

    3. 建立角色面板,選擇可信實體類型為阿里雲帳號,單擊下一步

    4. 輸入角色名稱備忘選擇信任的雲帳號其他雲帳號,填寫雲帳號B的帳號ID,單擊完成

      說明

      將滑鼠移至上方在控制台右上方頭像的位置,即可查詢主帳號ID。

      以上步驟中建立的RAM角色詳情如下。

      {
        "Statement": [
          {
            "Action": "sts:AssumeRole",
            "Effect": "Allow",
            "Principal": {
              "RAM": [
                "acs:ram::<雲帳號B的帳號ID>:root"
              ]
            }
          }
        ],
        "Version": "1"
      }
  3. 建立權限原則。

    1. 在左側導覽列,選擇許可權管理 > 權限原則

    2. 權限原則頁面,單擊建立權限原則

    3. 單擊指令碼編輯

    4. 建立權限原則頁面的指令碼編輯頁簽中,將配置框中的原有指令碼替換為如下內容。

      此處配置的權限原則為雲帳號A授予雲帳號B的許可權內容。

      如果僅需要寫資料,具體許可權如下:

      {
        "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,請參考如下內容:

      • 授權指定Project:acs:log::{projectOwnerAliUid}:project/

      • 授權指定Logstore:acs:log::{projectOwnerAliUid}:project/{projectName}/logstore/{logstoreName}/

      完整的資源說明請參見Log ServiceRAM資源

    5. 編輯完成指令碼後,單擊繼續編輯基本資料,配置如下參數:

      參數

      說明

      名稱

      輸入策略名稱稱。

      備忘

      輸入您需要備忘的內容。

    6. 單擊確定

  4. 雲帳號A為RAM角色授權。

    1. 在左側導覽列,選擇身份管理 > 角色

    2. 角色列表下,找到目標RAM角色,單擊新增授權

    3. 選擇許可權選擇自訂策略並在列表中選中步驟3建立的權限原則,單擊確定

    4. 單擊完成,即完成授權。

步驟2:雲帳號B建立RAM使用者B1並授權

雲帳號B建立RAM使用者B1,並為其授予AliyunSTSAssumeRoleAccess(調用STS AssumeRole介面)的系統策略。

  1. 使用阿里雲帳號(主帳號)或Resource Access Management員登入RAM控制台

  2. 在左側導覽列中,選擇身份管理 > 使用者

  3. 使用者頁面,單擊建立使用者

  4. 建立使用者頁面,參考如下說明進行參數配置並單擊確定

    參數

    說明

    使用者帳號資訊

    請輸入登入名稱稱顯示名稱

    訪問方式

    選中控制台訪問OpenAPI 呼叫訪問

  5. 返回使用者頁面,在使用者登入名稱稱/顯示名稱列表中,找到目標RAM使用者,單擊添加許可權

  6. 添加許可權頁面,授權主體會自動填入。選中系統策略,在權限原則名稱列表下,單擊需要授予RAM角色的權限原則AliyunSTSAssumeRoleAccess,單擊確定

  7. 單擊完成

步驟3:RAM帳號B1擷取STS臨時憑證訪問Log Service

  1. 調用STS AssumeRole介面擷取臨時AK和Token。更多資訊,請參見AssumeRole

    您可以選擇以下方式調用該介面:

    通過STS SDK調用。更多資訊,請參見STS SDK概覽

  2. 調用Log Service介面,關於Log ServiceSDK請參見SDK參考

範例程式碼

基於Java SDK,以RAM帳號B1通過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/document_detail/29008.html
	    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());
	    }
	  }
}