In Python3.6.5 Requests getting SSL Certificate Error - web-scraping

I had try to get the following URL using requests, but am getting an SSL certificate Error. I had tried all earlier Stack overflow Queries but nothing seems working
Code:
resp = requests.get('https://www.magidglove.com/', verify=certifi.where())
I had given verify=False, still not works
Error:
raise MaxRetryError(_pool, url, error or ResponseError(cause))urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='www.magidglove.com', port=443): Max retries exceeded with url: / (Caused by SSLError(SSLError("bad handshake: Error([('SSL routines', 'tls_process_server_certificate', 'certificate verify failed')],)",),))

TL;DR - The server is misconfigured. Either fix the server, pass verify=ssl.CERT_NONE, or download and pass www.magidglove.com's certificate explicitly.
The problem here is on the server, not the client. The server is only configured to return it's own certificate, which isn't enough for the client to trust it. Servers generally need to be configured to return the full certificate chain.
In order to diagnose this, you can use openssl to view some raw information about the certificate chain returned:
$ openssl s_client -connect www.google.com:443 -showcerts -servername www.google.com
CONNECTED(00000003)
depth=2 OU = GlobalSign Root CA - R2, O = GlobalSign, CN = GlobalSign
verify return:1
depth=1 C = US, O = Google Trust Services, CN = Google Internet Authority G3
verify return:1
depth=0 C = US, ST = California, L = Mountain View, O = Google LLC, CN = www.google.com
verify return:1
... snipped the rest of the output ...
You can see that 3 certificates were returned by the server, and they were verified in reverse order. The GlobalSign certificate is trusted by the certifi library, the cert at depth=1 was created by the cert at depth=2, and the last cert, CN=www.google.com, was created by the cert at depth=1.
Now let's compare that to the server you were trying to connect to:
$ openssl s_client -connect www.magidglove.com:443 -showcerts -servername www.magidglove.com
CONNECTED(00000003)
depth=0 businessCategory = Private Organization, jurisdictionC = US, jurisdictionST = Illinois, serialNumber = 00043176, C = US, ST = Illinois, L = Romeoville, O = "Magid Glove and Safety Manufacturing Company, L.L.C.", OU = web site, CN = www.magidglove.com
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 businessCategory = Private Organization, jurisdictionC = US, jurisdictionST = Illinois, serialNumber = 00043176, C = US, ST = Illinois, L = Romeoville, O = "Magid Glove and Safety Manufacturing Company, L.L.C.", OU = web site, CN = www.magidglove.com
verify error:num=21:unable to verify the first certificate
verify return:1
You can see a few things from this output:
- The server only returned a single certificate
- The client tried to verify the certificate and couldn't
It requires some knowledge of ssl to know that the reason why it couldn't verify was that it doesn't trust the certificate, but now that we know that, we can see that having the server return the full certificate chain will fix that. I suspect that the reason why chrome and other browsers don't report an error is that the browser itself knows about DigiCert, so it doesn't require a full chain.

This problem can easily be solved by adding importing the ssl to your python code and adding verify=ssl.CERT_NONE so your code should look something like this:
import requests
import ssl
resp = requests.get('https://www.magidglove.com/', verify=ssl.CERT_NONE)
That being said when running this code you might come across this error:
/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/urllib3/connectionpool.py:858: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
which you could disable by adding the following lines to your code:
import requests
import ssl
import urllib3
urllib3.disable_warnings()
resp = requests.get('https://www.magidglove.com/', verify=ssl.CERT_NONE)
Hope this helps!

Related

api.loganalytics.io unable to get local issuer certificate

I've been using the code based on the snipped below for several months and it worked.
import requests
resp = requests.get(
'https://api.loganalytics.io',
# verify=False
)
Now I have an error:
File "C:....virtualenvs\pythonProject-XaZ9hdp4\lib\site-packages\requests\adapters.py", line 563, in send
raise SSLError(e, request=request)
requests.exceptions.SSLError: HTTPSConnectionPool(host='api.loganalytics.io', port=443): Max retries exceeded with url: / (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:997)')))
I checked SSL certificate for api.loganalytics.io with third-party online service and it looks like everything is OK with its SSL certificate.
I created new Python project and re-install requests and certifi in new virtual environment.
What kind of another certificate can be meant in this error message? How can I find and update it?
I work under Windows 10.
import requests
resp = requests.get(
'https://api.loganalytics.io',
# verify=False
)
In this code we need change Verify = false to verify=ssl.CERT_NONE
import requests
resp = requests.get(
'https://api.loganalytics.io',
verify=ssl.CERT_NONE
)
if you have any ssl certificate you can use this
s = requests.Session()
s.cert = '/path/client.cert'

gRPC unable to create connection to server (Go) from client (Python)

