From 340a7609dc50474d4479c1e1a3567efdd3da9f5c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9rome=20Perrin?= <jerome@nexedi.com> Date: Mon, 1 Feb 2021 02:52:18 +0100 Subject: [PATCH] software/*: version up urllib3, requests and dependencies Several softwares were using fixed versions, but versions are also defined in stack/slapos.cfg, so let's use from stack/slapos.cfg which will simplify version management. This urllib3 has visible changes for us, it no longer send the request path "as is", but normalizes the . and .. which is not what we want in caddy-frontend test, so we adjust the test to use prepared requests, which is the recommended approach for this kind of low level needs. Since prepared requests does not set default user agent "python-requests", tests checking that user agent is in log files have been adjusted to use a dedicated test user agent header. Another change is that certificates are now verified by default, so we adjust seleniumserver tests to disable certificate validation. jstestnode, already had a patch regarding certificate validation, because we wanted certificates to be validated before it was the default. We just update this patch a bit because we want to keep the optional behaviours of validating against a specific CA or to disable validation. --- software/caddy-frontend/software.cfg | 9 ------ software/caddy-frontend/test/test.py | 37 +++++++++++++++--------- software/erp5/test/test/test_balancer.py | 2 +- software/jstestnode/buildout.hash.cfg | 2 +- software/jstestnode/runTestSuite.in | 4 +-- software/jstestnode/software.cfg | 3 -- software/monitor/software.cfg | 5 ---- software/seleniumserver/test/test.py | 9 +++++- software/slapos-sr-testing/software.cfg | 15 +--------- 9 files changed, 37 insertions(+), 49 deletions(-) diff --git a/software/caddy-frontend/software.cfg b/software/caddy-frontend/software.cfg index efd1809f1..ef9ed2e20 100644 --- a/software/caddy-frontend/software.cfg +++ b/software/caddy-frontend/software.cfg @@ -228,15 +228,6 @@ mode = 0644 [versions] # Modern KeDiFa requires zc.lockfile zc.lockfile = 1.4 -# Versions pinned for kedifa need urllib3 >= 1.18 -urllib3 = 1.24 -requests = 2.20.0 -certifi = 2018.10.15 -idna = 2.7 -chardet = 3.0.4 -# ipaddress is patching IPAddress so IPv6 match works -ipaddress = 1.0.22 -# Versions pinned for kedifa need urllib3 >= 1.18 validators = 0.12.2 PyRSS2Gen = 1.1 diff --git a/software/caddy-frontend/test/test.py b/software/caddy-frontend/test/test.py index 9aa33325f..b43838604 100644 --- a/software/caddy-frontend/test/test.py +++ b/software/caddy-frontend/test/test.py @@ -419,13 +419,21 @@ def fakeHTTPSResult(domain, path, port=HTTPS_PORT, try: add_custom_dns(domain, port, TEST_IP) socket.getaddrinfo = new_getaddrinfo - return session.get( - 'https://%s:%s/%s' % (domain, port, path), - verify=False, - allow_redirects=False, - headers=headers, - cookies=cookies - ) + # Use a prepared request, to disable path normalization. + # We need this because some test checks requests with paths like + # /test-path/deep/.././deeper but we don't want the client to send + # /test-path/deeper + # See also https://github.com/psf/requests/issues/5289 + url = 'https://%s:%s/%s' % (domain, port, path) + req = requests.Request( + method='GET', + url=url, + headers=headers, + cookies=cookies, + ) + prepped = req.prepare() + prepped.url = url + return session.send(prepped, verify=False, allow_redirects=False) finally: socket.getaddrinfo = socket_getaddrinfo @@ -447,11 +455,13 @@ def fakeHTTPResult(domain, path, port=HTTP_PORT, new_source = source.SourceAddressAdapter(source_ip) session.mount('http://', new_source) session.mount('https://', new_source) - return session.get( - 'http://%s:%s/%s' % (TEST_IP, port, path), - headers=headers, - allow_redirects=False, - ) + + # Use a prepared request, to disable path normalization. + url = 'http://%s:%s/%s' % (TEST_IP, port, path) + req = requests.Request(method='GET', url=url, headers=headers) + prepped = req.prepare() + prepped.url = url + return session.send(prepped, allow_redirects=False) class TestHandler(BaseHTTPRequestHandler): @@ -1821,6 +1831,7 @@ class TestSlave(SlaveHttpFrontendTestCase, TestDataMixin): headers={ 'Timeout': '10', # more than default backend-connect-timeout == 5 'Accept-Encoding': 'gzip', + 'User-Agent': 'TEST USER AGENT', } ) @@ -1854,7 +1865,7 @@ class TestSlave(SlaveHttpFrontendTestCase, TestDataMixin): log_regexp = r'^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3} - - ' \ r'\[\d{2}\/.{3}\/\d{4}\:\d{2}\:\d{2}\:\d{2} \+\d{4}\] ' \ r'"GET \/test-path\/deep\/..\/.\/deeper HTTP\/1.1" \d{3} ' \ - r'\d+ "-" "python-requests.*" \d+' + r'\d+ "-" "TEST USER AGENT" \d+' self.assertRegexpMatches( open(log_file, 'r').readlines()[-1], diff --git a/software/erp5/test/test/test_balancer.py b/software/erp5/test/test/test_balancer.py index 4dcfe2acd..a9ab9c6eb 100644 --- a/software/erp5/test/test/test_balancer.py +++ b/software/erp5/test/test/test_balancer.py @@ -750,7 +750,7 @@ class TestFrontendXForwardedFor(BalancerTestCase): ).json() self.assertNotEqual(result['Incoming Headers'].get('x-forwarded-for', '').split(', ')[0], '1.2.3.4') balancer_url = json.loads(self.computer_partition.getConnectionParameterDict()['_'])['default-auth'] - with self.assertRaises(OpenSSL.SSL.Error): + with self.assertRaisesRegexp(Exception, "certificate required"): requests.get( balancer_url, headers={'X-Forwarded-For': '1.2.3.4'}, diff --git a/software/jstestnode/buildout.hash.cfg b/software/jstestnode/buildout.hash.cfg index 54b3d085d..d08486019 100644 --- a/software/jstestnode/buildout.hash.cfg +++ b/software/jstestnode/buildout.hash.cfg @@ -27,4 +27,4 @@ md5sum = 98faa5ad8cfb23a11d97a459078a1d05 [template-runTestSuite] filename = runTestSuite.in -md5sum = bb3f053b6cdb0a8888e9d32e63085ed5 +md5sum = 73ef758825563b7a6a1d660d4d5229b8 diff --git a/software/jstestnode/runTestSuite.in b/software/jstestnode/runTestSuite.in index 23e3bdc9f..bbfcdf1ef 100644 --- a/software/jstestnode/runTestSuite.in +++ b/software/jstestnode/runTestSuite.in @@ -97,8 +97,8 @@ def main(): executable_path='${geckodriver:location}') else: assert target == 'selenium-server', "Unsupported target {}".format(test_runner['target']) - # use a remote connection which verifies TLS certificate - # workaround for https://github.com/SeleniumHQ/selenium/issues/6534 + # use a remote connection which optionally verifies TLS certificate + # and optionally against a user provided CA. executor = RemoteConnection(test_runner['server-url'], keep_alive=True) cert_reqs = 'CERT_REQUIRED' ca_certs = certifi.where() diff --git a/software/jstestnode/software.cfg b/software/jstestnode/software.cfg index c67c5611a..310c7995c 100644 --- a/software/jstestnode/software.cfg +++ b/software/jstestnode/software.cfg @@ -117,7 +117,4 @@ output = ${buildout:directory}/template-nginx.cfg.in output = ${buildout:directory}/runTestSuite.in [versions] - selenium = 3.14.1 -urllib3 = 1.24 -certifi = 2018.10.15 diff --git a/software/monitor/software.cfg b/software/monitor/software.cfg index 98de4a4e7..42648c75b 100644 --- a/software/monitor/software.cfg +++ b/software/monitor/software.cfg @@ -81,12 +81,7 @@ surykatka = 0.5.0 # For surykatka 0.5.0 click = 7.0 -certifi = 2019.11.28 -chardet = 3.0.4 dnspython = 1.16.0 forcediphttpsadapter = 1.0.1 -idna = 2.8 miniupnpc = 2.0.2 peewee = 3.13.1 -requests = 2.22.0 -urllib3 = 1.25.8 diff --git a/software/seleniumserver/test/test.py b/software/seleniumserver/test/test.py index 3596c3c99..9eb7d302d 100644 --- a/software/seleniumserver/test/test.py +++ b/software/seleniumserver/test/test.py @@ -46,8 +46,10 @@ from PIL import Image from selenium import webdriver from selenium.webdriver.common.by import By from selenium.webdriver.common.desired_capabilities import DesiredCapabilities +from selenium.webdriver.remote.remote_connection import RemoteConnection from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.support.ui import WebDriverWait +import urllib3 from slapos.testing.testcase import makeModuleSetUpAndTestCaseClass from slapos.testing.utils import findFreeTCPPort, ImageComparisonTestCase, ManagedHTTPServer @@ -318,8 +320,13 @@ class TestFrontend(WebServerMixin, SeleniumServerTestCase): self.assertEqual('selenium', parsed.username) self.assertTrue(parsed.password) + # XXX we are using a self signed certificate, but selenium 3.141.0 does + # not expose API to ignore certificate verification + executor = RemoteConnection(webdriver_url, keep_alive=True) + executor._conn = urllib3.PoolManager(cert_reqs='CERT_NONE', ca_certs=None) + driver = webdriver.Remote( - command_executor=webdriver_url, + command_executor=executor, desired_capabilities=DesiredCapabilities.CHROME) driver.get(self.server_url) diff --git a/software/slapos-sr-testing/software.cfg b/software/slapos-sr-testing/software.cfg index 41a200726..3cb4bb030 100644 --- a/software/slapos-sr-testing/software.cfg +++ b/software/slapos-sr-testing/software.cfg @@ -298,16 +298,7 @@ selenium = 3.141.0 # Patched eggs PyPDF2 = 1.26.0+SlapOSPatched001 -# modern versions for SSL fixed support -requests = 2.20.0 -certifi = 2018.10.15 -idna = 2.7 -chardet = 3.0.4 - -# ipaddress is patching IPAddress so IPv6 match works -ipaddress = 1.0.22 - -# cacuase and its dependencies +# caucase and its dependencies caucase = 0.9.4 pem = 18.2.0 PyJWT = 1.6.4 @@ -315,10 +306,6 @@ PyJWT = 1.6.4 # Django 1.11 is python 2 compatible Django = 1.11 -# Required by: -# selenium==3.141.0 -urllib3 = 1.24.1 - mock = 2.0.0 testfixtures = 6.11 funcsigs = 1.0.2 -- 2.30.9