You need to enable JavaScript to run this app.
导航

通过 STS 访问日志服务

最近更新时间2023.11.13 16:31:34

首次发布时间2022.11.25 21:31:15

日志服务支持通过安全令牌服务(STS)提供的临时安全令牌进行临时授权访问。在 SDK 上传日志等场景中,您可以通过 STS 服务申请临时安全令牌,使指定 IAM 用户在指定时间内访问权限范围内的日志服务资源。本文档介绍使用 STS 临时安全令牌访问日志服务的配置步骤。

典型场景

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

  • 临时安全令牌可设置自定义的时效,无需在客户端代码中暴露 IAM 用户的永久密钥,降低了帐号泄露引起的安全风险。
  • 获取临时安全令牌时,可以通过请求参数 Policy 设置临时的访问权限,进一步约束临时安全令牌使用者的权限范围,便于权限的精细化管理。

业务流程

图片

操作步骤

1 创建 IAM 角色

通过火山引擎账号创建 IAM 角色,并设置其信任身份类型为账号,表示授权指定账号通过此角色访问您的火山引擎云资源。在火山引擎 IAM 控制台中创建 IAM 角色的操作步骤如下。

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

    说明

    创建 IAM 角色时授权账号只能设置为本账号,您需要在步骤 4 中变更授权账号为指定 IAM 用户,便于后续使用 IAM 用户扮演此角色。

  5. 配置角色信息面板,设置角色名等信息,单击下一步
  6. 添加权限面板,单击跳过,完成角色的创建。

图片

2 为 IAM 角色授予日志服务权限

在内嵌日志服务控制台页面的场景下,您可以为 IAM 角色授予系统默认权限 TLSReadOnlyAccess,表示该角色具备所有日志服务资源和页面的只读权限。您也可以根据日志服务可授权的操作与资源列表,创建自定义的授权策略。详细说明请参考可授权的操作可授权的资源

说明

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

为 IAM 角色授予系统默认权限 TLSReadOnlyAccess 的操作步骤如下。您也可以参考 IAM 文档创建自定义权限策略,并将其授予步骤 1 中创建的 IAM 角色。

  1. 在左侧导航栏单击角色
  2. 角色列表中找到步骤 1 中创建的角色,并单击角色名称。
  3. 权限>全局权限页签中,单击添加权限
  4. 添加权限面板中,选择系统预设策略 TLSReadOnlyAccess,并单击确定

图片

3 创建 IAM 用户

IAM 用户作为实体身份类型,有确定的身份 ID 和身份凭证,拥有独立的登录密码和访问密钥。日志服务推荐您在日常操作与数据资源管理的场景下使用 IAM 用户进行访问与鉴权,降低火山引擎账号密钥泄露的风险。在免密登录日志服务的场景下,您需要创建一个 IAM 用户,便于后续获取临时安全令牌。
在火山引擎 IAM 控制台中创建 IAM 用户的操作步骤如下。本文以通过用户名创建为例,其他创建方式请参考创建用户

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

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

免密访问日志服务场景下,您需要为指定 IAM 用户授予扮演 IAM 角色的权限,授权后,IAM 用户才能通过角色扮演获取临时安全令牌,访问 IAM 角色权限范围内的日志服务资源。
此环节的授权包括以下两部分,均为必选设置,缺少其中一个授权步骤都会导致鉴权失败。

  • 为 IAM 角色设置信任策略。 创建 IAM 角色时,默认的可信实体为火山引擎账号,您需要修改 IAM 的信任策略,将 Principal 中的账号配置修改为步骤 3 中创建的 IAM 用户,表示该 IAM 角色可以被指定 IAM 用户扮演。
  • 为 IAM 用户授予 STSAssumeRoleAccess 权限策略。 临时安全令牌必须由 IAM 用户账号申请,所以您需要为 IAM 用户授予系统预设策略 STSAssumeRoleAccess,IAM 用户从而具备调用 AssumeRole 申请临时安全令牌的权限。

