Skip to content

fix(ssh): scope tunnel port-forward to DynamoDB Local (fixes Mongo/ES) - #499

Merged
Blankll merged 6 commits into
masterfrom
fix/ssh-tunnel-port-forward
Aug 17, 2026
Merged

fix(ssh): scope tunnel port-forward to DynamoDB Local (fixes Mongo/ES)#499
Blankll merged 6 commits into
masterfrom
fix/ssh-tunnel-port-forward

Conversation

@Blankll

@Blankll Blankll commented Aug 16, 2026

Copy link
Copy Markdown
Member

What this PR does

SSH tunnel behavior for the three database types. The tunnel defaults to SOCKS5/CONNECT (keeps the real hostname for TLS/SNI); PortForward is forced only for DynamoDB Local (plain HTTP), where the AWS SDK emits origin-form HTTP (not CONNECT) that a SOCKS5 proxy cannot forward.

Port-forward scoped to DynamoDB Local

  • force_port_forward is true only when type == "DYNAMODB" && endpointUrl is http:// (force_port_forward_for).
  • Previously the scheme defaulted to http for configs without endpointUrl, which wrongly forced MongoDB and ES into PortForward mode and broke their connections (Connection reset by peer on the rewritten 127.0.0.1:port). Type-based gating plus carrying type through normalize_config fixes this — Mongo/ES never force.
  • https DynamoDB (AWS), ES, and MongoDB keep SOCKS5/CONNECT.

Implementation

  • force_port_forward flows as an explicit parameter through start_transport_layers → start_tunnel/start_chain → spawn_tunnel, not a runtime-only #[serde(skip)] field on SshTunnelConfig. SshTunnelConfig stays pure serializable data; the "last-hop-only" invariant is explicit in start_chain (is_last && force_port_forward); no mutation of cloned layer configs.

AWS DynamoDB through the tunnel

  • ProxyConfig::http → https in the DynamoDB client — http only matched http:// targets, so AWS DynamoDB (https) silently bypassed the SOCKS5/CONNECT tunnel. https matches and tunnels via CONNECT.

MongoDB through the tunnel

  • Honor socks5Proxy in the MongoDB capability client factory; normalize MongoDB URI auth (mongodb://u:p@host:port/db) through the SSH tunnel (single-host host/port rewrite).

Verification

  • cargo build --lib: clean
  • cargo test --lib: SSH / ssh_bridge / connection_resolver / dynamo / mongo_client suites green
  • clippy: 0 warnings in touched files
  • force_port_forward_for unit tests cover: DynamoDB-Local→force, AWS-https→no force, MongoDB→no force (even with http endpointUrl), ES/OpenSearch→no force, case-insensitive type, missing type→no force

Note: the DBA capability expansion lives in #496. This PR is the SSH-tunnel fix only.

Blankll and others added 5 commits August 16, 2026 15:05
DynamoDB Local (endpointUrl=http://host:port) over an SSH tunnel failed
with SdkError::DispatchFailure (Connection reset by peer). Root cause:
the AWS SDK's ProxyConfig::http sends origin-form HTTP requests (not
CONNECT) to the proxy for http:// targets, but the dual-protocol tunnel
only accepts SOCKS5 (0x05) and HTTP CONNECT ('C'), so the request byte
0x50 ('P') was dropped and the connection reset.

Fix: resolve_ssh_in_place forces expose_lan for http:// endpoints, which
switches the tunnel to port-forward mode — the client talks plain HTTP
to 127.0.0.1:{local_port} and SSH forwards it to the target. HTTPS and
mongodb:// targets (Mongo/ES/AWS DynamoDB) are unaffected.

Also:
- invoke_capability accepts an optional raw config (for unsaved connect-
  dialog connections), routing on config vs connection_id — unifies the
  listTables entry point and removes the listTablesViaSsh dual path
- normalize_dynamo falls back to host:port for Local connections missing
  endpointUrl (mirrors dynamo_test_connection)
- list_tables errors use Debug format to surface the real transport
  cause instead of the generic 'dispatch failure'

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
…ctive)

The previous attempt set sshTunnel.exposeLan at the JSON top level, which
SshConnectionConfig silently ignores (expose_lan lives in the SSH profile).
This is the working fix:

- config.rs: add runtime-only force_port_forward field (serde skip, not
  persisted, distinct from expose_lan — does NOT widen the bind address)
- tunnel.rs: effective_tunnel_mode + spawn_tunnel_config honor it;
  spawn_tunnel/spawn_chain pass it through (multi-hop supported)
- ssh_bridge: resolve_ssh_tunnel gains a force_port_forward param; callers
  pass scheme == "http" for the endpoint. Port-forward mode rewrites
  endpointUrl to http://127.0.0.1:{local_port}, so the AWS SDK talks plain
  HTTP to the local port and SSH forwards to the target — sidestepping the
  origin-form-vs-CONNECT mismatch entirely.
- dynamo.rs: ProxyConfig::http -> https. ProxyConfig::http only matches
  http:// targets; AWS DynamoDB (https://) was silently bypassing the tunnel.
- invoke_capability: normalize the raw config arg (nested auth -> flat) so
  unsaved connect-dialog configs carry accessKeyId; fixes Missing accessKeyId.
- dynamo_test_connection: also honor http scheme for the tunnel.

Multi-hop chains forward through each hop and reach the target in both
schemes. Mongo (mongodb://) and ES (https://) keep SOCKS5/CONNECT.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Completes the in-progress SSH tunnel work: honors socks5Proxy and HTTP-proxy
transport in the MongoDB capability client factory, normalizes MongoDB URI
auth in tunnel mode, and restores Data Studio auto-scroll with stop/cancel
controls on the chat panel.

Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent)

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
Remove the runtime-only force_port_forward field from SshTunnelConfig
and pass it as an explicit parameter through start_transport_layers,
start_tunnel/start_chain, and spawn_tunnel.

