question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

SSHHook will not work if `extra.private_key` is a RSA key

See original GitHub issue

Apache Airflow version: 2.0.2

Kubernetes version (if you are using kubernetes) (use kubectl version):

Environment:

  • Cloud provider or hardware configuration:
  • OS (e.g. from /etc/os-release):
  • Kernel (e.g. uname -a):
  • Install tools:
  • Others:

What happened:

ssh-keygen -t rsa -P "" -f test_rsa
cat test_rsa | python -c 'import sys;import json; print(json.dumps(sys.stdin.read()))' # gives the private key encoded as JSON string to be pasted in the connection extra private_key

I created an Airflow Connection

  • type: ssh
  • extra:
{
"look_for_keys": "false",
"no_host_key_check": "true",
"private_key": "-----BEGIN OPENSSH PRIVATE KEY-----\nb3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAABlwAAAAdzc2gtcn\nNhAA........W4tTGFndW5hLU1hY0Jvb2stUHJvAQI=\n-----END OPENSSH PRIVATE KEY-----\n",
"private_key_passphrase": ""
}

When this SSH connection is used in SFTPToS3Operator for example it will incorrectly parse that private_key as a paramiko.dsskey.DSSKey instead of the correct paramiko.rsakey.RSAKey.

The code responsible for the processing of private_key is not not deterministic (I don’t think .values() returns items in any particular order) , but in my case it will always try paramiko.dsskey.DSSKey before it tries paramiko.rsakey.RSAKey:

https://github.com/apache/airflow/blob/8e2a0bc2e39aeaf15b409bbfa8ac0c85aa873815/airflow/providers/ssh/hooks/ssh.py#L363-L369

This incorrectly parsed private key will cause a very confusing error later when it’s actually used

[2021-06-30 23:33:14,604] {transport.py:1819} INFO - Connected (version 2.0, client AWS_SFTP_1.0)
[2021-06-30 23:33:14,732] {transport.py:1819} ERROR - Unknown exception: q must be exactly 160, 224, or 256 bits long
[2021-06-30 23:33:14,737] {transport.py:1817} ERROR - Traceback (most recent call last):
[2021-06-30 23:33:14,737] {transport.py:1817} ERROR -   File "/Users/rubelagu/git/apache-airflow-providers-tdh/venv/lib/python3.8/site-packages/paramiko/transport.py", line 2109, in run
[2021-06-30 23:33:14,737] {transport.py:1817} ERROR -     handler(self.auth_handler, m)
[2021-06-30 23:33:14,738] {transport.py:1817} ERROR -   File "/Users/rubelagu/git/apache-airflow-providers-tdh/venv/lib/python3.8/site-packages/paramiko/auth_handler.py", line 298, in _parse_service_accept
[2021-06-30 23:33:14,738] {transport.py:1817} ERROR -     sig = self.private_key.sign_ssh_data(blob)
[2021-06-30 23:33:14,738] {transport.py:1817} ERROR -   File "/Users/rubelagu/git/apache-airflow-providers-tdh/venv/lib/python3.8/site-packages/paramiko/dsskey.py", line 108, in sign_ssh_data
[2021-06-30 23:33:14,738] {transport.py:1817} ERROR -     key = dsa.DSAPrivateNumbers(
[2021-06-30 23:33:14,738] {transport.py:1817} ERROR -   File "/Users/rubelagu/git/apache-airflow-providers-tdh/venv/lib/python3.8/site-packages/cryptography/hazmat/primitives/asymmetric/dsa.py", line 244, in private_key
[2021-06-30 23:33:14,738] {transport.py:1817} ERROR -     return backend.load_dsa_private_numbers(self)
[2021-06-30 23:33:14,738] {transport.py:1817} ERROR -   File "/Users/rubelagu/git/apache-airflow-providers-tdh/venv/lib/python3.8/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 826, in load_dsa_private_numbers
[2021-06-30 23:33:14,738] {transport.py:1817} ERROR -     dsa._check_dsa_private_numbers(numbers)
[2021-06-30 23:33:14,739] {transport.py:1817} ERROR -   File "/Users/rubelagu/git/apache-airflow-providers-tdh/venv/lib/python3.8/site-packages/cryptography/hazmat/primitives/asymmetric/dsa.py", line 282, in _check_dsa_private_numbers
[2021-06-30 23:33:14,739] {transport.py:1817} ERROR -     _check_dsa_parameters(parameters)
[2021-06-30 23:33:14,739] {transport.py:1817} ERROR -   File "/Users/rubelagu/git/apache-airflow-providers-tdh/venv/lib/python3.8/site-packages/cryptography/hazmat/primitives/asymmetric/dsa.py", line 274, in _check_dsa_parameters
[2021-06-30 23:33:14,739] {transport.py:1817} ERROR -     raise ValueError("q must be exactly 160, 224, or 256 bits long")
[2021-06-30 23:33:14,739] {transport.py:1817} ERROR - ValueError: q must be exactly 160, 224, or 256 bits long
[2021-06-30 23:33:14,739] {transport.py:1817} ERROR - 

What you expected to happen:

I expected to parse the private_key as a RSAKey.

I did my own test and paramiko.dsskey.DSSKey.from_private_key(StringIO(private_key), password=passphrase) will happily parse (incorrectly) a RSA key. The current code assumes that it will raise an exception but it won’t.

How to reproduce it:

Anything else we need to know:

For me it happens always, I don’t think the order of .values() is deterministic, but in my laptop it will always try DSSKey before RSAKey.

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:16 (13 by maintainers)

github_iconTop GitHub Comments

1reaction
ashbcommented, Jul 1, 2021

Having to specify the key type is “duplication” for most of the cases.

I think we should do two things:

  1. Move DSA to the end, so it is tried last (doesn’t solve the problem, but it is just so rarely used it shouldn’t be first)
  2. Try out the key by calling ssh_sign_data
            try:
                key = pkey_type.from_private_key(StringIO(private_key), password=passphrase)
                # Test the key out
                key.sign_ssh_data(b'')
                return key
            except (paramiko.ssh_exception.SSHException, ValueError):
                continue
0reactions
potiukcommented, Mar 29, 2022

BTW. It’s really funny when people are told they should expect no support and then they … expect support 😃.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Airflow:SSHHook:ERROR - not a valid RSA private key file
The trick for me was including \n in the private key. So your json for Extra in SSH connection would look like
Read more >
SSH Connection - Apache Airflow
The SSH connection type provides connection to use SSHHook to run commands on a remote server using SSHOperator or transfer file from/to the...
Read more >
SSHHook will not work if `extra.private_key` is a RSA key
I did my own impl of SFTPToS3Operator and SSHHook to overcome this problem ... 'Private key provided cannot be read by paramiko.
Read more >
Set up SSH public key authentication to connect to a remote ...
To set up public key authentication using SSH on a Linux or macOS ... If the private key you're using does not have...
Read more >
Connect to an Amazon EC2 instance when the SSH key pair ...
How can I connect to my Amazon EC2 instance if I lost my SSH key pair ... and adds a new SSH (public/private)...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found