Skip to content

Commit

Permalink
Add automember rebuild command
Browse files Browse the repository at this point in the history
Add a new command to IPA CLI: ipa automember-rebuild

The command integrates the automember rebuild membership task functionality
into IPA CLI. It makes it possible to rebuild automember membership for
groups/hostgroups.

Design: http://www.freeipa.org/page/V3/Automember_rebuild_membership
https://fedorahosted.org/freeipa/ticket/3752
  • Loading branch information
infraredgirl authored and mkosek committed Nov 15, 2013
1 parent eaaf7ed commit d97386d
Show file tree
Hide file tree
Showing 3 changed files with 143 additions and 11 deletions.
9 changes: 9 additions & 0 deletions API.txt
Expand Up @@ -199,6 +199,15 @@ option: Str('version?', exclude='webui')
output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
output: Output('value', <type 'unicode'>, None)
command: automember_rebuild
args: 0,4,3
option: Str('hosts*')
option: StrEnum('type', cli_name='type', multivalue=False, required=False, values=(u'group', u'hostgroup'))
option: Str('users*')
option: Str('version?', exclude='webui')
output: Output('result', <type 'bool'>, None)
output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
output: Output('value', <type 'unicode'>, None)
command: automember_remove_condition
args: 1,8,5
arg: Str('cn', cli_name='automember_rule')
Expand Down
2 changes: 1 addition & 1 deletion VERSION
Expand Up @@ -89,4 +89,4 @@ IPA_DATA_VERSION=20100614120000
# #
########################################################
IPA_API_VERSION_MAJOR=2
IPA_API_VERSION_MINOR=66
IPA_API_VERSION_MINOR=67
143 changes: 133 additions & 10 deletions ipalib/plugins/automember.py
Expand Up @@ -16,13 +16,11 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.

from ipalib import api, errors
from ipalib import Str, StrEnum
import uuid
import ldap as _ldap
from ipalib import api, errors, Str, StrEnum, _, ngettext
from ipalib.plugins.baseldap import *
from ipalib import _, ngettext
from ipalib.request import context
import ldap as _ldap
from ipapython.dn import DN

__doc__ = _("""
Expand All @@ -43,6 +41,8 @@
match any rule. In case of user entries this group will be a fallback group
because all users are by default members of group specified in IPA config.
The automember-rebuild command can be used to retroactively run automember rules
against existing entries, thus rebuilding their membership.
EXAMPLES:
Expand Down Expand Up @@ -107,6 +107,18 @@
Delete an automember rule:
ipa automember-del --type=hostgroup webservers
ipa automember-del --type=group devel
Rebuild membership for all users:
ipa automember-rebuild --type=group
Rebuild membership for all hosts:
ipa automember-rebuild --type=hostgroup
Rebuild membership for specified users:
ipa automember-rebuild --users=tuser1 --users=tuser2
Rebuild membership for specified hosts:
ipa automember-rebuild --hosts=web1.example.com --hosts=web2.example.com
""")

# Options used by Condition Add and Remove.
Expand Down Expand Up @@ -184,14 +196,17 @@ class automember(LDAPObject):
),
)

def dn_exists(self, grouptype, groupname, *keys):
def dn_exists(self, otype, oname):
ldap = self.api.Backend.ldap2
dn = self.api.Object[grouptype].get_dn(groupname)
dn = self.api.Object[otype].get_dn(oname)
try:
(gdn, entry_attrs) = ldap.get_entry(dn, [])
entry = ldap.get_entry(dn, [])
except errors.NotFound:
raise errors.NotFound(reason=_(u'Group: %s not found!') % groupname)
return gdn
raise errors.NotFound(
reason=_(u'%(otype)s "%(oname)s" not found') %
dict(otype=otype, oname=oname)
)
return entry.dn

def get_dn(self, *keys, **options):
if self.parent_object:
Expand Down Expand Up @@ -587,3 +602,111 @@ def execute(self, *keys, **options):
return result

api.register(automember_default_group_show)


class automember_rebuild(Command):
__doc__ = _('Rebuild auto membership.')
# TODO: Add a --dry-run option:
# https://fedorahosted.org/freeipa/ticket/3936
takes_options = (
group_type[0].clone(
required=False,
label=_('Rebuild membership for all members of a grouping')
),
Str(
'users*',
label=_('Users'),
doc=_('Rebuild membership for specified users'),
),
Str(
'hosts*',
label=_('Hosts'),
doc=_('Rebuild membership for specified hosts'),
),
)
has_output = output.standard_value
msg_summary = _('Automember rebuild membership task completed')

def validate(self, **kw):
"""
Validation rules:
- at least one of 'type', 'users', 'hosts' is required
- 'users' and 'hosts' cannot be combined together
- if 'users' and 'type' are specified, 'type' must be 'group'
- if 'hosts' and 'type' are specified, 'type' must be 'hostgroup'
"""
super(automember_rebuild, self).validate(**kw)
users, hosts, gtype = kw.get('users'), kw.get('hosts'), kw.get('type')

if not (gtype or users or hosts):
raise errors.MutuallyExclusiveError(
reason=_('at least one of options: type, users, hosts must be '
'specified')
)

if users and hosts:
raise errors.MutuallyExclusiveError(
reason=_("users and hosts cannot both be set")
)
if gtype == 'group' and hosts:
raise errors.MutuallyExclusiveError(
reason=_("hosts cannot be set when type is 'group'")
)
if gtype == 'hostgroup' and users:
raise errors.MutuallyExclusiveError(
reason=_("users cannot be set when type is 'hostgroup'")
)

def execute(self, *keys, **options):
ldap = self.api.Backend.ldap2
cn = str(uuid.uuid4())

gtype = options.get('type')
if not gtype:
gtype = 'group' if options.get('users') else 'hostgroup'

types = {
'group': (
'user',
'users',
DN(api.env.container_user, api.env.basedn)
),
'hostgroup': (
'host',
'hosts',
DN(api.env.container_host, api.env.basedn)
),
}

obj_name, opt_name, basedn = types[gtype]
obj = self.api.Object[obj_name]

names = options.get(opt_name)
if names:
for name in names:
obj.get_dn_if_exists(name)
search_filter = ldap.make_filter_from_attr(
obj.primary_key.name,
names,
rules=ldap.MATCH_ANY
)
else:
search_filter = '(%s=*)' % obj.primary_key.name

entry = ldap.make_entry(
DN(
('cn', cn),
('cn', 'automember rebuild membership'),
('cn', 'tasks'),
('cn', 'config'),
),
objectclass=['top', 'extensibleObject'],
cn=[cn],
basedn=[basedn],
filter=[search_filter],
scope=['sub']
)
ldap.add_entry(entry)
return dict(result=True, value=u'')

api.register(automember_rebuild)

0 comments on commit d97386d

Please sign in to comment.