diff options
author | Jan Cholasta <jcholast@redhat.com> | 2016-04-28 10:30:05 +0200 |
---|---|---|
committer | Jan Cholasta <jcholast@redhat.com> | 2016-06-03 09:00:34 +0200 |
commit | 6e44557b601f769d23ee74555a72e8b5cc62c0c9 (patch) | |
tree | eedd3e054b0709341b9f58c190ea54f999f7d13a /ipaserver/plugins/hostgroup.py | |
parent | ec841e5d7ab29d08de294b3fa863a631cd50e30a (diff) | |
download | freeipa-6e44557b601f769d23ee74555a72e8b5cc62c0c9.tar.gz freeipa-6e44557b601f769d23ee74555a72e8b5cc62c0c9.tar.xz freeipa-6e44557b601f769d23ee74555a72e8b5cc62c0c9.zip |
ipalib: move server-side plugins to ipaserver
Move the remaining plugin code from ipalib.plugins to ipaserver.plugins.
Remove the now unused ipalib.plugins package.
https://fedorahosted.org/freeipa/ticket/4739
Reviewed-By: David Kupka <dkupka@redhat.com>
Diffstat (limited to 'ipaserver/plugins/hostgroup.py')
-rw-r--r-- | ipaserver/plugins/hostgroup.py | 316 |
1 files changed, 316 insertions, 0 deletions
diff --git a/ipaserver/plugins/hostgroup.py b/ipaserver/plugins/hostgroup.py new file mode 100644 index 000000000..dab354d9c --- /dev/null +++ b/ipaserver/plugins/hostgroup.py @@ -0,0 +1,316 @@ +# Authors: +# Rob Crittenden <rcritten@redhat.com> +# Pavel Zuna <pzuna@redhat.com> +# +# Copyright (C) 2009 Red Hat +# see file 'COPYING' for use and warranty information +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import six + +from ipalib.plugable import Registry +from .baseldap import (LDAPObject, LDAPCreate, LDAPRetrieve, + LDAPDelete, LDAPUpdate, LDAPSearch, + LDAPAddMember, LDAPRemoveMember, + entry_from_entry, wait_for_value) +from ipalib import Str, api, _, ngettext, errors +from .netgroup import NETGROUP_PATTERN, NETGROUP_PATTERN_ERRMSG +from ipapython.dn import DN + +if six.PY3: + unicode = str + +__doc__ = _(""" +Groups of hosts. + +Manage groups of hosts. This is useful for applying access control to a +number of hosts by using Host-based Access Control. + +EXAMPLES: + + Add a new host group: + ipa hostgroup-add --desc="Baltimore hosts" baltimore + + Add another new host group: + ipa hostgroup-add --desc="Maryland hosts" maryland + + Add members to the hostgroup (using Bash brace expansion): + ipa hostgroup-add-member --hosts={box1,box2,box3} baltimore + + Add a hostgroup as a member of another hostgroup: + ipa hostgroup-add-member --hostgroups=baltimore maryland + + Remove a host from the hostgroup: + ipa hostgroup-remove-member --hosts=box2 baltimore + + Display a host group: + ipa hostgroup-show baltimore + + Delete a hostgroup: + ipa hostgroup-del baltimore +""") + + +def get_complete_hostgroup_member_list(hostgroup): + result = api.Command['hostgroup_show'](hostgroup)['result'] + direct = list(result.get('member_host', [])) + indirect = list(result.get('memberindirect_host', [])) + return direct + indirect + + +register = Registry() + +PROTECTED_HOSTGROUPS = (u'ipaservers',) + + +@register() +class hostgroup(LDAPObject): + """ + Hostgroup object. + """ + container_dn = api.env.container_hostgroup + object_name = _('host group') + object_name_plural = _('host groups') + object_class = ['ipaobject', 'ipahostgroup'] + permission_filter_objectclasses = ['ipahostgroup'] + search_attributes = ['cn', 'description', 'member', 'memberof'] + default_attributes = ['cn', 'description', 'member', 'memberof', + 'memberindirect', 'memberofindirect', + ] + uuid_attribute = 'ipauniqueid' + attribute_members = { + 'member': ['host', 'hostgroup'], + 'memberof': ['hostgroup', 'netgroup', 'hbacrule', 'sudorule'], + 'memberindirect': ['host', 'hostgroup'], + 'memberofindirect': ['hostgroup', 'hbacrule', 'sudorule'], + } + managed_permissions = { + 'System: Read Hostgroups': { + 'replaces_global_anonymous_aci': True, + 'ipapermbindruletype': 'all', + 'ipapermright': {'read', 'search', 'compare'}, + 'ipapermdefaultattr': { + 'businesscategory', 'cn', 'description', 'ipauniqueid', 'o', + 'objectclass', 'ou', 'owner', 'seealso', + }, + }, + 'System: Read Hostgroup Membership': { + 'replaces_global_anonymous_aci': True, + 'ipapermbindruletype': 'all', + 'ipapermright': {'read', 'search', 'compare'}, + 'ipapermdefaultattr': { + 'member', 'memberof', 'memberuser', 'memberhost', + }, + }, + 'System: Add Hostgroups': { + 'ipapermright': {'add'}, + 'replaces': [ + '(target = "ldap:///cn=*,cn=hostgroups,cn=accounts,$SUFFIX")(version 3.0;acl "permission:Add Hostgroups";allow (add) groupdn = "ldap:///cn=Add Hostgroups,cn=permissions,cn=pbac,$SUFFIX";)', + ], + 'default_privileges': {'Host Group Administrators'}, + }, + 'System: Modify Hostgroup Membership': { + 'ipapermright': {'write'}, + 'ipapermtargetfilter': [ + '(objectclass=ipahostgroup)', + '(!(cn=ipaservers))', + ], + 'ipapermdefaultattr': {'member'}, + 'replaces': [ + '(targetattr = "member")(target = "ldap:///cn=*,cn=hostgroups,cn=accounts,$SUFFIX")(version 3.0;acl "permission:Modify Hostgroup membership";allow (write) groupdn = "ldap:///cn=Modify Hostgroup membership,cn=permissions,cn=pbac,$SUFFIX";)', + ], + 'default_privileges': {'Host Group Administrators'}, + }, + 'System: Modify Hostgroups': { + 'ipapermright': {'write'}, + 'ipapermdefaultattr': {'cn', 'description'}, + 'replaces': [ + '(targetattr = "cn || description")(target = "ldap:///cn=*,cn=hostgroups,cn=accounts,$SUFFIX")(version 3.0; acl "permission:Modify Hostgroups";allow (write) groupdn = "ldap:///cn=Modify Hostgroups,cn=permissions,cn=pbac,$SUFFIX";)', + ], + 'default_privileges': {'Host Group Administrators'}, + }, + 'System: Remove Hostgroups': { + 'ipapermright': {'delete'}, + 'replaces': [ + '(target = "ldap:///cn=*,cn=hostgroups,cn=accounts,$SUFFIX")(version 3.0;acl "permission:Remove Hostgroups";allow (delete) groupdn = "ldap:///cn=Remove Hostgroups,cn=permissions,cn=pbac,$SUFFIX";)', + ], + 'default_privileges': {'Host Group Administrators'}, + }, + } + + label = _('Host Groups') + label_singular = _('Host Group') + + takes_params = ( + Str('cn', + pattern=NETGROUP_PATTERN, + pattern_errmsg=NETGROUP_PATTERN_ERRMSG, + cli_name='hostgroup_name', + label=_('Host-group'), + doc=_('Name of host-group'), + primary_key=True, + normalizer=lambda value: value.lower(), + ), + Str('description?', + cli_name='desc', + label=_('Description'), + doc=_('A description of this host-group'), + ), + ) + + def suppress_netgroup_memberof(self, ldap, dn, entry_attrs): + """ + We don't want to show managed netgroups so remove them from the + memberOf list. + """ + hgdn = DN(dn) + for member in list(entry_attrs.get('memberof', [])): + ngdn = DN(member) + if ngdn['cn'] != hgdn['cn']: + continue + + filter = ldap.make_filter({'objectclass': 'mepmanagedentry'}) + try: + ldap.get_entries(ngdn, ldap.SCOPE_BASE, filter, ['']) + except errors.NotFound: + pass + else: + entry_attrs['memberof'].remove(member) + + +@register() +class hostgroup_add(LDAPCreate): + __doc__ = _('Add a new hostgroup.') + + msg_summary = _('Added hostgroup "%(value)s"') + + def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + assert isinstance(dn, DN) + try: + # check duplicity with hostgroups first to provide proper error + api.Object['hostgroup'].get_dn_if_exists(keys[-1]) + self.obj.handle_duplicate_entry(*keys) + except errors.NotFound: + pass + + try: + # when enabled, a managed netgroup is created for every hostgroup + # make sure that the netgroup can be created + api.Object['netgroup'].get_dn_if_exists(keys[-1]) + raise errors.DuplicateEntry(message=unicode(_( + u'netgroup with name "%s" already exists. ' + u'Hostgroups and netgroups share a common namespace' + ) % keys[-1])) + except errors.NotFound: + pass + + return dn + + def post_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) + # Always wait for the associated netgroup to be created so we can + # be sure to ignore it in memberOf + newentry = wait_for_value(ldap, dn, 'objectclass', 'mepOriginEntry') + entry_from_entry(entry_attrs, newentry) + self.obj.suppress_netgroup_memberof(ldap, dn, entry_attrs) + + return dn + + +@register() +class hostgroup_del(LDAPDelete): + __doc__ = _('Delete a hostgroup.') + + msg_summary = _('Deleted hostgroup "%(value)s"') + + def pre_callback(self, ldap, dn, *keys, **options): + if keys[0] in PROTECTED_HOSTGROUPS: + raise errors.ProtectedEntryError(label=_(u'hostgroup'), + key=keys[0], + reason=_(u'privileged hostgroup')) + + return dn + + +@register() +class hostgroup_mod(LDAPUpdate): + __doc__ = _('Modify a hostgroup.') + + msg_summary = _('Modified hostgroup "%(value)s"') + + def post_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) + self.obj.suppress_netgroup_memberof(ldap, dn, entry_attrs) + return dn + + +@register() +class hostgroup_find(LDAPSearch): + __doc__ = _('Search for hostgroups.') + + member_attributes = ['member', 'memberof'] + msg_summary = ngettext( + '%(count)d hostgroup matched', '%(count)d hostgroups matched', 0 + ) + + def post_callback(self, ldap, entries, truncated, *args, **options): + if options.get('pkey_only', False): + return truncated + for entry in entries: + self.obj.suppress_netgroup_memberof(ldap, entry.dn, entry) + return truncated + + +@register() +class hostgroup_show(LDAPRetrieve): + __doc__ = _('Display information about a hostgroup.') + + def post_callback(self, ldap, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) + self.obj.suppress_netgroup_memberof(ldap, dn, entry_attrs) + return dn + + +@register() +class hostgroup_add_member(LDAPAddMember): + __doc__ = _('Add members to a hostgroup.') + + def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) + self.obj.suppress_netgroup_memberof(ldap, dn, entry_attrs) + return (completed, dn) + + +@register() +class hostgroup_remove_member(LDAPRemoveMember): + __doc__ = _('Remove members from a hostgroup.') + + def pre_callback(self, ldap, dn, found, not_found, *keys, **options): + if keys[0] in PROTECTED_HOSTGROUPS and 'host' in options: + result = api.Command.hostgroup_show(keys[0]) + hosts_left = set(result['result'].get('member_host', [])) + hosts_deleted = set(options['host']) + if hosts_left.issubset(hosts_deleted): + raise errors.LastMemberError(key=sorted(hosts_deleted)[0], + label=_(u'hostgroup'), + container=keys[0]) + + return dn + + def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options): + assert isinstance(dn, DN) + self.obj.suppress_netgroup_memberof(ldap, dn, entry_attrs) + return (completed, dn) + |