将 APM 控制台嵌入自建系统

最近更新时间:2024-08-01 14:40:04

我的收藏
您可以将 APM 控制台嵌入到自建 Web 服务中,为用户提供以下方便:
在外部系统服务中(例如公司内部运维系统)快速集成 APM 数据的查询分析能力。
无需管理众多腾讯云子账号,方便将 APM 数据分享给他人进行查看。
用户不需要登录腾讯云就可以使用 APM。
整体的交互流程如下:



前提条件

该方案需要在自建 Web 服务中,通过代码获取当前用户的访问密钥,具体的获取方式由您的业务场景自行决定,不在本文的讨论范围之内。您可以参考 子账号访问密钥管理 预先对用户访问密钥进行持久化保存。

步骤1:创建 CAM 角色

用户访问 Web 服务后,需要通过扮演角色的方式登录 APM 控制台,因此需要预先创建 CAM 角色。关于角色的基本概念,请参考 角色概述 。您可以为多个用户创建统一的角色,也可以为每个用户创建单独的角色,具体的实现方式由您的业务场景决定,不在本文的讨论范围之内。您可以通过控制台或 创建角色API 创建对应的角色,本文将介绍如何通过控制台创建角色。
2. 单击左侧菜单栏中的角色,进入角色页面。
3. 选择新建角色 > 腾讯云账户,开始新建自定义角色。
4. 选择当前主账号并勾选允许当前角色访问控制台,单击下一步



5. 为角色关联 APM 的权限策略,例如全读写访问权限 QcloudAPMFullAccess,或者只读访问权限 QcloudAPMReadOnlyFullAccess,单击下一步。



6. 为角色配置不同维度标签,使用标签对用户进行分类管理,然后单击下一步



7. 输入角色名,点击完成即可创建成功。




步骤2:申请扮演角色临时访问凭证

在 Web 服务中,需要基于用户的访问密钥,访问腾讯云 STS 服务的 AssumeRole 接口,申请对应 CAM 角色的临时访问凭证。本文提供了 Java 代码实现,其他语言的代码可以参考 AssumeRole 接口调试,其中的关键入参包括:
参数名称
是否必选
类型
描述
RoleArn
String
需要扮演的角色的 ARN,可以从 CAM 控制台获取,例如 qcs::cam::uin/1500000688:roleName/RoleWithAPMFullAccess
RoleSessionName
String
临时会话名称,由用户自定义名称
DurationSeconds
Int
指定临时访问凭证的有效期,单位为秒。建议设置在5分钟以内
腾讯云 STS 服务将返回扮演角色临时访问凭证,包括 Secret ID、Secret Key 和 Token。

步骤3:生成登录 URL

1. 拼接需要签名的字符串

对要求签名的参数按照字母表或数字表递增顺序的排序,先考虑第一个字母,在相同的情况下考虑第二个字母,以此类推。您可以借助编程语言中的相关排序函数来实现这一功能,如 PHP中 的 ksort 函数。其中要求签名的参数包含以下内容:
参数名称
是否必选
类型
描述
action
String
操作动作,固定为 roleLogin
timestamp
Int
当前时间戳
nonce
Int
随机整数,取值 10000-100000000
secretId
String
从 STS 服务返回的临时 Secret ID
将把上一步排序好的请求参数,按参数名称=参数值的格式拼接成请求字符串,并使用&符合分隔,例如:
action=roleLogin&nonce=67439&secretId=AKI***PLE&timestamp=1484793352
请求方法 + 请求路径 + ? + 请求字符串的规则,拼接需要签名的字符串。
参数
必选
描述
请求路径
固定为 cloud.tencent.com/login/roleAccessCallback
请求方法
支持 GET 或 POST
需要签名的字符串示例:
GETcloud.tencent.com/login/roleAccessCallback?action=roleLogin&nonce=67439&secretId=AKI***PLE&timestamp=1484793352

2. 签名

使用 HMAC-SHA1 或 HMAC-SHA256 算法对字符串进行签名,签名时用到的 key 是从 STS 服务获得的临时 Secret Key,具体实现方式可以参考本文的示例代码。

3. 拼接最终的登录 URL

根据以下规则,拼接最终的登录 URL,其中每一个参数都需要通过 URLEncoder 进行编码
https://cloud.tencent.com/login/roleAccessCallback
?algorithm=<签名时加密算法,目前只支持sha1和sha256>
&secretId=<从STS服务返回的临时Secret ID>
&token=<从STS服务返回的临时Token>
&nonce=<签名时用到的nonce>
&timestamp=<签名时用到的timestamp>
&signature=<签名结果>
&s_url=<目标URL, 固定为 https://console.cloud.tencent.com/apm?hideWidget=true&hideTopNav=true >

