您可以通过安全令牌服务 STS 服务申请临时安全令牌,使指定的 IAM 用户在指定时间内访问权限范围内的日志服务资源。本文介绍如何使用 STS 临时安全令牌访问日志服务。
STS 是火山引擎提供的一种临时访问权限管理服务,主要用于授权第三方临时访问云服务。例如通过日志服务 SDK 直接上传日志数据到日志服务的场景中,出于安全考虑,不建议将火山引擎账号或 IAM 用户的访问密钥保存在客户端代码中。此时您可以在应用的服务端通过 STS 服务获取临时安全令牌,将临时安全令牌下发给客户端,为第三方自建应用或 IAM 用户颁发一个可以自定义时效和访问权限的临时身份凭证。
相对于使用火山引擎访问密钥,临时安全令牌具备如下优势:
IAM 角色是一种虚拟用户,无永久的身份凭证,只能通过 STS 获取可以自定义时效和访问权限的临时安全令牌,且需要被一个可信的实体身份扮演。在本示例中,您需要创建一个 IAM 角色并为其授权,指定 IAM 角色在被 IAM 用户扮演时所拥有的日志服务资源访问权限。
说明
创建 IAM 角色时授权账号只能设置为本账号,您需要在3 为 IAM 用户授予扮演 IAM 角色的权限和调用 AssumeRole 的权限中变更授权账号为指定的 IAM 用户,便于后续使用 IAM 用户扮演此角色。
TLSReadOnlyAccess
权限策略,然后单击提交。TLSReadOnlyAccess
为例。授权后,该 IAM 角色具备所有日志服务资源和页面的只读权限。您也可以根据业务需求,创建自定义权限策略。具体步骤请参考新建自定义策略,具体的可授权操作与资源说明请参考可授权的操作与可授权的资源。注意
出于策略最小化的原则,请谨慎设置 IAM 角色权限。例如在免密登录与控制台内嵌场景下,推荐仅设置指定 Project 或 Topic 的数据查看权限,不设置任何的变更操作权限。
IAM 用户是一种实体身份类型,拥有确定的身份 ID 和身份凭证、独立的登录密码和访问密钥。您需要创建一个 IAM 用户,用于扮演 IAM 角色,便于后续获取临时安全令牌。本文以通过用户名创建为例,其他创建方式请参考创建用户。
说明
日志服务推荐您在日常操作与数据资源管理的场景下使用 IAM 用户进行访问与鉴权,降低火山引擎账号密钥泄露的风险。
完成此授权后,IAM 用户才能扮演 IAM 角色去获取 IAM 角色的临时安全令牌,并访问 IAM 角色权限范围内的日志服务资源。
此环节的授权包括以下两部分,均为必选设置。
Principal
中的账号配置修改为您在2 创建 IAM 用户中创建的 IAM 用户,表示该 IAM 角色可以被指定的 IAM 用户扮演。STSAssumeRoleAccess
权限策略。STSAssumeRoleAccess
权限策略后,您才能使用 IAM 用户的访问密钥调用 AssumeRole 接口申请临时安全令牌。授权步骤如下:
在左侧导航栏中,选择身份管理 > 角色。
在角色页面,找到并单击您在步骤 1 中创建的角色。
在角色详情页面,单击信任关系。
在信任关系页签,单击编辑信任策略。
修改信任策略中的 IAM
字段,并单击保存。
将 trn
中默认指定的 root
改为 user/${IAMUserName}
,例如 user/TLSUser
。 以下述信任策略为例,该策略表示此 IAM 角色可以被火山引擎账号 21000****
下的 IAM 用户 TLSUser
扮演。
{ "Statement": [ { "Effect": "Allow", "Action": [ "sts:AssumeRole" ], "Principal": { "IAM": [ "trn:iam::21000****:user/TLSUser" ] } } ] }
STSAssumeRoleAccess
权限。
STSAssumeRoleAccess
权限策略,并单击确定。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" } } }
获取临时安全令牌后,您可以通过该临时安全令牌完成 SDK 鉴权,然后通过 SDK 访问日志服务。日志服务提供的 SDK 以及相关示例代码请参考 SDK 列表。 例如参考如下 Python SDK 示例,完成创建日志项目、创建日志主题、配置索引、写入日志、消费日志及查询日志等操作。
说明
# 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)