smartsheet-platform / smartsheet-python-sdk

Library that uses Python to connect to Smartsheet services (using API 2.0).
Apache License 2.0
136 stars 81 forks source link

smartsheet client SSLError #158

Open pruv opened 3 years ago

pruv commented 3 years ago

I am using python 3.7 and other libraries are listed below smartsheet-python-sdk: 2.105.1 certifi: 2020.12.5 requests: 2.25.1 urllib3: 1.26.2

Below code gives me ssl handshake exception.

smart = smartsheet.Smartsheet(access_token)
smart.Users.get_current_user()
smartsheet.exceptions.HttpError: (SSLError(MaxRetryError("HTTPSConnectionPool(host='api.smartsheet.com', port=443): Max retries exceeded with url: /2.0/users/me (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1056)')))")), 'SSL handshake error, old CA bundle or old OpenSSL?')

I browsed existing issues but none of the suggestions (like trying different versions of above mentioned libraries, etc) helped fixing the issue.

I was able to get it working by creating my own child class and control the http session. I see the code where http client session is being created here https://github.com/smartsheet-platform/smartsheet-python-sdk/blob/master/smartsheet/smartsheet.py#L154 https://github.com/smartsheet-platform/smartsheet-python-sdk/blob/master/smartsheet/session.py#L50

Can you please enhance Smartsheet class constructor to accept Session object so that user can control http/ssl level configuration.

rnag commented 2 years ago

@pruv Good day, unfortunately I'm also running into the same issue on my terminal (using latest version of both requests and smartsheet-python-sdk==2.105.1). Would you be able to share more details about a potential solution to work around the SSL error?

rnag commented 2 years ago

It's not pretty, but I managed to resolve it - or at least patch it, temporarily 🤷 . For clarification, the issue in our case is we need to use a custom SSL cert for outbound requests, otherwise everything breaks (don't ask 😅 ). So we've already set all required env variables already - like AWS_CA_BUNDLE, REQUESTS_CA_BUNDLE, and NODE_EXTRA_CA_CERTS. The problem is that the Smartsheet SDK doesn't seem to honor the REQUESTS_CA_BUNDLE variable.

So i'm currently using the below workaround, that seems to resolve it at least when running from our local (not deployed elsewhere, like on AWS for example):

import os
path_to_ca_file = os.getenv('REQUESTS_CA_BUNDLE')

if path_to_ca_file:
    from smartsheet.session import _SSLAdapter
    import ssl

    def create_ssl_context(self):
        ctx = ssl.create_default_context(cafile=path_to_ca_file)

        ctx.options |= ssl.OP_NO_SSLv2
        ctx.options |= ssl.OP_NO_SSLv3
        ctx.options |= ssl.OP_NO_TLSv1
        return ctx

    _SSLAdapter.create_ssl_context = create_ssl_context

As original issue above mentions, it would be great if we can enhance Smartsheet SDK to allow the user to control http/ssl level configuration.