All Products
Search
Document Center

Application Real-Time Monitoring Service:Embed a Grafana dashboard in a self-managed web application

Last Updated:Mar 11, 2026

Embed an Application Real-Time Monitoring Service (ARMS) Grafana dashboard into your web application so that users can view monitoring data directly, without switching to the Grafana console or logging on separately.

Important

Only Grafana Shared Edition pages support embedding. Dedicated Edition and Expert Edition pages do not support this feature.

How it works

Your web application obtains temporary credentials through Security Token Service (STS), exchanges them for a logon token at the Alibaba Cloud federation endpoint, and constructs a logon-free URL that loads the Grafana dashboard.

Workflow diagram

The authentication flow involves four components:

ComponentRole
RAM userA service account with permission to call STS
RAM roleGrants access to the ARMS console. The RAM user assumes this role to get temporary credentials
STS temporary credentialsA short-lived AccessKey pair and security token returned by the AssumeRole operation
Logon tokenA federation token exchanged from STS credentials, used to build the logon-free URL

Prerequisites

Before you begin, make sure that you have:

  • An Alibaba Cloud account or a RAM user with administrative rights

  • An ARMS Grafana workspace with at least one dashboard

  • A self-managed web application with a backend server capable of making API calls

Step 1: Create a RAM user and grant STS permissions

Create a dedicated RAM user that your web server uses to call STS.

  1. Log on to the RAM console.

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

  3. On the Users page, click Create User.

    Create User button

  4. In the User Account Information section, set Logon Name and Display Name. In the Access Mode section, select Console Access, and then click OK.

    Important

    RAM generates an AccessKey pair for the new user automatically. The RAM console only displays the AccessKey secret once. Copy and store it securely before closing the dialog.

  5. On the Users page, find the RAM user you created and click Add Permissions in the Actions column.

    Note

    To grant permissions to multiple RAM users at once, select the users and click Add Permissions at the bottom of the page.

    Add Permissions

  6. In the Policy section of the Grant Permission panel, search for and add AliyunSTSAssumeRoleAccess, then click Grant permissions.

  7. Click Close.

Step 2: Create a RAM role and grant ARMS permissions

Create a RAM role that provides access to the ARMS console. The RAM user from Step 1 assumes this role to get temporary credentials.

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

  2. Grant permissions to the RAM role. Attach one of the following policies:

    PolicyAccess level
    AliyunARMSFullAccessFull read and write access to ARMS
    AliyunARMSReadOnlyAccessRead-only access to ARMS

Step 3: Get temporary credentials from STS

On your web server, call the AssumeRole operation to get a temporary AccessKey pair and STS token.

You can call AssumeRole through either of these methods:

The following example uses the RAM SDK for Java. Replace the placeholders with your actual values:

String accessKey = "<your-access-key-id>";       // AccessKey ID of the RAM user
String accessSecret = "<your-access-key-secret>"; // AccessKey secret of the RAM user
String roleArn = "<your-role-arn>";               // ARN of the RAM role
PlaceholderDescriptionWhere to find it
<your-access-key-id>AccessKey ID of the RAM userSaved during Step 1. See Create an AccessKey pair
<your-access-key-secret>AccessKey secret of the RAM userSaved during Step 1
<your-role-arn>Alibaba Cloud Resource Name (ARN) of the RAM roleRAM console, as described below

Find the ARN of a RAM role

  1. In the left-side navigation pane of the RAM console, choose Identities > Roles.

  2. Click the name of the target RAM role.

  3. In the Basic Information section, copy the value of ARN.

    Example ARN

Step 4: Get a logon token

Exchange the STS temporary credentials for a logon token by calling the GetSigninToken operation on the Alibaba Cloud federation endpoint.

Important

The STS token may contain special characters. URL-encode the token value before sending the request.

Send a GET request to the federation endpoint:

https://signin.alibabacloud.com/federation?Action=GetSigninToken
    &AccessKeyId=<temporary-access-key-id>
    &AccessKeySecret=<temporary-access-key-secret>
    &SecurityToken=<url-encoded-sts-token>
ParameterValue
AccessKeyIdTemporary AccessKey ID returned by AssumeRole
AccessKeySecretTemporary AccessKey secret returned by AssumeRole
SecurityTokenURL-encoded STS token returned by AssumeRole
Note

If your web application is deployed by a virtual network operator, append &TicketType=mini to the request.

Step 5: Build the logon-free URL

Combine the logon token with the Grafana dashboard URL to generate a logon-free URL that loads the dashboard without requiring a separate logon.

Note

A logon token expires after 3 hours. Generate a new token on each page request to provide uninterrupted access.

Get the dashboard URL

  1. Open the target dashboard in the ARMS Grafana console.

  2. Copy the URL from the browser address bar.

Control the Grafana UI with kiosk mode

Append a kiosk parameter to the dashboard URL to hide navigation elements:

ParameterEffect
kiosk=tvHides the left-side navigation pane
kioskHides both the top navigation bar and left-side navigation pane
kiosk=tv2Hides navigation elements but keeps the time selector in the upper-right corner

Construct the logon-free URL

Use the logon token and the dashboard URL to build the logon-free URL:

http://signin.alibabacloud.com/federation?Action=Login
    &LoginUrl=<your-fallback-url>
    &Destination=<grafana-dashboard-url>
    &SigninToken=<logon-token>
ParameterDescription
LoginUrlFallback URL that the user is redirected to if logon fails (HTTP 302)
DestinationGrafana dashboard URL, including any kiosk parameters
SigninTokenLogon token from Step 4

Verify the result

Open the logon-free URL in a browser. The Grafana dashboard loads without prompting for credentials. If you specified a kiosk parameter, confirm that the expected navigation elements are hidden.

Expand to view the complete sample code for the iframe URL

/*
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 {
            // Set the parameters based on your account and role. For virtual network operators, add 4service to the Grafana URL.
            String destination = "https://gnew4servims.console.alibabacloud.com/d/1098370038******-53945-422/ack-pro-apiserver?orgId=9&refresh=60s";
            String regionId = "cn-hangzhou"; // Set this parameter as needed.
            String accessKey = "";  // Set this parameter based on your account and role. The account must have the AliyunSTSAssumeRoleAccess permission for STS.
            String secretKey = ""; // Set this parameter based on your account and role.
            // Note: Set this parameter based on your account and role. The role must have the AliyunARMSReadOnlyAccess read-only permission. If the role has insufficient permissions, access fails.
            String role="acs:ram::109837003******:role/armsreadonlyforgrafanaiframe";

            /*
             * Step 1
             * */
            // Set the parameters, specify the role ARN, and set a policy to further restrict the permissions of the STS token. // acs:ram::$accountID:role/$roleName
            // Build an 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
             * Obtain the logon-free URL.
             * */
            String url = getUrl(token, destination);

            /*
             * Step 4
             * The redirection 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("AssumeRoleService load ErrCode:" + 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("SigninTokenService 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("SigninTokenService failed to retrieve signInToken!");
            }
            String signInRes = EntityUtils.toString(httpResponse.getEntity());
            signInToken = JSON.parseObject(signInRes).getString("SigninToken");
            if (signInToken == null) {
                throw new RuntimeException("SigninTokenService signInToken is empty while signInRes is:" + signInRes);
            }
            return signInToken;
        } catch (Exception e) {
            throw new RuntimeException("SigninTokenService get signInToken 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("SigninUrlService build getUrl error:" + e.getMessage());
        }
        return url;
    }
}