Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
155 changes: 155 additions & 0 deletions Britive Bridge/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
# Britive Bridge — Deployment Options

> **Note:** This directory targets **Britive Bridge v1.x**. The deployment
> scripts, templates, and examples here are in **BETA** — validate them in a
> non-production environment first, and expect changes between releases.

Britive Bridge is a self-hosted container that connects to the Britive platform
through the Britive Broker and brokers clientless, browser-based sessions to
your internal resources. This directory collects **ready-to-use deployment
templates** for the most common environments, so you can pick the one that
matches your infrastructure and stand Bridge up quickly.

Every option deploys the same `britive/bridge` container. They differ only in
**where** it runs and **how** traffic reaches it.

---

## How Bridge works (the short version)

- The Bridge container connects **outbound** to the Britive platform via the
Broker (MQTT). It registers using a **broker pool token**.
- It serves an HTTPS endpoint on **port 8080** (API + WebSocket + browser
session protocols). By default it presents an **auto-generated self-signed
certificate**; you can front it with a real certificate (ALB/ACM, Ingress +
cert-manager, or a mounted cert).
- It persists active session/checkout state to **`/data`**, so that path should
be backed by durable storage.
- Two environment variables are always required:
- `BRITIVE_BROKER_TENANT_SUBDOMAIN` — e.g. `acme` for `acme.britive-app.com`
- `BRITIVE_BROKER_AUTH_TOKEN` — the broker pool token

Users reach Bridge at an external URL (the `BRIDGE_URL`). That URL must be
reachable from the user's browser, which is what the load balancer / ingress in
each option provides.

---

## Before you start: one-time platform setup

Regardless of which deployment you choose, the Britive platform needs a broker
pool, a token, a Bridge resource, and an admin profile. The
[`platform-setup/`](platform-setup/) directory contains an interactive script
that creates all of these for you and prints the env vars Bridge needs.

Run it **first** — see [platform-setup/README.md](platform-setup/README.md).
You'll typically run it **twice**: once before deploying (with a placeholder
Bridge URL) and once after, to set the real URL — re-running updates the
existing resource in place.

---

## Choosing an option

| Option | Where it runs | TLS / external access | Persistence | Best for |
|--------|---------------|-----------------------|-------------|----------|
| [**Docker Compose**](docker-compose/) | Any Docker host / VM | Self-signed (8080) or mounted cert | Docker volume | Local trials, POCs, single-VM deployments |
| [**Linux VM (Docker)**](linux-vm-docker/) | A Linux server / VM | Self-signed (8080) or mounted cert | Docker volume | Standalone Linux host; on-prem or cloud VM, fully scripted |
| [**Windows VM (Docker)**](windows-vm-docker/) | A Windows server / VM (WSL 2) | Self-signed (8080) or mounted cert | Docker volume | Standalone Windows host (Linux container via WSL 2) |
| [**AWS ECS Fargate + NLB**](aws-ecs-fargate-nlb/) | AWS ECS Fargate | TLS passthrough via NLB:443 → container self-signed cert | EFS | Serverless AWS, minimal moving parts, no ACM cert needed |
| [**AWS ECS Fargate + ALB**](aws-ecs-fargate-alb/) | AWS ECS Fargate | ALB terminates TLS with an **ACM cert** on 443 | EFS | Production AWS with a real cert + custom domain |
| [**AWS ECS Fargate + ALB + SSH**](aws-ecs-fargate-alb-ssh/) | AWS ECS Fargate | Same as ALB option | EFS | ALB option **plus** broker SSH access to EC2 via a key in Secrets Manager |
| [**Kubernetes**](kubernetes/) | Any K8s cluster (EKS/AKS/GKE/on-prem) | Ingress (cert-manager / ALB) → backend HTTPS | PVC | Teams standardized on Kubernetes; Helm chart on the roadmap |

### Quick guidance

