Skip to content

Commit

Permalink
Enhancements: (#130)
Browse files Browse the repository at this point in the history
1) Check connectivity using static domain controllers if set
2) Make connectivity check optional
  • Loading branch information
saimonation committed Jul 20, 2021
1 parent 823e572 commit 18ec416
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 20 deletions.
23 changes: 16 additions & 7 deletions cterasdk/edge/directoryservice.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import re
import logging

from ..common import Object
Expand All @@ -17,21 +18,18 @@ def connected(self):
"""
return self._gateway.get('/status/fileservices/cifs/joinStatus') == 0

def connect(self, domain, username, password, ou=None):
def connect(self, domain, username, password, ou=None, check_connection=False):
"""
Connect the Gateway to an Active Directory
:param str domain: The active directory domain to connect to
:param str username: The user name to use when connecting to the active directory services
:param str password: The password to use when connecting to the active directory services
:param str,optional ou: The OU path to use when connecting to the active directory services, defaults to None
:param bool,optional check_connection: Check connectivity before attempting to connect to directory services, defaults to `False`
"""
port = 389
tcp_connect_result = self._gateway.network.tcp_connect(TCPService(domain, port))
if not tcp_connect_result.is_open:
logging.getLogger().error("Connection failed. No traffic allowed over port %(port)s", dict(port=tcp_connect_result.port))
raise CTERAConnectionError('Unable to establish connection', None, host=tcp_connect_result.host,
port=tcp_connect_result.port, protocol='LDAP')
if check_connection:
self._check_domain_connectivity(domain)

cifs = self._gateway.get('/config/fileservices/cifs')
cifs.type = "domain"
Expand All @@ -53,6 +51,17 @@ def connect(self, domain, username, password, ou=None):
raise error
logging.getLogger().info("Connected to Active Directory.")

def _check_domain_connectivity(self, domain):
port = 389
domain_controllers = self.get_static_domain_controller()
domain_controllers = re.findall(r'\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b', domain_controllers) if domain_controllers else [domain]
connection_results = self._gateway.network.diagnose([TCPService(host, port) for host in domain_controllers])
for connection_result in connection_results:
if not connection_result.is_open:
logging.getLogger().error("Connection failed. No traffic allowed over port %(port)s", dict(port=connection_result.port))
raise CTERAConnectionError('Unable to establish connection', None, host=connection_result.host,
port=connection_result.port, protocol='LDAP')

def get_static_domain_controller(self):
"""
Retrieve the static domain controller configuration
Expand Down
47 changes: 34 additions & 13 deletions tests/ut/test_edge_directory_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,14 +37,17 @@ def test_disconnected(self):
self.assertFalse(ret)

def test_connect(self):
get_response = self._get_workgroup_param()
self._init_filer(get_response=get_response)
self._init_filer()
self._filer.get = mock.MagicMock(side_effect=TestEdgeDirectoryService._get_response_side_effect(self._get_workgroup_param(), None))
self._filer.network.tcp_connect = mock.MagicMock(return_value=TCPConnectResult(self._domain, self._ldap_port, True))

directoryservice.DirectoryService(self._filer).connect(self._domain, self._username, self._password)
directoryservice.DirectoryService(self._filer).connect(self._domain, self._username, self._password, check_connection=True)

self._filer.network.tcp_connect.assert_called_once_with(self._ldap_service)
self._filer.get.assert_called_once_with('/config/fileservices/cifs')
self._filer.get.assert_has_calls([
mock.call('/config/fileservices/cifs/passwordServer'),
mock.call('/config/fileservices/cifs')
])
self._filer.put.assert_called_once_with('/config/fileservices/cifs', mock.ANY)

expected_param = self._get_domain_param()
Expand All @@ -57,15 +60,18 @@ def test_connect(self):
self._assert_equal_objects(actual_param, expected_param)

def test_connect_with_ou_path(self):
self._init_filer()
ou_path = "ou=North America,DC=ctera,DC=local"
get_response = self._get_workgroup_param()
self._init_filer(get_response=get_response)
self._filer.get = mock.MagicMock(side_effect=TestEdgeDirectoryService._get_response_side_effect(self._get_workgroup_param(), None))
self._filer.network.tcp_connect = mock.MagicMock(return_value=TCPConnectResult(self._domain, self._ldap_port, True))

directoryservice.DirectoryService(self._filer).connect(self._domain, self._username, self._password, ou_path)
directoryservice.DirectoryService(self._filer).connect(self._domain, self._username, self._password, ou_path, check_connection=True)

self._filer.network.tcp_connect.assert_called_once_with(self._ldap_service)
self._filer.get.assert_called_once_with('/config/fileservices/cifs')
self._filer.get.assert_has_calls([
mock.call('/config/fileservices/cifs/passwordServer'),
mock.call('/config/fileservices/cifs')
])
self._filer.put.assert_called_once_with('/config/fileservices/cifs', mock.ANY)

expected_param = self._get_domain_param()
Expand All @@ -87,17 +93,20 @@ def test_connect_failure_no_connection_over_port(self):
directoryservice.DirectoryService(self._filer).connect(self._domain, self._username, self._password)

def test_connect_join_failure(self):
get_response = self._get_workgroup_param()
self._init_filer(get_response=get_response)
self._init_filer()
self._filer.get = mock.MagicMock(side_effect=TestEdgeDirectoryService._get_response_side_effect(self._get_workgroup_param(), None))
self._filer.network.tcp_connect = mock.MagicMock(return_value=TCPConnectResult(self._domain, self._ldap_port, True))
self._filer.execute = mock.MagicMock(side_effect=task_manager_base.TaskError(self._task_id))

with self.assertRaises(exception.CTERAException):
directoryservice.DirectoryService(self._filer).connect(self._domain, self._username, self._password)
directoryservice.DirectoryService(self._filer).connect(self._domain, self._username, self._password, check_connection=True)

self._filer.network.tcp_connect.assert_called_once_with(self._ldap_service)

self._filer.get.assert_called_once_with('/config/fileservices/cifs')
self._filer.get.assert_has_calls([
mock.call('/config/fileservices/cifs/passwordServer'),
mock.call('/config/fileservices/cifs')
])

self._filer.put.assert_called_once_with('/config/fileservices/cifs', mock.ANY)
expected_param = self._get_domain_param()
Expand All @@ -110,11 +119,13 @@ def test_connect_join_failure(self):
self._assert_equal_objects(actual_param, expected_param)

def test_connect_connection_error(self):
self._init_filer(get_response=None)
self._filer.network.tcp_connect = mock.MagicMock(return_value=TCPConnectResult(self._domain, self._ldap_port, False))

with self.assertRaises(exception.CTERAConnectionError) as error:
directoryservice.DirectoryService(self._filer).connect(self._domain, self._username, self._password)
directoryservice.DirectoryService(self._filer).connect(self._domain, self._username, self._password, check_connection=True)

self._filer.get.assert_called_once_with('/config/fileservices/cifs/passwordServer')
self._filer.network.tcp_connect.assert_called_once_with(self._ldap_service)
self.assertEqual('Unable to establish connection', error.exception.message)

Expand Down Expand Up @@ -213,3 +224,13 @@ def _get_workgroup_param(self):
cifs_param.workgroup = self._workgroup
cifs_param.domain = None
return cifs_param

@staticmethod
def _get_response_side_effect(cifs_param, domain_controllers):
def get_response(path):
if path == '/config/fileservices/cifs/passwordServer':
return domain_controllers
if path == '/config/fileservices/cifs':
return cifs_param
return None
return get_response

0 comments on commit 18ec416

Please sign in to comment.