Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Certifi support for websockets #69

Closed
sargun opened this issue Aug 2, 2020 · 5 comments
Closed

Add Certifi support for websockets #69

sargun opened this issue Aug 2, 2020 · 5 comments

Comments

@sargun
Copy link
Contributor

sargun commented Aug 2, 2020

Is your feature request related to a problem? Please describe.
If you're on OS X, the default SSL library that the websockets client uses doesn't have a cert for the TD Ameritrade streaming endpoint.

Describe the solution you'd like
Instead of using the default store, use certifi. Code wise, this looks something like:

import ssl, certifi

ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLS_CLIENT)
ssl_context.load_verify_locations(cafile=certifi.where())

# And then when we connect:
```python3
self._socket = await websockets.client.connect(wss_url, ssl=ssl_context)

Additional context
We can alternatively use certitude for OS X users: https://github.com/python-hyper/certitude and explain to people how to load their stuff into the cert chain.

My suggestion is just make it so you can pass a custom SSL context to StreamClient.

@sargun
Copy link
Contributor Author

sargun commented Aug 2, 2020

P.S. I'm willing to submit the PR if you're open to the idea, just let me know what route you would prefer.

@alexgolec
Copy link
Owner

What symptoms are you encountering? Are you finding the websocket doesn't create a connection or downgrades to not using TLS?

Also, I could use some more context on this, but it feels like a useful contribution and I'm happy to review a PR.

@sargun
Copy link
Contributor Author

sargun commented Aug 2, 2020

The context is: slackapi/python-slack-sdk#334. Basically, the cert bundle which is used by the websockets library on Mac doesn't have the requisite root certificate for me.

So, you get an error like:

Traceback (most recent call last):
  File "prep3.py", line 31, in <module>
    asyncio.get_event_loop().run_until_complete(read_stream())
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/base_events.py", line 587, in run_until_complete
    return future.result()
  File "prep3.py", line 22, in read_stream
    await stream_client.login()
  File "/Users/sdhillon/repos/options/venv/lib/python3.7/site-packages/tda/streaming.py", line 338, in login
    await self._init_from_principals(r)
  File "/Users/sdhillon/repos/options/venv/lib/python3.7/site-packages/tda/streaming.py", line 197, in _init_from_principals
    self._socket = await websockets.client.connect(wss_url)
  File "/Users/sdhillon/repos/options/venv/lib/python3.7/site-packages/websockets/client.py", line 535, in __await_impl__
    transport, protocol = await self._create_connection()
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/base_events.py", line 989, in create_connection
    ssl_handshake_timeout=ssl_handshake_timeout)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/base_events.py", line 1017, in _create_connection_transport
    await waiter
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/sslproto.py", line 530, in data_received
    ssldata, appdata = self._sslpipe.feed_ssldata(data)
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/asyncio/sslproto.py", line 189, in feed_ssldata
    self._sslobj.do_handshake()
  File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ssl.py", line 774, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1091)

My suggestion is that we allow users to pass a custom ssl_context on creation of StreamClient.

sargun added a commit to sargun/tda-api that referenced this issue Aug 3, 2020
The websockets client on OS X doesn't include a full set of root
certificates to be completely useful. This allows users to supply
their own ssl_context object that the websockets function can use.

Solves issue:
alexgolec#69
sargun added a commit to sargun/tda-api that referenced this issue Aug 4, 2020
The websockets client on OS X doesn't include a full set of root
certificates to be completely useful. This allows users to supply
their own ssl_context object that the websockets function can use.

Solves issue:
alexgolec#69
sargun added a commit to sargun/tda-api that referenced this issue Aug 4, 2020
The websockets client on OS X doesn't include a full set of root
certificates to be completely useful. This allows users to supply
their own ssl_context object that the websockets function can use.

Solves issue:
alexgolec#69
alexgolec pushed a commit that referenced this issue Aug 4, 2020
…#74)

The websockets client on OS X doesn't include a full set of root
certificates to be completely useful. This allows users to supply
their own ssl_context object that the websockets function can use.

Solves issue:
#69
@sargun sargun closed this as completed Aug 7, 2020
@rmarnold
Copy link

The following command worked for me "/Applications/Python\ 3.8/Install\ Certificates.command"

@janice-andrews
Copy link

The following command worked for me "/Applications/Python\ 3.8/Install\ Certificates.command"

Yeah tried this, and I am still experiencing the error

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants