All Products
Search
Document Center

Application Real-Time Monitoring Service:Embed a Grafana dashboard in your web app

Last Updated:Jun 20, 2026

You can embed a Grafana dashboard into your self-managed web application to view it without logging on, which avoids switching between systems.

Limitations

You can only embed dashboards from the shared edition of Managed Service for Grafana into a self-managed web application.

Background information

By embedding a Grafana dashboard into your self-managed web application, you can:

  • Log on to your own system and view the embedded Grafana dashboard.

  • Hide the Grafana top navigation bar and left-side navigation pane. For instructions, see Step 5.

How it works

image

Step 1: Create a RAM user

Use your Alibaba Cloud account to create a RAM user and grant it permissions to call the Security Token Service (STS) AssumeRole operation.

  1. Log on to the Resource Access Management (RAM) console with your Alibaba Cloud account (root account) or as a RAM administrator.

  2. In the left-side navigation pane, choose Identities > Users.

  3. On the Users page, click Create User.

  4. On the Create User page, enter a Logon Name and Display name in the User Account Information section. In the Access Method section, select Console Access, and then click OK.

    Important

    For security, the RAM console displays the AccessKey secret only once. Be sure to save it in a secure location.

  5. In the Create Authorization panel, add the AliyunSTSAssumeRoleAccess policy in the Policy section, and then click OK.

Step 2: Create a RAM role

Create a RAM role and grant it permissions to access the console. The RAM user will assume this role to access the console.

  1. Create a RAM role for a trusted Alibaba Cloud account.

  2. Grant the role full or read-only permissions on Application Real-Time Monitoring Service (ARMS). For instructions, see Manage permissions for a RAM role.

    • AliyunARMSFullAccess: Full permissions on ARMS.

    • AliyunARMSReadOnlyAccess: Read-only permissions on ARMS.

Step 3: Obtain temporary credentials

Log on to your self-managed web application. On the web server, call the STS AssumeRole operation to obtain temporary credentials: a temporary AccessKey ID, an AccessKey secret, and an STS token. For more information about the AssumeRole operation, see AssumeRole.

You can call the AssumeRole operation in one of the following ways:

This topic uses the Java SDK as an example.

When you use the Java SDK, specify the following parameters:

String accessKey = "<accessKeyId>"; // The AccessKey ID of the RAM user.
String accessSecret = "<accessKeySecret>"; // The AccessKey secret of the RAM user.
String roleArn = "<roleArn>"; // The ARN of the RAM role.

You obtain the AccessKey ID and AccessKey secret when you create the RAM user. For more information, see Create an AccessKey.

To obtain the Alibaba Cloud Resource Name (ARN) of the RAM role, perform the following steps:

  1. On the RAM console, on the Identities > Roles page, click the name of the target RAM role in the list.

  2. On the role details page, copy the ARN in the Basic Information section.

Step 4: Obtain a logon token

After obtaining the temporary credentials by calling the STS AssumeRole operation, call the logon service to obtain a logon token.

Important

The STS token returned by STS may contain special characters. You must URL-encode these characters before use.

Sample request:

https://signin.alibabacloud.com/federation?Action=GetSigninToken
    &AccessKeyId=<The temporary AccessKey ID returned by STS>
    &AccessKeySecret=<The temporary AccessKey secret returned by STS>
    &SecurityToken=<The STS token returned by STS>
Note

If you are a virtual network operator, you must also add the &TicketType=mini parameter.

Step 5: Generate a logon-free URL

Use the logon token and the URL of the Grafana dashboard you want to embed to generate a logon-free URL. This URL allows users to access the Grafana dashboard from your self-managed web application without logging on.

Note

The logon token is valid for three hours. We recommend that you configure your web application to generate a new logon token for each request.

  1. In Grafana, get the URL of the dashboard you want to embed.

    Note
    • To hide the left-side navigation pane, add kiosk=tv to the URL's query string.

    • To hide the top navigation bar and left-side navigation pane, add kiosk to the URL's query string.

    • To hide the top navigation bar and left-side navigation pane but keep the time range picker in the upper-right corner, add kiosk=tv2 to the URL's query string.

  2. Use the logon token and the Grafana dashboard URL to generate the logon-free URL.

    http://signin.alibabacloud.com/federation?Action=Login
        &LoginUrl=<The URL to which users are redirected if the logon fails. This is typically the URL that your application configures for 302 redirects.>
        &Destination=<The URL of the Grafana dashboard>
        &SigninToken=<The logon token you obtained>
  3. Open the logon-free URL in your browser.

Sample code

/*
Copyright 2022 Alibaba Cloud.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
    http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package com.aliyun.arms.unifydemo.unifydemo;
import com.alibaba.fastjson.JSON;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.auth.sts.AssumeRoleRequest;
import com.aliyuncs.auth.sts.AssumeRoleResponse;
import com.aliyuncs.http.MethodType;
import com.aliyuncs.profile.DefaultProfile;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.util.EntityUtils;
import java.net.URLEncoder;
/**
 * @author XX
 * @version V1.0.0
 * @dept XX-XX
 * @date 2025/7/2 16:10
 * @description
 */
