Containers

Introducing Amazon ECS Exec to access your Windows containers on Amazon EC2 and AWS Fargate

Today, we are launching the Amazon ECS Exec functionality for Amazon Elastic Container Service (Amazon ECS) customers running Windows containers on Amazon Elastic Compute Cloud (Amazon EC2), AWS Fargate or Amazon ECS Anywhere. This feature enables you to run commands in or get a shell to a container. In this blog post, we will walk through the steps for setting up the required infrastructure and demonstrate the Amazon ECS Exec feature for Amazon ECS Windows workloads running on Amazon EC2 and AWS Fargate.

Background

Prior to this feature launch, if users had to execute any commands inside their containers in order to debug, they had no option available when using Fargate launch type. For EC2 launch type, they had to undergo a complicated process that required them to:

  • Get access to their host EC2 instance either via Windows remote desktop protocol (RDP) or Session Manager. In scenarios where RDP access to the instances is disabled to improve security or the IAM policies for Session Manager are not present, the customers had to circumvent their security measures to access the host EC2 instances.
  • Find the container ID of the specific container of a task which the customer wanted to access. In production scenarios, multiple tasks with multiple containers would be running on an EC2 instance. Therefore, finding the container ID of a specific task would require multiple CLI commands.
  • Use docker exec to execute commands inside their containers.

Not only was this process cumbersome, but there also wasn’t any native support for the logging of such sessions. Lack of logging and auditing of such sessions in the production environment is not a good security practice. This feature release addresses these issues and ensures a continued seamless customer experience on Amazon ECS for Windows customers.

The primary functionality available with this feature would be:

  • The ability to establish secure interactive sessions or execute standalone commands against any Windows container of a task running on Amazon EC2, AWS Fargate, or Amazon ECS Anywhere
    • Amazon ECS Exec leverages AWS Systems Manager, specifically Systems Manager Session Manager, to create a secure channel between the device you use to initiate the exec command and the target container.
    • Amazon ECS Exec is client-platform agnostic. This means all Windows, Linux, and Mac users who have AWS CLI or AWS Copilot installed can use Amazon ECS Exec to execute commands in containers.
    • Amazon ECS Exec can also be used via AWS SDKs.
  • The native support of logging the session commands their output in Amazon S3 or Amazon CloudWatch
  • Logging of Amazon ECS Exec session information to AWS CloudTrail for auditing purposes.
    • Note that only the AWS API calls get logged (along with the command) to AWS CloudTrail. Other commands and their output are logged to CloudWatch or Amazon Simple Storage Service (Amazon S3) as configured.
  • Additional support for using your own AWS Key Management Service (AWS KMS) keys to secure the data channel between the client and the container. By default, the communication is secured using TLS1.2.

Some considerations

  • Amazon ECS Exec is supported via AWS SDKs, AWS CLI, and AWS Copilot. We will add console support for this feature in the future.
  • Amazon ECS Exec feature is not supported for Windows Server 2016 when using EC2 launch type.
  • Amazon ECS Exec cannot be used for containers running Windows Nanoserver based images.
  • Only the command, script, or shell present on the container can be used. For example, PowerShell cannot be started on an image if the same is not present in the image.
  • You can’t enable Amazon ECS Exec for existing tasks. It can only be enabled for new tasks by specifying --enable-execute-command flag during task launch.

Prerequisites

There are a few requirements that must be completed for using Amazon ECS Exec with Windows workloads:

  • 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.

Getting Started

Infrastructure Configuration

Before we can use Amazon ECS Exec to exec into a Windows container, we need to set up the required infrastructure. This includes:

  • (Optional) AWS KMS key to encrypt the communication while using Amazon ECS Exec to access container instances
  • (Optional) Logging options including Amazon S3 or CloudWatch
  • Relevant IAM roles to provide appropriate permissions to the tasks

For creating the AWS KMS key:

  1. Access the AWS KMS console.
  2. Select Create Key option from the console.
  3. In the following Create Key wizard:
    1. Select the key type as Symmetric.
    2. Provide an appropriate key alias. For example, ecs_exec_windows_demo_key.
    3. Select Next on Define key administrative permissions
    4. Select Next on Define key usage permissions
    5. Select Finish to create the AWS KMS key.
    6. Take note of the Key ID, as it will be used in the next step.

For more information, please visit the documentation on Creating keys.

Key Management Service console key configuration

