Commit Graph

3 Commits

Author SHA1 Message Date
Fabian @ Blax Software 8eb57e5a77 feat(broker): allowlist-gated command broker mode
Add a second operating mode alongside FORCE_COMMAND: the client supplies
the command and it runs only if it matches a regex allowlist
(ALLOWED_COMMANDS / mounted allowed-commands.list), optionally behind a
trusted COMMAND_PREFIX. Matching is whole-line anchored (grep -Eqx) and
multi-line requests are rejected; execution is shell-free word-split, so
; | & $() are literal args and a sloppy rule can't become injection.

Works over SSH (SSH_ORIGINAL_COMMAND) and HTTP (X-Bastion-Command).
FORCE_COMMAND mode is unchanged and remains the default when no allowlist
is set; config is read from boot-written files since sshd does not pass
the daemon env to a ForceCommand session.

- scripts/bastion-broker: the allowlist gate + no-shell exec
- scripts/start-container: mode detection, broker wrapper + CGI, banner
- Dockerfile / config/sshd_config: wire in the broker, document env vars
- examples/docker-mailserver: ready-to-run broker config + allowlist
2026-06-02 19:32:57 +02:00
Fabian @ Blax Software 0262f677c1 A users.d/ drop-in directory for live-read authorized keys
sshd now consults /etc/bastion/users.d/*.pub on every authentication
attempt via AuthorizedKeysCommand, so adding or removing a user
takes effect immediately without restarting the container — just
drop `alice.pub` (or any *.pub file) into the host-bound dir,
sshd picks it up on the next login.

Implementation:
- /usr/local/bin/bastion-list-keys: minimal POSIX-sh script that
  cats $AUTHORIZED_KEYS_DIR/*.pub. Runs as the agent user (per
  AuthorizedKeysCommandUser), reads world-readable pubkeys.
- sshd_config: AuthorizedKeysCommand alongside the existing
  AuthorizedKeysFile — both checked, so the boot-merged
  file (AUTHORIZED_KEYS_HOST/_REPO) still works for single-file UX.
- start-container: 'zero key sources' is now a WARN, not a fatal.
  Bastion comes up empty; SSH attempts fail with 'publickey denied'
  until you drop a key. Lets users `docker compose up` first and
  add keys later.

Bug fix on the way through: `grep -c` exits non-zero when no
lines match, which under `set -eu` killed the boot script
silently after '[2/5] Authorized keys...'. Switched to
`awk … | wc -l` which exits 0 cleanly on empty input.

README updated with the new source priority and env var.
2026-05-28 12:31:51 +02:00
Fabian @ Blax Software 86b8966130 A initial docker-bastion image
Minimal SSH bastion (alpine + openssh-server + docker-cli) that
authenticates by key and runs exactly one preconfigured command
(FORCE_COMMAND) per session. authorized_keys can be merged from
both a host-mounted source and a repo-mounted source. Host keys
persist via /etc/ssh/keys volume; docker socket group membership
is aligned at boot.
2026-05-28 10:50:06 +02:00