- SshTunnelConfig is pure serializable data again (no #[serde(skip)]
  runtime field; drops force_port_forward: false boilerplate from 5
  construction sites)
- No mutation of cloned layer configs in resolve_connection_target;
  the override flows as an explicit parameter
- The "force_port_forward only applies to the last hop" invariant is
  now explicit in start_chain (is_last && force_port_forward)

The semantic "force port-forward for DynamoDB Local only" stays at the
call sites via force_port_forward_for (type == DYNAMODB && http).
@Blankll Blankll changed the title fix(ssh): SSH tunnel fixes — port-forward for plain-HTTP targets + Mongo URI auth fix(ssh): scope port-forward tunnel to DynamoDB Local + Mongo URI auth Aug 16, 2026
@Blankll Blankll changed the title fix(ssh): scope port-forward tunnel to DynamoDB Local + Mongo URI auth fix(ssh): scope tunnel port-forward to DynamoDB Local (fixes Mongo/ES) Aug 16, 2026
listTables now passes the connection as a 4th config arg to
invokeCapability (Rust resolve_ssh_in_place handles SSH from the
config). Update the 4 toHaveBeenCalledWith assertions to expect the
config object, and drop the obsolete listTablesViaSsh tests (the
function was removed — listTables handles SSH transparently now).
@Blankll
Blankll force-pushed the fix/ssh-tunnel-port-forward branch from 4be7f31 to 768e0e1 Compare August 16, 2026 08:48
@codecov

codecov Bot commented Aug 16, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 61.53846% with 80 lines in your changes missing coverage. Please review.
✅ Project coverage is 60.33%. Comparing base (2db878a) to head (768e0e1).

Files with missing lines Patch % Lines
src-tauri/src/common/ssh_bridge.rs 70.66% 22 Missing ⚠️
src-tauri/src/ssh/tunnel.rs 59.52% 17 Missing ⚠️
src-tauri/src/dynamo_client.rs 0.00% 13 Missing ⚠️
src-tauri/src/mongo_client.rs 0.00% 8 Missing ⚠️
src-tauri/src/capabilities/commands.rs 0.00% 7 Missing ⚠️
src-tauri/src/common/connection_resolver.rs 82.92% 7 Missing ⚠️
src-tauri/src/ssh/transport.rs 66.66% 2 Missing ⚠️
src-tauri/src/dynamo/list_tables.rs 0.00% 1 Missing ⚠️
src-tauri/src/fetch_client.rs 0.00% 1 Missing ⚠️
src-tauri/src/ssh/commands.rs 0.00% 1 Missing ⚠️
... and 1 more
Additional details and impacted files

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #499      +/-   ##
==========================================
+ Coverage   60.28%   60.33%   +0.04%     
==========================================
  Files         122      122              
  Lines       18962    19113     +151     
  Branches      885      881       -4     
==========================================
+ Hits        11431    11531     +100     
- Misses       7268     7322      +54     
+ Partials      263      260       -3     
Files with missing lines Coverage Δ
src-tauri/src/common/dynamo.rs 86.47% <100.00%> (ø)
src-tauri/src/common/mongo.rs 99.22% <100.00%> (+0.01%) ⬆️
src/store/connectionStore.ts 68.07% <100.00%> (+0.30%) ⬆️
src-tauri/src/dynamo/list_tables.rs 0.00% <0.00%> (ø)
src-tauri/src/fetch_client.rs 52.90% <0.00%> (ø)
src-tauri/src/ssh/commands.rs 0.00% <0.00%> (ø)
src/datasources/dynamoApi.ts 82.17% <50.00%> (+0.86%) ⬆️
src-tauri/src/ssh/transport.rs 67.94% <66.66%> (+0.84%) ⬆️
src-tauri/src/capabilities/commands.rs 88.16% <0.00%> (-1.06%) ⬇️
src-tauri/src/common/connection_resolver.rs 89.82% <82.92%> (-1.15%) ⬇️
... and 4 more
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@Blankll
Blankll merged commit 5fa8526 into master Aug 17, 2026
9 checks passed
@Blankll
Blankll deleted the fix/ssh-tunnel-port-forward branch August 17, 2026 02:21
Blankll added a commit that referenced this pull request Aug 17, 2026
…496)

## What this PR does

Expands the agent-visible DBA capability surface across the three
database types.

### DynamoDB (26 → 33 agent-visible tools)
- Flip 12 UI-only capabilities to agent-visible: `create_table`,
`delete_table`, `truncate_table`, `update_table_config`,
`update/delete_gsi`, `update_ttl`, `update_pitr`, `update_streams`,
`describe_ttl`, `describe_continuous_backups`, `get_table_metrics`
- Add 7 new: `restore_table` (from backup + PITR), `create_backup`,
`list_backups`, `describe_backup`, `describe_limits`, `list_tags`,
`tag_resource`
- Enriched the 12 newly-exposed descriptions with DBA-scenario guidance
(中文/English)

### Elasticsearch (19 → 24)
`cluster_health`, `cat_nodes`, `cat_shards`, `list_snapshots`,
`restore_snapshot`

### MongoDB (30 → 32)
`get_slow_queries` (currentOp with system.profile fallback),
`list_users` (usersInfo)

Agent-tag regression tests assert 33/24/32 capabilities are
agent-visible.

## Verification
- agent-tag tests: dynamo@33 / es@24 / mongo@32 green
- `cargo test --lib`: green

> Note: the SSH tunnel fixes live in #499. This branch currently also
carries the SSH commits (duplicated with #499); it will be rebased onto
#499's master before merge so only the capability commits remain.

---------

Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
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