Peyton Chenault
Peyton Chenault

Reputation: 23

Certificate Verify Failed when using Requests in Python with a self signed certificate

I'm using python to access Aruba switches through an API. I'm wanting to use HTTPS so that my traffic (that is sending usernames and passwords for verification) is encrypted:

import requests
import json
import base64
from requests.packages.urllib3.exceptions import InsecureRequestWarning
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
import certifi

url = 'https://10.4.10.10/rest/v3/'
creds = {'userName': 'username', 'password': 'password'}
command = 'show config'

s = requests.Session()
r = s.post(url + 'login-sessions', data=json.dumps(creds), timeout=1)
print(r.json())
cookie_response = r.json()['cookie']
if r.status_code != 201:
    print('Login error, status code {}'.format(r.status_code))

I generated a self signed certificate in the CLI and then was able to grab it by putting the ip address into chrome (with https:// in front of it) and then downloading the certificate file. I had to use openssl to convert the certificate file type into a .pem. Finally, I opened the file in a text editor and added the certificate to the end of the cacert.pem file that is used by the Requests module. After doing all this, I still get the following error:

ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1076)

I've searched all over, but still can't find a solution. Any help or ideas would be greatly appreciated! Thanks!

-EDIT-

Here is the contents of the certificate I am using:

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            17:13:91:1c:86:72:ae:bd:01:27:28:39:8f:4e:5a:2d:18:ae:1f:04
        Signature Algorithm: sha256WithRSAEncryption
        Issuer: CN=testSwitch, OU=OCSwitch, O=OC, L=Edmond, ST=Oklahoma, C=US
        Validity
            Not Before: Jun 16 10:59:12 2020 GMT
            Not After : Jun 16 23:59:59 2021 GMT
        Subject: CN=testSwitch, OU=OCSwitch, O=OC, L=Edmond, ST=Oklahoma, C=US
        Subject Public Key Info:
            Public Key Algorithm: rsaEncryption
            RSA Public Key: (1024 bit)
                Modulus (1024 bit):
                    00:be:6a:27:02:f5:6a:98:19:0f:db:c7:11:26:dd:
                    77:26:bd:18:ef:ab:62:53:3e:13:a1:61:b0:5a:88:
                    77:d8:ba:81:56:2a:7d:66:0a:2c:cd:f1:78:4b:35:
                    61:73:31:4c:4f:80:51:21:86:bf:2c:1c:95:87:cc:
                    e7:5f:47:d8:d8:6e:ed:d4:4f:56:79:24:01:65:c9:
                    72:cb:6c:7a:55:ef:9b:1b:ae:4e:28:8f:27:50:1d:
                    36:08:c3:85:67:2c:8a:1a:42:15:83:d2:e3:b3:ef:
                    d3:ce:cd:77:d5:3f:25:f5:b3:c1:ce:e8:7c:e1:cb:
                    fc:c5:12:e8:0a:d0:87:1b:4d
                Exponent: 65537 (0x10001)
        X509v3 extensions:
            X509v3 Key Usage: critical
                Digital Signature, Key Encipherment, Key Agreement
            X509v3 Extended Key Usage: 
                TLS Web Server Authentication
    Signature Algorithm: sha256WithRSAEncryption
        51:01:6c:13:40:8a:73:70:96:71:ea:b1:4b:b1:36:c3:82:ed:
        2b:3a:d8:b3:23:77:6e:bb:56:d5:71:56:ff:0a:66:4f:81:69:
        ef:33:9e:1f:ff:20:3e:49:70:c4:8b:c9:92:65:ce:80:78:62:
        0e:e4:8e:39:ee:e0:04:6d:73:67:41:1a:dd:1e:ec:19:af:45:
        0b:f3:4b:2e:88:10:5e:c1:89:6b:37:d1:12:a7:23:e1:86:94:
        4f:b2:8a:fd:62:d6:33:5f:14:62:50:2e:38:0f:b1:46:55:ad:
        46:71:df:b3:6d:44:48:c9:72:f5:0b:0a:13:ed:9a:2f:05:5c:
        05:0b

I've modified my code by importing ssl and using ssl.get_server_certificate():

import ssl

cert = ssl.get_server_certificate(('10.4.10.10', 443))
with open('cert.pem', 'w') as file:
    file.write(cert)

I then point to 'cert.pem' with verify= and still get the same error.

Upvotes: 2

Views: 3988

Answers (2)

Steffen Ullrich
Steffen Ullrich

Reputation: 123531

    X509v3 extensions:
        X509v3 Key Usage: critical
            Digital Signature, Key Encipherment, Key Agreement
        X509v3 Extended Key Usage: 
            TLS Web Server Authentication

This is a leaf certificate and not a CA certificate (no basic constraints CA:true). OpenSSL historically requires the trust anchor for verification to be a self-signed CA certificate though.

This is changed only with newer versions (OpenSSL 1.0.2 and later) when the option X509_V_FLAG_PARTIAL_CHAIN is used in certificate verification. In this case an arbitrary CA certificate in the CA store would work as trust anchor and also self-signed certificates without CA:true seem to work.

Unfortunately this flag is not exposed in Python yet and I see no way to specify custom verify options or a custom context with special verify options to requests. With other libraries this might be more doable, see Python WWS Library requires entire certificate chain to verify server.

Upvotes: 1

Sreekumar
Sreekumar

Reputation: 151

Could you check if the certificates were imported from the root level to the bottom of the chain? Also, try to pass the path to the certificate file in the requests function to see if the certificate works:

r = s.post(url, data=data, verify='/path/to/public_key.pem')

Upvotes: 1

Related Questions