Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save nathanpeck/6b03e647e79455a460551f8f295c7f9e to your computer and use it in GitHub Desktop.
Save nathanpeck/6b03e647e79455a460551f8f295c7f9e to your computer and use it in GitHub Desktop.

Revisions

  1. nathanpeck created this gist Jun 11, 2025.
    82 changes: 82 additions & 0 deletions secure-containerized-mcp-servers-with-aws-creds.md
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,82 @@
    ## Launch ECS Local Container Endpoints

    See [`awslabs/amazon-ecs-local-container-endpoints`](https://github.com/awslabs/amazon-ecs-local-container-endpoints/tree/mainline).

    This is an official container that mimics the Amazon ECS credential vending endpoint that is available in
    production AWS Fargate environments, and Amazon EC2 instances under Amazon ECS management. The credential vending
    endpoint is what allows an application running in AWS Fargate, under Amazon ECS management, to assume a given
    task IAM role.

    The following command utilizes `podman` but will also work with `docker`.

    ```sh
    #!/bin/bash

    # Create the credentials network with a specific subnet
    podman network create credentials_network \
    --subnet="169.254.171.0/24" \
    --gateway="169.254.171.1"

    # Run the ECS local container endpoints with the specific IP address
    podman run -d \
    --name ecs-local-endpoints \
    --network credentials_network \
    --ip 169.254.171.2 \
    -v "$HOME/.aws/:/home/.aws/" \
    -e AWS_PROFILE="default" \
    amazon/amazon-ecs-local-container-endpoints
    ```

    ## Launch your MCP server in a container in the same network

    Rather than running the MCP server directly on host, we run it in an container
    linked to the same network.

    We also pass two important environment variables that are baked into the AWS SDK,
    and therefore usable by any AWS SDK based application:

    * `ECS_CONTAINER_METADATA_URI` - Must match the defined IP address of the credential vending container
    * `AWS_CONTAINER_CREDENTIALS_RELATIVE_URI` - Two potential values for this variable
    * `/creds` - Containerized application will get the same level of access that you have on your host
    * `/task-arn/<task-arn>` - The credential vending container will use your host level credentials to assume this role
    and the container will be given credentials for this role.

    Example config for the [AWS DynamoDB MCP Server](https://awslabs.github.io/mcp/#amazon-dynamodb-mcp-server):

    ```json
    {
    "mcpServers": {
    "aws-dynamodb": {
    "command": "podman",
    "args": [
    "run",
    "--rm",
    "--interactive",
    "--network",
    "credentials_network",
    "--env",
    "FASTMCP_LOG_LEVEL=ERROR",
    "--env",
    "AWS_CONTAINER_CREDENTIALS_RELATIVE_URI=/creds",
    "--env",
    "ECS_CONTAINER_METADATA_URI=http://169.254.171.2/v3",
    "awslabs/dynamodb-mcp-server:latest"
    ]
    }
    }
    }
    ```

    ## Important caveats

    There is nothing stopping a particularly malicious container from ignoring your configured `AWS_CONTAINER_CREDENTIALS_RELATIVE_URI`
    and choosing to fetch `/creds` to get your host level AWS credentials. Therefore if you are running untrustworthy MCP
    servers you should still use best practices by limiting how much scope you give the `amazon-ecs-local-container-endpoints`,
    so that it can't give your MCP servers too much access either.

    See:

    - `amazon-ecs-local-container-endpoints` on how to use a specific AWS profile: https://github.com/awslabs/amazon-ecs-local-container-endpoints/blob/mainline/docs/configuration.md#credentials
    - AWS documentation on how to configure multiple profiles, with separate access level for each profile: https://docs.aws.amazon.com/cli/v1/userguide/cli-configure-files.html