Skip to content

feat: native SSH tunnel support + password env vars, prompting, and SSH passfile/agent flags - #36

Open
jdputsch wants to merge 2 commits into
Macmod:mainfrom
jdputsch:feature/native-ssh-tunnel
Open

feat: native SSH tunnel support + password env vars, prompting, and SSH passfile/agent flags#36
jdputsch wants to merge 2 commits into
Macmod:mainfrom
jdputsch:feature/native-ssh-tunnel

Conversation

@jdputsch

Copy link
Copy Markdown

Native SSH Tunnel Support

Motivation

godap is most useful against the LDAP servers you can't reach directly. This branch adds a built-in SSH tunnel so you can get there without leaving the tool:

  • Isolated / air-gapped networks — Your LDAP server lives in a network segment (datacenter, lab, VPN-only zone) that your workstation cannot reach directly. You can SSH into a bastion host that can reach the LDAP server, and godap will establish the tunnel automatically before connecting — no need to open a separate terminal and manually set up port forwarding.
  • Remote work / VPN-less access — When you can SSH into an environment but don't have a full VPN, an SSH tunnel lets you use godap locally as if you were sitting inside that network.
  • Security-conscious environments — Keeps LDAP traffic encrypted end-to-end inside the SSH session rather than traversing the network in plaintext.

What's new

SSH tunnel (pkg/ssh/tunnel.go)

A new self-contained sshtunnel package handles establishing the SSH connection and forwarding LDAP traffic through a local listener. It supports three auth methods (password, public key, SSH agent), known-hosts verification with a helpful error when a host key is unrecognized, and a clean shutdown path.

New CLI flags

Flag Description
--ssh-host Bastion/jump host (also enables the tunnel)
--ssh-port SSH port (default 22)
--ssh-user SSH username (defaults to $USER)
--ssh-key Path to SSH private key
--ssh-key-passphrase Passphrase for the private key
--ssh-password SSH password
--ssh-passfile Read SSH password from a file (or - to prompt)
--ssh-agent Use the SSH agent ($SSH_AUTH_SOCK)
--ssh-ignore-host-key Skip host key verification (insecure)

SSH auth method is inferred automatically from the flags provided — --ssh-auth is retained for backwards compatibility and the TUI config form but is no longer required.

Password improvements (LDAP and SSH)

  • GODAP_PASSWD environment variable sets the LDAP password (overridden by --password / --passfile)
  • GODAP_SSH_PASSWORD environment variable sets the SSH password (overridden by --ssh-password / --ssh-passfile)
  • When -u is given but no password method is specified, godap prompts interactively with hidden input
  • --passfile - and --ssh-passfile - both support reading from stdin with a visible prompt when connected to a terminal

TUI config form

The SSH tunnel section is integrated into the existing reconnect/config form — you can enable the tunnel, change the bastion host, and reconnect without restarting.

Debug logging (pkg/debug/log.go)

A lightweight debug log (enabled with --debug-log <path>) records tunnel setup, connection events, and errors for troubleshooting without cluttering the TUI.

Jeff Putsch and others added 2 commits July 17, 2026 16:24
Allows godap to transparently forward LDAP connections through an SSH
jump host without requiring manual port forwarding.

New packages:
- pkg/debug/log.go: file-based debug logger, no-op by default, activated
  via debug.Init(path). Keeps SSH lifecycle logs off the TUI screen.
- pkg/ssh/tunnel.go: SSH tunnel implementation supporting password, key,
  and agent auth. Listens on 127.0.0.1:0 and forwards to the remote LDAP
  host:port via bidirectional io.Copy. Unknown host keys are surfaced as
  HostKeyUnknownError for TUI-friendly handling.
- pkg/ssh/tunnel_test.go: unit tests covering password auth, key file
  auth, end-to-end data forwarding, Close() behavior, and bad host error.

Modified files:
- godap.go: adds CLI flags --ssh-host, --ssh-port, --ssh-user, --ssh-auth,
  --ssh-password, --ssh-key, --ssh-key-passphrase, --ssh-ignore-host-key,
  and --debug-log. A non-empty --ssh-host implicitly enables the tunnel.
- tui/main.go: integrates tunnel lifecycle into setupLDAPConn() and
  reconnectLdap(); adds showHostKeyModal() for unknown host key guidance;
  extends openConfigForm() with a third SSH tunnel panel section.
- go.mod: promotes golang.org/x/crypto from indirect to direct dependency.

Example:
  godap --ssh-host jumpbox.corp --ssh-user admin --ssh-auth key         --ssh-key ~/.ssh/id_rsa ldap.internal
…ent flags

- GODAP_PASSWD env var sets LDAP password (overridden by --password/--passfile)
- GODAP_SSH_PASSWORD env var sets SSH tunnel password (overridden by --ssh-password/--ssh-passfile)
- Interactive LDAP password prompt when -u is given but no password method is set
- New --ssh-passfile flag reads SSH password from a file or stdin (- to prompt)
- New --ssh-agent flag selects SSH agent auth; SSH auth method is now inferred
  from flags (--ssh-agent, --ssh-key, --ssh-password/--ssh-passfile) with conflict
  detection; --ssh-auth kept for backwards compat and TUI config form
- TUI SSH config form adds passfile option to SSH Auth dropdown and a password file field

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
@Macmod

Macmod commented Jul 18, 2026

Copy link
Copy Markdown
Owner

Hello @jdputsch!

This is an interesting idea, but doesn't -x work for this scenario already? Users with this sort of need can spawn a dynamic reverse SOCKS tunnel via OpenSSH in any version above 7.6 with i.e. -R 1080, along with the familiar -D option for direct SOCKS, so it's not 100% clear to me if merging this adds additional value. Is there any special use case of this implementation?

@jdputsch

jdputsch commented Jul 18, 2026 via email

Copy link
Copy Markdown
Author

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.

2 participants