授权步骤如下:

  1. 为 IAM 角色设置信任策略。

    1. 在左侧导航栏中,选择身份管理 > 角色
    2. 角色列表,单击步骤 1 中创建的角色名称。
    3. 角色详情页面,单击信任关系
    4. 信任关系页签,单击编辑信任策略
    5. 修改信任策略中 IAM 字段内容,并单击保存
      修改 IAM 字段时,应将 trn 中默认指定的 root 改为 user/&{IAMUserName},例如 user/TLSUser。 以下述信任策略为例,该策略表示此 IAM 角色可以被火山引擎账号(AccountID=21000****)下的 IAM 用户 TLSUser 扮演。
      {
          "Statement": [
              {
                  "Effect": "Allow",
                  "Action": [
                      "sts:AssumeRole"
                  ],
                  "Principal": {
                      "IAM": [
                          "trn:iam::21000****:user/TLSUser"
                      ]
                  }
              }
          ]
      }
      

    图片

  2. 为 IAM 用户授予 STSAssumeRoleAccess 权限策略。

    1. 在左侧导航栏中,选择身份管理 > 用户
    2. 用户页面,单击步骤 3 中创建的用户名称。
    3. 用户详情页面,单击权限页签。
    4. 权限页签中,单击添加权限
    5. 添加权限面板,选择STSAssumeRoleAccess策略,并单击确定
      图片

5 通过 AssumeRole 获取临时安全令牌

以 IAM 用户身份调用安全令牌服务(STS)的 AssumeRole 接口,获取临时的安全令牌。临时安全令牌包括临时凭证 AK 和 SK,以及使用临时凭证 AK、SK 时配套的 SessionToken。
请求示例如下,其中参数 RoleTrn 应指定为步骤 1 中创建的 IAM 角色名称,并通过 IAM 用户身份进行 OpenAPI 接口鉴权。

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

返回示例如下,其中 AccessKeyId、SecretAccessKey 和 SessionToken 为 IAM 用户申请的临时安全令牌。

{
    "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**2ZDcxMDg",
            "SecretAccessKey": "TVRNNVlqRmxPR1mRoTkdWbE1E****",
            "SessionToken": "STSeyJBY2NvdW50SWklkZW50aXR5VHlwZSI6NCwiSWRlbnRpdHlJZCI6MzAyMTcsIkNoYW5uZWwiOiJyZXNvdXJjZSIsIkFjY2Vzc0tleUlkIjoiQUtUUE9EZzBNelZrWlRNMVlqQXlOR05sWkdGbU0yVTNaVEl6T0RnMlpEY3hNRGciLCJTaWduZWRTZWNyZXRBY2Nlc3NLZXkiOiJHSHRuc2Q1b3BOOThUeUNrckVuMVAxTDd1ZzBXczZFMytzTktDMDJQT01lNzFMOUloNzhYaDB5VXE4Ni9JMW8reEZxTmtkK01tVUR0cjRHR0NodXJQdz09IiwiRXhwaXJlZFRpbWUiOjE2MTgxOTk4MjksIlBvbGljeVN0cmluZyI6IiIsIlNpZ25hdHVyZSI6IjdiZTEzNTU1MDM5NzcyM2VkMDQxYmVkNTIyNzU4YmMyNjQ3YzRmNzZiNmRjYTViNzVhZDUyOTMwYTg1NjE5ZGEiLCJTZXNzaW9uTmFtZSI6ImNlc2hpYXNzdW1****"
        },
        "AssumedRoleUser": {
            "Trn": "trn:sts::20**94:assumed-role/TLSRole/ceshiassume",
            "AssumedRoleId": "**:ceshiassume"
        }
    }
}

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

获取临时安全令牌之后,您可以通过日志服务提供的多语言 SDK 访问日志服务。日志服务提供的 SDK 列表请参考 SDK 概述

说明

  • 临时安全令牌默认有效期为 1 小时,到期后需要及时更新临时安全令牌。
  • 您可以通过 AssumeRole 的 DurationSeconds 参数设置临时安全令牌的有效期。DurationSeconds 参数单位为秒,最大可设置 12 小时。
package tls

import (
        "github.com/google/uuid"
        "github.com/volcengine/volc-sdk-golang/service/tls"
)

