Python + OSX OpenSSL Issue

I recently ran into an issue with the requests library in Python and TLS 1.1 and 1.2. I was trying to build out some scripts to configure some stuff in Cisco ACI but was getting errors when using HTTPS. Using HTTP, the script would execute just fine. Okay so that’s pretty obvious that the issue is around the encryption bits, but my good friend Google kind of let me down while searching for a fix. So I started dorking about in ACI to see if there was anything I could do (who knows what!), and experimented with disabling TLS 1.1 and 1.2, leaving only TLS 1.0 enabled. This got me an SSLv3 error about invalid cert I believe. I started going down the path of forcing my script to use SSLv2 but got stymied pretty quickly there by my lack of Python skills. Okay so flipping TLS 1.1 and 1.2 back on I got a different error than with 1.0 on – which I guess is a good thing since its something new to search on… that error was about “connection error: error 54” or something like that. Eventually I tested this same script out on an Ubuntu 15.10 box and it worked (with TLS 1.2) no problem… okay so whats the difference between OSX and Ubuntu? Python was the same version on both boxes, so that ruled that out, same script, so no issue there, what else? After a bit of thinking (and Googling) I realized that it wasn’t any of those things, but the problem lied with OpenSSL! On my Macbook, I ran the command:

openssl version


This just displays the version – I was getting something like this:

OpenSSL 0.9.8zg 14 July 2015


Doesn’t take much Googling to realize that is a bit old since we are in 2016! So I started trying to figure out how to update that, turns out its nice and easy with brew:

brew update
brew install openssl


This installed the new version for me, but when I checked the version again it was still using the old one. So some more Googling and I discovered how to force the new version:

brew link openssl --force


Note that until the terminal window gets closed it will still show the old version when you do:

openssl version


After opening a new terminal window I’m showing:

OpenSSL 1.0.2f 28 Jan 2016


However I was still having issues with Python not connecting to my APIC. Turns out that Python was stuck tied to an older version, you can check that by hopping into the interpreter and importing the SSL library:

python
>>> import ssl
>>> print ssl.OPENSSL_VERSION
OpenSSL 0.9.8zg 14 July 2015
>>> exit()


Okay, so that’s not cool. Guess Python is compiled against the older version, so lets update that and hook it to the newer OpenSSL:

brew install python --with-brewed-openssl


Now Python OpenSSL Version should be good:

python
>>> import ssl
>>> print ssl.OPENSSL_VERSION
OpenSSL 1.0.2f 28 Jan 2016
>>> exit()


For some reason had to close out of terminal and load it back up then things worked. I also unlinked openssl with:

brew unlink openssl


Not entirely sure that’s needed or maybe I just wasn’t supposed to do that in the first place :) In any case, my scripts are now working on my Macbook with TLS 1.1 and 1.2!

Hopefully this will help somebody else out since it took me entirely too long to figure this all out!