> For the complete documentation index, see [llms.txt](https://developer.harness.io/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://developer.harness.io/continuous-delivery/use-continuous-delivery/verify-deployments/configure-cv/health-sources/cloudwatch-aws.md).

# CloudWatch Logs

Configure CloudWatch Logs as a Continuous Verification health source, including IAM permissions for Access Keys, Assume Role, IRSA, dynamic Role ARN, and OIDC

{% hint style="info" %}
This feature is in Beta[^1] and requires enablement. [View all early access features.](/release-notes/features.md)

{% @harness-feature-flag-access/request-feature-flag-access module="continuous-delivery" pagePath="continuous-delivery/use-continuous-delivery/verify-deployments/configure-cv/health-sources/cloudwatch-aws" featureFlags="%5B%7B%22name%22%3A%22CloudWatch%20Logs%20health%20source%22%2C%22key%22%3A%22CDS\_CV\_CLOUDWATCH\_LOGS\_ENABLED%22%2C%22status%22%3A%22BETA%22%2C%22description%22%3A%22Enables%20CloudWatch%20Logs%20as%20a%20Continuous%20Verification%20health%20source.%22%7D%2C%7B%22name%22%3A%22CloudWatch%20Logs%20dynamic%20Role%20ARN%22%2C%22key%22%3A%22CDS\_CV\_CLOUDWATCH\_DYNAMIC\_ROLE\_ARN\_ENABLED%22%2C%22status%22%3A%22BETA%22%2C%22description%22%3A%22Enables%20a%20per-query%20dynamic%20IAM%20Role%20ARN%20override%20for%20CloudWatch%20Logs%20health%20source%20queries.%22%7D%2C%7B%22name%22%3A%22Optional%20DescribeRegions%20for%20AWS%20connectors%22%2C%22key%22%3A%22CDS\_AWS\_DESCRIBE\_REGIONS\_OPTIONAL%22%2C%22status%22%3A%22LIMITED\_GA%22%2C%22description%22%3A%22Makes%20ec2%3ADescribeRegions%20optional%20during%20AWS%20connector%20validation.%22%7D%5D" %}
{% endhint %}

Use Amazon CloudWatch Logs as a health source for Continuous Verification. This topic covers prerequisites, configuration notes, and the IAM permissions required for Access Keys, cross-account Assume Role, IRSA, dynamic Role ARN, and OIDC.

{% hint style="info" %}
**Feature availability and delegate version**

CloudWatch Logs health source support requires the feature flag `CDS_CV_CLOUDWATCH_LOGS_ENABLED`. The oldest supported delegate version is `858xx`.
{% endhint %}

***

## What you will learn from this topic

* How to apply [general CloudWatch Logs configuration rules](#general-instructions)
* Which [IAM permissions](#iam-permissions) the AWS connector needs for DescribeRegions and Logs APIs
* How to configure [Assume Role, IRSA](#advanced-permissions-for-assume-iam-role-and-irsa), [dynamic Role ARN](#dynamic-role-arn), and [OIDC authentication](#oidc-authentication)

***

## Before you begin

* **Continuous Verification setup:** Configure an AI Verify (v1) step and health sources in your Deploy stage. Go to [Configure Continuous Verification](/continuous-delivery/use-continuous-delivery/verify-deployments/configure-cv/verify-deployments.md) to set up verification.
* **AWS connector:** Create or select an AWS connector that can reach CloudWatch Logs. Go to [AWS connector settings reference](https://developer.harness.io/docs/platform/connectors/cloud-providers/ref-cloud-providers/aws-connector-settings-reference) to configure credentials, Assume Role, IRSA, or OIDC.
* **Delegate version:** Use delegate version `858xx` or later for CloudWatch Logs, `859xx` or later for dynamic Role ARN, and `89800` or later for OIDC.

***

## General instructions

Use the following rules for each CloudWatch Logs Continuous Verification configuration:

* Select only one AWS region.
* Select multiple log groups when needed. If you enter a log group name manually, press Enter to register the value in the form.
* Start from a sample query such as: `fields @log, @logStream, @message, @timestamp`

***

## IAM permissions

### Describe Regions

By default, the AWS connector requires the `ec2:DescribeRegions` permission for validation. You can add it with the following policy. You can remove this requirement with the feature flag `CDS_AWS_DESCRIBE_REGIONS_OPTIONAL`. Go to [DescribeRegions - Optional](https://developer.harness.io/docs/platform/connectors/cloud-providers/ref-cloud-providers/aws-connector-settings-reference#describeregions---optional) for details.

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "ec2:DescribeRegions",
            "Resource": "*"
        }
    ]
}
```

### Logs

Harness uses these CloudWatch Logs APIs:

* Describe Log Groups
* Start Query
* Get Query Results

The credentials in the AWS connector must allow those operations. The following sample policies show the required shape.

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "logs:DescribeLogGroups"
            ],
            "Resource": "arn:aws:logs:*:<AWS_ACCOUNT>:*"
        }
    ]
}
```

{% hint style="info" %}
**Restrict DescribeLogGroups by region**

Replace the first `*` with an AWS region to list log groups from that region only.
{% endhint %}

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "logs:StartQuery",
                "logs:GetQueryResults"
            ],
            "Resource": "arn:aws:logs:*:<AWS_ACCOUNT>:log-group:log-group-1:*"
        }
    ]
}
```

{% hint style="info" %}
**Restrict query APIs by region**

Replace the first `*` with an AWS region if you want to restrict Start Query and Get Query Results to that region only.
{% endhint %}

These permissions are enough when you configure the connector with AWS Access Keys credentials only.

***

## Advanced permissions for Assume IAM role and IRSA

If you configure the AWS connector with either of the following options, add the permissions in this section in addition to the Logs and DescribeRegions permissions above:

* Assume IAM role on delegate
* IRSA (IAM Role on Service Account)

### Assume IAM Role on Delegate with STS enabled

When you also enable cross-account access (STS Role), the IAM Role ARN must allow the delegate to assume it, and the delegate role must allow that AssumeRole call. The setup needs a two-way handshake with permission policies and trust policies.

Suppose `IAM_Role_ARN_LOGS` in Account A (where CloudWatch Logs live) must be assumed by a delegate in Account B that uses `IAM_Role_ARN_DELEGATE`. Confirm that `IAM_Role_ARN_LOGS` also has the CloudWatch Logs and DescribeRegions permissions from the earlier section.

Use a trust policy on `IAM_Role_ARN_LOGS` similar to the following:

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "IAM_ROLE_ARN_DELEGATE"
                ]
            },
            "Action": "sts:AssumeRole"
        }
    ]
}
```

