> ## Documentation Index
> Fetch the complete documentation index at: /docs/llms.txt
> Use this file to discover all available pages before exploring further.

# AWS CloudWatch

> Read CloudWatch logs and metrics through an IAM role. Auto Monitors can create CloudWatch alarms.

**1. Connect**

Go to **Connections** and click **Connect** next to AWS CloudWatch. Ordyn generates an **External ID** for you.

**2. Create the role**

Run the setup command Ordyn shows in AWS CloudShell. It creates a role that trusts Ordyn's account with that External ID and grants everything below. You can also create the role by hand.

**3. Enter the role ARN and region**

Paste the role ARN, pick the region, and connect.

## Permissions

The IAM role Ordyn assumes needs the AWS managed policies CloudWatchReadOnlyAccess and ViewOnlyAccess, plus the `struct-coverage-access` inline policy (89 actions) for Auto Monitors, infrastructure checks and AMP. AMP access is optional for connection readiness; setup includes it.

### Verify permissions

Check the role's own permissions without creating anything.

Granted by: `struct-coverage-access`.

| Permission | Used for |
| - | - |
| `iam:SimulatePrincipalPolicy` | Without it every other check is reported as unverified. |

### Infrastructure inventory

List the account's resources in every enabled region.

Granted by: `ViewOnlyAccess`, `struct-coverage-access`.

Permissions Ordyn uses: `resource-explorer-2:Search`, `resource-explorer-2:ListResources`, `resource-explorer-2:GetIndex`, `resource-explorer-2:GetView`, `resource-explorer-2:GetDefaultView`, `ec2:DescribeRegions`.

### Resource configuration

Read control-plane configuration without application data or secret values.

Granted by: `struct-coverage-access`.

> **Permissions Ordyn uses (51)**
>
> ```text theme={null}
> sts:GetCallerIdentity
> ec2:DescribeRegions
> ec2:DescribeInstances
> ec2:DescribeSecurityGroups
> cloudtrail:LookupEvents
> eks:DescribeCluster
> dynamodb:DescribeTable
> s3:GetBucketVersioning
> resource-explorer-2:Search
> resource-explorer-2:ListResources
> resource-explorer-2:ListIndexes
> resource-explorer-2:GetIndex
> resource-explorer-2:GetView
> resource-explorer-2:GetDefaultView
> resource-explorer-2:ListSupportedResourceTypes
> cloudformation:ListTypes
> cloudformation:DescribeType
> cloudformation:ListResources
> cloudformation:GetResource
> iam:SimulatePrincipalPolicy
> iam:GetRole
> iam:ListAttachedRolePolicies
> iam:ListRolePolicies
> iam:GetRolePolicy
> iam:GetPolicy
> iam:GetPolicyVersion
> lambda:GetFunctionConfiguration
> lambda:GetPolicy
> lambda:ListFunctions
> ecs:DescribeServices
> ecs:DescribeTaskDefinition
> ecs:ListServices
> ecs:ListClusters
> ecs:DescribeClusters
> rds:DescribeDBInstances
> rds:DescribeDBClusters
> rds:DescribeDBParameters
> elasticache:DescribeCacheClusters
> elasticache:DescribeReplicationGroups
> elasticloadbalancing:DescribeLoadBalancers
> elasticloadbalancing:DescribeTargetGroups
> elasticloadbalancing:DescribeTargetHealth
> sqs:ListQueues
> sqs:GetQueueUrl
> sqs:GetQueueAttributes
> sqs:ListQueueTags
> sns:GetTopicAttributes
> s3:GetBucketLocation
> s3:GetBucketTagging
> s3:GetBucketNotification
> s3:GetBucketPolicyStatus
> ```

### Metrics

Discover and query CloudWatch metrics.

Granted by: `CloudWatchReadOnlyAccess`.

Permissions Ordyn uses: `cloudwatch:ListMetrics`, `cloudwatch:GetMetricData`, `cloudwatch:GetMetricStatistics`.

### Logs

Read existing logs and run read-only log queries.

Granted by: `CloudWatchReadOnlyAccess`.

Permissions Ordyn uses: `logs:DescribeLogGroups`, `logs:FilterLogEvents`, `logs:StartQuery`, `logs:GetQueryResults`, `logs:StopQuery`.

### Infrastructure change history

Read management events to refresh resources that changed.

Granted by: `ViewOnlyAccess`, `struct-coverage-access`.

Permissions Ordyn uses: `cloudtrail:LookupEvents`.

### Managed Prometheus metrics

Only needed for AMP: discover workspaces and query PromQL using the existing role.

Granted by: `struct-coverage-access`.

Permissions Ordyn uses: `aps:ListWorkspaces`, `aps:DescribeWorkspace`, `aps:QueryMetrics`, `aps:GetLabels`, `aps:GetSeries`, `aps:GetMetricMetadata`.

### Managed Prometheus rule inventory

Only needed for AMP: inspect existing alerts, recording rules and delivery.

Granted by: `struct-coverage-access`.

Permissions Ordyn uses: `aps:ListRuleGroupsNamespaces`, `aps:DescribeRuleGroupsNamespace`, `aps:DescribeAlertManagerDefinition`.

### Manage Prometheus alerts

Only needed for AMP: manage native rules, Alertmanager and SNS delivery.

Granted by: `struct-coverage-access`.

> **Permissions Ordyn uses (16)**
>
> ```text theme={null}
> aps:ListRuleGroupsNamespaces
> aps:DescribeRuleGroupsNamespace
> aps:DescribeAlertManagerDefinition
> aps:CreateRuleGroupsNamespace
> aps:PutRuleGroupsNamespace
> aps:DeleteRuleGroupsNamespace
> aps:CreateAlertManagerDefinition
> aps:PutAlertManagerDefinition
> aps:TagResource
> sns:CreateTopic
> sns:TagResource
> sns:ListTagsForResource
> sns:GetTopicAttributes
> sns:SetTopicAttributes
> sns:ListSubscriptionsByTopic
> sns:Subscribe
> ```

### Manage monitoring

Create, tag, inspect and remove the alarms and metric filters Ordyn manages, and the SNS topic that delivers alarms to Ordyn.

Granted by: `struct-coverage-access`.

| Permission | Used for |
| - | - |
| `cloudwatch:DescribeAlarms` | |
| `cloudwatch:ListMetrics` | |
| `cloudwatch:GetMetricData` | |
| `cloudwatch:PutMetricAlarm` | |
| `cloudwatch:DeleteAlarms` | |
| `cloudwatch:ListTagsForResource` | |
| `cloudwatch:TagResource` | Alarms are created with tags, so this is needed alongside cloudwatch:PutMetricAlarm. |
| `cloudwatch:UntagResource` | |
| `logs:DescribeLogGroups` | |
| `logs:DescribeMetricFilters` | Finding the metric filters Ordyn created. |
| `logs:FilterLogEvents` | |
| `logs:GetLogEvents` | |
| `logs:StartQuery` | |
| `logs:GetQueryResults` | |
| `logs:StopQuery` | |
| `logs:PutMetricFilter` | |
| `logs:DeleteMetricFilter` | |
| `sns:CreateTopic` | |
| `sns:TagResource` | |
| `sns:Subscribe` | |
| `sns:ListSubscriptionsByTopic` | |

* Inventory reads through AWS Resource Explorer. Turn on Resource Explorer indexing in the account and set an unfiltered default view, or Ordyn reports inventory as incomplete.
* Do not use CloudWatchLogsReadOnlyAccess alone: it cannot list metrics or describe alarms.
* Some configuration responses can include sensitive values, such as Lambda and ECS environment variables. Ordyn redacts environment variables and known secret-bearing fields before saving resource snapshots.

### How to grant

