diff options
-rw-r--r-- | ipa_server/plugins/b_ldap.py | 18 | ||||
-rw-r--r-- | ipa_server/servercore.py | 46 | ||||
-rw-r--r-- | ipalib/cli.py | 12 | ||||
-rw-r--r-- | ipalib/plugins/f_delegation.py | 3 | ||||
-rw-r--r-- | ipalib/plugins/f_group.py | 151 | ||||
-rw-r--r-- | ipalib/plugins/f_user.py | 40 |
6 files changed, 235 insertions, 35 deletions
diff --git a/ipa_server/plugins/b_ldap.py b/ipa_server/plugins/b_ldap.py index e63865bbf..a07e8e710 100644 --- a/ipa_server/plugins/b_ldap.py +++ b/ipa_server/plugins/b_ldap.py @@ -146,6 +146,24 @@ class ldap(CrudBackend): def modify_password(self, dn, **kw): return servercore.modify_password(dn, kw.get('oldpass'), kw.get('newpass')) + def add_member_to_group(self, memberdn, groupdn): + """ + Add a new member to a group. + + :param memberdn: the DN of the member to add + :param groupdn: the DN of the group to add a member to + """ + return servercore.add_member_to_group(memberdn, groupdn) + + def remove_member_from_group(self, memberdn, groupdn): + """ + Remove a new member from a group. + + :param memberdn: the DN of the member to remove + :param groupdn: the DN of the group to remove a member from + """ + return servercore.remove_member_from_group(memberdn, groupdn) + # The CRUD operations def create(self, **kw): diff --git a/ipa_server/servercore.py b/ipa_server/servercore.py index 1f41d410f..e69967a90 100644 --- a/ipa_server/servercore.py +++ b/ipa_server/servercore.py @@ -389,7 +389,9 @@ def mark_entry_inactive (dn): return res def add_member_to_group(member_dn, group_dn): - """Add a member to an existing group.""" + """ + Add a member to an existing group. + """ # logging.info("IPA: add_member_to_group '%s' to '%s'" % (member_dn, group_dn)) if member_dn.lower() == group_dn.lower(): # You can't add a group to itself @@ -404,12 +406,12 @@ def add_member_to_group(member_dn, group_dn): if not member_entry: raise errors.NotFound - if group.get('member') is not None: - if isinstance(group.get('member'),basestring): - group['member'] = [group['member']] - group['member'].append(member_dn) - else: - group['member'] = member_dn + # Add the new member to the group member attribute + members = group.get('member', []) + if isinstance(members, basestring): + members = [members] + members.append(member_dn) + group['member'] = members try: return update_entry(group) @@ -430,20 +432,24 @@ def remove_member_from_group(member_dn, group_dn=None): """ # logging.info("IPA: remove_member_from_group '%s' from '%s'" % (member_dn, group_dn)) - if group.get('member') is not None: - if isinstance(group.get('member'),basestring): - group['member'] = [group['member']] - for i in range(len(group['member'])): - group['member'][i] = ipaldap.IPAdmin.normalizeDN(group['member'][i]) - try: - group['member'].remove(member_dn) - except ValueError: - # member is not in the group - # FIXME: raise more specific error? - raise errors.NotGroupMember - else: - # Nothing to do if the group has no members + members = group.get('member', False) + if not members: + raise errors.NotGroupMember + + if isinstance(members,basestring): + members = [members] + for i in range(len(members)): + members[i] = ipaldap.IPAdmin.normalizeDN(members[i]) + try: + members.remove(member_dn) + except ValueError: + # member is not in the group + # FIXME: raise more specific error? raise errors.NotGroupMember + except Exception, e: + raise e + + group['member'] = members try: return update_entry(group) diff --git a/ipalib/cli.py b/ipalib/cli.py index 365eea20a..ab7e36204 100644 --- a/ipalib/cli.py +++ b/ipalib/cli.py @@ -277,7 +277,10 @@ class CLI(object): def run_cmd(self, cmd, argv): kw = self.parse(cmd, argv) - self.run_interactive(cmd, kw) + try: + self.run_interactive(cmd, kw) + except KeyboardInterrupt: + return def run_interactive(self, cmd, kw): for param in cmd.params(): @@ -325,11 +328,16 @@ class CLI(object): usage=self.get_usage(cmd), ) for option in cmd.options(): - parser.add_option('--%s' % to_cli(option.cli_name), + o = optparse.make_option('--%s' % to_cli(option.cli_name), dest=option.name, metavar=option.type.name.upper(), help=option.doc, ) + if isinstance(option.type, ipa_types.Bool): + o.action = 'store_true' + o.default = option.default + o.type = None + parser.add_option(o) return parser def parse_globals(self, argv=sys.argv[1:]): diff --git a/ipalib/plugins/f_delegation.py b/ipalib/plugins/f_delegation.py index 1fb2b4f9e..fbf8cfbff 100644 --- a/ipalib/plugins/f_delegation.py +++ b/ipalib/plugins/f_delegation.py @@ -26,9 +26,6 @@ from ipalib import crud from ipalib.frontend import Param from ipalib import api from ipalib import errors -from ipa_server import servercore -from ipa_server import ipaldap -import ldap class delegation(frontend.Object): """ diff --git a/ipalib/plugins/f_group.py b/ipalib/plugins/f_group.py index e83c870e9..b5f80f93c 100644 --- a/ipalib/plugins/f_group.py +++ b/ipalib/plugins/f_group.py @@ -25,7 +25,8 @@ from ipalib import frontend from ipalib import crud from ipalib.frontend import Param from ipalib import api -from ipa_server import ipautil +from ipalib import errors +from ipalib import ipa_types class group(frontend.Object): @@ -33,7 +34,14 @@ class group(frontend.Object): Group object. """ takes_params = ( - 'description', + Param('description', + doc='A description of this group', + ), + Param('gidnumber?', + cli_name='gid', + type=ipa_types.Int(), + doc='The gid to use for this group. If not included one is automatically set.', + ), Param('cn', cli_name='name', primary_key=True, @@ -210,4 +218,143 @@ class group_show(crud.Get): # FIXME: should kw contain the list of attributes to display? return ldap.retrieve(dn) + def output_for_cli(self, group): + if not group: + return + + for a in group.keys(): + print "%s: %s" % (a, group[a]) + api.register(group_show) + + +class group_add_member(frontend.Command): + 'Add a member to a group.' + takes_args = ( + Param('group', primary_key=True), + ) + takes_options = ( + Param('users?', doc='comma-separated list of users to add'), + Param('groups?', doc='comma-separated list of groups to add'), + ) + def execute(self, cn, **kw): + """ + Execute the group-add-member operation. + + Returns the updated group entry + + :param cn: The group name to add new members to. + :param kw: groups is a comma-separated list of groups to add + :parem kw: users is a comma-separated list of users to add + """ + ldap = self.api.Backend.ldap + dn = ldap.find_entry_dn("cn", cn) + add_failed = [] + to_add = [] + completed = 0 + + members = kw.get('groups', '').split(',') + for m in members: + if not m: continue + try: + member_dn = ldap.find_entry_dn("cn", m) + to_add.append(member_dn) + except errors.NotFound: + add_failed.append(m) + continue + + members = kw.get('users', '').split(',') + for m in members: + if not m: continue + try: + member_dn = ldap.find_entry_dn("uid", m) + to_add.append(member_dn) + except errors.NotFound: + add_failed.append(m) + continue + + for member_dn in to_add: + try: + ldap.add_member_to_group(member_dn, dn) + completed+=1 + except: + add_failed.append(member_dn) + + return add_failed + + def output_for_cli(self, add_failed): + """ + Output result of this command to command line interface. + """ + if add_failed: + print "These entries failed to add to the group:" + for a in add_failed: + print "\t'%s'" % a + + +api.register(group_add_member) + + +class group_remove_member(frontend.Command): + 'Remove a member from a group.' + takes_args = ( + Param('group', primary_key=True), + ) + takes_options = ( + Param('users?', doc='comma-separated list of users to remove'), + Param('groups?', doc='comma-separated list of groups to remove'), + ) + def execute(self, cn, **kw): + """ + Execute the group-remove-member operation. + + Returns the members that could not be added + + :param cn: The group name to add new members to. + :param kw: groups is a comma-separated list of groups to remove + :parem kw: users is a comma-separated list of users to remove + """ + ldap = self.api.Backend.ldap + dn = ldap.find_entry_dn("cn", cn) + to_remove = [] + remove_failed = [] + completed = 0 + + members = kw.get('groups', '').split(',') + for m in members: + if not m: continue + try: + member_dn = ldap.find_entry_dn("cn", m) + to_remove.append(member_dn) + except errors.NotFound: + remove_failed.append(m) + continue + + members = kw.get('users', '').split(',') + for m in members: + try: + member_dn = ldap.find_entry_dn("uid", m,) + to_remove.append(member_dn) + except errors.NotFound: + remove_failed.append(m) + continue + + for member_dn in to_remove: + try: + ldap.remove_member_from_group(member_dn, dn) + completed+=1 + except: + remove_failed.append(member_dn) + + return remove_failed + + def output_for_cli(self, remove_failed): + """ + Output result of this command to command line interface. + """ + if remove_failed: + print "These entries failed to be removed from the group:" + for a in remove_failed: + print "\t'%s'" % a + +api.register(group_remove_member) diff --git a/ipalib/plugins/f_user.py b/ipalib/plugins/f_user.py index 6aebddfa4..70952b29f 100644 --- a/ipalib/plugins/f_user.py +++ b/ipalib/plugins/f_user.py @@ -55,11 +55,11 @@ class user(frontend.Object): takes_params = ( Param('givenname', cli_name='first', - doc='User first name', + doc='User\'s first name', ), Param('sn', cli_name='last', - doc='User last name', + doc='User\'s last name', ), Param('uid', cli_name='user', @@ -68,22 +68,40 @@ class user(frontend.Object): normalize=lambda value: value.lower(), ), Param('gecos?', - doc='GECOS field', + doc='Set the GECOS field', default_from=lambda uid: uid, ), Param('homedirectory?', cli_name='home', - doc='Path of user home directory', + doc='Set the User\'s home directory', default_from=lambda uid: '/home/%s' % uid, ), Param('loginshell?', cli_name='shell', default=u'/bin/sh', - doc='Login shell', + doc='Set User\'s Login shell', ), Param('krbprincipalname?', cli_name='principal', - default_from=lambda uid: '%s@EXAMPLE.COM' % uid, + doc='Set User\'s Kerberos Principal name', + default_from=lambda uid: '%s@%s' % (uid, api.env.realm), ), + Param('mailaddress?', + cli_name='mail', + doc='Set User\'s e-mail address', + ), + Param('userpassword?', + cli_name='password', + doc='Set User\'s password', + ), + Param('groups?', + doc='Add account to one or more groups (comma-separated)', + ), + Param('uidnumber?', + cli_name='uid', + type=ipa_types.Int(), + doc='The uid to use for this user. If not included one is automatically set.', + ), + ) api.register(user) @@ -265,6 +283,9 @@ api.register(user_find) class user_show(crud.Get): 'Examine an existing user.' + takes_options = ( + Param('all?', type=ipa_types.Bool(), doc='Display all user attributes'), + ) def execute(self, uid, **kw): """ Execute the user-show operation. @@ -275,12 +296,15 @@ class user_show(crud.Get): Returns the entry :param uid: The login name of the user to retrieve. - :param kw: Not used. + :param kw: "all" set to True = return all attributes """ ldap = self.api.Backend.ldap dn = ldap.find_entry_dn("uid", uid) # FIXME: should kw contain the list of attributes to display? - return ldap.retrieve(dn) + if kw.get('all', False): + return ldap.retrieve(dn) + else: + return ldap.retrieve(dn, ['uid','givenname','sn','homeDirectory','loginshell']) def output_for_cli(self, user): if user: for a in user.keys(): |