From 8f22069fdae256df334dcbd21397fdad29093f0b Mon Sep 17 00:00:00 2001 From: Tomas Kopecek Date: Jan 03 2018 11:47:03 +0000 Subject: drop old ssl support + compatrequests Koji now uses ssl via python-requests - use_old_ssl option is removed - koji.ssl library removed - compatrequests dropped Related: https://pagure.io/koji/issue/467 --- diff --git a/.coveragerc3 b/.coveragerc3 index 8bd87e7..3e60769 100644 --- a/.coveragerc3 +++ b/.coveragerc3 @@ -7,7 +7,6 @@ omit = tests/* hub/* util/* - koji/ssl/* koji/daemon.py koji/tasks.py diff --git a/builder/kojid b/builder/kojid index f1e20f3..e94f637 100755 --- a/builder/kojid +++ b/builder/kojid @@ -5632,7 +5632,6 @@ def get_options(): 'offline_retry_interval': 120, 'keepalive' : True, 'timeout' : None, - 'use_old_ssl' : False, 'no_ssl_verify' : False, 'use_fast_upload': True, 'use_createrepo_c': False, @@ -5661,7 +5660,7 @@ def get_options(): elif name in ['offline_retry', 'use_createrepo_c', 'createrepo_skip_stat', 'createrepo_update', 'keepalive', 'use_fast_upload', 'support_rpm_source_layout', 'krb_rdns', 'krb_canon_host', - 'build_arch_can_fail', 'use_old_ssl', 'no_ssl_verify']: + 'build_arch_can_fail', 'no_ssl_verify']: defaults[name] = config.getboolean('kojid', name) elif name in ['plugin', 'plugins']: defaults['plugin'] = value.split() diff --git a/koji.spec b/koji.spec index a389cfe..63ef96a 100644 --- a/koji.spec +++ b/koji.spec @@ -33,8 +33,7 @@ Name: koji Version: 1.15.0 Release: %{release}%{?dist} -License: LGPLv2 and GPLv2+ -# koji.ssl libs (from plague) are GPLv2+ +License: LGPLv2 Summary: Build system tools Group: Applications/System URL: https://pagure.io/koji diff --git a/koji/Makefile b/koji/Makefile index d51de8d..c138231 100644 --- a/koji/Makefile +++ b/koji/Makefile @@ -8,7 +8,7 @@ ifeq ($(PYTHON), python3) else PYFILES = $(wildcard *.py) PYSCRIPTS = context.py - SUBDIRS = ssl + SUBDIRS = endif PYVER := $(shell $(PYTHON) -c 'import sys; print("%.3s" % (sys.version))') PYSYSDIR := $(shell $(PYTHON) -c 'import sys; print(sys.prefix)') diff --git a/koji/__init__.py b/koji/__init__.py index f5e2374..a6147e2 100644 --- a/koji/__init__.py +++ b/koji/__init__.py @@ -62,10 +62,7 @@ import os.path import pwd import random import re -try: - import requests -except ImportError: #pragma: no cover - requests = None +import requests try: from requests_kerberos import HTTPKerberosAuth except ImportError: #pragma: no cover @@ -1638,7 +1635,6 @@ def read_config(profile_name, user_config=None): 'anon_retry' : None, 'offline_retry' : None, 'offline_retry_interval' : None, - 'use_old_ssl' : False, 'keepalive' : True, 'timeout' : None, 'use_fast_upload': False, @@ -1708,7 +1704,7 @@ def read_config(profile_name, user_config=None): #not have a default value set in the option parser. if name in result: if name in ('anon_retry', 'offline_retry', 'keepalive', - 'use_fast_upload', 'krb_rdns', 'use_old_ssl', + 'use_fast_upload', 'krb_rdns', 'debug', 'debug', 'debug_xmlrpc', 'krb_canon_host'): result[name] = config.getboolean(profile_name, name) elif name in ('max_retries', 'retry_interval', @@ -1916,9 +1912,6 @@ pathinfo = PathInfo() def is_requests_cert_error(e): """Determine if a requests error is due to a bad cert""" - if requests is None: #pragma: no cover - # We are not using requests, so this is not a requests cert error - return False if not isinstance(e, requests.exceptions.SSLError): return False @@ -1982,22 +1975,21 @@ def is_conn_error(e): return False if isinstance(e, six.moves.http_client.BadStatusLine): return True - if requests is not None: - try: - if isinstance(e, requests.exceptions.ConnectionError): - # we see errors like this in keep alive timeout races - # ConnectionError(ProtocolError('Connection aborted.', BadStatusLine("''",)),) - e2 = getattr(e, 'args', [None])[0] - if isinstance(e2, requests.packages.urllib3.exceptions.ProtocolError): - e3 = getattr(e2, 'args', [None, None])[1] - if isinstance(e3, six.moves.http_client.BadStatusLine): - return True - if isinstance(e2, socket.error): - # same check as unwrapped socket error - if getattr(e, 'errno', None) in (errno.ECONNRESET, errno.ECONNABORTED, errno.EPIPE): - return True - except (TypeError, AttributeError): - pass + try: + if isinstance(e, requests.exceptions.ConnectionError): + # we see errors like this in keep alive timeout races + # ConnectionError(ProtocolError('Connection aborted.', BadStatusLine("''",)),) + e2 = getattr(e, 'args', [None])[0] + if isinstance(e2, requests.packages.urllib3.exceptions.ProtocolError): + e3 = getattr(e2, 'args', [None, None])[1] + if isinstance(e3, six.moves.http_client.BadStatusLine): + return True + if isinstance(e2, socket.error): + # same check as unwrapped socket error + if getattr(e, 'errno', None) in (errno.ECONNRESET, errno.ECONNABORTED, errno.EPIPE): + return True + except (TypeError, AttributeError): + pass # otherwise return False @@ -2035,7 +2027,6 @@ def grab_session_options(options): 'upload_blocksize', 'krb_rdns', 'krb_canon_host', - 'use_old_ssl', 'no_ssl_verify', 'serverca', ) @@ -2070,24 +2061,13 @@ class ClientSession(object): self.rsession = None self.new_session() self.opts.setdefault('timeout', 60 * 60 * 12) - self._old_ssl_warning = False def new_session(self): self.logger.debug("Opening new requests session") if self.rsession: self.rsession.close() - if self.opts.get('use_old_ssl', False) or requests is None: - if not self._old_ssl_warning: - # only warn once per instance - self.logger.warn('The use_old_ssl option is deprecated') - self._old_ssl_warning = True - if not six.PY2: - raise GenericError('use_old_ssl is only supported on python2') - import koji.compatrequests - self.rsession = koji.compatrequests.Session() - else: - self.rsession = requests.Session() + self.rsession = requests.Session() def setSession(self, sinfo): """Set the session info @@ -2230,7 +2210,6 @@ class ClientSession(object): raise PythonImportError( "Please install python-requests-kerberos to use GSSAPI." ) - # force https old_baseurl = self.baseurl uri = six.moves.urllib.parse.urlsplit(self.baseurl) diff --git a/koji/compatrequests.py b/koji/compatrequests.py deleted file mode 100644 index 2bd89ac..0000000 --- a/koji/compatrequests.py +++ /dev/null @@ -1,150 +0,0 @@ -""" -koji.compatrequests -~~~~~~~~~~~~~~~~~~~ - -This module contains a *very limited* partial implemention of the requests -module that is based on the older codepaths in koji. It only provides -the bits that koji needs. -""" - -import httplib -import urlparse -import urllib -import sys -import ssl.SSLCommon -from warnings import warn -try: - from ssl import ssl as pyssl -except ImportError: # pragma: no cover - pass - - -class Session(object): - - def __init__(self): - self.connection = None - warn('koji: compatrequests is deprecated', DeprecationWarning) - - def post(self, url, data=None, headers=None, stream=None, verify=None, - cert=None, timeout=None): - uri = urlparse.urlsplit(url) - if uri[3]: - handler = "%s?%s" % (uri[2], uri[3]) - else: - handler = uri[2] - cnx = self.get_connection(uri, cert, verify, timeout) - #cnx.set_debuglevel(1) - cnx.putrequest('POST', handler) - if headers: - for k in headers: - cnx.putheader(k, headers[k]) - cnx.endheaders() - if data is not None: - cnx.send(data) - response = cnx.getresponse() - return Response(self, response) - - def get_connection(self, uri, cert, verify, timeout): - scheme = uri[0] - host, port = urllib.splitport(uri[1]) - key = (scheme, host, cert, verify, timeout) - #if self.connection and self.opts.get('keepalive'): - if self.connection: # XXX honor keepalive - if key == self.connection[0]: - cnx = self.connection[1] - if getattr(cnx, 'sock', None): - return cnx - # Otherwise we make a new one - default_port = 80 - certs = {} - if isinstance(verify, basestring): - certs['peer_ca_cert'] = verify - if cert: - certs['key_and_cert'] = cert - ctx = ssl.SSLCommon.CreateSSLContext(certs) - cnxOpts = {'ssl_context' : ctx} - cnxClass = ssl.SSLCommon.PlgHTTPSConnection - default_port = 443 - elif scheme == 'https': - cnxOpts = {} - if verify: - if sys.version_info[:3] >= (2, 7, 9): - try: - proto = pyssl.PROTOCOL_TLS - except AttributeError: - proto = pyssl.PROTOCOL_SSLv23 - ctx = pyssl.SSLContext(proto) - ctx.load_verify_locations(cafile=verify) - ctx.verify_mode = pyssl.CERT_REQUIRED - cnxOpts['context'] = ctx - else: - cnxOpts['cert_file'] = verify - elif verify is None: - # not specified, leave as default - pass - elif sys.version_info[:3] >= (2, 7, 9): - # no verify - ctx = pyssl._create_unverified_context() - cnxOpts['context'] = ctx - cnxClass = httplib.HTTPSConnection - default_port = 443 - elif scheme == 'http': - cnxOpts = {} - cnxClass = httplib.HTTPConnection - else: - raise IOError("unsupported protocol: %s" % scheme) - - timeout_compat = False - if timeout: - if sys.version_info[:3] < (2, 6, 0) and 'ssl_context' not in cnxOpts: - timeout_compat = True - else: - cnxOpts['timeout'] = timeout - # no need to close connection - port = (port and int(port) or default_port) - cnx = cnxClass(host, port, **cnxOpts) - self.connection = (key, cnx) - if timeout_compat: - # in python < 2.6 httplib does not support the timeout option - # but socket supports it since 2.3 - cnx.connect() - cnx.sock.settimeout(timeout) - return cnx - - def close(self): - if self.connection: - self.connection[1].close() - self.connection = None - - -class Response(object): - - def __init__(self, session, response): - self.session = session - self.response = response - - def raise_for_status(self): - if self.response.status >= 400: - raise httplib.HTTPException("HTTP %s: %s" % (self.response.status, - self.response.reason)) - - - def iter_content(self, blocksize=1): - # should we check this in Session.post()? - # should we even check this here? - if self.response.status != 200: - if (self.response.getheader("content-length", 0)): - self.response.read() - # XXX wrong exception - raise Exception("Server status: %s" % self.response.status) - while True: - chunk = self.response.read(blocksize) - if not chunk: - break - yield chunk - - def close(self): - self.response.close() - - - diff --git a/koji/ssl/Makefile b/koji/ssl/Makefile deleted file mode 100644 index f643700..0000000 --- a/koji/ssl/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -FILES = $(wildcard *.py) - -PYTHON=python - -_default: - @echo "nothing to make. try make install" - -clean: - rm -f *.o *.so *.pyc *~ - -install: - @if [ "$(DESTDIR)" = "" ]; then \ - echo " "; \ - echo "ERROR: A destdir is required"; \ - exit 1; \ - fi - - mkdir -p $(DESTDIR) - install -p -m 644 $(FILES) $(DESTDIR) - - $(PYTHON) -c "import compileall; compileall.compile_dir('$(DESTDIR)', 1, '$(PYDIR)', 1)" diff --git a/koji/ssl/SSLCommon.py b/koji/ssl/SSLCommon.py deleted file mode 100644 index a1ab2bb..0000000 --- a/koji/ssl/SSLCommon.py +++ /dev/null @@ -1,80 +0,0 @@ -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation; either version 2 of the License, or -# (at your option) any later version. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Library General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -# -# Copyright 2005 Dan Williams and Red Hat, Inc. - -import os, sys -from OpenSSL import SSL -import SSLConnection -import httplib -import socket - -def our_verify(connection, x509, errNum, errDepth, preverifyOK): - # print("Verify: errNum = %s, errDepth = %s, preverifyOK = %s" % (errNum, errDepth, preverifyOK)) - - # preverifyOK should tell us whether or not the client's certificate - # correctly authenticates against the CA chain - return preverifyOK - - -def CreateSSLContext(certs): - key_and_cert = certs['key_and_cert'] - peer_ca_cert = certs['peer_ca_cert'] - for f in key_and_cert, peer_ca_cert: - if f and not os.access(f, os.R_OK): - raise Exception("%s does not exist or is not readable" % f) - - ctx = SSL.Context(SSL.SSLv23_METHOD) # Use best possible TLS Method - ctx.use_certificate_file(key_and_cert) - ctx.use_privatekey_file(key_and_cert) - ctx.load_verify_locations(peer_ca_cert) - verify = SSL.VERIFY_PEER | SSL.VERIFY_FAIL_IF_NO_PEER_CERT - ctx.set_verify(verify, our_verify) - ctx.set_verify_depth(10) - ctx.set_options(SSL.OP_NO_SSLv3 | SSL.OP_NO_SSLv2) # disable SSLv2 and SSLv3 - return ctx - - -class PlgHTTPSConnection(httplib.HTTPConnection): - "This class allows communication via SSL." - - response_class = httplib.HTTPResponse - - def __init__(self, host, port=None, ssl_context=None, strict=None, timeout=None): - httplib.HTTPConnection.__init__(self, host, port, strict) - self.ssl_ctx = ssl_context - self._timeout = timeout - - def connect(self): - for res in socket.getaddrinfo(self.host, self.port, 0, socket.SOCK_STREAM): - af, socktype, proto, canonname, sa = res - try: - sock = socket.socket(af, socktype, proto) - con = SSL.Connection(self.ssl_ctx, sock) - self.sock = SSLConnection.SSLConnection(con) - if sys.version_info[:3] >= (2, 3, 0): - self.sock.settimeout(self._timeout) - self.sock.connect(sa) - if self.debuglevel > 0: - print("connect: (%s, %s) [ssl]" % (self.host, self.port)) - except socket.error: - if self.debuglevel > 0: - print('connect fail:', (self.host, self.port)) - if self.sock: - self.sock.close() - self.sock = None - continue - break - else: - raise socket.error("failed to connect") diff --git a/koji/ssl/SSLConnection.py b/koji/ssl/SSLConnection.py deleted file mode 100644 index 2e53db7..0000000 --- a/koji/ssl/SSLConnection.py +++ /dev/null @@ -1,162 +0,0 @@ -# Higher-level SSL objects used by rpclib -# -# Copyright (c) 2002 Red Hat, Inc. -# -# Author: Mihai Ibanescu -# Modifications by Dan Williams - - -from OpenSSL import SSL -import time, socket, select - - -class SSLConnection: - """ - This whole class exists just to filter out a parameter - passed in to the shutdown() method in SimpleXMLRPC.doPOST() - """ - - DEFAULT_TIMEOUT = 600 - - def __init__(self, conn): - """ - Connection is not yet a new-style class, - so I'm making a proxy instead of subclassing. - """ - self.__dict__["conn"] = conn - self.__dict__["close_refcount"] = 1 - self.__dict__["closed"] = False - self.__dict__["timeout"] = self.DEFAULT_TIMEOUT - - def __del__(self): - self.__dict__["conn"].close() - - def __getattr__(self, name): - return getattr(self.__dict__["conn"], name) - - def __setattr__(self, name, value): - setattr(self.__dict__["conn"], name, value) - - def settimeout(self, timeout): - if timeout == None: - self.__dict__["timeout"] = self.DEFAULT_TIMEOUT - else: - self.__dict__["timeout"] = timeout - self.__dict__["conn"].settimeout(timeout) - - def shutdown(self, how=1): - """ - SimpleXMLRpcServer.doPOST calls shutdown(1), - and Connection.shutdown() doesn't take - an argument. So we just discard the argument. - """ - self.__dict__["conn"].shutdown() - - def accept(self): - """ - This is the other part of the shutdown() workaround. - Since servers create new sockets, we have to infect - them with our magic. :) - """ - c, a = self.__dict__["conn"].accept() - return (SSLConnection(c), a) - - def makefile(self, mode='r', bufsize=-1): - """ - We need to use socket._fileobject Because SSL.Connection - doesn't have a 'dup'. Not exactly sure WHY this is, but - this is backed up by comments in socket.py and SSL/connection.c - - Since httplib.HTTPSResponse/HTTPConnection depend on the - socket being duplicated when they close it, we refcount the - socket object and don't actually close until its count is 0. - """ - self.__dict__["close_refcount"] = self.__dict__["close_refcount"] + 1 - return PlgFileObject(self, mode, bufsize) - - def close(self): - if self.__dict__["closed"]: - return - self.__dict__["close_refcount"] = self.__dict__["close_refcount"] - 1 - if self.__dict__["close_refcount"] == 0: - self.shutdown() - self.__dict__["conn"].close() - self.__dict__["closed"] = True - - def sendall(self, data, flags=0): - """ - - Use select() to simulate a socket timeout without setting the socket - to non-blocking mode. - - Don't use pyOpenSSL's sendall() either, since it just loops on WantRead - or WantWrite, consuming 100% CPU, and never times out. - """ - timeout = self.__dict__["timeout"] - con = self.__dict__["conn"] - (read, write, excpt) = select.select([], [con], [], timeout) - if not con in write: - raise socket.timeout((110, "Operation timed out.")) - - starttime = time.time() - origlen = len(data) - sent = -1 - while len(data): - curtime = time.time() - if curtime - starttime > timeout: - raise socket.timeout((110, "Operation timed out.")) - - try: - sent = con.send(data, flags) - except SSL.SysCallError as e: - if e[0] == 32: # Broken Pipe - self.close() - sent = 0 - else: - raise socket.error(e) - except (SSL.WantWriteError, SSL.WantReadError): - time.sleep(0.2) - continue - - data = data[sent:] - return origlen - len(data) - - def recv(self, bufsize, flags=0): - """ - Use select() to simulate a socket timeout without setting the socket - to non-blocking mode - """ - timeout = self.__dict__["timeout"] - con = self.__dict__["conn"] - (read, write, excpt) = select.select([con], [], [], timeout) - if not con in read: - raise socket.timeout((110, "Operation timed out.")) - - starttime = time.time() - while True: - curtime = time.time() - if curtime - starttime > timeout: - raise socket.timeout((110, "Operation timed out.")) - - try: - return con.recv(bufsize, flags) - except SSL.ZeroReturnError: - return None - except SSL.WantReadError: - time.sleep(0.2) - except SSL.SysCallError as e: - if e.args == (-1, 'Unexpected EOF'): - break - raise - return None - -class PlgFileObject(socket._fileobject): - def close(self): - """ - socket._fileobject doesn't actually _close_ the socket, - which we want it to do, so we have to override. - """ - try: - if self._sock: - self.flush() - self._sock.close() - finally: - self._sock = None diff --git a/koji/ssl/__init__.py b/koji/ssl/__init__.py deleted file mode 100644 index 7b4c2b3..0000000 --- a/koji/ssl/__init__.py +++ /dev/null @@ -1,8 +0,0 @@ -# identify this as the ssl module - -# our own ssl submodule masks python's in the main lib, so we import this here -try: - import ssl # python's ssl module -except ImportError: # pragma: no cover - # ssl module added in 2.6 - pass diff --git a/tests/test_lib/test_client_session.py b/tests/test_lib/test_client_session.py index 5edab10..961421a 100644 --- a/tests/test_lib/test_client_session.py +++ b/tests/test_lib/test_client_session.py @@ -34,30 +34,17 @@ class TestClientSession(unittest.TestCase): @mock.patch('requests.Session') def test_new_session(self, rsession): - opts = {'use_old_ssl': False} - ksession = koji.ClientSession('http://koji.example.com/kojihub', opts) + koji.ClientSession('http://koji.example.com/kojihub') # init should have called new_session for us rsession.assert_called_once() @mock.patch('requests.Session') - def test_new_session_old(self, rsession): - if six.PY3: - return - opts = {'use_old_ssl': True} - ksession = koji.ClientSession('http://koji.example.com/kojihub', opts) - - # init should have called new_session for us - - rsession.assert_not_called() - - @mock.patch('requests.Session') def test_new_session_close(self, rsession): if six.PY3: return - opts = {'use_old_ssl': True} - ksession = koji.ClientSession('http://koji.example.com/kojihub', opts) + ksession = koji.ClientSession('http://koji.example.com/kojihub') my_rsession = mock.MagicMock() ksession.rsession = my_rsession @@ -69,7 +56,7 @@ class TestClientSession(unittest.TestCase): class TestFastUpload(unittest.TestCase): def setUp(self): - self.ksession = koji.ClientSession('http://koji.example.com/kojihub', {}) + self.ksession = koji.ClientSession('http://koji.example.com/kojihub') self.do_fake_login() # mocks self.ksession._callMethod = mock.MagicMock() diff --git a/tests/test_lib/test_grab_session_options.py b/tests/test_lib/test_grab_session_options.py index 71d8c3e..98d2f7f 100644 --- a/tests/test_lib/test_grab_session_options.py +++ b/tests/test_lib/test_grab_session_options.py @@ -20,7 +20,6 @@ NORMAL_VAL = {'user': 'jdoe', 'upload_blocksize': 1024, 'krb_rdns': 'fakerdns', 'krb_canon_host': 'fakehost', - 'use_old_ssl': False, 'no_ssl_verify': True, 'serverca': '/fake/serverca.cert', } @@ -43,7 +42,6 @@ NONE_VAL = {'user': None, 'upload_blocksize': None, 'krb_rdns': None, 'krb_canon_host': None, - 'use_old_ssl': None, 'no_ssl_verify': None, 'serverca': None, } diff --git a/tests/test_lib_py2only/test_compatrequests.py b/tests/test_lib_py2only/test_compatrequests.py deleted file mode 100644 index c67f585..0000000 --- a/tests/test_lib_py2only/test_compatrequests.py +++ /dev/null @@ -1,267 +0,0 @@ -import httplib -import mock -import unittest -import urlparse - -import koji.compatrequests - - -class TestResponse(unittest.TestCase): - - def setUp(self): - session = mock.MagicMock() - response = mock.MagicMock() - self.response = koji.compatrequests.Response(session, response) - - def tearDown(self): - del self.response - - def test_read(self): - self.response.response.status = 200 - data = [ - "Here's some data", - "Here's some mooore data", - "And look!", - "Here's a nice block of lorem text", - "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do " - "eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut " - "enim ad minim veniam, quis nostrud exercitation ullamco laboris " - "nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor " - "in reprehenderit in voluptate velit esse cillum dolore eu fugiat " - "nulla pariatur. Excepteur sint occaecat cupidatat non proident, " - "sunt in culpa qui officia deserunt mollit anim id est laborum.", - "", #eof - ] - self.response.response.read.side_effect = data - - result = list(self.response.iter_content(blocksize=10240)) - - self.assertEqual(result, data[:-1]) - rcalls = [mock.call(10240) for s in data] - self.response.response.read.assert_has_calls(rcalls) - - self.response.close() - self.response.response.close.assert_called_once() - - def test_error(self): - self.response.response.status = 404 - self.response.response.getheader.return_value = 0 - with self.assertRaises(Exception): - list(self.response.iter_content(8192)) - self.response.response.read.assert_not_called() - - self.response.response.status = 404 - self.response.response.getheader.return_value = 42 - with self.assertRaises(Exception): - list(self.response.iter_content(8192)) - self.response.response.read.assert_called_once() - - self.response.response.status = 404 - self.response.response.reason = 'Not Found' - self.response.response.getheader.return_value = 42 - with self.assertRaises(httplib.HTTPException): - self.response.raise_for_status() - - - -class TestSessionPost(unittest.TestCase): - - def test_simple(self): - session = koji.compatrequests.Session() - url = 'https://www.fakedomain.org/KOJIHUB' - cnx = mock.MagicMock() - session.get_connection = mock.MagicMock() - session.get_connection.return_value = cnx - response = mock.MagicMock() - cnx.getresponse.return_value = response - - ret = session.post(url, data="data", headers={"foo": "bar"}) - cnx.putrequest.assert_called_once_with('POST', '/KOJIHUB') - cnx.putheader.assert_called_once_with('foo', 'bar') - cnx.send.assert_called_once_with("data") - self.assertEqual(ret.response, response) - - def test_less_simple(self): - session = koji.compatrequests.Session() - url = 'https://www.fakedomain.org/KOJIHUB?a=1&b=2' - cnx = mock.MagicMock() - session.get_connection = mock.MagicMock() - session.get_connection.return_value = cnx - response = mock.MagicMock() - cnx.getresponse.return_value = response - - ret = session.post(url, data="data", headers={"foo": "bar"}, - cert="cert", verify="verify", stream=True, timeout=1701) - cnx.putrequest.assert_called_once_with('POST', '/KOJIHUB?a=1&b=2') - cnx.putheader.assert_called_once_with('foo', 'bar') - cnx.send.assert_called_once_with("data") - self.assertEqual(ret.response, response) - - -class TestSessionConnection(unittest.TestCase): - - @mock.patch('httplib.HTTPConnection') - def test_http(self, HTTPConnection): - # no cert, no verify, no timeout - session = koji.compatrequests.Session() - url = 'http://www.fakedomain234234.org/KOJIHUB?a=1&b=2' - uri = urlparse.urlsplit(url) - - cnx = session.get_connection(uri, None, None, None) - HTTPConnection.assert_called_once_with('www.fakedomain234234.org', 80) - key = ('http', 'www.fakedomain234234.org', None, None, None) - self.assertEqual(session.connection, (key, cnx)) - - # and close it - session.close() - self.assertEqual(session.connection, None) - cnx.close.assert_called_with() - - # double close should not error - session.close() - - def test_cached(self): - session = koji.compatrequests.Session() - url = 'http://www.fakedomain234234.org/KOJIHUB?a=1&b=2' - uri = urlparse.urlsplit(url) - key = ('http', 'www.fakedomain234234.org', None, None, None) - cnx = mock.MagicMock() - session.connection = (key, cnx) - - ret = session.get_connection(uri, None, None, None) - self.assertEqual(ret, cnx) - - def test_badproto(self): - session = koji.compatrequests.Session() - url = 'nosuchproto://www.fakedomain234234.org/KOJIHUB?a=1&b=2' - uri = urlparse.urlsplit(url) - - with self.assertRaises(IOError): - ret = session.get_connection(uri, None, None, None) - - @mock.patch('httplib.HTTPConnection') - @mock.patch('sys.version_info', new=(2, 7, 12, 'final', 0)) - def test_timeout(self, HTTPConnection): - # no cert, no verify - session = koji.compatrequests.Session() - url = 'http://www.fakedomain234234.org/KOJIHUB?a=1&b=2' - uri = urlparse.urlsplit(url) - timeout = 1701 - - cnx = session.get_connection(uri, None, None, 1701) - HTTPConnection.assert_called_once_with('www.fakedomain234234.org', 80, timeout=1701) - key = ('http', 'www.fakedomain234234.org', None, None, 1701) - self.assertEqual(session.connection, (key, cnx)) - - @mock.patch('httplib.HTTPConnection') - @mock.patch('sys.version_info', new=(2, 4, 3, 'final', 0)) - def test_timeout_compat(self, HTTPConnection): - # no cert, no verify - session = koji.compatrequests.Session() - url = 'http://www.fakedomain234234.org/KOJIHUB?a=1&b=2' - uri = urlparse.urlsplit(url) - timeout = 1701 - - cnx = session.get_connection(uri, None, None, 1701) - HTTPConnection.assert_called_once_with('www.fakedomain234234.org', 80) - key = ('http', 'www.fakedomain234234.org', None, None, 1701) - self.assertEqual(session.connection, (key, cnx)) - cnx.connect.assert_called_once() - cnx.sock.settimeout.assert_called_with(1701) - - @mock.patch('httplib.HTTPSConnection') - def test_https(self, HTTPSConnection): - # no cert, no verify, no timeout - session = koji.compatrequests.Session() - url = 'https://www.fakedomain234234.org/KOJIHUB?a=1&b=2' - uri = urlparse.urlsplit(url) - - cnx = session.get_connection(uri, None, None, None) - HTTPSConnection.assert_called_once_with('www.fakedomain234234.org', 443) - key = ('https', 'www.fakedomain234234.org', None, None, None) - self.assertEqual(session.connection, (key, cnx)) - - @mock.patch('koji.ssl.SSLCommon.CreateSSLContext') - @mock.patch('koji.ssl.SSLCommon.PlgHTTPSConnection') - def test_cert(self, PlgHTTPSConnection, CreateSSLContext): - # no verify, no timeout - session = koji.compatrequests.Session() - url = 'https://www.fakedomain234234.org/KOJIHUB?a=1&b=2' - uri = urlparse.urlsplit(url) - cert = '/path/to/cert/file' - context = mock.MagicMock() - CreateSSLContext.return_value = context - - cnx = session.get_connection(uri, cert, None, None) - PlgHTTPSConnection.assert_called_once_with('www.fakedomain234234.org', 443, ssl_context=context) - key = ('https', 'www.fakedomain234234.org', cert, None, None) - self.assertEqual(session.connection, (key, cnx)) - - @mock.patch('ssl._create_unverified_context') - @mock.patch('httplib.HTTPSConnection') - @mock.patch('sys.version_info', new=(2, 7, 12, 'final', 0)) - def test_unverified(self, HTTPSConnection, create_unverified_context): - # no cert, verify=False, no timeout - session = koji.compatrequests.Session() - url = 'https://www.fakedomain234234.org/KOJIHUB?a=1&b=2' - uri = urlparse.urlsplit(url) - context = mock.MagicMock() - create_unverified_context.return_value = context - - cnx = session.get_connection(uri, None, False, None) - create_unverified_context.assert_called_once() - HTTPSConnection.assert_called_once_with('www.fakedomain234234.org', 443, context=context) - key = ('https', 'www.fakedomain234234.org', None, False, None) - self.assertEqual(session.connection, (key, cnx)) - - @mock.patch('httplib.HTTPSConnection') - @mock.patch('sys.version_info', new=(2, 4, 3, 'final', 0)) - def test_unverified_compat(self, HTTPSConnection): - # no cert, verify=False, no timeout - session = koji.compatrequests.Session() - url = 'https://www.fakedomain234234.org/KOJIHUB?a=1&b=2' - uri = urlparse.urlsplit(url) - - cnx = session.get_connection(uri, None, False, None) - HTTPSConnection.assert_called_once_with('www.fakedomain234234.org', 443) - key = ('https', 'www.fakedomain234234.org', None, False, None) - self.assertEqual(session.connection, (key, cnx)) - - @mock.patch('ssl._create_unverified_context') - @mock.patch('ssl.SSLContext') - @mock.patch('httplib.HTTPSConnection') - @mock.patch('sys.version_info', new=(2, 7, 12, 'final', 0)) - def test_verify(self, HTTPSConnection, SSLContext, create_unverified_context): - # no cert, no timeout - session = koji.compatrequests.Session() - url = 'https://www.fakedomain234234.org/KOJIHUB?a=1&b=2' - uri = urlparse.urlsplit(url) - context = mock.MagicMock() - SSLContext.return_value = context - verify = '/path/to/verify/cert' - - cnx = session.get_connection(uri, None, verify, None) - create_unverified_context.assert_not_called() - SSLContext.assert_called_once() - context.load_verify_locations.called_once_with(cafile=verify) - HTTPSConnection.assert_called_once_with('www.fakedomain234234.org', 443, context=context) - key = ('https', 'www.fakedomain234234.org', None, verify, None) - self.assertEqual(session.connection, (key, cnx)) - - @mock.patch('ssl._create_unverified_context') - @mock.patch('ssl.SSLContext') - @mock.patch('httplib.HTTPSConnection') - @mock.patch('sys.version_info', new=(2, 4, 3, 'final', 0)) - def test_verify_compat(self, HTTPSConnection, SSLContext, create_unverified_context): - # no cert, no timeout - session = koji.compatrequests.Session() - url = 'https://www.fakedomain234234.org/KOJIHUB?a=1&b=2' - uri = urlparse.urlsplit(url) - verify = '/path/to/verify/cert' - - cnx = session.get_connection(uri, None, verify, None) - create_unverified_context.assert_not_called() - SSLContext.assert_not_called() - HTTPSConnection.assert_called_once_with('www.fakedomain234234.org', 443, cert_file=verify) - key = ('https', 'www.fakedomain234234.org', None, verify, None) - self.assertEqual(session.connection, (key, cnx)) diff --git a/util/koji-gc b/util/koji-gc index 9c20cdb..89cc492 100755 --- a/util/koji-gc +++ b/util/koji-gc @@ -154,7 +154,6 @@ def get_options(): ['unprotected_keys', None, 'string'], ['grace_period', None, 'string'], ['trashcan_tag', None, 'string'], - ['use_old_ssl', None, 'boolean'], ['no_ssl_verify', None, 'boolean'], ['timeout', None, 'integer'], ] diff --git a/util/kojira b/util/kojira index ba8d6fd..090da5c 100755 --- a/util/kojira +++ b/util/kojira @@ -744,7 +744,6 @@ def get_options(): 'max_retries': 120, 'offline_retry': True, 'offline_retry_interval': 120, - 'use_old_ssl': False, 'no_ssl_verify': False, 'max_delete_processes': 4, 'max_repo_tasks' : 4, @@ -767,7 +766,7 @@ def get_options(): str_opts = ('topdir', 'server', 'user', 'password', 'logfile', 'principal', 'keytab', 'krbservice', 'cert', 'ca', 'serverca', 'debuginfo_tags', 'source_tags') # FIXME: remove ca here bool_opts = ('with_src','verbose','debug','ignore_stray_repos', 'offline_retry', - 'krb_rdns', 'krb_canon_host', 'use_old_ssl', 'no_ssl_verify') + 'krb_rdns', 'krb_canon_host', 'no_ssl_verify') for name in config.options(section): if name in int_opts: defaults[name] = config.getint(section, name) diff --git a/vm/kojivmd b/vm/kojivmd index bc92f0f..41789ec 100755 --- a/vm/kojivmd +++ b/vm/kojivmd @@ -127,7 +127,6 @@ def get_options(): 'server': None, 'user': None, 'password': None, - 'use_old_ssl': False, 'no_ssl_verify': False, 'retry_interval': 60, 'max_retries': 120, @@ -147,7 +146,7 @@ def get_options(): except ValueError: quit("value for %s option must be a valid integer" % name) elif name in ['offline_retry', 'krb_rdns', 'krb_canon_host', - 'use_old_ssl', 'no_ssl_verify']: + 'no_ssl_verify']: defaults[name] = config.getboolean('kojivmd', name) elif name in ['plugin', 'plugins']: defaults['plugin'] = value.split()