步骤4:用户访问登录 URL 进入 APM 控制台

可以通过<iframe>等方式,引导用户访问登录 URL,这样就能将 APM 控制台嵌入到自建系统中,最终用户并不需要再登录腾讯云就能访问 APM。

完整代码

请参考如下 Java 代码完成开发,代码分为两部分:
1. 向腾讯云 STS 服务申请扮演角色临时访问凭证。其他语言的代码可以参考 API 文档
2. 拼接登录 URL。其他语言的代码可以借助于工具转换,或者参考 Java 代码自行编写。
import java.net.URLEncoder; import java.util.Random; import com.tencentcloudapi.common.Credential; import com.tencentcloudapi.common.profile.ClientProfile; import com.tencentcloudapi.common.profile.HttpProfile; import com.tencentcloudapi.sts.v20180813.StsClient; import com.tencentcloudapi.sts.v20180813.models.*; import javax.crypto.Mac; import javax.crypto.spec.SecretKeySpec; import java.nio.charset.StandardCharsets; import java.util.Base64; public class LoginWithoutPass { public static void main(String[] args) throws Exception { /* 以下代码用于申请扮演角色临时访问凭证,其他语言的代码可以参考API文档 https://cloud.tencent.com/document/product/1312/48197 */ // 根据自身业务逻辑,获取当前用户的访问密钥 String secretId = getSecretId(); String secretKey = getSecretKey(); Credential cred = new Credential(secretId, secretKey); HttpProfile httpProfile = new HttpProfile(); httpProfile.setEndpoint("sts.tencentcloudapi.com"); ClientProfile clientProfile = new ClientProfile(); clientProfile.setHttpProfile(httpProfile); // 地域列表请参考 https://cloud.tencent.com/document/product/213/6091 StsClient client = new StsClient(cred, "ap-guangzhou", clientProfile); AssumeRoleRequest req = new AssumeRoleRequest(); // 需要扮演的角色的ARN,可以从CAM控制台获取 req.setRoleArn("qcs::cam::uin/1500000688:roleName/RoleWithAPMFullAccess"); // 临时会话名称,由用户自定义名称 req.setRoleSessionName("cts"); // 临时访问凭证的有效期,建议5分钟以内 req.setDurationSeconds(1800L); AssumeRoleResponse resp = client.AssumeRole(req); // 从腾讯云STS服务获取的临时访问凭证,包括密钥和Token String stsSecretId = resp.getCredentials().getTmpSecretId(); String stsSecretKey = resp.getCredentials().getTmpSecretKey(); String token = resp.getCredentials().getToken(); /* 以下代码用于拼接登录URL,其他语言的代码可以借助于工具转换,或者自行编写 */ int timestamp = (int) (System.currentTimeMillis() / 1000); // 生成10000-100000000之间的随机数 Random rand = new Random(); int min = 10000; int max = 100000000; int nonce = rand.nextInt((max - min) + 1) + min; // 拼接需要签名的字符串 String sourceString = "GETcloud.tencent.com/login/roleAccessCallback?action=roleLogin&nonce=" + nonce + "&secretId=" + stsSecretId + "&timestamp=" + timestamp; // 通过SHA256进行签名 String signatureString = Base64.getEncoder().encodeToString(hmacSha256(sourceString, stsSecretKey)); // 拼接最终的登录URL String result = "https://cloud.tencent.com/login/roleAccessCallback?algorithm=sha256&secretId=" + URLEncoder.encode(stsSecretId, StandardCharsets.UTF_8.toString()) + "&token=" + URLEncoder.encode(token, StandardCharsets.UTF_8.toString()) + "&nonce=" + nonce + "&timestamp=" + timestamp + "&signature=" + URLEncoder.encode(signatureString, StandardCharsets.UTF_8.toString()) + "&s_url=" + URLEncoder.encode("https://console.cloud.tencent.com/apm?hideWidget=true&hideTopNav=true", StandardCharsets.UTF_8.toString());
// 接下来引导用户访问生成的登录URL,进入APM控制台 } private static byte[] hmacSha256(String data, String key) throws Exception { SecretKeySpec secretKeySpec = new SecretKeySpec(key.getBytes(StandardCharsets.UTF_8), "HmacSHA256"); Mac mac = Mac.getInstance("HmacSHA256"); mac.init(secretKeySpec); return mac.doFinal(data.getBytes(StandardCharsets.UTF_8)); } }