Merge pull request #478 from tianhao64/master
Fix thumbprint verification
This commit is contained in:
@@ -942,8 +942,6 @@ class SoapStubAdapterBase(StubAdapterBase):
|
|||||||
## Subclass of HTTPConnection that connects over a Unix domain socket
|
## Subclass of HTTPConnection that connects over a Unix domain socket
|
||||||
## instead of a TCP port. The path of the socket is passed in place of
|
## instead of a TCP port. The path of the socket is passed in place of
|
||||||
## the hostname. Fairly gross but does the job.
|
## the hostname. Fairly gross but does the job.
|
||||||
# NOTE (hartsock): rewrite this class as a wrapper, see HTTPSConnectionWrapper
|
|
||||||
# below for a guide.
|
|
||||||
class UnixSocketConnection(http_client.HTTPConnection):
|
class UnixSocketConnection(http_client.HTTPConnection):
|
||||||
# The HTTPConnection ctor expects a single argument, which it interprets
|
# The HTTPConnection ctor expects a single argument, which it interprets
|
||||||
# as the host to connect to; for UnixSocketConnection, we instead interpret
|
# as the host to connect to; for UnixSocketConnection, we instead interpret
|
||||||
@@ -999,20 +997,14 @@ except ImportError:
|
|||||||
wrappedSocket = socket.ssl(rawSocket, keyfile, certfile)
|
wrappedSocket = socket.ssl(rawSocket, keyfile, certfile)
|
||||||
return http_client.FakeSocket(rawSocket, wrappedSocket)
|
return http_client.FakeSocket(rawSocket, wrappedSocket)
|
||||||
|
|
||||||
## https connection wrapper
|
|
||||||
|
## Internal version of https connection
|
||||||
#
|
#
|
||||||
# NOTE (hartsock): do not override core library types or implementations
|
|
||||||
# directly because this makes brittle code that is too easy to break and
|
|
||||||
# closely tied to implementation details we do not control. Instead, wrap
|
|
||||||
# the core object to introduce additional behaviors.
|
|
||||||
#
|
|
||||||
# Purpose:
|
|
||||||
# Support ssl.wrap_socket params which are missing from httplib
|
# Support ssl.wrap_socket params which are missing from httplib
|
||||||
# HTTPSConnection (e.g. ca_certs)
|
# HTTPSConnection (e.g. ca_certs)
|
||||||
# Note: Only works iff the ssl params are passing in as kwargs
|
# Note: Only works if the ssl params are passing in as kwargs
|
||||||
class HTTPSConnectionWrapper(object):
|
class _HTTPSConnection(http_client.HTTPSConnection):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
wrapped = http_client.HTTPSConnection(*args, **kwargs)
|
|
||||||
# Extract ssl.wrap_socket param unknown to httplib.HTTPSConnection,
|
# Extract ssl.wrap_socket param unknown to httplib.HTTPSConnection,
|
||||||
# and push back the params in connect()
|
# and push back the params in connect()
|
||||||
self._sslArgs = {}
|
self._sslArgs = {}
|
||||||
@@ -1022,14 +1014,15 @@ class HTTPSConnectionWrapper(object):
|
|||||||
"ciphers"]:
|
"ciphers"]:
|
||||||
if key in tmpKwargs:
|
if key in tmpKwargs:
|
||||||
self._sslArgs[key] = tmpKwargs.pop(key)
|
self._sslArgs[key] = tmpKwargs.pop(key)
|
||||||
self._wrapped = wrapped
|
http_client.HTTPSConnection.__init__(self, *args, **tmpKwargs)
|
||||||
|
|
||||||
## Override connect to allow us to pass in additional ssl paramters to
|
## Override connect to allow us to pass in additional ssl paramters to
|
||||||
# ssl.wrap_socket (e.g. cert_reqs, ca_certs for ca cert verification)
|
# ssl.wrap_socket (e.g. cert_reqs, ca_certs for ca cert verification)
|
||||||
def connect(self, wrapped):
|
def connect(self):
|
||||||
if len(self._sslArgs) == 0 or hasattr(self, '_baseclass'):
|
if len(self._sslArgs) == 0:
|
||||||
# No override
|
# No override
|
||||||
return wrapped.connect
|
http_client.HTTPSConnection.connect(self)
|
||||||
|
return
|
||||||
|
|
||||||
# Big hack. We have to copy and paste the httplib connect fn for
|
# Big hack. We have to copy and paste the httplib connect fn for
|
||||||
# each python version in order to handle extra ssl paramters. Yuk!
|
# each python version in order to handle extra ssl paramters. Yuk!
|
||||||
@@ -1037,30 +1030,34 @@ class HTTPSConnectionWrapper(object):
|
|||||||
# Python 2.7
|
# Python 2.7
|
||||||
sock = socket.create_connection((self.host, self.port),
|
sock = socket.create_connection((self.host, self.port),
|
||||||
self.timeout, self.source_address)
|
self.timeout, self.source_address)
|
||||||
if wrapped._tunnel_host:
|
if self._tunnel_host:
|
||||||
wrapped.sock = sock
|
self.sock = sock
|
||||||
wrapped._tunnel()
|
self._tunnel()
|
||||||
wrapped.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file, **self._sslArgs)
|
self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file,
|
||||||
|
**self._sslArgs)
|
||||||
elif hasattr(self, "timeout"):
|
elif hasattr(self, "timeout"):
|
||||||
# Python 2.6
|
# Python 2.6
|
||||||
sock = socket.create_connection((self.host, self.port), self.timeout)
|
sock = socket.create_connection((self.host, self.port), self.timeout)
|
||||||
wrapped.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file, **self._sslArgs)
|
self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file,
|
||||||
|
**self._sslArgs)
|
||||||
|
else:
|
||||||
|
# Unknown python version. Do nothing
|
||||||
|
http_client.HTTPSConnection.connect(self)
|
||||||
|
return
|
||||||
|
|
||||||
return wrapped.connect
|
# TODO: Additional verification of peer cert if needed
|
||||||
|
# cert_reqs = self._sslArgs.get("cert_reqs", ssl.CERT_NONE)
|
||||||
# TODO: Additional verification of peer cert if needed
|
# ca_certs = self._sslArgs.get("ca_certs", None)
|
||||||
#cert_reqs = self._sslArgs.get("cert_reqs", ssl.CERT_NONE)
|
# if cert_reqs != ssl.CERT_NONE and ca_certs:
|
||||||
#ca_certs = self._sslArgs.get("ca_certs", None)
|
# if hasattr(self.sock, "getpeercert"):
|
||||||
#if cert_reqs != ssl.CERT_NONE and ca_certs:
|
# # TODO: verify peer cert
|
||||||
# if hasattr(self.sock, "getpeercert"):
|
# dercert = self.sock.getpeercert(False)
|
||||||
# # TODO: verify peer cert
|
# # pemcert = ssl.DER_cert_to_PEM_cert(dercert)
|
||||||
# dercert = self.sock.getpeercert(False)
|
|
||||||
# # pemcert = ssl.DER_cert_to_PEM_cert(dercert)
|
|
||||||
|
|
||||||
def __getattr__(self, item):
|
def __getattr__(self, item):
|
||||||
if item == 'connect':
|
if item == 'connect':
|
||||||
return self.connect(self._wrapped)
|
return self.connect(self._wrapped)
|
||||||
return getattr(self._wrapped, item)
|
return getattr(self._wrapped, item)
|
||||||
|
|
||||||
## Stand-in for the HTTPSConnection class that will connect to a proxy and
|
## Stand-in for the HTTPSConnection class that will connect to a proxy and
|
||||||
## issue a CONNECT command to start an SSL tunnel.
|
## issue a CONNECT command to start an SSL tunnel.
|
||||||
@@ -1222,10 +1219,10 @@ class SoapStubAdapter(SoapStubAdapterBase):
|
|||||||
if urlpath not in ('', '/'):
|
if urlpath not in ('', '/'):
|
||||||
path = urlpath
|
path = urlpath
|
||||||
self.scheme = scheme == "http" and http_client.HTTPConnection \
|
self.scheme = scheme == "http" and http_client.HTTPConnection \
|
||||||
or scheme == "https" and HTTPSConnectionWrapper
|
or scheme == "https" and _HTTPSConnection
|
||||||
else:
|
else:
|
||||||
port, self.scheme = port < 0 and (-port, http_client.HTTPConnection) \
|
port, self.scheme = port < 0 and (-port, http_client.HTTPConnection) \
|
||||||
or (port, HTTPSConnectionWrapper)
|
or (port, _HTTPSConnection)
|
||||||
if host.find(':') != -1: # is IPv6?
|
if host.find(':') != -1: # is IPv6?
|
||||||
host = '[' + host + ']'
|
host = '[' + host + ']'
|
||||||
self.host = '{0}:{1}'.format(host, port)
|
self.host = '{0}:{1}'.format(host, port)
|
||||||
@@ -1243,7 +1240,7 @@ class SoapStubAdapter(SoapStubAdapterBase):
|
|||||||
self.scheme = SSLTunnelConnection(sslProxyPath)
|
self.scheme = SSLTunnelConnection(sslProxyPath)
|
||||||
self.is_ssl_tunnel = True
|
self.is_ssl_tunnel = True
|
||||||
elif httpProxyHost:
|
elif httpProxyHost:
|
||||||
if self.scheme == HTTPSConnectionWrapper:
|
if self.scheme == _HTTPSConnection:
|
||||||
self.scheme = SSLTunnelConnection(self.host)
|
self.scheme = SSLTunnelConnection(self.host)
|
||||||
self.is_ssl_tunnel = True
|
self.is_ssl_tunnel = True
|
||||||
else:
|
else:
|
||||||
@@ -1279,7 +1276,7 @@ class SoapStubAdapter(SoapStubAdapterBase):
|
|||||||
# depend on the behavior that close() still leaves the socket semi-functional.
|
# depend on the behavior that close() still leaves the socket semi-functional.
|
||||||
if sys.version_info[:2] < (2,7):
|
if sys.version_info[:2] < (2,7):
|
||||||
def _CloseConnection(self, conn):
|
def _CloseConnection(self, conn):
|
||||||
if self.scheme == HTTPSConnectionWrapper and conn.sock:
|
if self.scheme == _HTTPSConnection and conn.sock:
|
||||||
conn.sock.shutdown(socket.SHUT_RDWR)
|
conn.sock.shutdown(socket.SHUT_RDWR)
|
||||||
conn.close()
|
conn.close()
|
||||||
else:
|
else:
|
||||||
|
@@ -14,9 +14,14 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import unittest
|
|
||||||
import vcr
|
|
||||||
import socket
|
import socket
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
import vcr
|
||||||
|
from vcr import config
|
||||||
|
from vcr.stubs import VCRHTTPSConnection
|
||||||
|
|
||||||
|
from pyVmomi import SoapAdapter
|
||||||
|
|
||||||
|
|
||||||
def tests_resource_path(local_path=''):
|
def tests_resource_path(local_path=''):
|
||||||
@@ -33,6 +38,8 @@ def monkey_patch_vcrpy():
|
|||||||
vcr.stubs.VCRFakeSocket = socket.socket
|
vcr.stubs.VCRFakeSocket = socket.socket
|
||||||
|
|
||||||
class VCRTestBase(unittest.TestCase):
|
class VCRTestBase(unittest.TestCase):
|
||||||
|
my_vcr = config.VCR(
|
||||||
|
custom_patches=((SoapAdapter, '_HTTPSConnection', VCRHTTPSConnection),))
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
monkey_patch_vcrpy()
|
monkey_patch_vcrpy()
|
||||||
|
@@ -15,7 +15,6 @@
|
|||||||
|
|
||||||
import tests
|
import tests
|
||||||
import unittest
|
import unittest
|
||||||
import vcr
|
|
||||||
|
|
||||||
from pyVim import connect
|
from pyVim import connect
|
||||||
from pyVmomi import vim
|
from pyVmomi import vim
|
||||||
@@ -23,7 +22,7 @@ from pyVmomi import vim
|
|||||||
|
|
||||||
class ConnectionTests(tests.VCRTestBase):
|
class ConnectionTests(tests.VCRTestBase):
|
||||||
|
|
||||||
@vcr.use_cassette('basic_connection.yaml',
|
@tests.VCRTestBase.my_vcr.use_cassette('basic_connection.yaml',
|
||||||
cassette_library_dir=tests.fixtures_path,
|
cassette_library_dir=tests.fixtures_path,
|
||||||
record_mode='none')
|
record_mode='none')
|
||||||
def test_basic_connection(self):
|
def test_basic_connection(self):
|
||||||
@@ -40,7 +39,7 @@ class ConnectionTests(tests.VCRTestBase):
|
|||||||
self.assertTrue(session_id is not None)
|
self.assertTrue(session_id is not None)
|
||||||
self.assertEqual('52b5395a-85c2-9902-7835-13a9b77e1fec', session_id)
|
self.assertEqual('52b5395a-85c2-9902-7835-13a9b77e1fec', session_id)
|
||||||
|
|
||||||
@vcr.use_cassette('sspi_connection.yaml',
|
@tests.VCRTestBase.my_vcr.use_cassette('sspi_connection.yaml',
|
||||||
cassette_library_dir=tests.fixtures_path,
|
cassette_library_dir=tests.fixtures_path,
|
||||||
record_mode='none')
|
record_mode='none')
|
||||||
def test_sspi_connection(self):
|
def test_sspi_connection(self):
|
||||||
@@ -57,7 +56,7 @@ class ConnectionTests(tests.VCRTestBase):
|
|||||||
self.assertTrue(session_id is not None)
|
self.assertTrue(session_id is not None)
|
||||||
self.assertEqual('52b5395a-85c2-9902-7835-13a9b77e1fec', session_id)
|
self.assertEqual('52b5395a-85c2-9902-7835-13a9b77e1fec', session_id)
|
||||||
|
|
||||||
@vcr.use_cassette('basic_connection_bad_password.yaml',
|
@tests.VCRTestBase.my_vcr.use_cassette('basic_connection_bad_password.yaml',
|
||||||
cassette_library_dir=tests.fixtures_path,
|
cassette_library_dir=tests.fixtures_path,
|
||||||
record_mode='none')
|
record_mode='none')
|
||||||
def test_basic_connection_bad_password(self):
|
def test_basic_connection_bad_password(self):
|
||||||
@@ -68,7 +67,7 @@ class ConnectionTests(tests.VCRTestBase):
|
|||||||
|
|
||||||
self.assertRaises(vim.fault.InvalidLogin, should_fail)
|
self.assertRaises(vim.fault.InvalidLogin, should_fail)
|
||||||
|
|
||||||
@vcr.use_cassette('smart_connection.yaml',
|
@tests.VCRTestBase.my_vcr.use_cassette('smart_connection.yaml',
|
||||||
cassette_library_dir=tests.fixtures_path,
|
cassette_library_dir=tests.fixtures_path,
|
||||||
record_mode='none')
|
record_mode='none')
|
||||||
def test_smart_connection(self):
|
def test_smart_connection(self):
|
||||||
@@ -84,13 +83,13 @@ class ConnectionTests(tests.VCRTestBase):
|
|||||||
def test_disconnect_on_no_connection(self):
|
def test_disconnect_on_no_connection(self):
|
||||||
connect.Disconnect(None)
|
connect.Disconnect(None)
|
||||||
|
|
||||||
@vcr.use_cassette('ssl_tunnel.yaml',
|
@tests.VCRTestBase.my_vcr.use_cassette('ssl_tunnel.yaml',
|
||||||
cassette_library_dir=tests.fixtures_path,
|
cassette_library_dir=tests.fixtures_path,
|
||||||
record_mode='none')
|
record_mode='none')
|
||||||
def test_ssl_tunnel(self):
|
def test_ssl_tunnel(self):
|
||||||
connect.SoapStubAdapter('sdkTunnel', 8089, httpProxyHost='vcsa').GetConnection()
|
connect.SoapStubAdapter('sdkTunnel', 8089, httpProxyHost='vcsa').GetConnection()
|
||||||
|
|
||||||
@vcr.use_cassette('ssl_tunnel_http_failure.yaml',
|
@tests.VCRTestBase.my_vcr.use_cassette('ssl_tunnel_http_failure.yaml',
|
||||||
cassette_library_dir=tests.fixtures_path,
|
cassette_library_dir=tests.fixtures_path,
|
||||||
record_mode='none')
|
record_mode='none')
|
||||||
def test_ssl_tunnel_http_failure(self):
|
def test_ssl_tunnel_http_failure(self):
|
||||||
|
@@ -13,7 +13,6 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
import tests
|
import tests
|
||||||
import vcr
|
|
||||||
|
|
||||||
from pyVim import connect
|
from pyVim import connect
|
||||||
from pyVmomi import vim
|
from pyVmomi import vim
|
||||||
@@ -21,7 +20,7 @@ from pyVmomi import vim
|
|||||||
|
|
||||||
class ContainerViewTests(tests.VCRTestBase):
|
class ContainerViewTests(tests.VCRTestBase):
|
||||||
|
|
||||||
@vcr.use_cassette('basic_container_view.yaml',
|
@tests.VCRTestBase.my_vcr.use_cassette('basic_container_view.yaml',
|
||||||
cassette_library_dir=tests.fixtures_path,
|
cassette_library_dir=tests.fixtures_path,
|
||||||
record_mode='once')
|
record_mode='once')
|
||||||
def test_basic_container_view(self):
|
def test_basic_container_view(self):
|
||||||
|
@@ -16,15 +16,18 @@ from datetime import datetime
|
|||||||
from datetime import timedelta
|
from datetime import timedelta
|
||||||
|
|
||||||
import tests
|
import tests
|
||||||
import vcr
|
|
||||||
|
|
||||||
from pyVim import connect
|
from pyVim import connect
|
||||||
from pyVmomi.Iso8601 import TZManager
|
from pyVmomi.Iso8601 import TZManager
|
||||||
|
from pyVmomi import SoapAdapter
|
||||||
|
|
||||||
|
from vcr.stubs import VCRHTTPSConnection
|
||||||
|
from vcr import config
|
||||||
|
|
||||||
|
|
||||||
class Iso8601Tests(tests.VCRTestBase):
|
class Iso8601Tests(tests.VCRTestBase):
|
||||||
|
|
||||||
@vcr.use_cassette('test_vm_config_iso8601.yaml',
|
@tests.VCRTestBase.my_vcr.use_cassette('test_vm_config_iso8601.yaml',
|
||||||
cassette_library_dir=tests.fixtures_path,
|
cassette_library_dir=tests.fixtures_path,
|
||||||
record_mode='once')
|
record_mode='once')
|
||||||
def test_vm_config_iso8601(self):
|
def test_vm_config_iso8601(self):
|
||||||
@@ -76,7 +79,9 @@ class Iso8601Tests(tests.VCRTestBase):
|
|||||||
return False
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
my_vcr = vcr.VCR()
|
my_vcr = config.VCR(
|
||||||
|
custom_patches=(
|
||||||
|
(SoapAdapter, '_HTTPSConnection', VCRHTTPSConnection),))
|
||||||
my_vcr.register_matcher('document', check_date_time_value)
|
my_vcr.register_matcher('document', check_date_time_value)
|
||||||
|
|
||||||
# NOTE (hartsock): the `match_on` option is altered to use the
|
# NOTE (hartsock): the `match_on` option is altered to use the
|
||||||
|
@@ -15,14 +15,13 @@
|
|||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
import tests
|
import tests
|
||||||
import vcr
|
|
||||||
|
|
||||||
from pyVim import connect
|
from pyVim import connect
|
||||||
|
|
||||||
|
|
||||||
class ManagedObjectTests(tests.VCRTestBase):
|
class ManagedObjectTests(tests.VCRTestBase):
|
||||||
|
|
||||||
@vcr.use_cassette('root_folder_parent.yaml',
|
@tests.VCRTestBase.my_vcr.use_cassette('root_folder_parent.yaml',
|
||||||
cassette_library_dir=tests.fixtures_path,
|
cassette_library_dir=tests.fixtures_path,
|
||||||
record_mode='once')
|
record_mode='once')
|
||||||
def test_root_folder_parent(self):
|
def test_root_folder_parent(self):
|
||||||
|
@@ -13,8 +13,8 @@
|
|||||||
# See the License for the specific language governing permissions and
|
# See the License for the specific language governing permissions and
|
||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
import tests
|
import tests
|
||||||
import vcr
|
from vcr.stubs import VCRHTTPSConnection
|
||||||
|
from vcr import config
|
||||||
|
|
||||||
from pyVmomi import SoapAdapter
|
from pyVmomi import SoapAdapter
|
||||||
from pyVmomi import SoapStubAdapter
|
from pyVmomi import SoapStubAdapter
|
||||||
@@ -22,6 +22,7 @@ from pyVmomi import vim
|
|||||||
from pyVmomi.VmomiSupport import GetRequestContext
|
from pyVmomi.VmomiSupport import GetRequestContext
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class SerializerTests(tests.VCRTestBase):
|
class SerializerTests(tests.VCRTestBase):
|
||||||
def test_serialize_object(self):
|
def test_serialize_object(self):
|
||||||
val = vim.vm.device.VirtualDeviceSpec.FileOperation()
|
val = vim.vm.device.VirtualDeviceSpec.FileOperation()
|
||||||
@@ -40,7 +41,9 @@ class SerializerTests(tests.VCRTestBase):
|
|||||||
SoapAdapter.Serialize(pc, version='vim.version.version10')
|
SoapAdapter.Serialize(pc, version='vim.version.version10')
|
||||||
|
|
||||||
def _base_serialize_test(self, soap_creator, request_matcher):
|
def _base_serialize_test(self, soap_creator, request_matcher):
|
||||||
my_vcr = vcr.VCR()
|
my_vcr = config.VCR(
|
||||||
|
custom_patches=(
|
||||||
|
(SoapAdapter, '_HTTPSConnection', VCRHTTPSConnection),))
|
||||||
my_vcr.register_matcher('request_matcher', request_matcher)
|
my_vcr.register_matcher('request_matcher', request_matcher)
|
||||||
|
|
||||||
with my_vcr.use_cassette(
|
with my_vcr.use_cassette(
|
||||||
|
@@ -15,7 +15,6 @@
|
|||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
import tests
|
import tests
|
||||||
import vcr
|
|
||||||
|
|
||||||
from pyVim import connect
|
from pyVim import connect
|
||||||
from pyVmomi import vim
|
from pyVmomi import vim
|
||||||
@@ -23,7 +22,7 @@ from pyVmomi import vim
|
|||||||
|
|
||||||
class VirtualMachineTests(tests.VCRTestBase):
|
class VirtualMachineTests(tests.VCRTestBase):
|
||||||
|
|
||||||
@vcr.use_cassette('vm_nic_data.yaml',
|
@tests.VCRTestBase.my_vcr.use_cassette('vm_nic_data.yaml',
|
||||||
cassette_library_dir=tests.fixtures_path,
|
cassette_library_dir=tests.fixtures_path,
|
||||||
record_mode='never')
|
record_mode='never')
|
||||||
def test_vm_nic_data(self):
|
def test_vm_nic_data(self):
|
||||||
|
Reference in New Issue
Block a user