From 336c80b694eaac21826854c4bde8693f80373a79 Mon Sep 17 00:00:00 2001 From: Matthieu Darbois Date: Sat, 31 Oct 2020 10:06:14 +0100 Subject: [PATCH] Use certifi provided certificates when downloading files (#455) * Use certifi provided certificates when downloading files * fix typo * Add comment about certifi usage Co-authored-by: Joe Rickerby Co-authored-by: Joe Rickerby --- cibuildwheel/util.py | 8 +++++++- setup.py | 2 +- unit_test/download_test.py | 31 +++++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 2 deletions(-) create mode 100644 unit_test/download_test.py diff --git a/cibuildwheel/util.py b/cibuildwheel/util.py index d528a73b..c24f9bf5 100644 --- a/cibuildwheel/util.py +++ b/cibuildwheel/util.py @@ -1,6 +1,8 @@ import os import textwrap +import certifi import urllib.request +import ssl from fnmatch import fnmatch from pathlib import Path from time import sleep @@ -66,10 +68,14 @@ def download(url: str, dest: Path) -> None: if not dest_dir.exists(): dest_dir.mkdir(parents=True) + # we've had issues when relying on the host OS' CA certificates on Windows, + # so we use certifi (this sounds odd but requests also does this by default) + cafile = os.environ.get('SSL_CERT_FILE', certifi.where()) + context = ssl.create_default_context(cafile=cafile) repeat_num = 3 for i in range(repeat_num): try: - response = urllib.request.urlopen(url) + response = urllib.request.urlopen(url, context=context) except Exception: if i == repeat_num - 1: raise diff --git a/setup.py b/setup.py index ee11c393..dd417612 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ long_description = (this_directory / 'README.md').read_text(encoding='utf-8') setup( name='cibuildwheel', version='1.6.3', - install_requires=['bashlex!=0.13', 'toml'], + install_requires=['bashlex!=0.13', 'toml', 'certifi'], description="Build Python wheels on CI with minimal configuration.", long_description=long_description, long_description_content_type='text/markdown', diff --git a/unit_test/download_test.py b/unit_test/download_test.py new file mode 100644 index 00000000..b5e28228 --- /dev/null +++ b/unit_test/download_test.py @@ -0,0 +1,31 @@ +import certifi +import pytest +import ssl + +from cibuildwheel.util import download + + +DOWNLOAD_URL = 'https://raw.githubusercontent.com/joerick/cibuildwheel/v1.6.3/requirements-dev.txt' + + +def test_download(monkeypatch, tmp_path): + monkeypatch.delenv('SSL_CERT_FILE', raising=False) + dest = tmp_path / 'file.txt' + download(DOWNLOAD_URL, dest) + assert len(dest.read_bytes()) == 134 + + +def test_download_good_ssl_cert_file(monkeypatch, tmp_path): + monkeypatch.setenv('SSL_CERT_FILE', certifi.where()) + dest = tmp_path / 'file.txt' + download(DOWNLOAD_URL, dest) + assert len(dest.read_bytes()) == 134 + + +def test_download_bad_ssl_cert_file(monkeypatch, tmp_path): + bad_cafile = tmp_path / 'ca.pem' + bad_cafile.write_text('bad certificates') + monkeypatch.setenv('SSL_CERT_FILE', str(bad_cafile)) + dest = tmp_path / 'file.txt' + with pytest.raises(ssl.SSLError): + download(DOWNLOAD_URL, dest)