You need to enable JavaScript to run this app.
导航
通过 STS 访问日志服务
最近更新时间:2024.12.13 16:30:46首次发布时间:2022.11.25 21:31:15

您可以通过安全令牌服务 STS 服务申请临时安全令牌,使指定的 IAM 用户在指定时间内访问权限范围内的日志服务资源。本文介绍如何使用 STS 临时安全令牌访问日志服务。

背景信息

STS 是火山引擎提供的一种临时访问权限管理服务,主要用于授权第三方临时访问云服务。例如通过日志服务 SDK 直接上传日志数据到日志服务的场景中,出于安全考虑,不建议将火山引擎账号或 IAM 用户的访问密钥保存在客户端代码中。此时您可以在应用的服务端通过 STS 服务获取临时安全令牌,将临时安全令牌下发给客户端,为第三方自建应用或 IAM 用户颁发一个可以自定义时效和访问权限的临时身份凭证。
相对于使用火山引擎访问密钥,临时安全令牌具备如下优势:

  • 使用临时安全令牌,可减少火山引擎访问密钥泄露的风险。
  • 临时安全令牌可设置自定义时效,到期后自动失效。
  • 临时安全令牌可绑定自定义的权限策略,进一步约束临时安全令牌使用者的权限范围,便于权限的精细化管理。

业务流程

Image

操作步骤

1 创建 IAM 角色并授予日志服务权限

IAM 角色是一种虚拟用户,无永久的身份凭证,只能通过 STS 获取可以自定义时效和访问权限的临时安全令牌,且需要被一个可信的实体身份扮演。在本示例中,您需要创建一个 IAM 角色并为其授权,指定 IAM 角色在被 IAM 用户扮演时所拥有的日志服务资源访问权限。

  1. 通过火山引擎主账号登录访问控制 IAM 控制台
  2. 在左侧导航栏中,选择身份管理 > 角色
  3. 角色页面,单击新建角色
  4. 新建角色面板中,设置选择信任身份类型账号,设置选择身份当前账号,然后单击下一步

    说明

    创建 IAM 角色时授权账号只能设置为本账号,您需要在3 为 IAM 用户授予扮演 IAM 角色的权限和调用 AssumeRole 的权限中变更授权账号为指定的 IAM 用户,便于后续使用 IAM 用户扮演此角色。

  5. 设置角色名,然后单击下一步
  6. 选择 TLSReadOnlyAccess 权限策略,然后单击提交
    此处以为 IAM 角色授予系统默认权限 TLSReadOnlyAccess 为例。授权后,该 IAM 角色具备所有日志服务资源和页面的只读权限。您也可以根据业务需求,创建自定义权限策略。具体步骤请参考新建自定义策略,具体的可授权操作与资源说明请参考可授权的操作可授权的资源

    注意

    出于策略最小化的原则,请谨慎设置 IAM 角色权限。例如在免密登录与控制台内嵌场景下,推荐仅设置指定 Project 或 Topic 的数据查看权限,不设置任何的变更操作权限。

  7. 保存 IAM 角色的 TRN。
    1. 角色页面,单击您所创建的 IAM 角色。
    2. 角色详情页面,获取 IAM 角色的 TRN。
      在调用 AssumeRole 接口时,需要输入该 TRN。
      Image

2 创建 IAM 用户

IAM 用户是一种实体身份类型,拥有确定的身份 ID 和身份凭证、独立的登录密码和访问密钥。您需要创建一个 IAM 用户,用于扮演 IAM 角色,便于后续获取临时安全令牌。本文以通过用户名创建为例,其他创建方式请参考创建用户

说明

日志服务推荐您在日常操作与数据资源管理的场景下使用 IAM 用户进行访问与鉴权,降低火山引擎账号密钥泄露的风险。

  1. 在左侧导航栏中,选择身份管理 > 用户
  2. 用户页面,单击新建用户
  3. 创建用户页面,单击通过用户名创建
  4. 设置用户名,在登录设置中开启编程访问,然后单击下一步
  5. 权限设置步骤,单击下一步
  6. 审阅步骤,确认用户名信息,单击提交

3 授予 IAM 用户扮演 IAM 角色的权限

完成此授权后,IAM 用户才能扮演 IAM 角色去获取 IAM 角色的临时安全令牌,并访问 IAM 角色权限范围内的日志服务资源。
此环节的授权包括以下两部分,均为必选设置。

  • 为 IAM 角色设置信任策略。
    创建 IAM 角色时,默认的可信实体为火山引擎账号,您需要修改 IAM 角色的信任策略,将 Principal 中的账号配置修改为您在2 创建 IAM 用户中创建的 IAM 用户,表示该 IAM 角色可以被指定的 IAM 用户扮演。
  • 为 IAM 用户授予 STSAssumeRoleAccess 权限策略。
    为 IAM 用户授予 STSAssumeRoleAccess 权限策略后,您才能使用 IAM 用户的访问密钥调用 AssumeRole 接口申请临时安全令牌。

