Setup CA cert verification for compatibility with previous libcloud (but requests bundles CA now), fixed route53 tests, fixed httplib_ssl tests
Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/3a492b8a Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/3a492b8a Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/3a492b8a Branch: refs/heads/requests Commit: 3a492b8abca690093513a24433b899dd3bf1de4b Parents: d0f6d22 Author: anthony-shaw <anthony.p.s...@gmail.com> Authored: Tue Apr 5 16:30:10 2016 +1000 Committer: anthony-shaw <anthony.p.s...@gmail.com> Committed: Tue Apr 5 16:30:10 2016 +1000 ---------------------------------------------------------------------- libcloud/httplib_ssl.py | 17 ++++- libcloud/test/dns/fixtures/route53/get_zone.xml | 1 - .../fixtures/route53/record_does_not_exist.xml | 17 ----- libcloud/test/test_httplib_ssl.py | 66 -------------------- libcloud/test/test_response_classes.py | 14 ++--- 5 files changed, 23 insertions(+), 92 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/libcloud/blob/3a492b8a/libcloud/httplib_ssl.py ---------------------------------------------------------------------- diff --git a/libcloud/httplib_ssl.py b/libcloud/httplib_ssl.py index b8d9286..1207243 100644 --- a/libcloud/httplib_ssl.py +++ b/libcloud/httplib_ssl.py @@ -21,6 +21,7 @@ import socket import requests +import libcloud.security from libcloud.utils.py3 import urlparse @@ -68,8 +69,12 @@ class LibcloudBaseConnection(object): http_proxy_used = False + ca_cert = None + def __init__(self): self.session = requests.Session() + self.verify = True + self.ca_cert = None def set_http_proxy(self, proxy_url): """ @@ -137,6 +142,15 @@ class LibcloudBaseConnection(object): return (proxy_scheme, proxy_host, proxy_port, proxy_username, proxy_password) + def _setup_verify(self): + self.verify = libcloud.security.VERIFY_SSL_CERT + + def _setup_ca_cert(self): + if self.verify is False: + pass + else: + self.ca_cert = libcloud.security.CA_CERTS_PATH + class LibcloudConnection(LibcloudBaseConnection): timeout = None @@ -165,7 +179,8 @@ class LibcloudConnection(LibcloudBaseConnection): data=body, headers=headers, allow_redirects=1, - stream=raw + stream=raw, + verify=self.ca_cert if self.ca_cert is not None else self.verify ) def getresponse(self): http://git-wip-us.apache.org/repos/asf/libcloud/blob/3a492b8a/libcloud/test/dns/fixtures/route53/get_zone.xml ---------------------------------------------------------------------- diff --git a/libcloud/test/dns/fixtures/route53/get_zone.xml b/libcloud/test/dns/fixtures/route53/get_zone.xml index 3a1ffbe..c7e5be8 100644 --- a/libcloud/test/dns/fixtures/route53/get_zone.xml +++ b/libcloud/test/dns/fixtures/route53/get_zone.xml @@ -1,4 +1,3 @@ - <?xml version="1.0" encoding="UTF-8"?> <GetHostedZoneResponse xmlns="https://route53.amazonaws.com/doc/2012-02-29/"> <HostedZone> http://git-wip-us.apache.org/repos/asf/libcloud/blob/3a492b8a/libcloud/test/dns/fixtures/route53/record_does_not_exist.xml ---------------------------------------------------------------------- diff --git a/libcloud/test/dns/fixtures/route53/record_does_not_exist.xml b/libcloud/test/dns/fixtures/route53/record_does_not_exist.xml deleted file mode 100644 index 6a767d1..0000000 --- a/libcloud/test/dns/fixtures/route53/record_does_not_exist.xml +++ /dev/null @@ -1,17 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<ListResourceRecordSetsResponse xmlns="https://route53.amazonaws.com/doc/2012-02-29/"> - <ResourceRecordSets> - - <ResourceRecordSet> - <Name>definitely.not.what.you.askedfor.t.com</Name> - <Type>CNAME</Type> - <TTL>86400</TTL> - <ResourceRecords> - <ResourceRecord> - <Value>t.com</Value> - </ResourceRecord> - </ResourceRecords> - </ResourceRecordSet> - - </ResourceRecordSets> -</ListResourceRecordSetsResponse> \ No newline at end of file http://git-wip-us.apache.org/repos/asf/libcloud/blob/3a492b8a/libcloud/test/test_httplib_ssl.py ---------------------------------------------------------------------- diff --git a/libcloud/test/test_httplib_ssl.py b/libcloud/test/test_httplib_ssl.py index 55d1b23..9c96df4 100644 --- a/libcloud/test/test_httplib_ssl.py +++ b/libcloud/test/test_httplib_ssl.py @@ -70,20 +70,6 @@ class TestHttpLibSSLTests(unittest.TestCase): self.assertEqual(libcloud.security.CA_CERTS_PATH, [file_path]) @patch('warnings.warn') - def test_setup_verify(self, _): - libcloud.security.CA_CERTS_PATH = [] - - # Should throw a runtime error - libcloud.security.VERIFY_SSL_CERT = True - - expected_msg = libcloud.security.CA_CERTS_UNAVAILABLE_ERROR_MSG - self.assertRaisesRegexp(RuntimeError, expected_msg, - self.httplib_object._setup_verify) - - libcloud.security.VERIFY_SSL_CERT = False - self.httplib_object._setup_verify() - - @patch('warnings.warn') def test_setup_ca_cert(self, _): # verify = False, _setup_ca_cert should be a no-op self.httplib_object.verify = False @@ -100,58 +86,6 @@ class TestHttpLibSSLTests(unittest.TestCase): self.assertTrue(self.httplib_object.ca_cert is not None) - # verify = True, no CA certs are available, exception should be thrown - libcloud.security.CA_CERTS_PATH = [] - - expected_msg = libcloud.security.CA_CERTS_UNAVAILABLE_ERROR_MSG - self.assertRaisesRegexp(RuntimeError, expected_msg, - self.httplib_object._setup_ca_cert) - - @mock.patch('socket.create_connection', mock.MagicMock()) - @mock.patch('socket.socket', mock.MagicMock()) - @mock.patch('ssl.wrap_socket') - def test_connect_throws_friendly_error_message_on_ssl_wrap_connection_reset_by_peer(self, mock_wrap_socket): - # Test that we re-throw a more friendly error message in case - # "connection reset by peer" error occurs when trying to establish a - # SSL connection - libcloud.security.VERIFY_SSL_CERT = True - self.httplib_object.verify = True - self.httplib_object.http_proxy_used = False - - # No connection reset by peer, original exception should be thrown - mock_wrap_socket.side_effect = Exception('foo bar fail') - - expected_msg = 'foo bar fail' - self.assertRaisesRegexp(Exception, expected_msg, - self.httplib_object.connect) - - # Connection reset by peer, wrapped exception with friendly error - # message should be thrown - mock_wrap_socket.side_effect = socket.error('Connection reset by peer') - - expected_msg = 'Failed to establish SSL / TLS connection' - self.assertRaisesRegexp(socket.error, expected_msg, - self.httplib_object.connect) - - # Same error but including errno - with self.assertRaises(socket.error) as cm: - mock_wrap_socket.side_effect = socket.error(104, 'Connection reset by peer') - self.httplib_object.connect() - - e = cm.exception - self.assertEqual(e.errno, 104) - self.assertTrue(expected_msg in str(e)) - - # Test original exception is propagated correctly on non reset by peer - # error - with self.assertRaises(socket.error) as cm: - mock_wrap_socket.side_effect = socket.error(105, 'Some random error') - self.httplib_object.connect() - - e = cm.exception - self.assertEqual(e.errno, 105) - self.assertTrue('Some random error' in str(e)) - if __name__ == '__main__': sys.exit(unittest.main()) http://git-wip-us.apache.org/repos/asf/libcloud/blob/3a492b8a/libcloud/test/test_response_classes.py ---------------------------------------------------------------------- diff --git a/libcloud/test/test_response_classes.py b/libcloud/test/test_response_classes.py index ceeab4c..0bdd06a 100644 --- a/libcloud/test/test_response_classes.py +++ b/libcloud/test/test_response_classes.py @@ -34,7 +34,7 @@ class ResponseClassesTests(unittest.TestCase): self._mock_connection = Mock() def test_XmlResponse_class(self): - self._mock_response.read.return_value = '<foo>bar</foo>' + self._mock_response.text = '<foo>bar</foo>' response = XmlResponse(response=self._mock_response, connection=self._mock_connection) @@ -43,7 +43,7 @@ class ResponseClassesTests(unittest.TestCase): self.assertEqual(parsed.text, 'bar') def test_XmlResponse_class_malformed_response(self): - self._mock_response.read.return_value = '<foo>' + self._mock_response.text = '<foo>' try: XmlResponse(response=self._mock_response, @@ -54,7 +54,7 @@ class ResponseClassesTests(unittest.TestCase): self.fail('Exception was not thrown') def test_XmlResponse_class_zero_length_body_strip(self): - self._mock_response.read.return_value = ' ' + self._mock_response.text = ' ' response = XmlResponse(response=self._mock_response, connection=self._mock_connection) @@ -71,7 +71,7 @@ class ResponseClassesTests(unittest.TestCase): self.assertEqual(parsed, {'foo': 'bar'}) def test_JsonResponse_class_malformed_response(self): - self._mock_response.read.return_value = '{"foo": "bar' + self._mock_response.text = '{"foo": "bar' try: JsonResponse(response=self._mock_response, @@ -82,7 +82,7 @@ class ResponseClassesTests(unittest.TestCase): self.fail('Exception was not thrown') def test_JsonResponse_class_zero_length_body_strip(self): - self._mock_response.read.return_value = ' ' + self._mock_response.text = ' ' response = JsonResponse(response=self._mock_response, connection=self._mock_connection) @@ -94,7 +94,7 @@ class ResponseClassesTests(unittest.TestCase): original_data = 'foo bar ponies, wooo zlib' compressed_data = zlib.compress(b(original_data)) - self._mock_response.read.return_value = compressed_data + self._mock_response.text = compressed_data self._mock_response.getheaders.return_value = \ {'Content-Encoding': 'deflate'} @@ -127,7 +127,7 @@ class ResponseClassesTests(unittest.TestCase): stream.close() compressed_data = string_io.getvalue() - self._mock_response.read.return_value = compressed_data + self._mock_response.text = compressed_data self._mock_response.getheaders.return_value = \ {'Content-Encoding': 'gzip'}