gear/gear
Guillaume Chauvel 66ba8442dc Create SSL context using PROTOCOL_TLS, fallback to highest supported version
Zuul test: tests.unit.test_scheduler.TestSchedulerSSL.test_jobs_executed
fails on ubuntu focal with the following exception:

Traceback (most recent call last):
  File "/home/gchauvel/zuul/zuul/.tox/py38/lib/python3.8/site-packages/gear/__init__.py", line 2835, in _doConnectLoop
    self.connectLoop()
  File "/home/gchauvel/zuul/zuul/.tox/py38/lib/python3.8/site-packages/gear/__init__.py", line 2865, in connectLoop
    c = context.wrap_socket(c, server_side=True)
  File "/usr/lib/python3.8/ssl.py", line 500, in wrap_socket
    return self.sslsocket_class._create(
  File "/usr/lib/python3.8/ssl.py", line 1040, in _create
    self.do_handshake()
  File "/usr/lib/python3.8/ssl.py", line 1309, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLError: [SSL] internal error (_ssl.c:1108)

This is due to libssl1.1 being compiled with
"-DOPENSSL_TLS_SECURITY_LEVEL=2" and gear forcing TLSv1.0

Extracted from ubuntu source package:

  The default security level for TLS connections was increased from
  level 1 to level 2. This moves from the 80 bit security level to the
  112 bit security level and will require 2048 bit or larger RSA and
  DHE keys, 224 bit or larger ECC keys, SHA-2, TLSv1.2 or DTLSv1.2.

Allowing to negotiate TLS to the highest available version between
server and client solves the issue, provided that TLSv1.2 is useable.
The option is supported by in the latest version of all pythons >=3.5
[1][2][3]. Unfortunately Xenial doesn't have latest 3.5 and lacks the
ssl.PROTOCOL_TLS definition. We provide a fallback to select the highest
version of TLS supported in that case.

There is some risk using the fallback beacuse both the client and server
need to agree on the version supported in this case. Xenial python 3.5
does support TLSv1_2 which means that for all practical purposes TLS
v1.2 should be available on all platforms that gear runs avoiding this
problem.

Disable TLSv1.3:
According to https://bugs.python.org/issue43622#msg389497, an event on
ssl socket can happen without data being available at application level.
As gear is using a polling loop with multiple file descriptors and ssl
socket used as a blocking one, a blocked state could happen.
This is highlighted by Zuul SSL test: TestSchedulerSSL, where such
blocked state appears consistently.
note: gear tests and zuul tests are ok when using TLSv1.2 but the
previous behavior could also happen

[1] https://docs.python.org/2.7/library/ssl.html?highlight=protocol_tls#ssl.PROTOCOL_TLS
[2] https://docs.python.org/3.5/library/ssl.html?highlight=protocol_tls#ssl.PROTOCOL_TLS
[3] https://docs.python.org/3/library/ssl.html?highlight=protocol_tls#ssl.PROTOCOL_TLS

Change-Id: I5efb6c0576987815c5b93f8bc4020cdee2898d04
2021-03-30 14:56:38 +02:00
..
cmd Add --listen-address flag to geard 2018-04-16 16:27:49 -04:00
tests Bump crypto requirement to accomodate security standards 2020-07-21 12:16:31 +00:00
__init__.py Create SSL context using PROTOCOL_TLS, fallback to highest supported version 2021-03-30 14:56:38 +02:00
acl.py Re-enable flake8 2016-11-08 11:57:04 -06:00
constants.py Re-enable flake8 2016-11-08 11:57:04 -06:00