class BaseLdapTestCase(TestCase): USER_LDAP_ID = LdapObject.MIN_LDAP_UID USER_FULL_DN = 'uid=johnlennon,ou=people,' + settings.LDAP_BASE_DN USER_GROUP_FULL_DN = 'cn=johnlennon,ou=groups,' + settings.LDAP_BASE_DN def setUp(self): info = ('dc=local', { 'dc': ['local']}) adrf = (settings.LDAP_BASE_DN, { 'dc': ['dfadmin']}) admin = (settings.LDAP_SETTINGS['Connection']['BindDN'], { 'cn': [ 'admin'], 'userPassword': [settings.LDAP_SETTINGS['Connection']['BindPassword']]}) people = ('ou=People,' + settings.LDAP_BASE_DN, {'ou': ['People']}) groups = ('ou=Groups,' + settings.LDAP_BASE_DN, {'ou': ['Groups']}) projects = ('ou=Projects,' + settings.LDAP_BASE_DN, {'ou': ['Projects']}) datasets = ('ou=Datasets,' + settings.LDAP_BASE_DN, {'ou': ['Datasets']}) directory = dict([info, adrf, admin, people, groups, projects, datasets]) self.mockldap = MockLdap(directory) self.mockldap.start() self.ldapobj = self.mockldap[settings.LDAP_SERVER] def tearDown(self): self.mockldap.stop() del self.ldapobj @classmethod def setUser(cls, ldap_id=USER_LDAP_ID, ldap_name=None, first_name="John", last_name="Lennon", email="*****@*****.**", status=User.STATUS_ACTIVE, ldap_last_auth_time=None, ldap_lock_time=None, ldap_last_pwd_change=None, created_at=None, updated_at=None, system_user=False): result = User.objects.filter(ldap_id=ldap_id) if len(result) == 0: u = User(ldap_id=ldap_id) else: u = result[0] u.first_name = first_name u.last_name = last_name u.email = email u.status = status u.system_user = system_user if ldap_last_auth_time: u.ldap_last_auth_time = ldap_last_auth_time if ldap_lock_time: u.ldap_lock_time = ldap_lock_time if ldap_last_pwd_change: u.ldap_last_pwd_change = ldap_last_pwd_change if ldap_name: u.ldap_name = ldap_name if created_at: u.created_at = created_at u.save()
def test_department(self): ''' Test department lookups. ''' mockldap = MockLdap({ 'o=Novell': {'o': 'Novell'}, 'cn=mcihar,o=Novell': { 'mail': ['*****@*****.**'], 'ou': ['TestDept'], 'cn': ['mcihar'], 'uid': ['mcihar'], }, 'cn=foobar,o=Novell': { 'mail': ['*****@*****.**'], 'ou': ['L3 Maintenance'], 'cn': ['foobar'], 'uid': ['foobar'], }, }) mockldap.start() try: userinfo = UserInfo('ldap://ldap', 'o=novell') # By mail with fixup self.assertEqual( 'L3/Maintenance', userinfo.get_department('*****@*****.**') ) # By UID self.assertEqual( 'TestDept', userinfo.get_department('mcihar') ) # By UID from cache self.assertEqual( 'TestDept', userinfo.get_department('mcihar') ) # By email self.assertEqual( 'TestDept', userinfo.get_department('*****@*****.**') ) # Hardcoded entries self.assertEqual( 'Security team', userinfo.get_department('*****@*****.**') ) # Non existing entry self.assertEqual( 'N/A', userinfo.get_department('nobody') ) finally: mockldap.stop()
def test_update_with_external_auth(self): # Run a mock LDAP. mockldap = MockLdap({ "dc=quay,dc=io": { "dc": ["quay", "io"] }, "ou=employees,dc=quay,dc=io": { "dc": ["quay", "io"], "ou": "employees" }, "uid=" + ADMIN_ACCESS_USER + ",ou=employees,dc=quay,dc=io": { "dc": ["quay", "io"], "ou": "employees", "uid": [ADMIN_ACCESS_USER], "userPassword": ["password"], "mail": [ADMIN_ACCESS_EMAIL], }, }) config = { "AUTHENTICATION_TYPE": "LDAP", "LDAP_BASE_DN": ["dc=quay", "dc=io"], "LDAP_ADMIN_DN": "uid=devtable,ou=employees,dc=quay,dc=io", "LDAP_ADMIN_PASSWD": "password", "LDAP_USER_RDN": ["ou=employees"], "LDAP_UID_ATTR": "uid", "LDAP_EMAIL_ATTR": "mail", } mockldap.start() try: # Write the config with the valid password. self.putResponse( SuperUserConfig, data={ "config": config, "password": "******", "hostname": "foo" }, expected_code=200, ) # Ensure that the user row has been linked. # TODO: fix this test # self.assertEquals(ADMIN_ACCESS_USER, # model.user.verify_federated_login('ldap', ADMIN_ACCESS_USER).username) finally: mockldap.stop()
def test_update_with_external_auth(self): # Run a mock LDAP. mockldap = MockLdap({ 'dc=quay,dc=io': { 'dc': ['quay', 'io'] }, 'ou=employees,dc=quay,dc=io': { 'dc': ['quay', 'io'], 'ou': 'employees' }, 'uid=' + ADMIN_ACCESS_USER + ',ou=employees,dc=quay,dc=io': { 'dc': ['quay', 'io'], 'ou': 'employees', 'uid': [ADMIN_ACCESS_USER], 'userPassword': ['password'], 'mail': [ADMIN_ACCESS_EMAIL], }, }) config = { 'AUTHENTICATION_TYPE': 'LDAP', 'LDAP_BASE_DN': ['dc=quay', 'dc=io'], 'LDAP_ADMIN_DN': 'uid=devtable,ou=employees,dc=quay,dc=io', 'LDAP_ADMIN_PASSWD': 'password', 'LDAP_USER_RDN': ['ou=employees'], 'LDAP_UID_ATTR': 'uid', 'LDAP_EMAIL_ATTR': 'mail', } mockldap.start() try: # Write the config with the valid password. self.putResponse(SuperUserConfig, data={'config': config, 'password': '******', 'hostname': 'foo'}, expected_code=200) # Ensure that the user row has been linked. # TODO: fix this test # self.assertEquals(ADMIN_ACCESS_USER, # model.user.verify_federated_login('ldap', ADMIN_ACCESS_USER).username) finally: mockldap.stop()
class TestLDAP(TestCase): # See settings.test for LDAP settings configuration top = ("o=test", {"o": ["test"]}) example = ("ou=example,o=test", {"ou": ["example"]}) alice = ( "cn=alice_ldap,ou=example,o=test", { "cn": ["alice_ldap"], "givenName": ["Alice"], "sn": ["Example"], "mail": ["*****@*****.**"], "userPassword": ["alicepw"], }, ) directory = dict([top, example, alice]) @classmethod def setUpClass(cls): cls.mock_ldap = MockLdap(cls.directory) @classmethod def tearDownClass(cls): del cls.mock_ldap def setUp(self): self.mock_ldap = MockLdap(self.directory) self.mock_ldap.start() self.ldapobj = self.mock_ldap["ldap://localhost/"] def tearDown(self): self.mock_ldap.stop() del self.ldapobj del self.mock_ldap def test_login_with_ldap_details(self): assert self.client.login(username="******", password="******") alice = User.objects.get(username="******") assert alice.first_name == "Alice" assert alice.last_name == "Example" assert alice.email == "*****@*****.**" assert alice.api_key
def test_department(self): ''' Test department lookups. ''' mockldap = MockLdap({ 'o=Novell': { 'o': 'Novell' }, 'cn=mcihar,o=Novell': { 'mail': ['*****@*****.**'], 'ou': ['TestDept'], 'cn': ['mcihar'], 'uid': ['mcihar'], }, 'cn=foobar,o=Novell': { 'mail': ['*****@*****.**'], 'ou': ['L3 Maintenance'], 'cn': ['foobar'], 'uid': ['foobar'], }, }) mockldap.start() try: userinfo = UserInfo('ldap://ldap', 'o=novell') # By mail with fixup self.assertEqual('L3/Maintenance', userinfo.get_department('*****@*****.**')) # By UID self.assertEqual('TestDept', userinfo.get_department('mcihar')) # By UID from cache self.assertEqual('TestDept', userinfo.get_department('mcihar')) # By email self.assertEqual('TestDept', userinfo.get_department('*****@*****.**')) # Hardcoded entries self.assertEqual('Security team', userinfo.get_department('*****@*****.**')) # Non existing entry self.assertEqual('N/A', userinfo.get_department('nobody')) finally: mockldap.stop()
class TestLDAP(TestCase): # See settings.test for LDAP settings configuration top = ('o=test', {'o': ['test']}) example = ('ou=example,o=test', {'ou': ['example']}) alice = ('cn=alice_ldap,ou=example,o=test', { 'cn': ['alice_ldap'], 'givenName': ['Alice'], 'sn': ['Example'], 'mail': ['*****@*****.**'], 'userPassword': ['alicepw'] }) directory = dict([top, example, alice]) @classmethod def setUpClass(cls): cls.mock_ldap = MockLdap(cls.directory) @classmethod def tearDownClass(cls): del cls.mock_ldap def setUp(self): self.mock_ldap = MockLdap(self.directory) self.mock_ldap.start() self.ldapobj = self.mock_ldap['ldap://localhost/'] def tearDown(self): self.mock_ldap.stop() del self.ldapobj del self.mock_ldap def test_login_with_ldap_details(self): assert self.client.login(username='******', password='******') alice = User.objects.get(username='******') assert alice.first_name == 'Alice' assert alice.last_name == 'Example' assert alice.email == '*****@*****.**' assert alice.api_key
def mock_ldap(requires_email=True, user_filter=None): mock_data = { "dc=quay,dc=io": {"dc": ["quay", "io"]}, "ou=employees,dc=quay,dc=io": {"dc": ["quay", "io"], "ou": "employees"}, "ou=otheremployees,dc=quay,dc=io": {"dc": ["quay", "io"], "ou": "otheremployees"}, "cn=AwesomeFolk,dc=quay,dc=io": {"dc": ["quay", "io"], "cn": "AwesomeFolk"}, "uid=testy,ou=employees,dc=quay,dc=io": { "dc": ["quay", "io"], "ou": "employees", "uid": ["testy"], "userPassword": ["password"], "mail": ["*****@*****.**"], "memberOf": ["cn=AwesomeFolk,dc=quay,dc=io", "cn=*Guys,dc=quay,dc=io"], "filterField": ["somevalue"], }, "uid=someuser,ou=employees,dc=quay,dc=io": { "dc": ["quay", "io"], "ou": "employees", "uid": ["someuser"], "userPassword": ["somepass"], "mail": ["*****@*****.**"], "memberOf": ["cn=AwesomeFolk,dc=quay,dc=io", "cn=*Guys,dc=quay,dc=io"], "filterField": ["somevalue"], }, "uid=nomail,ou=employees,dc=quay,dc=io": { "dc": ["quay", "io"], "ou": "employees", "uid": ["nomail"], "userPassword": ["somepass"], "filterField": ["somevalue"], }, "uid=cool.user,ou=employees,dc=quay,dc=io": { "dc": ["quay", "io"], "ou": "employees", "uid": ["cool.user", "referred"], "userPassword": ["somepass"], "mail": ["*****@*****.**"], "filterField": ["somevalue"], }, "uid=referred,ou=employees,dc=quay,dc=io": { "uid": ["referred"], "_referral": "ldap:///uid=cool.user,ou=employees,dc=quay,dc=io", }, "uid=invalidreferred,ou=employees,dc=quay,dc=io": { "uid": ["invalidreferred"], "_referral": "ldap:///uid=someinvaliduser,ou=employees,dc=quay,dc=io", }, "uid=multientry,ou=subgroup1,ou=employees,dc=quay,dc=io": { "uid": ["multientry"], "mail": ["*****@*****.**"], "userPassword": ["somepass"], "filterField": ["somevalue"], }, "uid=multientry,ou=subgroup2,ou=employees,dc=quay,dc=io": { "uid": ["multientry"], "another": ["key"], "filterField": ["somevalue"], }, "uid=secondaryuser,ou=otheremployees,dc=quay,dc=io": { "dc": ["quay", "io"], "ou": "otheremployees", "uid": ["secondaryuser"], "userPassword": ["somepass"], "mail": ["*****@*****.**"], "filterField": ["somevalue"], }, # Feature: Email Blacklisting "uid=blacklistedcom,ou=otheremployees,dc=quay,dc=io": { "dc": ["quay", "io"], "ou": "otheremployees", "uid": ["blacklistedcom"], "userPassword": ["somepass"], "mail": ["*****@*****.**"], "filterField": ["somevalue"], }, "uid=blacklistednet,ou=otheremployees,dc=quay,dc=io": { "dc": ["quay", "io"], "ou": "otheremployees", "uid": ["blacklistednet"], "userPassword": ["somepass"], "mail": ["*****@*****.**"], "filterField": ["somevalue"], }, "uid=blacklistedorg,ou=otheremployees,dc=quay,dc=io": { "dc": ["quay", "io"], "ou": "otheremployees", "uid": ["blacklistedorg"], "userPassword": ["somepass"], "mail": ["*****@*****.**"], "filterField": ["somevalue"], }, "uid=notblacklistedcom,ou=otheremployees,dc=quay,dc=io": { "dc": ["quay", "io"], "ou": "otheremployees", "uid": ["notblacklistedcom"], "userPassword": ["somepass"], "mail": ["*****@*****.**"], "filterField": ["somevalue"], }, } if not requires_email: for path in mock_data: mock_data[path].pop("mail", None) mockldap = MockLdap(mock_data) def initializer(uri, trace_level=0): obj = mockldap[uri] # Seed to "support" wildcard queries, which MockLDAP does not support natively. cool_block = { "dc": ["quay", "io"], "ou": "employees", "uid": ["cool.user", "referred"], "userPassword": ["somepass"], "mail": ["*****@*****.**"], } if not requires_email: cool_block.pop("mail", None) obj.search_s.seed("ou=employees,dc=quay,dc=io", 2, "(|(uid=cool*)(mail=cool*))")( [("uid=cool.user,ou=employees,dc=quay,dc=io", cool_block)] ) obj.search_s.seed("ou=otheremployees,dc=quay,dc=io", 2, "(|(uid=cool*)(mail=cool*))")([]) obj.search_s.seed("ou=employees,dc=quay,dc=io", 2, "(|(uid=unknown*)(mail=unknown*))")([]) obj.search_s.seed("ou=otheremployees,dc=quay,dc=io", 2, "(|(uid=unknown*)(mail=unknown*))")( [] ) no_users_found_exception = Exception() no_users_found_exception.message = {"matched": "dc=quay,dc=io", "desc": "No such object"} obj.search_s.seed("ou=nonexistent,dc=quay,dc=io", 2)(no_users_found_exception) obj.search_s.seed("ou=employees,dc=quay,dc=io", 2)( [("uid=cool.user,ou=employees,dc=quay,dc=io", cool_block)] ) obj.search.seed("ou=employees,dc=quay,dc=io", 2, "(objectClass=*)")( [("uid=cool.user,ou=employees,dc=quay,dc=io", cool_block)] ) obj.search.seed("ou=employees,dc=quay,dc=io", 2)( [("uid=cool.user,ou=employees,dc=quay,dc=io", cool_block)] ) obj._results = {} original_result_fn = obj.result def result(messageid): if messageid is None: return None, [], None, None # NOTE: Added because of weirdness with using mock-ldap. if isinstance(messageid, list): return None, messageid if messageid in obj._results: return obj._results[messageid] return original_result_fn(messageid) def result3(messageid): if messageid is None: return None, [], None, None return obj._results[messageid] def search_ext( user_search_dn, scope, search_flt=None, serverctrls=None, sizelimit=None, attrlist=None ): if scope != ldap.SCOPE_SUBTREE: return None if not serverctrls: if search_flt: rdata = obj.search_s(user_search_dn, scope, search_flt, attrlist=attrlist) else: if attrlist: rdata = obj.search_s(user_search_dn, scope, attrlist=attrlist) else: rdata = obj.search_s(user_search_dn, scope) obj._results["messageid"] = (None, rdata) return "messageid" page_control = serverctrls[0] if page_control.controlType != ldap.controls.SimplePagedResultsControl.controlType: return None if search_flt: msgid = obj.search(user_search_dn, scope, search_flt, attrlist=attrlist) else: if attrlist: msgid = obj.search(user_search_dn, scope, attrlist=attrlist) else: msgid = obj.search(user_search_dn, scope) _, rdata = obj.result(msgid) msgid = "messageid" cookie = int(page_control.cookie) if page_control.cookie else 0 results = rdata[cookie : cookie + page_control.size] cookie = cookie + page_control.size if cookie > len(results): page_control.cookie = None else: page_control.cookie = cookie obj._results["messageid"] = (None, results, None, [page_control]) return msgid def search_ext_s(user_search_dn, scope, sizelimit=None): return [obj.search_s(user_search_dn, scope)] obj.search_ext = search_ext obj.result = result obj.result3 = result3 obj.search_ext_s = search_ext_s return obj mockldap.start() try: with patch("ldap.initialize", new=initializer): yield _create_ldap(requires_email=requires_email, user_filter=user_filter) finally: mockldap.stop()
class MinarcaDiskSpaceTest(WebCase): # Reset app and testcases on every test reset_app = True reset_testcases = False # Disable interactive mode. interactive = False # Data for LDAP mock. basedn = ('dc=nodomain', { 'dc': ['nodomain'], 'o': ['nodomain']}) people = ('ou=People,dc=nodomain', { 'ou': ['People'], 'objectClass': ['organizationalUnit']}) bob = ('uid=bob,ou=People,dc=nodomain', { 'uid': ['bob'], 'cn': ['bob'], 'userPassword': ['password'], 'homeDirectory': '/tmp/bob', 'mail': ['*****@*****.**'], 'description': ['v2'], 'objectClass': ['person', 'organizationalPerson', 'inetOrgPerson', 'posixAccount']}) # This is the content of our mock LDAP directory. It takes the form # {dn: {attr: [value, ...], ...}, ...}. directory = dict([ basedn, people, bob, ]) @classmethod def setup_server(cls): WebCase.setup_server(default_config={ 'AddMissingUser': '******', 'LdapUri': '__default__', 'LdapBaseDn': 'dc=nodomain', 'MinarcaUserBaseDir': '/tmp/minarca-test', }) def setUp(self): self.app.store.get_user('admin').user_root = '/tmp' # Mock LDAP self.mockldap = MockLdap(self.directory) self.mockldap.start() self.ldapobj = self.mockldap['ldap://localhost/'] WebCase.setUp(self) self.plugin = MinarcaUserSetup(self.app) if not os.path.isdir('/tmp/minarca-test'): os.mkdir('/tmp/minarca-test') def tearDown(self): WebCase.tearDown(self) # Stop patching ldap.initialize and reset state. self.mockldap.stop() del self.ldapobj del self.mockldap shutil.rmtree('/tmp/minarca-test') def test_login(self): """ Check if new user is created with user_root and email. """ userobj = self.app.store.login('bob', 'password') self.assertIsNotNone(userobj) self.assertIsNotNone(self.app.store.get_user('bob')) # Check if profile get update from Ldap info. self.assertEquals('*****@*****.**', self.app.store.get_user('bob').email) self.assertEquals('/tmp/minarca-test/bob', self.app.store.get_user('bob').user_root) @httpretty.activate def test_set_disk_quota(self): httpretty.register_uri(httpretty.POST, "http://localhost:8081/quota/bob", body='{"avail": 2147483648, "used": 0, "size": 2147483648}') userobj = self.app.store.add_user('bob') self.plugin.set_disk_quota(userobj, quota=1234567) @httpretty.activate def test_update_userquota_401(self): # Checks if exception is raised when authentication is failing. httpretty.register_uri(httpretty.POST, "http://localhost:8081/quota/bob", status=401) # Make sure an exception is raised. userobj = self.app.store.add_user('bob') with self.assertRaises(Exception): self.plugin.set_disk_quota(userobj, quota=1234567) @httpretty.activate def test_get_disk_usage(self): """ Check if value is available. """ # Checks if exception is raised when authentication is failing. httpretty.register_uri(httpretty.GET, "http://localhost:8081/quota/bob", body='{"avail": 2147483648, "used": 0, "size": 2147483648}') # Make sure an exception is raised. userobj = self.app.store.add_user('bob') self.assertEquals({"avail": 2147483648, "used": 0, "size": 2147483648}, self.plugin.get_disk_usage(userobj)) def test_get_api_minarca(self): self.app.cfg['minarcaremotehost'] = None self.app.cfg['minarcaremotehostidentity'] = None self._login('bob', 'password') self.getPage("/api/minarca") # Check version self.assertInBody('version') # Check remoteHost self.assertInBody('remotehost') self.assertInBody('127.0.0.1') # Check identity self.assertInBody('identity') def test_get_api_minarca_identity(self): self.app.cfg['minarcaremotehost'] = "test.examples:2222" self.app.cfg['minarcaremotehostidentity'] = pkg_resources.resource_filename(__name__, '') # @UndefinedVariable self._login(self.USERNAME, self.PASSWORD) data = self.getJson("/api/minarca/") self.assertIn("[test.examples]:2222", data['identity']) def test_get_api_minarca_with_reverse_proxy(self): self.app.cfg['minarcaremotehost'] = None self.app.cfg['minarcaremotehostidentity'] = None # When behind an apache reverse proxy, minarca server should make use # of the Header to determine the public hostname provided. self._login('bob', 'password') headers = [ ('X-Forwarded-For', '10.255.1.106'), ('X-Forwarded-Host', 'sestican.patrikdufresne.com'), ('X-Forwarded-Server', '10.255.1.106')] self.getPage("/api/minarca", headers=headers) self.assertInBody('remotehost') self.assertInBody('sestican.patrikdufresne.com') def test_get_help(self): # Check if help get redirect self.getPage("/help") self.assertStatus(303) self.assertHeader('Location', 'https://www.ikus-soft.com/en/support/#form') # Check if the URL can be changed self.app.cfg['minarcahelpurl'] = 'https://example.com/help/' self.getPage("/help") self.assertStatus(303) self.assertHeader('Location', 'https://example.com/help/')
class OrloAuthTest(TestCase): """ Base test class to setup the app """ top = ('o=test', {'o': ['test']}) example = ('ou=example,o=test', {'ou': ['example']}) people = ('ou=people,ou=example,o=test', {'ou': ['other']}) ldapuser = ('uid=ldapuser,ou=people,ou=example,o=test', { 'uid': ['ldapuser'], 'userPassword': ['ldapuserpw'] }) # This is the content of our mock LDAP directory. It takes the form # {dn: {attr: [value, ...], ...}, ...}. directory = dict([top, example, people, ldapuser]) def create_app(self): self.app = orlo.app self.app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite://' self.app.config['TESTING'] = True self.app.config['DEBUG'] = False self.app.config['TRAP_HTTP_EXCEPTIONS'] = True self.app.config['PRESERVE_CONTEXT_ON_EXCEPTION'] = False return self.app @classmethod def setUpClass(self): # We only need to create the MockLdap instance once. The content we # pass in will be used for all LDAP connections. self.mockldap = MockLdap(self.directory) @classmethod def tearDownClass(self): del self.mockldap def setUp(self): db.create_all() self.mockldap.start() self.ldapobj = self.mockldap['ldap://localhost/'] self.orig_security_enabled = orlo.config.get('security', 'enabled') self.orig_security_secret_key = orlo.config.set( 'security', 'secret_key') self.orig_security_ldap_server = orlo.config.set( 'security', 'ldap_server') self.orig_security_ldap_port = orlo.config.set('security', 'ldap_port') self.orig_security_user_base_dn = orlo.config.set( 'security', 'user_base_dn') orlo.config.set('security', 'enabled', 'true') orlo.config.set( 'security', 'secret_key', 'It does not matter how ' 'slowly you go so long as ' 'you do not stop') orlo.config.set('security', 'ldap_server', 'localhost') orlo.config.set('security', 'ldap_port', '389') orlo.config.set('security', 'user_base_dn', 'ou=people,ou=example,o=test') def tearDown(self): db.session.remove() db.drop_all() self.mockldap.stop() del self.ldapobj orlo.config.set('security', 'enabled', self.orig_security_enabled) orlo.config.set('security', 'secret_key', self.orig_security_secret_key) def get_with_basic_auth(self, path, username='******', password='******'): """ Do a request with ldap auth :param path: :param username: :param password: """ h = Headers() s_auth = base64.b64encode('{u}:{p}'.format(u=username, p=password).encode('utf-8')) h.add('Authorization', 'Basic ' + s_auth.decode('utf-8')) response = Client.open(self.client, path=path, headers=h) return response def get_with_token_auth(self, path, token): """ Do a request with token auth :param token: :param path: """ h = Headers() h.add('X-Auth-Token', token) response = Client.open(self.client, path=path, headers=h) return response def post_with_token_auth(self, path, token, data): """ Do a request with token auth :param token: :param path: """ h = Headers() h.add('X-Auth-Token', token) h.add('Content-Type', 'application/json') response = Client.open(self.client, method='POST', data=data, path=path, headers=h) return response def get_token(self): response = self.get_with_basic_auth('/token') return response.json['token']
class BaseTestCase(XMLBaseTest): """ Tests for L{DirectoryService}. """ url = "ldap://localhost/" baseDN = u"dc=calendarserver,dc=org" realmName = unicode(url) def setUp(self): if MockLdap is None: raise SkipTest("No MockLdap available") def matches(self, dn, attrs, upcall=MockLDAPFilterTest.matches): if upcall(self, dn, attrs): return True else: return mockldap_matches(self, dn, attrs) self.patch(MockLDAPFilterTest, "_parse_expression", mockldap_parse) self.patch(MockLDAPFilterTest, "matches", mockldap_matches) self.xmlSeedService = xmlService(self.mktemp()) self.mockData = mockDirectoryDataFromXMLService(self.xmlSeedService) if False: from pprint import pprint print("") print("-" * 80) pprint(self.mockData) print("-" * 80) self.mockLDAP = MockLdap(self.mockData) self.mockLDAP.start() def tearDown(self): self.mockLDAP.stop() def service(self, **kwargs): svc = TestService( url=self.url, baseDN=self.baseDN, fieldNameToAttributesMap=TEST_FIELDNAME_MAP, recordTypeSchemas=MappingProxyType({ RecordType.user: RecordTypeSchema( relativeDN=u"cn=user", # (objectClass=inetOrgPerson) attributes=( ( LDAPAttribute.objectClass.value, LDAPObjectClass.inetOrgPerson.value, ), ), ), RecordType.group: RecordTypeSchema( relativeDN=u"cn=group", # (objectClass=groupOfNames) attributes=( ( LDAPAttribute.objectClass.value, LDAPObjectClass.groupOfUniqueNames.value, ), ), ), }), **kwargs ) svc.fieldName = ConstantsContainer( (svc.fieldName, TestFieldName) ) return svc
class OrloAuthTest(TestCase): """ Base test class to setup the app """ top = ('o=test', {'o': ['test']}) example = ('ou=example,o=test', {'ou': ['example']}) people = ('ou=people,ou=example,o=test', {'ou': ['other']}) ldapuser = ('uid=ldapuser,ou=people,ou=example,o=test', {'uid': ['ldapuser'], 'userPassword': ['ldapuserpw']}) # This is the content of our mock LDAP directory. It takes the form # {dn: {attr: [value, ...], ...}, ...}. directory = dict([top, example, people, ldapuser]) def create_app(self): self.app = orlo.app self.app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite://' self.app.config['TESTING'] = True self.app.config['DEBUG'] = True self.app.config['TRAP_HTTP_EXCEPTIONS'] = True self.app.config['PRESERVE_CONTEXT_ON_EXCEPTION'] = False return self.app @classmethod def setUpClass(self): # We only need to create the MockLdap instance once. The content we # pass in will be used for all LDAP connections. self.mockldap = MockLdap(self.directory) @classmethod def tearDownClass(self): del self.mockldap def setUp(self): db.create_all() self.mockldap.start() self.ldapobj = self.mockldap['ldap://localhost/'] self.orig_security_enabled = orlo.config.get('security', 'enabled') self.orig_security_secret_key = orlo.config.set('security', 'secret_key') self.orig_security_ldap_server = orlo.config.set('security', 'ldap_server') self.orig_security_ldap_port = orlo.config.set('security', 'ldap_port') self.orig_security_user_base_dn = orlo.config.set('security', 'user_base_dn') orlo.config.set('security', 'enabled', 'true') orlo.config.set('security', 'secret_key', 'It does not matter how slowly you go so long as you do not stop') orlo.config.set('security', 'ldap_server', 'localhost') orlo.config.set('security', 'ldap_port', '389') orlo.config.set('security', 'user_base_dn', 'ou=people,ou=example,o=test') def tearDown(self): db.session.remove() db.drop_all() self.mockldap.stop() del self.ldapobj orlo.config.set('security', 'enabled', self.orig_security_enabled) orlo.config.set('security', 'secret_key', self.orig_security_secret_key) def get_with_basic_auth(self, path, username='******', password='******'): """ Do a request with basic auth :param path: :param username: :param password: """ h = Headers() h.add('Authorization', 'Basic ' + base64.b64encode( '{u}:{p}'.format(u=username, p=password) )) response = Client.open(self.client, path=path, headers=h) return response def get_with_ldap_auth(self, path, username='******', password='******'): """ Do a request with ldap auth :param path: :param username: :param password: """ h = Headers() h.add('Authorization', 'Basic ' + base64.b64encode( '{u}:{p}'.format(u=username, p=password) )) response = Client.open(self.client, path=path, headers=h) return response def get_with_token_auth(self, path, token): """ Do a request with token auth :param token: :param path: """ h = Headers() h.add('X-Auth-Token', token) response = Client.open(self.client, path=path, headers=h) return response def post_with_token_auth(self, path, token, data): """ Do a request with token auth :param token: :param path: """ h = Headers() h.add('X-Auth-Token', token) h.add('Content-Type', 'application/json') response = Client.open(self.client, method='POST', data=data, path=path, headers=h) return response def get_token(self): response = self.get_with_basic_auth('/token') return response.json['token']
def configure_mock_ldap(): from mockldap import MockLdap mockldap = MockLdap(directory) mockldap.start() yield mockldap.stop()
def mock_ldap(requires_email=True): mock_data = { 'dc=quay,dc=io': { 'dc': ['quay', 'io'] }, 'ou=employees,dc=quay,dc=io': { 'dc': ['quay', 'io'], 'ou': 'employees' }, 'ou=otheremployees,dc=quay,dc=io': { 'dc': ['quay', 'io'], 'ou': 'otheremployees' }, 'cn=AwesomeFolk,dc=quay,dc=io': { 'dc': ['quay', 'io'], 'cn': 'AwesomeFolk' }, 'uid=testy,ou=employees,dc=quay,dc=io': { 'dc': ['quay', 'io'], 'ou': 'employees', 'uid': ['testy'], 'userPassword': ['password'], 'mail': ['*****@*****.**'], 'memberOf': ['cn=AwesomeFolk,dc=quay,dc=io', 'cn=*Guys,dc=quay,dc=io'], }, 'uid=someuser,ou=employees,dc=quay,dc=io': { 'dc': ['quay', 'io'], 'ou': 'employees', 'uid': ['someuser'], 'userPassword': ['somepass'], 'mail': ['*****@*****.**'], 'memberOf': ['cn=AwesomeFolk,dc=quay,dc=io', 'cn=*Guys,dc=quay,dc=io'], }, 'uid=nomail,ou=employees,dc=quay,dc=io': { 'dc': ['quay', 'io'], 'ou': 'employees', 'uid': ['nomail'], 'userPassword': ['somepass'] }, 'uid=cool.user,ou=employees,dc=quay,dc=io': { 'dc': ['quay', 'io'], 'ou': 'employees', 'uid': ['cool.user', 'referred'], 'userPassword': ['somepass'], 'mail': ['*****@*****.**'] }, 'uid=referred,ou=employees,dc=quay,dc=io': { 'uid': ['referred'], '_referral': 'ldap:///uid=cool.user,ou=employees,dc=quay,dc=io' }, 'uid=invalidreferred,ou=employees,dc=quay,dc=io': { 'uid': ['invalidreferred'], '_referral': 'ldap:///uid=someinvaliduser,ou=employees,dc=quay,dc=io' }, 'uid=multientry,ou=subgroup1,ou=employees,dc=quay,dc=io': { 'uid': ['multientry'], 'mail': ['*****@*****.**'], 'userPassword': ['somepass'], }, 'uid=multientry,ou=subgroup2,ou=employees,dc=quay,dc=io': { 'uid': ['multientry'], 'another': ['key'] }, 'uid=secondaryuser,ou=otheremployees,dc=quay,dc=io': { 'dc': ['quay', 'io'], 'ou': 'otheremployees', 'uid': ['secondaryuser'], 'userPassword': ['somepass'], 'mail': ['*****@*****.**'] }, # Feature: Email Blacklisting 'uid=blacklistedcom,ou=otheremployees,dc=quay,dc=io': { 'dc': ['quay', 'io'], 'ou': 'otheremployees', 'uid': ['blacklistedcom'], 'userPassword': ['somepass'], 'mail': ['*****@*****.**'] }, 'uid=blacklistednet,ou=otheremployees,dc=quay,dc=io': { 'dc': ['quay', 'io'], 'ou': 'otheremployees', 'uid': ['blacklistednet'], 'userPassword': ['somepass'], 'mail': ['*****@*****.**'] }, 'uid=blacklistedorg,ou=otheremployees,dc=quay,dc=io': { 'dc': ['quay', 'io'], 'ou': 'otheremployees', 'uid': ['blacklistedorg'], 'userPassword': ['somepass'], 'mail': ['*****@*****.**'] }, 'uid=notblacklistedcom,ou=otheremployees,dc=quay,dc=io': { 'dc': ['quay', 'io'], 'ou': 'otheremployees', 'uid': ['notblacklistedcom'], 'userPassword': ['somepass'], 'mail': ['*****@*****.**'] }, } if not requires_email: for path in mock_data: mock_data[path].pop('mail', None) mockldap = MockLdap(mock_data) def initializer(uri, trace_level=0): obj = mockldap[uri] # Seed to "support" wildcard queries, which MockLDAP does not support natively. cool_block = { 'dc': ['quay', 'io'], 'ou': 'employees', 'uid': ['cool.user', 'referred'], 'userPassword': ['somepass'], 'mail': ['*****@*****.**'] } if not requires_email: cool_block.pop('mail', None) obj.search_s.seed('ou=employees,dc=quay,dc=io', 2, '(|(uid=cool*)(mail=cool*))')([ ('uid=cool.user,ou=employees,dc=quay,dc=io', cool_block) ]) obj.search_s.seed('ou=otheremployees,dc=quay,dc=io', 2, '(|(uid=cool*)(mail=cool*))')([]) obj.search_s.seed('ou=employees,dc=quay,dc=io', 2, '(|(uid=unknown*)(mail=unknown*))')([]) obj.search_s.seed('ou=otheremployees,dc=quay,dc=io', 2, '(|(uid=unknown*)(mail=unknown*))')([]) no_users_found_exception = Exception() no_users_found_exception.message = { 'matched': 'dc=quay,dc=io', 'desc': 'No such object' } obj.search_s.seed('ou=nonexistent,dc=quay,dc=io', 2)(no_users_found_exception) obj.search_s.seed('ou=employees,dc=quay,dc=io', 2)([ ('uid=cool.user,ou=employees,dc=quay,dc=io', cool_block) ]) obj.search.seed('ou=employees,dc=quay,dc=io', 2, '(objectClass=*)')([ ('uid=cool.user,ou=employees,dc=quay,dc=io', cool_block) ]) obj.search.seed('ou=employees,dc=quay,dc=io', 2)([ ('uid=cool.user,ou=employees,dc=quay,dc=io', cool_block) ]) obj._results = {} original_result_fn = obj.result def result(messageid): if messageid is None: return None, [], None, None # NOTE: Added because of weirdness with using mock-ldap. if isinstance(messageid, list): return None, messageid if messageid in obj._results: return obj._results[messageid] return original_result_fn(messageid) def result3(messageid): if messageid is None: return None, [], None, None return obj._results[messageid] def search_ext(user_search_dn, scope, search_flt=None, serverctrls=None, sizelimit=None, attrlist=None): if scope != ldap.SCOPE_SUBTREE: return None if not serverctrls: if search_flt: rdata = obj.search_s(user_search_dn, scope, search_flt, attrlist=attrlist) else: if attrlist: rdata = obj.search_s(user_search_dn, scope, attrlist=attrlist) else: rdata = obj.search_s(user_search_dn, scope) obj._results['messageid'] = (None, rdata) return 'messageid' page_control = serverctrls[0] if page_control.controlType != ldap.controls.SimplePagedResultsControl.controlType: return None if search_flt: msgid = obj.search(user_search_dn, scope, search_flt, attrlist=attrlist) else: if attrlist: msgid = obj.search(user_search_dn, scope, attrlist=attrlist) else: msgid = obj.search(user_search_dn, scope) _, rdata = obj.result(msgid) msgid = 'messageid' cookie = int(page_control.cookie) if page_control.cookie else 0 results = rdata[cookie:cookie + page_control.size] cookie = cookie + page_control.size if cookie > len(results): page_control.cookie = None else: page_control.cookie = cookie obj._results['messageid'] = (None, results, None, [page_control]) return msgid def search_ext_s(user_search_dn, scope, sizelimit=None): return [obj.search_s(user_search_dn, scope)] obj.search_ext = search_ext obj.result = result obj.result3 = result3 obj.search_ext_s = search_ext_s return obj mockldap.start() with patch('ldap.initialize', new=initializer): yield _create_ldap(requires_email=requires_email) mockldap.stop()