Also grant `IAM_Role_ARN_DELEGATE` permission to assume roles. For example:

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "AssumeRole",
            "Effect": "Allow",
            "Action": "sts:AssumeRole",
            "Resource": "*"
        },
        {
            "Sid": "Statement1",
            "Effect": "Allow",
            "Action": [
                "sts:AssumeRoleWithWebIdentity"
            ],
            "Resource": "*"
        }
    ]
}
```

### IRSA

For IRSA, annotate the correct service account. If the service account role ARN is `IAM_Role_ARN_SERVICE_ACCOUNT`, use a trust policy on `IAM_Role_ARN_LOGS` similar to the following:

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "IAM_ROLE_ARN_SERVICE_ACCOUNT"
                ]
            },
            "Action": "sts:AssumeRole"
        }
    ]
}
```

Also grant `IAM_Role_ARN_SERVICE_ACCOUNT` permission to assume `IAM_Role_ARN_LOGS`. For example:

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "sts:AssumeRole",
            "Resource": "IAM_ROLE_ARN_LOGS"
        }
    ]
}
```

***

## Dynamic Role ARN

### Prerequisites

* Feature flag `CDS_CV_CLOUDWATCH_DYNAMIC_ROLE_ARN_ENABLED` must be enabled.
* Oldest supported delegate version is `859xx`.

### IAM permissions

Permissions match Assume IAM Role with STS for the new dynamic role ARN (for example, `Dynamic_Role_ARN_1`). The dynamic role ARN must allow the delegate to assume it, and the delegate must be able to assume the dynamic role.

**Permission policies**

Grant the same CloudWatch Logs and DescribeRegions permissions described earlier.

**Trust policies**

Use a trust policy similar to Assume IAM role:

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "AWS": [
                    "IAM_ROLE_ARN_DELEGATE"
                ]
            },
            "Action": "sts:AssumeRole"
        }
    ]
}
```