授权步骤如下:

  1. 修改 IAM 角色的信任策略。
    1. 在左侧导航栏中,选择身份管理 > 角色

    2. 角色页面,找到并单击您在步骤 1 中创建的角色。

    3. 角色详情页面,单击信任关系

    4. 信任关系页签,单击编辑信任策略

    5. 修改信任策略中的 IAM 字段,并单击保存
      trn 中默认指定的 root 改为 user/${IAMUserName},例如 user/TLSUser。 以下述信任策略为例,该策略表示此 IAM 角色可以被火山引擎账号 21000**** 下的 IAM 用户 TLSUser 扮演。

      {
          "Statement": [
              {
                  "Effect": "Allow",
                  "Action": [
                      "sts:AssumeRole"
                  ],
                  "Principal": {
                      "IAM": [
                          "trn:iam::21000****:user/TLSUser"
                      ]
                  }
              }
          ]
      }
      

      Image

  2. 为 IAM 用户授予 STSAssumeRoleAccess 权限。
    1. 在左侧导航栏中,选择身份管理 > 用户
    2. 用户页面,找到并单击您在2 创建 IAM 用户中创建的用户。
    3. 用户详情页面,选择权限>全局权限,然后单击添加权限
    4. 添加权限面板,选择 STSAssumeRoleAccess 权限策略,并单击确定

4 调用 AssumeRole 获取临时安全令牌

IAM 用户将通过扮演 IAM 角色来调用安全令牌服务的 AssumeRole 接口,并获取 IAM 角色的临时安全令牌。临时安全令牌包括临时访问密钥(AccessKeyId和SecretAccessKey)和 临时 Token(SessionToken)。
请求示例如下,其中参数 RoleTrn 应指定为您在步骤 1 中创建的 IAM 角色的TRN。

GET /?RoleTrn=trn:iam::200000****:role/TLSRole&RoleSessionName=ceshiassume&Action=AssumeRole&Version=2018-01-01 HTTP/1.1
Accept: application/json
Content-Type: application/x-www-form-urlencoded
Host: iam.volcengineapi.com
X-Date: 20180614T131357Z
Authorization: HMAC-SHA256 Credential=AKLT4MQ/20180614/cn-north-1/sts/request, SignedHeaders=accept;content-type;host;x-date, Signature=83671ac2**8a5581f

AssumeRole 接口的返回示例如下:

{
    "ResponseMetadata": {
        "RequestId": "202104124922",
        "Action": "AssumeRole",
        "Version": "2018-01-01",
        "Service": "sts"
    },
    "Result": {
        "Credentials": {
            "CurrentTime": "2021-04-12T10:57:09+08:00",
            "ExpiredTime": "2021-04-12T11:57:09+08:00",
            "AccessKeyId": "AKTPODg0MzV**2ZDc***",
            "SecretAccessKey": "TVRNNVlqRmxPR1mRoTkdWbE1E****",
            "SessionToken": "STSeyJBY2NvdW50SWklkZW50aXR5VHlwZSI6NCwiSWRlbnRpdHlJZCI6MzAyMTcsIkNoYW5uZWwiOiJyZXNvdXJjZSIsIkFjY2Vzc0tleUlkIjoiQUtUUE9EZzBNelZrWlRNMVlqQXlOR05sWkdGbU0yVTNaVEl6T0RnMlpEY3hNRGciLCJTaWduZWRTZWNyZXRBY2Nlc3NLZXkiOiJHSHRuc2Q1b3BOOThUeUNrckVuMVAxTDd1ZzBXczZFMytzTktDMDJQT01lNzFMOUloNzhYaDB5VXE4Ni9JMW8reEZxTmtkK01tVUR0cjRHR0NodXJQdz09IiwiRXhwaXJlZFRpbWUiOjE2MTgxOTk4MjksIlBvbGljeVN0cmluZyI6IiIsIlNpZ25hdHVyZSI6IjdiZTEzNTU1MDM5NzcyM2VkMDQxYmVkNTIyNzU4YmMyNjQ3YzRmNzZiNmRjYTViNzVhZDUyOTMwYTg1NjE5ZGEiLCJTZXNzaW9uTmFtZSI6ImNlc2hpYXNzdW1****"
        },
        "AssumedRoleUser": {
            "Trn": "trn:sts::20**94:assumed-role/TLSRole/ceshiassume",
            "AssumedRoleId": "**:ceshiassume"
        }
    }
}

5 使用临时安全令牌访问日志服务

获取临时安全令牌后,您可以通过该临时安全令牌完成 SDK 鉴权,然后通过 SDK 访问日志服务。日志服务提供的 SDK 以及相关示例代码请参考 SDK 列表。 例如参考如下 Python SDK 示例,完成创建日志项目、创建日志主题、配置索引、写入日志、消费日志及查询日志等操作。

