Grafana can only directly query CloudWatch metrics from the AWS account it’s configured in, forcing you to set up separate Grafana instances for each account or dig into complex cross-account IAM roles.

Let’s see how to make Grafana talk to CloudWatch in other AWS accounts. We’ll use a scenario where your Grafana instance is in Account-A and you want to pull metrics from Account-B and Account-C.

First, you need a Grafana instance running, with the CloudWatch data source plugin installed. If you don’t have it, grafana-cli plugins install grafana-cloudwatch-datasource will get it for you.

The Core Problem: IAM Permissions

Grafana’s CloudWatch data source needs IAM permissions to cloudwatch:ListMetrics and cloudwatch:GetMetricStatistics (and a few others, but these are the main ones). When Grafana is running outside AWS (e.g., on-prem or in another cloud), you typically provide these via an IAM user’s access key and secret key.

When Grafana is inside AWS (e.g., on an EC2 instance or in EKS), it usually assumes an IAM role attached to the EC2 instance or Kubernetes service account. This is the preferred method.

The challenge for cross-account access is giving the Grafana instance (or its assumed role) permission to access resources in other accounts.

Solution: Cross-Account IAM Roles

The standard AWS way to grant access between accounts is via IAM roles. Here’s the breakdown:

  1. In the target AWS accounts (Account-B, Account-C):

    • Create an IAM role. Let’s call it GrafanaCrossAccountReader.
    • Trust Relationship: This is key. The trust policy must allow the principal running Grafana (e.g., the EC2 instance profile role in Account-A, or a specific IAM user ARN if Grafana is external) to sts:AssumeRole.
      • Example Trust Policy for Account-B’s GrafanaCrossAccountReader role:
        {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Principal": {
                "AWS": "arn:aws:iam::ACCOUNT-A-ID:root"
                // OR if Grafana is on EC2 in Account-A:
                // "AWS": "arn:aws:iam::ACCOUNT-A-ID:role/YourGrafanaEC2Role"
              },
              "Action": "sts:AssumeRole"
            }
          ]
        }
        
        Replace ACCOUNT-A-ID with the actual AWS account ID of Account-A. If you know the specific ARN of the role Grafana assumes in Account-A, use that for a more granular permission.
    • Permissions Policy: Attach a policy to this role that grants read-only access to CloudWatch.
      • Example Permissions Policy for GrafanaCrossAccountReader:
        {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Action": [
                "cloudwatch:ListMetrics",
                "cloudwatch:GetMetricStatistics",
                "cloudwatch:DescribeAlarms" // Often useful too
              ],
              "Resource": "*"
            }
          ]
        }
        
        You can scope this down further by region or specific metric namespaces if needed, but Resource: "*" is common for broad read access.
  2. In the Grafana AWS account (Account-A):

    • Grafana Instance’s IAM Role: Ensure the IAM role that your Grafana instance (e.g., EC2 instance profile role) is using has permissions to sts:AssumeRole for the roles you just created in Account-B and Account-C.
      • Example Policy to attach to Grafana’s role in Account-A:
        {
          "Version": "2012-10-17",
          "Statement": [
            {
              "Effect": "Allow",
              "Action": "sts:AssumeRole",
              "Resource": [
                "arn:aws:iam::ACCOUNT-B-ID:role/GrafanaCrossAccountReader",
                "arn:aws:iam::ACCOUNT-C-ID:role/GrafanaCrossAccountReader"
              ]
            }
          ]
        }
        
        Replace ACCOUNT-B-ID and ACCOUNT-C-ID with their respective AWS account IDs.
  3. Configure Grafana Data Source:

    • In Grafana, go to Configuration -> Data Sources.
    • Add a new CloudWatch data source or edit an existing one.
    • Authentication: Select Credentials file or IAM role depending on your Grafana setup.
      • If using IAM role (recommended for EC2/EKS), Grafana will automatically use the role it’s running under.
      • If Grafana is external, you might need to configure ~/.aws/credentials on the Grafana server with a profile that has sts:AssumeRole permissions.
    • Region: Select the AWS region for the metrics you want to query (e.g., us-east-1).
    • Access & Metrics: This is where you specify the cross-account details.
      • Default Auth: Leave as Default (Instance Role or Credentials File).
      • Assume Role ARN: This is the crucial field. Enter the ARN of the GrafanaCrossAccountReader role you created in the target account.
        • For Account-B: arn:aws:iam::ACCOUNT-B-ID:role/GrafanaCrossAccountReader
        • For Account-C: arn:aws:iam::ACCOUNT-C-ID:role/GrafanaCrossAccountReader
      • Custom Metrics Namespaces: (Optional) If you have custom metrics, you might need to specify them here.
    • Save & Test: Click "Save & Test". Grafana will attempt to assume the specified role and query CloudWatch in that account.

Adding Multiple Accounts

You’ll repeat this process for each AWS account you want to query. You can configure multiple CloudWatch data sources in Grafana, each pointing to a different Assume Role ARN for a different account.

For example:

  • Data Source 1: Name CloudWatch-Account-A, Region us-east-1, Assume Role ARN (empty or Account-A’s role)
  • Data Source 2: Name CloudWatch-Account-B, Region us-east-1, Assume Role ARN arn:aws:iam::ACCOUNT-B-ID:role/GrafanaCrossAccountReader
  • Data Source 3: Name CloudWatch-Account-C, Region us-east-1, Assume Role ARN arn:aws:iam::ACCOUNT-C-ID:role/GrafanaCrossAccountReader

Then, when creating dashboards, you can select the appropriate data source for each panel.

The "Next Error"

After successfully configuring cross-account access, the next common hurdle is dealing with metric resolution and aggregation across accounts, especially when panels try to display data from different time granularities or when Sum aggregation across multiple instances in different accounts doesn’t yield the expected results due to differing metric publication rates.

Want structured learning?

Take the full Grafana course →