IAM Setup

InfraWatch needs an IAM user and role to access AWS services. This page explains how to set them up with least-privilege permissions.

How It Works

InfraWatch uses a two-layer IAM model:

  1. IAM User (POWER_AWS_ACCESS_KEY_ID) — has permission to call sts:AssumeRole on the base role. This is the only permission this user needs.
  2. IAM Role (BASE_ROLE_ARN) — has read-only access to AWS services. The backend assumes this role and applies a restrictive session policy per request, scoped to only the services the user was approved for.
Session policies can only restrict, never expand
Even if the base role has broad permissions, each user session is scoped down to only the specific services they were approved for. CloudWatch is always included for metrics.

Step 1 — Create the IAM User

Create an IAM user with programmatic access (access key + secret key). This user only needs one permission:

IAM Policy for the User
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": "sts:AssumeRole",
      "Resource": "arn:aws:iam::123456789012:role/InfraWatchRole"
    }
  ]
}

Set the access key and secret in your .env or Helm values as POWER_AWS_ACCESS_KEY_ID and POWER_AWS_SECRET_ACCESS_KEY.

Step 2 — Create the IAM Role

Create an IAM role (e.g., InfraWatchRole) that the IAM user can assume. The trust policy should allow the user's account:

Trust Policy
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::123456789012:user/infrawatch-power-user"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

Set this role's ARN as BASE_ROLE_ARN in your configuration.

Step 3 — Attach Permissions to the Role

The base role needs read-only access to the AWS services InfraWatch monitors. Attach a policy with the following actions:

ServiceRequired IAM Actions
EC2ec2:Describe*
EKSeks:List*, eks:Describe*
Databasesrds:Describe*, rds:List*, docdb:Describe*, docdb:List*
ElastiCacheelasticache:Describe*, elasticache:List*
OpenSearches:List*, es:Describe*, es:ESHttpGet
MQmq:List*, mq:Describe*
SESses:*, sesv2:*
Secrets Managersecretsmanager:Get*, secretsmanager:List*, secretsmanager:Describe*
IAMiam:Get*, iam:List*, iam:GenerateCredentialReport
Cost Explorerce:Get*, ce:List*, ce:Describe*
Load Balancerselasticloadbalancing:Describe*
CloudWatchcloudwatch:Get*, cloudwatch:List*
AWS Healthhealth:Describe*
CloudWatch is always included
Every session policy includes CloudWatch permissions regardless of which services the user requested, since all service panels need CloudWatch for metrics.

Full IAM Policy

Here's a complete policy you can attach to the role:

InfraWatchReadOnlyPolicy
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "EC2",
      "Effect": "Allow",
      "Action": "ec2:Describe*",
      "Resource": "*"
    },
    {
      "Sid": "EKS",
      "Effect": "Allow",
      "Action": ["eks:List*", "eks:Describe*"],
      "Resource": "*"
    },
    {
      "Sid": "Databases",
      "Effect": "Allow",
      "Action": [
        "rds:Describe*", "rds:List*",
        "docdb:Describe*", "docdb:List*"
      ],
      "Resource": "*"
    },
    {
      "Sid": "ElastiCache",
      "Effect": "Allow",
      "Action": ["elasticache:Describe*", "elasticache:List*"],
      "Resource": "*"
    },
    {
      "Sid": "OpenSearch",
      "Effect": "Allow",
      "Action": ["es:List*", "es:Describe*", "es:ESHttpGet"],
      "Resource": "*"
    },
    {
      "Sid": "MQ",
      "Effect": "Allow",
      "Action": ["mq:List*", "mq:Describe*"],
      "Resource": "*"
    },
    {
      "Sid": "SES",
      "Effect": "Allow",
      "Action": ["ses:*", "sesv2:*"],
      "Resource": "*"
    },
    {
      "Sid": "SecretsManager",
      "Effect": "Allow",
      "Action": [
        "secretsmanager:Get*",
        "secretsmanager:List*",
        "secretsmanager:Describe*"
      ],
      "Resource": "*"
    },
    {
      "Sid": "IAM",
      "Effect": "Allow",
      "Action": [
        "iam:Get*", "iam:List*",
        "iam:GenerateCredentialReport"
      ],
      "Resource": "*"
    },
    {
      "Sid": "CostExplorer",
      "Effect": "Allow",
      "Action": ["ce:Get*", "ce:List*", "ce:Describe*"],
      "Resource": "*"
    },
    {
      "Sid": "LoadBalancers",
      "Effect": "Allow",
      "Action": "elasticloadbalancing:Describe*",
      "Resource": "*"
    },
    {
      "Sid": "CloudWatch",
      "Effect": "Allow",
      "Action": ["cloudwatch:Get*", "cloudwatch:List*"],
      "Resource": "*"
    },
    {
      "Sid": "Health",
      "Effect": "Allow",
      "Action": "health:Describe*",
      "Resource": "*"
    }
  ]
}

Session Policies

When a user's access request is approved, InfraWatch calls sts:AssumeRole with a session policy that limits the temporary credentials to only the approved services. For example, if a user is approved for EC2 and RDS, the session policy only includes ec2:Describe*, rds:Describe*, rds:List*, and cloudwatch:*.

This means:

AWS Health API

The AWS Health API (health:Describe*) requires a Business or Enterprise support plan. If your account doesn't have one, the collector handles the SubscriptionRequiredException gracefully — health events simply won't appear in the alerts panel.