说明

  • 临时安全令牌默认有效期为 1 小时,到期后需要及时更新临时安全令牌。
  • 您可以通过 AssumeRole 的 DurationSeconds 参数设置临时安全令牌的有效期。DurationSeconds 参数单位为秒,最大可设置 12 小时。
# coding=utf-8 
from __future__ import absolute_import 
from __future__ import division 
from __future__ import print_function 
 
import time 
 
from volcengine.tls.TLSService import TLSService 
from volcengine.tls.tls_requests import * 
 
 
if __name__ == "__main__": 
    # 初始化客户端时,推荐通过环境变量动态获取火山引擎密钥等身份认证信息,以免 AccessKey 硬编码引发数据安全风险。详细说明请参考 https://www.volcengine.com/docs/6470/1166455。  
    # 使用 STS 时,VOLCENGINE_ACCESS_KEY_ID 和 VOLCENGINE_ACCESS_KEY_SECRET 均使用临时访问密钥,且需设置 VOLCENGINE_TOKEN。
    endpoint = os.environ["VOLCENGINE_ENDPOINT"] 
    region = os.environ["VOLCENGINE_REGION"] 
    access_key_id = os.environ["VOLCENGINE_ACCESS_KEY_ID"] 
    access_key_secret = os.environ["VOLCENGINE_ACCESS_KEY_SECRET"] 
 
    # 初始化 TLS 客户端。 
    tls_service = TLSService(endpoint, access_key_id, access_key_secret, region) 
 
    # 创建日志项目。
    create_project_request = CreateProjectRequest(project_name="project-name", region=region, 
                                                  description="project-description") 
    create_project_response = tls_service.create_project(create_project_request) 
    project_id = create_project_response.project_id 
 
    # 创建日志主题。
    create_topic_request = CreateTopicRequest(topic_name="topic-name", project_id=project_id, 
                                              ttl=3650, description="topic-description", shard_count=2) 
    create_topic_response = tls_service.create_topic(create_topic_request) 
    topic_id = create_topic_response.topic_id 
 
    # 配置索引。
    full_text = FullTextInfo(case_sensitive=False, delimiter=",-;", include_chinese=False) 
    value_info_a = ValueInfo(value_type="text", delimiter="", case_sensitive=True, 
                             include_chinese=False, sql_flag=False) 
    value_info_b = ValueInfo(value_type="long", delimiter="", case_sensitive=False, 
                             include_chinese=False, sql_flag=True) 
    key_value_info_a = KeyValueInfo(key="key1", value=value_info_a) 
    key_value_info_b = KeyValueInfo(key="key2", value=value_info_b) 
    key_value = [key_value_info_a, key_value_info_b] 
    create_index_request = CreateIndexRequest(topic_id, full_text, key_value) 
    create_index_response = tls_service.create_index(create_index_request) 
 
    # 写入日志。
    logs = PutLogsV2Logs(source="192.168.1.1", filename="sys.log") 
    for i in range(100): 
        logs.add_log(contents={"key1": "value1-" + str(i + 1), "key2": "value2-" + str(i + 1)}, 
                     log_time=int(round(time.time()))) 
    tls_service.put_logs_v2(PutLogsV2Request(topic_id, logs)) 
    time.sleep(30) 
 
    # 查询消费游标。
    describe_cursor_request = DescribeCursorRequest(topic_id, shard_id=0, from_time="begin") 
    describe_cursor_response = tls_service.describe_cursor(describe_cursor_request) 
 
    # 消费日志。 
    consume_logs_request = ConsumeLogsRequest(topic_id, shard_id=0, cursor=describe_cursor_response.cursor) 
    consume_logs_response = tls_service.consume_logs(consume_logs_request) 
 
    # 当您需要检索分析日志时,推荐您使用 Python SDK 提供的 search_logs_v2 方法,下面的代码提供了具体的调用示例。 
    # 检索日志(全文检索)。 
    search_logs_request = SearchLogsRequest(topic_id, query="error", limit=10, 
                                            start_time=1346457600000, end_time=1630454400000) 
    search_logs_response = tls_service.search_logs_v2(search_logs_request) 
 
    # 检索日志(键值检索)。
    search_logs_request = SearchLogsRequest(topic_id, query="key1:error", limit=10, 
                                            start_time=1346457600000, end_time=1630454400000) 
    search_logs_response = tls_service.search_logs_v2(search_logs_request) 
 
    # 检索分析日志。
    search_logs_request = SearchLogsRequest(topic_id, query="* | select key1, key2", limit=10, 
                                            start_time=1346457600000, end_time=1630454400000) 
    search_logs_response = tls_service.search_logs_v2(search_logs_request) 
 
    # 检索分析日志。
    search_logs_request = SearchLogsRequest(topic_id, query="* | select key1, key2", limit=10, 
                                            start_time=1346457600000, end_time=1630454400000) 
    search_logs_response = tls_service.search_logs(search_logs_request)