> **Create the role (AWS CloudShell)**
>
> ```bash theme={null}
> aws iam create-role --role-name=StructCloudWatchRole --assume-role-policy-document '{"Version": "2012-10-17", "Statement": [{"Effect": "Allow", "Principal": {"AWS": "<struct-principal-arn>"}, "Action": "sts:AssumeRole", "Condition": {"StringEquals": {"sts:ExternalId": "<external-id>"}}}]}' --query 'Role.Arn' --output text &&
> aws iam attach-role-policy --role-name=StructCloudWatchRole --policy-arn arn:aws:iam::aws:policy/job-function/ViewOnlyAccess &&
> aws iam attach-role-policy --role-name=StructCloudWatchRole --policy-arn arn:aws:iam::aws:policy/CloudWatchReadOnlyAccess &&
> aws iam put-role-policy --role-name=StructCloudWatchRole --policy-name struct-coverage-access --policy-document '{"Version": "2012-10-17", "Statement": [{"Effect": "Allow", "Action": ["cloudwatch:DescribeAlarms", "cloudwatch:ListMetrics", "cloudwatch:GetMetricData", "cloudwatch:PutMetricAlarm", "cloudwatch:DeleteAlarms", "cloudwatch:ListTagsForResource", "cloudwatch:TagResource", "cloudwatch:UntagResource", "logs:DescribeLogGroups", "logs:DescribeMetricFilters", "logs:FilterLogEvents", "logs:GetLogEvents", "logs:StartQuery", "logs:GetQueryResults", "logs:StopQuery", "logs:PutMetricFilter", "logs:DeleteMetricFilter", "sns:CreateTopic", "sns:TagResource", "sns:Subscribe", "sns:ListSubscriptionsByTopic", "sts:GetCallerIdentity", "ec2:DescribeRegions", "ec2:DescribeInstances", "ec2:DescribeSecurityGroups", "cloudtrail:LookupEvents", "eks:DescribeCluster", "dynamodb:DescribeTable", "s3:GetBucketVersioning", "resource-explorer-2:Search", "resource-explorer-2:ListResources", "resource-explorer-2:ListIndexes", "resource-explorer-2:GetIndex", "resource-explorer-2:GetView", "resource-explorer-2:GetDefaultView", "resource-explorer-2:ListSupportedResourceTypes", "cloudformation:ListTypes", "cloudformation:DescribeType", "cloudformation:ListResources", "cloudformation:GetResource", "iam:SimulatePrincipalPolicy", "iam:GetRole", "iam:ListAttachedRolePolicies", "iam:ListRolePolicies", "iam:GetRolePolicy", "iam:GetPolicy", "iam:GetPolicyVersion", "lambda:GetFunctionConfiguration", "lambda:GetPolicy", "lambda:ListFunctions", "ecs:DescribeServices", "ecs:DescribeTaskDefinition", "ecs:ListServices", "ecs:ListClusters", "ecs:DescribeClusters", "rds:DescribeDBInstances", "rds:DescribeDBClusters", "rds:DescribeDBParameters", "elasticache:DescribeCacheClusters", "elasticache:DescribeReplicationGroups", "elasticloadbalancing:DescribeLoadBalancers", "elasticloadbalancing:DescribeTargetGroups", "elasticloadbalancing:DescribeTargetHealth", "sqs:ListQueues", "sqs:GetQueueUrl", "sqs:GetQueueAttributes", "sqs:ListQueueTags", "sns:GetTopicAttributes", "s3:GetBucketLocation", "s3:GetBucketTagging", "s3:GetBucketNotification", "s3:GetBucketPolicyStatus", "aps:ListWorkspaces", "aps:DescribeWorkspace", "aps:QueryMetrics", "aps:GetLabels", "aps:GetSeries", "aps:GetMetricMetadata", "aps:ListRuleGroupsNamespaces", "aps:DescribeRuleGroupsNamespace", "aps:DescribeAlertManagerDefinition", "aps:CreateRuleGroupsNamespace", "aps:PutRuleGroupsNamespace", "aps:DeleteRuleGroupsNamespace", "aps:CreateAlertManagerDefinition", "aps:PutAlertManagerDefinition", "aps:TagResource", "sns:ListTagsForResource", "sns:SetTopicAttributes"], "Resource": "*"}]}'
> ```

