fix(ssh-tunnel): support ed25519 and ECDSA keys, not just RSA (#24180)#40139
fix(ssh-tunnel): support ed25519 and ECDSA keys, not just RSA (#24180)#40139rusackas wants to merge 3 commits into
Conversation
Code Review Agent Run #c2a919Actionable Suggestions - 0Review Details
Bito Usage GuideCommands Type the following command in the pull request comment and save the comment.
Refer to the documentation for additional commands. Configuration This repository uses Documentation & Help |
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #40139 +/- ##
==========================================
- Coverage 64.14% 64.14% -0.01%
==========================================
Files 2592 2592
Lines 138841 138855 +14
Branches 32201 32202 +1
==========================================
+ Hits 89064 89070 +6
- Misses 48245 48253 +8
Partials 1532 1532
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
|
The flagged issue is correct: the new ed25519 regression test will fail deterministically because SSHManager.create_tunnel hard-codes RSA key parsing, causing an 'unpack requires 4 bytes' error when trying to parse ed25519 keys. To resolve, update the key loading logic to use paramiko's polymorphic loader instead of RSAKey. superset/extensions/ssh.py |
Code Review Agent Run #186373Actionable Suggestions - 0Review Details
Bito Usage GuideCommands Type the following command in the pull request comment and save the comment.
Refer to the documentation for additional commands. Configuration This repository uses Documentation & Help |
aminghadersohi
left a comment
There was a problem hiding this comment.
Review: SSH key type support
The fix is correct, secure, and backwards-compatible — _load_private_key cleanly solves the ed25519/ECDSA bug without touching any auth boundaries and without leaking key material in error paths. RSA regression test is a nice touch.
Three things worth addressing before LGTM (details in inline comments):
raise ... from last_exc— one-word fix, restores traceback chainPasswordRequiredExceptionshould be re-raised rather than absorbed by theexcept SSHExceptionclause — it's a distinct, actionable signal ("key requires passphrase") that gets masked as "Unable to parse"- ECDSA test missing — third declared key type, distinct paramiko code path
Nits inline as well.
aminghadersohi
left a comment
There was a problem hiding this comment.
Review feedback addressed in the follow-up commit (8dbc525):
PasswordRequiredExceptionis now re-raised immediately instead of being absorbed by theexcept SSHExceptionloop — passphrase errors surface as actionablePasswordRequiredExceptionrather than a generic "Unable to parse" message- Exception chaining added:
raise SSHException(...) from last_excpreserves the full traceback for Sentry/debugging last_exctype narrowed toSSHException | None- ECDSA test added (
test_create_tunnel_accepts_ecdsa_private_key, NIST P-256) — all three types in_SSH_KEY_TYPESare now exercised - Inline RSA import moved to module level (consistent with ed25519 import style)
All pre-commit hooks pass. LGTM.
Closes #24180 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
`SSHManager.create_tunnel` unconditionally called `RSAKey.from_private_key` regardless of key type, so users who pasted a modern key (ed25519, ECDSA) got an opaque `paramiko.ssh_exception.SSHException: unpack requires a buffer of 4 bytes` and the tunnel never opened. paramiko does not expose a polymorphic `PKey.from_private_key`; each key class only accepts its own format. Add `_load_private_key` that tries Ed25519Key → ECDSAKey → RSAKey in order and returns the first that parses cleanly. Modern types are tried first because RSA's parser is the most permissive and would happily accept a non-RSA buffer with the same vague error otherwise. If none of the loaders succeed, surface a single `SSHException` whose message lists every type that was attempted — much more actionable than the original 4-bytes-buffer error. Companion regression tests (added in this PR's earlier commit) cover both the new ed25519 path and the backward-compatible RSA path. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Re-raise PasswordRequiredException immediately instead of absorbing it into the try-next-type loop, so callers see an actionable "key requires passphrase" error rather than "Unable to parse" - Add `from last_exc` to the final raise to preserve the exception chain for traceback tools (Sentry et al.) - Narrow last_exc type annotation to SSHException | None - Add test_create_tunnel_accepts_ecdsa_private_key (NIST P-256) to cover the third entry in _SSH_KEY_TYPES - Move RSA and ECDSA crypto imports to module level (rm inline import)
8dbc525 to
5a6cdd8
Compare
✅ Deploy Preview for superset-docs-preview ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
Code Review Agent Run #831652Actionable Suggestions - 0Review Details
Bito Usage GuideCommands Type the following command in the pull request comment and save the comment.
Refer to the documentation for additional commands. Configuration This repository uses Documentation & Help |
SUMMARY
Closes #24180.
SSHManager.create_tunnel(insuperset/extensions/ssh.py) unconditionally calledRSAKey.from_private_keyregardless of key type. Users who pasted an ed25519 (or ECDSA) private key got an opaqueparamiko.ssh_exception.SSHException: unpack requires a buffer of 4 bytesand the tunnel never opened. ed25519 has been the OpenSSH default since 2018, so this hits anyone with a recentssh-keygenconfig.This PR:
_load_private_key()— a polymorphic loader that triesEd25519Key→ECDSAKey→RSAKeyin order and returns the first that parses cleanly. Modern types are tried first because RSA's parser is the most permissive and would happily mis-accept a non-RSA buffer.RSAKey.from_private_keycall with_load_private_key(...).SSHExceptionwhose message lists every type attempted — much better than the original four-bytes-buffer error.test_create_tunnel_accepts_ed25519_private_key— the new pathtest_create_tunnel_accepts_rsa_private_key_unchanged— backward-compat for RSABEFORE/AFTER SCREENSHOTS OR ANIMATED GIF
N/A — backend key-loader change. Verified locally:
TESTING INSTRUCTIONS
ADDITIONAL INFORMATION
SSH_TUNNELING🤖 Generated with Claude Code