func main() {
        //初始化客户端,配置Endpoint、AccessKeyID、AccessKeySecret、securityToken和Region。其中,securityToken为通过IAM的STS机制获取的临时Token,使用临时Token时也应传入临时的AK、SK;不使用临时Token时securityToken传空即可。
        client := tls.NewClient(testEndPoint, testAk, testSk, testSessionToken, testRegion)

        //新建project
        createResp, _ := client.CreateProject(&tls.CreateProjectRequest{
                ProjectName: testPrefix + uuid.NewString(),
                Description: "",
                Region:      testRegion,
        })

        testProjectId = createResp.ProjectId

        // 新建topic
        // TopicName Description字段规范参考api文档
        createTopicRequest := &tls.CreateTopicRequest{
                ProjectID:   testProjectId,
                TopicName:   testPrefix + uuid.NewString(),
                Ttl:         30,
                ShardCount:  2,
                Description: "topic desc",
        }
        topic, _ := client.CreateTopic(createTopicRequest)
        testTopicId = topic.TopicID

        //新建index,开启全文索引和kv索引
        createIndexReq := &tls.CreateIndexRequest{
                TopicID: testTopicId,
                FullText: &tls.FullTextInfo{
                        CaseSensitive:  false,
                        IncludeChinese: false,
                        Delimiter:      ", ?",
                },
                KeyValue: &[]tls.KeyValueInfo{
                        {
                                Key: "test1",
                                Value: tls.Value{
                                        ValueType:      "text",
                                        Delimiter:      ", ?",
                                        CasSensitive:   false,
                                        IncludeChinese: false,
                                        SQLFlag:        false,
                                },
                        },
                },
        }
        _, _ = client.CreateIndex(createIndexReq)

        //新建index,仅开启全文索引
        createIndexReq2 := &tls.CreateIndexRequest{
                TopicID: testTopicId,
                FullText: &tls.FullTextInfo{
                        CaseSensitive:  false,
                        IncludeChinese: false,
                        Delimiter:      ", ?",
                },
                KeyValue: nil,
        }
        _, _ = client.CreateIndex(createIndexReq2)

        //新建index,仅开启kv索引
        createIndexReq3 := &tls.CreateIndexRequest{
                TopicID:  testTopicId,
                FullText: nil,
                KeyValue: &[]tls.KeyValueInfo{
                        {
                                Key: "test1",
                                Value: tls.Value{
                                        ValueType:      "text",
                                        Delimiter:      ", ?",
                                        CasSensitive:   false,
                                        IncludeChinese: false,
                                        SQLFlag:        false,
                                },
                        },
                },
        }
        _, _ = client.CreateIndex(createIndexReq3)

        //修改索引

        //开启全文和kv
        updateIndexReq := &tls.ModifyIndexRequest{
                TopicID: testTopicId,
                FullText: &tls.FullTextInfo{
                        CaseSensitive:  false,
                        IncludeChinese: false,
                        Delimiter:      ", ?",
                },
                KeyValue: &[]tls.KeyValueInfo{
                        {
                                Key: "test1",
                                Value: tls.Value{
                                        ValueType:      "text",
                                        Delimiter:      ", ?",
                                        CasSensitive:   false,
                                        IncludeChinese: false,
                                        SQLFlag:        false,
                                },
                        },
                },
        }

        _, _ = client.ModifyIndex(updateIndexReq)
        //开启全文,关闭kv
        updateIndexReq2 := &tls.ModifyIndexRequest{
                TopicID: testTopicId,
                FullText: &tls.FullTextInfo{
                        CaseSensitive:  false,
                        IncludeChinese: false,
                        Delimiter:      ", ?",
                },
                KeyValue: nil,
        }
        _, _ = client.ModifyIndex(updateIndexReq2)

        //关闭全文,开启kv
        updateIndexReq3 := &tls.ModifyIndexRequest{
                TopicID:  testTopicId,
                FullText: nil,
                KeyValue: &[]tls.KeyValueInfo{
                        {
                                Key: "test1",
                                Value: tls.Value{
                                        ValueType:      "text",
                                        Delimiter:      ", ?",
                                        CasSensitive:   false,
                                        IncludeChinese: false,
                                        SQLFlag:        false,
                                },
                        },
                },
        }
        _, _ = client.ModifyIndex(updateIndexReq3)

        //查询索引详情
        _, _ = client.DescribeIndex(&tls.DescribeIndexRequest{
                TopicID: testTopicId,
        })

}