Reputation: 23
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
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
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