summaryrefslogtreecommitdiffstats
path: root/ipalib
diff options
context:
space:
mode:
authorJohn Dennis <jdennis@redhat.com>2012-08-16 20:28:44 -0400
committerMartin Kosek <mkosek@redhat.com>2012-09-03 18:11:49 +0200
commit4f03aed5e603389bbb149464eee597180470ad70 (patch)
treed6a4caf1214ac130bc68d0aac5bd038e2db1f0a6 /ipalib
parent557b2605503738f25d9c89e8b51d1832b24d5636 (diff)
downloadfreeipa-4f03aed5e603389bbb149464eee597180470ad70.tar.gz
freeipa-4f03aed5e603389bbb149464eee597180470ad70.tar.xz
freeipa-4f03aed5e603389bbb149464eee597180470ad70.zip
prevent last admin from being disabled
We prevent the last member of the admin group from being deleted. The same check needs to be performed when disabling a user. * Moved the code in del_user to the common subroutine check_protected_member() and call it from both user_del and user_disable. Note, unlike user_del user_disable does not have a 'pre' callback therefore the check function is called in user_disable's execute routine. * Make check_protected_member() aware of disabled members. It's not sufficient to check which members of the protected group are present, one must only consider those members which are enabled. * Add tests to test_user_plugin.py. - verify you cannot delete nor disable the last member of the admin group - verify when the admin group contains disabled users in addition to enabled users only the enabled users are considered when determining if the last admin is about to be disabled or deleted. * Replace duplicated hardcoded values in the tests with variables or subroutines, this makes the individual tests a bit more succinct and easier to copy/modify. * Update error msg to reflect either deleting or disabling is an error. https://fedorahosted.org/freeipa/ticket/2979
Diffstat (limited to 'ipalib')
-rw-r--r--ipalib/errors.py6
-rw-r--r--ipalib/plugins/user.py27
2 files changed, 24 insertions, 9 deletions
diff --git a/ipalib/errors.py b/ipalib/errors.py
index c25560b8e..1bff2acbb 100644
--- a/ipalib/errors.py
+++ b/ipalib/errors.py
@@ -1627,18 +1627,18 @@ class DependentEntry(ExecutionError):
class LastMemberError(ExecutionError):
"""
- **4308** Raised when an entry being deleted is last member of a protected group
+ **4308** Raised when an entry being deleted or disabled is last member of a protected group
For example:
>>> raise LastMemberError(key=u'admin', label=u'group', container=u'admins')
Traceback (most recent call last):
...
- LastMemberError: admin cannot be deleted because it is the last member of group admins
+ LastMemberError: admin cannot be deleted or disabled because it is the last member of group admins
"""
errno = 4308
- format = _('%(key)s cannot be deleted because it is the last member of %(label)s %(container)s')
+ format = _('%(key)s cannot be deleted or disabled because it is the last member of %(label)s %(container)s')
class ProtectedEntryError(ExecutionError):
diff --git a/ipalib/plugins/user.py b/ipalib/plugins/user.py
index 6a7f53fde..c024e8555 100644
--- a/ipalib/plugins/user.py
+++ b/ipalib/plugins/user.py
@@ -166,6 +166,24 @@ def normalize_principal(principal):
return unicode('%s@%s' % (user, realm))
+def check_protected_member(user, protected_group_name=u'admins'):
+ '''
+ Ensure the last enabled member of a protected group cannot be deleted or
+ disabled by raising LastMemberError.
+ '''
+
+ # Get all users in the protected group
+ result = api.Command.user_find(in_group=protected_group_name)
+
+ # Build list of users in the protected group who are enabled
+ result = result['result']
+ enabled_users = [entry['uid'][0] for entry in result if not entry['nsaccountlock']]
+
+ # If the user is the last enabled user raise LastMemberError exception
+ if enabled_users == [user]:
+ raise errors.LastMemberError(key=user, label=_(u'group'),
+ container=protected_group_name)
+
class user(LDAPObject):
"""
User object.
@@ -550,11 +568,7 @@ class user_del(LDAPDelete):
def pre_callback(self, ldap, dn, *keys, **options):
assert isinstance(dn, DN)
- protected_group_name = u'admins'
- result = api.Command.group_show(protected_group_name)
- if result['result'].get('member_user', []) == [keys[-1]]:
- raise errors.LastMemberError(key=keys[-1], label=_(u'group'),
- container=protected_group_name)
+ check_protected_member(keys[-1])
return dn
api.register(user_del)
@@ -686,8 +700,9 @@ class user_disable(LDAPQuery):
def execute(self, *keys, **options):
ldap = self.obj.backend
- dn = self.obj.get_dn(*keys, **options)
+ check_protected_member(keys[-1])
+ dn = self.obj.get_dn(*keys, **options)
ldap.deactivate_entry(dn)
return dict(