summaryrefslogtreecommitdiffstats
path: root/ipatests/test_xmlrpc
diff options
context:
space:
mode:
authorFilip Skola <fskola@redhat.com>2015-11-06 10:57:37 +0100
committerMartin Basti <mbasti@redhat.com>2016-01-25 16:04:32 +0100
commit3d1adb325512cf14de8b88ca8178dd4a754256ec (patch)
treeac3dd81e67c62c9c4e6e34536ead4b44503b2105 /ipatests/test_xmlrpc
parentb0894a84932c3b02c495f29b7c110dd072da745f (diff)
downloadfreeipa-3d1adb325512cf14de8b88ca8178dd4a754256ec.tar.gz
freeipa-3d1adb325512cf14de8b88ca8178dd4a754256ec.tar.xz
freeipa-3d1adb325512cf14de8b88ca8178dd4a754256ec.zip
Refactor test_user_plugin, use UserTracker for tests
Reviewed-By: Ales 'alich' Marecek <amarecek@redhat.com> Reviewed-By: Milan Kubik <mkubik@redhat.com>
Diffstat (limited to 'ipatests/test_xmlrpc')
-rw-r--r--ipatests/test_xmlrpc/test_user_plugin.py2377
-rw-r--r--ipatests/test_xmlrpc/tracker/user_plugin.py169
2 files changed, 1026 insertions, 1520 deletions
diff --git a/ipatests/test_xmlrpc/test_user_plugin.py b/ipatests/test_xmlrpc/test_user_plugin.py
index 084fb83c4..355573138 100644
--- a/ipatests/test_xmlrpc/test_user_plugin.py
+++ b/ipatests/test_xmlrpc/test_user_plugin.py
@@ -2,6 +2,7 @@
# Rob Crittenden <rcritten@redhat.com>
# Pavel Zuna <pzuna@redhat.com>
# Jason Gerard DeRose <jderose@redhat.com>
+# Filip Skola <fskola@redhat.com>
#
# Copyright (C) 2008, 2009 Red Hat
# see file 'COPYING' for use and warranty information
@@ -23,6 +24,7 @@
Test the `ipalib/plugins/user.py` module.
"""
+import pytest
import datetime
import ldap
import re
@@ -30,42 +32,41 @@ import re
from ipalib import api, errors
from ipatests.test_xmlrpc import objectclasses
from ipatests.util import (
- assert_equal, assert_not_equal, raises)
+ assert_deepequal, assert_equal, assert_not_equal, raises)
from xmlrpc_test import (
- XMLRPC_test, Declarative, fuzzy_digits, fuzzy_uuid, fuzzy_password,
- fuzzy_string, fuzzy_dergeneralizedtime, add_sid, add_oc)
+ XMLRPC_test, fuzzy_digits, fuzzy_uuid, fuzzy_password,
+ fuzzy_string, fuzzy_dergeneralizedtime, add_sid, add_oc, raises_exact)
from ipapython.dn import DN
-import pytest
-user1 = u'tuser1'
-user2 = u'tuser2'
+from ipatests.test_xmlrpc.tracker.base import Tracker
+from ipatests.test_xmlrpc.tracker.group_plugin import GroupTracker
+from ipatests.test_xmlrpc.tracker.user_plugin import UserTracker
+
admin1 = u'admin'
-admin2 = u'admin2'
-renameduser1 = u'tuser'
-group1 = u'group1'
-admins_group = u'admins'
+admin_group = u'admins'
invaliduser1 = u'+tuser1'
-invaliduser2 = u'tuser1234567890123456789012345678901234567890'
+invaliduser2 = u''.join(['a' for n in range(256)])
sshpubkey = (u'ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDGAX3xAeLeaJggwTqMjxNwa6X'
- 'HBUAikXPGMzEpVrlLDCZtv00djsFTBi38PkgxBJVkgRWMrcBsr/35lq7P6w8KGI'
- 'wA8GI48Z0qBS2NBMJ2u9WQ2hjLN6GdMlo77O0uJY3251p12pCVIS/bHRSq8kHO2'
- 'No8g7KA9fGGcagPfQH+ee3t7HUkpbQkFTmbPPN++r3V8oVUk5LxbryB3UIIVzNm'
- 'cSIn3JrXynlvui4MixvrtX6zx+O/bBo68o8/eZD26QrahVbA09fivrn/4h3TM01'
- '9Eu/c2jOdckfU3cHUV/3Tno5d6JicibyaoDDK7S/yjdn5jhaz8MSEayQvFkZkiF'
- '0L public key test')
+ 'HBUAikXPGMzEpVrlLDCZtv00djsFTBi38PkgxBJVkgRWMrcBsr/35lq7P6w8KGI'
+ 'wA8GI48Z0qBS2NBMJ2u9WQ2hjLN6GdMlo77O0uJY3251p12pCVIS/bHRSq8kHO2'
+ 'No8g7KA9fGGcagPfQH+ee3t7HUkpbQkFTmbPPN++r3V8oVUk5LxbryB3UIIVzNm'
+ 'cSIn3JrXynlvui4MixvrtX6zx+O/bBo68o8/eZD26QrahVbA09fivrn/4h3TM01'
+ '9Eu/c2jOdckfU3cHUV/3Tno5d6JicibyaoDDK7S/yjdn5jhaz8MSEayQvFkZkiF'
+ '0L public key test')
sshpubkeyfp = (u'13:67:6B:BF:4E:A2:05:8E:AE:25:8B:A1:31:DE:6F:1B '
- 'public key test (ssh-rsa)')
+ 'public key test (ssh-rsa)')
-validlanguage1 = u'en-US;q=0.987 , en, abcdfgh-abcdefgh;q=1 , a;q=1.000'
-validlanguage2 = u'*'
+validlanguages = {
+ u'en-US;q=0.987 , en, abcdfgh-abcdefgh;q=1 , a;q=1.000',
+ u'*'
+ }
-invalidlanguage1 = u'abcdfghji-abcdfghji'
-invalidlanguage2 = u'en-us;q=0,123'
-invalidlanguage3 = u'en-us;q=0.1234'
-invalidlanguage4 = u'en-us;q=1.1'
-invalidlanguage5 = u'en-us;q=1.0000'
+invalidlanguages = {
+ u'abcdfghji-abcdfghji', u'en-us;q=0,123',
+ u'en-us;q=0.1234', u'en-us;q=1.1', u'en-us;q=1.0000'
+ }
principal_expiration_string = "2020-12-07T19:54:13Z"
principal_expiration_date = datetime.datetime(2020, 12, 7, 19, 54, 13)
@@ -77,6 +78,856 @@ expired_expiration_string = "1991-12-07T19:54:13Z"
isodate_re = re.compile('^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z$')
+@pytest.fixture(scope='class')
+def user(request):
+ tracker = UserTracker(name=u'user1', givenname=u'Test', sn=u'User1')
+ return tracker.make_fixture(request)
+
+
+@pytest.fixture(scope='class')
+def user2(request):
+ tracker = UserTracker(name=u'user2', givenname=u'Test2', sn=u'User2')
+ return tracker.make_fixture(request)
+
+
+@pytest.fixture(scope='class')
+def renameduser(request):
+ tracker = UserTracker(name=u'ruser1', givenname=u'Ruser', sn=u'Ruser1')
+ return tracker.make_fixture(request)
+
+
+@pytest.fixture(scope='class')
+def admin2(request):
+ tracker = UserTracker(name=u'admin2', givenname=u'Second', sn=u'Admin')
+ return tracker.make_fixture(request)
+
+
+@pytest.fixture(scope='class')
+def user_npg(request, group):
+ """ User tracker fixture for testing users with no private group """
+ tracker = UserTracker(name=u'npguser1', givenname=u'Npguser',
+ sn=u'Npguser1', noprivate=True)
+ tracker.track_create()
+ del tracker.attrs['mepmanagedentry']
+ tracker.attrs.update(
+ description=[], memberof_group=[group.cn],
+ objectclass=add_oc(objectclasses.user_base, u'ipantuserattrs')
+ )
+ return tracker.make_fixture(request)
+
+
+@pytest.fixture(scope='class')
+def user_npg2(request, group):
+ """ User tracker fixture for testing users with no private group """
+ tracker = UserTracker(name=u'npguser2', givenname=u'Npguser',
+ sn=u'Npguser2', noprivate=True, gidnumber=1000)
+ tracker.track_create()
+ del tracker.attrs['mepmanagedentry']
+ tracker.attrs.update(
+ gidnumber=[u'1000'], description=[], memberof_group=[group.cn],
+ objectclass=add_oc(objectclasses.user_base, u'ipantuserattrs')
+ )
+ return tracker.make_fixture(request)
+
+
+@pytest.fixture(scope='class')
+def group(request):
+ tracker = GroupTracker(name=u'group1')
+ return tracker.make_fixture(request)
+
+
+@pytest.mark.tier1
+class TestNonexistentUser(XMLRPC_test):
+ def test_retrieve_nonexistent(self, user):
+ """ Try to retrieve a non-existent user """
+ user.ensure_missing()
+ command = user.make_retrieve_command()
+ with raises_exact(errors.NotFound(
+ reason=u'%s: user not found' % user.uid)):
+ command()
+
+ def test_update_nonexistent(self, user):
+ """ Try to update a non-existent user """
+ user.ensure_missing()
+ command = user.make_update_command(
+ updates=dict(givenname=u'changed'))
+ with raises_exact(errors.NotFound(
+ reason=u'%s: user not found' % user.uid)):
+ command()
+
+ def test_delete_nonexistent(self, user):
+ """ Try to delete a non-existent user """
+ user.ensure_missing()
+ command = user.make_delete_command()
+ with raises_exact(errors.NotFound(
+ reason=u'%s: user not found' % user.uid)):
+ command()
+
+ def test_rename_nonexistent(self, user, renameduser):
+ """ Try to rename a non-existent user """
+ user.ensure_missing()
+ command = user.make_update_command(
+ updates=dict(setattr=u'uid=%s' % renameduser.uid))
+ with raises_exact(errors.NotFound(
+ reason=u'%s: user not found' % user.uid)):
+ command()
+
+
+@pytest.mark.tier1
+class TestUser(XMLRPC_test):
+ def test_retrieve(self, user):
+ """ Create user and try to retrieve it """
+ user.retrieve()
+
+ def test_delete(self, user):
+ """ Delete user """
+ user.delete()
+
+ def test_query_status(self, user):
+ """ Query user_status on a user """
+ user.ensure_exists()
+ result = user.run_command('user_status', user.uid)
+ assert_deepequal(dict(
+ count=1,
+ result=[dict(
+ dn=user.dn,
+ krblastfailedauth=[u'N/A'],
+ krblastsuccessfulauth=[u'N/A'],
+ krbloginfailedcount=u'0',
+ now=isodate_re.match,
+ server=api.env.host,
+ ), ],
+ summary=u'Account disabled: False',
+ truncated=False,
+ ), result)
+ user.delete()
+
+ def test_remove_userclass(self, user):
+ """ Remove attribute userclass from user entry """
+ user.ensure_exists()
+ result = user.run_command(
+ 'user_mod', user.uid, **dict(userclass=u'')
+ )
+ user.check_update(result)
+ user.delete()
+
+
+@pytest.mark.tier1
+class TestFind(XMLRPC_test):
+ def test_find(self, user):
+ """ Basic check of user-find """
+ user.find()
+
+ def test_find_with_all(self, user):
+ """ Basic check of user-find with --all """
+ user.find(all=True)
+
+ def test_find_with_pkey_only(self, user):
+ """ Basic check of user-find with primary keys only """
+ user.ensure_exists()
+ command = user.make_find_command(
+ uid=user.uid, pkey_only=True
+ )
+ result = command()
+ user.check_find(result, pkey_only=True)
+
+
+@pytest.mark.tier1
+class TestActive(XMLRPC_test):
+ def test_disable(self, user):
+ """ Disable user using user-disable """
+ user.ensure_exists()
+ user.disable()
+ command = user.make_retrieve_command()
+ result = command()
+ user.check_retrieve(result)
+
+ def test_enable(self, user):
+ """ Enable user using user-enable """
+ user.ensure_exists()
+ user.enable()
+ command = user.make_retrieve_command()
+ result = command()
+ user.check_retrieve(result)
+
+ def test_disable_using_setattr(self, user):
+ """ Disable user using setattr """
+ user.ensure_exists()
+ # we need to update the track manually
+ user.attrs['nsaccountlock'] = True
+
+ command = user.make_update_command(
+ updates=dict(setattr=u'nsaccountlock=True')
+ )
+ result = command()
+ user.check_update(result)
+
+ def test_enable_using_setattr(self, user):
+ """ Enable user using setattr """
+ user.ensure_exists()
+ user.attrs['nsaccountlock'] = False
+
+ command = user.make_update_command(
+ updates=dict(setattr=u'nsaccountlock=False')
+ )
+ result = command()
+ user.check_update(result)
+
+ def test_disable_using_usermod(self, user):
+ """ Disable user using user-mod """
+ user.update(dict(nsaccountlock=True), dict(nsaccountlock=True))
+
+ def test_enable_using_usermod(self, user):
+ """ Enable user using user-mod """
+ user.update(dict(nsaccountlock=False), dict(nsaccountlock=False))
+
+
+@pytest.mark.tier1
+class TestUpdate(XMLRPC_test):
+ def test_set_virtual_attribute(self, user):
+ """ Try to assign an invalid virtual attribute """
+ attr = 'random'
+ user.ensure_exists()
+ command = user.make_update_command(
+ updates=dict(setattr=(u'%s=xyz123' % attr))
+ )
+ with raises_exact(errors.ObjectclassViolation(
+ info=u'attribute "%s" not allowed' % attr)):
+ command()
+
+ def test_update(self, user):
+ """ Update a user attribute """
+ user.update(dict(givenname=u'Franta'))
+
+ def test_update_krb_ticket_policy(self, user):
+ """ Try to update krbmaxticketlife """
+ attr = 'krbmaxticketlife'
+ user.ensure_exists()
+ command = user.make_update_command(
+ updates=dict(setattr=(u'%s=88000' % attr))
+ )
+ with raises_exact(errors.ObjectclassViolation(
+ info=u'attribute "%s" not allowed' % attr)):
+ command()
+
+ def test_rename(self, user, renameduser):
+ """ Rename user and than rename it back """
+ user.ensure_exists()
+ renameduser.ensure_missing()
+ olduid = user.uid
+
+ # using user.update(dict(uid=value)) results in
+ # OverlapError: overlapping arguments and options: ['uid']
+ user.attrs.update(uid=[renameduser.uid])
+ command = user.make_update_command(
+ updates=dict(setattr=(u'uid=%s' % renameduser.uid))
+ )
+ result = command()
+ user.check_update(result)
+ user.uid = renameduser.uid
+
+ # rename the test user back so it gets properly deleted
+ user.attrs.update(uid=[olduid])
+ command = user.make_update_command(
+ updates=dict(setattr=(u'uid=%s' % olduid))
+ )
+ result = command()
+ user.check_update(result)
+ user.uid = olduid
+
+ def test_rename_to_the_same_value(self, user):
+ """ Try to rename user to the same value """
+ user.ensure_exists()
+ command = user.make_update_command(
+ updates=dict(setattr=(u'uid=%s' % user.uid))
+ )
+ with raises_exact(errors.EmptyModlist()):
+ command()
+
+ def test_rename_to_the_same_with_other_mods(self, user):
+ """ Try to rename user to the same value while
+ including other modifications that should be done """
+ user.ensure_exists()
+ user.attrs.update(loginshell=[u'/bin/false'])
+ command = user.make_update_command(
+ updates=dict(setattr=u'uid=%s' % user.uid,
+ loginshell=u'/bin/false')
+ )
+ result = command()
+ user.check_update(result)
+
+ def test_rename_to_too_long_login(self, user):
+ """ Try to change user login to too long value """
+ user.ensure_exists()
+ command = user.make_update_command(
+ updates=dict(rename=invaliduser2)
+ # no exception raised, user is renamed
+ )
+ with raises_exact(errors.ValidationError(
+ name='rename',
+ error=u'can be at most 255 characters')):
+ command()
+
+ def test_update_illegal_ssh_pubkey(self, user):
+ """ Try to update user with an illegal SSH public key """
+ user.ensure_exists()
+ command = user.make_update_command(
+ updates=dict(ipasshpubkey=[u"anal nathrach orth' bhais's bethad "
+ "do che'l de'nmha"])
+ )
+ with raises_exact(errors.ValidationError(
+ name='sshpubkey',
+ error=u'invalid SSH public key')):
+ command()
+
+ def test_set_ipauserauthtype(self, user):
+ """ Set ipauserauthtype to 'password' and than back to None """
+ user.ensure_exists()
+ user.update(dict(ipauserauthtype=u'password'))
+ user.retrieve()
+
+ user.update(dict(ipauserauthtype=None))
+ user.delete()
+
+ def test_set_random_password(self, user):
+ """ Modify user with random password """
+ user.ensure_exists()
+ user.attrs.update(
+ randompassword=fuzzy_password,
+ has_keytab=True,
+ has_password=True
+ )
+ user.update(
+ dict(random=True),
+ dict(random=None, randompassword=fuzzy_password)
+ )
+ user.delete()
+
+ def test_rename_to_invalid_login(self, user):
+ """ Try to change user login to an invalid value """
+ user.ensure_exists()
+ command = user.make_update_command(
+ updates=dict(rename=invaliduser1)
+ )
+ with raises_exact(errors.ValidationError(
+ name='rename',
+ error=u'may only include letters, numbers, _, -, . and $')):
+ command()
+
+
+@pytest.mark.tier1
+class TestCreate(XMLRPC_test):
+ def test_create_with_krb_ticket_policy(self):
+ """ Try to create user with krbmaxticketlife set """
+ testuser = UserTracker(
+ name=u'tuser1', givenname=u'Test',
+ sn=u'Tuser1', setattr=u'krbmaxticketlife=88000'
+ )
+ command = testuser.make_create_command()
+ with raises_exact(errors.ObjectclassViolation(
+ info=u'attribute "%s" not allowed' % 'krbmaxticketlife')):
+ command()
+
+ def test_create_with_ssh_pubkey(self):
+ """ Create user with an assigned SSH public key """
+ testuser = UserTracker(
+ name=u'tuser1', givenname=u'Test',
+ sn=u'Tuser1', ipasshpubkey=sshpubkey
+ )
+ testuser.track_create()
+ # fingerprint is expected in the tracker attrs
+ testuser.attrs.update(sshpubkeyfp=[sshpubkeyfp])
+ command = testuser.make_create_command()
+ result = command()
+ testuser.check_create(result)
+ testuser.delete()
+
+ def test_create_with_invalid_login(self):
+ """ Try to create user with an invalid login string """
+ testuser = UserTracker(
+ name=invaliduser1, givenname=u'Test', sn=u'User1'
+ )
+ command = testuser.make_create_command()
+ with raises_exact(errors.ValidationError(
+ name=u'login',
+ error=u'may only include letters, numbers, _, -, . and $')):
+ command()
+
+ def test_create_with_too_long_login(self):
+ """ Try to create user with too long login string """
+ testuser = UserTracker(
+ name=invaliduser2, givenname=u'Test', sn=u'User1'
+ )
+ command = testuser.make_create_command()
+ with raises_exact(errors.ValidationError(
+ name=u'login',
+ error=u'can be at most 255 characters')):
+ command()
+
+ def test_create_with_full_address(self):
+ """ Create user with full address set """
+ testuser = UserTracker(
+ name=u'tuser1', givenname=u'Test', sn=u'Tuser1',
+ street=u'123 Maple Rd', l=u'Anytown', st=u'MD',
+ postalcode=u'01234-5678', mobile=u'410-555-1212'
+ )
+ testuser.create()
+ testuser.delete()
+
+ def test_create_with_random_passwd(self):
+ """ Create user with random password """
+ testuser = UserTracker(
+ name=u'tuser1', givenname=u'Test', sn=u'Tuser1', random=True
+ )
+ testuser.track_create()
+ testuser.attrs.update(
+ randompassword=fuzzy_password,
+ has_keytab=True, has_password=True,
+ krbextradata=[fuzzy_string],
+ krbpasswordexpiration=[fuzzy_dergeneralizedtime],
+ krblastpwdchange=[fuzzy_dergeneralizedtime]
+ )
+ command = testuser.make_create_command()
+ result = command()
+ testuser.check_create(result)
+ testuser.delete()
+
+ def test_create_with_different_default_home(self, user):
+ """ Change default home directory and check that a newly created
+ user has his home set properly """
+ user.ensure_missing()
+ user.run_command('config_mod', **{u'ipahomesrootdir': u'/other-home'})
+ user.track_create()
+ user.attrs.update(homedirectory=[u'/other-home/%s' % user.name])
+
+ command = user.make_create_command()
+ result = command()
+ user.check_create(result)
+ user.run_command('config_mod', **{u'ipahomesrootdir': u'/home'})
+ user.delete()
+
+ def test_create_with_different_default_shell(self, user):
+ """ Change default login shell and check that a newly created
+ user is created with correct login shell value """
+ user.ensure_missing()
+ user.run_command(
+ 'config_mod', **{u'ipadefaultloginshell': u'/bin/zsh'}
+ )
+ user.track_create()
+ user.attrs.update(loginshell=[u'/bin/zsh'])
+ command = user.make_create_command()
+ result = command()
+ user.check_create(result)
+ user.run_command(
+ 'config_mod', **{u'ipadefaultloginshell': u'/bin/sh'}
+ )
+ user.delete()
+
+ def test_create_without_upg(self):
+ """ Try to create user without User's Primary GID """
+ testuser = UserTracker(
+ name=u'tuser1', givenname=u'Test', sn=u'Tuser1',
+ noprivate=True
+ )
+ command = testuser.make_create_command()
+ with raises_exact(errors.NotFound(
+ reason=u'Default group for new users is not POSIX')):
+ command()
+
+ def test_create_without_upg_with_gid_set(self):
+ """ Create user without User's Primary GID with GID set """
+ testuser = UserTracker(
+ name=u'tuser1', givenname=u'Test', sn=u'Tuser1',
+ noprivate=True, gidnumber=1000
+ )
+ testuser.track_create()
+ del testuser.attrs['mepmanagedentry']
+ testuser.attrs.update(gidnumber=[u'1000'])
+ testuser.attrs.update(
+ description=[],
+ objectclass=add_oc(objectclasses.user_base, u'ipantuserattrs')
+ )
+ command = testuser.make_create_command()
+ result = command()
+ testuser.check_create(result, [u'description'])
+ testuser.delete()
+
+ def test_create_with_uid_999(self):
+ """ Check that server return uid and gid 999
+ when a new client asks for uid 999 """
+ testuser = UserTracker(
+ name=u'tuser1', givenname=u'Test', sn=u'Tuser1', uidnumber=999
+ )
+ testuser.track_create()
+ testuser.attrs.update(
+ uidnumber=[u'999'],
+ gidnumber=[u'999']
+ )
+ command = testuser.make_create_command()
+ result = command()
+ testuser.check_create(result)
+ testuser.delete()
+
+ def test_create_with_old_DNA_MAGIC_999(self):
+ """ Check that server picks suitable uid and gid
+ when an old client asks for the magic uid 999 """
+ testuser = UserTracker(
+ name=u'tuser1', givenname=u'Test', sn=u'Tuser1',
+ uidnumber=999, version=u'2.49'
+ )
+ testuser.track_create()
+ testuser.attrs.update(
+ uidnumber=[lambda v: int(v) != 999],
+ gidnumber=[lambda v: int(v) != 999],
+ )
+ command = testuser.make_create_command()
+ result = command()
+ testuser.check_create(result)
+ testuser.delete()
+
+ def test_create_duplicate(self, user):
+ """ Try to create second user with the same name """
+ user.ensure_exists()
+ command = user.make_create_command()
+ with raises_exact(errors.DuplicateEntry(
+ message=u'user with name "%s" already exists' %
+ user.uid)):
+ command()
+
+ def test_create_where_managed_group_exists(self, user, group):
+ """ Create a managed group and then try to create user
+ with the same name the group has """
+ group.create()
+ command = user.make_command(
+ 'user_add', group.cn, **dict(givenname=u'Test', sn=u'User1')
+ )
+ with raises_exact(errors.ManagedGroupExistsError(group=group.cn)):
+ command()
+
+
+@pytest.mark.tier1
+class TestUserWithGroup(XMLRPC_test):
+ def test_change_default_user_group(self, group):
+ """ Change default group for TestUserWithGroup class of tests """
+ group.create()
+ group.run_command(
+ 'config_mod', **{u'ipadefaultprimarygroup': group.cn}
+ )
+
+ def test_create_without_upg(self, user_npg):
+ """ Try to create user without User's Primary GID
+ after default group was changed """
+ command = user_npg.make_create_command()
+ # User without private group has some different attrs upon creation
+ # so we won't use make_create, but do own check instead
+ # These are set in the fixture
+ result = command()
+ user_npg.check_create(result, [u'description', u'memberof_group'])
+
+ def test_create_without_upg_with_gid_set(self, user_npg2):
+ """ Create user without User's Primary GID with GID set
+ after default group was changed """
+ command = user_npg2.make_create_command()
+ result = command()
+ user_npg2.check_create(result, [u'description', u'memberof_group'])
+
+ def test_set_manager(self, user_npg, user_npg2):
+ """ Update user with own group with manager with own group """
+ user_npg.update(dict(manager=user_npg2.uid))
+
+ def test_check_user_with_renamed_manager(self, user_npg, user_npg2):
+ """ Rename manager with own group, retrieve user and check
+ if its manager is also renamed """
+ renamed_name = u'renamed_npg2'
+ old_name = user_npg2.uid
+ command = user_npg2.make_update_command(dict(rename=renamed_name))
+ result = command()
+ user_npg2.attrs.update(uid=[renamed_name])
+ user_npg2.check_update(result)
+ user_npg.attrs.update(manager=[renamed_name])
+ user_npg.retrieve(all=True)
+
+ command = user_npg2.make_command(
+ 'user_mod', renamed_name, **dict(rename=old_name)
+ )
+ # we rename the user back otherwise the tracker is too confused
+ result = command()
+
+ def test_check_if_manager_gets_removed(self, user_npg, user_npg2):
+ """ Delete manager and check if it's gone from user's attributes """
+ user_npg2.delete()
+ del user_npg.attrs[u'manager']
+ del user_npg.attrs[u'description']
+ user_npg.retrieve(all=True)
+
+ def test_change_default_user_group_back(self, user_npg, user_npg2):
+ """ Change default group back to 'ipausers' and clean up members """
+ user_npg.delete()
+ user_npg.run_command(
+ 'config_mod', **{u'ipadefaultprimarygroup': u'ipausers'}
+ )
+
+
+@pytest.mark.tier1
+class TestManagers(XMLRPC_test):
+ def test_assign_nonexistent_manager(self, user, user2):
+ """ Try to assign user a non-existent manager """
+ user.ensure_exists()
+ user2.ensure_missing()
+ command = user.make_update_command(
+ updates=dict(manager=user2.uid)
+ )
+ with raises_exact(errors.NotFound(
+ reason=u'manager %s not found' % user2.uid)):
+ command()
+
+ def test_assign_manager(self, user, user2):
+ """ Make user manager of another user """
+ user.ensure_exists()
+ user2.ensure_exists()
+ user.update(dict(manager=user2.uid))
+
+ def test_search_by_manager(self, user, user2):
+ """ Find user by his manager's UID """
+ command = user.make_find_command(manager=user2.uid)
+ result = command()
+ user.check_find(result)
+
+ def test_delete_both_user_and_manager(self, user, user2):
+ """ Delete both user and its manager at once """
+ result = user.run_command(
+ 'user_del', [user.uid, user2.uid],
+ preserve=False, no_preserve=True
+ )
+ assert_deepequal(dict(
+ value=[user.uid, user2.uid],
+ summary=u'Deleted user "%s,%s"' % (user.uid, user2.uid),
+ result=dict(failed=[]),
+ ), result)
+ # mark users as deleted
+ user.exists = False
+ user2.exists = False
+
+
+@pytest.mark.tier1
+class TestAdmins(XMLRPC_test):
+ def test_remove_original_admin(self):
+ """ Try to remove the only admin """
+ tracker = Tracker()
+ command = tracker.make_command('user_del', [admin1])
+
+ with raises_exact(errors.LastMemberError(
+ key=admin1, label=u'group', container=admin_group)):
+ command()
+
+ def test_disable_original_admin(self):
+ """ Try to disable the only admin """
+ tracker = Tracker()
+ command = tracker.make_command('user_disable', admin1)
+
+ with raises_exact(errors.LastMemberError(
+ key=admin1, label=u'group', container=admin_group)):
+ command()
+
+ def test_create_admin2(self, admin2):
+ """ Test whether second admin gets created """
+ admin2.ensure_exists()
+ admin2.make_admin()
+ admin2.delete()
+
+ def test_last_admin_preservation(self, admin2):
+ """ Create a second admin, disable it. Then try to disable and
+ remove the original one and receive LastMemberError. Last trial
+ are these ops with second admin removed. """
+ admin2.ensure_exists()
+ admin2.make_admin()
+ admin2.disable()
+ tracker = Tracker()
+
+ with raises_exact(errors.LastMemberError(
+ key=admin1, label=u'group', container=admin_group)):
+ tracker.run_command('user_disable', admin1)
+ with raises_exact(errors.LastMemberError(
+ key=admin1, label=u'group', container=admin_group)):
+ tracker.run_command('user_del', admin1)
+ admin2.delete()
+
+ with raises_exact(errors.LastMemberError(
+ key=admin1, label=u'group', container=admin_group)):
+ tracker.run_command('user_disable', admin1)
+ with raises_exact(errors.LastMemberError(
+ key=admin1, label=u'group', container=admin_group)):
+ tracker.run_command('user_del', admin1)
+
+
+@pytest.mark.tier1
+class TestPreferredLanguages(XMLRPC_test):
+ def test_invalid_preferred_languages(self, user):
+ """ Try to assign various invalid preferred languages to user """
+ user.ensure_exists()
+ for invalidlanguage in invalidlanguages:
+ command = user.make_update_command(
+ dict(preferredlanguage=invalidlanguage)
+ )
+
+ with raises_exact(errors.ValidationError(
+ name='preferredlanguage',
+ error=(u'must match RFC 2068 - 14.4, e.g., '
+ '"da, en-gb;q=0.8, en;q=0.7"')
+ )):
+ command()
+ user.delete()
+
+ def test_valid_preferred_languages(self, user):
+ """ Update user with different preferred languages """
+ for validlanguage in validlanguages:
+ user.update(dict(preferredlanguage=validlanguage))
+ user.delete()
+
+
+@pytest.mark.tier1
+class TestPrincipals(XMLRPC_test):
+ def test_create_with_bad_realm_in_principal(self):
+ """ Try to create user with a bad realm in principal """
+ testuser = UserTracker(
+ name=u'tuser1', givenname=u'Test', sn=u'Tuser1',
+ krbprincipalname=u'tuser1@NOTFOUND.ORG'
+ )
+
+ command = testuser.make_create_command()
+ with raises_exact(errors.RealmMismatch()):
+ command()
+
+ def test_create_with_malformed_principal(self):
+ """ Try to create user with wrongly formed principal """
+ testuser = UserTracker(
+ name=u'tuser1', givenname=u'Test', sn=u'Tuser1',
+ krbprincipalname=u'tuser1@BAD@NOTFOUND.ORG'
+ )
+
+ command = testuser.make_create_command()
+ with raises_exact(errors.MalformedUserPrincipal(
+ principal=u'tuser1@BAD@NOTFOUND.ORG')):
+ command()
+
+ def test_set_principal_expiration(self, user):
+ """ Set principal expiration for user """
+ user.update(
+ dict(krbprincipalexpiration=principal_expiration_string),
+ dict(krbprincipalexpiration=[principal_expiration_date])
+ )
+
+ def test_set_invalid_principal_expiration(self, user):
+ """ Try to set incorrent principal expiration value for user """
+ user.ensure_exists()
+ command = user.make_update_command(
+ dict(krbprincipalexpiration=invalid_expiration_string)
+ )
+
+ with raises_exact(errors.ConversionError(
+ name='principal_expiration',
+ error=(u'does not match any of accepted formats: '
+ '%Y%m%d%H%M%SZ, %Y-%m-%dT%H:%M:%SZ, %Y-%m-%dT%H:%MZ, '
+ '%Y-%m-%dZ, %Y-%m-%d %H:%M:%SZ, %Y-%m-%d %H:%MZ')
+ )):
+ command()
+
+ def test_create_with_uppercase_principal(self):
+ """ Create user with upper-case principal """
+ testuser = UserTracker(
+ name=u'tuser1', givenname=u'Test', sn=u'Tuser1',
+ krbprincipalname=u'tuser1'.upper()
+ )
+ testuser.create()
+ testuser.delete()
+
+
+@pytest.mark.tier1
+class TestValidation(XMLRPC_test):
+ # The assumption for this class of tests is that if we don't
+ # get a validation error then the request was processed normally.
+
+ def test_validation_disabled_on_deletes(self):
+ """ Test that validation is disabled on user deletes """
+ tracker = Tracker()
+ command = tracker.make_command('user_del', invaliduser1)
+ with raises_exact(errors.NotFound(
+ reason=u'%s: user not found' % invaliduser1)):
+ command()
+
+ def test_validation_disabled_on_show(self):
+ """ Test that validation is disabled on user retrieves """
+ tracker = Tracker()
+ command = tracker.make_command('user_show', invaliduser1)
+ with raises_exact(errors.NotFound(
+ reason=u'%s: user not found' % invaliduser1)):
+ command()
+
+ def test_validation_disabled_on_find(self, user):
+ """ Test that validation is disabled on user searches """
+ result = user.run_command('user_find', invaliduser1)
+ user.check_find_nomatch(result)
+
+
+@pytest.mark.tier1
+class TestDeniedBindWithExpiredPrincipal(XMLRPC_test):
+
+ password = u'random'
+
+ @classmethod
+ def setup_class(cls):
+ super(TestDeniedBindWithExpiredPrincipal, cls).setup_class()
+
+ cls.connection = ldap.initialize('ldap://{host}'
+ .format(host=api.env.host))
+
+ @classmethod
+ def teardown_class(cls):
+ super(TestDeniedBindWithExpiredPrincipal, cls).teardown_class()
+
+ def test_bind_as_test_user(self, user):
+ """ Bind as user """
+ self.failsafe_add(
+ api.Object.user,
+ user.uid,
+ givenname=u'Test',
+ sn=u'User1',
+ userpassword=self.password,
+ krbprincipalexpiration=principal_expiration_string
+ )
+
+ self.connection.simple_bind_s(
+ str(get_user_dn(user.uid)), self.password
+ )
+
+ def test_bind_as_expired_test_user(self, user):
+ """ Try to bind as expired user """
+ api.Command['user_mod'](
+ user.uid,
+ krbprincipalexpiration=expired_expiration_string
+ )
+
+ raises(ldap.UNWILLING_TO_PERFORM,
+ self.connection.simple_bind_s,
+ str(get_user_dn(user.uid)), self.password
+ )
+
+ def test_bind_as_renewed_test_user(self, user):
+ """ Bind as renewed user """
+ api.Command['user_mod'](
+ user.uid,
+ krbprincipalexpiration=principal_expiration_string
+ )
+
+ self.connection.simple_bind_s(
+ str(get_user_dn(user.uid)), self.password
+ )
+
+# This set of functions (get_*, upg_check, not_upg_check)
+# is mostly for legacy purposes here, tests using UserTracker
+# should not rely on them
+
+
def get_user_result(uid, givenname, sn, operation='show', omit=[],
**overrides):
"""Get a user result for a user-{add,mod,find,show} command
@@ -155,10 +1006,12 @@ def get_admin_result(operation='show', **overrides):
def get_user_dn(uid):
+ """ Get user DN by uid """
return DN(('uid', uid), api.env.container_user, api.env.basedn)
def get_group_dn(cn):
+ """ Get group DN by CN """
return DN(('cn', cn), api.env.container_group, api.env.basedn)
@@ -178,1477 +1031,3 @@ def not_upg_check(response):
assert_not_equal(response['result']['uidnumber'],
response['result']['gidnumber'])
return True
-
-
-@pytest.mark.tier1
-class test_user(Declarative):
-
- cleanup_commands = [
- ('user_del', [user1, user2, renameduser1, admin2], {'continue': True}),
- ('group_del', [group1], {}),
- ('automember_default_group_remove', [], {'type': u'group'}),
- ]
-
- tests = [
-
- dict(
- desc='Try to retrieve non-existent "%s"' % user1,
- command=('user_show', [user1], {}),
- expected=errors.NotFound(reason=u'%s: user not found' % user1),
- ),
-
-
- dict(
- desc='Try to update non-existent "%s"' % user1,
- command=('user_mod', [user1], dict(givenname=u'Foo')),
- expected=errors.NotFound(reason=u'%s: user not found' % user1),
- ),
-
-
- dict(
- desc='Try to delete non-existent "%s"' % user1,
- command=('user_del', [user1], {}),
- expected=errors.NotFound(reason=u'%s: user not found' % user1),
- ),
-
-
- dict(
- desc='Try to rename non-existent "%s"' % user1,
- command=('user_mod', [user1],
- dict(setattr=u'uid=%s' % renameduser1)),
- expected=errors.NotFound(reason=u'%s: user not found' % user1),
- ),
-
-
- dict(
- desc='Create "%s"' % user1,
- command=(
- 'user_add',
- [user1],
- dict(
- givenname=u'Test',
- sn=u'User1',
- userclass=u'testusers'
- )
- ),
- expected=dict(
- value=user1,
- summary=u'Added user "%s"' % user1,
- result=get_user_result(
- user1,
- u'Test',
- u'User1',
- 'add',
- userclass=[u'testusers'],
- objectclass=add_oc(
- objectclasses.user,
- u'ipantuserattrs'
- ) + [u'ipauser']
- ),
- ),
- extra_check = upg_check,
- ),
-
-
- dict(
- desc='Try to create duplicate "%s"' % user1,
- command=(
- 'user_add', [user1], dict(givenname=u'Test', sn=u'User1')
- ),
- expected=errors.DuplicateEntry(
- message=u'user with name "%s" already exists' % user1),
- ),
-
-
- dict(
- desc='Retrieve "%s"' % user1,
- command=(
- 'user_show', [user1], {}
- ),
- expected=dict(
- result=get_user_result(
- user1,
- u'Test',
- u'User1',
- 'show',
- userclass=[u'testusers']
- ),
- value=user1,
- summary=None,
- ),
- ),
-
- dict(
- desc='Remove userclass for user "%s"' % user1,
- command=('user_mod', [user1], dict(userclass=u'')),
- expected=dict(
- result=get_user_result(user1, u'Test', u'User1', 'mod'),
- value=user1,
- summary=u'Modified user "%s"' % user1,
- ),
- ),
-
- dict(
- desc='Search for "%s" with all=True' % user1,
- command=(
- 'user_find', [user1], {'all': True}
- ),
- expected=dict(
- result=[
- get_user_result(
- user1,
- u'Test',
- u'User1',
- 'show-all',
- objectclass=add_oc(
- objectclasses.user,
- u'ipantuserattrs'
- ) + [u'ipauser'],
- preserved=False
- ),
- ],
- summary=u'1 user matched',
- count=1, truncated=False,
- ),
- ),
-
-
- dict(
- desc='Search for "%s" with pkey-only=True' % user1,
- command=(
- 'user_find', [user1], {'pkey_only': True}
- ),
- expected=dict(
- result=[
- {
- 'dn': get_user_dn(user1),
- 'uid': [user1],
- },
- ],
- summary=u'1 user matched',
- count=1, truncated=False,
- ),
- ),
-
-
- dict(
- desc='Search for "%s" with minimal attributes' % user1,
- command=(
- 'user_find', [user1], {}
- ),
- expected=dict(
- result=[
- get_user_result(user1, u'Test', u'User1', 'find'),
- ],
- summary=u'1 user matched',
- count=1,
- truncated=False,
- ),
- ),
-
-
- dict(
- desc='Search for all users',
- command=(
- 'user_find', [], {}
- ),
- expected=dict(
- result=[
- get_admin_result('find'),
- get_user_result(user1, u'Test', u'User1', 'find'),
- ],
- summary=u'2 users matched',
- count=2,
- truncated=False,
- ),
- ),
-
-
- dict(
- desc='Search for all users with a limit of 1',
- command=(
- 'user_find', [], dict(sizelimit=1,),
- ),
- expected=dict(
- result=[get_admin_result('find')],
- summary=u'1 user matched',
- count=1,
- truncated=True,
- ),
- ),
-
-
- dict(
- desc='Disable "%s"' % user1,
- command=(
- 'user_disable', [user1], {}
- ),
- expected=dict(
- result=True,
- value=user1,
- summary=u'Disabled user account "%s"' % user1,
- ),
- ),
-
- dict(
- desc='Assert user is disabled',
- command=('user_find', [user1], {}),
- expected=dict(
- result=[get_user_result(user1, u'Test', u'User1', 'find',
- nsaccountlock=True)],
- summary=u'1 user matched',
- count=1,
- truncated=False,
- ),
- ),
-
- dict(
- desc='Enable "%s"' % user1,
- command=(
- 'user_enable', [user1], {}
- ),
- expected=dict(
- result=True,
- value=user1,
- summary=u'Enabled user account "%s"' % user1,
- ),
- ),
-
- dict(
- desc='Assert user "%s" is enabled' % user1,
- command=('user_find', [user1], {}),
- expected=dict(
- result=[get_user_result(user1, u'Test', u'User1', 'find')],
- summary=u'1 user matched',
- count=1,
- truncated=False,
- ),
- ),
-
- dict(
- desc='Disable "%s" using setattr' % user1,
- command=('user_mod', [user1], dict(setattr=u'nsaccountlock=True')),
- expected=dict(
- result=get_user_result(user1, u'Test', u'User1', 'mod',
- nsaccountlock=True),
- value=user1,
- summary=u'Modified user "%s"' % user1,
- ),
- ),
-
- dict(
- desc='Enable "%s" using setattr' % user1,
- command=('user_mod', [user1], dict(setattr=u'nsaccountlock=False')),
- expected=dict(
- result=get_user_result(user1, u'Test', u'User1', 'mod'),
- value=user1,
- summary=u'Modified user "%s"' % user1,
- ),
- ),
-
- dict(
- desc='Disable "%s" using user_mod' % user1,
- command=('user_mod', [user1], dict(nsaccountlock=True)),
- expected=dict(
- result=get_user_result(user1, u'Test', u'User1', 'mod',
- nsaccountlock=True),
- value=user1,
- summary=u'Modified user "%s"' % user1,
- ),
- ),
-
- dict(
- desc='Enable "%s" using user_mod' % user1,
- command=('user_mod', [user1], dict(nsaccountlock=False)),
- expected=dict(
- result=get_user_result(user1, u'Test', u'User1', 'mod'),
- value=user1,
- summary=u'Modified user "%s"' % user1,
- ),
- ),
-
- dict(
- desc='Try setting virtual attribute on "%s" using setattr' % user1,
- command=('user_mod', [user1], dict(setattr=u'random=xyz123')),
- expected=errors.ObjectclassViolation(
- info='attribute "random" not allowed'),
- ),
-
- dict(
- desc='Update "%s"' % user1,
- command=(
- 'user_mod', [user1], dict(givenname=u'Finkle')
- ),
- expected=dict(
- result=get_user_result(user1, u'Finkle', u'User1', 'mod'),
- summary=u'Modified user "%s"' % user1,
- value=user1,
- ),
- ),
-
-
- dict(
- desc='Try updating the krb ticket policy of "%s"' % user1,
- command=(
- 'user_mod', [user1], dict(setattr=u'krbmaxticketlife=88000')
- ),
- expected=errors.ObjectclassViolation(
- info=u'attribute "krbmaxticketlife" not allowed'),
- ),
-
-
- dict(
- desc='Retrieve "%s" to verify update' % user1,
- command=('user_show', [user1], {}),
- expected=dict(
- result=get_user_result(user1, u'Finkle', u'User1', 'show'),
- summary=None,
- value=user1,
- ),
-
- ),
-
-
- dict(
- desc='Rename "%s"' % user1,
- command=('user_mod', [user1],
- dict(setattr=u'uid=%s' % renameduser1)),
- expected=dict(
- result=get_user_result(
- renameduser1, u'Finkle', u'User1', 'mod',
- mail=[u'%s@%s' % (user1, api.env.domain)],
- homedirectory=[u'/home/%s' % user1]),
- summary=u'Modified user "%s"' % user1,
- value=user1,
- ),
- ),
-
-
- dict(
- desc='Rename "%s" to same value' % renameduser1,
- command=('user_mod', [renameduser1],
- dict(setattr=u'uid=%s' % renameduser1)),
- expected=errors.EmptyModlist(),
- ),
-
- dict(
- desc='Rename "%s" to same value, check that other modifications '
- 'are performed' % renameduser1,
- command=('user_mod', [renameduser1],
- dict(setattr=u'uid=%s' % renameduser1,
- loginshell=u'/bin/bash')),
- expected=dict(
- result=get_user_result(
- renameduser1, u'Finkle', u'User1', 'mod',
- mail=[u'%s@%s' % (user1, api.env.domain)],
- homedirectory=[u'/home/%s' % user1],
- loginshell=[u'/bin/bash']),
- summary=u'Modified user "%s"' % renameduser1,
- value=renameduser1,
- ),
- ),
-
-
- dict(
- desc='Rename back "%s"' % renameduser1,
- command=('user_mod', [renameduser1],
- dict(setattr=u'uid=%s' % user1, loginshell=u'/bin/sh')),
- expected=dict(
- result=get_user_result(user1, u'Finkle', u'User1', 'mod'),
- summary=u'Modified user "%s"' % renameduser1,
- value=renameduser1,
- ),
- ),
-
-
- dict(
- desc='Delete "%s"' % user1,
- command=('user_del', [user1], {}),
- expected=dict(
- result=dict(failed=[]),
- summary=u'Deleted user "%s"' % user1,
- value=[user1],
- ),
- ),
-
-
- dict(
- desc='Try to delete non-existent "%s"' % user1,
- command=('user_del', [user1], {}),
- expected=errors.NotFound(reason=u'tuser1: user not found'),
- ),
-
-
- dict(
- desc='Create user "%s" with krb ticket policy' % user1,
- command=(
- 'user_add', [user1], dict(givenname=u'Test', sn=u'User1',
- setattr=u'krbmaxticketlife=88000')
- ),
- expected=errors.ObjectclassViolation(
- info='attribute "krbmaxticketlife" not allowed'),
- ),
-
-
- dict(
- desc='Create "%s" with SSH public key' % user1,
- command=(
- 'user_add', [user1], dict(givenname=u'Test', sn=u'User1',
- ipasshpubkey=[sshpubkey])
- ),
- expected=dict(
- value=user1,
- summary=u'Added user "%s"' % user1,
- result=get_user_result(
- user1, u'Test', u'User1', 'add',
- objectclass=add_oc(objectclasses.user, u'ipantuserattrs'),
- ipasshpubkey=[sshpubkey],
- sshpubkeyfp=[sshpubkeyfp],
- ),
- ),
- extra_check = upg_check,
- ),
-
-
- dict(
- desc='Add an illegal SSH public key to "%r"' % user1,
- command=('user_mod', [user1],
- dict(ipasshpubkey=[u"anal nathrach orth' bhais's bethad "
- "do che'l de'nmha"])),
- expected=errors.ValidationError(name='sshpubkey',
- error=u'invalid SSH public key'),
- ),
-
-
- dict(
- desc='Delete "%s"' % user1,
- command=('user_del', [user1], {}),
- expected=dict(
- result=dict(failed=[]),
- summary=u'Deleted user "%s"' % user1,
- value=[user1],
- ),
- ),
-
-
- dict(
- desc='Create "%s"' % user1,
- command=(
- 'user_add', [user1], dict(givenname=u'Test', sn=u'User1')
- ),
- expected=dict(
- value=user1,
- summary=u'Added user "%s"' % user1,
- result=get_user_result(user1, u'Test', u'User1', 'add'),
- ),
- extra_check = upg_check,
- ),
-
-
- dict(
- desc='Create "%s"' % user2,
- command=(
- 'user_add', [user2], dict(givenname=u'Test', sn=u'User2')
- ),
- expected=dict(
- value=user2,
- summary=u'Added user "%s"' % user2,
- result=get_user_result(user2, u'Test', u'User2', 'add'),
- ),
- extra_check = upg_check,
- ),
-
-
- dict(
- desc='Make non-existent "%s" the manager of "%s"' % (renameduser1,
- user2),
- command=('user_mod', [user2], dict(manager=renameduser1)),
- expected=errors.NotFound(
- reason=u'manager %s not found' % renameduser1),
- ),
-
-
- dict(
- desc='Make "%s" the manager of "%s"' % (user1, user2),
- command=('user_mod', [user2], dict(manager=user1)),
- expected=dict(
- result=get_user_result(user2, u'Test', u'User2', 'mod',
- manager=[user1]),
- summary=u'Modified user "%s"' % user2,
- value=user2,
- ),
- ),
-
- dict(
- desc='Search for "%s" with manager "%s"' % (user2, user1),
- command=(
- 'user_find', [user2], {'manager': user1}
- ),
- expected=dict(
- result=[get_user_result(user2, u'Test', u'User2', 'find',
- manager=[user1])],
- summary=u'1 user matched',
- count=1,
- truncated=False,
- ),
- ),
-
- dict(
- desc='Delete "%s" and "%s" at the same time' % (user1, user2),
- command=('user_del', [user1, user2], {}),
- expected=dict(
- result=dict(failed=[]),
- summary=u'Deleted user "tuser1,tuser2"',
- value=[user1, user2],
- ),
- ),
-
- dict(
- desc='Try to retrieve non-existent "%s"' % user1,
- command=('user_show', [user1], {}),
- expected=errors.NotFound(reason=u'%s: user not found' % user1),
- ),
-
-
- dict(
- desc='Try to update non-existent "%s"' % user1,
- command=('user_mod', [user1], dict(givenname=u'Foo')),
- expected=errors.NotFound(reason=u'%s: user not found' % user1),
- ),
-
-
- dict(
- desc='Test an invalid login name "%s"' % invaliduser1,
- command=('user_add', [invaliduser1], dict(givenname=u'Test',
- sn=u'User1')),
- expected=errors.ValidationError(name='login',
- error=u'may only include letters, numbers, _, -, . and $'),
- ),
-
-
- dict(
- desc='Test a login name that is too long "%s"' % invaliduser2,
- command=('user_add', [invaliduser2],
- dict(givenname=u'Test', sn=u'User1')),
- expected=errors.ValidationError(name='login',
- error='can be at most 32 characters'),
- ),
-
-
- # The assumption on these next 4 tests is that if we don't get a
- # validation error then the request was processed normally.
- dict(
- desc='Test that validation is disabled on deletes',
- command=('user_del', [invaliduser1], {}),
- expected=errors.NotFound(
- reason=u'%s: user not found' % invaliduser1),
- ),
-
-
- dict(
- desc='Test that validation is disabled on show',
- command=('user_show', [invaliduser1], {}),
- expected=errors.NotFound(
- reason=u'%s: user not found' % invaliduser1),
- ),
-
-
- dict(
- desc='Test that validation is disabled on find',
- command=('user_find', [invaliduser1], {}),
- expected=dict(
- count=0,
- truncated=False,
- summary=u'0 users matched',
- result=[],
- ),
- ),
-
-
- dict(
- desc='Try to rename to invalid username "%s"' % user1,
- command=('user_mod', [user1], dict(rename=invaliduser1)),
- expected=errors.ValidationError(name='rename',
- error=u'may only include letters, numbers, _, -, . and $'),
- ),
-
-
- dict(
- desc='Try to rename to a username that is too long "%s"' % user1,
- command=('user_mod', [user1], dict(rename=invaliduser2)),
- expected=errors.ValidationError(name='login',
- error='can be at most 32 characters'),
- ),
-
-
- dict(
- desc='Create "%s"' % group1,
- command=(
- 'group_add', [group1], dict(description=u'Test desc')
- ),
- expected=dict(
- value=group1,
- summary=u'Added group "%s"' % group1,
- result=dict(
- cn=[group1],
- description=[u'Test desc'],
- gidnumber=[fuzzy_digits],
- objectclass=objectclasses.group + [u'posixgroup'],
- ipauniqueid=[fuzzy_uuid],
- dn=get_group_dn(group1),
- ),
- ),
- ),
-
-
- dict(
- desc='Try to user "%s" where the managed group exists' % group1,
- command=(
- 'user_add', [group1], dict(givenname=u'Test', sn=u'User1')
- ),
- expected=errors.ManagedGroupExistsError(group=group1)
- ),
-
-
- dict(
- desc='Create "%s" with a full address' % user1,
- command=(
- 'user_add', [user1], dict(givenname=u'Test', sn=u'User1',
- street=u'123 Maple Rd', l=u'Anytown', st=u'MD',
- telephonenumber=u'410-555-1212', postalcode=u'01234-5678')
- ),
- expected=dict(
- value=user1,
- summary=u'Added user "%s"' % user1,
- result=get_user_result(
- user1, u'Test', u'User1', 'add',
- street=[u'123 Maple Rd'], l=[u'Anytown'], st=[u'MD'],
- telephonenumber=[u'410-555-1212'],
- postalcode=[u'01234-5678'],
- ),
- ),
- ),
-
-
- dict(
- desc='Delete "%s"' % user1,
- command=('user_del', [user1], {}),
- expected=dict(
- result=dict(failed=[]),
- summary=u'Deleted user "%s"' % user1,
- value=[user1],
- ),
- ),
-
- dict(
- desc='Create "%s" with random password' % user1,
- command=(
- 'user_add', [user1], dict(givenname=u'Test', sn=u'User1',
- random=True)
- ),
- expected=dict(
- value=user1,
- summary=u'Added user "%s"' % user1,
- result=get_user_result(
- user1, u'Test', u'User1', 'add',
- randompassword=fuzzy_password,
- has_keytab=True, has_password=True,
- krbextradata=[fuzzy_string],
- krbpasswordexpiration=[fuzzy_dergeneralizedtime],
- krblastpwdchange=[fuzzy_dergeneralizedtime]
- ),
- ),
- ),
-
- dict(
- desc='Delete "%s"' % user1,
- command=('user_del', [user1], {}),
- expected=dict(
- result=dict(failed=[]),
- summary=u'Deleted user "%s"' % user1,
- value=[user1],
- ),
- ),
-
- dict(
- desc='Create "%s"' % user2,
- command=(
- 'user_add', [user2], dict(givenname=u'Test', sn=u'User2')
- ),
- expected=dict(
- value=user2,
- summary=u'Added user "%s"' % user2,
- result=get_user_result(user2, u'Test', u'User2', 'add'),
- ),
- ),
-
- dict(
- desc='Modify "%s" with random password' % user2,
- command=(
- 'user_mod', [user2], dict(random=True)
- ),
- expected=dict(
- result=get_user_result(
- user2, u'Test', u'User2', 'mod',
- randompassword=fuzzy_password,
- has_keytab=True, has_password=True,
- ),
- summary=u'Modified user "%s"' % user2,
- value=user2,
- ),
- ),
-
- dict(
- desc='Delete "%s"' % user2,
- command=('user_del', [user2], {}),
- expected=dict(
- result=dict(failed=[]),
- summary=u'Deleted user "%s"' % user2,
- value=[user2],
- ),
- ),
-
- dict(
- desc='Create user "%s" with upper-case principal' % user1,
- command=(
- 'user_add', [user1], dict(givenname=u'Test', sn=u'User1',
- krbprincipalname=user1.upper())
- ),
- expected=dict(
- value=user1,
- summary=u'Added user "%s"' % user1,
- result=get_user_result(user1, u'Test', u'User1', 'add'),
- ),
- ),
-
-
- dict(
- desc='Create user "%s" with bad realm in principal' % user1,
- command=(
- 'user_add', [user1], dict(givenname=u'Test', sn=u'User1',
- krbprincipalname='%s@NOTFOUND.ORG' % user1)
- ),
- expected=errors.RealmMismatch()
- ),
-
-
- dict(
- desc='Create user "%s" with malformed principal' % user1,
- command=(
- 'user_add', [user1], dict(givenname=u'Test', sn=u'User1',
- krbprincipalname='%s@BAD@NOTFOUND.ORG' % user1)
- ),
- expected=errors.MalformedUserPrincipal(
- principal='%s@BAD@NOTFOUND.ORG' % user1),
- ),
-
- dict(
- desc='Delete "%s"' % user1,
- command=('user_del', [user1], {}),
- expected=dict(
- result=dict(failed=[]),
- summary=u'Deleted user "%s"' % user1,
- value=[user1],
- ),
- ),
-
- dict(
- desc='Change default home directory',
- command=(
- 'config_mod', [], dict(ipahomesrootdir=u'/other-home'),
- ),
- expected=lambda x, output: x is None,
- ),
-
- dict(
- desc=('Create user "%s" with different default '
- 'home directory' % user1),
- command=(
- 'user_add', [user1], dict(givenname=u'Test', sn=u'User1')
- ),
- expected=dict(
- value=user1,
- summary=u'Added user "%s"' % user1,
- result=get_user_result(user1, u'Test', u'User1', 'add',
- homedirectory=[u'/other-home/tuser1']),
- ),
- ),
-
-
- dict(
- desc='Reset default home directory',
- command=(
- 'config_mod', [], dict(ipahomesrootdir=u'/home'),
- ),
- expected=lambda x, output: x is None,
- ),
-
- dict(
- desc='Delete "%s"' % user1,
- command=('user_del', [user1], {}),
- expected=dict(
- result=dict(failed=[]),
- summary=u'Deleted user "%s"' % user1,
- value=[user1],
- ),
- ),
-
- dict(
- desc='Change default login shell',
- command=(
- 'config_mod', [],
- dict(ipadefaultloginshell=u'/usr/bin/ipython'),
- ),
- expected=lambda x, output: x is None,
- ),
-
- dict(
- desc='Create user "%s" with different default login shell' % user1,
- command=(
- 'user_add', [user1], dict(givenname=u'Test', sn=u'User1')
- ),
- expected=dict(
- value=user1,
- summary=u'Added user "%s"' % user1,
- result=get_user_result(user1, u'Test', u'User1', 'add',
- loginshell=[u'/usr/bin/ipython']),
- ),
- ),
-
- dict(
- desc='Reset default login shell',
- command=(
- 'config_mod', [], dict(ipadefaultloginshell=u'/bin/sh'),
- ),
- expected=lambda x, output: x is None,
- ),
-
- dict(
- desc='Delete "%s"' % user1,
- command=('user_del', [user1], {}),
- expected=dict(
- result=dict(failed=[]),
- summary=u'Deleted user "%s"' % user1,
- value=[user1],
- ),
- ),
-
- dict(
- desc='Create "%s" without UPG' % user1,
- command=(
- 'user_add', [user1], dict(givenname=u'Test', sn=u'User1',
- noprivate=True)
- ),
- expected=errors.NotFound(
- reason='Default group for new users is not POSIX'),
- ),
-
- dict(
- desc='Create "%s" without UPG with GID explicitly set' % user2,
- command=(
- 'user_add', [user2], dict(givenname=u'Test', sn=u'User2',
- noprivate=True, gidnumber=1000)
- ),
- expected=dict(
- value=user2,
- summary=u'Added user "%s"' % user2,
- result=get_user_result(
- user2, u'Test', u'User2', 'add',
- objectclass=add_oc(objectclasses.user_base,
- u'ipantuserattrs'),
- gidnumber=[u'1000'],
- description=[],
- omit=['mepmanagedentry'],
- ),
- ),
- ),
-
- dict(
- desc='Delete "%s"' % user2,
- command=('user_del', [user2], {}),
- expected=dict(
- result=dict(failed=[]),
- summary=u'Deleted user "%s"' % user2,
- value=[user2],
- ),
- ),
-
- dict(
- desc='Change default user group',
- command=(
- 'config_mod', [], dict(ipadefaultprimarygroup=group1),
- ),
- expected=lambda x, output: x is None,
- ),
-
- dict(
- desc='Create "%s" without UPG' % user1,
- command=(
- 'user_add', [user1], dict(givenname=u'Test', sn=u'User1',
- noprivate=True)
- ),
- expected=dict(
- value=user1,
- summary=u'Added user "%s"' % user1,
- result=get_user_result(
- user1, u'Test', u'User1', 'add',
- objectclass=add_oc(objectclasses.user_base,
- u'ipantuserattrs'),
- description=[],
- memberof_group=[group1],
- omit=['mepmanagedentry'],
- ),
- ),
- extra_check = not_upg_check,
- ),
-
- dict(
- desc='Create "%s" without UPG with GID explicitly set' % user2,
- command=(
- 'user_add', [user2], dict(givenname=u'Test', sn=u'User2',
- noprivate=True, gidnumber=1000)
- ),
- expected=dict(
- value=user2,
- summary=u'Added user "%s"' % user2,
- result=get_user_result(
- user2, u'Test', u'User2', 'add',
- objectclass=add_oc(objectclasses.user_base,
- u'ipantuserattrs'),
- description=[],
- gidnumber=[u'1000'],
- memberof_group=[group1],
- omit=['mepmanagedentry'],
- ),
- ),
- ),
-
- dict(
- desc='Set %r as manager of %r' % (user1, user2),
- command=(
- 'user_mod', [user2], dict(manager=user1)
- ),
- expected=dict(
- result=get_user_result(user2, u'Test', u'User2', 'mod',
- gidnumber=[u'1000'],
- memberof_group=[group1],
- manager=[user1]),
- summary=u'Modified user "%s"' % user2,
- value=user2,
- ),
- ),
-
- dict(
- desc='Rename "%s"' % user1,
- command=('user_mod', [user1], dict(rename=renameduser1)),
- expected=dict(
- result=get_user_result(
- renameduser1, u'Test', u'User1', 'mod',
- homedirectory=[u'/home/%s' % user1],
- mail=[u'%s@%s' % (user1, api.env.domain)],
- memberof_group=[group1],
- ),
- summary=u'Modified user "%s"' % user1,
- value=user1,
- ),
- ),
-
- dict(
- desc='Retrieve %r and check that manager is renamed' % user2,
- command=(
- 'user_show', [user2], {'all': True}
- ),
- expected=dict(
- result=get_user_result(
- user2, u'Test', u'User2', 'show-all',
- gidnumber=[u'1000'],
- memberof_group=[group1],
- manager=[renameduser1],
- objectclass=add_oc(objectclasses.user_base,
- u'ipantuserattrs'),
- preserved=False,
- omit=['mepmanagedentry'],
- ),
- value=user2,
- summary=None,
- ),
- ),
-
- dict(
- desc='Delete %r' % renameduser1,
- command=('user_del', [renameduser1], {}),
- expected=dict(
- result=dict(failed=[]),
- summary=u'Deleted user "%s"' % renameduser1,
- value=[renameduser1],
- ),
- ),
-
- dict(
- desc='Retrieve %r and check that manager is gone' % user2,
- command=(
- 'user_show', [user2], {'all': True}
- ),
- expected=dict(
- result=get_user_result(
- user2, u'Test', u'User2', 'show-all',
- gidnumber=[u'1000'],
- memberof_group=[group1],
- objectclass=add_oc(objectclasses.user_base,
- u'ipantuserattrs'),
- preserved=False,
- omit=['mepmanagedentry'],
- ),
- value=user2,
- summary=None,
- ),
- ),
-
- dict(
- desc='Reset default user group',
- command=(
- 'config_mod', [], dict(ipadefaultprimarygroup=u'ipausers'),
- ),
- expected=lambda x, output: x is None,
- ),
-
- dict(
- desc='Try to remove the original admin user "%s"' % admin1,
- command=('user_del', [admin1], {}),
- expected=errors.LastMemberError(key=admin1, label=u'group',
- container=admins_group),
- ),
-
- dict(
- desc='Try to disable the original admin user "%s"' % admin1,
- command=('user_disable', [admin1], {}),
- expected=errors.LastMemberError(key=admin1, label=u'group',
- container=admins_group),
- ),
-
-
- dict(
- desc='Create 2nd admin user "%s"' % admin2,
- command=(
- 'user_add', [admin2], dict(givenname=u'Second', sn=u'Admin')
- ),
- expected=dict(
- value=admin2,
- summary=u'Added user "%s"' % admin2,
- result=get_user_result(admin2, u'Second', u'Admin', 'add'),
- ),
- ),
-
- dict(
- desc='Add "%s" to the admins group "%s"' % (admin2, admins_group),
- command=('group_add_member', [admins_group], dict(user=admin2)),
- expected=dict(
- completed=1,
- failed=dict(
- member=dict(
- group=tuple(),
- user=tuple(),
- ),
- ),
- result={
- 'dn': get_group_dn(admins_group),
- 'member_user': [admin1, admin2],
- 'gidnumber': [fuzzy_digits],
- 'cn': [admins_group],
- 'description': [u'Account administrators group'],
- },
- ),
- ),
-
-
- dict(
- desc=('Retrieve admins group "%s" to verify membership is '
- '"%s","%s"' % (admins_group, admin1, admin2)),
- command=('group_show', [admins_group], {}),
- expected=dict(
- value=admins_group,
- result=dict(
- cn=[admins_group],
- gidnumber=[fuzzy_digits],
- description=[u'Account administrators group'],
- dn=get_group_dn(admins_group),
- member_user=[admin1, admin2],
- ),
- summary=None,
- ),
- ),
-
- dict(
- desc=('Disable 2nd admin user "%s", admins group "%s" should also '
- 'contain enabled "%s"' % (admin2, admins_group, admin1)),
- command=(
- 'user_disable', [admin2], {}
- ),
- expected=dict(
- result=True,
- value=admin2,
- summary=u'Disabled user account "%s"' % admin2,
- ),
- ),
-
- dict(
- desc='Assert 2nd admin user "%s" is disabled' % admin2,
- command=('user_find', [admin2], {}),
- expected=dict(
- result=[lambda d: d['nsaccountlock'] is True],
- summary=u'1 user matched',
- count=1,
- truncated=False,
- ),
- ),
-
- dict(
- desc='Try to disable the origin admin user "%s"' % admin1,
- command=('user_disable', [admin1], {}),
- expected=errors.LastMemberError(key=admin1, label=u'group',
- container=admins_group),
- ),
-
- dict(
- desc='Try to remove the original admin user "%s"' % admin1,
- command=('user_del', [admin1], {}),
- expected=errors.LastMemberError(key=admin1, label=u'group',
- container=admins_group),
- ),
-
- dict(
- desc='Delete 2nd admin "%s"' % admin2,
- command=('user_del', [admin2], {}),
- expected=dict(
- result=dict(failed=[]),
- summary=u'Deleted user "%s"' % admin2,
- value=[admin2],
- ),
- ),
-
- dict(
- desc=('Retrieve admins group "%s" to verify membership is "%s"'
- % (admins_group, admin1)),
- command=('group_show', [admins_group], {}),
- expected=dict(
- value=admins_group,
- result=dict(
- cn=[admins_group],
- gidnumber=[fuzzy_digits],
- description=[u'Account administrators group'],
- dn=get_group_dn(admins_group),
- member_user=[admin1],
- ),
- summary=None,
- ),
- ),
-
- dict(
- desc='Assert original admin user "%s" is enabled' % admin1,
- command=('user_find', [admin1], {}),
- expected=dict(
- result=[lambda d: d['nsaccountlock'] is False],
- summary=u'1 user matched',
- count=1,
- truncated=False,
- ),
- ),
-
- dict(
- desc='Try to remove the original admin user "%s"' % admin1,
- command=('user_del', [admin1], {}),
- expected=errors.LastMemberError(key=admin1, label=u'group',
- container=admins_group),
- ),
-
- dict(
- desc='Try to disable the original admin user "%s"' % admin1,
- command=('user_disable', [admin1], {}),
- expected=errors.LastMemberError(key=admin1, label=u'group',
- container=admins_group),
- ),
-
- dict(
- desc='Set default automember group for groups as ipausers',
- command=(
- 'automember_default_group_set', [], dict(
- type=u'group',
- automemberdefaultgroup=u'ipausers'
- )
- ),
- expected=dict(
- result=dict(
- cn=[u'Group'],
- automemberdefaultgroup=[DN(('cn', 'ipausers'),
- ('cn', 'groups'),
- ('cn', 'accounts'),
- api.env.basedn)],
- ),
- value=u'group',
- summary=u'Set default (fallback) group for automember "group"',
- ),
- ),
-
- dict(
- desc='Delete "%s"' % user2,
- command=('user_del', [user2], {}),
- expected=dict(
- result=dict(failed=[]),
- summary=u'Deleted user "%s"' % user2,
- value=[user2],
- ),
- ),
-
- dict(
- desc='Create %r' % user2,
- command=(
- 'user_add', [user2], dict(givenname=u'Test', sn=u'User2')
- ),
- expected=dict(
- value=user2,
- summary=u'Added user "tuser2"',
- result=get_user_result(user2, u'Test', u'User2', 'add'),
- ),
- ),
-
- dict(
- desc='Create "%s" with UID 999' % user1,
- command=(
- 'user_add', [user1], dict(
- givenname=u'Test', sn=u'User1', uidnumber=999)
- ),
- expected=dict(
- value=user1,
- summary=u'Added user "%s"' % user1,
- result=get_user_result(user1, u'Test', u'User1', 'add',
- uidnumber=[u'999'],
- gidnumber=[u'999']),
- ),
- extra_check = upg_check,
- ),
-
- dict(
- desc='Delete "%s"' % user1,
- command=('user_del', [user1], {}),
- expected=dict(
- result=dict(failed=[]),
- summary=u'Deleted user "%s"' % user1,
- value=[user1],
- ),
- ),
-
- dict(
- desc='Create "%s" with old DNA_MAGIC uid 999' % user1,
- command=(
- 'user_add', [user1], dict(
- givenname=u'Test', sn=u'User1', uidnumber=999,
- version=u'2.49')
- ),
- expected=dict(
- value=user1,
- summary=u'Added user "%s"' % user1,
- result=get_user_result(
- user1, u'Test', u'User1', 'add',
- uidnumber=[lambda v: int(v) != 999],
- gidnumber=[lambda v: int(v) != 999],
- ),
- ),
- extra_check = upg_check,
- ),
-
- dict(
- desc='Set ipauserauthtype for "%s"' % user1,
- command=('user_mod', [user1], dict(ipauserauthtype=u'password')),
- expected=dict(
- result=get_user_result(user1, u'Test', u'User1', 'mod',
- ipauserauthtype=[u'password'],
- ),
- value=user1,
- summary='Modified user "%s"' % user1,
- ),
- ),
-
- dict(
- desc='Retrieve "%s" to verify ipauserauthtype' % user1,
- command=('user_show', [user1], {}),
- expected=dict(
- result=get_user_result(user1, u'Test', u'User1', 'show',
- ipauserauthtype=[u'password'],
- ),
- value=user1,
- summary=None,
- ),
- ),
-
- dict(
- desc='Unset ipauserauthtype for "%s"' % user1,
- command=('user_mod', [user1], dict(ipauserauthtype=None)),
- expected=dict(
- result=get_user_result(user1, u'Test', u'User1', 'mod'),
- value=user1,
- summary='Modified user "%s"' % user1,
- ),
- ),
-
- dict(
- desc='Query status of "%s"' % user1,
- command=('user_status', [user1], {}),
- expected=dict(
- count=1,
- result=[
- dict(
- dn=get_user_dn(user1),
- krblastfailedauth=[u'N/A'],
- krblastsuccessfulauth=[u'N/A'],
- krbloginfailedcount=u'0',
- now=isodate_re.match,
- server=api.env.host,
- ),
- ],
- summary=u'Account disabled: False',
- truncated=False,
- ),
- ),
-
- dict(
- desc='Test an invalid preferredlanguage "%s"' % invalidlanguage1,
- command=('user_mod', [user1],
- dict(preferredlanguage=invalidlanguage1)),
- expected=errors.ValidationError(name='preferredlanguage',
- error=(u'must match RFC 2068 - 14.4, e.g., '
- '"da, en-gb;q=0.8, en;q=0.7"')),
- ),
-
- dict(
- desc='Test an invalid preferredlanguage "%s"' % invalidlanguage2,
- command=('user_mod', [user1],
- dict(preferredlanguage=invalidlanguage2)),
- expected=errors.ValidationError(name='preferredlanguage',
- error=(u'must match RFC 2068 - 14.4, e.g., '
- '"da, en-gb;q=0.8, en;q=0.7"')),
- ),
-
- dict(
- desc='Test an invalid preferredlanguage "%s"' % invalidlanguage3,
- command=('user_mod', [user1],
- dict(preferredlanguage=invalidlanguage3)),
- expected=errors.ValidationError(name='preferredlanguage',
- error=(u'must match RFC 2068 - 14.4, e.g., '
- '"da, en-gb;q=0.8, en;q=0.7"')),
- ),
-
- dict(
- desc='Test an invalid preferredlanguage "%s"' % invalidlanguage4,
- command=('user_mod', [user1],
- dict(preferredlanguage=invalidlanguage4)),
- expected=errors.ValidationError(name='preferredlanguage',
- error=(u'must match RFC 2068 - 14.4, e.g., '
- '"da, en-gb;q=0.8, en;q=0.7"')),
- ),
-
- dict(
- desc='Test an invalid preferredlanguage "%s"' % invalidlanguage5,
- command=('user_mod', [user1],
- dict(preferredlanguage=invalidlanguage5)),
- expected=errors.ValidationError(name='preferredlanguage',
- error=(u'must match RFC 2068 - 14.4, e.g., '
- '"da, en-gb;q=0.8, en;q=0.7"')),
- ),
-
- dict(
- desc='Set preferredlanguage "%s"' % validlanguage1,
- command=('user_mod', [user1],
- dict(preferredlanguage=validlanguage1)),
- expected=dict(
- result=get_user_result(user1, u'Test', u'User1', 'mod',
- preferredlanguage=[validlanguage1],
- ),
- value=user1,
- summary='Modified user "%s"' % user1,
- ),
- ),
-
- dict(
- desc='Set preferredlanguage "%s"' % validlanguage2,
- command=('user_mod', [user1],
- dict(preferredlanguage=validlanguage2)),
- expected=dict(
- result=get_user_result(user1, u'Test', u'User1', 'mod',
- preferredlanguage=[validlanguage2],
- ),
- value=user1,
- summary='Modified user "%s"' % user1,
- ),
- ),
-
- dict(
- desc='Set principal expiration "%s"' % principal_expiration_string,
- command=('user_mod', [user1],
- dict(krbprincipalexpiration=principal_expiration_string)),
- expected=dict(
- result=get_user_result(user1, u'Test', u'User1', 'mod',
- krbprincipalexpiration=[principal_expiration_date],
- ),
- value=user1,
- summary='Modified user "%s"' % user1,
- ),
- ),
-
- dict(
- desc='Set principal expiration "%s"' % invalid_expiration_string,
- command=('user_mod', [user1],
- dict(krbprincipalexpiration=invalid_expiration_string)),
- expected=errors.ConversionError(name='principal_expiration',
- error=(u'does not match any of accepted formats: '
- '%Y%m%d%H%M%SZ, %Y-%m-%dT%H:%M:%SZ, %Y-%m-%dT%H:%MZ, '
- '%Y-%m-%dZ, %Y-%m-%d %H:%M:%SZ, %Y-%m-%d %H:%MZ')
- ),
- ),
-
- ]
-
-
-@pytest.mark.tier1
-class test_denied_bind_with_expired_principal(XMLRPC_test):
-
- password = u'random'
-
- @classmethod
- def setup_class(cls):
- super(test_denied_bind_with_expired_principal, cls).setup_class()
-
- cls.connection = ldap.initialize('ldap://{host}'
- .format(host=api.env.host))
-
- @classmethod
- def teardown_class(cls):
- cls.failsafe_del(api.Object.user, user1)
- super(test_denied_bind_with_expired_principal, cls).teardown_class()
-
- def test_1_bind_as_test_user(self):
- self.failsafe_add(
- api.Object.user,
- user1,
- givenname=u'Test',
- sn=u'User1',
- userpassword=self.password,
- krbprincipalexpiration=principal_expiration_string
- )
-
- self.connection.simple_bind_s(str(get_user_dn(user1)), self.password)
-
- def test_2_bind_as_expired_test_user(self):
- api.Command['user_mod'](
- user1,
- krbprincipalexpiration=expired_expiration_string)
-
- raises(ldap.UNWILLING_TO_PERFORM,
- self.connection.simple_bind_s,
- str(get_user_dn(user1)), self.password)
-
- def test_3_bind_as_renewed_test_user(self):
- api.Command['user_mod'](
- user1,
- krbprincipalexpiration=principal_expiration_string)
-
- self.connection.simple_bind_s(str(get_user_dn(user1)), self.password)
diff --git a/ipatests/test_xmlrpc/tracker/user_plugin.py b/ipatests/test_xmlrpc/tracker/user_plugin.py
index 2e042c60e..c72e17424 100644
--- a/ipatests/test_xmlrpc/tracker/user_plugin.py
+++ b/ipatests/test_xmlrpc/tracker/user_plugin.py
@@ -29,28 +29,31 @@ class UserTracker(Tracker):
u'krbprincipalexpiration', u'usercertificate', u'dn', u'has_keytab',
u'has_password', u'street', u'postalcode', u'facsimiletelephonenumber',
u'carlicense', u'ipasshpubkey', u'sshpubkeyfp', u'nsaccountlock',
- u'preserved', u'memberof_group', u'l', u'mobile', u'krbextradata',
- u'krblastpwdchange', u'krbpasswordexpiration', u'pager', u'st'
- }
+ u'memberof_group', u'l', u'mobile', u'krbextradata',
+ u'krblastpwdchange', u'krbpasswordexpiration', u'pager', u'st',
+ u'manager', u'preserved'}
retrieve_all_keys = retrieve_keys | {
u'cn', u'ipauniqueid', u'objectclass', u'mepmanagedentry',
- u'displayname', u'gecos', u'initials', u'krbprincipalname', u'manager'}
+ u'displayname', u'gecos', u'initials', u'krbprincipalname',
+ u'preserved'}
retrieve_preserved_keys = retrieve_keys - {u'memberof_group'}
retrieve_preserved_all_keys = retrieve_all_keys - {u'memberof_group'}
create_keys = retrieve_all_keys | {
- u'randompassword', u'mepmanagedentry',
u'krbextradata', u'krbpasswordexpiration', u'krblastpwdchange',
- u'krbprincipalkey', u'randompassword', u'userpassword'
- }
+ u'krbprincipalkey', u'userpassword', u'randompassword'}
+ create_keys = create_keys - {u'nsaccountlock'}
+
update_keys = retrieve_keys - {u'dn'}
activate_keys = retrieve_all_keys - {u'has_keytab', u'has_password',
u'nsaccountlock', u'sshpubkeyfp'}
find_keys = retrieve_keys - {u'mepmanagedentry', u'memberof_group'}
- find_all_keys = retrieve_all_keys - {u'mepmanagedentry', u'memberof_group'}
+ find_all_keys = retrieve_all_keys
+
+ primary_keys = {u'uid', u'dn'}
def __init__(self, name, givenname, sn, **kwargs):
super(UserTracker, self).__init__(default_version=None)
@@ -108,11 +111,18 @@ class UserTracker(Tracker):
""" Make function that enables user using user-enable """
return self.make_command('user_enable', self.uid)
+ def make_disable_command(self):
+ """ Make function that disables user using user-disable """
+ return self.make_command('user_disable', self.uid)
+
def make_stage_command(self):
""" Make function that restores preserved user by moving it to
staged container """
return self.make_command('user_stage', self.uid)
+ def make_group_add_member_command(self, *args, **kwargs):
+ return self.make_command('group_add_member', *args, **kwargs)
+
def track_create(self):
""" Update expected state for user creation """
self.attrs = dict(
@@ -137,25 +147,71 @@ class UserTracker(Tracker):
has_password=False,
mepmanagedentry=[get_group_dn(self.uid)],
memberof_group=[u'ipausers'],
+ nsaccountlock=[u'false'],
)
for key in self.kwargs:
if key == u'krbprincipalname':
- self.attrs[key] = [u'%s@%s' % (
- (self.kwargs[key].split('@'))[0].lower(),
- (self.kwargs[key].split('@'))[1]
+ try:
+ self.attrs[key] = [u'%s@%s' % (
+ (self.kwargs[key].split('@'))[0].lower(),
+ (self.kwargs[key].split('@'))[1]
+ )]
+ except IndexError as ex:
+ # we can provide just principal part
+ self.attrs[key] = [u'%s@%s' % (
+ (self.kwargs[key].lower(),
+ self.api.env.realm)
)]
else:
- self.attrs[key] = [self.kwargs[key]]
+ if not type(self.kwargs[key]) is list:
+ self.attrs[key] = [self.kwargs[key]]
+ else:
+ self.attrs[key] = self.kwargs[key]
self.exists = True
- def check_create(self, result):
+ def update(self, updates, expected_updates=None):
+ """Helper function to update this user and check the result
+
+ Overriding Tracker method for setting self.attrs correctly;
+ * most attributes stores its value in list
+ * the rest can be overridden by expected_updates
+ * allow deleting parametrs if update value is None
+ """
+ if expected_updates is None:
+ expected_updates = {}
+
+ self.ensure_exists()
+ command = self.make_update_command(updates)
+ result = command()
+
+ for key, value in updates.items():
+ if value is None or value is '' or value is u'':
+ del self.attrs[key]
+ else:
+ if type(value) is list:
+ self.attrs[key] = value
+ else:
+ self.attrs[key] = [value]
+ for key, value in expected_updates.items():
+ if value is None or value is '' or value is u'':
+ del self.attrs[key]
+ else:
+ self.attrs[key] = value
+
+ self.check_update(
+ result,
+ extra_keys=set(updates.keys()) | set(expected_updates.keys())
+ )
+
+ def check_create(self, result, extra_keys=()):
""" Check 'user-add' command result """
+ expected = self.filter_attrs(self.create_keys | set(extra_keys))
assert_deepequal(dict(
value=self.uid,
summary=u'Added user "%s"' % self.uid,
- result=self.filter_attrs(self.create_keys),
+ result=self.filter_attrs(expected),
), result)
def check_delete(self, result):
@@ -166,9 +222,8 @@ class UserTracker(Tracker):
result=dict(failed=[]),
), result)
- def check_retrieve(self, result, all=False):
+ def check_retrieve(self, result, all=False, raw=False):
""" Check 'user-show' command result """
-
if u'preserved' in self.attrs and self.attrs[u'preserved']:
self.retrieve_all_keys = self.retrieve_preserved_all_keys
self.retrieve_keys = self.retrieve_preserved_keys
@@ -195,16 +250,26 @@ class UserTracker(Tracker):
result=expected,
), result)
- def check_find(self, result, all=False, raw=False):
+ def check_find(self, result, all=False, pkey_only=False, raw=False):
""" Check 'user-find' command result """
- self.attrs[u'nsaccountlock'] = True
- self.attrs[u'preserved'] = True
-
if all:
+ if u'preserved' not in self.attrs:
+ self.attrs.update(preserved=False)
expected = self.filter_attrs(self.find_all_keys)
+ elif pkey_only:
+ expected = self.filter_attrs(self.primary_keys)
else:
expected = self.filter_attrs(self.find_keys)
+ if all and self.attrs[u'preserved']:
+ del expected[u'mepmanagedentry']
+
+ if u'nsaccountlock' in expected:
+ if expected[u'nsaccountlock'] == [u'true']:
+ expected[u'nsaccountlock'] = True
+ elif expected[u'nsaccountlock'] == [u'false']:
+ expected[u'nsaccountlock'] = False
+
assert_deepequal(dict(
count=1,
truncated=False,
@@ -223,10 +288,32 @@ class UserTracker(Tracker):
def check_update(self, result, extra_keys=()):
""" Check 'user-mod' command result """
+ expected = self.filter_attrs(self.update_keys | set(extra_keys))
+ if expected[u'nsaccountlock'] == [u'true']:
+ expected[u'nsaccountlock'] = True
+ elif expected[u'nsaccountlock'] == [u'false']:
+ expected[u'nsaccountlock'] = False
+
assert_deepequal(dict(
value=self.uid,
summary=u'Modified user "%s"' % self.uid,
- result=self.filter_attrs(self.update_keys | set(extra_keys))
+ result=expected
+ ), result)
+
+ def check_enable(self, result):
+ """ Check result of enable user operation """
+ assert_deepequal(dict(
+ value=self.name,
+ summary=u'Enabled user account "%s"' % self.name,
+ result=True
+ ), result)
+
+ def check_disable(self, result):
+ """ Check result of disable user operation """
+ assert_deepequal(dict(
+ value=self.name,
+ summary=u'Disabled user account "%s"' % self.name,
+ result=True
), result)
def create_from_staged(self, stageduser):
@@ -287,6 +374,22 @@ class UserTracker(Tracker):
result=True
), result)
+ def enable(self):
+ """ Enable user account if it was disabled """
+ if (self.attrs['nsaccountlock'] is True or
+ self.attrs['nsaccountlock'] == [u'true']):
+ self.attrs.update(nsaccountlock=False)
+ result = self.make_enable_command()()
+ self.check_enable(result)
+
+ def disable(self):
+ """ Disable user account if it was enabled """
+ if (self.attrs['nsaccountlock'] is False or
+ self.attrs['nsaccountlock'] == [u'false']):
+ self.attrs.update(nsaccountlock=True)
+ result = self.make_disable_command()()
+ self.check_disable(result)
+
def track_delete(self, preserve=False):
"""Update expected state for host deletion"""
if preserve:
@@ -348,3 +451,27 @@ class UserTracker(Tracker):
request.addfinalizer(finish)
return self
+
+ def make_admin(self, admin_group=u'admins'):
+ """ Add user to the administrator's group """
+ result = self.run_command('group_show', admin_group)
+ admin_group_content = result[u'result'][u'member_user']
+ admin_group_expected = list(admin_group_content) + [self.name]
+
+ command = self.make_group_add_member_command(
+ admin_group, **dict(user=self.name)
+ )
+ result = command()
+ assert_deepequal(dict(
+ completed=1,
+ failed=dict(
+ member=dict(group=tuple(), user=tuple())
+ ),
+ result={
+ 'dn': get_group_dn(admin_group),
+ 'member_user': admin_group_expected,
+ 'gidnumber': [fuzzy_digits],
+ 'cn': [admin_group],
+ 'description': [u'Account administrators group'],
+ },
+ ), result)