Home > Software engineering >  module 'requests.packages.urllib3.contrib' has no attribute 'pyopenssl'
module 'requests.packages.urllib3.contrib' has no attribute 'pyopenssl'

Time:03-03

I'm working on a simple python script that uses a base64 encoded certificate and private key. These are base64 encoded string literals in the script.

I create a Pkcs12Context class definition like so (where it loads the cert and the key).

class Pkcs12Context(requests.packages.urllib3.contrib.pyopenssl.OpenSSL.SSL.Context):
    def __init__(self, method):
        super(Pkcs12Context, self).__init__(method)
        self.use_certificate(load_certificate(FILETYPE_PEM, base64.b64decode(ENCODED_CERT)))
        self.use_privatekey(load_privatekey(FILETYPE_PEM, base64.b64decode(ENCODED_PRIVATEKEY)))

Later on I take a json payload object and sign it using jwt.encode(), providing it the decoded privatekey.

Then I make a requests request like so:

response = requests.post('https://<sampleapiendpoint>', headers={"Content-Type": "text/xml"}, data=signed_payload, timeout=60)

The problem is when I run the script with python2, it will error out:

Traceback (most recent call last):
  File "apirequest.py", line 171, in <module>
    response = requests.post('https://<sampleapiendpoint>', headers={"Content-Type": "text/xml"}, data=signed_payload, timeout=60)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/requests/api.py", line 108, in post
    return request('post', url, data=data, json=json, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/requests/api.py", line 50, in request
    response = session.request(method=method, url=url, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/requests/sessions.py", line 464, in request
    resp = self.send(prep, **send_kwargs)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/requests/sessions.py", line 576, in send
    r = adapter.send(request, **kwargs)
  File "/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/requests/adapters.py", line 431, in send
    raise SSLError(e, request=request)
requests.exceptions.SSLError: [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:727)

If I use python3 I get the following callstack:

    Traceback (most recent call last):
  File "/Users/<username>/Projects/<folder>/<folder2>/apicall.py", line 94, in <module>
    class Pkcs12Context(requests.packages.urllib3.contrib.pyopenssl.OpenSSL.SSL.Context):
AttributeError: module 'requests.packages.urllib3.contrib' has no attribute 'pyopenssl'

I have tried uninstalling and reinstalling pyopenssl to no avail. I have tried both python2 and python3, neither work. I do suspect however that the python2 one is working, but there's something wrong with the certs/keys so that the handshake never succeeds (which means its a script or endpoint configuration problem). I have also tried a potential solution described on a forum at https://github.com/certbot/certbot/issues/6328, where they say to try to use requests 2.6.0, which I am. Is the python2 version actually working, but there's a cert/key configuration problem with the api endpoint? And why doesn't the python3 version work?

Here is the output of the pip freeze command:

certifi==2021.10.8
cffi==1.15.0
charset-normalizer==2.0.12
cryptography==36.0.1
idna==3.3
pycparser==2.21
PyJWT==2.3.0
pyOpenSSL==22.0.0
requests==2.6.0
urllib3==1.26.8

CodePudding user response:

I could not solve this issue directly. Instead it was solved with the following approach. Instead of creating a Pkcs12Context, we just don't do that at all, and use the certs argument of the requests.posts method to provide the certs to the request call.

response = requests.post('https://<url>',
                         cert=(SSL_CERTIFICATE_FILENAME, SSL_CERTIFICATE_PVKEY_FILENAME),
                         headers={"Content-Type": "text/xml"}, data=encoded, timeout=60)
  • Related