Basic support for client cert authentication
Add client_cert_file to nsxlib initialization. If specified, nsxlib will authenticate with client certificate. If unspecified (default), basic user/pwd authentication is used. Change-Id: If36841e9fd9701fa173ffa294732415dc07d49e7
This commit is contained in:
parent
fc115e4605
commit
c9063831c3
|
@ -30,6 +30,7 @@ NSX_PASSWORD = 'default'
|
||||||
NSX_MANAGER = '1.2.3.4'
|
NSX_MANAGER = '1.2.3.4'
|
||||||
NSX_INSECURE = False
|
NSX_INSECURE = False
|
||||||
NSX_CERT = '/opt/stack/certs/nsx.pem'
|
NSX_CERT = '/opt/stack/certs/nsx.pem'
|
||||||
|
CLIENT_CERT = '/opt/stack/certs/client.pem'
|
||||||
NSX_HTTP_RETRIES = 10
|
NSX_HTTP_RETRIES = 10
|
||||||
NSX_HTTP_TIMEOUT = 10
|
NSX_HTTP_TIMEOUT = 10
|
||||||
NSX_HTTP_READ_TIMEOUT = 180
|
NSX_HTTP_READ_TIMEOUT = 180
|
||||||
|
@ -108,13 +109,37 @@ def get_default_nsxlib_config():
|
||||||
plugin_ver=PLUGIN_VER)
|
plugin_ver=PLUGIN_VER)
|
||||||
|
|
||||||
|
|
||||||
|
def get_nsxlib_config_with_client_cert():
|
||||||
|
return config.NsxLibConfig(
|
||||||
|
client_cert_file=CLIENT_CERT,
|
||||||
|
retries=NSX_HTTP_RETRIES,
|
||||||
|
insecure=NSX_INSECURE,
|
||||||
|
ca_file=NSX_CERT,
|
||||||
|
concurrent_connections=NSX_CONCURENT_CONN,
|
||||||
|
http_timeout=NSX_HTTP_TIMEOUT,
|
||||||
|
http_read_timeout=NSX_HTTP_READ_TIMEOUT,
|
||||||
|
conn_idle_timeout=NSX_CONN_IDLE_TIME,
|
||||||
|
http_provider=None,
|
||||||
|
nsx_api_managers=[],
|
||||||
|
plugin_scope=PLUGIN_SCOPE,
|
||||||
|
plugin_tag=PLUGIN_TAG,
|
||||||
|
plugin_ver=PLUGIN_VER)
|
||||||
|
|
||||||
|
|
||||||
class NsxLibTestCase(unittest.TestCase):
|
class NsxLibTestCase(unittest.TestCase):
|
||||||
|
|
||||||
|
def use_client_cert_auth(self):
|
||||||
|
return False
|
||||||
|
|
||||||
def setUp(self, *args, **kwargs):
|
def setUp(self, *args, **kwargs):
|
||||||
super(NsxLibTestCase, self).setUp()
|
super(NsxLibTestCase, self).setUp()
|
||||||
_mock_nsxlib()
|
_mock_nsxlib()
|
||||||
|
|
||||||
|
if self.use_client_cert_auth():
|
||||||
|
nsxlib_config = get_nsxlib_config_with_client_cert()
|
||||||
|
else:
|
||||||
nsxlib_config = get_default_nsxlib_config()
|
nsxlib_config = get_default_nsxlib_config()
|
||||||
|
|
||||||
self.nsxlib = v3.NsxLib(nsxlib_config)
|
self.nsxlib = v3.NsxLib(nsxlib_config)
|
||||||
|
|
||||||
# print diffs when assert comparisons fail
|
# print diffs when assert comparisons fail
|
||||||
|
|
|
@ -58,6 +58,25 @@ class RequestsHTTPProviderTestCase(unittest.TestCase):
|
||||||
self.assertEqual(session.adapters['https://'].max_retries.total, 100)
|
self.assertEqual(session.adapters['https://'].max_retries.total, 100)
|
||||||
self.assertEqual(session.timeout, 99)
|
self.assertEqual(session.timeout, 99)
|
||||||
|
|
||||||
|
def test_new_connection_with_client_auth(self):
|
||||||
|
mock_api = mock.Mock()
|
||||||
|
mock_api.nsxlib_config = mock.Mock()
|
||||||
|
mock_api.nsxlib_config.retries = 100
|
||||||
|
mock_api.nsxlib_config.insecure = True
|
||||||
|
mock_api.nsxlib_config.ca_file = None
|
||||||
|
mock_api.nsxlib_config.http_timeout = 99
|
||||||
|
mock_api.nsxlib_config.conn_idle_timeout = 39
|
||||||
|
provider = cluster.NSXRequestsHTTPProvider()
|
||||||
|
session = provider.new_connection(
|
||||||
|
mock_api, cluster.Provider('9.8.7.6', 'https://9.8.7.6',
|
||||||
|
None, None, None,
|
||||||
|
'/etc/cert.pem'))
|
||||||
|
|
||||||
|
self.assertEqual(session.auth, None)
|
||||||
|
self.assertEqual(session.verify, False)
|
||||||
|
self.assertEqual(session.cert, '/etc/cert.pem')
|
||||||
|
self.assertEqual(session.timeout, 99)
|
||||||
|
|
||||||
def test_validate_connection(self):
|
def test_validate_connection(self):
|
||||||
self.skipTest("Revist")
|
self.skipTest("Revist")
|
||||||
mock_conn = mocks.MockRequestSessionApi()
|
mock_conn = mocks.MockRequestSessionApi()
|
||||||
|
@ -125,6 +144,14 @@ class NsxV3ClusteredAPITestCase(nsxlib_testcase.NsxClientTestCase):
|
||||||
self.assertEqual(kwargs['timeout'], (7, 37))
|
self.assertEqual(kwargs['timeout'], (7, 37))
|
||||||
|
|
||||||
|
|
||||||
|
# Repeat the above tests with client cert present
|
||||||
|
# in NsxLib initialization
|
||||||
|
class NsxV3ClusteredAPIWithClientCertTestCase(NsxV3ClusteredAPITestCase):
|
||||||
|
|
||||||
|
def use_client_cert_auth(self):
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
class ClusteredAPITestCase(nsxlib_testcase.NsxClientTestCase):
|
class ClusteredAPITestCase(nsxlib_testcase.NsxClientTestCase):
|
||||||
|
|
||||||
def _test_health(self, validate_fn, expected_health):
|
def _test_health(self, validate_fn, expected_health):
|
||||||
|
|
|
@ -121,7 +121,11 @@ class NSXRequestsHTTPProvider(AbstractHTTPProvider):
|
||||||
config = cluster_api.nsxlib_config
|
config = cluster_api.nsxlib_config
|
||||||
session = TimeoutSession(config.http_timeout,
|
session = TimeoutSession(config.http_timeout,
|
||||||
config.http_read_timeout)
|
config.http_read_timeout)
|
||||||
|
if provider.client_cert_file:
|
||||||
|
session.cert = provider.client_cert_file
|
||||||
|
else:
|
||||||
session.auth = (provider.username, provider.password)
|
session.auth = (provider.username, provider.password)
|
||||||
|
|
||||||
# NSX v3 doesn't use redirects
|
# NSX v3 doesn't use redirects
|
||||||
session.max_redirects = 0
|
session.max_redirects = 0
|
||||||
|
|
||||||
|
@ -172,11 +176,13 @@ class Provider(object):
|
||||||
a connection URL, and the credential details.
|
a connection URL, and the credential details.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, provider_id, provider_url, username, password, ca_file):
|
def __init__(self, provider_id, provider_url,
|
||||||
|
username, password, ca_file, client_cert_file=None):
|
||||||
self.id = provider_id
|
self.id = provider_id
|
||||||
self.url = provider_url
|
self.url = provider_url
|
||||||
self.username = username
|
self.username = username
|
||||||
self.password = password
|
self.password = password
|
||||||
|
self.client_cert_file = client_cert_file
|
||||||
self.ca_file = ca_file
|
self.ca_file = ca_file
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
@ -489,5 +495,6 @@ class NSXClusteredAPI(ClusteredAPI):
|
||||||
urlparse.urlunparse(conf_url),
|
urlparse.urlunparse(conf_url),
|
||||||
self.nsxlib_config.username(provider_index),
|
self.nsxlib_config.username(provider_index),
|
||||||
self.nsxlib_config.password(provider_index),
|
self.nsxlib_config.password(provider_index),
|
||||||
self.nsxlib_config.ca_file(provider_index)))
|
self.nsxlib_config.ca_file(provider_index),
|
||||||
|
self.nsxlib_config.client_cert_file(provider_index)))
|
||||||
return providers
|
return providers
|
||||||
|
|
|
@ -25,6 +25,10 @@ class NsxLibConfig(object):
|
||||||
and port 443 for https.
|
and port 443 for https.
|
||||||
:param username: User name for the NSX manager
|
:param username: User name for the NSX manager
|
||||||
:param password: Password for the NSX manager
|
:param password: Password for the NSX manager
|
||||||
|
:param client_cert_file: Specify a file containing client certificate and
|
||||||
|
private key. If specified, nsxlib will use client
|
||||||
|
cert authentication instead of basic
|
||||||
|
authentication.
|
||||||
:param insecure: If true, the NSX Manager server certificate is not
|
:param insecure: If true, the NSX Manager server certificate is not
|
||||||
verified. If false the CA bundle specified via "ca_file"
|
verified. If false the CA bundle specified via "ca_file"
|
||||||
will be used or if unsest the default system root CAs
|
will be used or if unsest the default system root CAs
|
||||||
|
@ -67,6 +71,7 @@ class NsxLibConfig(object):
|
||||||
nsx_api_managers=None,
|
nsx_api_managers=None,
|
||||||
username=None,
|
username=None,
|
||||||
password=None,
|
password=None,
|
||||||
|
client_cert_file=None,
|
||||||
insecure=True,
|
insecure=True,
|
||||||
ca_file=None,
|
ca_file=None,
|
||||||
concurrent_connections=10,
|
concurrent_connections=10,
|
||||||
|
@ -86,6 +91,7 @@ class NsxLibConfig(object):
|
||||||
self.nsx_api_managers = nsx_api_managers
|
self.nsx_api_managers = nsx_api_managers
|
||||||
self._username = username
|
self._username = username
|
||||||
self._password = password
|
self._password = password
|
||||||
|
self._client_cert_file = client_cert_file
|
||||||
self._ca_file = ca_file
|
self._ca_file = ca_file
|
||||||
self.insecure = insecure
|
self.insecure = insecure
|
||||||
self.concurrent_connections = concurrent_connections
|
self.concurrent_connections = concurrent_connections
|
||||||
|
@ -119,5 +125,8 @@ class NsxLibConfig(object):
|
||||||
def password(self, index):
|
def password(self, index):
|
||||||
return self._attribute_by_index(self._password, index)
|
return self._attribute_by_index(self._password, index)
|
||||||
|
|
||||||
|
def client_cert_file(self, index):
|
||||||
|
return self._attribute_by_index(self._client_cert_file, index)
|
||||||
|
|
||||||
def ca_file(self, index):
|
def ca_file(self, index):
|
||||||
return self._attribute_by_index(self._ca_file, index)
|
return self._attribute_by_index(self._ca_file, index)
|
||||||
|
|
Loading…
Reference in New Issue