artemy / alfred-ns-schedule

Alfred workflow for getting NS (Nederlandse Spoorwegen) train schedule.
MIT License
4 stars 1 forks source link

SSL Certificate error with Alfred 5 (Python 3.7) #11

Open qblone opened 6 days ago

qblone commented 6 days ago

12:45:20.705] ERROR: NS train schedule[Script Filter] Code 1: Traceback (most recent call last): File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/urllib/request.py", line 1350, in do_open encode_chunked=req.has_header('Transfer-encoding')) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/http/client.py", line 1277, in request self._send_request(method, url, body, headers, encode_chunked) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/http/client.py", line 1323, in _send_request self.endheaders(body, encode_chunked=encode_chunked) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/http/client.py", line 1272, in endheaders self._send_output(message_body, encode_chunked=encode_chunked) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/http/client.py", line 1032, in _send_output self.send(msg) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/http/client.py", line 972, in send self.connect() File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/http/client.py", line 1447, in connect server_hostname=server_hostname) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ssl.py", line 423, in wrap_socket session=session File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ssl.py", line 870, in _create self.do_handshake() File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/ssl.py", line 1139, in do_handshake self._sslobj.do_handshake() ssl.SSLCertVerificationError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1091)

During handling of the above exception, another exception occurred:

Traceback (most recent call last): File "ns_schedule.py", line 121, in main() File "ns_schedule.py", line 117, in main print((create_json(retrieve_schedule()))) File "ns_schedule.py", line 100, in retrieve_schedule response = call_api(origin, destination) File "ns_schedule.py", line 31, in call_api response = urllib.request.urlopen(req) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/urllib/request.py", line 222, in urlopen return opener.open(url, data, timeout) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/urllib/request.py", line 525, in open response = self._open(req, data) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/urllib/request.py", line 543, in _open '_open', req) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/urllib/request.py", line 503, in _call_chain result = func(*args) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/urllib/request.py", line 1393, in https_open context=self._context, check_hostname=self._check_hostname) File "/Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/urllib/request.py", line 1352, in do_open raise URLError(err) urllib.error.URLError: <urlopen error [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: self signed certificate in certificate chain (_ssl.c:1091)>

qblone commented 6 days ago

Disabling cert works for me, which is not ideal since it is now prone to MITM attack

import ssl

def call_api(origin, destination):
    params = urllib.parse.urlencode({'fromStation': origin, 'toStation': destination})
    url = 'https://gateway.apiportal.ns.nl/reisinformatie-api/api/v3/trips?' + params

    req = urllib.request.Request(url, headers=create_headers())
    context = ssl.create_default_context()
    context.check_hostname = False
    context.verify_mode = ssl.CERT_NONE
    response = urllib.request.urlopen(req, context=context)
    return json.loads(response.read())
qblone commented 6 days ago

The other work around is to go via certifi

import certifi
import ssl
def call_api(origin, destination):
    params = urllib.parse.urlencode({'fromStation': origin, 'toStation': destination})
    url = 'https://gateway.apiportal.ns.nl/reisinformatie-api/api/v3/trips?' + params

    req = urllib.request.Request(url, headers=create_headers())
    context = ssl.create_default_context(cafile=certifi.where())
    response = urllib.request.urlopen(req, context=context)
    return json.loads(response.read())
artemy commented 6 days ago

Hi, @qblone

I can't seem to reproduce it on python 3.13. Do you think it's somehow related to bundled python certs?

vitorgalvao commented 6 days ago

This usually happens when someone installs Python from their website (as opposed to using Homebrew), which is one of the reasons that is not recommended. If you do that, you also have to install the certificates.

3.7 is an old version, though, even older than what Apple ships with macOS, and that’s saying something. What macOS version are you on? When making a report it’s always useful to report the installed versions of macOS, Alfred, and the workflow, for a proper diagnosis.

@artemy I recommend you change the Script Filter to use /usr/bin/python3 (as opposed to python3) to force the system version.