ojarva / python-sshpubkeys

OpenSSH public key parser for Python
BSD 3-Clause "New" or "Revised" License
101 stars 42 forks source link

error from Django: _SSHCipher() takes no arguments #101

Open maxadamo opened 11 months ago

maxadamo commented 11 months ago

I am using this simple function, which works from a terminal, but it doesn't work from Django:

def validate_ssh_public_key(key_string):
    """validate ssh public key"""
    try:
        ssh = SSHKey(key_string)
    except Exception as err:
        print("Error running SSHKey:", err)
        return False

    try:
        ssh.parse()
        return True
    except Exception as err:
        print("Error running ssh.parse():", err)
        return False

and I get this error:

Error running SSHKey: _SSHCipher() takes no arguments
ojarva commented 11 months ago

Please try without try-except causing a crash to be logged with a stacktrace.

Alternatively you can log it from Exception if that works better for you.

ojarva commented 11 months ago

Also how certain you are your input is a strong rather than bytes?

maxadamo commented 11 months ago

@ojarva ~I think I understood where the problem is. but I need to understand if I can circumvent the error on Django, or if it's a problem with the library.~

~IMO it seems that the white spaces are creating multiple arguments.~ ~If I remove ssh-rsa from the beginning, and the email at the end, I get a sensible error, because it's missing they key type:~

Error: Couldn't find beginning of the key data

And this is the full error if I remove the try-execpt, this is the error that I'm getting:

[Sat Nov 18 17:04:39.824631 2023] [wsgi:error] [pid 1988249:tid 140184335144512] [remote 2001:xxx:xxx:xx::xxx:56860] Internal Server Error: /terraformui/vm_common/
[Sat Nov 18 17:04:39.824964 2023] [wsgi:error] [pid 1988249:tid 140184335144512] [remote 2001:xxx:xxx:xx::xxx:56860] Traceback (most recent call last):
[Sat Nov 18 17:04:39.825031 2023] [wsgi:error] [pid 1988249:tid 140184335144512] [remote 2001:xxx:xxx:xx::xxx:56860]   File "/home/terraform/venv/django/lib/python3.12/site-packages/django/core/handlers/exception.py", line 55, in inner
[Sat Nov 18 17:04:39.825126 2023] [wsgi:error] [pid 1988249:tid 140184335144512] [remote 2001:xxx:xxx:xx::xxx:56860]     response = get_response(request)
[Sat Nov 18 17:04:39.825274 2023] [wsgi:error] [pid 1988249:tid 140184335144512] [remote 2001:xxx:xxx:xx::xxx:56860]                ^^^^^^^^^^^^^^^^^^^^^
[Sat Nov 18 17:04:39.825360 2023] [wsgi:error] [pid 1988249:tid 140184335144512] [remote 2001:xxx:xxx:xx::xxx:56860]   File "/home/terraform/venv/django/lib/python3.12/site-packages/django/core/handlers/base.py", line 197, in _get_response
[Sat Nov 18 17:04:39.825447 2023] [wsgi:error] [pid 1988249:tid 140184335144512] [remote 2001:xxx:xxx:xx::xxx:56860]     response = wrapped_callback(request, *callback_args, **callback_kwargs)
[Sat Nov 18 17:04:39.825532 2023] [wsgi:error] [pid 1988249:tid 140184335144512] [remote 2001:xxx:xxx:xx::xxx:56860]                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[Sat Nov 18 17:04:39.825617 2023] [wsgi:error] [pid 1988249:tid 140184335144512] [remote 2001:xxx:xxx:xx::xxx:56860]   File "/home/terraform/venv/django/lib/python3.12/site-packages/django/contrib/auth/decorators.py", line 23, in _wrapper_view
[Sat Nov 18 17:04:39.825702 2023] [wsgi:error] [pid 1988249:tid 140184335144512] [remote 2001:xxx:xxx:xx::xxx:56860]     return view_func(request, *args, **kwargs)
[Sat Nov 18 17:04:39.825786 2023] [wsgi:error] [pid 1988249:tid 140184335144512] [remote 2001:xxx:xxx:xx::xxx:56860]            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[Sat Nov 18 17:04:39.825836 2023] [wsgi:error] [pid 1988249:tid 140184335144512] [remote 2001:xxx:xxx:xx::xxx:56860]   File "/home/terraform/terraformator/terraformui/views.py", line 162, in vm_common
[Sat Nov 18 17:04:39.825869 2023] [wsgi:error] [pid 1988249:tid 140184335144512] [remote 2001:xxx:xxx:xx::xxx:56860]     if not check_data.validate_ssh_public_key(ssh_pub_key):
[Sat Nov 18 17:04:39.825901 2023] [wsgi:error] [pid 1988249:tid 140184335144512] [remote 2001:xxx:xxx:xx::xxx:56860]            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[Sat Nov 18 17:04:39.826045 2023] [wsgi:error] [pid 1988249:tid 140184335144512] [remote 2001:xxx:xxx:xx::xxx:56860]   File "/home/terraform/terraformator/terraformui/check_data.py", line 11, in validate_ssh_public_key
[Sat Nov 18 17:04:39.826106 2023] [wsgi:error] [pid 1988249:tid 140184335144512] [remote 2001:xxx:xxx:xx::xxx:56860]     sshpubkeys.SSHKey(key_string, Strict=True).parse()
[Sat Nov 18 17:04:39.826138 2023] [wsgi:error] [pid 1988249:tid 140184335144512] [remote 2001:xxx:xxx:xx::xxx:56860]     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[Sat Nov 18 17:04:39.826231 2023] [wsgi:error] [pid 1988249:tid 140184335144512] [remote 2001:xxx:xxx:xx::xxx:56860]   File "/home/terraform/venv/django/lib/python3.12/site-packages/sshpubkeys/keys.py", line 135, in __init__
[Sat Nov 18 17:04:39.826330 2023] [wsgi:error] [pid 1988249:tid 140184335144512] [remote 2001:xxx:xxx:xx::xxx:56860]     self.parse(keydata)
[Sat Nov 18 17:04:39.826429 2023] [wsgi:error] [pid 1988249:tid 140184335144512] [remote 2001:xxx:xxx:xx::xxx:56860]   File "/home/terraform/venv/django/lib/python3.12/site-packages/sshpubkeys/keys.py", line 475, in parse
[Sat Nov 18 17:04:39.826528 2023] [wsgi:error] [pid 1988249:tid 140184335144512] [remote 2001:xxx:xxx:xx::xxx:56860]     key_data_length = self._process_key(self._decoded_key[current_position:])
[Sat Nov 18 17:04:39.826579 2023] [wsgi:error] [pid 1988249:tid 140184335144512] [remote 2001:xxx:xxx:xx::xxx:56860]                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
[Sat Nov 18 17:04:39.826672 2023] [wsgi:error] [pid 1988249:tid 140184335144512] [remote 2001:xxx:xxx:xx::xxx:56860]   File "/home/terraform/venv/django/lib/python3.12/site-packages/sshpubkeys/keys.py", line 426, in _process_key
[Sat Nov 18 17:04:39.826759 2023] [wsgi:error] [pid 1988249:tid 140184335144512] [remote 2001:xxx:xxx:xx::xxx:56860]     return self._process_ssh_rsa(data)
[Sat Nov 18 17:04:39.826842 2023] [wsgi:error] [pid 1988249:tid 140184335144512] [remote 2001:xxx:xxx:xx::xxx:56860]            ^^^^^^^^^^^^^^^^^^^^^^^^^^^
[Sat Nov 18 17:04:39.826924 2023] [wsgi:error] [pid 1988249:tid 140184335144512] [remote 2001:xxx:xxx:xx::xxx:56860]   File "/home/terraform/venv/django/lib/python3.12/site-packages/sshpubkeys/keys.py", line 310, in _process_ssh_rsa
[Sat Nov 18 17:04:39.827007 2023] [wsgi:error] [pid 1988249:tid 140184335144512] [remote 2001:xxx:xxx:xx::xxx:56860]     self.rsa = RSAPublicNumbers(unpacked_e, unpacked_n).public_key(default_backend())
[Sat Nov 18 17:04:39.827146 2023] [wsgi:error] [pid 1988249:tid 140184335144512] [remote 2001:xxx:xxx:xx::xxx:56860]                                                                    ^^^^^^^^^^^^^^^^^
[Sat Nov 18 17:04:39.827230 2023] [wsgi:error] [pid 1988249:tid 140184335144512] [remote 2001:xxx:xxx:xx::xxx:56860]   File "/home/terraform/venv/django/lib/python3.12/site-packages/cryptography/hazmat/backends/__init__.py", line 11, in default_backend
[Sat Nov 18 17:04:39.827314 2023] [wsgi:error] [pid 1988249:tid 140184335144512] [remote 2001:xxx:xxx:xx::xxx:56860]     from cryptography.hazmat.backends.openssl.backend import backend
[Sat Nov 18 17:04:39.827399 2023] [wsgi:error] [pid 1988249:tid 140184335144512] [remote 2001:xxx:xxx:xx::xxx:56860]   File "/home/terraform/venv/django/lib/python3.12/site-packages/cryptography/hazmat/backends/openssl/__init__.py", line 7, in <module>
[Sat Nov 18 17:04:39.827482 2023] [wsgi:error] [pid 1988249:tid 140184335144512] [remote 2001:xxx:xxx:xx::xxx:56860]     from cryptography.hazmat.backends.openssl.backend import backend
[Sat Nov 18 17:04:39.827565 2023] [wsgi:error] [pid 1988249:tid 140184335144512] [remote 2001:xxx:xxx:xx::xxx:56860]   File "/home/terraform/venv/django/lib/python3.12/site-packages/cryptography/hazmat/backends/openssl/backend.py", line 13, in <module>
[Sat Nov 18 17:04:39.827648 2023] [wsgi:error] [pid 1988249:tid 140184335144512] [remote 2001:xxx:xxx:xx::xxx:56860]     from cryptography import utils, x509
[Sat Nov 18 17:04:39.827731 2023] [wsgi:error] [pid 1988249:tid 140184335144512] [remote 2001:xxx:xxx:xx::xxx:56860]   File "/home/terraform/venv/django/lib/python3.12/site-packages/cryptography/x509/__init__.py", line 8, in <module>
[Sat Nov 18 17:04:39.827786 2023] [wsgi:error] [pid 1988249:tid 140184335144512] [remote 2001:xxx:xxx:xx::xxx:56860]     from cryptography.x509.base import (
[Sat Nov 18 17:04:39.827863 2023] [wsgi:error] [pid 1988249:tid 140184335144512] [remote 2001:xxx:xxx:xx::xxx:56860]   File "/home/terraform/venv/django/lib/python3.12/site-packages/cryptography/x509/base.py", line 14, in <module>
[Sat Nov 18 17:04:39.827949 2023] [wsgi:error] [pid 1988249:tid 140184335144512] [remote 2001:xxx:xxx:xx::xxx:56860]     from cryptography.hazmat.primitives import hashes, serialization
[Sat Nov 18 17:04:39.827996 2023] [wsgi:error] [pid 1988249:tid 140184335144512] [remote 2001:xxx:xxx:xx::xxx:56860]   File "/home/terraform/venv/django/lib/python3.12/site-packages/cryptography/hazmat/primitives/serialization/__init__.py", line 25, in <module>
[Sat Nov 18 17:04:39.828081 2023] [wsgi:error] [pid 1988249:tid 140184335144512] [remote 2001:xxx:xxx:xx::xxx:56860]     from cryptography.hazmat.primitives.serialization.ssh import (
[Sat Nov 18 17:04:39.828114 2023] [wsgi:error] [pid 1988249:tid 140184335144512] [remote 2001:xxx:xxx:xx::xxx:56860]   File "/home/terraform/venv/django/lib/python3.12/site-packages/cryptography/hazmat/primitives/serialization/ssh.py", line 105, in <module>
[Sat Nov 18 17:04:39.828145 2023] [wsgi:error] [pid 1988249:tid 140184335144512] [remote 2001:xxx:xxx:xx::xxx:56860]     b"aes256-ctr": _SSHCipher(
[Sat Nov 18 17:04:39.828175 2023] [wsgi:error] [pid 1988249:tid 140184335144512] [remote 2001:xxx:xxx:xx::xxx:56860]                    ^^^^^^^^^^^
[Sat Nov 18 17:04:39.828257 2023] [wsgi:error] [pid 1988249:tid 140184335144512] [remote 2001:xxx:xxx:xx::xxx:56860] TypeError: _SSHCipher() takes no arguments
maxadamo commented 11 months ago

~in fact, I tried the following, which doesn't work, but the error is sensible again, because it states that they keys starts with a wrong string: "ssh-rsa~

def validate_ssh_public_key(key_string):
    """validate ssh public key"""
    if not key_string:
        return True
    test = f'"{key_string}"'
    print(test)
    try:
        sshpubkeys.SSHKey(test).parse()
    except Exception as err:  # pylint: disable=broad-except
        print("Error:", err)
        return False
Error: Couldn't find beginning of the key data
maxadamo commented 11 months ago

I have also tried to just remove all the spaces: ssh-rsaAAA.....XXXemail.exampl.org

and the error still makes sense:

Error: Unexpected key format: at least type and base64 encoded value is required

Problem could be with white spaces.

I wonder whether this is an issue with Django, or I am doing something wrong, or this is an issue with this library

maxadamo commented 11 months ago

sorry, it was a wrong assumption. If I use a key like ssh-rsa 123456 sdfsf, I am also getting a sensible error, and the key contains spaces:

[Sat Nov 18 17:32:10.461615 2023] [wsgi:error] [pid 1990929:tid 140184226039360] [remote 2001:xxxxxx:57685] Error: Unable to decode the key

the problem is with the library.

ojarva commented 11 months ago

So... With what input exactly you get the weird (incorrect) error?

maxadamo commented 11 months ago

So... With what input exactly you get the weird (incorrect) error?

I get the weird error when I use a proper key. Wrong keys throw a regular exception.

ojarva commented 11 months ago

Considering the test suite contains quite exhaustive list of different kind of proper keys, I'm going to need more information to figure out what's going on.

If your code works from the command line with exactly the same input that breaks stuff in django... I have a strong suspicion it's not the same input.

If it's exactly the same, please provide a minimal, runnable django example (minimal app source code with say, API endpoint), and I'll debug what's going on.

On Sat, Nov 18, 2023, 23:14 Massimiliano Adamo @.***> wrote:

So... With what input exactly you get the weird (incorrect) error?

I get the weird error when I use a proper key. Wrong keys throw a regular exception.

— Reply to this email directly, view it on GitHub https://github.com/ojarva/python-sshpubkeys/issues/101#issuecomment-1817643826, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAI7RROBYM4EQSIJTO2H2G3YFEQKZAVCNFSM6AAAAAA7RB7IJ6VHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTQMJXGY2DGOBSGY . You are receiving this because you were mentioned.Message ID: @.***>

maxadamo commented 11 months ago

that's gonna take a while but I can do it. I need to create a setup with at least a sqlite DB.

The error is happening at the following line (line number is different for me, as I am using version 3.3.1): https://github.com/ojarva/python-sshpubkeys/blob/master/sshpubkeys/keys.py#L362

self.rsa = RSAPublicNumbers(unpacked_e, unpacked_n).public_key(default_backend())

if, right before that line, I add the following 2 lines:

print(type(self.keydata))
print(f"BEGING{self.keydata}END")

The output from Django looks good to me, and it's exactly the same output that I get from the command line:

[Sun Nov 19 12:33:39.06 ...<CUT>... 02c:55771]  <class 'str'>
[Sun Nov 19 12:33:39.06 ...<CUT>... 02c:55771] BEGINGssh-rsa AAAAB3 ...<HIDDEN>... 2Oh0Sx maxadamo@maxadamoEND
[Sun Nov 19 12:33:39.06 ...<CUT>... 02c:55771] Error running SSHKey _SSHCipher() takes no arguments
maxadamo commented 11 months ago

I found a workaround and I can also prove that I was passing proper data to the function. if instead of calling a function within Django, I use subprocess to run an external python script, the library sshpubkeys works like a charm and it validates my SSH key.

This is the script /home/terraform/bin/check_pub_key.py:

#!/home/terraform/venv/django/bin/python
import sys
from sshpubkeys import SSHKey

if len(sys.argv) > 1:
    key_string = sys.argv[1]

    try:
        ssh = SSHKey(key_string)
    except Exception as err:  # pylint: disable=broad-except
        print("Error running SSHKey", err)
        sys.exit(1)

    try:
        ssh.parse()
    except Exception as err:  # pylint: disable=broad-except
        print("Error running ssh.parse()", err)
        sys.exit(1)

and in Django I am doing:

cmd_check = [f"{settings.HOME_DIR}/bin/check_pub_key.py", ssh_pub_key]
check_pub_key = sp.run(cmd_check, check=False, capture_output=True, text=True)
if check_pub_key.returncode != 0:
    print('some cursing here...')

and I can pretty-print the error on the page (if I used a wrong key) 👻

image

ojarva commented 11 months ago

You don't need to set up a sqlite - I would recommend just generating a new ssh key (so that there's nothing secret on that one) and hardcode that to your minimal django example.

If the issue only occurs when the data comes from sqlite, then it's definitely something with the input data that goes sideways.

maxadamo commented 11 months ago

Sorry for the misunderstanding. DB is a requirement for Django (django-get-your-database-running), but I'm not using a DB with my application. However, it turns out that DB is required only to enable API functionality. In our case we won't need any DB. p.s.: thanks a lot for the head up, for the key ... it's a public key in the end. Someone may want to use it to allow me onto their system, or repositories 😺

Only one thing has changed: instead of calling a function, I am calling a python script with subprocess. And the script is using the same Python virtualenv with python 3.12

ojarva commented 11 months ago

I'm very aware it's a public key but you censored it above, so my suggestion was to make sure the example will actually work (fail with that mysterious error). It doesn't necessary do that with all keys - I have no clue why that fails like it does in your setup.