79 lines
3.7 KiB
Markdown
79 lines
3.7 KiB
Markdown
|
|
# OSM taxiway bastion (broker mode)
|
||
|
|
|
||
|
|
A **self-contained, whitelisted** SSH box for an OSM taxiway export pipeline. It lets a
|
||
|
|
backend fetch/generate airport ground-layout GeoJSON without handing it a shell or root:
|
||
|
|
the bastion only ever runs **three** commands, validated whole-line against a regex
|
||
|
|
allowlist and exec'd **shell-free** (no `sh -c`, so nothing an ICAO argument contains can
|
||
|
|
become a shell operator or a path).
|
||
|
|
|
||
|
|
```
|
||
|
|
ssh agent@<osm-host>
|
||
|
|
└─ bastion-broker (key auth; matches request vs allowed-commands.list)
|
||
|
|
├─ taxiways-list → ls *-taxiways.geojson in /osm-maps
|
||
|
|
├─ taxiways-export <ICAO> → export-icao-geojson.sh <ICAO> (osmium/ogr2ogr/jq)
|
||
|
|
└─ taxiways-cat <ICAO> → base64 <ICAO>-taxiways.geojson (ssh-safe tunnel)
|
||
|
|
```
|
||
|
|
|
||
|
|
The OSM toolchain (`osmium`, `ogr2ogr`, `jq`) is baked into the image (see `Dockerfile`),
|
||
|
|
so the export runs **inside** this container against the mounted `osm-maps` directory
|
||
|
|
(which holds a region PBF + `export-icao-geojson.sh`). No docker socket, no second
|
||
|
|
container — the only host data reachable is that one directory.
|
||
|
|
|
||
|
|
## Files
|
||
|
|
|
||
|
|
| file | purpose |
|
||
|
|
|------|---------|
|
||
|
|
| `Dockerfile` | Debian base (Alpine has no `osmium-tool`) + `osmium-tool`/`gdal-bin`/`jq` + openssh + the wrappers |
|
||
|
|
| `bastion-broker` | the allowlist gate, verbatim from `docker-bastion/scripts` (whole-line ERE match → shell-free exec) |
|
||
|
|
| `entrypoint` | broker-only sshd: key-only, single non-root user, every session forced through the broker |
|
||
|
|
| `bin/taxiways-{list,export,cat}` | the only executables the allowlist lets a client run |
|
||
|
|
| `allowed-commands.list` | the regex allowlist (`taxiways-export [A-Z]{4}`, …) — the security boundary |
|
||
|
|
| `docker-compose.yml` | broker-mode service, osm-maps + allowlist + keys mounts, port 6770 |
|
||
|
|
|
||
|
|
> This flavor is **Debian standalone** (not `FROM blaxsoftware/bastion`) because the export needs
|
||
|
|
> `osmium`, which Alpine doesn't package. It reuses the base repo's `bastion-broker` unchanged; only
|
||
|
|
> the sshd bootstrap is a compact broker-only `entrypoint` instead of the Alpine `start-container`.
|
||
|
|
|
||
|
|
## Deploy (on the host holding your osm-maps dir)
|
||
|
|
|
||
|
|
```bash
|
||
|
|
# 1) Authorize the backend's agent key
|
||
|
|
mkdir -p docker-data/bastion/users.d
|
||
|
|
cp /path/to/agent.pub docker-data/bastion/users.d/backend.pub
|
||
|
|
|
||
|
|
# 2) Let the bastion's `agent` user write into osm-maps (export writes files + work/)
|
||
|
|
AGENT_UID=$(docker run --rm blaxsoftware/bastion:latest id -u agent)
|
||
|
|
chown -R "$AGENT_UID" /srv/osm-maps # point at your actual osm-maps dir
|
||
|
|
|
||
|
|
# 3) Confirm the osm-maps dir has the script + PBF
|
||
|
|
ls /srv/osm-maps/export-icao-geojson.sh /srv/osm-maps/*.osm.pbf
|
||
|
|
|
||
|
|
# 4) Build + run
|
||
|
|
docker compose up -d --build
|
||
|
|
```
|
||
|
|
|
||
|
|
To publish the image for reuse:
|
||
|
|
|
||
|
|
```bash
|
||
|
|
docker build --platform linux/amd64 -t blaxsoftware/bastion-osm-taxiways:latest .
|
||
|
|
docker push blaxsoftware/bastion-osm-taxiways:latest
|
||
|
|
```
|
||
|
|
|
||
|
|
## Test
|
||
|
|
|
||
|
|
```bash
|
||
|
|
ssh -p 6770 agent@<osm-host> taxiways-list # → list (maybe empty)
|
||
|
|
ssh -p 6770 agent@<osm-host> taxiways-export EDDF # → runs the export (minutes)
|
||
|
|
ssh -p 6770 agent@<osm-host> taxiways-cat EDDF | base64 -d | head # → GeoJSON
|
||
|
|
ssh -p 6770 agent@<osm-host> 'rm -rf /' # → "command not permitted", exit 126
|
||
|
|
ssh -p 6770 agent@<osm-host> taxiways-export eddf # → refused (lowercase ≠ [A-Z]{4})
|
||
|
|
```
|
||
|
|
|
||
|
|
## Backend wiring
|
||
|
|
|
||
|
|
The backend stores the private key whose `*.pub` you dropped in `users.d/`, and connects
|
||
|
|
as `agent@<osm-host>:6770`, sending one of the three commands per connection. `taxiways-cat`
|
||
|
|
returns base64 that the backend decodes into its own storage; `taxiways-export` runs the
|
||
|
|
(minutes-long) OSM export. A pure-PHP SSH client (e.g. phpseclib) works fine — no `ssh`
|
||
|
|
binary is required on the backend side.
|