Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions airflow-core/newsfragments/54079.significant.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
The SSH and SFTP providers now require ``paramiko>=4.0.0``, which drops support for DSA (DSS)
private keys. Connections that rely on a DSA key must generate a new RSA, ECDSA, or Ed25519 key
and update the connection's ``key_file`` or ``private_key`` accordingly.
3 changes: 1 addition & 2 deletions devel-common/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,7 @@ dependencies = [
"types-certifi>=2021.10.8.3",
"types-croniter>=2.0.0.20240423",
"types-docutils>=0.21.0.20240704",
# TODO: Bump to >= 4.0.0 once https://github.com/apache/airflow/issues/54079
"types-paramiko>=3.4.0.20240423,<4.0.0",
"types-paramiko>=4.0.0",
"types-protobuf>=5.26.0.20240422",
"types-python-dateutil>=2.9.0.20240316",
"types-python-slugify>=8.0.2.20240310",
Expand Down
3 changes: 1 addition & 2 deletions providers/sftp/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,7 @@ dependencies = [
"apache-airflow>=2.11.0",
"apache-airflow-providers-ssh>=4.0.0",
"apache-airflow-providers-common-compat>=1.12.0",
# TODO: Bump to >= 4.0.0 once https://github.com/apache/airflow/issues/54079 is handled
"paramiko>=3.5.1,<4.0.0",
"paramiko>=4.0.0",
"asyncssh>=2.12.0; python_version < '3.14'",
"asyncssh>=2.22.0; python_version >= '3.14'",
]
Expand Down
7 changes: 7 additions & 0 deletions providers/ssh/docs/connections/ssh.rst
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,13 @@ Extra (optional)
* ``disabled_algorithms`` - A dictionary mapping algorithm type to an iterable of algorithm identifiers, which will be disabled for the lifetime of the transport.
* ``ciphers`` - A list of ciphers to use in order of preference.

.. note::
As of ``paramiko`` 4.0 (a minimum requirement of this provider), DSA (DSS) private keys are no
longer supported due to their removal from the underlying library. Supported key types are RSA,
ECDSA, and Ed25519. If your connection currently uses a DSA key, generate a new key of one of the
supported types (e.g. ``ssh-keygen -t ed25519``) and update the connection's ``key_file`` or
``private_key`` accordingly.

Example "extras" field:

.. code-block:: json
Expand Down
3 changes: 1 addition & 2 deletions providers/ssh/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,7 @@ dependencies = [
"apache-airflow>=2.11.0",
"apache-airflow-providers-common-compat>=1.12.0",
"asyncssh>=2.12.0",
# TODO: Bump to >= 4.0.0 once https://github.com/apache/airflow/issues/54079 is handled
"paramiko>=3.5.1,<4.0.0",
"paramiko>=4.0.0",

]

Expand Down
4 changes: 2 additions & 2 deletions providers/ssh/src/airflow/providers/ssh/hooks/ssh.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,16 +88,16 @@ class SSHHook(BaseHook):
"""

# List of classes to try loading private keys as, ordered (roughly) by most common to least common
# Note: DSSKey (DSA) support was removed in paramiko 4.0+, so it is no longer offered here.
# Users relying on DSA keys must migrate to RSA, ECDSA, or Ed25519 keys.
_pkey_loaders: Sequence[type[paramiko.PKey]] = (
paramiko.RSAKey,
paramiko.ECDSAKey,
paramiko.Ed25519Key,
paramiko.DSSKey,
)

_host_key_mappings = {
"rsa": paramiko.RSAKey,
"dss": paramiko.DSSKey,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should add a handler or document to avoid regression. For example, if users configured ssh-dss in host_key and then upgrade the ssh provider, this can fail with a KeyError.

e.g.
A connection like this:

Connection(
  conn_id="ssh_with_dss_host_key",
  host="localhost",
  conn_type="ssh",
  extra=json.dumps({"host_key": "ssh-dss AAAAB3NzaC1kc3MAAAAA"}),
)

would fail here because dss has been removed from _host_key_mappings:

if host_key is not None:
if host_key.startswith("ssh-"):
key_type, host_key = host_key.split(None)[:2]
key_constructor = self._host_key_mappings[key_type[4:]]

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, add a small regression test might be better I think :)

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for catching this, @nailo2c you're right, the host_key lookup would have hit a bare KeyError for anyone with an ssh-dss host key configured. Good catch.

Looking at this more, I noticed #69669 also addresses this issue and goes further — it fixes the equivalent regression in the SFTP hook too (which mine doesn't touch), handles more host key type variants (ecdsa-sha2-nistp*, legacy ssh-ecdsa, whitespace/tab-separated formats), and caps the paramiko version bound more carefully.

I'll close this one in favor of that PR rather than duplicate effort. Thanks again for the review!

"ecdsa": paramiko.ECDSAKey,
"ed25519": paramiko.Ed25519Key,
}
Expand Down
28 changes: 19 additions & 9 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading