Reputation: 141
I've been trying to test Requests SSL verification using a self-signed cert and setting that as the verify param CA bundle. Instead of the test passing, I get [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:590)
.
Here is my test code:
class TestSubjectVerification(HttpTestSupport):
@classmethod
def setUpClass(cls):
cls.https_port = get_random_port()
cls.httpsd = server.HTTPServer(('', cls.https_port), Handler)
cls.httpsd.socket = ssl.wrap_socket(cls.httpsd.socket,
certfile=os.path.join(TEST_RESOURCES_DIR, "certificate.pem"),
keyfile=os.path.join(TEST_RESOURCES_DIR, "private.key"),
server_side=True)
Thread(target=cls.httpsd.serve_forever).start()
def test_hello(self):
port = self.__class__.https_port
ca = os.path.join(TEST_RESOURCES_DIR, "certificate.pem")
r = requests.get("https://127.0.0.1:%s" % port, verify=ca)
self.assertEqual("hello", r.text)
I created my key and cert with the following openssl commands (referencing this stackoverflow post):
openssl genrsa -out private.key 3072
openssl req -new -x509 -key private.key -sha256 -out certificate.pem -days 730
Customizing openssl.cnf, I specified 127.0.0.1 as an IP subjectAltName. Examining the certificate:
$ openssl x509 -in certificate.pem -text -noout
Certificate:
Data:
Version: 3 (0x2)
Serial Number: 15231302753528708005 (0xd3607527ca81fba5)
Signature Algorithm: sha256WithRSAEncryption
Issuer: C=US, ST=North Carolina, L=Durham, O=Foo Company, OU=Foo Org, CN=Craig McDaniel/[email protected]
Validity
Not Before: Apr 18 19:40:03 2017 GMT
Not After : Apr 18 19:40:03 2019 GMT
Subject: C=US, ST=North Carolina, L=Apex, O=DataStax, OU=OpsCenter, CN=Craig McDaniel/[email protected]
Subject Public Key Info:
Public Key Algorithm: rsaEncryption
Public-Key: (3072 bit)
Modulus:
00:e7:3a:b0:b9:28:bd:e1:d0:74:9f:4b:a7:9b:f6:
fe:ba:7e:58:da:05:fc:b4:b7:9c:fc:7a:1f:c4:d5:
02:09:77:94:14:07:d6:dd:e3:59:ad:09:fc:e1:79:
c5:5d:7f:6e:56:ca:08:21:f3:af:c1:0d:31:c5:aa:
2d:78:e9:2f:26:79:0e:76:f9:64:77:9e:94:32:4b:
09:c0:3b:15:d0:64:b0:58:85:53:96:e4:f0:ac:da:
b1:f4:e3:17:dc:6d:ba:94:e7:49:88:dd:fe:f7:a7:
ac:36:4b:3e:07:4b:d0:dc:c1:ae:54:56:a5:4e:8e:
89:0b:63:a1:0f:10:12:25:3b:11:0c:8a:a4:03:3d:
ef:67:4f:0c:2b:3c:d9:f3:a6:b4:eb:e1:d4:e5:d0:
12:45:c6:6a:42:d3:a0:c7:c0:2e:e5:c7:95:17:98:
8b:9d:d7:32:f5:a4:87:5a:b5:77:86:91:44:0c:82:
f7:94:31:dc:f5:5c:5e:bc:82:73:de:e5:31:84:e3:
99:af:bd:7f:80:15:61:cd:f9:5a:85:ae:3a:96:fb:
36:27:51:c2:ee:37:8b:65:61:47:f6:9f:0c:8f:1d:
d2:a2:99:de:a9:a9:d5:30:04:55:8e:27:d2:c1:cf:
ec:b3:3e:47:7b:5a:b6:ac:92:1b:56:0f:65:81:f3:
22:97:96:15:9a:0c:a7:8f:ca:72:6b:90:c4:0e:dc:
d8:e2:d4:36:32:8e:fd:94:35:a4:b6:44:75:32:3d:
8a:7a:96:bc:bc:00:6a:1f:ef:a2:93:29:7f:6a:95:
87:47:5b:af:99:88:3d:57:ea:c7:9a:8b:57:b1:a3:
5f:26:f6:4e:f8:68:9d:ed:a7:ae:f3:97:20:46:c4:
e8:a2:c6:e4:f1:d2:92:1d:9a:08:fa:24:f0:cf:42:
74:d6:ed:e2:68:36:2e:dc:5a:6e:e0:ae:33:5e:c1:
c1:79:37:a8:49:b7:a3:79:46:40:3c:3b:e5:1b:a2:
93:23:04:f9:4b:1e:9d:4f:04:f7
Exponent: 65537 (0x10001)
X509v3 extensions:
X509v3 Subject Key Identifier:
08:80:0D:CF:99:29:C4:25:4A:1E:BE:E8:B1:86:F7:83:1E:1C:98:BD
X509v3 Authority Key Identifier:
keyid:08:80:0D:CF:99:29:C4:25:4A:1E:BE:E8:B1:86:F7:83:1E:1C:98:BD
X509v3 Basic Constraints:
CA:TRUE
X509v3 Key Usage:
Digital Signature, Key Encipherment
X509v3 Subject Alternative Name:
IP Address:127.0.0.1
Signature Algorithm: sha256WithRSAEncryption
54:53:a9:f8:ba:1d:7d:ed:f8:b6:be:c3:46:38:cf:3a:f8:b1:
25:25:c5:66:c6:d7:b1:eb:7a:c4:4d:0a:55:a2:89:82:31:13:
37:14:d2:5e:5c:e8:a5:2b:f9:ba:0f:02:21:cd:b8:f7:57:36:
31:48:8a:8c:a8:04:cd:26:90:e9:7a:99:ab:ec:6d:bf:40:1a:
d7:6f:37:6d:6c:11:73:5e:44:c3:cd:97:0d:cc:9d:78:91:1e:
26:8f:48:40:c8:7e:5d:10:f1:35:1b:1e:04:ea:c0:be:54:14:
39:01:33:86:e9:e3:2a:cc:55:9d:cd:95:eb:74:ab:3b:e2:f1:
87:ce:1e:dd:50:ac:00:28:8e:71:89:87:78:e9:e0:ba:52:6f:
05:1c:13:7e:9c:32:77:da:f0:b2:34:05:02:df:3f:95:2a:57:
96:d5:22:59:c1:e3:c5:45:80:da:01:15:e2:fa:5d:e6:f2:88:
97:09:a1:3d:5c:81:85:ce:34:f9:d2:21:59:f5:40:50:b5:59:
09:78:41:8f:99:03:aa:5c:70:e9:ee:95:4d:48:3c:09:e8:bf:
55:dd:9a:21:4e:f1:2b:4e:bb:7e:5a:c0:9b:5d:dc:57:0b:0b:
f6:55:18:bc:53:4a:d1:15:41:02:4a:1c:33:ae:c6:ec:eb:66:
ca:aa:17:05:f9:2d:99:b7:c6:73:5e:2b:9d:0b:30:16:ab:b3:
06:5b:f5:79:91:a4:f8:2a:4e:19:87:33:50:7d:c4:23:0d:39:
6d:4e:2b:88:59:55:77:d4:b5:bd:a3:4f:1c:b8:18:e4:56:07:
13:ef:57:ce:9e:67:60:55:1d:0d:42:ea:27:50:07:fa:f9:30:
fd:69:5c:39:ba:cf:36:a1:f7:e0:ff:69:8b:38:41:f1:4c:7d:
39:ac:25:a9:41:ed:2b:c7:b9:88:0f:1e:d0:12:50:c8:ba:4a:
5e:07:d7:12:77:c7:68:09:8f:37:be:b8:a3:d4:e2:ea:9d:88:
36:25:df:f6:3c:f8
Also, curl seems to validate the cert just fine and prints the response (though it gives some other error):
curl --cacert /path/to/my/certificate.pem https://127.0.0.1:8443/
curl: (56) GnuTLS recv error (-110): The TLS connection was non-properly terminated.
hello
curl https://127.0.0.1:8443/
curl: (60) server certificate verification failed. CAfile: /etc/ssl/certs/ca-certificates.crt CRLfile: none
Upvotes: 3
Views: 2284
Reputation: 123320
My guess is that you are using Python 2.7. According to the source code of ssl.py only DNS entries in subject alternative names are checked which means your IP address entry is simply ignored. This seems to be valid even in the latest version of Python 2.7, i.e. 2.7.13.
With Python 3 this is fixed. According to ssl.py in Python 3.5 it will specifically check the IP address type in subject alternative names.
This means you either have to use a DNS entry instead of the IP address entry which although wrong works with Python 2.7 but stops working with Python 3. Or you can use Python 3 instead. Or use a hostname.
Upvotes: 1