public class GrafanaIframeUrlGenerator {
    private static final String signInHost = "https://signin.aliyun.com";
    private static final String loginUrl = "https://www.aliyun.com";
    private static final String loginUri = "/federation?Action=Login&LoginUrl=%s&Destination=%s&SigninToken=%s";
    private static final String signInTokenUri = "/federation?Action=GetSigninToken&AccessKeyId=%s&AccessKeySecret=%s&SecurityToken=%s&TicketType=%s";
    public static void main(String[] args) {
        try {
            // The URL of the destination Grafana dashboard. For virtual network operators, the URL typically contains '4service'.
            String destination = "https://gnew4servims.console.alibabacloud.com/d/1098370038******-53945-422/ack-pro-apiserver?orgId=9&refresh=60s";
            String regionId = "cn-hangzhou";// Specify your region ID.
            // The AccessKey ID of the RAM user. This user must have the AliyunSTSAssumeRoleAccess policy attached.
            String accessKey = "";
            String secretKey = "";// Set this parameter based on your account and role.
            // The ARN of the RAM role to assume. This role must have at least read-only permissions on ARMS (e.g., AliyunARMSReadOnlyAccess) to prevent access failures.
            String role="acs:ram::109837003******:role/armsreadonlyforgrafanaiframe";
            /*
             * Step 1
             * */
            // Set parameters, specify the role ARN, and set a policy to further restrict the permissions of the STS token. // acs:ram::$accountID:role/$roleName
            // Build the AssumeRole request.
            AssumeRoleResponse.Credentials key = getCredentials(regionId, accessKey, secretKey, role, "role-" + System.currentTimeMillis());
            /*
             * Step 2: Obtain the logon token
             * */
            String token = getLoginToken(key, destination);
            /*
             * Step 3: Get the logon-free URL
             * */
            String url = getUrl(token, destination);
            /*
             * Step 4: Redirect to the URL
             * */
            System.out.println(url);
        } catch (Error e) {
            e.printStackTrace();
        }
    }
    private static AssumeRoleResponse.Credentials getCredentials(String regionId, String accessKey, String secretKey, String roleArn, String roleSessionName) {
        DefaultProfile profile = DefaultProfile.getProfile(regionId, accessKey, secretKey);
        IAcsClient client = new DefaultAcsClient(profile);
        AssumeRoleRequest request = new AssumeRoleRequest();
        request.setSysMethod(MethodType.POST);
        request.setRoleArn(roleArn);
        request.setRoleSessionName(roleSessionName);
        request.setDurationSeconds(3600L);
        try {
            AssumeRoleResponse response = client.getAcsResponse(request);
            return response.getCredentials();
        } catch (Exception e) {
            throw new RuntimeException("Failed to call the AssumeRole operation. Error: " + e.getMessage());
        }
    }
    public static String getLoginToken(AssumeRoleResponse.Credentials key, String destination) {
        String token = "";
        if (key == null) {
            return "";
        }
        String ticketType = "normal";
        if (destination == null || destination.trim().length() == 0 || destination.contains("4service")) {
            ticketType = "mini";
        }
        String signInTokenUrl = "";
        try {
            signInTokenUrl = signInHost + String.format(signInTokenUri,
                    URLEncoder.encode(key.getAccessKeyId(), "utf-8"),
                    URLEncoder.encode(key.getAccessKeySecret(), "utf-8"),
                    URLEncoder.encode(key.getSecurityToken(), "utf-8"),
                    URLEncoder.encode(ticketType, "utf-8"));
        } catch (Exception e) {
            throw new RuntimeException("Failed to build signInTokenUrl. Error: " + e.getMessage());
        }
        final CloseableHttpClient httpClient = HttpClients.createDefault();
        try {
            HttpGet signInGet = new HttpGet(signInTokenUrl);
            HttpResponse httpResponse = httpClient.execute(signInGet);
            String signInToken = "";
            if (httpResponse.getStatusLine().getStatusCode() != 200) {
                throw new RuntimeException("Failed to retrieve the logon token.");
            }
            String signInRes = EntityUtils.toString(httpResponse.getEntity());
            signInToken = JSON.parseObject(signInRes).getString("SigninToken");
            if (signInToken == null) {
                throw new RuntimeException("The logon token is empty. Response: " + signInRes);
            }
            return signInToken;
        } catch (Exception e) {
            throw new RuntimeException("Failed to get the logon token. Error: " + e.getMessage());
        }
    }
    public static String getUrl(String token, String destination) {
        String url = "";
        try {
            url = signInHost + String.format(loginUri,
                    URLEncoder.encode(loginUrl, "utf-8"),
                    URLEncoder.encode(destination, "utf-8"),
                    URLEncoder.encode(token, "utf-8"));
        } catch (Exception e) {
            throw new RuntimeException("Failed to build the logon URL. Error: " + e.getMessage());
        }
        return url;
    }
}