AWS Security ChangesHomeSearch

AWS AmazonCloudWatch documentation change

Service: AmazonCloudWatch · 2025-05-01 · Documentation low

File: AmazonCloudWatch/latest/monitoring/CloudWatch-Application-Signals-EKS-CDK.md

Summary

Revised documentation to use AWS CDK constructs for Application Signals setup on ECS, including code examples for sidecar, daemon, and replica modes. Added security group configuration guidance for replica mode and updated Node.js ESM instructions.

Security assessment

The changes introduce security-related documentation by specifying security group configurations for replica mode (ports 2000/4316) and abstracting IAM role management via CDK constructs. However, the replica mode code example includes an overly permissive security group rule (allowing all TCP ports), which could lead to misconfigurations if followed without adjustment. There is no explicit evidence of addressing a known security vulnerability.

Diff

diff --git a/AmazonCloudWatch/latest/monitoring/CloudWatch-Application-Signals-EKS-CDK.md b/AmazonCloudWatch/latest/monitoring/CloudWatch-Application-Signals-EKS-CDK.md
index 7e7852a63..34857a67e 100644
--- a//AmazonCloudWatch/latest/monitoring/CloudWatch-Application-Signals-EKS-CDK.md
+++ b//AmazonCloudWatch/latest/monitoring/CloudWatch-Application-Signals-EKS-CDK.md
@@ -33 +33 @@ For more information about this role, see [Service-linked role permissions for C
-  2. Create IAM roles – You must create an IAM role. If you already have created this role, you might need to add permissions to it.
+  2. Instrument your application with the [AWS::ApplicationSignals Construct Library](https://www.npmjs.com/package/@aws-cdk/aws-applicationsignals-alpha) in the AWS CDK. The code snippets in this document are provided in _TypeScript_. For other language-specific alternatives, see [Supported programming languages for the AWS CDK](https://docs.aws.amazon.com/cdk/v2/guide/languages.html). 
@@ -35 +35 @@ For more information about this role, see [Service-linked role permissions for C
-**ECS task role—** Containers use this role to run. The permissions should be whatever your applications need, plus **CloudWatchAgentServerPolicy**. 
+     * **Enable Application Signals on Amazon ECS with sidecar mode**
@@ -37 +37 @@ For more information about this role, see [Service-linked role permissions for C
-For more information about creating IAM roles, see [Creating IAM Roles](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_create.html).
+       1. Configure `instrumentation` to instrument the application with the AWS Distro for OpenTelemetry (ADOT) SDK Agent. The following is an example of instrumenting a Java application. See [InstrumentationVersion](https://docs.aws.amazon.com/cdk/api/v2/docs/@aws-cdk_aws-applicationsignals-alpha.InstrumentationVersion.html) for all supported language versions.
@@ -39 +39 @@ For more information about creating IAM roles, see [Creating IAM Roles](https://
-  3. Instrument your application with the CloudWatch agent in AWS CDK – To enable Application Signals for Amazon ECS using the AWS CDK, follow the steps outlined below. The code snippets in this document are provided in TypeScript. For other language-specific alternatives, see [Supported programming languages for the AWS CDK cloudwatch-agent](https://docs.aws.amazon.com/cdk/v2/guide/languages.html)
+       2. Specify `cloudWatchAgentSidecar` to configure the CloudWatch Agent as a sidecar container.
@@ -41 +41,5 @@ For more information about creating IAM roles, see [Creating IAM Roles](https://
-To instrument your application with the CloudWatch agent, do the following.
+                        import { Construct } from 'constructs';
+            import * as appsignals from '@aws-cdk/aws-applicationsignals-alpha';
+            import * as cdk from 'aws-cdk-lib';
+            import * as ec2 from 'aws-cdk-lib/aws-ec2';
+            import * as ecs from 'aws-cdk-lib/aws-ecs';
@@ -43 +47,5 @@ To instrument your application with the CloudWatch agent, do the following.
-    1. In your application task definition, specify a bind mount. Replace `MOUNT_VOLUME` according to the language your application uses. For example use `opentelemetry-auto-instrumentation` in Java. The volume will be used to share files across containers in the next steps. You will use this bind mount later in this procedure:
+            class MyStack extends cdk.Stack {
+              public constructor(scope?: Construct, id?: string, props: cdk.StackProps = {}) {
+                super();
+                const vpc = new ec2.Vpc(this, 'TestVpc', {});
+                const cluster = new ecs.Cluster(this, 'TestCluster', { vpc });
@@ -45,10 +53,4 @@ To instrument your application with the CloudWatch agent, do the following.
-                const taskDefinition = new ecs.FargateTaskDefinition(this, 'MyTaskDefinition', {
-          ...
-          volumes: [{
-            name: MOUNT_VOLUME,
-          }]
-         );
-        
-        
-
-    2. Next, you add the CloudWatch agent. There are two possible methods to use add CloudWatch agent: sidecar strategy and daemon strategy. For information about the pros and cons for each method, see [Use a custom setup to enable Application Signals on Amazon ECS](./CloudWatch-Application-Signals-Enable-ECSMain.html#CloudWatch-Application-Signals-Enable-ECS) and choose the best method for your environment.
+                const fargateTaskDefinition = new ecs.FargateTaskDefinition(this, 'SampleAppTaskDefinition', {
+                  cpu: 2048,
+                  memoryLimitMiB: 4096,
+                });
@@ -56 +58,3 @@ To instrument your application with the CloudWatch agent, do the following.
-       * **Sidecar strategy** – Append a new container called `ecs-cwagent` to your application's task definition. Replace `$IMAGE` with the path to the latest CloudWatch container image on Amazon Elastic Container Registry. For more information, see [ cloudwatch-agent](https://gallery.ecr.aws/cloudwatch-agent/cloudwatch-agent) on Amazon ECR.
+                fargateTaskDefinition.addContainer('app', {
+                  image: ecs.ContainerImage.fromRegistry('test/sample-app'),
+                });
@@ -58,4 +62,4 @@ To instrument your application with the CloudWatch agent, do the following.
-                        const cwAgentContainer = taskDefinition.addContainer('ecs-cwagent', {
-              image: ecs.ContainerImage.fromRegistry("$IMAGE"),
-              environment: {
-                CW_CONFIG_CONTENT: '{"agent": {"debug": true}, "traces": {"traces_collected": {"application_signals": {"enabled": true}}}, "logs": {"metrics_collected": {"application_signals": {"enabled": true}}}}',
+                new appsignals.ApplicationSignalsIntegration(this, 'ApplicationSignalsIntegration', {
+                  taskDefinition: fargateTaskDefinition,
+                  instrumentation: {
+                    sdkVersion: appsignals.JavaInstrumentationVersion.V2_10_0,
@@ -63,6 +67,13 @@ To instrument your application with the CloudWatch agent, do the following.
-              logging: new ecs.AwsLogDriver({
-                streamPrefix: 'ecs',
-                logGroup: new logs.LogGroup(this, 'CwAgentLogGroup', {
-                  logGroupName: '/ecs/ecs-cwagent',
-                }),
-              }),
+                  serviceName: 'sample-app',
+                  cloudWatchAgentSidecar: {
+                    containerName: 'ecs-cwagent',
+                    enableLogging: true,
+                    cpu: 256,
+                    memoryLimitMiB: 512,
+                  }
+                });
+            
+                new ecs.FargateService(this, 'MySampleApp', {
+                  cluster: cluster,
+                  taskDefinition: fargateTaskDefinition,
+                  desiredCount: 1,
@@ -69,0 +81,2 @@ To instrument your application with the CloudWatch agent, do the following.
+              }
+            }
@@ -71 +84 @@ To instrument your application with the CloudWatch agent, do the following.
-       * **Daemon strategy** – Create a new service called `ecs-cwagent` in your stack. Replace `$TASK_ROLE_ARN` and `$EXECUTION_ROLE_ARN` with the IAM roles that you prepared. Replace `$IMAGE` with the path to the latest CloudWatch container image on Amazon Elastic Container Registry. For more information, see [ cloudwatch-agent](https://gallery.ecr.aws/cloudwatch-agent/cloudwatch-agent) on Amazon ECR.
+     * **Enable Application Signals on Amazon ECS with daemon mode**
@@ -75 +88,5 @@ To instrument your application with the CloudWatch agent, do the following.
-The daemon service exposes two ports on the host, with 4316 used as the endpoint for receiving metrics and traces and 2000 as the CloudWatch trace sampler endpoint. This setup allows the agent to collect and transmit telemetry data from all application tasks running on the host. Ensure that these ports are not used by other services on the host to avoid conflicts.
+The daemon deployment strategy is not supported on Amazon ECS Fargate and is only supported on Amazon ECS on Amazon EC2.
+
+       1. Run CloudWatch Agent as a daemon service with `HOST` network mode.
+
+       2. Configure `instrumentation` to instrument the application with the ADOT Python Agent.
@@ -77,3 +94,16 @@ The daemon service exposes two ports on the host, with 4316 used as the endpoint
-                        const cwAgentTaskDefinition = new ecs.Ec2TaskDefinition(this, 'CwAgentDaemonTaskDef', {
-                taskRole: "$TASK_ROLE_ARN",
-                executionRole: "$EXECUTION_ROLE_ARN",
+                        import { Construct } from 'constructs';
+            import * as appsignals from '@aws-cdk/aws-applicationsignals-alpha';
+            import * as cdk from 'aws-cdk-lib';
+            import * as ec2 from 'aws-cdk-lib/aws-ec2';
+            import * as ecs from 'aws-cdk-lib/aws-ecs';
+            
+            class MyStack extends cdk.Stack {
+              public constructor(scope?: Construct, id?: string, props: cdk.StackProps = {}) {
+                super(scope, id, props);
+            
+                const vpc = new ec2.Vpc(this, 'TestVpc', {});
+                const cluster = new ecs.Cluster(this, 'TestCluster', { vpc });
+            
+                // Define Task Definition for CloudWatch agent (Daemon)
+                const cwAgentTaskDefinition = new ecs.Ec2TaskDefinition(this, 'CloudWatchAgentTaskDefinition', {
+                  networkMode: ecs.NetworkMode.HOST,
@@ -82,3 +112,4 @@ The daemon service exposes two ports on the host, with 4316 used as the endpoint
-            // Add the CloudWatch agent container
-            const cwAgentContainer = cwAgentTaskDefinition.addContainer('ecs-cwagent', {
-                image: ecs.ContainerImage.fromRegistry("$IMAGE"),
+                new appsignals.CloudWatchAgentIntegration(this, 'CloudWatchAgentIntegration', {
+                  taskDefinition: cwAgentTaskDefinition,
+                  containerName: 'ecs-cwagent',
+                  enableLogging: false,
@@ -97,9 +127,0 @@ The daemon service exposes two ports on the host, with 4316 used as the endpoint
-                logging: new ecs.AwsLogDriver({
-                    streamPrefix: 'ecs',
-                    logGroup: new logs.LogGroup(this, 'CwAgentLogGroup', {
-                        logGroupName: '/ecs/ecs-cwagent-daemon',
-                    }),
-                }),
-                environment: {
-                    CW_CONFIG_CONTENT: '{"agent": {"debug": true}, "traces": {"traces_collected": {"application_signals": {"enabled": true}}}, "logs": {"metrics_collected": {"application_signals": {"enabled": true}}}}',
-                },
@@ -108,2 +130,2 @@ The daemon service exposes two ports on the host, with 4316 used as the endpoint
-            // Add the CloudWatch agent service running as a daemon
-            const cwAgentService = new ecs.Ec2Service(this, 'CwAgentDaemonService', {
+                // Create the CloudWatch Agent daemon service
+                new ecs.Ec2Service(this, 'CloudWatchAgentDaemon', {
@@ -112 +134 @@ The daemon service exposes two ports on the host, with 4316 used as the endpoint
-                daemon: true,
+                  daemon: true,  // Runs one container per EC2 instance
@@ -115 +137,4 @@ The daemon service exposes two ports on the host, with 4316 used as the endpoint
-    3. Append a new container init to your application's task definition. Replace `$IMAGE` with the latest image from the [AWS Distro for OpenTelemetry Amazon ECR image repository](https://gallery.ecr.aws/aws-observability/adot-autoinstrumentation-java). Replace `MOUNT_CONTAINER_PATH` and `INIT_CONTAINER_COMMAND` according to the language your application uses.
+                // Define Task Definition for user application
+                const sampleAppTaskDefinition = new ecs.Ec2TaskDefinition(this, 'SampleAppTaskDefinition', {
+                  networkMode: ecs.NetworkMode.HOST,
+                });
@@ -117 +142,5 @@ The daemon service exposes two ports on the host, with 4316 used as the endpoint
-For example, in Java use ``INIT_CONTAINER_COMMAND`=["cp", "/javaagent.jar", "/otel-auto-instrumentation/javaagent.jar"], `MOUNT_CONTAINER_PATH`='/otel-auto-instrumentation'`
+                sampleAppTaskDefinition.addContainer('app', {
+                  image: ecs.ContainerImage.fromRegistry('test/sample-app'),
+                  cpu: 0,
+                  memoryLimitMiB: 512,
+                });
@@ -119,4 +148,7 @@ For example, in Java use ``INIT_CONTAINER_COMMAND`=["cp", "/javaagent.jar", "/ot
-                const initContainer = taskDefinition.addContainer('init', {
-            image: ecs.ContainerImage.fromRegistry("$IMAGE"),
-            essential: false,
-            command: INIT_CONTAINER_COMMAND
+                // No CloudWatch Agent sidecar is needed as application container communicates to CloudWatch Agent daemon through host network
+                new appsignals.ApplicationSignalsIntegration(this, 'ApplicationSignalsIntegration', {
+                  taskDefinition: sampleAppTaskDefinition,
+                  instrumentation: {
+                    sdkVersion: appsignals.PythonInstrumentationVersion.V0_8_0
+                  },
+                  serviceName: 'sample-app'
@@ -125,4 +157,4 @@ For example, in Java use ``INIT_CONTAINER_COMMAND`=["cp", "/javaagent.jar", "/ot
-        initContainer.addMountPoints({
-            sourceVolume: MOUNT_VOLUME,
-            containerPath: MOUNT_CONTAINER_PATH,
-            readOnly: false
+                new ecs.Ec2Service(this, 'MySampleApp', {
+                  cluster,
+                  taskDefinition: sampleAppTaskDefinition,
+                  desiredCount: 1,
@@ -129,0 +162,2 @@ For example, in Java use ``INIT_CONTAINER_COMMAND`=["cp", "/javaagent.jar", "/ot
+              }
+            }
@@ -131 +165 @@ For example, in Java use ``INIT_CONTAINER_COMMAND`=["cp", "/javaagent.jar", "/ot
-    4. Add the environment variables `ENVIRONMENT_VARIABLES` to your application container according to the language your application uses. And mount the volume `MOUNT_VOLUME` in the application container.
+     * **Enable Application Signals on Amazon ECS with replica mode**
@@ -135 +169,3 @@ For example, in Java use ``INIT_CONTAINER_COMMAND`=["cp", "/javaagent.jar", "/ot
-For language-specific setup instructions that specify values for `MOUNT_VOLUME`>, `MOUNT_CONTAINER_PATH`>, `INIT_CONTAINER_COMMAND`>, and `ENVIRONMENT_VARIABLES`, see [Step 4: Instrument your application with the CloudWatch agent](./CloudWatch-Application-Signals-ECS-Sidecar.html#CloudWatch-Application-Signals-Enable-ECS-Instrument). 
+Running CloudWatch Agent service using replica mode requires specific security group configurations to enable communication with other services. For Application Signals functionality, configure the security group with the minimum inbound rules: Port 2000 (HTTP) and Port 4316 (HTTP). This configuration ensures proper connectivity between the CloudWatch Agent and dependent services.
+
+       1. Run CloudWatch Agent as a replica service with service connect.
@@ -137 +173 @@ For language-specific setup instructions that specify values for `MOUNT_VOLUME`>
-The following is an example:
+       2. Configure `instrumentation` to instrument the application with the ADOT Python Agent.
@@ -139,5 +175,36 @@ The following is an example:
-                const appContainer = taskDefinition.addContainer('my-app', {
-            ...
-            environment: {
-                ...
-                ENVIRONMENT_VARIABLES
+       3. Override environment variables by configuring `overrideEnvironments` to use service connect endpoints to communicate to the CloudWatch agent server.
+            
+                        import { Construct } from 'constructs';
+            import * as appsignals from '@aws-cdk/aws-applicationsignals-alpha';
+            import * as cdk from 'aws-cdk-lib';
+            import * as ec2 from 'aws-cdk-lib/aws-ec2';
+            import * as ecs from 'aws-cdk-lib/aws-ecs';
+            import { PrivateDnsNamespace } from 'aws-cdk-lib/aws-servicediscovery';