I have this Python code that is supposed to use a certificate and connect to a server via the server's IP address (no FQDN available) but I get an error every time I try it:
ssl_transport_security.cc:222] LOOP - TLS client process_change_ciph - !!!!!!
ssl_transport_security.cc:222] LOOP - TLS client read_server_finishe - !!!!!!
ssl_transport_security.cc:222] LOOP - TLS client finish_client_hands - !!!!!!
ssl_transport_security.cc:222] LOOP - TLS client done - !!!!!!
ssl_transport_security.cc:222] HANDSHAKE DONE - TLS client done - !!!!!!
security_handshaker.cc:184] Security handshake failed: {"created":"#1582052112.923538253","description":"Peer name 172.18.0.14 is not in peer certificate","file":"src/core/lib/security/security_connector/ssl/ssl_security_connector.cc","file_line":55}
subchannel.cc:1003] Connect failed: {"created":"#1582052112.923538253","description":"Peer name 172.18.0.14 is not in peer certificate","file":"src/core/lib/security/security_connector/ssl/ssl_security_connector.cc","file_line":55}
subchannel.cc:940] Subchannel 0x55ad70542020: Retry immediately
subchannel.cc:967] Failed to connect to channel, retrying
From what I understand this could be due to me connecting to an ip address and not a FQDN but these are servers and I only have access to IP addresses. Any idea how to overcome this?
Python code used:
def get_secure_channel(host, port):
if os.environ.get('https_proxy'):
del os.environ['https_proxy']
if os.environ.get('http_proxy'):
del os.environ['http_proxy']
with open(os.path.join(settings.DJANGO_ROOT, '../grpc_proto/cert/server.crt'), 'rb') as f:
cert = f.read()
credentials = grpc.ssl_channel_credentials(root_certificates=cert)
return grpc.secure_channel('{}:{}'.format(host, port), credentials)
def reset_client(channel, ip_address):
stub = dnsadblock_pb2_grpc.DnsadblockServiceStub(channel)
return stub.ResetClient(dnsadblock_pb2.ResetClientRequest(ipAddress=ip_address))
channel = get_secure_channel(c.server.hostname, settings.GRPC_PORT)
rpc.reset_client(channel, c.ip_address)
https://support.dnsimple.com/articles/what-is-common-name/
In this case, the endpoint you are connecting are not matching the description of peer's certificate. Hence, the connection was rejected. You could either try to use one of the CN in your certificate to connect to the server. Or adding the endpoint to your certificate.
I was integrating a go grpc server and a Python client. To make it work I did the following.
When creating the server.csr file using this line
openssl req -new -sha256 -key certs/server.key -out certs/server.csr -config certs/certificate.conf
The certs/certificate.conf looked likes this:
[req]
default_bits = 4096
prompt = no
default_md = sha256
req_extensions = req_ext
distinguished_name = dn
[dn]
C = AU
ST = VIC
O = OCOM Software
CN = hub_proxy
[req_ext]
subjectAltName = #alt_names
[alt_names]
DNS.1 = hub_proxy
IP.1 = ::1
IP.2 = 127.0.0.1
Notice the CN = hub_proxy and the DNS.1 = hub_proxy
I am not sure which solved this but when I regenerated the certificates and keys with these settings.
And then connected to the server using the hostname (in the client) of hub_proxy:9000 (where 9000 is the port number) it worked.

How can I skip ssl certificate verification on HTTPS connection using the OpenEdge.Net Libraries?

I am trying to to do a POST to an API endpoint using Openedge.
I have installed the ssl certificate of the place i am requesting from but the https request fails, telling me it can't find the ssl certificate of that place (in my /usr/dlc/certs).
"_errors": [
{
"_errorMsg": "ERROR condition: Secure Socket Layer (SSL) failure. error code -54: unable to get local issuer certificate: for 85cf5865.0 in /usr/dlc/certs (9318) (7211)",
"_errorNum": 9318
}
]
So, i have resorted to doing an insecure request, like curl does it with the --insecure or wget does it with "no-check-certificate"
I am using the OpenEdge.Net Libraries on OpenEdge 11.6
creds = new Credentials('https://xxxx.com', 'usersname', 'password').
oPayload = NEW JsonObject().
oRequestBody = new String('CustomerReference=xxx&NoOfParcelsToAdd=2').
oRequest = RequestBuilder:Post('https://xxxxx.com/endpoint', oRequestBody)// Add credentials to the request
:UsingBasicAuthentication(creds)
:ContentType('application/x-www-form-urlencoded')
:AcceptJson() :Request.
oResponse = ClientBuilder:Build():Client:Execute(oRequest).
I want to know, for this OpenEdge.Net Libraries is there a tag that i can put in order to skip the checking of the certificate?
I don't know of any option to skip verification but I do know that a common source of that error is that your certificate authority is not in $DLC/certs. The default list of certificate authorities is fairly narrow.
USING OpenEdge.Net.HTTP.IHttpClientLibrary.
USING OpenEdge.Net.HTTP.Lib.ClientLibraryBuilder.
DEFINE VARIABLE oLib AS IHttpClientLibrary NO-UNDO.
oLib = ClientLibraryBuilder:Build()
:sslVerifyHost(NO)
:Library.
oHttpClient = ClientBuilder:Build()
:UsingLibrary(oLib)
:Client.

