Merge pull request #478 from tianhao64/master
Fix thumbprint verification
This commit is contained in:
commit
46f5ecaebb
@ -942,8 +942,6 @@ class SoapStubAdapterBase(StubAdapterBase):
|
||||
## 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
|
||||
## 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):
|
||||
# The HTTPConnection ctor expects a single argument, which it interprets
|
||||
# as the host to connect to; for UnixSocketConnection, we instead interpret
|
||||
@ -999,20 +997,14 @@ except ImportError:
|
||||
wrappedSocket = socket.ssl(rawSocket, keyfile, certfile)
|
||||
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
|
||||
# HTTPSConnection (e.g. ca_certs)
|
||||
# Note: Only works iff the ssl params are passing in as kwargs
|
||||
class HTTPSConnectionWrapper(object):
|
||||
# Note: Only works if the ssl params are passing in as kwargs
|
||||
class _HTTPSConnection(http_client.HTTPSConnection):
|
||||
def __init__(self, *args, **kwargs):
|
||||
wrapped = http_client.HTTPSConnection(*args, **kwargs)
|
||||
# Extract ssl.wrap_socket param unknown to httplib.HTTPSConnection,
|
||||
# and push back the params in connect()
|
||||
self._sslArgs = {}
|
||||
@ -1022,14 +1014,15 @@ class HTTPSConnectionWrapper(object):
|
||||
"ciphers"]:
|
||||
if key in tmpKwargs:
|
||||
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
|
||||
# ssl.wrap_socket (e.g. cert_reqs, ca_certs for ca cert verification)
|
||||
def connect(self, wrapped):
|
||||
if len(self._sslArgs) == 0 or hasattr(self, '_baseclass'):
|
||||
def connect(self):
|
||||
if len(self._sslArgs) == 0:
|
||||
# No override
|
||||
return wrapped.connect
|
||||
http_client.HTTPSConnection.connect(self)
|
||||
return
|
||||
|
||||
# Big hack. We have to copy and paste the httplib connect fn for
|
||||
# each python version in order to handle extra ssl paramters. Yuk!
|
||||
@ -1037,30 +1030,34 @@ class HTTPSConnectionWrapper(object):
|
||||
# Python 2.7
|
||||
sock = socket.create_connection((self.host, self.port),
|
||||
self.timeout, self.source_address)
|
||||
if wrapped._tunnel_host:
|
||||
wrapped.sock = sock
|
||||
wrapped._tunnel()
|
||||
wrapped.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file, **self._sslArgs)
|
||||
if self._tunnel_host:
|
||||
self.sock = sock
|
||||
self._tunnel()
|
||||
self.sock = ssl.wrap_socket(sock, self.key_file, self.cert_file,
|
||||
**self._sslArgs)
|
||||
elif hasattr(self, "timeout"):
|
||||
# Python 2.6
|
||||
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)
|
||||
#ca_certs = self._sslArgs.get("ca_certs", None)
|
||||
#if cert_reqs != ssl.CERT_NONE and ca_certs:
|
||||
# if hasattr(self.sock, "getpeercert"):
|
||||
# # TODO: verify peer cert
|
||||
# dercert = self.sock.getpeercert(False)
|
||||
# # pemcert = ssl.DER_cert_to_PEM_cert(dercert)
|
||||
# TODO: Additional verification of peer cert if needed
|
||||
# cert_reqs = self._sslArgs.get("cert_reqs", ssl.CERT_NONE)
|
||||
# ca_certs = self._sslArgs.get("ca_certs", None)
|
||||
# if cert_reqs != ssl.CERT_NONE and ca_certs:
|
||||
# if hasattr(self.sock, "getpeercert"):
|
||||
# # TODO: verify peer cert
|
||||
# dercert = self.sock.getpeercert(False)
|
||||
# # pemcert = ssl.DER_cert_to_PEM_cert(dercert)
|
||||
|
||||
def __getattr__(self, item):
|
||||
if item == 'connect':
|
||||
return self.connect(self._wrapped)
|
||||
return getattr(self._wrapped, item)
|
||||
if item == 'connect':
|
||||
return self.connect(self._wrapped)
|
||||
return getattr(self._wrapped, item)
|
||||
|
||||
## Stand-in for the HTTPSConnection class that will connect to a proxy and
|
||||
## issue a CONNECT command to start an SSL tunnel.
|
||||
@ -1222,10 +1219,10 @@ class SoapStubAdapter(SoapStubAdapterBase):
|
||||
if urlpath not in ('', '/'):
|
||||
path = urlpath
|
||||
self.scheme = scheme == "http" and http_client.HTTPConnection \
|
||||
or scheme == "https" and HTTPSConnectionWrapper
|
||||
or scheme == "https" and _HTTPSConnection
|
||||
else:
|
||||
port, self.scheme = port < 0 and (-port, http_client.HTTPConnection) \
|
||||
or (port, HTTPSConnectionWrapper)
|
||||
or (port, _HTTPSConnection)
|
||||
if host.find(':') != -1: # is IPv6?
|
||||
host = '[' + host + ']'
|
||||
self.host = '{0}:{1}'.format(host, port)
|
||||
@ -1243,7 +1240,7 @@ class SoapStubAdapter(SoapStubAdapterBase):
|
||||
self.scheme = SSLTunnelConnection(sslProxyPath)
|
||||
self.is_ssl_tunnel = True
|
||||
elif httpProxyHost:
|
||||
if self.scheme == HTTPSConnectionWrapper:
|
||||
if self.scheme == _HTTPSConnection:
|
||||
self.scheme = SSLTunnelConnection(self.host)
|
||||
self.is_ssl_tunnel = True
|
||||
else:
|
||||
@ -1279,7 +1276,7 @@ class SoapStubAdapter(SoapStubAdapterBase):
|
||||
# depend on the behavior that close() still leaves the socket semi-functional.
|
||||
if sys.version_info[:2] < (2,7):
|
||||
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.close()
|
||||
else:
|
||||
|
@ -14,9 +14,14 @@
|
||||
# limitations under the License.
|
||||
import logging
|
||||
import os
|
||||
import unittest
|
||||
import vcr
|
||||
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=''):
|
||||
@ -33,6 +38,8 @@ def monkey_patch_vcrpy():
|
||||
vcr.stubs.VCRFakeSocket = socket.socket
|
||||
|
||||
class VCRTestBase(unittest.TestCase):
|
||||
my_vcr = config.VCR(
|
||||
custom_patches=((SoapAdapter, '_HTTPSConnection', VCRHTTPSConnection),))
|
||||
|
||||
def setUp(self):
|
||||
monkey_patch_vcrpy()
|
||||
|
@ -15,7 +15,6 @@
|
||||
|
||||
import tests
|
||||
import unittest
|
||||
import vcr
|
||||
|
||||
from pyVim import connect
|
||||
from pyVmomi import vim
|
||||
@ -23,7 +22,7 @@ from pyVmomi import vim
|
||||
|
||||
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,
|
||||
record_mode='none')
|
||||
def test_basic_connection(self):
|
||||
@ -40,7 +39,7 @@ class ConnectionTests(tests.VCRTestBase):
|
||||
self.assertTrue(session_id is not None)
|
||||
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,
|
||||
record_mode='none')
|
||||
def test_sspi_connection(self):
|
||||
@ -57,7 +56,7 @@ class ConnectionTests(tests.VCRTestBase):
|
||||
self.assertTrue(session_id is not None)
|
||||
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,
|
||||
record_mode='none')
|
||||
def test_basic_connection_bad_password(self):
|
||||
@ -68,7 +67,7 @@ class ConnectionTests(tests.VCRTestBase):
|
||||
|
||||
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,
|
||||
record_mode='none')
|
||||
def test_smart_connection(self):
|
||||
@ -84,13 +83,13 @@ class ConnectionTests(tests.VCRTestBase):
|
||||
def test_disconnect_on_no_connection(self):
|
||||
connect.Disconnect(None)
|
||||
|
||||
@vcr.use_cassette('ssl_tunnel.yaml',
|
||||
@tests.VCRTestBase.my_vcr.use_cassette('ssl_tunnel.yaml',
|
||||
cassette_library_dir=tests.fixtures_path,
|
||||
record_mode='none')
|
||||
def test_ssl_tunnel(self):
|
||||
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,
|
||||
record_mode='none')
|
||||
def test_ssl_tunnel_http_failure(self):
|
||||
|
@ -13,7 +13,6 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
import tests
|
||||
import vcr
|
||||
|
||||
from pyVim import connect
|
||||
from pyVmomi import vim
|
||||
@ -21,7 +20,7 @@ from pyVmomi import vim
|
||||
|
||||
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,
|
||||
record_mode='once')
|
||||
def test_basic_container_view(self):
|
||||
|
@ -16,15 +16,18 @@ from datetime import datetime
|
||||
from datetime import timedelta
|
||||
|
||||
import tests
|
||||
import vcr
|
||||
|
||||
from pyVim import connect
|
||||
from pyVmomi.Iso8601 import TZManager
|
||||
from pyVmomi import SoapAdapter
|
||||
|
||||
from vcr.stubs import VCRHTTPSConnection
|
||||
from vcr import config
|
||||
|
||||
|
||||
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,
|
||||
record_mode='once')
|
||||
def test_vm_config_iso8601(self):
|
||||
@ -76,7 +79,9 @@ class Iso8601Tests(tests.VCRTestBase):
|
||||
return False
|
||||
return True
|
||||
|
||||
my_vcr = vcr.VCR()
|
||||
my_vcr = config.VCR(
|
||||
custom_patches=(
|
||||
(SoapAdapter, '_HTTPSConnection', VCRHTTPSConnection),))
|
||||
my_vcr.register_matcher('document', check_date_time_value)
|
||||
|
||||
# NOTE (hartsock): the `match_on` option is altered to use the
|
||||
|
@ -15,14 +15,13 @@
|
||||
from __future__ import print_function
|
||||
|
||||
import tests
|
||||
import vcr
|
||||
|
||||
from pyVim import connect
|
||||
|
||||
|
||||
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,
|
||||
record_mode='once')
|
||||
def test_root_folder_parent(self):
|
||||
|
@ -13,8 +13,8 @@
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
import tests
|
||||
import vcr
|
||||
|
||||
from vcr.stubs import VCRHTTPSConnection
|
||||
from vcr import config
|
||||
|
||||
from pyVmomi import SoapAdapter
|
||||
from pyVmomi import SoapStubAdapter
|
||||
@ -22,6 +22,7 @@ from pyVmomi import vim
|
||||
from pyVmomi.VmomiSupport import GetRequestContext
|
||||
|
||||
|
||||
|
||||
class SerializerTests(tests.VCRTestBase):
|
||||
def test_serialize_object(self):
|
||||
val = vim.vm.device.VirtualDeviceSpec.FileOperation()
|
||||
@ -40,7 +41,9 @@ class SerializerTests(tests.VCRTestBase):
|
||||
SoapAdapter.Serialize(pc, version='vim.version.version10')
|
||||
|
||||
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)
|
||||
|
||||
with my_vcr.use_cassette(
|
||||
|
@ -15,7 +15,6 @@
|
||||
from __future__ import print_function
|
||||
|
||||
import tests
|
||||
import vcr
|
||||
|
||||
from pyVim import connect
|
||||
from pyVmomi import vim
|
||||
@ -23,7 +22,7 @@ from pyVmomi import vim
|
||||
|
||||
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,
|
||||
record_mode='never')
|
||||
def test_vm_nic_data(self):
|
||||
|
Loading…
x
Reference in New Issue
Block a user