Now, let’s create the Amazon S3 bucket and CloudWatch log group for storing the session logs.

For creating the Amazon S3 bucket:

  1. Access the Amazon S3 console.
  2. Select Create Bucket option from the console.
  3. In the following Create Bucket wizard:
    1. Provide an appropriate bucket name. For example, ecs-exec-windows-demo-bucket.
    2. Select the Region where you want the bucket to reside.
    3. In bucket settings for Block Public Access, choose the Block Public Access settings that you want to apply to the bucket. For our demo, we can block all public access.
    4. Select Create Bucket option to create the S3 bucket.

For more information, please visit the documentation available at the Amazon S3 User Guide.

Creating S3 bucket in console

For creating the CloudWatch log group:

  1. Access the CloudWatch console.
  2. Select Log groups from Logs in the side menu.
  3. Select Create log group option from the console.
  4. In the following wizard:
    1. Enter a name for the log group. For example, ecs_exec_windows_demo_log_group.
    2. Select the retention setting as required.
    3. Select the Create option to create the log group.

For more information, please visit the documentation available here.

Creating CloudWatch log group in console

For creating the IAM roles required by the tasks for enabling Amazon ECS Exec:

  1. Access the AWS Identity and Access Management (IAM) console.
  2. Select Roles from Access management in the side menu.
  3. For creating the required task execution role:
    1. Select Create role option from the console.
    2. For trusted entities, select Elastic Container Service as service and Elastic Container Service Task as the use case.
    3. Attach AmazonECSTaskExecutionRolePolicy policy in the Attach permissions policies screen.
    4. Provide the appropriate role name in the review screen. For example, ecs_exec_windows_demo_task_execution_role
    5. Select Create role option to create the task role.UI to select create role option
  1. For creating the required task role:
    1. Before creating the task role, let’s create the IAM policy required for this role.
      1. Select Policies from Access management in the side menu.
      2. In the following wizard, select JSON to configure the policy.
      3. Copy the following JSON into the policy editor. Be sure to edit the JSON to add your AWS_REGION, ACCOUNT_ID, LOG_GROUP_NAME, ECS_EXEC_BUCKET_NAME, and KMS_KEY_ARN.
{
    "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>"
        }
    ]
}
      1. Provide an appropriate name for this policy. For example, ecs_exec_windows_demo_task_role_policy.
      2. Select Create policy to create this policy.
    1. Creating the task execution IAM role:
      1. Select Create role option from the console.
      2. For trusted entities, select Elastic Container Service as service and Elastic Container Service Task as the use case.
      3. Attach the previously created policy in the Attach permissions policies screen.
      4. Provide the appropriate role name in the review screen. For example, ecs_exec_windows_demo_task_role.
      5. Select Create role option to create the task role.UI to select create role option

For more information about creating task IAM Roles, please visit the documentation available at the Amazon ECS Developer Guide.

Creating the cluster

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

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}}"

Note: For now, this needs to be done using AWS CLI, AWS SDK, or AWS Copilot. Also, if the logging configuration is not required, then we can create a cluster from the console itself and use that for accessing Windows containers using Amazon ECS Exec.

Now that we have created a cluster, we can launch tasks in it using Fargate launch type which eliminates any need to manage container instances. Alternatively, we can launch EC2 instances with the latest Amazon ECS optimized Windows AMIs to use ECS Exec.

Running the tasks

Now that the required infrastructure has been created, let’s register a simple task definition using the previously created IAM roles. A sample task definition is provided below. As visible in the task definition, we do not add any reference to the Amazon ECS Exec, and therefore, the existing task definitions can be used for this feature.

{
  "family": "ecs-exec-demo",
  "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"
}

To register a task definition:

  1. Access the Amazon ECS console.
  2. Select Task Definitions from the navigation bar.
  3. Select Create new Task Definition option from the console.
  4. In the following wizard:
    1. Select Amazon EC2 in launch type compatibility.
    2. Use Configure via JSON option in the next screen and add the preceding JSON.
    3. Select Create option to create the task definition.

For more information, please visit the documentation on Creating a task definition.

Now we are ready to run our Amazon ECS task using Fargate launch type or EC2 launch type and use Amazon ECS Exec as we start it. Note: For now, enabling Amazon ECS Exec is only supported via AWS CLI, AWS SDK, or AWS Copilot.

For EC2 launch type-

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

For Fargate launch type-

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>

