summaryrefslogtreecommitdiffstats
path: root/ipaserver/plugins/hostgroup.py
diff options
context:
space:
mode:
authorJan Cholasta <jcholast@redhat.com>2016-04-28 10:30:05 +0200
committerJan Cholasta <jcholast@redhat.com>2016-06-03 09:00:34 +0200
commit6e44557b601f769d23ee74555a72e8b5cc62c0c9 (patch)
treeeedd3e054b0709341b9f58c190ea54f999f7d13a /ipaserver/plugins/hostgroup.py
parentec841e5d7ab29d08de294b3fa863a631cd50e30a (diff)
downloadfreeipa-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.py316
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)
+