### Setup

Enable the Dynamic ARN toggle, enter the dynamic role ARN in the text box that appears, then select the region and log group.

![CloudWatch Logs health source with Dynamic ARN enabled, role ARN field, region, and log group](https://3694223630-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2Fy1JhZ4oKIppwY7d5AhPj%2Fuploads%2Fgit-blob-df1154499bacee5296b76f3a5f196a9dfc7fac88%2Fcloudwatch-logs-1.png?alt=media)

***

## OIDC authentication

Harness supports OIDC-based AWS connectors for both CloudWatch Logs and CloudWatch Metrics health sources. With OIDC, Harness exchanges a short-lived identity token for temporary AWS credentials, so you do not need to store long-lived access keys or run a delegate with inherited IAM permissions.

{% hint style="info" %}
**Delegate version for OIDC**

This feature requires a minimum delegate version of `89800`.
{% endhint %}

### Trust policy

The IAM role that the connector assumes must trust the Harness OIDC identity provider. Replace `<AWS_ACCOUNT_ID>` and `<HARNESS_ACCOUNT_ID>` with your values.

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": {
                "Federated": "arn:aws:iam::<AWS_ACCOUNT_ID>:oidc-provider/app.harness.io/ng/api/oidc/account/<HARNESS_ACCOUNT_ID>"
            },
            "Action": "sts:AssumeRoleWithWebIdentity",
            "Condition": {
                "StringEquals": {
                    "app.harness.io/ng/api/oidc/account/<HARNESS_ACCOUNT_ID>:aud": "sts.amazonaws.com"
                }
            }
        }
    ]
}
```

### IAM permissions for OIDC

Attach the same CloudWatch permissions to the OIDC role that you use for other credential types. The following policy covers both CloudWatch Logs and CloudWatch Metrics health sources.

```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "ec2:DescribeRegions",
            "Resource": "*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "logs:DescribeLogGroups",
                "logs:StartQuery",
                "logs:GetQueryResults"
            ],
            "Resource": "arn:aws:logs:*:<AWS_ACCOUNT_ID>:*"
        },
        {
            "Effect": "Allow",
            "Action": [
                "cloudwatch:GetMetricData",
                "cloudwatch:ListMetrics"
            ],
            "Resource": "*"
        }
    ]
}
```

If you only use CloudWatch Logs, you can omit the `cloudwatch:GetMetricData` and `cloudwatch:ListMetrics` actions. If you only use CloudWatch Metrics, you can omit the `logs:*` actions.

### Cross-account access with OIDC

To access CloudWatch data in a different AWS account, add `sts:AssumeRole` to the OIDC role permission policy and configure the target account role trust policy to allow the OIDC role to assume it. This pattern matches [Assume IAM Role on Delegate with STS enabled](#assume-iam-role-on-delegate-with-sts-enabled), except the source role is the OIDC role rather than a delegate-bound role.

If you use a per-query role ARN override (CloudWatch Logs only), the override chains from the OIDC session credentials rather than from the delegate ambient identity. Go to [Dynamic Role ARN](#dynamic-role-arn) for setup details.

***

## Next steps

* [Configure Continuous Verification](/continuous-delivery/use-continuous-delivery/verify-deployments/configure-cv/verify-deployments.md): Add an AI Verify (v1) step and health sources to a Deploy stage.
* [CloudWatch](/continuous-delivery/use-continuous-delivery/verify-deployments/configure-cv/health-sources/cloudwatch.md): Configure CloudWatch Metrics as a health source.
* [AWS connector settings reference](https://developer.harness.io/docs/platform/connectors/cloud-providers/ref-cloud-providers/aws-connector-settings-reference): Configure Access Keys, Assume Role, IRSA, or OIDC for the connector.

{% @harness-feedback/feedback %}

[^1]: Beta features are feature-complete but still being validated. Available on request.
