I have the following minimal file:
import requests
index_response = requests.get("https://my.end.point.com/", cert="mypem.pem")
print(index_response.status_code)
Python 2.7.15 (v2.7.15:ca079a3ea3, Apr 30 2018, 16:30:26) [MSC v.1500 64 bit (AMD64)] on win32
gives a response of 200Python 2.7.15 (default, Jun 3 2019, 14:08:52) [GCC 4.8.4] on
linux2
gives a response of 403Both use Python 2.7.15 and there's no error displayed, so I’m not clear on where to start looking. I appreciate this isn’t an easily reproducible example; if there are any example PEM/endpoints I can use, I’d be happy to edit my question.
First, as @wowkin2 mentioned, make sure you use the same versions of requests and urllib3 on your two computers. I'm using requests==2.22.0 and urllib3==1.25.7 here.
And please consider switching to Python 3, Python 2 support ends in January 2020.
OK, so if you have the same versions but still see the issue, let's try to debug it by first using another client certificate. badssl.com is a TLS test service who provides such a client certificate. Testing with badssl.com is more complicated than it should be because it uses a password and requests does not support that out of the box, but here's how you can do it:
import requests
from requests.adapters import HTTPAdapter
from urllib3.poolmanager import PoolManager
class ClientCertPasswordAdapter(HTTPAdapter):
def __init__(self, password):
self.password = password
super(ClientCertPasswordAdapter, self).__init__()
def init_poolmanager(self, connections, maxsize, block=False):
self.poolmanager = PoolManager(
num_pools=connections,
maxsize=maxsize,
block=block,
key_password=self.password,
)
print("fetching client certificate")
with open("client.pem", "wb") as f:
r = requests.get("https://badssl.com/certs/badssl.com-client.pem")
f.write(r.content)
print("requesting data")
s = requests.Session()
s.mount("https://client.badssl.com/", ClientCertPasswordAdapter("badssl.com"))
r = s.get("https://client.badssl.com/", cert="client.pem")
print(r.status_code)
Does this print 200 for your two OSes? This would allow to rule out an issue in your certificate.
Another test you can make is to use your client certificate and give it to a server that won't verify it but will print you the public information it received. I'm sending the badssl.com client certificate here:
import requests
from requests.adapters import HTTPAdapter
from urllib3.poolmanager import PoolManager
class ClientCertPasswordAdapter(HTTPAdapter):
def __init__(self, password):
self.password = password
super(ClientCertPasswordAdapter, self).__init__()
def init_poolmanager(self, connections, maxsize, block=False):
self.poolmanager = PoolManager(
num_pools=connections,
maxsize=maxsize,
block=block,
key_password=self.password,
)
print("fetching client certificate")
with open("client.pem", "wb") as f:
r = requests.get("https://badssl.com/certs/badssl.com-client.pem")
f.write(r.content)
print("requesting data")
s = requests.Session()
s.mount("https://server.cryptomix.com/", ClientCertPasswordAdapter("badssl.com"))
r = s.get("https://server.cryptomix.com/secure/", cert="client.pem")
print(r.status_code)
print(r.text)
This should print debug information including SSL_CLIENT
information:
[SSL_CLIENT_S_DN_C] => US
[SSL_CLIENT_S_DN_ST] => California
[SSL_CLIENT_S_DN_L] => San Francisco
[SSL_CLIENT_S_DN_O] => BadSSL
[SSL_CLIENT_S_DN_CN] => BadSSL Client Certificate
[SSL_CLIENT_I_DN_C] => US
[SSL_CLIENT_I_DN_ST] => California
[SSL_CLIENT_I_DN_L] => San Francisco
[SSL_CLIENT_I_DN_O] => BadSSL
[SSL_CLIENT_I_DN_CN] => BadSSL Client Root Certificate Authority
[SSL_CLIENT_VERIFY] => GENEROUS
[SSL_CLIENT_M_VERSION] => 3
[SSL_CLIENT_M_SERIAL] => 2B936CE32D82CE8B01FD9A0595AC6366AA014C82
[SSL_CLIENT_V_START] => Nov 27 00:19:57 2019 GMT
[SSL_CLIENT_V_END] => Nov 26 00:19:57 2021 GMT
[SSL_CLIENT_V_REMAIN] => 730
[SSL_CLIENT_S_DN] => CN=BadSSL Client Certificate,O=BadSSL,L=San Francisco,ST=California,C=US
[SSL_CLIENT_I_DN] => CN=BadSSL Client Root Certificate Authority,O=BadSSL,L=San Francisco,ST=California,C=US
[SSL_CLIENT_A_KEY] => rsaEncryption
[SSL_CLIENT_A_SIG] => sha256WithRSAEncryption
[SSL_CLIENT_CERT_RFC4523_CEA] => { serialNumber 248774298121081469895139733087446207053965642882, issuer rdnSequence:"CN=BadSSL Client Root Certificate Authority,O=BadSSL,L=San Francisco,ST=California,C=US" }
Do you see the same values with your two OSes?