Amazon ECS Exec to access your Windows containers on Amazon EC2 and AWS Fargate
Tags: aws, containerapps, docker, devops
Published: 2022-09-17 03:31:33

Before the announcement of this feature, ECS users deploying tasks on EC2 would need to do the following to troubleshoot issues:

- be granted ssh access to the EC2 instances
  - This alone is a big effort because it requires opening ports, distributing keys or passwords, etc.
- locate the specific EC2 instance in the cluster where the task that needs attention was deployed
- ssh into the EC2 instance
- docker exec into the container to troubleshoot

This is a lot of work (and against security best practices) to simply exec into a container (running on an EC2 instance).

**Please note** that ECS Exec is supported via [AWS SDKs](https://aws.amazon.com/tools/), [AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-welcome.html), as well as [AWS Copilot](https://aws.github.io/copilot-cli/). In the future, we will enable this capability in the AWS Console. Also, this feature only supports Linux containers (Windows containers support for ECS Exec is not part of this announcement).

**Prerequisites-Client-side requirements**

- You must have properly installed and configured the AWS CLI (for Mac, Linux, or Windows) and AWS Tools for PowerShell (only for Windows) on your computer.

- Session Manager plugin for the AWS CLI must be installed on your machine.

- Amazon ECS Agent version 1.56.0 or above must be present on your EC2 instances, when using EC2 launch type.
   - If you are using Amazon ECS-Optimized AMIs, then this functionality can be used out of the box by using the latest AMIs.
   - You can also build custom AMIs that support Amazon ECS Exec using the custom components. The details for the same are available at the Amazon ECS Developer Guide.

**Prerequisites-Server-side requirements(AWS Fargate)**
If the ECS task and its containers are running on Fargate, there is nothing you need to do because Fargate already includes all the infrastructure software requirements to enable this ECS 
capability.

Set up the required infrastructure for ECS Exec to exec into a Windows container.
 1. IAM roles required to provide permissions to the tasks
Optional
  2. AWS S3 or Cloudwatch for logging
  3. While using AWS ECS Exec to access container instance KMS key to encrypt the communication

**Steps creating AWS S3 bucket**
  1. Open [AWS S3 console](https://console.aws.amazon.com/s3/home)
  2. Select -> Create Bucket option from the console
  3. Provide Bucket name and select Region you want bucket to reside
  4. In bucket properties, choose apply **Block Public Access**
  
For more details, refer [AWS S3 user guide](https://docs.aws.amazon.com/AmazonS3/latest/userguide/create-bucket-overview.html)


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/au7iogci89wsbv1p1g97.png)



**Steps creating AWS Cloudwatch log group**
  1. Open [Cloudwatch](https://console.aws.amazon.com/cloudwatch/home) console
  2. From the side menu, Select Log groups from **Logs**
  3. From the **console Create log group** 
  4. Enter the name for the log group
  5. Select the retention settings as required
  6. Create log group in the Create option


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/esxampumqyz6mo18bj8m.png)



**Steps creating AWS IAM roles **
  1. Open  [AWS Identity and Access Management (IAM)](https://console.aws.amazon.com/iam/home) console.
  2. From the side menu, Select Roles from **Access management**
  3. From the console, select **Create role**
  4. Select ECS as service and ECS Task for trusted entities
  5. From the Attach permissions policies screen, attach AmazonECSTaskExecutionRolePolicy
  6. Provide role name
  7. From the Create role option to create task role


![Image description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/f4wmicedq9kp8uvz1awh.png)


Creating the required task role
  1. First create IAM policy for this role
  2. Select JSON to configure the policy
  3. From the below JSON code edit to add your **AWS_REGION, ACCOUNT_ID, LOG_GROUP_NAME,ECS_EXEC_BUCKET_NAME, and KMS_KEY_ARN**

```
JSON

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ssmmessages:CreateControlChannel",
                "ssmmessages:CreateDataChannel",
                "ssmmessages:OpenControlChannel",
                "ssmmessages:OpenDataChannel"
            ],
            "Resource": "*"
            },
            {
            "Effect": "Allow",
            "Action": [
                "logs:DescribeLogGroups"
            ],
            "Resource": "*"
            },
            {
            "Effect": "Allow",
            "Action": [
                "logs:CreateLogStream",
                "logs:DescribeLogStreams",
                "logs:PutLogEvents"
            ],
            "Resource": "arn:aws:logs:<AWS_REGION>:<ACCOUNT_ID>:log-group:<Log_GROUP_NAME>:*"
            },
            {
            "Effect": "Allow",
            "Action": [
                "s3:PutObject"
            ],
            "Resource": "arn:aws:s3:::< ECS_EXEC_BUCKET_NAME>/*"
            },
            {
            "Effect": "Allow",
            "Action": [
                "s3:GetEncryptionConfiguration"
            ],
            "Resource": "arn:aws:s3:::<ECS_EXEC_BUCKET_NAME>"
            },
            {
            "Effect": "Allow",
            "Action": [
                "kms:Decrypt"
            ],
            "Resource": "<KMS_KEY_ARN>"
        }
    ]
}
```

  4. Provide name for this policy and select create policy

Creating task execution IAM role
  1. Create role option from the console
  2. Select ECS as service and ECS Task for trusted entities
  3. From the Attach permissions policies screen, attach AmazonECSTaskExecutionRolePolicy
  4. Provide role name




Creating the Cluster
let’s create a cluster that uses the AWS KMS key, S3 bucket, and CloudWatch log group we previously generated under ”Infrastructure Configuration”.

```
JSON

aws ecs create-cluster \
    --cluster-name <CLUSTER_NAME> \
    --region <AWS_REGION> \
    --configuration executeCommandConfiguration="{logging=OVERRIDE,\
                                                kmsKeyId=<KMS_KEY_ID>,\
                                                logConfiguration={cloudWatchLogGroupName=<LOG_GROUP_NAME>,\
                                                                s3BucketName=<S3_BUCKET_NAME>,\
                                                                s3KeyPrefix=exec-output}}"
```

Run the tasks
Now register a simple task definition using the previously created IAM roles.

```
JSON

{
  "family": "ecs-exec-test",
  "executionRoleArn": "<ARN_OF_THE TASK_EXECUTION_ROLE_CREATED_EARLIER>",
  "taskRoleArn": "<ARN_OF_THE TASK_ROLE_CREATED_EARLIER>",
  "runtimePlatform": {
    "cpuArchitecture": "X86_64",
    "operatingSystemFamily": "WINDOWS_SERVER_2019_CORE"
  },
  "requiresCompatibilities": [
    "EC2",
    "FARGATE"
  ],
  "containerDefinitions": [
    {
      "entryPoint": [
        "powershell",
        "-Command"
      ],
      "command": [
        "ping -t localhost"
      ],
      "cpu": 1024,
      "memory": 1024,
      "image": "mcr.microsoft.com/windows/servercore:ltsc2019",
      "name": "windows_container"
    }
  ],
  "memory": "4096",
  "cpu": "2048",
  "networkMode": "awsvpc"
}
```

Register a task definition
  1. Open  [Amazon ECS console](https://console.aws.amazon.com/ecs/).
  2. Select Task Definitions.
  3. From the Console, Create new Task Definition
  4. Select AWS EC2 in launch type
  5. Use Configure via JSON
  6. Proceed to create task definition

For more details, please visit on [Creating a task definition](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/create-task-definition.html)

Now we are ready to run our AWS ECS task using Fargate launch type or EC2 launch type and use Amazon ECS Exec.

**Fargate launch type**

```
BASH

aws ecs run-task \ 
--cluster <CLUSTER_NAME> \
--task-definition <TASK_DEFINATION> \
--network-configuration awsvpcConfiguration="{subnets=[<PUBLIC_SUBNET_ID>],securityGroups=[<SECURITY_GROUP_ID>],assignPublicIp=ENABLED}" \
--enable-execute-command \
--launch-type FARGATE \
--region <AWS_REGION>
```

**EC2 launch type**

```
BASH

aws ecs start-task --cluster <CLUSTER_NAME> \
--container-instances <ECS_CONTAINER_INSTANCE_ID> \
--enable-execute-command \
--task-definition <TASK_DEFINITION_NAME>
```

You can query the task and check that the describe-task result has enableExecuteCommand flag set as true and the managed agent ExecuteCommandAgent.

```
BASH

aws ecs describe-tasks \
--cluster <CLUSTER_NAME> \
--region <AWS_REGION> \
--tasks <TASK_ID>

```

**Tearing down the environment**
Before we conclude, let’s clean up the environment we created for the demo test.
Stopping the task that was started
Terminating the EC2 instance(For EC2 launch type)
Cleanup the Amazon ECS cluster
Delete the CloudWatch log group
Delete the S3 bucket
Delete the task IAM role
Delete the task execution IAM role
Delete the AWS KMS key

-------------------