mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
Enable group inactivation by using the Class of Service plugin.
This adds 2 new groups: activated and inactivated. If you, or a group you are a member of, is in inactivated then you are too. If you, or a group you are a member of, is in the activated group, then you are too. In a fight between activated and inactivated, activated wins. The DNs for doing this matching is case and white space sensitive. The goal is to never have to actually set nsAccountLock in a user directly but move them between these groups. We need to decide where in the CLI this will happen. Right it is split between ipa-deluser and ipa-usermod. To inactivate groups for now just add the group to inactivate or active.
This commit is contained in:
parent
56d67b86e1
commit
f42f1f44c8
@ -57,11 +57,14 @@ def main():
|
|||||||
ret = client.delete_user(args[1])
|
ret = client.delete_user(args[1])
|
||||||
msg = "deleted"
|
msg = "deleted"
|
||||||
else:
|
else:
|
||||||
ret = client.mark_user_deleted(args[1])
|
try:
|
||||||
if (ret == "Success"):
|
ret = client.mark_user_inactive(args[1])
|
||||||
|
except ipa.ipaerror.exception_for(ipa.ipaerror.LDAP_EMPTY_MODLIST):
|
||||||
|
print "User is already marked inactive"
|
||||||
|
return 0
|
||||||
|
except:
|
||||||
|
raise
|
||||||
print args[1] + " successfully %s" % msg
|
print args[1] + " successfully %s" % msg
|
||||||
else:
|
|
||||||
print args[1] + " " + ret
|
|
||||||
except xmlrpclib.Fault, fault:
|
except xmlrpclib.Fault, fault:
|
||||||
if fault.faultCode == errno.ECONNREFUSED:
|
if fault.faultCode == errno.ECONNREFUSED:
|
||||||
print "The IPA XML-RPC service is not responding."
|
print "The IPA XML-RPC service is not responding."
|
||||||
|
@ -32,7 +32,7 @@ import ldap
|
|||||||
import errno
|
import errno
|
||||||
|
|
||||||
def usage():
|
def usage():
|
||||||
print "ipa-usermod [-c|--gecos STRING] [-d|--directory STRING] [-f|--firstname STRING] [-l|--lastname STRING] [-s|--shell STRING] [--add attribute=value] [--del attribute] [--set attribute=value] user"
|
print "ipa-usermod [-a|--activate] [-c|--gecos STRING] [-d|--directory STRING] [-f|--firstname STRING] [-l|--lastname STRING] [-s|--shell STRING] [--add attribute=value] [--del attribute] [--set attribute=value] user"
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
|
|
||||||
def set_add_usage(which):
|
def set_add_usage(which):
|
||||||
@ -40,6 +40,8 @@ def set_add_usage(which):
|
|||||||
|
|
||||||
def parse_options():
|
def parse_options():
|
||||||
parser = OptionParser()
|
parser = OptionParser()
|
||||||
|
parser.add_option("-a", "--activate", dest="activate", action="store_true",
|
||||||
|
help="Activate the user")
|
||||||
parser.add_option("-c", "--gecos", dest="gecos",
|
parser.add_option("-c", "--gecos", dest="gecos",
|
||||||
help="Set the GECOS field")
|
help="Set the GECOS field")
|
||||||
parser.add_option("-d", "--directory", dest="directory",
|
parser.add_option("-d", "--directory", dest="directory",
|
||||||
@ -111,7 +113,7 @@ def main():
|
|||||||
return 1
|
return 1
|
||||||
|
|
||||||
# If any options are set we use just those. Otherwise ask for all of them.
|
# If any options are set we use just those. Otherwise ask for all of them.
|
||||||
if options.gn or options.sn or options.directory or options.gecos or options.mail or options.shell or options.addattr or options.delattr or options.setattr:
|
if options.gn or options.sn or options.directory or options.gecos or options.mail or options.shell or options.addattr or options.delattr or options.setattr or options.activate:
|
||||||
givenname = options.gn
|
givenname = options.gn
|
||||||
lastname = options.sn
|
lastname = options.sn
|
||||||
gecos = options.gecos
|
gecos = options.gecos
|
||||||
@ -236,8 +238,16 @@ def main():
|
|||||||
value = cvalue + [value]
|
value = cvalue + [value]
|
||||||
user.setValue(attr, value)
|
user.setValue(attr, value)
|
||||||
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
if options.activate:
|
||||||
|
try:
|
||||||
|
client.mark_user_active(user.getValues('uid'))
|
||||||
|
print "User activated successfully."
|
||||||
|
except ipa.ipaerror.exception_for(ipa.ipaerror.LDAP_EMPTY_MODLIST):
|
||||||
|
print "User is already marked active"
|
||||||
|
return 0
|
||||||
|
except:
|
||||||
|
raise
|
||||||
client.update_user(user)
|
client.update_user(user)
|
||||||
except xmlrpclib.Fault, fault:
|
except xmlrpclib.Fault, fault:
|
||||||
if fault.faultCode == errno.ECONNREFUSED:
|
if fault.faultCode == errno.ECONNREFUSED:
|
||||||
|
@ -177,10 +177,16 @@ class IPAClient:
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def mark_user_deleted(self,uid):
|
def mark_user_active(self,uid):
|
||||||
|
"""Set a user as active by uid."""
|
||||||
|
|
||||||
|
result = self.transport.mark_user_active(uid)
|
||||||
|
return result
|
||||||
|
|
||||||
|
def mark_user_inactive(self,uid):
|
||||||
"""Set a user as inactive by uid."""
|
"""Set a user as inactive by uid."""
|
||||||
|
|
||||||
result = self.transport.mark_user_deleted(uid)
|
result = self.transport.mark_user_inactive(uid)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
# Groups support
|
# Groups support
|
||||||
@ -335,6 +341,20 @@ class IPAClient:
|
|||||||
entries.append(user.User(e))
|
entries.append(user.User(e))
|
||||||
|
|
||||||
return entries
|
return entries
|
||||||
|
|
||||||
|
def mark_group_active(self,cn):
|
||||||
|
"""Set a group as active by cn."""
|
||||||
|
|
||||||
|
result = self.transport.mark_group_active(cn)
|
||||||
|
return result
|
||||||
|
|
||||||
|
def mark_group_inactive(self,cn):
|
||||||
|
"""Set a group as inactive by cn."""
|
||||||
|
|
||||||
|
result = self.transport.mark_group_inactive(cn)
|
||||||
|
return result
|
||||||
|
|
||||||
|
# Configuration
|
||||||
|
|
||||||
def get_ipa_config(self):
|
def get_ipa_config(self):
|
||||||
"""Get the IPA configuration"""
|
"""Get the IPA configuration"""
|
||||||
|
@ -318,12 +318,12 @@ class RPCClient:
|
|||||||
|
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def mark_user_deleted(self,uid):
|
def mark_user_active(self,uid):
|
||||||
"""Mark a user as deleted/inactive"""
|
"""Mark a user as active"""
|
||||||
server = self.setup_server()
|
server = self.setup_server()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
result = server.mark_user_deleted(uid)
|
result = server.mark_user_active(uid)
|
||||||
except xmlrpclib.Fault, fault:
|
except xmlrpclib.Fault, fault:
|
||||||
raise ipaerror.gen_exception(fault.faultCode, fault.faultString)
|
raise ipaerror.gen_exception(fault.faultCode, fault.faultString)
|
||||||
except socket.error, (value, msg):
|
except socket.error, (value, msg):
|
||||||
@ -331,6 +331,20 @@ class RPCClient:
|
|||||||
|
|
||||||
return ipautil.unwrap_binary_data(result)
|
return ipautil.unwrap_binary_data(result)
|
||||||
|
|
||||||
|
def mark_user_inactive(self,uid):
|
||||||
|
"""Mark a user as inactive"""
|
||||||
|
server = self.setup_server()
|
||||||
|
|
||||||
|
try:
|
||||||
|
result = server.mark_user_inactive(uid)
|
||||||
|
except xmlrpclib.Fault, fault:
|
||||||
|
raise ipaerror.gen_exception(fault.faultCode, fault.faultString)
|
||||||
|
except socket.error, (value, msg):
|
||||||
|
raise xmlrpclib.Fault(value, msg)
|
||||||
|
|
||||||
|
return ipautil.unwrap_binary_data(result)
|
||||||
|
|
||||||
|
|
||||||
# Group support
|
# Group support
|
||||||
|
|
||||||
def get_groups_by_member(self,member_dn,sattrs=None):
|
def get_groups_by_member(self,member_dn,sattrs=None):
|
||||||
@ -601,6 +615,34 @@ class RPCClient:
|
|||||||
|
|
||||||
return ipautil.unwrap_binary_data(result)
|
return ipautil.unwrap_binary_data(result)
|
||||||
|
|
||||||
|
def mark_group_active(self,cn):
|
||||||
|
"""Mark a group as active"""
|
||||||
|
server = self.setup_server()
|
||||||
|
|
||||||
|
try:
|
||||||
|
result = server.mark_group_active(cn)
|
||||||
|
except xmlrpclib.Fault, fault:
|
||||||
|
raise ipaerror.gen_exception(fault.faultCode, fault.faultString)
|
||||||
|
except socket.error, (value, msg):
|
||||||
|
raise xmlrpclib.Fault(value, msg)
|
||||||
|
|
||||||
|
return ipautil.unwrap_binary_data(result)
|
||||||
|
|
||||||
|
def mark_group_inactive(self,cn):
|
||||||
|
"""Mark a group as inactive"""
|
||||||
|
server = self.setup_server()
|
||||||
|
|
||||||
|
try:
|
||||||
|
result = server.mark_group_inactive(cn)
|
||||||
|
except xmlrpclib.Fault, fault:
|
||||||
|
raise ipaerror.gen_exception(fault.faultCode, fault.faultString)
|
||||||
|
except socket.error, (value, msg):
|
||||||
|
raise xmlrpclib.Fault(value, msg)
|
||||||
|
|
||||||
|
return ipautil.unwrap_binary_data(result)
|
||||||
|
|
||||||
|
# Configuration support
|
||||||
|
|
||||||
def get_ipa_config(self):
|
def get_ipa_config(self):
|
||||||
"""Get the IPA configuration"""
|
"""Get the IPA configuration"""
|
||||||
server = self.setup_server()
|
server = self.setup_server()
|
||||||
|
@ -9,6 +9,10 @@ class GroupFields():
|
|||||||
|
|
||||||
editprotected_hidden = widgets.HiddenField(name="editprotected")
|
editprotected_hidden = widgets.HiddenField(name="editprotected")
|
||||||
|
|
||||||
|
nsAccountLock = widgets.SingleSelectField(name="nsAccountLock",
|
||||||
|
label="Group Status",
|
||||||
|
options = [("", "active"), ("true", "inactive")])
|
||||||
|
|
||||||
group_orig = widgets.HiddenField(name="group_orig")
|
group_orig = widgets.HiddenField(name="group_orig")
|
||||||
member_data = widgets.HiddenField(name="member_data")
|
member_data = widgets.HiddenField(name="member_data")
|
||||||
dn_to_info_json = widgets.HiddenField(name="dn_to_info_json")
|
dn_to_info_json = widgets.HiddenField(name="dn_to_info_json")
|
||||||
|
@ -22,7 +22,7 @@ log = logging.getLogger(__name__)
|
|||||||
group_new_form = ipagui.forms.group.GroupNewForm()
|
group_new_form = ipagui.forms.group.GroupNewForm()
|
||||||
group_edit_form = ipagui.forms.group.GroupEditForm()
|
group_edit_form = ipagui.forms.group.GroupEditForm()
|
||||||
|
|
||||||
group_fields = ['*']
|
group_fields = ['*', 'nsAccountLock']
|
||||||
|
|
||||||
class GroupController(IPAController):
|
class GroupController(IPAController):
|
||||||
|
|
||||||
@ -75,6 +75,9 @@ class GroupController(IPAController):
|
|||||||
new_group.setValue('description', kw.get('description'))
|
new_group.setValue('description', kw.get('description'))
|
||||||
|
|
||||||
rv = client.add_group(new_group)
|
rv = client.add_group(new_group)
|
||||||
|
|
||||||
|
if kw.get('nsAccountLock'):
|
||||||
|
client.mark_group_inactive(kw.get('cn'))
|
||||||
except ipaerror.exception_for(ipaerror.LDAP_DUPLICATE):
|
except ipaerror.exception_for(ipaerror.LDAP_DUPLICATE):
|
||||||
turbogears.flash("Group with name '%s' already exists" %
|
turbogears.flash("Group with name '%s' already exists" %
|
||||||
kw.get('cn'))
|
kw.get('cn'))
|
||||||
@ -224,6 +227,12 @@ class GroupController(IPAController):
|
|||||||
turbogears.flash("Edit group cancelled")
|
turbogears.flash("Edit group cancelled")
|
||||||
raise turbogears.redirect('/group/show', cn=cn[0])
|
raise turbogears.redirect('/group/show', cn=cn[0])
|
||||||
|
|
||||||
|
if kw.get('editprotected') == '':
|
||||||
|
# if editprotected set these don't get sent in kw
|
||||||
|
orig_group_dict = loads(b64decode(kw.get('group_orig')))
|
||||||
|
kw['cn'] = orig_group_dict['cn']
|
||||||
|
kw['gidnumber'] = orig_group_dict['gidnumber']
|
||||||
|
|
||||||
# Decode the member data, in case we need to round trip
|
# Decode the member data, in case we need to round trip
|
||||||
member_dicts = loads(b64decode(kw.get('member_data')))
|
member_dicts = loads(b64decode(kw.get('member_data')))
|
||||||
|
|
||||||
@ -251,6 +260,17 @@ class GroupController(IPAController):
|
|||||||
if new_group.gidnumber != new_gid:
|
if new_group.gidnumber != new_gid:
|
||||||
group_modified = True
|
group_modified = True
|
||||||
new_group.setValue('gidnumber', new_gid)
|
new_group.setValue('gidnumber', new_gid)
|
||||||
|
else:
|
||||||
|
new_group.setValue('gidnumber', orig_group_dict.get('gidnumber'))
|
||||||
|
new_group.setValue('cn', orig_group_dict.get('cn'))
|
||||||
|
if new_group.cn != kw.get('cn'):
|
||||||
|
group_modified = True
|
||||||
|
new_group.setValue('cn', kw['cn'])
|
||||||
|
|
||||||
|
if group_modified:
|
||||||
|
rv = client.update_group(new_group)
|
||||||
|
#
|
||||||
|
# If the group update succeeds, but below operations fail, we
|
||||||
if new_group.cn != kw.get('cn'):
|
if new_group.cn != kw.get('cn'):
|
||||||
group_modified = True
|
group_modified = True
|
||||||
new_group.setValue('cn', kw['cn'])
|
new_group.setValue('cn', kw['cn'])
|
||||||
@ -268,6 +288,17 @@ class GroupController(IPAController):
|
|||||||
return dict(form=group_edit_form, group=kw, members=member_dicts,
|
return dict(form=group_edit_form, group=kw, members=member_dicts,
|
||||||
tg_template='ipagui.templates.groupedit')
|
tg_template='ipagui.templates.groupedit')
|
||||||
|
|
||||||
|
if kw.get('nsAccountLock') == '':
|
||||||
|
kw['nsAccountLock'] = "false"
|
||||||
|
|
||||||
|
modify_no_update = False
|
||||||
|
if kw.get('nsAccountLock') == "false" and new_group.getValues('nsaccountlock') == "true":
|
||||||
|
client.mark_group_active(kw.get('cn'))
|
||||||
|
modify_no_update = True
|
||||||
|
elif kw.get('nsAccountLock') == "true" and new_group.nsaccountlock != "true":
|
||||||
|
client.mark_group_inactive(kw.get('cn'))
|
||||||
|
modify_no_update = True
|
||||||
|
|
||||||
#
|
#
|
||||||
# Add members
|
# Add members
|
||||||
#
|
#
|
||||||
@ -326,7 +357,7 @@ class GroupController(IPAController):
|
|||||||
cn0 = kw['cn'][0]
|
cn0 = kw['cn'][0]
|
||||||
else:
|
else:
|
||||||
cn0 = kw['cn']
|
cn0 = kw['cn']
|
||||||
if group_modified == True:
|
if group_modified == True or modify_no_update == True:
|
||||||
turbogears.flash("%s updated!" % cn0)
|
turbogears.flash("%s updated!" % cn0)
|
||||||
else:
|
else:
|
||||||
turbogears.flash("No modifications requested.")
|
turbogears.flash("No modifications requested.")
|
||||||
|
@ -197,14 +197,14 @@ class UserController(IPAController):
|
|||||||
new_user.setValue('carlicense', kw.get('carlicense'))
|
new_user.setValue('carlicense', kw.get('carlicense'))
|
||||||
new_user.setValue('labeleduri', kw.get('labeleduri'))
|
new_user.setValue('labeleduri', kw.get('labeleduri'))
|
||||||
|
|
||||||
if kw.get('nsAccountLock'):
|
|
||||||
new_user.setValue('nsAccountLock', 'true')
|
|
||||||
|
|
||||||
for custom_field in user_new_form.custom_fields:
|
for custom_field in user_new_form.custom_fields:
|
||||||
new_user.setValue(custom_field.name,
|
new_user.setValue(custom_field.name,
|
||||||
kw.get(custom_field.name, ''))
|
kw.get(custom_field.name, ''))
|
||||||
|
|
||||||
rv = client.add_user(new_user)
|
rv = client.add_user(new_user)
|
||||||
|
|
||||||
|
if kw.get('nsAccountLock'):
|
||||||
|
client.mark_user_inactive(kw.get('uid'))
|
||||||
except ipaerror.exception_for(ipaerror.LDAP_DUPLICATE):
|
except ipaerror.exception_for(ipaerror.LDAP_DUPLICATE):
|
||||||
turbogears.flash("User with login '%s' already exists" %
|
turbogears.flash("User with login '%s' already exists" %
|
||||||
kw.get('uid'))
|
kw.get('uid'))
|
||||||
@ -482,12 +482,6 @@ class UserController(IPAController):
|
|||||||
new_user.setValue('carlicense', kw.get('carlicense'))
|
new_user.setValue('carlicense', kw.get('carlicense'))
|
||||||
new_user.setValue('labeleduri', kw.get('labeleduri'))
|
new_user.setValue('labeleduri', kw.get('labeleduri'))
|
||||||
|
|
||||||
|
|
||||||
if kw.get('nsAccountLock'):
|
|
||||||
new_user.setValue('nsAccountLock', 'true')
|
|
||||||
else:
|
|
||||||
new_user.setValue('nsAccountLock', None)
|
|
||||||
|
|
||||||
if kw.get('editprotected') == 'true':
|
if kw.get('editprotected') == 'true':
|
||||||
if kw.get('userpassword'):
|
if kw.get('userpassword'):
|
||||||
password_change = True
|
password_change = True
|
||||||
@ -572,6 +566,20 @@ class UserController(IPAController):
|
|||||||
user_groups=user_groups_dicts,
|
user_groups=user_groups_dicts,
|
||||||
tg_template='ipagui.templates.useredit')
|
tg_template='ipagui.templates.useredit')
|
||||||
|
|
||||||
|
if kw.get('nsAccountLock') == '':
|
||||||
|
kw['nsAccountLock'] = "false"
|
||||||
|
|
||||||
|
try:
|
||||||
|
if kw.get('nsAccountLock') == "false" and new_user.getValues('nsaccountlock') == "true":
|
||||||
|
client.mark_user_active(kw.get('uid'))
|
||||||
|
elif kw.get('nsAccountLock') == "true" and new_user.nsaccountlock != "true":
|
||||||
|
client.mark_user_inactive(kw.get('uid'))
|
||||||
|
except ipaerror.IPAError, e:
|
||||||
|
turbogears.flash("User status change failed: " + str(e) + "<br/>" + e.detail[0]['desc'])
|
||||||
|
return dict(form=user_edit_form, user=kw,
|
||||||
|
user_groups=user_groups_dicts,
|
||||||
|
tg_template='ipagui.templates.useredit')
|
||||||
|
|
||||||
turbogears.flash("%s updated!" % kw['uid'])
|
turbogears.flash("%s updated!" % kw['uid'])
|
||||||
raise turbogears.redirect('/user/show', uid=kw['uid'])
|
raise turbogears.redirect('/user/show', uid=kw['uid'])
|
||||||
|
|
||||||
|
@ -112,6 +112,16 @@ from ipagui.helpers import ipahelper
|
|||||||
</script>
|
</script>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
<label class="fieldlabel" for="${group_fields.nsAccountLock.field_id}" py:content="group_fields.nsAccountLock.label" />:
|
||||||
|
</th>
|
||||||
|
<td>
|
||||||
|
<span py:replace="group_fields.nsAccountLock.display(value_for(group_fields.nsAccountLock))" />
|
||||||
|
<span py:if="tg.errors.get('nsAccountLock')" class="fielderror"
|
||||||
|
py:content="tg.errors.get('nsAccountLock')" />
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<div>
|
<div>
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div py:if='(groups != None) and (len(groups) > 0)'>
|
<div py:if='(groups != None) and (len(groups) > 0)'>
|
||||||
<h2>${len(groups)} results returned:</h2>
|
<h2>${len(groups)} results returned:</h2>
|
||||||
<table id="resultstable" class="details sortable resizable">
|
<table id="resultstable" class="details sortable resizable" cellspacing="0">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>
|
<th>
|
||||||
@ -32,7 +32,15 @@
|
|||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
<tr py:for="group in groups">
|
<tr py:for="group in groups" py:if="group.nsAccountLock != 'true'">
|
||||||
|
<td>
|
||||||
|
<a href="${tg.url('/group/show',cn=group.cn)}">${group.cn}</a>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
${group.description}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr id="inactive" py:for="group in groups" py:if="group.nsAccountLock == 'true'">
|
||||||
<td>
|
<td>
|
||||||
<a href="${tg.url('/group/show',cn=group.cn)}">${group.cn}</a>
|
<a href="${tg.url('/group/show',cn=group.cn)}">${group.cn}</a>
|
||||||
</td>
|
</td>
|
||||||
|
@ -11,6 +11,7 @@ cn = group.get('cn')
|
|||||||
if isinstance(cn, list):
|
if isinstance(cn, list):
|
||||||
cn = cn[0]
|
cn = cn[0]
|
||||||
edit_url = tg.url('/group/edit', cn=cn)
|
edit_url = tg.url('/group/edit', cn=cn)
|
||||||
|
from ipagui.helpers import userhelper
|
||||||
?>
|
?>
|
||||||
<div id="details">
|
<div id="details">
|
||||||
<h1>View Group</h1>
|
<h1>View Group</h1>
|
||||||
@ -42,6 +43,12 @@ edit_url = tg.url('/group/edit', cn=cn)
|
|||||||
</th>
|
</th>
|
||||||
<td>${group.get("gidnumber")}</td>
|
<td>${group.get("gidnumber")}</td>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th>
|
||||||
|
<label class="fieldlabel" py:content="fields.nsAccountLock.label" />:
|
||||||
|
</th>
|
||||||
|
<td>${userhelper.account_status_display(group.get("nsAccountLock"))}</td>
|
||||||
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
<h2 class="formsection">Group Members</h2>
|
<h2 class="formsection">Group Members</h2>
|
||||||
|
@ -787,7 +787,7 @@ from ipagui.helpers import ipahelper
|
|||||||
group_dn = group.get('dn')
|
group_dn = group.get('dn')
|
||||||
group_dn_esc = ipahelper.javascript_string_escape(group_dn)
|
group_dn_esc = ipahelper.javascript_string_escape(group_dn)
|
||||||
|
|
||||||
group_name = group.get('cn')[0]
|
group_name = group.get('cn')
|
||||||
group_descr = "[group]"
|
group_descr = "[group]"
|
||||||
group_type = "group"
|
group_type = "group"
|
||||||
|
|
||||||
|
@ -116,3 +116,42 @@ ipaDefaultLoginShell: /bin/sh
|
|||||||
ipaDefaultPrimaryGroup: ipausers
|
ipaDefaultPrimaryGroup: ipausers
|
||||||
ipaMaxUsernameLength: 8
|
ipaMaxUsernameLength: 8
|
||||||
ipaPwdExpAdvNotify: 4
|
ipaPwdExpAdvNotify: 4
|
||||||
|
|
||||||
|
dn: cn=account inactivation,cn=accounts,$SUFFIX
|
||||||
|
description: Lock accounts based on group membership
|
||||||
|
objectClass: top
|
||||||
|
objectClass: ldapsubentry
|
||||||
|
objectClass: cosSuperDefinition
|
||||||
|
objectClass: cosClassicDefinition
|
||||||
|
cosTemplateDn: cn=cosTemplates,cn=accounts,$SUFFIX
|
||||||
|
cosAttribute: nsAccountLock operational
|
||||||
|
cosAttribute: pager
|
||||||
|
cosSpecifier: memberOf
|
||||||
|
cn: Account Inactivation
|
||||||
|
|
||||||
|
dn: cn=cosTemplates,cn=accounts,$SUFFIX
|
||||||
|
objectclass: top
|
||||||
|
objectclass: nsContainer
|
||||||
|
cn: cosTemplates
|
||||||
|
|
||||||
|
dn: cn="cn=inactivated,cn=account inactivation,cn=accounts,$SUFFIX", cn=cosTemplates,cn=accounts,$SUFFIX
|
||||||
|
objectClass: top
|
||||||
|
objectClass: cosTemplate
|
||||||
|
objectClass: extensibleobject
|
||||||
|
nsAccountLock: true
|
||||||
|
cosPriority: 1
|
||||||
|
|
||||||
|
dn: cn=inactivated,cn=account inactivation,cn=accounts,$SUFFIX
|
||||||
|
objectclass: top
|
||||||
|
objectclass: groupofuniquenames
|
||||||
|
|
||||||
|
dn: cn="cn=activated,cn=account inactivation,cn=accounts,$SUFFIX", cn=cosTemplates,cn=accounts,$SUFFIX
|
||||||
|
objectClass: top
|
||||||
|
objectClass: cosTemplate
|
||||||
|
objectClass: extensibleobject
|
||||||
|
nsAccountLock: false
|
||||||
|
cosPriority: 0
|
||||||
|
|
||||||
|
dn: cn=Activated,cn=Account Inactivation,cn=accounts,$SUFFIX
|
||||||
|
objectclass: top
|
||||||
|
objectclass: groupofuniquenames
|
||||||
|
@ -119,7 +119,7 @@ class DsInstance(service.Service):
|
|||||||
def __setup_sub_dict(self):
|
def __setup_sub_dict(self):
|
||||||
server_root = find_server_root()
|
server_root = find_server_root()
|
||||||
self.sub_dict = dict(FQHN=self.host_name, SERVERID=self.serverid,
|
self.sub_dict = dict(FQHN=self.host_name, SERVERID=self.serverid,
|
||||||
PASSWORD=self.dm_password, SUFFIX=self.suffix,
|
PASSWORD=self.dm_password, SUFFIX=self.suffix.lower(),
|
||||||
REALM=self.realm_name, USER=self.ds_user,
|
REALM=self.realm_name, USER=self.ds_user,
|
||||||
SERVER_ROOT=server_root)
|
SERVER_ROOT=server_root)
|
||||||
|
|
||||||
|
@ -36,6 +36,7 @@ import string
|
|||||||
from types import *
|
from types import *
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
import logging
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from threading import Lock
|
from threading import Lock
|
||||||
@ -49,6 +50,11 @@ ACIContainer = "cn=accounts"
|
|||||||
DefaultUserContainer = "cn=users,cn=accounts"
|
DefaultUserContainer = "cn=users,cn=accounts"
|
||||||
DefaultGroupContainer = "cn=groups,cn=accounts"
|
DefaultGroupContainer = "cn=groups,cn=accounts"
|
||||||
|
|
||||||
|
# FIXME: need to check the ipadebug option in ipa.conf
|
||||||
|
logging.basicConfig(level=logging.DEBUG,
|
||||||
|
format='%(asctime)s %(levelname)s %(message)s',
|
||||||
|
stream=sys.stderr)
|
||||||
|
|
||||||
#
|
#
|
||||||
# Apache runs in multi-process mode so each process will have its own
|
# Apache runs in multi-process mode so each process will have its own
|
||||||
# connection. This could theoretically drive the total number of connections
|
# connection. This could theoretically drive the total number of connections
|
||||||
@ -674,26 +680,80 @@ class IPAServer:
|
|||||||
else:
|
else:
|
||||||
raise
|
raise
|
||||||
|
|
||||||
def mark_user_deleted (self, uid, opts=None):
|
def mark_entry_active (self, dn, opts=None):
|
||||||
"""Mark a user as inactive in LDAP. We aren't actually deleting
|
"""Mark an entry as active in LDAP."""
|
||||||
users here, just making it so they can't log in, etc."""
|
|
||||||
user = self.get_user_by_uid(uid, ['dn', 'uid', 'nsAccountlock'], opts)
|
|
||||||
|
|
||||||
# Are we doing an add or replace operation?
|
# This can be tricky. The entry itself can be marked inactive
|
||||||
if user.has_key('nsaccountlock'):
|
# by being in the inactivated group. It can also be inactivated by
|
||||||
if user['nsaccountlock'] == "true":
|
# being the member of an inactive group.
|
||||||
return "already marked as deleted"
|
#
|
||||||
has_key = True
|
# First we try to remove the entry from the inactivated group. Then
|
||||||
else:
|
# if it is still inactive we have to add it to the activated group
|
||||||
has_key = False
|
# which will override the group membership.
|
||||||
|
|
||||||
|
logging.debug("IPA: activating entry %s" % dn)
|
||||||
|
|
||||||
|
res = ""
|
||||||
|
# First, check the entry status
|
||||||
|
entry = self.get_entry_by_dn(dn, ['dn', 'nsAccountlock'], opts)
|
||||||
|
|
||||||
|
if entry.get('nsaccountlock', 'false') == "false":
|
||||||
|
logging.debug("IPA: already active")
|
||||||
|
raise ipaerror.gen_exception(ipaerror.LDAP_EMPTY_MODLIST)
|
||||||
|
|
||||||
|
group = self.get_entry_by_cn("inactivated", None, opts)
|
||||||
|
res = self.remove_member_from_group(entry.get('dn'), group.get('dn'), opts)
|
||||||
|
|
||||||
|
# Now they aren't a member of inactivated directly, what is the status
|
||||||
|
# now?
|
||||||
|
entry = self.get_entry_by_dn(dn, ['dn', 'nsAccountlock'], opts)
|
||||||
|
|
||||||
|
if entry.get('nsaccountlock', 'false') == "false":
|
||||||
|
# great, we're done
|
||||||
|
logging.debug("IPA: removing from inactivated did it.")
|
||||||
|
return res
|
||||||
|
|
||||||
|
# So still inactive, add them to activated
|
||||||
|
group = self.get_entry_by_cn("activated", None, opts)
|
||||||
|
res = self.add_member_to_group(dn, group.get('dn'), opts)
|
||||||
|
logging.debug("IPA: added to activated.")
|
||||||
|
|
||||||
conn = self.getConnection(opts)
|
|
||||||
try:
|
|
||||||
res = conn.inactivateEntry(user['dn'], has_key)
|
|
||||||
finally:
|
|
||||||
self.releaseConnection(conn)
|
|
||||||
return res
|
return res
|
||||||
|
|
||||||
|
def mark_entry_inactive (self, dn, opts=None):
|
||||||
|
"""Mark an entry as inactive in LDAP."""
|
||||||
|
|
||||||
|
logging.debug("IPA: inactivating entry %s" % dn)
|
||||||
|
|
||||||
|
entry = self.get_entry_by_dn(dn, ['dn', 'nsAccountlock', 'memberOf'], opts)
|
||||||
|
|
||||||
|
if entry.get('nsaccountlock', 'false') == "true":
|
||||||
|
logging.debug("IPA: already marked as inactive")
|
||||||
|
raise ipaerror.gen_exception(ipaerror.LDAP_EMPTY_MODLIST)
|
||||||
|
|
||||||
|
# First see if they are in the activated group as this will override
|
||||||
|
# the our inactivation.
|
||||||
|
group = self.get_entry_by_cn("activated", None, opts)
|
||||||
|
self.remove_member_from_group(dn, group.get('dn'), opts)
|
||||||
|
|
||||||
|
# Now add them to inactivated
|
||||||
|
group = self.get_entry_by_cn("inactivated", None, opts)
|
||||||
|
res = self.add_member_to_group(dn, group.get('dn'), opts)
|
||||||
|
|
||||||
|
return res
|
||||||
|
|
||||||
|
def mark_user_active(self, uid, opts=None):
|
||||||
|
"""Mark a user as active"""
|
||||||
|
|
||||||
|
user = self.get_user_by_uid(uid, ['dn', 'uid'], opts)
|
||||||
|
return self.mark_entry_active(user.get('dn'))
|
||||||
|
|
||||||
|
def mark_user_inactive(self, uid, opts=None):
|
||||||
|
"""Mark a user as inactive"""
|
||||||
|
|
||||||
|
user = self.get_user_by_uid(uid, ['dn', 'uid'], opts)
|
||||||
|
return self.mark_entry_inactive(user.get('dn'))
|
||||||
|
|
||||||
def delete_user (self, uid, opts=None):
|
def delete_user (self, uid, opts=None):
|
||||||
"""Delete a user. Not to be confused with inactivate_user. This
|
"""Delete a user. Not to be confused with inactivate_user. This
|
||||||
makes the entry go away completely.
|
makes the entry go away completely.
|
||||||
@ -1215,6 +1275,18 @@ class IPAServer:
|
|||||||
|
|
||||||
return entries
|
return entries
|
||||||
|
|
||||||
|
def mark_group_active(self, cn, opts=None):
|
||||||
|
"""Mark a group as active"""
|
||||||
|
|
||||||
|
group = self.get_entry_by_cn(cn, ['dn', 'cn'], opts)
|
||||||
|
return self.mark_entry_active(group.get('dn'))
|
||||||
|
|
||||||
|
def mark_group_inactive(self, cn, opts=None):
|
||||||
|
"""Mark a group as inactive"""
|
||||||
|
|
||||||
|
group = self.get_entry_by_cn(cn, ['dn', 'uid'], opts)
|
||||||
|
return self.mark_entry_inactive(group.get('dn'))
|
||||||
|
|
||||||
# Configuration support
|
# Configuration support
|
||||||
def get_ipa_config(self, opts=None):
|
def get_ipa_config(self, opts=None):
|
||||||
"""Retrieve the IPA configuration"""
|
"""Retrieve the IPA configuration"""
|
||||||
|
@ -332,7 +332,10 @@ def handler(req, profiling=False):
|
|||||||
h.register_function(f.find_users)
|
h.register_function(f.find_users)
|
||||||
h.register_function(f.update_user)
|
h.register_function(f.update_user)
|
||||||
h.register_function(f.delete_user)
|
h.register_function(f.delete_user)
|
||||||
h.register_function(f.mark_user_deleted)
|
h.register_function(f.mark_user_active)
|
||||||
|
h.register_function(f.mark_user_inactive)
|
||||||
|
h.register_function(f.mark_group_active)
|
||||||
|
h.register_function(f.mark_group_inactive)
|
||||||
h.register_function(f.modifyPassword)
|
h.register_function(f.modifyPassword)
|
||||||
h.register_function(f.get_groups_by_member)
|
h.register_function(f.get_groups_by_member)
|
||||||
h.register_function(f.add_group)
|
h.register_function(f.add_group)
|
||||||
|
Loading…
Reference in New Issue
Block a user