Overcoming TLS Frustrations with Python and macOS Sierra

The short version of this is that you probably want to upgrade to High Sierra (macOS 10.13) if you need to do much of anything with the built-in macOS version of Python and any network tasks.

Some would say: “Why don’t you just install your own, more current, copy of Python?”

Two main reasons:

  1. You are using code that is linked directly to the Apple supplied Python framework (this is true for the bBox FileMaker plug-in)
  2. You want to use things like the Objective-C bindings, which are only in the Apple supplied version of Python

For more information on some things I’ve tried, and a possible workaround for pip upgrade issues, read more below.

If you are using the macOS-supplied copy of Python, you may find that previously-working code fails if using SSL connections. This is largely due to older protocols (SSL v2, etc.) being disabled due to security concerns on servers.

The problem is largely caused by Python being linked to an older version of the OpenSSL library on any OS versions older than macOS High Sierra. We can check this like so:

For Sierra, we get “OpenSSL 0.9.8zh 14 Jan 2016” as the output.¬†Unfortunately, TLS 1.2 was not added until OpenSSL version 1.0.1.

Some posts I read online seemed to suggest that upgrading Requests, and perhaps some other modules, would help. I then discovered that both easy_install and pip were broken too:

To install or fix pip, I found that you can bootstrap yourself into the latest version  by running the following as root:

Great, so now I can install a current version of the Requests module with pip. But based on some reading, I’d probably want to install using the “secure” option. Using that led to more errors (only showing significant errors below):

This seems to be yet another rabbit hole, not directly related to the OpenSSL version dependencies. OK, so now installing Requests without the secure option. However, now I get this error when I try to connecting to a server requiring TLS 1.1+:

Trying another suggested tack, I attempted to work around this by using the HttpAdapter class with the Requests module but I found that the SSL class does not even define the constants for the newer protocols:

I may test a few further workarounds later, but it’s really looking like network related tasks are a lost cause for this configuration, with the only bright side being that pip can at least be fixed.

  • Simon

Leave a Reply