> **Update an existing role**
>
> ```bash theme={null}
> aws iam attach-role-policy --role-name=<role-name> --policy-arn arn:aws:iam::aws:policy/job-function/ViewOnlyAccess &&
> aws iam attach-role-policy --role-name=<role-name> --policy-arn arn:aws:iam::aws:policy/CloudWatchReadOnlyAccess &&
> aws iam put-role-policy --role-name=<role-name> --policy-name struct-coverage-access --policy-document '{"Version": "2012-10-17", "Statement": [{"Effect": "Allow", "Action": ["cloudwatch:DescribeAlarms", "cloudwatch:ListMetrics", "cloudwatch:GetMetricData", "cloudwatch:PutMetricAlarm", "cloudwatch:DeleteAlarms", "cloudwatch:ListTagsForResource", "cloudwatch:TagResource", "cloudwatch:UntagResource", "logs:DescribeLogGroups", "logs:DescribeMetricFilters", "logs:FilterLogEvents", "logs:GetLogEvents", "logs:StartQuery", "logs:GetQueryResults", "logs:StopQuery", "logs:PutMetricFilter", "logs:DeleteMetricFilter", "sns:CreateTopic", "sns:TagResource", "sns:Subscribe", "sns:ListSubscriptionsByTopic", "sts:GetCallerIdentity", "ec2:DescribeRegions", "ec2:DescribeInstances", "ec2:DescribeSecurityGroups", "cloudtrail:LookupEvents", "eks:DescribeCluster", "dynamodb:DescribeTable", "s3:GetBucketVersioning", "resource-explorer-2:Search", "resource-explorer-2:ListResources", "resource-explorer-2:ListIndexes", "resource-explorer-2:GetIndex", "resource-explorer-2:GetView", "resource-explorer-2:GetDefaultView", "resource-explorer-2:ListSupportedResourceTypes", "cloudformation:ListTypes", "cloudformation:DescribeType", "cloudformation:ListResources", "cloudformation:GetResource", "iam:SimulatePrincipalPolicy", "iam:GetRole", "iam:ListAttachedRolePolicies", "iam:ListRolePolicies", "iam:GetRolePolicy", "iam:GetPolicy", "iam:GetPolicyVersion", "lambda:GetFunctionConfiguration", "lambda:GetPolicy", "lambda:ListFunctions", "ecs:DescribeServices", "ecs:DescribeTaskDefinition", "ecs:ListServices", "ecs:ListClusters", "ecs:DescribeClusters", "rds:DescribeDBInstances", "rds:DescribeDBClusters", "rds:DescribeDBParameters", "elasticache:DescribeCacheClusters", "elasticache:DescribeReplicationGroups", "elasticloadbalancing:DescribeLoadBalancers", "elasticloadbalancing:DescribeTargetGroups", "elasticloadbalancing:DescribeTargetHealth", "sqs:ListQueues", "sqs:GetQueueUrl", "sqs:GetQueueAttributes", "sqs:ListQueueTags", "sns:GetTopicAttributes", "s3:GetBucketLocation", "s3:GetBucketTagging", "s3:GetBucketNotification", "s3:GetBucketPolicyStatus", "aps:ListWorkspaces", "aps:DescribeWorkspace", "aps:QueryMetrics", "aps:GetLabels", "aps:GetSeries", "aps:GetMetricMetadata", "aps:ListRuleGroupsNamespaces", "aps:DescribeRuleGroupsNamespace", "aps:DescribeAlertManagerDefinition", "aps:CreateRuleGroupsNamespace", "aps:PutRuleGroupsNamespace", "aps:DeleteRuleGroupsNamespace", "aps:CreateAlertManagerDefinition", "aps:PutAlertManagerDefinition", "aps:TagResource", "sns:ListTagsForResource", "sns:SetTopicAttributes"], "Resource": "*"}]}' && struct_legacy_policies=$(aws iam list-role-policies --role-name=<role-name> --query "PolicyNames[?@ == 'struct-managed-monitors-write' || starts_with(@, 'struct-coverage-infrastructure-') || starts_with(@, 'struct-coverage-monitors-')]" --output text) && (for name in $struct_legacy_policies; do aws iam delete-role-policy --role-name=<role-name> --policy-name "$name" || exit; done)
> ```

