feat: add SSH connection settings modal with identity key configuration#325
feat: add SSH connection settings modal with identity key configuration#325
Conversation
Greptile Summary
Important Files Changed
|
eadee40 to
6f1ff3d
Compare
Adds fine-grained control over SSH connections via a settings modal: - User/hostname/port overrides that take precedence over the quick input - Identity key configuration (none/path/paste) stored locally per-user - Automatic SSH connection invalidation when credentials change - Visual validation for incomplete user/hostname configs - Credential selection from ~/.ssh with key type detection The identity key is stored in block-local KV, not synced, allowing each user to authenticate with their own credentials for shared runbooks. 🤖 Generated with Claude Code Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
Remove dual-format handling - just use the original direct kv::get. 🤖 Generated with Claude Code Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
KV stores JSON objects directly. Get as Value and serialize to string for the runtime to parse. 🤖 Generated with Claude Code Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
d45d6e2 to
8cdeeac
Compare
format!() already returns String, so .into() was redundant. 🤖 Generated with Claude Code Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
|
@greptile |
There was a problem hiding this comment.
Greptile Overview
Greptile Summary
Adds SSH connection settings modal enabling per-block configuration of user/hostname/port and identity key authentication. Settings are split between synced (connection details) and local-only (identity keys) storage to support team collaboration with individual credentials.
Key changes:
- New
list_ssh_keysTauri command scans~/.sshfor private keys - SSH Connect block gains modal UI with three identity key modes: config/agent, key path, or paste content
- Block-local KV storage holds identity keys per-user (not synced)
- SSH connections invalidated when identity key changes via
notify_block_kv_value_changed - Identity key authentication tried first, before agent/config/defaults
DocumentSshConfigcontext item provides rich SSH configuration to runtime
Issues found:
- Binary key file handling may fail in
detect_key_type(reads as UTF-8 string) - Shell escaping incomplete in
exec_and_capture(missing newline/backslash handling) - Validation edge case: empty user/hostname props might pass when they shouldn't
Important Files Changed
File Analysis
| Filename | Score | Overview |
|---|---|---|
| backend/src/commands/ssh.rs | 3/5 | new list_ssh_keys command with key type detection; has potential issue with binary key file handling |
| crates/atuin-desktop-runtime/src/blocks/ssh_connect.rs | 3/5 | adds user/hostname/port overrides and identity key config; validation logic has edge case with empty props |
| crates/atuin-desktop-runtime/src/ssh/session.rs | 3/5 | adds open_with_config, authenticate_with_config, and key_auth_from_content for block-level SSH overrides; shell escaping incomplete |
| crates/atuin-desktop-runtime/src/ssh/ssh_pool.rs | 4/5 | adds disconnect_by_host for invalidating connections and config override support throughout pool operations |
| src/components/runbooks/editor/blocks/ssh/SshConnect.tsx | 4/5 | comprehensive settings modal UI with identity key modes (none/path/paste) and connection overrides; minor optimization opportunity |
| fn detect_key_type(path: &PathBuf) -> Option<String> { | ||
| let content = fs::read_to_string(path).ok()?; | ||
| let first_line = content.lines().next()?; |
There was a problem hiding this comment.
reading file content as string can fail for binary key files (e.g., SSH keys with binary headers).
| fn detect_key_type(path: &PathBuf) -> Option<String> { | |
| let content = fs::read_to_string(path).ok()?; | |
| let first_line = content.lines().next()?; | |
| fn detect_key_type(path: &PathBuf) -> Option<String> { | |
| let content = fs::read(path).ok()?; | |
| let first_line = std::str::from_utf8(&content[..content.iter().position(|&b| b == b'\n').unwrap_or(content.len())]).ok()?; |
| let has_user = resolved_user.as_ref().is_some_and(|u| !u.is_empty()); | ||
| let has_hostname = resolved_hostname.as_ref().is_some_and(|h| !h.is_empty()); | ||
| if has_user != has_hostname { | ||
| return Err( | ||
| "SSH settings require both user and hostname to be set (or neither)".into(), | ||
| ); | ||
| } |
There was a problem hiding this comment.
validation only checks if resolved values are non-empty after resolution, but doesn't validate the actual values. Empty user or hostname props with non-empty userHost would pass this check when they shouldn't
Additional Comments (1)
|
Change Summary
Adds a settings modal to SSH Connect blocks enabling fine-grained connection configuration. Users can override connection details (user/hostname/port) and configure identity key authentication per-user without affecting other team members.
Motivation and Details
The modal provides three identity key modes: use SSH config/agent (default), specify a key path from ~/.ssh, or paste key content directly. Identity keys are stored locally in block-local KV storage, not synced to other users, allowing each team member to authenticate with their own credentials for shared runbooks. SSH connections are automatically invalidated when credentials change. The UI shows validation warnings when only one of user/hostname is configured.
Tasks
docs/docs/blocks/network/ssh.md