# Gateway on AWS ECS

<figure><img src="https://762006384-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MJXOXEifAmpyvNVL1to%2Fuploads%2FETnLSTu5qYNj0xwMltI2%2FKeeperPAM%20Machine.jpg?alt=media&#x26;token=7f69333a-8f02-410f-8542-1882216994b6" alt=""><figcaption></figcaption></figure>

## Overview <a href="#overview" id="overview"></a>

This document contains information on how to install, configure, and update your Keeper Gateway on an AWS ECS. The Keeper Gateway container is built upon the base image of Rocky Linux 9 and it is hosted in [DockerHub](https://hub.docker.com/r/keeper/gateway).

## Prerequisites

* VPC: A VPC with at least one Private Subnet
* Internet Access: The ECS host must have an outbound route to Keeper's endpoints via an Internet Gateway (IGW) or NAT Gateway. See the [Gateway Network Configuration](https://docs.keeper.io/en/keeperpam/privileged-access-manager/references/gateway-network-configuration) page.
* Instance Type: You must use an EC2 instance type with at least 8GB of RAM available. See [sizing](https://docs.keeper.io/en/keeperpam/privileged-access-manager/getting-started/..#system-requirements) recommendations.
* Gateway scaling set to maximum instances: See below and [Scaling and High Availability](#scaling-and-high-availability).

***

## Create a Gateway <a href="#create-a-gateway" id="create-a-gateway"></a>

A new Gateway deployment can be created by clicking on **Create New** > **Gateway** from the Web Vault or Desktop App.

You can also create a Gateway and configuration file from the Commander CLI:

```
pam gateway new -n "<Gateway Name>" -a <Application Name or UID> -c b64
```

The Application names and UIDs can be found with `secrets-manager app list`

Download the Docker-compose YAML and save the Base64 configuration token.

***

## AWS Infrastructure Setup

**Outbound Rules:** HTTPS (443): Destination `0.0.0.0/0`

<figure><img src="https://762006384-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MJXOXEifAmpyvNVL1to%2Fuploads%2FlYgJcCcqswXNgRUjXJUW%2FSecuirty%20Group.png?alt=media&#x26;token=991c2a05-50e6-4803-9a53-e05ea7ffc0f5" alt=""><figcaption></figcaption></figure>

### Creating the Gateway Configuration Secret

Navigate to the **AWS Secrets Manager console**.

**Choose "Store a new secret"**: Click the button to start the creation process.

**Select Secret Type**:

* Choose "**Other type of secret**".

**Enter the Secret Value**:

* Switch to the "Plaintext" tab.
* Delete any existing curly braces `{}` and paste your Base64 Configuration Token.

**Encryption Key**: Leave this as `aws/secretsmanager`

**Click Next**

<figure><img src="https://762006384-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MJXOXEifAmpyvNVL1to%2Fuploads%2FMOiV9ZPudHmFc2lbxMmO%2FSecrets.png?alt=media&#x26;token=0e20cf7c-b2e3-4f32-9f28-97ee8f97e22a" alt=""><figcaption></figcaption></figure>

**Configure Secret Metadata**:

* **Secret name**: Enter a descriptive name, such as `keeper/gateway-config`.

**Store the Secret:** Skip the optional rotation settings and click Store.

**Copy the Secret ARN**: Once saved, click on your new secret and copy the Secret ARN, we will require this later

* *Example Format:* `arn:aws:secretsmanager:us-east-1:012345678901:secret:keeper/gateway-config-abc123`

### Create IAM Roles

#### ECS Instance Role

This role allows the EC2 instance to talk to the ECS cluster and enables AWS Systems Manager (SSM) for remote troubleshooting.

* Navigate to **IAM > Roles > Create role**.
* **Select trusted entity**: AWS Service.
* **Service or use case**: EC2.
* **Add permissions** (Attach these 2 Managed Policies):
  * `AmazonEC2ContainerServiceforEC2Role`
  * `AmazonSSMManagedInstanceCore`
* **Role name**: `[INSTANCE_ROLE_NAME]` (e.g., `ecsInstanceRole`).
* **Create role**.

<figure><img src="https://762006384-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MJXOXEifAmpyvNVL1to%2Fuploads%2F6WQ7kqyFJ8ExRfNHJZSI%2FECS%20Instance%20Role.png?alt=media&#x26;token=62f63132-d14e-4720-9b4d-c91181f9ead0" alt=""><figcaption></figcaption></figure>

#### Task Execution Role

This role is used by the ECS Agent to pull the image and decrypt the secret before the app starts

* Navigate to **IAM > Roles** and click Create role.
* **Trusted entity type**: Select **AWS service**.
* **Service or use case**: Select Elastic Container Service.
* **Use Case**: Search for and check:
  * `AmazonECSTaskExecutionRolePolicy`
* Click Next.
* Role name: e.g `ecsgateway-execution-role`.
* Click Create role.
* Add the Inline Policy for Secrets:
  * Find and click on your new `ecsgateway-execution-role`.
  * Click Add permissions > Create inline policy.
  * Switch to the JSON tab and paste the following (replacing `YOUR_SECRET_ARN` with the ARN that you copied earlier):

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "secretsmanager:GetSecretValue",
            "Resource": "YOUR_SECRET_ARN"
        }
    ]
}
```

* Click Review policy, name it `KeeperSecretAccess`, and click Create policy.

#### Task Role

This role is used by the application while it's running to manage your AWS resources.

* Navigate to **IAM > Roles** and click **Create role**.
* **Trusted entity type**: Select **AWS service**.
* **Service or use case:** Select **Elastic Container Service**, then **Elastic Container Service Task**. Click Next.
* **Add permissions**: Click **Next** (we will add a custom policy instead).
* **Role name**: e.g `ecsgateway-task-role`. Click **Create role**.
* **Add the Inline Policy for Resource Management**:
  * Click on the new `ecsgateway-task-role`.
  * Click **Add permissions > Create inline policy**.
  * Switch to the JSON tab and paste the following:

```
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ec2:DescribeInstances",
                "iam:UpdateLoginProfile"
            ],
            "Resource": "*"
        }
    ]
}
```

***

## **Create the ECS Cluster**

Navigate to **ECS > Clusters > Create cluster.**

**Cluster name**: `[CLUSTER_NAME]`.

Select **Fargate and Self-managed instances**

**Provisioning method:** On demand

**Container instance Amazon Machine Image (AMI)**: Amazon Linux 2023

**Instance type**: `t3.large`.

**EC2 instance role:** Select the ECS instance role you previously created

**Desired Capacity:** Set minimum 1 and desired maximum

**Network settings**: Select your VPC, Subnet and Security Group

**Create:** Click Create

<figure><img src="https://762006384-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MJXOXEifAmpyvNVL1to%2Fuploads%2FYzdkiCFCys2mfssT3cAg%2FECS%20cluster.png?alt=media&#x26;token=ed1393a5-3c44-451b-bcf1-62596f403119" alt=""><figcaption></figcaption></figure>

***

## Creating the Task Definition

* **Open the ECS Console**: Navigate to **Amazon Elastic Container Service** > Task Definitions.
* **Start Creation**: Click Create new task definition and select Create new task definition with JSON

<figure><img src="https://762006384-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MJXOXEifAmpyvNVL1to%2Fuploads%2FPoW3qxbd8y9iqqCYcN27%2Ftask%20definition.png?alt=media&#x26;token=09044ca0-c612-49b8-8a1a-bcaf1031641e" alt=""><figcaption></figcaption></figure>

* **Paste & Edit**: Paste the following template. Ensure sizing of CPU and memory meets your needs.

```
{
  "family": "[TASK_FAMILY_NAME]",
  "taskRoleArn": "arn:aws:iam::[ACCOUNT_ID]:role/ecsgateway-task-role",
  "executionRoleArn": "arn:aws:iam::[ACCOUNT_ID]:role/ecsgateway-execution-role",
  "networkMode": "bridge",
  "containerDefinitions": [
    {
      "name": "keeper-gateway",
      "image": "keeper/gateway:latest",
      "cpu": 2048,
      "memory": 8192,
      "essential": true,
      "privileged": true,
      "linuxParameters": {
        "sharedMemorySize": 2048
      },
      "environment": [
        { "name": "ACCEPT_EULA", "value": "Y" }
      ],
      "secrets": [
        {
          "name": "GATEWAY_CONFIG",
          "valueFrom": "arn:aws:secretsmanager:[REGION]:[ACCOUNT_ID]:secret:[SECRET_NAME]"
        }
      ],
      "logConfiguration": {
        "logDriver": "awslogs",
        "options": {
          "awslogs-group": "/ecs/[TASK_FAMILY_NAME]",
          "awslogs-create-group": "true",
          "awslogs-region": "[REGION]",
          "awslogs-stream-prefix": "ecs"
        }
      }
    }
  ],
  "requiresCompatibilities": [
    "EC2"
  ]
}
```

#### Parameters

`[TASK_FAMILY_NAME]:` Give a name for the task.

`ACCOUNT_ID`: Found in the top right hand corner.

Update the sizing to your required Gateway size.

`privileged: true`: Required for Remote Browser Isolation (RBI). Chromium needs elevated permissions to manage the "sandboxed" browser namespaces.

`sharedMemorySize: 2048`: Docker only gives 64MB of shared memory; modern web pages require at least 2GB to render without crashing.

`secrets` block: This maps the GATEWAY\_CONFIG environment variable to your AWS Secrets Manager ARN. The ECS agent handles the decryption automatically at runtime.

`network` Use `bridge` Mode to allow the container to share the host's networking stack for internal VPC discovery, but if your instances are in a private subnet, ensure your VPC Route Table directs outbound traffic to a NAT Gateway for secure internet connectivity to the Keeper Cloud and use `awsvpc` in the JSON.

***

## Deploy & Verify

#### Create the ECS Service

The **Service** ensures that your Task Definition stays running.

* **Open the ECS Console**: Go to **Clusters** and select your cluster (e.g., `Keeper-Cluster`).
* **Create Service**: Under the **Services** tab, click **Create**.
* **Environment Configuration**:
  * **Compute options**: Select **Launch type**.
  * **Launch type**: Select **EC2**.

<figure><img src="https://762006384-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2F-MJXOXEifAmpyvNVL1to%2Fuploads%2F0Rv8tTn5kC361c8TnF9K%2FService.png?alt=media&#x26;token=77be5528-168b-4e1d-8036-4f0c2f5be427" alt=""><figcaption></figcaption></figure>

* **Deployment Configuration**:
  * **Family**: Select the `ecsgatewaytask` you created.
  * **Revision**: Select the latest revision.
  * **Service** **name**: `keeper-gateway-service`.
  * **Desired tasks**: Set to `1`.
* **Networking**:
  * **Security Group**:
    * If `Bridge` Mode: Networking settings are inherited from the EC2 host. Skip SG selection in this wizard.
    * If `awsvpc` Mode: Select your VPC, Subnets, and the Gateway Security Group.
* **Review and Create**: Click Create.

***

## Scaling and High Availability

Before deploying additional containers, you must configure the Gateway for scaling and high availability. Match this to your maximum defined instances in your Cluster configuration.

After logging into Keeper Commander, get a list of gateways from this command:

```
pam gateway list
```

Run the following command for the gateway being configured for scaling:

```
pam gateway set-max-instances -g <GATEWAY_UID> -m <MAX_INSTANCES>
```

* `<GATEWAY_UID>` is the UID of the Gateway you are scaling.
* `<MAX_INSTANCES>` is the maximum number of Gateway instances you want to allow.

**Example:** The following example allows up to 5 Gateway instances to run concurrently:

```
pam gateway set-max-instances -g Dmg5bh63p3Yj7ov738BTAw -m 5
```

For further information on gateway scaling and high availability

* [Scaling and High Availability](#scaling-and-high-availability)

***

## Network Configuration

The Keeper Gateway establishes outbound-only connections and does not require any inbound firewall rules. The following outbound connections must be allowed:

<table><thead><tr><th width="310.1015625">Destination Endpoint</th><th>Ports Needed</th><th>More Info</th></tr></thead><tbody><tr><td><p><strong>Keeper Cloud</strong><br><code>keepersecurity.[x]</code></p><p>Endpoints:</p><p>US: <code>.com</code></p><p>EU: <code>.eu</code></p><p>AU: <code>.com.au</code></p><p>JP: <code>.jp</code></p><p>CA: <code>.ca</code></p><p>US_GOV: <code>.us</code></p></td><td>TLS Port 443</td><td>Communicates with Keeper Cloud to access target infrastructure via native protocols (e.g., SSH, RDP)</td></tr><tr><td><p><strong>Keeper Router</strong><br><code>connect.keepersecurity.[x]</code></p><p>Endpoints:</p><p>US: <code>.com</code></p><p>EU: <code>.eu</code></p><p>AU: <code>.com.au</code></p><p>JP: <code>.jp</code></p><p>CA: <code>.ca</code></p><p>US_GOV: <code>.us</code></p></td><td>TLS Port 443</td><td>Communicates with Keeper Router to establish secure, real-time WebSocket connections</td></tr><tr><td><p><strong>Keeper Stun/Turn Service</strong></p><p><code>krelay.keepersecurity.[x]</code></p><p>Endpoints:</p><p>US: <code>.com</code></p><p>EU: <code>.eu</code></p><p>AU: <code>.com.au</code></p><p>JP: <code>.jp</code></p><p>CA: <code>.ca</code></p><p>US_GOV: <code>.us</code></p></td><td>TCP and UDP opened on Port 3478<br><br>Outbound access to TCP and UDP ports 49152 through 65535<br></td><td>Facilitates secure and encrypted WebRTC connections between end-user's vault and target systems via the Gateway</td></tr></tbody></table>

The Gateway preserves zero knowledge by performing all encryption and decryption of data locally. Keeper Secrets Manager APIs are used to communicate with the Keeper cloud.
