Skip to content

feat: add remote agent auth tunneling via SSH agent protocol extensions#29

Open
brianm wants to merge 3 commits intomainfrom
multihop
Open

feat: add remote agent auth tunneling via SSH agent protocol extensions#29
brianm wants to merge 3 commits intomainfrom
multihop

Conversation

@brianm
Copy link
Copy Markdown
Collaborator

@brianm brianm commented Apr 18, 2026

Implement proxying of auth requests back through SSH agent forwarding, enabling users to SSH to a remote host and run epithet agent fish to get certificates from an internal CA while auth plugins (FIDO2, browser) run on the local machine.

Uses SSH agent protocol extensions (message type 27) with a registry pattern for extensibility:

Key components:

  • ProxyAgent: generic ExtendedAgent wrapper with extension handler registry
  • ProxyListener: per-connection upstream dialing for agent protocol proxying
  • Upstream client: ProbeUpstream() and RequestAuth() functions
  • Broker: WithUpstream option and Authenticate() helper (try upstream, fall back to local)
  • CLI: epithet agent <shell> wrapper mode mirroring ssh-agent's pattern

Multi-hop chaining works naturally — each layer proxies to its upstream. No changes to CA or policy server required.

Implement proxying of auth requests back through SSH agent forwarding,
enabling users to SSH to a remote host and run `epithet agent fish` to
get certificates from an internal CA while auth plugins (FIDO2, browser)
run on the local machine.

Uses SSH agent protocol extensions (message type 27) with a registry
pattern for extensibility:
- [email protected] — probe if socket is an epithet agent
- [email protected] — request auth token from upstream

Key components:
- ProxyAgent: generic ExtendedAgent wrapper with extension handler registry
- ProxyListener: per-connection upstream dialing for agent protocol proxying
- Upstream client: ProbeUpstream() and RequestAuth() functions
- Broker: WithUpstream option and Authenticate() helper (try upstream, fall back to local)
- CLI: `epithet agent <shell>` wrapper mode mirroring ssh-agent's pattern

Multi-hop chaining works naturally — each layer proxies to its upstream.
No changes to CA or policy server required.
@brianm brianm self-assigned this Apr 18, 2026
brianm added 2 commits April 18, 2026 16:11
- Add Ready() channel to ProxyListener with guaranteed close on all
  return paths, preventing caller hangs on listener startup failure
- Use per-process temp dirs in wrapper mode to avoid collisions between
  multiple wrapped shells against the same CA
- Only fall back to local auth on UpstreamUnavailableError; propagate
  genuine upstream auth failures (user cancelled, plugin error)
- Use errors.Is for ErrExtensionUnsupported sentinel comparison
- Fix test data races with atomic.Bool/Int32 for shared counters
- Document token forwarding trust model in extensions.go
- Drain brokerErr channel after shell exit in wrapper mode
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.

1 participant