> **The struct-coverage-access inline policy**
>
> ```json theme={null}
> {
>   "Version": "2012-10-17",
>   "Statement": [
>     {
>       "Effect": "Allow",
>       "Action": [
>         "cloudwatch:DescribeAlarms",
>         "cloudwatch:ListMetrics",
>         "cloudwatch:GetMetricData",
>         "cloudwatch:PutMetricAlarm",
>         "cloudwatch:DeleteAlarms",
>         "cloudwatch:ListTagsForResource",
>         "cloudwatch:TagResource",
>         "cloudwatch:UntagResource",
>         "logs:DescribeLogGroups",
>         "logs:DescribeMetricFilters",
>         "logs:FilterLogEvents",
>         "logs:GetLogEvents",
>         "logs:StartQuery",
>         "logs:GetQueryResults",
>         "logs:StopQuery",
>         "logs:PutMetricFilter",
>         "logs:DeleteMetricFilter",
>         "sns:CreateTopic",
>         "sns:TagResource",
>         "sns:Subscribe",
>         "sns:ListSubscriptionsByTopic",
>         "sts:GetCallerIdentity",
>         "ec2:DescribeRegions",
>         "ec2:DescribeInstances",
>         "ec2:DescribeSecurityGroups",
>         "cloudtrail:LookupEvents",
>         "eks:DescribeCluster",
>         "dynamodb:DescribeTable",
>         "s3:GetBucketVersioning",
>         "resource-explorer-2:Search",
>         "resource-explorer-2:ListResources",
>         "resource-explorer-2:ListIndexes",
>         "resource-explorer-2:GetIndex",
>         "resource-explorer-2:GetView",
>         "resource-explorer-2:GetDefaultView",
>         "resource-explorer-2:ListSupportedResourceTypes",
>         "cloudformation:ListTypes",
>         "cloudformation:DescribeType",
>         "cloudformation:ListResources",
>         "cloudformation:GetResource",
>         "iam:SimulatePrincipalPolicy",
>         "iam:GetRole",
>         "iam:ListAttachedRolePolicies",
>         "iam:ListRolePolicies",
>         "iam:GetRolePolicy",
>         "iam:GetPolicy",
>         "iam:GetPolicyVersion",
>         "lambda:GetFunctionConfiguration",
>         "lambda:GetPolicy",
>         "lambda:ListFunctions",
>         "ecs:DescribeServices",
>         "ecs:DescribeTaskDefinition",
>         "ecs:ListServices",
>         "ecs:ListClusters",
>         "ecs:DescribeClusters",
>         "rds:DescribeDBInstances",
>         "rds:DescribeDBClusters",
>         "rds:DescribeDBParameters",
>         "elasticache:DescribeCacheClusters",
>         "elasticache:DescribeReplicationGroups",
>         "elasticloadbalancing:DescribeLoadBalancers",
>         "elasticloadbalancing:DescribeTargetGroups",
>         "elasticloadbalancing:DescribeTargetHealth",
>         "sqs:ListQueues",
>         "sqs:GetQueueUrl",
>         "sqs:GetQueueAttributes",
>         "sqs:ListQueueTags",
>         "sns:GetTopicAttributes",
>         "s3:GetBucketLocation",
>         "s3:GetBucketTagging",
>         "s3:GetBucketNotification",
>         "s3:GetBucketPolicyStatus",
>         "aps:ListWorkspaces",
>         "aps:DescribeWorkspace",
>         "aps:QueryMetrics",
>         "aps:GetLabels",
>         "aps:GetSeries",
>         "aps:GetMetricMetadata",
>         "aps:ListRuleGroupsNamespaces",
>         "aps:DescribeRuleGroupsNamespace",
>         "aps:DescribeAlertManagerDefinition",
>         "aps:CreateRuleGroupsNamespace",
>         "aps:PutRuleGroupsNamespace",
>         "aps:DeleteRuleGroupsNamespace",
>         "aps:CreateAlertManagerDefinition",
>         "aps:PutAlertManagerDefinition",
>         "aps:TagResource",
>         "sns:ListTagsForResource",
>         "sns:SetTopicAttributes"
>       ],
>       "Resource": "*"
>     }
>   ]
> }
> ```

Replace the values in angle brackets.

Permission catalog version `2026-10-16.1`. See [permission changes](/reference/permission-changes).

The existing-role upgrade command, and the command Ordyn shows when a check finds missing access, replace `struct-coverage-access` and then delete inline policies that older Ordyn setups created under other names (`struct-managed-monitors-write`, `struct-coverage-infrastructure-*`, and `struct-coverage-monitors-*`). The new-role setup command does not remove legacy policies. If you created the role by hand, use the same policy name so later updates replace it.

## What Ordyn reads

Log groups and streams, CloudWatch Logs Insights queries, metrics, and existing alarms.

## Amazon Managed Service for Prometheus

Ordyn can discover AMP workspaces and query PromQL through the same assumed-role
connection. Keep the workspace ARN when reusing a query as evidence or a watch.
AMP permissions are optional and do not replace CloudWatch permissions. Query
access needs AMP workspace discovery plus query/label/series permissions; native
alert management additionally needs rule namespace, Alertmanager, and SNS delivery
permissions. The connection permission report shows the required actions.

Existing alert and recording rules remain separate. Ordyn preserves neighboring
rules and customer notification routes when changing an individual alert, and
reports incomplete inventories or configuration drift explicitly.


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.