1
0
mirror of https://github.com/kakwa/ldapcherry synced 2024-11-22 01:14:21 +01:00
ldapcherry/tests/test_LdapCherry.py
kakwa baa3430e63 fix test and exception handling in code
With python 2 it was possible to do exception[0][...] to recover
details about an exception.
It's no longer authorized with python 3.
Now, we must do something like exception.args or exception.urls.
fortunately this syntax also works with python 2.
So we use it for both.
2019-02-09 17:12:39 +01:00

365 lines
14 KiB
Python

#!/usr/bin/env python
# -*- coding: utf-8 -*-
from __future__ import with_statement
import pytest
import sys
import subprocess
from tempfile import NamedTemporaryFile as tempfile
import re
from ldapcherry import LdapCherry
from ldapcherry.exceptions import *
from ldapcherry.pyyamlwrapper import DumplicatedKey, RelationError
import ldapcherry.backend.backendAD
import cherrypy
from cherrypy.process import plugins, servers
from cherrypy import Application
import logging
from ldapcherry.lclogging import *
from disable import *
import json
if sys.version < '3':
from sets import Set as set
cherrypy.session = {}
adcfg = {
'display_name': u'test☭',
'domain': 'DC.LDAPCHERRY.ORG',
'login': 'Administrator',
'password': 'qwertyP455',
'uri': 'ldaps://ad.ldapcherry.org',
'checkcert': 'off',
}
adattr = ['shell', 'cn', 'sAMAccountName', 'uidNumber', 'gidNumber', 'home', 'unicodePwd', 'givenName', 'email', 'sn']
addefault_user = {
'sAMAccountName': u'☭default_user',
'sn': u'test☭1',
'cn': u'test☭2',
'unicodePwd': u'test☭P666',
'uidNumber': '42',
'gidNumber': '42',
'homeDirectory': '/home/test/'
}
# monkey patching cherrypy to disable config interpolation
def new_as_dict(self, raw=True, vars=None):
"""Convert an INI file to a dictionary"""
# Load INI file into a dict
result = {}
for section in self.sections():
if section not in result:
result[section] = {}
for option in self.options(section):
value = self.get(section, option, raw=raw, vars=vars)
try:
value = cherrypy.lib.reprconf.unrepr(value)
except Exception:
x = sys.exc_info()[1]
msg = ("Config error in section: %r, option: %r, "
"value: %r. Config values must be valid Python." %
(section, option, value))
raise ValueError(msg, x.__class__.__name__, x.args)
result[section][option] = value
return result
cherrypy.lib.reprconf.Parser.as_dict = new_as_dict
conf = {'/static': {'tools.staticdir.dir': './resources/static/', 'tools.staticdir.on': True}, 'roles': {'roles.file': './tests/cfg/roles.yml'}, 'global': {'tools.sessions.on': True, 'log.access_handler': 'syslog', 'log.level': 'debug', 'server.thread_pool': 8, 'log.error_handler': 'syslog', 'server.socket_port': 8080, 'server.socket_host': '127.0.0.1', 'tools.sessions.timeout': 10, 'request.show_tracebacks': False}, 'auth': {'auth.mode': 'or'}, 'backends': {'ldap.checkcert': 'off', 'ldap.module': 'ldapcherry.backends.ldap', 'ldap.uri': 'ldaps://ldap.ldapcherry.org', 'ldap.starttls': 'on', 'ldap.groupdn': 'ou=group,dc=example,dc=com', 'ldap.people': 'ou=group,dc=example,dc=com', 'ldap.authdn': 'cn=ldapcherry,dc=example,dc=com', 'ldap.password': 'password', 'ldap.ca': '/etc/dnscherry/TEST-cacert.pem', 'ad.module': 'ldapcherry.backends.ad', 'ad.auth': 'Administrator', 'ad.password': 'password'}, 'attributes': {'attributes.file': './tests/cfg/attributes.yml'}, 'resources': {'templates.dir': './resources/templates/'}}
def loadconf(configfile, instance):
app = cherrypy.tree.mount(instance, '/', configfile)
cherrypy.config.update(configfile)
instance.reload(app.config)
class HtmlValidationFailed(Exception):
def __init__(self, out):
self.errors = out
def htmlvalidator(page):
f = tempfile()
stdout = tempfile()
f.write(page.encode("utf-8"))
f.seek(0)
ret = subprocess.call(['./tests/html_validator.py', '-h', f.name], stdout=stdout)
stdout.seek(0)
out = stdout.read()
f.close()
stdout.close()
print(out)
if not re.search(r'Error:.*', out) is None:
raise HtmlValidationFailed(out)
class BadModule():
pass
class TestError(object):
def testNominal(self):
app = LdapCherry()
loadconf('./tests/cfg/ldapcherry.ini', app)
return True
def testMissingBackendModule(self):
app = LdapCherry()
loadconf('./tests/cfg/ldapcherry.ini', app)
cfg = {'backends': {'ldap.module': 'dontexists'}}
try:
app._init_backends(cfg)
except BackendModuleLoadingFail:
return
else:
raise AssertionError("expected an exception")
def testInitgBackendModuleFail(self):
app = LdapCherry()
loadconf('./tests/cfg/ldapcherry.ini', app)
cfg = {'backends': {'ldap.module': 'ldapcherry.backend'}}
try:
app._init_backends(cfg)
except BackendModuleInitFail:
return
else:
raise AssertionError("expected an exception")
def testLog(self):
app = LdapCherry()
cfg = { 'global' : {}}
for t in ['none', 'file', 'syslog']:
cfg['global']['log.access_handler']=t
cfg['global']['log.error_handler']=t
app._set_access_log(cfg, logging.DEBUG)
app._set_error_log(cfg, logging.DEBUG)
def testAuth(self):
app = LdapCherry()
loadconf('./tests/cfg/ldapcherry_test.ini', app)
app.auth_mode = 'and'
ret1 = app._auth('jsmith', 'passwordsmith')
app.auth_mode = 'or'
ret2 = app._auth('jsmith', 'passwordsmith')
assert ret2 == {'connected': True, 'isadmin': False} and \
ret1 == {'connected': True, 'isadmin': False}
def testPPolicy(self):
app = LdapCherry()
loadconf('./tests/cfg/ldapcherry.ini', app)
wrong = app._checkppolicy('password')['match']
good = app._checkppolicy('Passw0rd.')['match']
assert wrong == False and good == True
def testMissingBackend(self):
app = LdapCherry()
loadconf('./tests/cfg/ldapcherry.ini', app)
del app.backends_params['ad']
try:
app._check_backends()
except MissingBackend:
return
else:
raise AssertionError("expected an exception")
def testMissingParameters(self):
app = LdapCherry()
try:
app.reload({})
except SystemExit:
return
else:
raise AssertionError("expected an exception")
def testRandomException(self):
app = LdapCherry()
loadconf('./tests/cfg/ldapcherry.ini', app)
e = Exception()
app._handle_exception(e)
def testLogin(self):
app = LdapCherry()
loadconf('./tests/cfg/ldapcherry_test.ini', app)
app.auth_mode = 'or'
try:
app.login(u'jwatsoné', u'passwordwatsoné')
except cherrypy.HTTPRedirect as e:
expected = 'http://127.0.0.1:8080/'
assert e.urls[0] == expected
else:
raise AssertionError("expected an exception")
def testLoginFailure(self):
app = LdapCherry()
loadconf('./tests/cfg/ldapcherry_test.ini', app)
app.auth_mode = 'or'
try:
app.login(u'jwatsoné', u'wrongPasswordé')
except cherrypy.HTTPRedirect as e:
expected = 'http://127.0.0.1:8080/signin'
assert e.urls[0] == expected
else:
raise AssertionError("expected an exception")
def testSearch(self):
app = LdapCherry()
loadconf('./tests/cfg/ldapcherry_test.ini', app)
expected = {
u'ssmith': {
'password': u'passwordsmith',
'cn': u'Sheri Smith',
'name': u'smith',
'uid': u'ssmith',
'email': [u's.smith@example.com',
u'ssmith@example.com',
u'sheri.smith@example.com'
],
},
u'jsmith': {
'password': u'passwordsmith',
'cn': u'John Smith',
'name': u'Smith',
'uid': u'jsmith',
'email': [
'j.smith@example.com',
'jsmith@example.com',
'jsmith.smith@example.com'
],
}
}
ret = app._search('smith')
assert expected == ret
def testGetUser(self):
app = LdapCherry()
loadconf('./tests/cfg/ldapcherry_test.ini', app)
expected = {
'password': u'passwordsmith',
'cn': u'Sheri Smith',
'uid': u'ssmith',
'name': u'smith',
'email': [u's.smith@example.com',
u'ssmith@example.com',
u'sheri.smith@example.com'
],
}
ret = app._get_user('ssmith')
assert expected == ret
def testAddUser(self):
app = LdapCherry()
loadconf('./tests/cfg/ldapcherry_test.ini', app)
form = {'groups': {}, 'attrs': {'password1': u'password☭', 'password2': u'password☭', 'cn': u'Test ☭ Test', 'name': u'Test ☭', 'uidNumber': u'1000', 'gidNumber': u'1000', 'home': u'/home/test', 'first-name': u'Test ☭', 'email': u'test@test.fr', 'uid': u'test'}, 'roles': {'admin-lv3': u'on', 'admin-lv2': u'on', 'users': u'on'}}
app._adduser(form)
app._deleteuser('test')
def testParse(self):
app = LdapCherry()
form = {'attr.val': 'val', 'role.id': 'id', 'group.ldap.id': 'id'}
ret = app._parse_params(form)
expected = {'attrs': {'val': 'val'}, 'roles': {'id': 'id'}, 'groups': {'ldap': ['id']}}
assert expected == ret
def testModifUser(self):
app = LdapCherry()
loadconf('./tests/cfg/ldapcherry_test.ini', app)
form = {'groups': {}, 'attrs': {'password1': u'password☭', 'password2': u'password☭', 'cn': u'Test ☭ Test', 'name': u'Test ☭', 'uidNumber': u'1000', 'gidNumber': u'1000', 'home': u'/home/test', 'first-name': u'Test ☭', 'email': u'test@test.fr', 'uid': u'test'}, 'roles': {'admin-lv3': u'on', 'admin-lv2': u'on', 'users': u'on'}}
app._adduser(form)
modify_form = { 'attrs': {'first-name': u'Test42 ☭', 'uid': u'test'}, 'roles': { 'admin-lv3': u'on'}}
app._modify(modify_form)
app._deleteuser('test')
@slow_disabled
def testHtml(self):
app = LdapCherry()
loadconf('./tests/cfg/ldapcherry_test.ini', app)
pages = {
'signin': app.signin(),
'index': app.index(),
'searchuser': app.searchuser('smit'),
'searchadmin':app.searchadmin('smit'),
'adduser': app.adduser(),
'modify':app.modify('jsmith'),
'selfmodify':app.selfmodify(),
}
for page in pages:
print(page)
htmlvalidator(pages[page])
def testNoneType(self):
app = LdapCherry()
loadconf('./tests/cfg/ldapcherry_test.ini', app)
app.modify('ssmith')
def testNoneModify(self):
app = LdapCherry()
loadconf('./tests/cfg/ldapcherry_test.ini', app)
app.modify(user=None)
@slow_disabled
def testNaughtyStrings(self):
app = LdapCherry()
loadconf('./tests/cfg/ldapcherry_test.ini', app)
with open('./tests/cfg/blns.json') as data_file:
data = json.load(data_file)
for attr in data:
print('testing: ' + attr)
# delete whatever is happening...
try:
app._deleteuser('test')
except:
pass
form = {'groups': {}, 'attrs': {'password1': u'password☭', 'password2': u'password☭', 'cn': 'Test', 'name': attr, 'uidNumber': u'1000', 'gidNumber': u'1000', 'home': u'/home/test', 'first-name': u'Test ☭', 'email': u'test@test.fr', 'uid': 'test'}, 'roles': {'admin-lv3': u'on', 'admin-lv2': u'on', 'users': u'on'}}
app._adduser(form)
page = app.searchuser('test'),
app._deleteuser('test')
htmlvalidator(page[0])
@travis_disabled
def testDeleteUserOneBackend(self):
app = LdapCherry()
loadconf('./tests/cfg/ldapcherry_adldap.cfg', app)
inv = ldapcherry.backend.backendAD.Backend(adcfg, cherrypy.log, u'test☭', adattr, 'sAMAccountName')
inv.add_user(addefault_user.copy())
app._deleteuser(u'☭default_user')
@travis_disabled
def testAddUserOneBackend(self):
app = LdapCherry()
loadconf('./tests/cfg/ldapcherry_adldap.cfg', app)
inv = ldapcherry.backend.backendAD.Backend(adcfg, cherrypy.log, u'test☭', adattr, 'sAMAccountName')
inv.add_user(addefault_user.copy())
form = {'groups': {}, 'attrs': {'password1': u'password☭P455', 'password2': u'password☭P455', 'cn': u'Test ☭ Test', 'name': u'Test ☭', 'uidNumber': u'1000', 'gidNumber': u'1000', 'home': u'/home/test', 'first-name': u'Test ☭', 'email': u'test@test.fr', 'uid': u'☭default_user'}, 'roles': {'admin-lv3': u'on', 'admin-lv2': u'on', 'users': u'on'}}
app._adduser(form)
app._deleteuser(u'☭default_user')
@travis_disabled
def testModifyUserOneBackend(self):
app = LdapCherry()
loadconf('./tests/cfg/ldapcherry_adldap.cfg', app)
inv = ldapcherry.backend.backendAD.Backend(adcfg, cherrypy.log, u'test☭', adattr, 'sAMAccountName')
try:
app._deleteuser(u'☭default_user')
except:
pass
inv.add_user(addefault_user.copy())
modify_form = { 'attrs': {'first-name': u'Test42 ☭', 'uid': u'☭default_user'}, 'roles': { 'admin-lv3': u'on'}}
app._modify(modify_form)
app._deleteuser(u'☭default_user')
def testLogger(self):
app = LdapCherry()
loadconf('./tests/cfg/ldapcherry.ini', app)
assert get_loglevel('debug') is logging.DEBUG and \
get_loglevel('notice') is logging.INFO and \
get_loglevel('info') is logging.INFO and \
get_loglevel('warning') is logging.WARNING and \
get_loglevel('err') is logging.ERROR and \
get_loglevel('critical') is logging.CRITICAL and \
get_loglevel('alert') is logging.CRITICAL and \
get_loglevel('emergency') is logging.CRITICAL and \
get_loglevel('notalevel') is logging.INFO