SSL: CERTIFICATE_VERIFY_FAILED error displayed while connecting to SignalR through Python

from requests import Session
from signalr import Connection
with Session() as session:
connection = Connection("https://localhost:443/Platform", session)
Signalhub = connection.register_hub('MessageRouteHubspot')
with connection:
Signalhub.server.invoke('subscribe','1_FPGA_ACCESS_COMMANDS')
When executing this I'm getting error requests.exceptions.
SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:590)
How to bypass/ignore SSL verification??
Python's signalr-client uses WebSocket package to establish the connection. WebSocket package is then using OpenSSL to do SSL/TLS. It appears that the WebSocket client requires client CA (Certificate Authority) bundle to be passed as the environment variable WEBSOCKET_CLIENT_CA_BUNDLE.
Exporting this variable with the CA bundle including the certificates signing the original site's certificate should do the trick. Below is an example on my Ubuntu based system.
$ export WEBSOCKET_CLIENT_CA_BUNDLE=/etc/ssl/certs/ca-certificates.crt
$ python test-signalr.py

SSL verification causes RCurl and httr to break - on a website that should be legit

i'm trying to automate the login of the UK's data archive service. that website is obviously trustworthy. unfortunately, both RCurl and httr break at SSL verification. my web browser doesn't give any sort of warning. i can work around the issue by using ssl.verifypeer = FALSE in RCurl but i'd like to understand what's going on?
# breaks
library(httr)
GET( "https://www.esds.ac.uk/secure/UKDSRegister_start.asp" )
# breaks
library(RCurl)
cert <- system.file("CurlSSL/cacert.pem", package = "RCurl")
getURL("https://www.esds.ac.uk/secure/UKDSRegister_start.asp",cainfo = cert)
# works
library(RCurl)
getURL(
"https://www.esds.ac.uk/secure/UKDSRegister_start.asp" ,
.opts = list(ssl.verifypeer = FALSE)
) # note: use list(ssl.verifypeer = FALSE,followlocation=TRUE) to see content
TL;DR
Get the TERENA SSL CA PEM file from TERENA's repository of trusted certificates and use this file as your cainfo parameter.
EDIT: You might need to add two lines to the beginning of that file. The code works for me using the following TERENA.pem file:
TERENA
======
-----BEGIN CERTIFICATE-----
MIIEmDCCA4CgAwIBAgIQS8gUAy8H+mqk8Nop32F5ujANBgkqhkiG9w0BAQUFADCB
lzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug
Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho
dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3Qt
SGFyZHdhcmUwHhcNMDkwNTE4MDAwMDAwWhcNMjAwNTMwMTA0ODM4WjA2MQswCQYD
VQQGEwJOTDEPMA0GA1UEChMGVEVSRU5BMRYwFAYDVQQDEw1URVJFTkEgU1NMIENB
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAw+NIxC9cwcupmf0booNd
ij2tOtDipEMfTQ7+NSUwpWkbxOjlwY9UfuFqoppcXN49/ALOlrhfj4NbzGBAkPjk
tjolnF8UUeyx56+eUKExVccCvaxSin81joL6hK0V/qJ/gxA6VVOULAEWdJRUYyij
8lspPZSIgCDiFFkhGbSkmOFg5vLrooCDQ+CtaPN5GYtoQ1E/iptBhQw1jF218bbl
p8ODtWsjb9Sl61DllPFKX+4nSxQSFSRMDc9ijbcAIa06Mg9YC18em9HfnY6pGTVQ
L0GprTvG4EWyUzl/Ib8iGodcNK5Sbwd9ogtOnyt5pn0T3fV/g3wvWl13eHiRoBS/
fQIDAQABo4IBPjCCATowHwYDVR0jBBgwFoAUoXJfJhsomEOVXQc31YWWnUvSw0Uw
HQYDVR0OBBYEFAy9k2gM896ro0lrKzdXR+qQ47ntMA4GA1UdDwEB/wQEAwIBBjAS
BgNVHRMBAf8ECDAGAQH/AgEAMBgGA1UdIAQRMA8wDQYLKwYBBAGyMQECAh0wRAYD
VR0fBD0wOzA5oDegNYYzaHR0cDovL2NybC51c2VydHJ1c3QuY29tL1VUTi1VU0VS
Rmlyc3QtSGFyZHdhcmUuY3JsMHQGCCsGAQUFBwEBBGgwZjA9BggrBgEFBQcwAoYx
aHR0cDovL2NydC51c2VydHJ1c3QuY29tL1VUTkFkZFRydXN0U2VydmVyX0NBLmNy
dDAlBggrBgEFBQcwAYYZaHR0cDovL29jc3AudXNlcnRydXN0LmNvbTANBgkqhkiG
9w0BAQUFAAOCAQEATiPuSJz2hYtxxApuc5NywDqOgIrZs8qy1AGcKM/yXA4hRJML
thoh45gBlA5nSYEevj0NTmDa76AxTpXv8916WoIgQ7ahY0OzUGlDYktWYrA0irkT
Q1mT7BR5iPNIk+idyfqHcgxrVqDDFY1opYcfcS3mWm08aXFABFXcoEOUIEU4eNe9
itg5xt8Jt1qaqQO4KBB4zb8BG1oRPjj02Bs0ec8z0gH9rJjNbUcRkEy7uVvYcOfV
r7bMxIbmdcCeKbYrDyqlaQIN4+mitF3A884saoU4dmHGSYKrUbOCprlBmCiY+2v+
ihb/MX5UR6g83EMmqZsFt57ANEORMNQywxFa4Q==
-----END CERTIFICATE-----
Why?
The GET method of httr uses RCurl::curlPerform internally, as does RCurl::getURL, so the observed behavior is not surprising. The curl command-line tools with the "verbose" switch -v gives the following additional hints:
$ curl -v "https://www.esds.ac.uk/secure/UKDSRegister_start.asp"
* About to connect() to www.esds.ac.uk port 443 (#0)
* Trying 155.245.69.4...
* Connected to www.esds.ac.uk (155.245.69.4) port 443 (#0)
* successfully set certificate verify locations:
* CAfile: none
CApath: /etc/ssl/certs
* SSLv3, TLS handshake, Client hello (1):
* SSLv3, TLS handshake, Server hello (2):
* SSLv3, TLS handshake, CERT (11):
* SSLv3, TLS alert, Server hello (2):
* SSL certificate problem: unable to get local issuer certificate
* Closing connection 0
curl: (60) SSL certificate problem: unable to get local issuer certificate
More details here: http://curl.haxx.se/docs/sslcerts.html
curl performs SSL certificate verification by default, using a "bundle"
of Certificate Authority (CA) public keys (CA certs). If the default
bundle file isn't adequate, you can specify an alternate file
using the --cacert option.
If this HTTPS server uses a certificate signed by a CA represented in
the bundle, the certificate verification probably failed due to a
problem with the certificate (it might be expired, or the name might
not match the domain name in the URL).
If you'd like to turn off curl's verification of the certificate, use
the -k (or --insecure) option.
The link in the above error message contains, at enumeration item 3, instruction on obtaining the server's certificate:
$ openssl s_client -connect "www.esds.ac.uk:443"
CONNECTED(00000003)
depth=0 C = GB, ST = Essex, L = Colchester, O = University of Essex, OU = UK Data Archive, CN = www.esds.ac.uk
verify error:num=20:unable to get local issuer certificate
verify return:1
depth=0 C = GB, ST = Essex, L = Colchester, O = University of Essex, OU = UK Data Archive, CN = www.esds.ac.uk
verify error:num=27:certificate not trusted
verify return:1
depth=0 C = GB, ST = Essex, L = Colchester, O = University of Essex, OU = UK Data Archive, CN = www.esds.ac.uk
verify error:num=21:unable to verify the first certificate
verify return:1
---
Certificate chain
0 s:/C=GB/ST=Essex/L=Colchester/O=University of Essex/OU=UK Data Archive/CN=www.esds.ac.uk
i:/C=NL/O=TERENA/CN=TERENA SSL CA
---
Server certificate
-----BEGIN CERTIFICATE-----
MIIEIzCCAwugAwIBAgIQO9FPWbAYKDAuFHq61U3gDDANBgkqhkiG9w0BAQUFADA2
MQswCQYDVQQGEwJOTDEPMA0GA1UEChMGVEVSRU5BMRYwFAYDVQQDEw1URVJFTkEg
U1NMIENBMB4XDTEwMTIwNjAwMDAwMFoXDTEzMTIwNTIzNTk1OVowgYMxCzAJBgNV
......
To me, this reads as if the certificate is not trusted. A quick search for "terena ssl root certificate" found this website of the University of Helsinki which reads:
Unfortunately root certificates of these authorities are not always present in devices in use, instead, we need to install those root certificates ourselves.
This site also contains a link to the certificate repository.

Resources