# AWS ECS Express Activation Guide

Canonical page: https://www.kuudo.com/docs/cloud/aws-ecs-express-activation-guide/


This guide explains how to prepare AWS so the in-app **environment wizard** (Choose Deployment Pattern → Credentials → Configuration → Review & create) can create infrastructure for the **ECS Express** deployment pattern successfully.

**Core idea:** prepare AWS first (usually with the AWS CLI), then paste the access key, secret, and region into the product. The app validates credentials via STS at create time, then provisioning creates a small CloudFormation stack (ECR repository + IAM roles) that ECS Express uses on subsequent deploys.

> **About ECS Express**
> ECS Express is the lightweight ECS deployment pattern (replacing App Runner). The platform creates only an ECR repository plus two IAM roles up front; ECS Express manages the load balancer, security group, target group, and auto-scaling for each service at deploy time. No VPC, ALB, or cluster pre-provisioning is required.

---

## Quick path

1. Sign in with an AWS user that has IAM admin rights and select the correct account ([§ Sign in and select the account](#sign-in-and-select-the-account)).
2. Pick a region where ECS Express is supported and you want to deploy ([§ Region](#choose-a-region)).
3. Create or reuse a dedicated IAM user for the access-key flow and attach a policy with the required permissions ([§ IAM user](#create-or-reuse-an-iam-user)).
4. Create an access key for that user and save the **Access Key ID** and **Secret Access Key** ([§ Access key](#create-an-access-key)).
5. Verify the credentials can call STS and CloudFormation in your region ([§ Verify the credentials](#verify-the-credentials)).
6. Open the wizard: **Choose Deployment Pattern** → **Credentials** → **Configuration** → **Review & create** ([§ Complete the wizard](#complete-the-wizard-in-the-app)).
7. If something fails, use [§ Common issues](#common-issues).

---

## Prerequisites

- Access to the target AWS account.
- Permission to create IAM users / policies (for example **AdministratorAccess**, or an equivalent IAM admin).
- The **ECS Express** deployment pattern selected when creating the environment in the wizard (the `aws-ecs` pattern uses a different, larger CloudFormation stack).
- [AWS CLI v2](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html) installed locally, or [CloudShell](https://docs.aws.amazon.com/cloudshell/latest/userguide/welcome.html) from the AWS console.

The CLI is recommended because console labels and layout change more often than command-line flows.

---

## Field reference

The wizard matches AWS outputs like this:

| What you do in AWS                                     | Output to copy                 | Wizard field            |
| ------------------------------------------------------ | ------------------------------ | ----------------------- |
| IAM → Users → Security credentials → Create access key | Access key ID (e.g. `AKIA...`) | **Access Key ID**       |
| Same dialog                                            | Secret access key (shown once) | **Secret Access Key**   |
| Your choice of deploy location                         | Region code, e.g. `us-east-1`  | **Region**              |
| (your label only)                                      | Any name                       | **Environment Name**    |
| Account console / `aws sts get-caller-identity`        | 12-digit Account ID            | _(auto-derived by app)_ |

**Account ID vs other IDs:** AWS account ID is still important for verification and troubleshooting, but the current wizard derives it from credentials (STS) instead of asking you to type it.

**Region:** lowercase region code with hyphens (e.g. `us-east-1`, `eu-west-1`). List regions enabled on your account:

```bash
aws ec2 describe-regions --query "Regions[].RegionName" --output text
```

ECS Express must be available in the region you choose. If you are unsure, start with a major region like `us-east-1` or `us-west-2`.

**Access keys are long-lived:** rotate them periodically. AWS recommends temporary credentials where possible; use this IAM-user key flow only when the deployment wizard requires an access key and secret. Create a new key, update the wizard, then deactivate and delete the old one.

---

## Prepare AWS with the CLI

Run the steps below as an **AWS admin user** unless noted. Replace placeholders such as `<ACCOUNT_ID>`, `<REGION>`, and `<USER_NAME>` with your values.

### Sign in and select the account

```bash
aws configure                       # set admin profile
aws sts get-caller-identity --output json
```

From the JSON output, record:

- `Account` → **AWS Account ID**

### Choose a region

```bash
export AWS_REGION=<REGION>          # e.g. us-east-1
aws ec2 describe-regions \
  --query "Regions[?RegionName=='$AWS_REGION'].RegionName" --output text
```

A non-empty result confirms the region is enabled on your account.

### Create or reuse an IAM user

Reuse an existing IAM user if it is dedicated to this deployment workflow and already has the right permissions. Avoid root access keys. If your organization prefers IAM roles or AWS IAM Identity Center, use that path only if the deployment wizard supports temporary credentials or role assumption.

**Option A — new IAM user:**

```bash
aws iam create-user --user-name <USER_NAME>
```

**Option B — console:** **IAM** → **Users** → **Create user**.

### Attach a permissions policy

ECS Express provisioning needs to create a CloudFormation stack containing an ECR repository and two IAM roles, and to manage ECS services, log groups, and (via the ECS Express infrastructure role) elastic load balancing. The simplest path is **PowerUserAccess + IAMFullAccess** (CloudFormation needs IAM to create the execution and infrastructure roles).

```bash
aws iam attach-user-policy \
  --user-name <USER_NAME> \
  --policy-arn arn:aws:iam::aws:policy/PowerUserAccess

aws iam attach-user-policy \
  --user-name <USER_NAME> \
  --policy-arn arn:aws:iam::aws:policy/IAMFullAccess
```

For tighter least privilege, use a custom policy with at least these actions, scoped to your account/region as appropriate:

| Service / namespace                                                                                                                                            | Why                                                                                                               |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
| `cloudformation:*`                                                                                                                                             | Create / update / delete the ECS Express infrastructure stack                                                     |
| `ecr:*`                                                                                                                                                        | Manage the ECR repository created by the stack and push images during deploys                                     |
| `ecs:*`                                                                                                                                                        | Create and update ECS Express services                                                                            |
| `iam:CreateRole`, `iam:GetRole`, `iam:PassRole`, `iam:AttachRolePolicy`, `iam:PutRolePolicy`, `iam:DeleteRole`, `iam:DetachRolePolicy`, `iam:DeleteRolePolicy` | Stack creates the execution and infrastructure roles using `CAPABILITY_NAMED_IAM`; deploys `PassRole` them to ECS |
| `logs:*`                                                                                                                                                       | Create CloudWatch log groups for ECS tasks                                                                        |
| `elasticloadbalancing:*`                                                                                                                                       | Allow the ECS Express infrastructure role to attach services to managed ALBs                                      |
| `sts:GetCallerIdentity`                                                                                                                                        | Discover the AWS account ID at deploy time                                                                        |

> **Why CAPABILITY_NAMED_IAM?**
> The stack creates **named** IAM roles (e.g. `mcp-<env>-execution-role`, `mcp-<env>-infra-role`) so ECS Express can find them by name. CloudFormation requires explicit acknowledgement when a template names IAM resources, which is why the user must have `iam:*` on those role names.

Verify:

```bash
aws iam list-attached-user-policies --user-name <USER_NAME> --output table
```

### Create an access key

```bash
aws iam create-access-key --user-name <USER_NAME>
```

Record `AccessKey.AccessKeyId` (**Access Key ID**) and `AccessKey.SecretAccessKey` (**Secret Access Key**) immediately. The secret is only shown once. Treat it like a password — anyone with these two values can act as the user.

> **Rotation**
> to rotate, create a second access key, update the wizard, then `aws iam update-access-key --status Inactive` and `aws iam delete-access-key` for the old one.

### Verify the credentials

This separates AWS misconfiguration from product issues. Configure a temporary profile that uses the new key, then run a few read calls.

```bash
aws configure --profile mcp-deployer
# AWS Access Key ID:     <ACCESS_KEY_ID>
# AWS Secret Access Key: <SECRET_ACCESS_KEY>
# Default region name:   <REGION>
# Default output format: json

# 1. STS works (matches the wizard's identity check)
aws sts get-caller-identity --profile mcp-deployer

# 2. CloudFormation is reachable in the chosen region
aws cloudformation list-stacks --profile mcp-deployer --region <REGION> \
  --stack-status-filter CREATE_COMPLETE UPDATE_COMPLETE

# 3. ECR is reachable
aws ecr describe-repositories --profile mcp-deployer --region <REGION> \
  --max-items 1 || true

# 4. ECS is reachable
aws ecs list-clusters --profile mcp-deployer --region <REGION> --max-items 1
```

If `sts get-caller-identity` returns the expected account ID and the other calls return JSON (even an empty list), authentication and the most-used APIs are working.

---

## Complete the wizard in the app

Use the [Field reference](#field-reference) for definitions.

### Choose Deployment Pattern

- **Deployment Pattern** — choose **ECS Express** (not the full ECS pattern).

### Credentials

- **Environment Name** — label in your app (for example `aws-ecs-express`).
- **Access Key ID**, **Secret Access Key**, **Region** — from [§ Access key](#create-an-access-key).

### Configuration

- Optional settings page (for ECS Express, no additional required fields).

### Review & create

After submit, the platform creates a CloudFormation stack (name pattern `mcp-<environment-name>-<timestamp>`) containing:

- An **ECR repository** for your container images
- An **ECS task execution role** (ECR pull + CloudWatch logs)
- An **ECS Express infrastructure role** (manages ALB, security groups, auto-scaling)

You can watch progress in the AWS console under **CloudFormation → Stacks**.

---

## Common issues

| Symptom or error                                                                 | Likely cause                                                        | What to do                                                                                                                                                 |
| -------------------------------------------------------------------------------- | ------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `InvalidClientTokenId` / `The security token included in the request is invalid` | Wrong access key ID, deactivated key, or typo in secret             | Re-create the access key, update the wizard.                                                                                                               |
| `SignatureDoesNotMatch`                                                          | Secret access key copied with extra whitespace or partial value     | Re-paste the exact secret from `aws iam create-access-key` output.                                                                                         |
| Account ID mismatch / "Account ID does not match credentials"                    | Pasted the wrong account, or used an alias                          | Run `aws sts get-caller-identity` and copy the **12-digit `Account` field**.                                                                               |
| Environment creation fails with `AccessDenied` during credential checks          | IAM user lacks `sts:GetCallerIdentity`                              | Attach `PowerUserAccess` (or at least include STS read + required deploy actions in [§ Permissions](#attach-a-permissions-policy)).                        |
| `User: ... is not authorized to perform: iam:CreateRole`                         | IAM user is missing IAM permissions                                 | Attach `IAMFullAccess` or grant the IAM actions listed in [§ Permissions](#attach-a-permissions-policy).                                                   |
| `User ... is not authorized to perform: iam:PassRole` during deploy              | Deploy step cannot pass the execution role to ECS                   | Add `iam:PassRole` for the role ARNs created by the stack (or use `*` while developing).                                                                   |
| `Stack mcp-<id> already exists` on retry                                         | Previous provisioning partially completed                           | The platform will reuse the existing stack on retry. If it is in `ROLLBACK_COMPLETE`, delete it manually with `aws cloudformation delete-stack` and retry. |
| Region rejected or `OptInRequired`                                               | Region not enabled on the account, or ECS Express unavailable there | Enable the region in **Account → AWS Regions**, or pick a major region such as `us-east-1` / `us-west-2`.                                                  |
| Environment created, but deploy fails creating an ALB                            | ECS Express infrastructure role is missing `elasticloadbalancing:*` | Re-attach `PowerUserAccess`, or add `elasticloadbalancing:*` to your custom policy.                                                                        |
| Pasted **root account access keys**                                              | Root access keys are blocked by AWS best practice                   | Create a dedicated IAM user, attach the policies, and use that user's access keys.                                                                         |

## Official references

- [AWS IAM: Secure access keys](https://docs.aws.amazon.com/IAM/latest/UserGuide/securing_access-keys.html)
- [AWS CloudFormation: Control access with IAM](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/control-access-with-iam.html)
- [Amazon ECS infrastructure IAM role for load balancers](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/AmazonECSInfrastructureRolePolicyForLoadBalancers.html)
- [Install or update the AWS CLI](https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html)

---

## Appendix: Copy-paste activation script

The block below repeats [Prepare AWS with the CLI](#prepare-aws-with-the-cli) in one place for convenience. Replace placeholders before running.

```bash
# --- As your AWS admin ---

ACCOUNT_ID=<ACCOUNT_ID>
REGION=<REGION>           # e.g. us-east-1
USER_NAME=<USER_NAME>     # e.g. mcp-deployer

aws configure             # admin profile
aws sts get-caller-identity --output json

# Create dedicated IAM user
aws iam create-user --user-name "$USER_NAME"

# Attach permissions (broad — see guide for least-privilege alternative)
aws iam attach-user-policy \
  --user-name "$USER_NAME" \
  --policy-arn arn:aws:iam::aws:policy/PowerUserAccess

aws iam attach-user-policy \
  --user-name "$USER_NAME" \
  --policy-arn arn:aws:iam::aws:policy/IAMFullAccess

aws iam list-attached-user-policies --user-name "$USER_NAME" --output table

# Create access key (capture both fields immediately)
aws iam create-access-key --user-name "$USER_NAME"

# --- Test as the new user ---

aws configure --profile mcp-deployer    # paste the new key, secret, region

aws sts get-caller-identity --profile mcp-deployer
aws cloudformation list-stacks --profile mcp-deployer --region "$REGION" \
  --stack-status-filter CREATE_COMPLETE UPDATE_COMPLETE
aws ecr describe-repositories --profile mcp-deployer --region "$REGION" \
  --max-items 1 || true
aws ecs list-clusters --profile mcp-deployer --region "$REGION" --max-items 1
```

After this succeeds, fill the wizard using the [Field reference](#field-reference) and complete [§ Complete the wizard](#complete-the-wizard-in-the-app).