Please replace the PUBLIC_SUBNET_ID and SECURITY_GROUP_ID with the appropriate values from your VPC.

Using --enable-execute-command flag turns on the Amazon ECS Exec for the task. The same can be verified by describing the task. Internally, a managed agent named ExecuteCommandAgent is started by the ecs-agent for this task. This managed agent is responsible for the Amazon ECS Exec core functionality.

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

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

Starting an interactive session with Amazon ECS Exec

Our Amazon ECS task is now running. Let us use Amazon ECS Exec to start an interactive session with the container of the running task.

aws ecs execute-command \
--region <AWS_REGION> \
--cluster <CLUSTER_NAME> \
--task <TASK_ID> \
--container windows_container \
--interactive \
--command powershell.exe

Below, we will attach to a PowerShell session running inside our container and make a new directory.

Copyright (C) Microsoft Corporation. All rights reserved.

PS C:\> Get-ChildItem


 Directory: C:\

Mode LastWriteTime Length Name
---- ------------- ------ ----
d-r--- 10/8/2021 10:53 PM Program Files
d----- 9/13/2021 4:08 AM Program Files (x86)
d-r--- 9/13/2021 4:11 AM Users
d----- 10/8/2021 10:57 PM Windows
-a---- 5/7/2020 4:48 AM 5510 License.txt



PS C:\> New-Item -Path . -Name "demo" -ItemType "directory"


 Directory: C:\


Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 10/8/2021 11:19 PM demo


PS C:\> Get-ChildItem


 Directory: C:\


Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 10/8/2021 11:19 PM demo
d-r--- 10/8/2021 10:53 PM Program Files
d----- 9/13/2021 4:08 AM Program Files (x86)
d-r--- 9/13/2021 4:11 AM Users
d----- 10/8/2021 10:57 PM Windows
-a---- 5/7/2020 4:48 AM 5510 License.txt

Running a standalone command with Amazon ECS Exec

In addition to the interactive session, we can also run standalone commands inside the container.

aws ecs execute-command   \
--region <AWS_REGION> \
--cluster <CLUSTER_NAME> \
--task <TASK_ID> \
--container windows_container \
--interactive \
--command Get-ChildItem

This provides us with the following response:

Starting session with SessionId: ecs-execute-command-0236343166de7c108

 Directory: C:\


Mode LastWriteTime Length Name
---- ------------- ------ ----
d----- 10/8/2021 11:19 PM demo
d-r--- 10/8/2021 10:53 PM Program Files
d----- 9/13/2021 4:08 AM Program Files (x86)
d-r--- 9/13/2021 4:11 AM Users
d----- 10/8/2021 10:57 PM Windows
-a---- 5/7/2020 4:48 AM 5510 License.txt

Exiting session with sessionId:   ecs-execute-command-0236343166de7c108.

Amazon S3 and CloudWatch logs

Upon checking the CloudWatch log group that we created earlier, we can find the log streams generated for our Amazon ECS Exec sessions. The following snapshot shows the result of the standalone command that we executed earlier.Snapshot of the result of the standalone command

Similarly, we can look up the logs in the Amazon S3 bucket as well.

Exec output logs in the S3 bucket

Cleaning up the infrastructure

Before we conclude, let’s clean up the infrastructure we created for the demo. Not doing so may lead to incurring future costs. If any of the resources we created are not being used, then it’s advisable to delete them. The cleanup includes the following resources, which were created as part of the demo:

  • Stopping the task that was started
  • Terminating the EC2 instance that we started (For EC2 launch type)
  • Deleting the Amazon ECS cluster
  • Deleting the CloudWatch log group
  • Deleting the S3 bucket
  • Deleting the task IAM role
  • Deleting the task execution IAM role
  • Deleting the AWS KMS key

For more information about deleting the resources, please visit the documentation available here.

Conclusion

In this blog post, we went over the Amazon ECS Exec functionality for Windows containers running on Amazon EC2 and AWS Fargate. We performed the setup required for the Amazon ECS Exec functionality and then ran a task with Amazon ECS Exec enabled. We validated the Amazon ECS Exec functionality in an interactive session and the standalone mode.

To get started with Amazon ECS Exec for Windows tasks on Amazon EC2, AWS Fargate, or Amazon ECS Anywhere, visit our documentation available at the Amazon ECS Developer Guide.

Harsh Rawat

Harsh Rawat

Harsh is a Software Development Engineer at Amazon Web Services, working with containers and container orchestrators.