diff --git a/changelog.md b/changelog.md index 6cab6f51..8197e3fc 100644 --- a/changelog.md +++ b/changelog.md @@ -1,3 +1,18 @@ +Upcoming Release (TBD) +====================== + +Bug Fixes: +---------- + +* fix SSL through SSH jump host by using a true python socket for a tunnel + +Internal: +--------- + +Features: +--------- + + 1.28.0 (2024/11/10) ====================== diff --git a/mycli/AUTHORS b/mycli/AUTHORS index d5a9ce08..b8344520 100644 --- a/mycli/AUTHORS +++ b/mycli/AUTHORS @@ -98,6 +98,7 @@ Contributors: * Houston Wong * Mohamed Rezk * Ryosuke Kazami + * Cornel Cruceru Created by: diff --git a/mycli/packages/paramiko_stub/__init__.py b/mycli/packages/paramiko_stub/__init__.py index 045b00ea..de722ce7 100644 --- a/mycli/packages/paramiko_stub/__init__.py +++ b/mycli/packages/paramiko_stub/__init__.py @@ -13,9 +13,9 @@ def __getattr__(self, name): import sys from textwrap import dedent print(dedent(""" - To enable certain SSH features you need to install paramiko: + To enable certain SSH features you need to install paramiko and sshtunnel: - pip install paramiko + pip install paramiko sshtunnel It is required for the following configuration options: --list-ssh-config diff --git a/mycli/sqlexecute.py b/mycli/sqlexecute.py index bd5f5d98..3122b6ef 100644 --- a/mycli/sqlexecute.py +++ b/mycli/sqlexecute.py @@ -10,6 +10,7 @@ decoders) try: import paramiko + import sshtunnel except ImportError: from mycli.packages.paramiko_stub import paramiko @@ -189,19 +190,24 @@ def connect(self, database=None, user=None, password=None, host=None, ) if ssh_host: - client = paramiko.SSHClient() - client.load_system_host_keys() - client.set_missing_host_key_policy(paramiko.WarningPolicy()) - client.connect( - ssh_host, ssh_port, ssh_user, ssh_password, - key_filename=ssh_key_filename - ) - chan = client.get_transport().open_channel( - 'direct-tcpip', - (host, port), - ('0.0.0.0', 0), - ) - conn.connect(chan) + ##### paramiko.Channel is a bad socket implementation overall if you want SSL through an SSH tunnel + ##### + # instead let's open a tunnel and rewrite host:port to local bind + try: + chan = sshtunnel.SSHTunnelForwarder( + (ssh_host, ssh_port), + ssh_username=ssh_user, + ssh_pkey=ssh_key_filename, + ssh_password=ssh_password, + remote_bind_address=(host, port) + ) + chan.start() + + conn.host=chan.local_bind_host + conn.port=chan.local_bind_port + conn.connect() + except Exception as e: + raise e if hasattr(self, 'conn'): self.conn.close() diff --git a/requirements-dev.txt b/requirements-dev.txt index 603efa20..abf92d3b 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -10,6 +10,7 @@ colorama>=0.4.1 git+https://github.com/hayd/pep8radius.git # --error-status option not released click>=7.0 paramiko==2.11.0 +sshtunnel==0.4.0 pyperclip>=1.8.1 importlib_resources>=5.0.0 pyaes>=1.6.1