[python-swiftclient/el6-havana] Update to upstream 1.8.0
Jakub Ruzicka
jruzicka at fedoraproject.org
Tue Dec 10 13:51:05 UTC 2013
commit 9b33617aabc336b2e1177e05f4b189a61d089fd7
Author: Jakub Ruzicka <jruzicka at redhat.com>
Date: Tue Dec 10 14:44:51 2013 +0100
Update to upstream 1.8.0
Changelog:
- Update to upstream 1.8.0
- Add SSL certificate verification by default (CVE-2013-6396)
- New runtime and build dependency: pyOpenSSL
- New runtime dependency: python-keystoneclient
- python-pbr has been removed from runtime by upstream
.gitignore | 1 +
0001-Remove-builtin-requirements-handling.patch | 45 ++
0001-Remove-runtime-dependency-on-python-pbr.patch | 73 --
...d-SSL-certificate-verification-by-default.patch | 809 ++++++++++++++++++++
python-swiftclient.spec | 21 +-
sources | 2 +-
6 files changed, 871 insertions(+), 80 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index 40ed193..fecfadd 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,3 +5,4 @@
/python-swiftclient-1.5.0.tar.gz
/python-swiftclient-1.6.0.tar.gz
/python-swiftclient-1.7.0.tar.gz
+/python-swiftclient-1.8.0.tar.gz
diff --git a/0001-Remove-builtin-requirements-handling.patch b/0001-Remove-builtin-requirements-handling.patch
new file mode 100644
index 0000000..a28f2c5
--- /dev/null
+++ b/0001-Remove-builtin-requirements-handling.patch
@@ -0,0 +1,45 @@
+From 49f2f86b4852d4c4e7fcb1877f051cae490c0fc9 Mon Sep 17 00:00:00 2001
+From: Jakub Ruzicka <jruzicka at redhat.com>
+Date: Fri, 6 Dec 2013 17:36:12 +0100
+Subject: [PATCH] Remove builtin requirements handling
+
+---
+ requirements.txt | 1 -
+ setup.py | 1 -
+ test-requirements.txt | 9 ---------
+ 3 files changed, 11 deletions(-)
+ delete mode 100644 requirements.txt
+ delete mode 100644 test-requirements.txt
+
+diff --git a/requirements.txt b/requirements.txt
+deleted file mode 100644
+index 519b048..0000000
+--- a/requirements.txt
++++ /dev/null
+@@ -1 +0,0 @@
+-simplejson>=2.0.9
+diff --git a/setup.py b/setup.py
+index 70c2b3f..afab729 100644
+--- a/setup.py
++++ b/setup.py
+@@ -18,5 +18,4 @@
+ import setuptools
+
+ setuptools.setup(
+- setup_requires=['pbr'],
+ pbr=True)
+diff --git a/test-requirements.txt b/test-requirements.txt
+deleted file mode 100644
+index 5b78b5f..0000000
+--- a/test-requirements.txt
++++ /dev/null
+@@ -1,9 +0,0 @@
+-hacking>=0.5.6,<0.8
+-
+-coverage>=3.6
+-discover
+-mock>=1.0
+-python-keystoneclient>=0.3.2
+-sphinx>=1.1.2
+-testrepository>=0.0.17
+-testtools>=0.9.32
diff --git a/0002-Add-SSL-certificate-verification-by-default.patch b/0002-Add-SSL-certificate-verification-by-default.patch
new file mode 100644
index 0000000..fd048d7
--- /dev/null
+++ b/0002-Add-SSL-certificate-verification-by-default.patch
@@ -0,0 +1,809 @@
+From a92005b5b92dde8e7269557a50fbc498762ab4b2 Mon Sep 17 00:00:00 2001
+From: Thomas Leaman <thomas.leaman at hp.com>
+Date: Mon, 24 Jun 2013 16:22:55 +0000
+Subject: [PATCH] Add SSL certificate verification by default
+
+Verifies the SSL certificates including matching CNAME.
+Can be turned off with --insecure
+
+Fixes bug 1199783
+
+Change-Id: I168dba604b32e0cb814333d64396926e2bccf242
+---
+ bin/swift | 5 +-
+ swiftclient/client.py | 24 ++---
+ swiftclient/https_connection.py | 162 +++++++++++++++++++++++------
+ tests/test_ssl.py | 225 ++++++++++++++++++++++++++++++++++++++++
+ tests/test_swiftclient.py | 11 +-
+ tests/var/ca.crt | 34 ++++++
+ tests/var/certificate.crt | 66 ++++++++++++
+ tests/var/expired-cert.crt | 35 +++++++
+ tests/var/privatekey.key | 51 +++++++++
+ 9 files changed, 560 insertions(+), 53 deletions(-)
+ create mode 100644 tests/test_ssl.py
+ create mode 100644 tests/var/ca.crt
+ create mode 100644 tests/var/certificate.crt
+ create mode 100644 tests/var/expired-cert.crt
+ create mode 100644 tests/var/privatekey.key
+
+diff --git a/bin/swift b/bin/swift
+index 0de5fbe..e11e62b 100755
+--- a/bin/swift
++++ b/bin/swift
+@@ -1411,9 +1411,8 @@ Examples:
+ parser.add_option('--insecure',
+ action="store_true", dest="insecure",
+ default=default_val,
+- help='Allow swiftclient to access insecure keystone '
+- 'server. The keystone\'s certificate will not '
+- 'be verified. '
++ help='Allow swiftclient to access servers without '
++ 'verifying the SSL certificate. '
+ 'Defaults to env[SWIFTCLIENT_INSECURE] '
+ '(set to \'true\' to enable).')
+ parser.add_option('--no-ssl-compression',
+diff --git a/swiftclient/client.py b/swiftclient/client.py
+index a95ce70..5535a47 100644
+--- a/swiftclient/client.py
++++ b/swiftclient/client.py
+@@ -25,15 +25,11 @@ from functools import wraps
+
+ from urllib import quote as _quote
+ from urlparse import urlparse, urlunparse
+-from httplib import HTTPException, HTTPConnection, HTTPSConnection
++from httplib import HTTPException, HTTPConnection
+ from time import sleep
+
+ from swiftclient.exceptions import ClientException, InvalidHeadersException
+-
+-try:
+- from swiftclient.https_connection import HTTPSConnectionNoSSLComp
+-except ImportError:
+- HTTPSConnectionNoSSLComp = HTTPSConnection
++from swiftclient.https_connection import HTTPSConnection
+
+
+ try:
+@@ -119,13 +115,15 @@ except ImportError:
+ from json import loads as json_loads
+
+
+-def http_connection(url, proxy=None, ssl_compression=True):
++def http_connection(url, proxy=None, insecure=False, ssl_compression=True):
+ """
+ Make an HTTPConnection or HTTPSConnection
+
+ :param url: url to connect to
+ :param proxy: proxy to connect through, if any; None by default; str of the
+ format 'http://127.0.0.1:8888' to set one
++ :param insecure: Allow to access servers without checking SSL certs.
++ The server's certificate will not be verified.
+ :param ssl_compression: Whether to enable compression at the SSL layer.
+ If set to 'False' and the pyOpenSSL library is
+ present an attempt to disable SSL compression
+@@ -141,10 +139,9 @@ def http_connection(url, proxy=None, ssl_compression=True):
+ if parsed.scheme == 'http':
+ conn = HTTPConnection(host)
+ elif parsed.scheme == 'https':
+- if ssl_compression is True:
+- conn = HTTPSConnection(host)
+- else:
+- conn = HTTPSConnectionNoSSLComp(host)
++ conn = HTTPSConnection(host,
++ insecure=insecure,
++ ssl_compression=ssl_compression)
+ else:
+ raise ClientException('Cannot handle protocol scheme %s for url %s' %
+ (parsed.scheme, repr(url)))
+@@ -1043,8 +1040,8 @@ class Connection(object):
+ :param os_options: The OpenStack options which can have tenant_id,
+ auth_token, service_type, endpoint_type,
+ tenant_name, object_storage_url, region_name
+- :param insecure: Allow to access insecure keystone server.
+- The keystone's certificate will not be verified.
++ :param insecure: Allow to access servers without checking SSL certs.
++ The server's certificate will not be verified.
+ :param ssl_compression: Whether to enable compression at the SSL layer.
+ If set to 'False' and the pyOpenSSL library is
+ present an attempt to disable SSL compression
+@@ -1080,6 +1077,7 @@ class Connection(object):
+
+ def http_connection(self):
+ return http_connection(self.url,
++ insecure=self.insecure,
+ ssl_compression=self.ssl_compression)
+
+ def _add_response_dict(self, target_dict, kwargs):
+diff --git a/swiftclient/https_connection.py b/swiftclient/https_connection.py
+index 2a2dc1f..a0cf511 100644
+--- a/swiftclient/https_connection.py
++++ b/swiftclient/https_connection.py
+@@ -18,45 +18,132 @@ HTTPS/SSL related functionality
+ """
+
+ import socket
++import struct
+
+-from httplib import HTTPSConnection
+-
++from httplib import HTTPSConnection as _HTTPSConnection
+ import OpenSSL
+
+-try:
+- from eventlet.green.OpenSSL.SSL import GreenConnection
+- from eventlet.greenio import GreenSocket
+- from eventlet.patcher import is_monkey_patched
+
+- def getsockopt(self, *args, **kwargs):
+- return self.fd.getsockopt(*args, **kwargs)
+- # The above is a workaround for an eventlet bug in getsockopt.
+- # TODO(mclaren): Workaround can be removed when this fix lands:
+- # https://bitbucket.org/eventlet/eventlet/commits/609f230
+- GreenSocket.getsockopt = getsockopt
+-except ImportError:
+- def is_monkey_patched(*args):
+- return False
++class SSLCertificateError(BaseException):
++ pass
++
+
++class SSLConfigurationError(BaseException):
++ pass
+
+-class HTTPSConnectionNoSSLComp(HTTPSConnection):
++
++class HTTPSConnection(_HTTPSConnection):
+ """
+- Extended HTTPSConnection which uses the OpenSSL library
+- for disabling SSL compression.
+- Note: This functionality can eventually be replaced
++ Extended HTTPSConnection which attempts to use the OpenSSL
++ library for enhanced SSL support
++ Note: Much of this functionality can eventually be replaced
+ with native Python 3.3 code.
+ """
+- def __init__(self, host):
+- HTTPSConnection.__init__(self, host)
++ def __init__(self, host, port=None, key_file=None, cert_file=None,
++ cacert=None, timeout=None, insecure=False,
++ ssl_compression=True):
++ _HTTPSConnection.__init__(self, host, port,
++ key_file=key_file,
++ cert_file=cert_file)
++ self.key_file = key_file
++ self.cert_file = cert_file
++ self.timeout = timeout
++ self.insecure = insecure
++ self.ssl_compression = ssl_compression
++ self.cacert = cacert
+ self.setcontext()
+
++ @staticmethod
++ def host_matches_cert(host, x509):
++ """
++ Verify that the the x509 certificate we have received
++ from 'host' correctly identifies the server we are
++ connecting to, ie that the certificate's Common Name
++ or a Subject Alternative Name matches 'host'.
++ """
++ # First see if we can match the CN
++ if x509.get_subject().commonName == host:
++ return True
++
++ # Also try Subject Alternative Names for a match
++ san_list = None
++ for i in xrange(x509.get_extension_count()):
++ ext = x509.get_extension(i)
++ if ext.get_short_name() == 'subjectAltName':
++ san_list = str(ext)
++ for san in ''.join(san_list.split()).split(','):
++ if san == "DNS:%s" % host:
++ return True
++
++ # Server certificate does not match host
++ msg = ('Host "%s" does not match x509 certificate contents: '
++ 'CommonName "%s"' % (host, x509.get_subject().commonName))
++ if san_list is not None:
++ msg = msg + ', subjectAltName "%s"' % san_list
++ raise SSLCertificateError(msg)
++
++ def verify_callback(self, connection, x509, errnum,
++ depth, preverify_ok):
++ # NOTE(leaman): preverify_ok may be a non-boolean type
++ preverify_ok = bool(preverify_ok)
++ if x509.has_expired():
++ msg = "SSL Certificate expired on '%s'" % x509.get_notAfter()
++ raise SSLCertificateError(msg)
++
++ if depth == 0 and preverify_ok:
++ # We verify that the host matches against the last
++ # certificate in the chain
++ return self.host_matches_cert(self.host, x509)
++ else:
++ # Pass through OpenSSL's default result
++ return preverify_ok
++
+ def setcontext(self):
+ """
+ Set up the OpenSSL context.
+ """
+ self.context = OpenSSL.SSL.Context(OpenSSL.SSL.SSLv23_METHOD)
+- # Disable SSL layer compression.
+- self.context.set_options(0x20000) # SSL_OP_NO_COMPRESSION
++
++ if self.ssl_compression is False:
++ self.context.set_options(0x20000) # SSL_OP_NO_COMPRESSION
++
++ if self.insecure is not True:
++ self.context.set_verify(OpenSSL.SSL.VERIFY_PEER,
++ self.verify_callback)
++ else:
++ self.context.set_verify(OpenSSL.SSL.VERIFY_NONE,
++ lambda *args: True)
++
++ if self.cert_file:
++ try:
++ self.context.use_certificate_file(self.cert_file)
++ except Exception as e:
++ msg = 'Unable to load cert from "%s" %s' % (self.cert_file, e)
++ raise SSLConfigurationError(msg)
++ if self.key_file is None:
++ # We support having key and cert in same file
++ try:
++ self.context.use_privatekey_file(self.cert_file)
++ except Exception as e:
++ msg = ('No key file specified and unable to load key '
++ 'from "%s" %s' % (self.cert_file, e))
++ raise SSLConfigurationError(msg)
++
++ if self.key_file:
++ try:
++ self.context.use_privatekey_file(self.key_file)
++ except Exception as e:
++ msg = 'Unable to load key from "%s" %s' % (self.key_file, e)
++ raise SSLConfigurationError(msg)
++
++ if self.cacert:
++ try:
++ self.context.load_verify_locations(self.cacert)
++ except Exception as e:
++ msg = 'Unable to load CA from "%s"' % (self.cacert, e)
++ raise SSLConfigurationError(msg)
++ else:
++ self.context.set_default_verify_paths()
+
+ def connect(self):
+ """
+@@ -64,9 +151,24 @@ class HTTPSConnectionNoSSLComp(HTTPSConnection):
+ per-connection parameters.
+ """
+ sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
++ if self.timeout is not None:
++ # '0' microseconds
++ sock.setsockopt(socket.SOL_SOCKET, socket.SO_RCVTIMEO,
++ struct.pack('fL', self.timeout, 0))
+ self.sock = OpenSSLConnectionDelegator(self.context, sock)
+ self.sock.connect((self.host, self.port))
+
++ def close(self):
++ if self.sock:
++ # Removing reference to socket but don't close it yet.
++ # Response close will close both socket and associated
++ # file. Closing socket too soon will cause response
++ # reads to fail with socket IO error 'Bad file descriptor'.
++ self.sock = None
++
++ # Calling close on HTTPSConnection to continue doing that cleanup.
++ HTTPSConnection.close(self)
++
+
+ class OpenSSLConnectionDelegator(object):
+ """
+@@ -79,17 +181,15 @@ class OpenSSLConnectionDelegator(object):
+ a delegator must be used.
+ """
+ def __init__(self, *args, **kwargs):
+- if is_monkey_patched('socket'):
+- # If we are running in a monkey patched environment
+- # use eventlet's GreenConnection -- it handles eventlet's
+- # non-blocking sockets correctly.
+- Connection = GreenConnection
+- else:
+- Connection = OpenSSL.SSL.Connection
+- self.connection = Connection(*args, **kwargs)
++ self.connection = OpenSSL.SSL.Connection(*args, **kwargs)
+
+ def __getattr__(self, name):
+ return getattr(self.connection, name)
+
+ def makefile(self, *args, **kwargs):
++ # Making sure socket is closed when this file is closed
++ # since we now avoid closing socket on connection close
++ # see new close method under VerifiedHTTPSConnection
++ kwargs['close'] = True
++
+ return socket._fileobject(self.connection, *args, **kwargs)
+diff --git a/tests/test_ssl.py b/tests/test_ssl.py
+new file mode 100644
+index 0000000..b17b8bb
+--- /dev/null
++++ b/tests/test_ssl.py
+@@ -0,0 +1,225 @@
++# Copyright 2013 OpenStack LLC.
++# All Rights Reserved.
++#
++# Licensed under the Apache License, Version 2.0 (the "License"); you may
++# not use this file except in compliance with the License. You may obtain
++# a copy of the License at
++#
++# http://www.apache.org/licenses/LICENSE-2.0
++#
++# Unless required by applicable law or agreed to in writing, software
++# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
++# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
++# License for the specific language governing permissions and limitations
++# under the License.
++
++import os
++
++import testtools
++from OpenSSL import crypto
++
++from swiftclient import https_connection as h
++
++
++TEST_VAR_DIR = os.path.abspath(os.path.join(os.path.dirname(__file__),
++ 'var'))
++
++
++class TestHTTPSConnection(testtools.TestCase):
++ def test_ssl_init_ok(self):
++ """
++ Test HTTPSConnection class init
++ """
++ key_file = os.path.join(TEST_VAR_DIR, 'privatekey.key')
++ cert_file = os.path.join(TEST_VAR_DIR, 'certificate.crt')
++ cacert = os.path.join(TEST_VAR_DIR, 'ca.crt')
++ try:
++ h.HTTPSConnection('127.0.0.1', 0,
++ key_file=key_file,
++ cert_file=cert_file,
++ cacert=cacert)
++ except h.SSLConfigurationError:
++ self.fail('Failed to init HTTPSConnection.')
++
++ def test_ssl_init_cert_no_key(self):
++ """
++ Test HTTPSConnection: absense of SSL key file.
++ """
++ cert_file = os.path.join(TEST_VAR_DIR, 'certificate.crt')
++ cacert = os.path.join(TEST_VAR_DIR, 'ca.crt')
++ try:
++ h.HTTPSConnection('127.0.0.1', 0,
++ cert_file=cert_file,
++ cacert=cacert)
++ self.fail('Failed to raise assertion.')
++ except h.SSLConfigurationError:
++ pass
++
++ def test_ssl_init_key_no_cert(self):
++ """
++ Test HTTPSConnection: absense of SSL cert file.
++ """
++ key_file = os.path.join(TEST_VAR_DIR, 'privatekey.key')
++ cacert = os.path.join(TEST_VAR_DIR, 'ca.crt')
++ try:
++ h.HTTPSConnection('127.0.0.1', 0,
++ key_file=key_file,
++ cacert=cacert)
++ except:
++ self.fail('Failed to init HTTPSConnection.')
++
++ def test_ssl_init_bad_key(self):
++ """
++ Test HTTPSConnection: bad key.
++ """
++ cert_file = os.path.join(TEST_VAR_DIR, 'certificate.crt')
++ cacert = os.path.join(TEST_VAR_DIR, 'ca.crt')
++ try:
++ h.HTTPSConnection('127.0.0.1', 0,
++ cert_file=cert_file,
++ cacert=cacert)
++ self.fail('Failed to raise assertion.')
++ except h.SSLConfigurationError:
++ pass
++
++ def test_ssl_init_bad_cert(self):
++ """
++ Test HTTPSConnection: bad cert.
++ """
++ cert_file = os.path.join(TEST_VAR_DIR, 'badcert.crt')
++ cacert = os.path.join(TEST_VAR_DIR, 'ca.crt')
++ try:
++ h.HTTPSConnection('127.0.0.1', 0,
++ cert_file=cert_file,
++ cacert=cacert)
++ self.fail('Failed to raise assertion.')
++ except h.SSLConfigurationError:
++ pass
++
++ def test_ssl_init_bad_ca(self):
++ """
++ Test HTTPSConnection: bad CA.
++ """
++ cert_file = os.path.join(TEST_VAR_DIR, 'certificate.crt')
++ cacert = os.path.join(TEST_VAR_DIR, 'badca.crt')
++ try:
++ h.HTTPSConnection('127.0.0.1', 0,
++ cert_file=cert_file,
++ cacert=cacert)
++ self.fail('Failed to raise assertion.')
++ except h.SSLConfigurationError:
++ pass
++
++ def test_ssl_cert_cname(self):
++ """
++ Test certificate: CN match
++ """
++ cert_file = os.path.join(TEST_VAR_DIR, 'certificate.crt')
++ cert = crypto.load_certificate(crypto.FILETYPE_PEM,
++ file(cert_file).read())
++ # The expected cert should have CN=0.0.0.0
++ self.assertEqual(cert.get_subject().commonName, '0.0.0.0')
++ try:
++ conn = h.HTTPSConnection('0.0.0.0', 0)
++ conn.verify_callback(None, cert, 0, 0, 1)
++ except:
++ self.fail('Unexpected exception.')
++
++ def test_ssl_cert_subject_alt_name(self):
++ """
++ Test certificate: SAN match
++ """
++ cert_file = os.path.join(TEST_VAR_DIR, 'certificate.crt')
++ cert = crypto.load_certificate(crypto.FILETYPE_PEM,
++ file(cert_file).read())
++ # The expected cert should have CN=0.0.0.0
++ self.assertEqual(cert.get_subject().commonName, '0.0.0.0')
++ try:
++ conn = h.HTTPSConnection('alt1.example.com', 0)
++ conn.verify_callback(None, cert, 0, 0, 1)
++ except:
++ self.fail('Unexpected exception.')
++
++ try:
++ conn = h.HTTPSConnection('alt2.example.com', 0)
++ conn.verify_callback(None, cert, 0, 0, 1)
++ except:
++ self.fail('Unexpected exception.')
++
++ def test_ssl_cert_mismatch(self):
++ """
++ Test certificate: bogus host
++ """
++ cert_file = os.path.join(TEST_VAR_DIR, 'certificate.crt')
++ cert = crypto.load_certificate(crypto.FILETYPE_PEM,
++ file(cert_file).read())
++ # The expected cert should have CN=0.0.0.0
++ self.assertEqual(cert.get_subject().commonName, '0.0.0.0')
++ try:
++ conn = h.HTTPSConnection('mismatch.example.com', 0)
++ except:
++ self.fail('Failed to init HTTPSConnection.')
++
++ self.assertRaises(h.SSLCertificateError,
++ conn.verify_callback, None, cert, 0, 0, 1)
++
++ def test_ssl_expired_cert(self):
++ """
++ Test certificate: out of date cert
++ """
++ cert_file = os.path.join(TEST_VAR_DIR, 'expired-cert.crt')
++ cert = crypto.load_certificate(crypto.FILETYPE_PEM,
++ file(cert_file).read())
++ # The expected expired cert has CN=openstack.example.com
++ self.assertEqual(cert.get_subject().commonName,
++ 'openstack.example.com')
++ try:
++ conn = h.HTTPSConnection('openstack.example.com', 0)
++ except:
++ self.fail('Failed to init HTTPSConnection.')
++
++ self.assertRaises(h.SSLCertificateError,
++ conn.verify_callback, None, cert, 0, 0, 1)
++
++ def test_ssl_broken_key_file(self):
++ """
++ Test verify exception is raised.
++ """
++ cert_file = os.path.join(TEST_VAR_DIR, 'certificate.crt')
++ cacert = os.path.join(TEST_VAR_DIR, 'ca.crt')
++ key_file = 'fake.key'
++ self.assertRaises(
++ h.SSLConfigurationError,
++ h.HTTPSConnection, '127.0.0.1',
++ 0, key_file=key_file,
++ cert_file=cert_file, cacert=cacert)
++
++ def test_ssl_init_ok_with_insecure_true(self):
++ """
++ Test HTTPSConnection class init
++ """
++ key_file = os.path.join(TEST_VAR_DIR, 'privatekey.key')
++ cert_file = os.path.join(TEST_VAR_DIR, 'certificate.crt')
++ cacert = os.path.join(TEST_VAR_DIR, 'ca.crt')
++ try:
++ h.HTTPSConnection('127.0.0.1', 0,
++ key_file=key_file,
++ cert_file=cert_file,
++ cacert=cacert, insecure=True)
++ except h.SSLConfigurationError:
++ self.fail('Failed to init HTTPSConnection.')
++
++ def test_ssl_init_ok_with_ssl_compression_false(self):
++ """
++ Test HTTPSConnection class init
++ """
++ key_file = os.path.join(TEST_VAR_DIR, 'privatekey.key')
++ cert_file = os.path.join(TEST_VAR_DIR, 'certificate.crt')
++ cacert = os.path.join(TEST_VAR_DIR, 'ca.crt')
++ try:
++ h.HTTPSConnection('127.0.0.1', 0,
++ key_file=key_file,
++ cert_file=cert_file,
++ cacert=cacert, ssl_compression=False)
++ except h.SSLConfigurationError:
++ self.fail('Failed to init HTTPSConnection.')
+diff --git a/tests/test_swiftclient.py b/tests/test_swiftclient.py
+index 6cf3c11..10eecde 100644
+--- a/tests/test_swiftclient.py
++++ b/tests/test_swiftclient.py
+@@ -15,7 +15,6 @@
+
+ # TODO: More tests
+ import mock
+-import httplib
+ import socket
+ import StringIO
+ import testtools
+@@ -126,7 +125,7 @@ class MockHttpTest(testtools.TestCase):
+ query_string = kwargs.get('query_string')
+ storage_url = kwargs.get('storage_url')
+
+- def wrapper(url, proxy=None, ssl_compression=True):
++ def wrapper(url, proxy=None, insecure=False, ssl_compression=True):
+ if storage_url:
+ self.assertEqual(storage_url, url)
+
+@@ -187,9 +186,8 @@ class TestHttpHelpers(MockHttpTest):
+ _junk, conn = c.http_connection(url)
+ self.assertTrue(isinstance(conn, c.HTTPConnection))
+ url = 'https://www.test.com'
+- _junk, conn = c.http_connection(url)
+- self.assertTrue(isinstance(conn, httplib.HTTPSConnection) or
+- isinstance(conn, c.HTTPSConnectionNoSSLComp))
++ _junk, conn = c.http_connection(url, insecure=True)
++ self.assertTrue(isinstance(conn, c.HTTPSConnection))
+ url = 'ftp://www.test.com'
+ self.assertRaises(c.ClientException, c.http_connection, url)
+
+@@ -841,7 +839,8 @@ class TestConnection(MockHttpTest):
+ def read(self, *args, **kwargs):
+ return ''
+
+- def local_http_connection(url, proxy=None, ssl_compression=True):
++ def local_http_connection(url, proxy=None, insecure=False,
++ ssl_compression=True):
+ parsed = urlparse(url)
+ return parsed, LocalConnection()
+
+diff --git a/tests/var/ca.crt b/tests/var/ca.crt
+new file mode 100644
+index 0000000..c149d8c
+--- /dev/null
++++ b/tests/var/ca.crt
+@@ -0,0 +1,34 @@
++-----BEGIN CERTIFICATE-----
++MIIF7jCCA9YCCQDbl9qx7iIeJDANBgkqhkiG9w0BAQUFADCBuDEZMBcGA1UEChMQ
++T3BlbnN0YWNrIENBIE9yZzEaMBgGA1UECxMRT3BlbnN0YWNrIFRlc3QgQ0ExIzAh
++BgkqhkiG9w0BCQEWFGFkbWluQGNhLmV4YW1wbGUuY29tMREwDwYDVQQHEwhTdGF0
++ZSBDQTELMAkGA1UECBMCQ0ExCzAJBgNVBAYTAkFVMS0wKwYDVQQDEyRPcGVuc3Rh
++Y2sgVGVzdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMTIxMTE2MTI1MDE2WhcN
++NDAwNDAzMTI1MDE2WjCBuDEZMBcGA1UEChMQT3BlbnN0YWNrIENBIE9yZzEaMBgG
++A1UECxMRT3BlbnN0YWNrIFRlc3QgQ0ExIzAhBgkqhkiG9w0BCQEWFGFkbWluQGNh
++LmV4YW1wbGUuY29tMREwDwYDVQQHEwhTdGF0ZSBDQTELMAkGA1UECBMCQ0ExCzAJ
++BgNVBAYTAkFVMS0wKwYDVQQDEyRPcGVuc3RhY2sgVGVzdCBDZXJ0aWZpY2F0ZSBB
++dXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC94cpBjwj2
++MD0w5j1Jlcy8Ljmk3r7CRaoV5vhWUrAWpT7Thxr/Ti0qAfZZRSIVpvBM0RlseH0Q
++toUJixuYMoNRPUQ74r/TRoO8HfjQDJfnXtWg2L7DRP8p4Zgj3vByBUCU+rKsbI/H
++Nssl/AronADbZXCoL5hJRN8euMYZGrt/Gh1ZotKE5gQlEjylDFlA3s3pn+ABLgzf
++7L7iufwV3zLdPRHCb6Ve8YvUmKfI6gy+WwTRhNhLz4Nj0uBthnj6QhnRXtxkNT7A
++aAStqKH6TtYRnk2Owh8ITFbtLQ0/MSV8jHAxMXx9AloBhEKxv3cIpgLH6lOCnj//
++Ql+H6/QWtmTUHzP1kBfMhTQnWTfR92QTcgEMiZ7a07VyVtLh+kp/G5IUqpM6Pyz/
++O6QDs7FF69bTpws7Ce916PPrGFZ9Gqvo/P0jXge8kYqO+a8QnTRldAxdUzPJCK9+
++Dyi2LWeHf8nPFYdwW9Ov6Jw1CKDYxjJg6KIwnrMPa2eUdPB6/OKkqr9/KemOoKQu
++4KSaYadFZbaJwt7JPZaHy6TpkGxW7Af8RqGrW6a6nWEFcfO2POuHcAHWL5LiRmni
++unm60DBF3b3itDTqCvER3mZE9pN8dqtxdpB8SUX8eq0UJJK2K8mJQS+oE9crbqYb
++1kQbYjhhPLlvOQru+/m/abqZrC04u2OtYQIDAQABMA0GCSqGSIb3DQEBBQUAA4IC
++AQA8wGVBbzfpQ3eYpchiHyHF9N5LIhr6Bt4jYDKLz8DIbElLtoOlgH/v7hLGJ7wu
++R9OteonwQ1qr9umMmnp61bKXOEBJLBJbGKEt0MNLmmX89+M/h3rdMVZEz/Hht/xK
++Xm4di8pjkHfmdhqsbiFW81lAt9W1r74lnH7wQHr9ueALGKDx0hi8pAZ27itgQVHL
++eA1erhw0kjr9BqWpDIskVwePcD7pFoZ48GQlST0uIEq5U+1AWq7AbOABsqODygKi
++Ri5pmTasNFT7nEX3ti4VN214MNy0JnPzTRNWR2rD0I30AebM3KkzTprbLVfnGkm4
++7hOPV+Wc8EjgbbrUAIp2YpOfO/9nbgljTOUsqfjqxzvHx/09XOo2M6NIE5UiHqIq
++TXN7CeGIhBoYbvBAH2QvtveFXv41IYL4zFFXo4wTBSzCCOUGeDDv0U4hhsNaCkDQ
++G2TcubNA4g/FAtqLvPj/6VbIIgFE/1/6acsT+W0O+kkVAb7ej2dpI7J+jKXDXuiA
++PDCMn9dVQ7oAcaQvVdvvRphLdIZ9wHgqKhxKsMwzIMExuDKL0lWe/3sueFyol6nv
++xRCSgzr5MqSObbO3EnWgcUocBvlPyYLnTM2T8C5wh3BGnJXqJSRETggNn8PXBVIm
+++c5o+Ic0mYu4v8P1ZSozFdgf+HLriVPwzJU5dHvvTEu7sw==
++-----END CERTIFICATE-----
+diff --git a/tests/var/certificate.crt b/tests/var/certificate.crt
+new file mode 100644
+index 0000000..06c02ab
+--- /dev/null
++++ b/tests/var/certificate.crt
+@@ -0,0 +1,66 @@
++# Certificate:
++# Data:
++# Version: 3 (0x2)
++# Serial Number: 1 (0x1)
++# Signature Algorithm: sha1WithRSAEncryption
++# Issuer: O=Openstack CA Org, OU=Openstack Test CA/emailAddress=admin at ca.example.com,
++# L=State CA, ST=CA, C=AU, CN=Openstack Test Certificate Authority
++# Validity
++# Not Before: Nov 16 12:50:19 2012 GMT
++# Not After : Apr 3 12:50:19 2040 GMT
++# Subject: O=Openstack Test Org, OU=Openstack Test Unit/emailAddress=admin at example.com,
++# L=State1, ST=CA, C=US, CN=0.0.0.0
++# Subject Public Key Info:
++# Public Key Algorithm: rsaEncryption
++# RSA Public Key: (4096 bit)
++# Modulus (4096 bit):
++# 00:d4:bb:3a:c4:a0:06:54:31:23:5d:b0:78:5a:be:
++# 45:44:ae:a1:89:86:11:d8:ca:a8:33:b0:4f:f3:e1:
++# .
++# .
++# .
++# Exponent: 65537 (0x10001)
++# X509v3 extensions:
++# X509v3 Subject Alternative Name:
++# DNS:alt1.example.com, DNS:alt2.example.com
++# Signature Algorithm: sha1WithRSAEncryption
++# 2c:fc:5c:87:24:bd:4a:fa:40:d2:2e:35:a4:2a:f3:1c:b3:67:
++# b0:e4:8a:cd:67:6b:55:50:d4:cb:dd:2d:26:a5:15:62:90:a3:
++# .
++# .
++# .
++-----BEGIN CERTIFICATE-----
++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
++tdc5rw==
++-----END CERTIFICATE-----
+diff --git a/tests/var/expired-cert.crt b/tests/var/expired-cert.crt
+new file mode 100644
+index 0000000..227d422
+--- /dev/null
++++ b/tests/var/expired-cert.crt
+@@ -0,0 +1,35 @@
++-----BEGIN CERTIFICATE-----
++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
++l3+dFHnWayuCdqcFwIl3m8i8FupFihz9+A==
++-----END CERTIFICATE-----
+diff --git a/tests/var/privatekey.key b/tests/var/privatekey.key
+new file mode 100644
+index 0000000..5b47d44
+--- /dev/null
++++ b/tests/var/privatekey.key
+@@ -0,0 +1,51 @@
++-----BEGIN RSA PRIVATE KEY-----
++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
++-----END RSA PRIVATE KEY-----
diff --git a/python-swiftclient.spec b/python-swiftclient.spec
index ed71fb8..e07f002 100644
--- a/python-swiftclient.spec
+++ b/python-swiftclient.spec
@@ -1,5 +1,5 @@
Name: python-swiftclient
-Version: 1.7.0
+Version: 1.8.0
Release: 1%{?dist}
Summary: Client Library for OpenStack Object Storage API
License: ASL 2.0
@@ -7,12 +7,15 @@ URL: http://pypi.python.org/pypi/%{name}
Source0: http://pypi.python.org/packages/source/p/%{name}/%{name}-%{version}.tar.gz
#
-# patches_base=1.7.0
+# patches_base=1.8.0
#
-Patch0001: 0001-Remove-runtime-dependency-on-python-pbr.patch
+Patch0001: 0001-Remove-builtin-requirements-handling.patch
+Patch0002: 0002-Add-SSL-certificate-verification-by-default.patch
BuildArch: noarch
Requires: python-simplejson
+Requires: python-keystoneclient
+Requires: pyOpenSSL >= 0.12
# /usr/bin/swift collision with older swift-im rhbz#857900
Conflicts: swift < 2.0-0.3
@@ -20,6 +23,7 @@ BuildRequires: python2-devel
BuildRequires: python-setuptools
BuildRequires: python-d2to1
BuildRequires: python-pbr
+BuildRequires: pyOpenSSL
%description
Client library and command line utility for interacting with Openstack
@@ -39,9 +43,7 @@ Object Storage API.
%setup -q
%patch0001 -p1
-
-# We provide version like this in order to remove runtime dep on pbr.
-sed -i s/REDHATSWIFTCLIENTVERSION/%{version}/ swiftclient/version.py
+%patch0002 -p1
# Remove bundled egg-info
rm -rf python_swiftclient.egg-info
@@ -73,6 +75,13 @@ rm -fr doc/build/html/.doctrees doc/build/html/.buildinfo
%doc LICENSE doc/build/html
%changelog
+* Tue Dec 10 2013 Jakub Ruzicka <jruzicka at redhat.com> 1.8.0-1
+- Update to upstream 1.8.0
+- Add SSL certificate verification by default (CVE-2013-6396)
+- New runtime and build dependency: pyOpenSSL
+- New runtime dependency: python-keystoneclient
+- python-pbr has been removed from runtime by upstream
+
* Tue Oct 08 2013 Jakub Ruzicka <jruzicka at redhat.com> - 1.7.0-1
- Update to upstream 1.7.0.
diff --git a/sources b/sources
index 415cac1..8c87381 100644
--- a/sources
+++ b/sources
@@ -1 +1 @@
-6b31fa77d534d82a0053ed605dba01be python-swiftclient-1.7.0.tar.gz
+1f7be5a72f3590d20cf2706d86486927 python-swiftclient-1.8.0.tar.gz
More information about the scm-commits
mailing list