- **Just trying it out?** → Docker Compose.
- **A single Linux server (on-prem or cloud VM)?** → Linux VM (Docker) — scripted
install with per-distro handling.
- **A single Windows server?** → Windows VM (Docker) — runs the Linux image via
the WSL 2 backend (note the licensing/runtime caveats in that guide).
- **On AWS, want the simplest production path?** → ECS Fargate + ALB.
- **Don't have / don't want an ACM cert on AWS?** → ECS Fargate + NLB
(TLS passthrough to the container's self-signed cert).
- **Need the broker to SSH into EC2 instances?** → ECS Fargate + ALB + SSH.
- **Run everything on Kubernetes?** → Kubernetes manifests (Helm chart coming —
see the roadmap in that option's README).
- **Need the broker to run scripts that use extra tools** (`ssh`, `mysql`,
`aws`, `jq`, …)? → build a [custom image](custom-image/) and use it as the
image in any option above.

---

## Extending the image (custom utilities)

The broker runs your checkout/checkin scripts to mint and destroy ephemeral
credentials, and those scripts often need CLI tools not in the stock image. The
[`custom-image/`](custom-image/) directory shows how to layer them on top of
`britive/bridge` and deploy the result to **ECS or Kubernetes** unchanged — with
two worked examples (**Linux SSH** key provisioning and **Aurora MySQL**
temporary users/roles). This is orthogonal to the deployment options above: pick
a deployment, point its image at your custom build.

---

## Directory layout

```
Britive Bridge/
├── README.md # you are here
├── platform-setup/ # run FIRST — creates Britive platform objects
│ ├── quick-setup.py
│ ├── requirements.txt
│ └── README.md
├── custom-image/ # extend britive/bridge with extra utilities
│ ├── Dockerfile # base-distro & arch agnostic
│ ├── build-and-push.sh # multi-arch build → Docker Hub / ECR
│ ├── scripts/ # worked examples: Linux SSH + Aurora MySQL
│ ├── k8s-overlays/ # ready-to-apply: image + SSH key + IRSA SA
│ └── README.md
├── docker-compose/
│ ├── docker-compose.yaml
│ └── README.md
├── linux-vm-docker/ # standalone Linux VM via Docker
│ ├── install.sh
│ ├── bridge.env.example
│ └── README.md
├── windows-vm-docker/ # standalone Windows VM via Docker (WSL 2)
│ ├── install.ps1
│ ├── bridge.env.example
│ └── README.md
├── aws-ecs-fargate-nlb/
│ ├── ecs-fargate-nlb.yaml
│ ├── params.example.json
│ └── README.md
├── aws-ecs-fargate-alb/
│ ├── ecs-fargate-alb.yaml
│ ├── params.example.json
│ └── README.md
├── aws-ecs-fargate-alb-ssh/
│ ├── ecs-fargate-alb-ssh.yaml
│ ├── params.example.json
│ └── README.md
└── kubernetes/
├── manifests/
│ ├── namespace.yaml
│ ├── secret.example.yaml
│ ├── pvc.yaml
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── ingress.yaml
│ ├── external-secret.example.yaml # optional: External Secrets Operator
│ ├── pvc-rwm.example.yaml # optional HA: RWX PVC (instead of pvc.yaml)
│ └── ha-deployment-patch.example.yaml # optional HA: replicas + rolling update
└── README.md
```

---

## A note on placeholders

All templates use **placeholder values** (`<your-tenant-subdomain>`,
`vpc-EXAMPLE...`, `arn:aws:acm:<region>:<account-id>:...`, `bridge.example.com`,
etc.). Replace them with your real values before deploying. **Never commit real
tokens, private keys, account IDs, or certificate ARNs** to source control —
use the parameter files locally or, better, a secret store.
121 changes: 121 additions & 0 deletions Britive Bridge/aws-ecs-fargate-alb-ssh/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
# Britive Bridge — AWS ECS Fargate + ALB + SSH key

Everything in the [ALB option](../aws-ecs-fargate-alb/), **plus** an SSH private
key delivered to the broker so it can SSH into your EC2 instances. The key is
stored in **AWS Secrets Manager** and injected into the container at runtime —
it is **never baked into the image**.

Use this when Bridge brokers SSH sessions to EC2 hosts and the broker needs a
private key to authenticate.

## What it adds over the ALB option

CloudFormation template `ecs-fargate-alb-ssh.yaml` adds:

- A **Secrets Manager secret** holding the PEM-encoded private key (alongside
the broker auth token secret that all variants create)
- Execution-role permission to **read those secrets** at task start
- A container `Secrets` mapping that injects the key as `SSH_PRIVATE_KEY`
- A container entrypoint that writes the key to `/home/bridge/.ssh/id_ed25519`
(mode `600`) before starting Bridge
- Task-role permissions for **ECS Exec** (SSM) and CloudWatch Logs

Everything else (ALB + ACM TLS, EFS, security groups) matches the ALB option.

## Prerequisites

- All prerequisites from the [ALB option](../aws-ecs-fargate-alb/)
- An **SSH key pair** whose **public** key is installed on the target EC2
instances (in the relevant user's `authorized_keys`). You provide the
**private** key to this stack.

## Configure

```bash
cp params.example.json params.json
```

Same parameters as the ALB option, **plus**:

| Parameter | Notes |
|-----------|-------|
| `BrokerSSHPrivateKey` | PEM-encoded private key (ed25519 or RSA). **Highly sensitive.** |

### Filling in the private key safely

Avoid pasting the key into a file by hand — JSON requires the newlines to be
escaped, and doing that manually corrupts the key. Let `jq` do the escaping:

```bash
jq --arg key "$(cat ~/.ssh/bridge_ed25519)" \
'map(if .ParameterKey == "BrokerSSHPrivateKey" then .ParameterValue = $key else . end)' \
params.example.json > params.json
# fill in the remaining placeholder values, then delete params.json after deploy
```

Do **not** pre-escape the key (e.g. with `awk`/`sed`) before passing it to
`jq` — it gets escaped twice and the container receives literal `\n` text
instead of newlines, breaking SSH authentication.

> **Never commit `params.json`** with a real key. Delete it locally once the
> stack is up — the key lives in Secrets Manager from then on. To rotate, update
> the secret value (or redeploy with a new key) and restart the service.

## Deploy

```bash
aws cloudformation deploy \
--stack-name britive-bridge \
--template-file ecs-fargate-alb-ssh.yaml \
--parameter-overrides file://params.json \
--capabilities CAPABILITY_NAMED_IAM
```

## After deploy

Same as the ALB option (DNS record → `LoadBalancerDnsName`, set `BRIDGE_URL`,
verify `/api/health`). Additional output:

- `BrokerSSHKeySecretArn` — the Secrets Manager ARN holding the broker key.

Confirm the broker can reach a target host by checking out an SSH session
through Bridge, or inspect the running task with ECS Exec:

```bash
# find the task ID first:
aws ecs list-tasks --cluster <ClusterName> --service-name <ServiceName>

aws ecs execute-command --cluster <ClusterName> --task <task-id> \
--container bridge --interactive --command "/bin/sh"
# inside: ls -l /home/bridge/.ssh/id_ed25519 (should be mode 600)
```

## Security notes

- The private key is marked `NoEcho` in CloudFormation and stored only in
Secrets Manager; it is not written to CloudWatch.
- Scope the target instances' `authorized_keys` to the minimum needed; prefer a
dedicated, low-privilege broker user.
- Rotate the key periodically by updating the secret and restarting the service:

```bash
aws secretsmanager put-secret-value \
--secret-id britive-bridge/broker/ssh-private-key \
--secret-string "$(cat ~/.ssh/new_bridge_ed25519)"
aws ecs update-service --cluster <ClusterName> --service <ServiceName> \
--force-new-deployment
```

## Teardown

```bash
aws cloudformation delete-stack --stack-name britive-bridge
```

> The Secrets Manager secrets are retained with a recovery window after stack
> deletion. To redeploy the same stack name immediately, force-delete them first:
>
> ```bash
> aws secretsmanager delete-secret --secret-id britive-bridge/broker/ssh-private-key --force-delete-without-recovery
> aws secretsmanager delete-secret --secret-id britive-bridge/broker/auth-token --force-delete-without-recovery
> ```
Loading