-
Notifications
You must be signed in to change notification settings - Fork 185
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Allow setting TLS max/min versions #138
Conversation
Codecov Report
@@ Coverage Diff @@
## master #138 +/- ##
==========================================
+ Coverage 73.57% 73.59% +0.01%
==========================================
Files 8 8
Lines 2547 2556 +9
==========================================
+ Hits 1874 1881 +7
- Misses 673 675 +2
Continue to review full report at Codecov.
|
Great, thank you. Think it could be done without global variable, per host? You want to revert chmod on |
oops, fixed the chmod. Regarding non-global way to do this, I couldn't find one. |
friendly ping, anything else you need here? |
Please try something like this diff --git a/python3/httplib2/__init__.py b/python3/httplib2/__init__.py
index 73450be..7c72671 100644
--- a/python3/httplib2/__init__.py
+++ b/python3/httplib2/__init__.py
@@ -175,7 +175,8 @@ DEFAULT_TLS_VERSION = getattr(ssl, "PROTOCOL_TLS", None) or getattr(
def _build_ssl_context(
- disable_ssl_certificate_validation, ca_certs, cert_file=None, key_file=None
+ disable_ssl_certificate_validation, ca_certs, cert_file=None, key_file=None,
+ maximum_version=None, minimum_version=None,
):
if not hasattr(ssl, "SSLContext"):
raise RuntimeError("httplib2 requires Python 3.2+ for ssl.SSLContext")
@@ -185,6 +186,11 @@ def _build_ssl_context(
ssl.CERT_NONE if disable_ssl_certificate_validation else ssl.CERT_REQUIRED
)
+ if maximum_version is not None and hasattr(context, "maximum_version"):
+ context.maximum_version = getattr(ssl.TLSVersion, maximum_version)
+ if minimum_version is not None and hasattr(context, "minimum_version"):
+ context.minimum_version = getattr(ssl.TLSVersion, minimum_version)
+
# check_hostname requires python 3.4+
# we will perform the equivalent in HTTPSConnectionWithTimeout.connect() by calling ssl.match_hostname
# if check_hostname is not supported.
@@ -1226,6 +1232,8 @@ class HTTPSConnectionWithTimeout(http.client.HTTPSConnection):
proxy_info=None,
ca_certs=None,
disable_ssl_certificate_validation=False,
+ tls_maximum_version=None,
+ tls_minimum_version=None,
):
self.disable_ssl_certificate_validation = disable_ssl_certificate_validation
@@ -1236,7 +1244,8 @@ class HTTPSConnectionWithTimeout(http.client.HTTPSConnection):
self.proxy_info = proxy_info("https")
context = _build_ssl_context(
- self.disable_ssl_certificate_validation, self.ca_certs, cert_file, key_file
+ self.disable_ssl_certificate_validation, self.ca_certs, cert_file, key_file,
+ maximum_version=tls_maximum_version, minimum_version=tls_minimum_version,
)
super(HTTPSConnectionWithTimeout, self).__init__(
host,
@@ -1384,6 +1393,8 @@ class Http(object):
proxy_info=proxy_info_from_environment,
ca_certs=None,
disable_ssl_certificate_validation=False,
+ tls_maximum_version=None,
+ tls_minimum_version=None,
):
"""If 'cache' is a string then it is used as a directory name for
a disk cache. Otherwise it must be an object that supports the
@@ -1411,6 +1422,8 @@ class Http(object):
self.proxy_info = proxy_info
self.ca_certs = ca_certs
self.disable_ssl_certificate_validation = disable_ssl_certificate_validation
+ self.tls_maximum_version = tls_maximum_version
+ self.tls_minimum_version = tls_minimum_version
# Map domain name to an httplib connection
self.connections = {}
# The location of the cache, for now a directory
@@ -1753,6 +1766,8 @@ a string that contains the response entity body.
proxy_info=self.proxy_info,
ca_certs=self.ca_certs,
disable_ssl_certificate_validation=self.disable_ssl_certificate_validation,
+ tls_maximum_version=self.tls_maximum_version,
+ tls_minimum_version=self.tls_minimum_version,
)
else:
conn = self.connections[conn_key] = connection_type(
@@ -1761,6 +1776,8 @@ a string that contains the response entity body.
proxy_info=self.proxy_info,
ca_certs=self.ca_certs,
disable_ssl_certificate_validation=self.disable_ssl_certificate_validation,
+ tls_maximum_version=self.tls_maximum_version,
+ tls_minimum_version=self.tls_minimum_version,
)
else:
conn = self.connections[conn_key] = connection_type( |
@jay0lee it still has global variables. I believe this will be used to create bad surprises in the long run. |
ah, I assumed your patch was additive. I can pull out the globals now then. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
@jay0lee thank you.
@@ -185,6 +185,13 @@ def _build_ssl_context( | |||
ssl.CERT_NONE if disable_ssl_certificate_validation else ssl.CERT_REQUIRED | |||
) | |||
|
|||
# SSLContext.maximum_version and SSLContext.minimum_version are python 3.7+. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
# SSLContext.maximum_version and SSLContext.minimum_version are Python 3.7+:
# https://docs.python.org/3/library/ssl.html#ssl.SSLContext.maximum_version
python3/httplib2/__init__.py
Outdated
@@ -185,6 +185,13 @@ def _build_ssl_context( | |||
ssl.CERT_NONE if disable_ssl_certificate_validation else ssl.CERT_REQUIRED | |||
) | |||
|
|||
# SSLContext.maximum_version and SSLContext.minimum_version are python 3.7+. | |||
# source: https://docs.python.org/3/library/ssl.html#ssl.SSLContext.maximum_version | |||
if maximum_version is not None and hasattr(context, "maximum_version"): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you also add code coverage?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Travis Python 3.7 uses OpenSSL 1.0 which won't support these attributes, the only way to do testing would be to pre-compile Python and OpenSSL on Travis and then run the tests against that. I can submit such a PR for .travis.yml (I do something like this for my own downstream project) but it will slow Travis testing down somewhat on that configuration.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@temoto Use tox-travis to force py37 and OpenSSL 1.1.0+? https://stackoverflow.com/questions/37016688/how-to-run-tox-with-travis-ci/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My suggestion to keep things organized is either:
- full revamp of current config to take full advantage of tox-travis
- just another job conforming to existing config
jobs:
include:
#...
- stage: test
env: _=py3-openssl-110
python: 3.7
install:
- CUSTOM_OPENSSL_INSTALL_SCRIPT
- pip install $pip_install_common 'codecov>=2.0.15' -r requirements-test.txt
script: script/test -sv
I'd only slightly prefer not tox-travis route because it's many changes and you still need to install custom openssl.
CUSTOM_OPENSSL_INSTALL_SCRIPT should be noop with hot Travis cache.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
pyopenssl actually tests something like this on Travis using MacOS which can use OpenSSL 1.1.1b (latest) via a brew update:
https://travis-ci.org/pyca/pyopenssl/jobs/537306843
I'm currently testing adding an additional job that would use MacOS, Python 3.7 and OpenSSL 1.1+ so we can actually test TLS min/max availability.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, MacOS proved far to problematic so went with your suggestion of a custom script to compile.
- I've added tests that are now passing
- I removed Python 3.4 support as it's end of life and broke the tests.
Let me know if you have thoughts on better testing or anything else.
Python 3.7.3
@temoto Please take another look and merge. |
@jay0lee sorry it took so long. Please have a look here 890b822 and say if you like to put that version. I'm happy if you are. Major change: only build results go into Travis cache, sources die in /tmp. |
@temoto that looks good except that you're using 1.1.1c instead of $OPENSSL_VERSION in the check at the end. It should be possible for Bash to expand the variable before Python executes the inline script. Do you want me to pull these changes into my PR fork? |
Yeah, sorry. Just tested this syntax works:
It was done separately for maybe you would not like your work changed so much and keep it. |
@jay0lee thank you very much. Your patch was just released in 0.13.0 |
…b2#138 commit e92155b85c719405fefe69b045f3bcf55d4fbcc1 Author: Sergey Shepelev <temotor@gmail.com> Date: Fri Jun 7 00:40:38 2019 +0500 v0.13.0 release commit 2a806cb4bc731058541ab902101ea7750f350282 Author: Jay Lee <jay0lee@gmail.com> Date: Thu Jun 6 02:59:21 2019 -0400 Allow setting TLS max/min versions httplib2/httplib2#138
Add httplib2.MAX_TLS_VERSION and httplib2.MIN_TLS_VERSION. Python 3.7+ and OpenSSL 1.1+ allow setting these:
https://docs.python.org/3/library/ssl.html#ssl.SSLContext.maximum_version
tests don't seem to be possible (yet) though as Travis Xenial image is using OpenSSL 1.0.