Skip to content

feat(tenant): one SSH port for all tenants through sshpiper (#80) - #81

Merged
entelecheia merged 3 commits into
mainfrom
feat/tenant-sshpiper
Oct 20, 2026
Merged

entelecheia merged 3 commits into
mainfrom
feat/tenant-sshpiper

Conversation

@entelecheia

Copy link
Copy Markdown
Member

Implements #80.

What it adds

  • modules.tenant.sshpiper (enabled, port default 2222, address, version default v1.6.1): download into /usr/local/lib/rootfiles/sshpiper/<version>, SHA-256 checked against values pinned in the code, rootfiles-sshpiper.service running yaml -- failtoban, host-only upstream key, refusal when another process holds the port, removal when disabled
  • Routes /etc/rootfiles/sshpiper/tenants/<t>.yaml (0600): per user a key pipe (sshpiper checks the synced authorized_keys, then logs in with the upstream key) and a password pipe without any key (the tenant's sshd checks the password and enforces the expired-password change); upstream host keys verified via known_hosts built from the stored tenant keys
  • Boot contract: with piper.pub, init.sh trusts the upstream key through AuthorizedKeysFile
  • tenant sync: every 2 minutes, root-only, no global lock (an apply can no longer make the timer fail); syncs hashes, keys and routes
  • Bounded container reads (timeout + head -c) for shadow, passwd, group and authorized_keys, so a tenant-controlled file cannot stall a sync or import
  • tenant status / create print the routed command

Verification

  • Unit: key cleaning, route file shape (password pipe never carries a key, mode 0600), known_hosts, tampered archive rejected, unpinned version refused, unit file
  • tenant-scenario (real Docker + systemd + sshpiper): routed password login, wrong password / unknown route / other tenant's user refused, temporary password change forced through the shared port, key added inside the container logs in after sync and an unlisted key is refused, disabling removes service and routes

Closes #80

🤖 Generated with Claude Code

https://claude.ai/code/session_0177Zk7to4EYohgM59v4Fcj7

modules.tenant.sshpiper installs a pinned, SHA-256-checked sshpiperd with
the yaml and failtoban plugins as rootfiles-sshpiper.service. Each tenant
user gets the route <tenant>.<user>: a key pipe checked against the
user's authorized_keys synced from the container, then logged in with a
host-only upstream key, and a password pipe passed to the tenant's sshd.
Upstream host keys are verified from the stored tenant keys.

tenant sync now runs every 2 minutes without the global lock, refreshes
keys and routes, and container reads are bounded in size and time.

Closes #80

Claude-Session: https://claude.ai/code/session_0177Zk7to4EYohgM59v4Fcj7
Copilot AI balanced review requested due to automatic review settings October 20, 2026 01:44

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Oct 20, 2026 •

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review ✅ Completed 2026-10-20T01:49:39.968125Z ebfbb82 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ebfbb82640

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread internal/module/tenant_piper.go
Comment thread internal/module/tenant_piper.go Outdated
@entelecheia
entelecheia merged commit 3eb2177 into main Oct 20, 2026
55 checks passed
@entelecheia
entelecheia deleted the feat/tenant-sshpiper branch October 20, 2026 02:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat(tenant): one SSH port for all tenants through sshpiper

2 participants