e3ffab
From 1d57cf654de99077d7ece28f9210d1a2d5dee5b7 Mon Sep 17 00:00:00 2001
e3ffab
From: Petr Vobornik <pvoborni@redhat.com>
e3ffab
Date: Mon, 1 Dec 2014 10:15:21 +0100
e3ffab
Subject: [PATCH] add --hosts and --hostgroup options to allow/retrieve keytab
e3ffab
 methods
e3ffab
e3ffab
`--hosts` and `--hostgroup` options added to:
e3ffab
* service-allow-create-keytab
e3ffab
* service-allow-retrieve-keytab
e3ffab
* service-disallow-create-keytab
e3ffab
* service-disallow-retrieve-keytab
e3ffab
* host-allow-create-keytab
e3ffab
* host-allow-retrieve-keytab
e3ffab
* host-disallow-create-keytab
e3ffab
* host-disallow-retrieve-keytab
e3ffab
e3ffab
in order to allow hosts to retrieve keytab of their services or related hosts as described on http://www.freeipa.org/page/V4/Keytab_Retrieval design page
e3ffab
e3ffab
https://fedorahosted.org/freeipa/ticket/4777
e3ffab
e3ffab
Reviewed-By: Jan Cholasta <jcholast@redhat.com>
e3ffab
---
e3ffab
 API.txt                                     |  32 ++++++--
e3ffab
 VERSION                                     |   4 +-
e3ffab
 ipalib/plugins/host.py                      |  28 +++++--
e3ffab
 ipalib/plugins/service.py                   |  28 +++++--
e3ffab
 ipatests/test_xmlrpc/test_host_plugin.py    | 109 ++++++++++++++++++++++++++--
e3ffab
 ipatests/test_xmlrpc/test_service_plugin.py |  92 ++++++++++++++++++++---
e3ffab
 6 files changed, 257 insertions(+), 36 deletions(-)
e3ffab
e3ffab
diff --git a/API.txt b/API.txt
e3ffab
index 2a63f1e2349f0df69433fa7cb742e269cd42d79f..e9768bf1e87d6679c439b98ed696b720937099d2 100644
e3ffab
--- a/API.txt
e3ffab
+++ b/API.txt
e3ffab
@@ -1826,10 +1826,12 @@ output: Output('completed', <type 'int'>, None)
e3ffab
 output: Output('failed', <type 'dict'>, None)
e3ffab
 output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
e3ffab
 command: host_allow_create_keytab
e3ffab
-args: 1,6,3
e3ffab
+args: 1,8,3
e3ffab
 arg: Str('fqdn', attribute=True, cli_name='hostname', multivalue=False, primary_key=True, query=True, required=True)
e3ffab
 option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
e3ffab
 option: Str('group*', alwaysask=True, cli_name='groups', csv=True)
e3ffab
+option: Str('host*', alwaysask=True, cli_name='hosts', csv=True)
e3ffab
+option: Str('hostgroup*', alwaysask=True, cli_name='hostgroups', csv=True)
e3ffab
 option: Flag('no_members', autofill=True, default=False, exclude='webui')
e3ffab
 option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
e3ffab
 option: Str('user*', alwaysask=True, cli_name='users', csv=True)
e3ffab
@@ -1838,10 +1840,12 @@ output: Output('completed', <type 'int'>, None)
e3ffab
 output: Output('failed', <type 'dict'>, None)
e3ffab
 output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
e3ffab
 command: host_allow_retrieve_keytab
e3ffab
-args: 1,6,3
e3ffab
+args: 1,8,3
e3ffab
 arg: Str('fqdn', attribute=True, cli_name='hostname', multivalue=False, primary_key=True, query=True, required=True)
e3ffab
 option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
e3ffab
 option: Str('group*', alwaysask=True, cli_name='groups', csv=True)
e3ffab
+option: Str('host*', alwaysask=True, cli_name='hosts', csv=True)
e3ffab
+option: Str('hostgroup*', alwaysask=True, cli_name='hostgroups', csv=True)
e3ffab
 option: Flag('no_members', autofill=True, default=False, exclude='webui')
e3ffab
 option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
e3ffab
 option: Str('user*', alwaysask=True, cli_name='users', csv=True)
e3ffab
@@ -1866,10 +1870,12 @@ output: Output('result', <type 'bool'>, None)
e3ffab
 output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
e3ffab
 output: PrimaryKey('value', None, None)
e3ffab
 command: host_disallow_create_keytab
e3ffab
-args: 1,6,3
e3ffab
+args: 1,8,3
e3ffab
 arg: Str('fqdn', attribute=True, cli_name='hostname', multivalue=False, primary_key=True, query=True, required=True)
e3ffab
 option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
e3ffab
 option: Str('group*', alwaysask=True, cli_name='groups', csv=True)
e3ffab
+option: Str('host*', alwaysask=True, cli_name='hosts', csv=True)
e3ffab
+option: Str('hostgroup*', alwaysask=True, cli_name='hostgroups', csv=True)
e3ffab
 option: Flag('no_members', autofill=True, default=False, exclude='webui')
e3ffab
 option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
e3ffab
 option: Str('user*', alwaysask=True, cli_name='users', csv=True)
e3ffab
@@ -1878,10 +1884,12 @@ output: Output('completed', <type 'int'>, None)
e3ffab
 output: Output('failed', <type 'dict'>, None)
e3ffab
 output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
e3ffab
 command: host_disallow_retrieve_keytab
e3ffab
-args: 1,6,3
e3ffab
+args: 1,8,3
e3ffab
 arg: Str('fqdn', attribute=True, cli_name='hostname', multivalue=False, primary_key=True, query=True, required=True)
e3ffab
 option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
e3ffab
 option: Str('group*', alwaysask=True, cli_name='groups', csv=True)
e3ffab
+option: Str('host*', alwaysask=True, cli_name='hosts', csv=True)
e3ffab
+option: Str('hostgroup*', alwaysask=True, cli_name='hostgroups', csv=True)
e3ffab
 option: Flag('no_members', autofill=True, default=False, exclude='webui')
e3ffab
 option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
e3ffab
 option: Str('user*', alwaysask=True, cli_name='users', csv=True)
e3ffab
@@ -3529,10 +3537,12 @@ output: Output('completed', <type 'int'>, None)
e3ffab
 output: Output('failed', <type 'dict'>, None)
e3ffab
 output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
e3ffab
 command: service_allow_create_keytab
e3ffab
-args: 1,6,3
e3ffab
+args: 1,8,3
e3ffab
 arg: Str('krbprincipalname', attribute=True, cli_name='principal', multivalue=False, primary_key=True, query=True, required=True)
e3ffab
 option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
e3ffab
 option: Str('group*', alwaysask=True, cli_name='groups', csv=True)
e3ffab
+option: Str('host*', alwaysask=True, cli_name='hosts', csv=True)
e3ffab
+option: Str('hostgroup*', alwaysask=True, cli_name='hostgroups', csv=True)
e3ffab
 option: Flag('no_members', autofill=True, default=False, exclude='webui')
e3ffab
 option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
e3ffab
 option: Str('user*', alwaysask=True, cli_name='users', csv=True)
e3ffab
@@ -3541,10 +3551,12 @@ output: Output('completed', <type 'int'>, None)
e3ffab
 output: Output('failed', <type 'dict'>, None)
e3ffab
 output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
e3ffab
 command: service_allow_retrieve_keytab
e3ffab
-args: 1,6,3
e3ffab
+args: 1,8,3
e3ffab
 arg: Str('krbprincipalname', attribute=True, cli_name='principal', multivalue=False, primary_key=True, query=True, required=True)
e3ffab
 option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
e3ffab
 option: Str('group*', alwaysask=True, cli_name='groups', csv=True)
e3ffab
+option: Str('host*', alwaysask=True, cli_name='hosts', csv=True)
e3ffab
+option: Str('hostgroup*', alwaysask=True, cli_name='hostgroups', csv=True)
e3ffab
 option: Flag('no_members', autofill=True, default=False, exclude='webui')
e3ffab
 option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
e3ffab
 option: Str('user*', alwaysask=True, cli_name='users', csv=True)
e3ffab
@@ -3568,10 +3580,12 @@ output: Output('result', <type 'bool'>, None)
e3ffab
 output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
e3ffab
 output: PrimaryKey('value', None, None)
e3ffab
 command: service_disallow_create_keytab
e3ffab
-args: 1,6,3
e3ffab
+args: 1,8,3
e3ffab
 arg: Str('krbprincipalname', attribute=True, cli_name='principal', multivalue=False, primary_key=True, query=True, required=True)
e3ffab
 option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
e3ffab
 option: Str('group*', alwaysask=True, cli_name='groups', csv=True)
e3ffab
+option: Str('host*', alwaysask=True, cli_name='hosts', csv=True)
e3ffab
+option: Str('hostgroup*', alwaysask=True, cli_name='hostgroups', csv=True)
e3ffab
 option: Flag('no_members', autofill=True, default=False, exclude='webui')
e3ffab
 option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
e3ffab
 option: Str('user*', alwaysask=True, cli_name='users', csv=True)
e3ffab
@@ -3580,10 +3594,12 @@ output: Output('completed', <type 'int'>, None)
e3ffab
 output: Output('failed', <type 'dict'>, None)
e3ffab
 output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
e3ffab
 command: service_disallow_retrieve_keytab
e3ffab
-args: 1,6,3
e3ffab
+args: 1,8,3
e3ffab
 arg: Str('krbprincipalname', attribute=True, cli_name='principal', multivalue=False, primary_key=True, query=True, required=True)
e3ffab
 option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
e3ffab
 option: Str('group*', alwaysask=True, cli_name='groups', csv=True)
e3ffab
+option: Str('host*', alwaysask=True, cli_name='hosts', csv=True)
e3ffab
+option: Str('hostgroup*', alwaysask=True, cli_name='hostgroups', csv=True)
e3ffab
 option: Flag('no_members', autofill=True, default=False, exclude='webui')
e3ffab
 option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
e3ffab
 option: Str('user*', alwaysask=True, cli_name='users', csv=True)
e3ffab
diff --git a/VERSION b/VERSION
e3ffab
index 750b5058867ca5f073a083009c4aadeeb0240c35..bfbce5604e79008afd2893e406c634718159b1e9 100644
e3ffab
--- a/VERSION
e3ffab
+++ b/VERSION
e3ffab
@@ -90,5 +90,5 @@ IPA_DATA_VERSION=20100614120000
e3ffab
 #                                                      #
e3ffab
 ########################################################
e3ffab
 IPA_API_VERSION_MAJOR=2
e3ffab
-IPA_API_VERSION_MINOR=109
e3ffab
-# Last change: npmccallum - display qrcode by default
e3ffab
+IPA_API_VERSION_MINOR=110
e3ffab
+# Last change: pvoborni - allow to retrieve keytab by hosts
e3ffab
diff --git a/ipalib/plugins/host.py b/ipalib/plugins/host.py
e3ffab
index c4d4bdf6473e0f34c8c68754d6c98e93d173d8fa..39a7d3c25b9cb56fca486b2500da5fe7bd4a6fbc 100644
e3ffab
--- a/ipalib/plugins/host.py
e3ffab
+++ b/ipalib/plugins/host.py
e3ffab
@@ -211,12 +211,24 @@ host_output_params = (
e3ffab
     Str('ipaallowedtoperform_read_keys_group',
e3ffab
         label=_('Groups allowed to retrieve keytab'),
e3ffab
     ),
e3ffab
+    Str('ipaallowedtoperform_read_keys_host',
e3ffab
+        label=_('Hosts allowed to retrieve keytab'),
e3ffab
+    ),
e3ffab
+    Str('ipaallowedtoperform_read_keys_hostgroup',
e3ffab
+        label=_('Host Groups allowed to retrieve keytab'),
e3ffab
+    ),
e3ffab
     Str('ipaallowedtoperform_write_keys_user',
e3ffab
         label=_('Users allowed to create keytab'),
e3ffab
     ),
e3ffab
     Str('ipaallowedtoperform_write_keys_group',
e3ffab
         label=_('Groups allowed to create keytab'),
e3ffab
     ),
e3ffab
+    Str('ipaallowedtoperform_write_keys_host',
e3ffab
+        label=_('Hosts allowed to create keytab'),
e3ffab
+    ),
e3ffab
+    Str('ipaallowedtoperform_write_keys_hostgroup',
e3ffab
+        label=_('Host Groups allowed to create keytab'),
e3ffab
+    ),
e3ffab
     Str('ipaallowedtoperform_read_keys',
e3ffab
         label=_('Failed allowed to retrieve keytab'),
e3ffab
     ),
e3ffab
@@ -284,8 +296,8 @@ class host(LDAPObject):
e3ffab
         'managing': ['host'],
e3ffab
         'memberofindirect': ['hostgroup', 'netgroup', 'role', 'hbacrule',
e3ffab
         'sudorule'],
e3ffab
-        'ipaallowedtoperform_read_keys': ['user', 'group'],
e3ffab
-        'ipaallowedtoperform_write_keys': ['user', 'group'],
e3ffab
+        'ipaallowedtoperform_read_keys': ['user', 'group', 'host', 'hostgroup'],
e3ffab
+        'ipaallowedtoperform_write_keys': ['user', 'group', 'host', 'hostgroup'],
e3ffab
     }
e3ffab
     bindable = True
e3ffab
     relationships = {
e3ffab
@@ -1201,7 +1213,8 @@ class host_remove_managedby(LDAPRemoveMember):
e3ffab
 
e3ffab
 @register()
e3ffab
 class host_allow_retrieve_keytab(LDAPAddMember):
e3ffab
-    __doc__ = _('Allow users or groups to retrieve a keytab of this host.')
e3ffab
+    __doc__ = _('Allow users, groups, hosts or host groups to retrieve a keytab'
e3ffab
+                ' of this host.')
e3ffab
     member_attributes = ['ipaallowedtoperform_read_keys']
e3ffab
     has_output_params = LDAPAddMember.has_output_params + host_output_params
e3ffab
 
e3ffab
@@ -1219,7 +1232,8 @@ class host_allow_retrieve_keytab(LDAPAddMember):
e3ffab
 
e3ffab
 @register()
e3ffab
 class host_disallow_retrieve_keytab(LDAPRemoveMember):
e3ffab
-    __doc__ = _('Disallow users or groups to retrieve a keytab of this host.')
e3ffab
+    __doc__ = _('Disallow users, groups, hosts or host groups to retrieve a '
e3ffab
+                'keytab of this host.')
e3ffab
     member_attributes = ['ipaallowedtoperform_read_keys']
e3ffab
     has_output_params = LDAPRemoveMember.has_output_params + host_output_params
e3ffab
 
e3ffab
@@ -1236,7 +1250,8 @@ class host_disallow_retrieve_keytab(LDAPRemoveMember):
e3ffab
 
e3ffab
 @register()
e3ffab
 class host_allow_create_keytab(LDAPAddMember):
e3ffab
-    __doc__ = _('Allow users or groups to create a keytab of this host.')
e3ffab
+    __doc__ = _('Allow users, groups, hosts or host groups to create a keytab '
e3ffab
+                'of this host.')
e3ffab
     member_attributes = ['ipaallowedtoperform_write_keys']
e3ffab
     has_output_params = LDAPAddMember.has_output_params + host_output_params
e3ffab
 
e3ffab
@@ -1254,7 +1269,8 @@ class host_allow_create_keytab(LDAPAddMember):
e3ffab
 
e3ffab
 @register()
e3ffab
 class host_disallow_create_keytab(LDAPRemoveMember):
e3ffab
-    __doc__ = _('Disallow users or groups to create a keytab of this host.')
e3ffab
+    __doc__ = _('Disallow users, groups, hosts or host groups to create a '
e3ffab
+                'keytab of this host.')
e3ffab
     member_attributes = ['ipaallowedtoperform_write_keys']
e3ffab
     has_output_params = LDAPRemoveMember.has_output_params + host_output_params
e3ffab
 
e3ffab
diff --git a/ipalib/plugins/service.py b/ipalib/plugins/service.py
e3ffab
index 2f703544452c6d7ee2de8eceeb5f2a26afed44f2..b37dc7b4bf56b69df204fd29e9487f1390197bbe 100644
e3ffab
--- a/ipalib/plugins/service.py
e3ffab
+++ b/ipalib/plugins/service.py
e3ffab
@@ -137,12 +137,24 @@ output_params = (
e3ffab
     Str('ipaallowedtoperform_read_keys_group',
e3ffab
         label=_('Groups allowed to retrieve keytab'),
e3ffab
     ),
e3ffab
+    Str('ipaallowedtoperform_read_keys_host',
e3ffab
+        label=_('Hosts allowed to retrieve keytab'),
e3ffab
+    ),
e3ffab
+    Str('ipaallowedtoperform_read_keys_hostgroup',
e3ffab
+        label=_('Host Groups allowed to retrieve keytab'),
e3ffab
+    ),
e3ffab
     Str('ipaallowedtoperform_write_keys_user',
e3ffab
         label=_('Users allowed to create keytab'),
e3ffab
     ),
e3ffab
     Str('ipaallowedtoperform_write_keys_group',
e3ffab
         label=_('Groups allowed to create keytab'),
e3ffab
     ),
e3ffab
+    Str('ipaallowedtoperform_write_keys_host',
e3ffab
+        label=_('Hosts allowed to create keytab'),
e3ffab
+    ),
e3ffab
+    Str('ipaallowedtoperform_write_keys_hostgroup',
e3ffab
+        label=_('Host Groups allowed to create keytab'),
e3ffab
+    ),
e3ffab
     Str('ipaallowedtoperform_read_keys',
e3ffab
         label=_('Failed allowed to retrieve keytab'),
e3ffab
     ),
e3ffab
@@ -350,8 +362,8 @@ class service(LDAPObject):
e3ffab
     attribute_members = {
e3ffab
         'managedby': ['host'],
e3ffab
         'memberof': ['role'],
e3ffab
-        'ipaallowedtoperform_read_keys': ['user', 'group'],
e3ffab
-        'ipaallowedtoperform_write_keys': ['user', 'group'],
e3ffab
+        'ipaallowedtoperform_read_keys': ['user', 'group', 'host', 'hostgroup'],
e3ffab
+        'ipaallowedtoperform_write_keys': ['user', 'group', 'host', 'hostgroup'],
e3ffab
     }
e3ffab
     bindable = True
e3ffab
     relationships = {
e3ffab
@@ -711,7 +723,8 @@ class service_remove_host(LDAPRemoveMember):
e3ffab
 
e3ffab
 @register()
e3ffab
 class service_allow_retrieve_keytab(LDAPAddMember):
e3ffab
-    __doc__ = _('Allow users or groups to retrieve a keytab of this service.')
e3ffab
+    __doc__ = _('Allow users, groups, hosts or host groups to retrieve a keytab'
e3ffab
+                ' of this service.')
e3ffab
     member_attributes = ['ipaallowedtoperform_read_keys']
e3ffab
     has_output_params = LDAPAddMember.has_output_params + output_params
e3ffab
 
e3ffab
@@ -729,7 +742,8 @@ class service_allow_retrieve_keytab(LDAPAddMember):
e3ffab
 
e3ffab
 @register()
e3ffab
 class service_disallow_retrieve_keytab(LDAPRemoveMember):
e3ffab
-    __doc__ = _('Disallow users or groups to retrieve a keytab of this service.')
e3ffab
+    __doc__ = _('Disallow users, groups, hosts or host groups to retrieve a '
e3ffab
+                'keytab of this service.')
e3ffab
     member_attributes = ['ipaallowedtoperform_read_keys']
e3ffab
     has_output_params = LDAPRemoveMember.has_output_params + output_params
e3ffab
 
e3ffab
@@ -746,7 +760,8 @@ class service_disallow_retrieve_keytab(LDAPRemoveMember):
e3ffab
 
e3ffab
 @register()
e3ffab
 class service_allow_create_keytab(LDAPAddMember):
e3ffab
-    __doc__ = _('Allow users or groups to create a keytab of this service.')
e3ffab
+    __doc__ = _('Allow users, groups, hosts or host groups to create a keytab '
e3ffab
+                'of this service.')
e3ffab
     member_attributes = ['ipaallowedtoperform_write_keys']
e3ffab
     has_output_params = LDAPAddMember.has_output_params + output_params
e3ffab
 
e3ffab
@@ -764,7 +779,8 @@ class service_allow_create_keytab(LDAPAddMember):
e3ffab
 
e3ffab
 @register()
e3ffab
 class service_disallow_create_keytab(LDAPRemoveMember):
e3ffab
-    __doc__ = _('Disallow users or groups to create a keytab of this service.')
e3ffab
+    __doc__ = _('Disallow users, groups, hosts or host groups to create a '
e3ffab
+                'keytab of this service.')
e3ffab
     member_attributes = ['ipaallowedtoperform_write_keys']
e3ffab
     has_output_params = LDAPRemoveMember.has_output_params + output_params
e3ffab
 
e3ffab
diff --git a/ipatests/test_xmlrpc/test_host_plugin.py b/ipatests/test_xmlrpc/test_host_plugin.py
e3ffab
index 67acb765fc1716e10ac7846d8780bf031c9f079e..1c46ce9131554b799d25a15922d26ccb92763e93 100644
e3ffab
--- a/ipatests/test_xmlrpc/test_host_plugin.py
e3ffab
+++ b/ipatests/test_xmlrpc/test_host_plugin.py
e3ffab
@@ -147,6 +147,9 @@ group1 = u'group1'
e3ffab
 group1_dn = get_group_dn(group1)
e3ffab
 group2 = u'group2'
e3ffab
 group2_dn = get_group_dn(group2)
e3ffab
+hostgroup1 = u'testhostgroup1'
e3ffab
+hostgroup1_dn = DN(('cn',hostgroup1),('cn','hostgroups'),('cn','accounts'),
e3ffab
+                    api.env.basedn)
e3ffab
 
e3ffab
 class test_host(Declarative):
e3ffab
 
e3ffab
@@ -1420,6 +1423,8 @@ class test_host_allowed_to(Declarative):
e3ffab
         ('group_del', [group1], {}),
e3ffab
         ('group_del', [group2], {}),
e3ffab
         ('host_del', [fqdn1], {}),
e3ffab
+        ('host_del', [fqdn3], {}),
e3ffab
+        ('hostgroup_del', [hostgroup1], {}),
e3ffab
     ]
e3ffab
 
e3ffab
     tests = [
e3ffab
@@ -1503,6 +1508,49 @@ class test_host_allowed_to(Declarative):
e3ffab
                 ),
e3ffab
             ),
e3ffab
         ),
e3ffab
+        dict(
e3ffab
+            desc='Create %r' % fqdn3,
e3ffab
+            command=(
e3ffab
+                'host_add', [fqdn3],
e3ffab
+                dict(
e3ffab
+                    force=True,
e3ffab
+                ),
e3ffab
+            ),
e3ffab
+            expected=dict(
e3ffab
+                value=fqdn3,
e3ffab
+                summary=u'Added host "%s"' % fqdn3,
e3ffab
+                result=dict(
e3ffab
+                    dn=dn3,
e3ffab
+                    fqdn=[fqdn3],
e3ffab
+                    krbprincipalname=[u'host/%s@%s' % (fqdn3, api.env.realm)],
e3ffab
+                    objectclass=objectclasses.host,
e3ffab
+                    ipauniqueid=[fuzzy_uuid],
e3ffab
+                    managedby_host=[fqdn3],
e3ffab
+                    has_keytab=False,
e3ffab
+                    has_password=False,
e3ffab
+                ),
e3ffab
+            ),
e3ffab
+        ),
e3ffab
+
e3ffab
+        dict(
e3ffab
+            desc='Create %r' % hostgroup1,
e3ffab
+            command=('hostgroup_add', [hostgroup1],
e3ffab
+                dict(description=u'Test hostgroup 1')
e3ffab
+            ),
e3ffab
+            expected=dict(
e3ffab
+                value=hostgroup1,
e3ffab
+                summary=u'Added hostgroup "testhostgroup1"',
e3ffab
+                result=dict(
e3ffab
+                    dn=hostgroup1_dn,
e3ffab
+                    cn=[hostgroup1],
e3ffab
+                    objectclass=objectclasses.hostgroup,
e3ffab
+                    description=[u'Test hostgroup 1'],
e3ffab
+                    ipauniqueid=[fuzzy_uuid],
e3ffab
+                    mepmanagedentry=[DN(('cn',hostgroup1),('cn','ng'),('cn','alt'),
e3ffab
+                                        api.env.basedn)],
e3ffab
+                ),
e3ffab
+            ),
e3ffab
+        ),
e3ffab
 
e3ffab
         # verify
e3ffab
         dict(
e3ffab
@@ -1513,6 +1561,8 @@ class test_host_allowed_to(Declarative):
e3ffab
                 failed=dict(
e3ffab
                     ipaallowedtoperform_read_keys=dict(
e3ffab
                         group=[],
e3ffab
+                        host=[],
e3ffab
+                        hostgroup=[],
e3ffab
                         user=[],
e3ffab
                     ),
e3ffab
                 ),
e3ffab
@@ -1535,6 +1585,8 @@ class test_host_allowed_to(Declarative):
e3ffab
                 failed=dict(
e3ffab
                     ipaallowedtoperform_read_keys=dict(
e3ffab
                         group=[],
e3ffab
+                        host=[],
e3ffab
+                        hostgroup=[],
e3ffab
                         user=[[user1, u'This entry is already a member']],
e3ffab
                     ),
e3ffab
                 ),
e3ffab
@@ -1553,20 +1605,25 @@ class test_host_allowed_to(Declarative):
e3ffab
             desc='Allow %r, %r to a retrieve keytab of %r' % (
e3ffab
                 group1, group2, fqdn1),
e3ffab
             command=('host_allow_retrieve_keytab', [fqdn1],
e3ffab
-                     dict(group=[group1, group2])),
e3ffab
+                     dict(group=[group1, group2], host=[fqdn3],
e3ffab
+                          hostgroup=[hostgroup1])),
e3ffab
             expected=dict(
e3ffab
                 failed=dict(
e3ffab
                     ipaallowedtoperform_read_keys=dict(
e3ffab
                         group=[],
e3ffab
+                        host=[],
e3ffab
+                        hostgroup=[],
e3ffab
                         user=[],
e3ffab
                     ),
e3ffab
                 ),
e3ffab
-                completed=2,
e3ffab
+                completed=4,
e3ffab
                 result=dict(
e3ffab
                     dn=dn1,
e3ffab
                     fqdn=[fqdn1],
e3ffab
                     ipaallowedtoperform_read_keys_user=[user1],
e3ffab
                     ipaallowedtoperform_read_keys_group=[group1, group2],
e3ffab
+                    ipaallowedtoperform_read_keys_host=[fqdn3],
e3ffab
+                    ipaallowedtoperform_read_keys_hostgroup=[hostgroup1],
e3ffab
                     krbprincipalname=[u'host/%s@%s' % (fqdn1, api.env.realm)],
e3ffab
                     managedby_host=[fqdn1],
e3ffab
                 ),
e3ffab
@@ -1581,6 +1638,8 @@ class test_host_allowed_to(Declarative):
e3ffab
                 failed=dict(
e3ffab
                     ipaallowedtoperform_read_keys=dict(
e3ffab
                         group=[],
e3ffab
+                        host=[],
e3ffab
+                        hostgroup=[],
e3ffab
                         user=[[user2, u'This entry is not a member']],
e3ffab
                     ),
e3ffab
                 ),
e3ffab
@@ -1590,6 +1649,8 @@ class test_host_allowed_to(Declarative):
e3ffab
                     fqdn=[fqdn1],
e3ffab
                     ipaallowedtoperform_read_keys_user=[user1],
e3ffab
                     ipaallowedtoperform_read_keys_group=[group1, group2],
e3ffab
+                    ipaallowedtoperform_read_keys_host=[fqdn3],
e3ffab
+                    ipaallowedtoperform_read_keys_hostgroup=[hostgroup1],
e3ffab
                     krbprincipalname=[u'host/%s@%s' % (fqdn1, api.env.realm)],
e3ffab
                     managedby_host=[fqdn1],
e3ffab
                 ),
e3ffab
@@ -1604,6 +1665,8 @@ class test_host_allowed_to(Declarative):
e3ffab
                 failed=dict(
e3ffab
                     ipaallowedtoperform_read_keys=dict(
e3ffab
                         group=[],
e3ffab
+                        host=[],
e3ffab
+                        hostgroup=[],
e3ffab
                         user=[],
e3ffab
                     ),
e3ffab
                 ),
e3ffab
@@ -1613,6 +1676,8 @@ class test_host_allowed_to(Declarative):
e3ffab
                     fqdn=[fqdn1],
e3ffab
                     ipaallowedtoperform_read_keys_user=[user1],
e3ffab
                     ipaallowedtoperform_read_keys_group=[group1],
e3ffab
+                    ipaallowedtoperform_read_keys_host=[fqdn3],
e3ffab
+                    ipaallowedtoperform_read_keys_hostgroup=[hostgroup1],
e3ffab
                     krbprincipalname=[u'host/%s@%s' % (fqdn1, api.env.realm)],
e3ffab
                     managedby_host=[fqdn1],
e3ffab
                 ),
e3ffab
@@ -1623,22 +1688,29 @@ class test_host_allowed_to(Declarative):
e3ffab
             desc='Allow %r, %r to a create keytab of %r' % (
e3ffab
                 group1, user1, fqdn1),
e3ffab
             command=('host_allow_create_keytab', [fqdn1],
e3ffab
-                     dict(group=[group1, group2], user=[user1])),
e3ffab
+                     dict(group=[group1, group2], user=[user1], host=[fqdn3],
e3ffab
+                          hostgroup=[hostgroup1])),
e3ffab
             expected=dict(
e3ffab
                 failed=dict(
e3ffab
                     ipaallowedtoperform_write_keys=dict(
e3ffab
                         group=[],
e3ffab
+                        host=[],
e3ffab
+                        hostgroup=[],
e3ffab
                         user=[],
e3ffab
                     ),
e3ffab
                 ),
e3ffab
-                completed=3,
e3ffab
+                completed=5,
e3ffab
                 result=dict(
e3ffab
                     dn=dn1,
e3ffab
                     fqdn=[fqdn1],
e3ffab
                     ipaallowedtoperform_read_keys_user=[user1],
e3ffab
                     ipaallowedtoperform_read_keys_group=[group1],
e3ffab
+                    ipaallowedtoperform_read_keys_host=[fqdn3],
e3ffab
+                    ipaallowedtoperform_read_keys_hostgroup=[hostgroup1],
e3ffab
                     ipaallowedtoperform_write_keys_user=[user1],
e3ffab
                     ipaallowedtoperform_write_keys_group=[group1, group2],
e3ffab
+                    ipaallowedtoperform_write_keys_host=[fqdn3],
e3ffab
+                    ipaallowedtoperform_write_keys_hostgroup=[hostgroup1],
e3ffab
                     krbprincipalname=[u'host/%s@%s' % (fqdn1, api.env.realm)],
e3ffab
                     managedby_host=[fqdn1],
e3ffab
                 ),
e3ffab
@@ -1648,12 +1720,15 @@ class test_host_allowed_to(Declarative):
e3ffab
         dict(
e3ffab
             desc='Duplicate add: %r, %r' % (user1, group1),
e3ffab
             command=('host_allow_create_keytab', [fqdn1],
e3ffab
-                     dict(group=[group1], user=[user1])),
e3ffab
+                     dict(group=[group1], user=[user1], host=[fqdn3],
e3ffab
+                          hostgroup=[hostgroup1])),
e3ffab
             expected=dict(
e3ffab
                 failed=dict(
e3ffab
                     ipaallowedtoperform_write_keys=dict(
e3ffab
                         group=[[group1, u'This entry is already a member']],
e3ffab
+                        host=[[fqdn3, u'This entry is already a member']],
e3ffab
                         user=[[user1, u'This entry is already a member']],
e3ffab
+                        hostgroup=[[hostgroup1, u'This entry is already a member']],
e3ffab
                     ),
e3ffab
                 ),
e3ffab
                 completed=0,
e3ffab
@@ -1662,8 +1737,12 @@ class test_host_allowed_to(Declarative):
e3ffab
                     fqdn=[fqdn1],
e3ffab
                     ipaallowedtoperform_read_keys_user=[user1],
e3ffab
                     ipaallowedtoperform_read_keys_group=[group1],
e3ffab
+                    ipaallowedtoperform_read_keys_host=[fqdn3],
e3ffab
+                    ipaallowedtoperform_read_keys_hostgroup=[hostgroup1],
e3ffab
                     ipaallowedtoperform_write_keys_user=[user1],
e3ffab
                     ipaallowedtoperform_write_keys_group=[group1, group2],
e3ffab
+                    ipaallowedtoperform_write_keys_host=[fqdn3],
e3ffab
+                    ipaallowedtoperform_write_keys_hostgroup=[hostgroup1],
e3ffab
                     krbprincipalname=[u'host/%s@%s' % (fqdn1, api.env.realm)],
e3ffab
                     managedby_host=[fqdn1],
e3ffab
                 ),
e3ffab
@@ -1678,6 +1757,8 @@ class test_host_allowed_to(Declarative):
e3ffab
                 failed=dict(
e3ffab
                     ipaallowedtoperform_write_keys=dict(
e3ffab
                         group=[],
e3ffab
+                        host=[],
e3ffab
+                        hostgroup=[],
e3ffab
                         user=[[user2, u'This entry is not a member']],
e3ffab
                     ),
e3ffab
                 ),
e3ffab
@@ -1687,8 +1768,12 @@ class test_host_allowed_to(Declarative):
e3ffab
                     fqdn=[fqdn1],
e3ffab
                     ipaallowedtoperform_read_keys_user=[user1],
e3ffab
                     ipaallowedtoperform_read_keys_group=[group1],
e3ffab
+                    ipaallowedtoperform_read_keys_host=[fqdn3],
e3ffab
+                    ipaallowedtoperform_read_keys_hostgroup=[hostgroup1],
e3ffab
                     ipaallowedtoperform_write_keys_user=[user1],
e3ffab
                     ipaallowedtoperform_write_keys_group=[group1, group2],
e3ffab
+                    ipaallowedtoperform_write_keys_host=[fqdn3],
e3ffab
+                    ipaallowedtoperform_write_keys_hostgroup=[hostgroup1],
e3ffab
                     krbprincipalname=[u'host/%s@%s' % (fqdn1, api.env.realm)],
e3ffab
                     managedby_host=[fqdn1],
e3ffab
                 ),
e3ffab
@@ -1703,6 +1788,8 @@ class test_host_allowed_to(Declarative):
e3ffab
                 failed=dict(
e3ffab
                     ipaallowedtoperform_write_keys=dict(
e3ffab
                         group=[],
e3ffab
+                        host=[],
e3ffab
+                        hostgroup=[],
e3ffab
                         user=[],
e3ffab
                     ),
e3ffab
                 ),
e3ffab
@@ -1712,8 +1799,12 @@ class test_host_allowed_to(Declarative):
e3ffab
                     fqdn=[fqdn1],
e3ffab
                     ipaallowedtoperform_read_keys_user=[user1],
e3ffab
                     ipaallowedtoperform_read_keys_group=[group1],
e3ffab
+                    ipaallowedtoperform_read_keys_host=[fqdn3],
e3ffab
+                    ipaallowedtoperform_read_keys_hostgroup=[hostgroup1],
e3ffab
                     ipaallowedtoperform_write_keys_user=[user1],
e3ffab
                     ipaallowedtoperform_write_keys_group=[group1],
e3ffab
+                    ipaallowedtoperform_write_keys_host=[fqdn3],
e3ffab
+                    ipaallowedtoperform_write_keys_hostgroup=[hostgroup1],
e3ffab
                     krbprincipalname=[u'host/%s@%s' % (fqdn1, api.env.realm)],
e3ffab
                     managedby_host=[fqdn1],
e3ffab
                 ),
e3ffab
@@ -1733,8 +1824,12 @@ class test_host_allowed_to(Declarative):
e3ffab
                     has_password=False,
e3ffab
                     ipaallowedtoperform_read_keys_user=[user1],
e3ffab
                     ipaallowedtoperform_read_keys_group=[group1],
e3ffab
+                    ipaallowedtoperform_read_keys_host=[fqdn3],
e3ffab
+                    ipaallowedtoperform_read_keys_hostgroup=[hostgroup1],
e3ffab
                     ipaallowedtoperform_write_keys_user=[user1],
e3ffab
                     ipaallowedtoperform_write_keys_group=[group1],
e3ffab
+                    ipaallowedtoperform_write_keys_host=[fqdn3],
e3ffab
+                    ipaallowedtoperform_write_keys_hostgroup=[hostgroup1],
e3ffab
                     krbprincipalname=[u'host/%s@%s' % (fqdn1, api.env.realm)],
e3ffab
                     managedby_host=[fqdn1],
e3ffab
                 ),
e3ffab
@@ -1756,8 +1851,12 @@ class test_host_allowed_to(Declarative):
e3ffab
                     has_password=False,
e3ffab
                     ipaallowedtoperform_read_keys_user=[user1],
e3ffab
                     ipaallowedtoperform_read_keys_group=[group1],
e3ffab
+                    ipaallowedtoperform_read_keys_host=[fqdn3],
e3ffab
+                    ipaallowedtoperform_read_keys_hostgroup=[hostgroup1],
e3ffab
                     ipaallowedtoperform_write_keys_user=[user1],
e3ffab
                     ipaallowedtoperform_write_keys_group=[group1],
e3ffab
+                    ipaallowedtoperform_write_keys_host=[fqdn3],
e3ffab
+                    ipaallowedtoperform_write_keys_hostgroup=[hostgroup1],
e3ffab
                     krbprincipalname=[u'host/%s@%s' % (fqdn1, api.env.realm)],
e3ffab
                     managedby_host=[fqdn1],
e3ffab
                 ),
e3ffab
diff --git a/ipatests/test_xmlrpc/test_service_plugin.py b/ipatests/test_xmlrpc/test_service_plugin.py
e3ffab
index 927ce73f86a0025b8384cf0126ef00be3598975a..946dc572b0d0e5b3f26cd7bfd6ad8128f113493f 100644
e3ffab
--- a/ipatests/test_xmlrpc/test_service_plugin.py
e3ffab
+++ b/ipatests/test_xmlrpc/test_service_plugin.py
e3ffab
@@ -54,6 +54,9 @@ group1 = u'group1'
e3ffab
 group1_dn = get_group_dn(group1)
e3ffab
 group2 = u'group2'
e3ffab
 group2_dn = get_group_dn(group2)
e3ffab
+hostgroup1 = u'testhostgroup1'
e3ffab
+hostgroup1_dn = DN(('cn',hostgroup1),('cn','hostgroups'),('cn','accounts'),
e3ffab
+                    api.env.basedn)
e3ffab
 
e3ffab
 class test_service(Declarative):
e3ffab
 
e3ffab
@@ -770,6 +773,7 @@ class test_service_allowed_to(Declarative):
e3ffab
         ('group_del', [group2], {}),
e3ffab
         ('host_del', [fqdn1], {}),
e3ffab
         ('service_del', [service1], {}),
e3ffab
+        ('hostgroup_del', [hostgroup1], {}),
e3ffab
     ]
e3ffab
 
e3ffab
     tests = [
e3ffab
@@ -858,6 +862,25 @@ class test_service_allowed_to(Declarative):
e3ffab
             ),
e3ffab
         ),
e3ffab
         dict(
e3ffab
+            desc='Create %r' % hostgroup1,
e3ffab
+            command=('hostgroup_add', [hostgroup1],
e3ffab
+                dict(description=u'Test hostgroup 1')
e3ffab
+            ),
e3ffab
+            expected=dict(
e3ffab
+                value=hostgroup1,
e3ffab
+                summary=u'Added hostgroup "testhostgroup1"',
e3ffab
+                result=dict(
e3ffab
+                    dn=hostgroup1_dn,
e3ffab
+                    cn=[hostgroup1],
e3ffab
+                    objectclass=objectclasses.hostgroup,
e3ffab
+                    description=[u'Test hostgroup 1'],
e3ffab
+                    ipauniqueid=[fuzzy_uuid],
e3ffab
+                    mepmanagedentry=[DN(('cn',hostgroup1),('cn','ng'),('cn','alt'),
e3ffab
+                                        api.env.basedn)],
e3ffab
+                ),
e3ffab
+            ),
e3ffab
+        ),
e3ffab
+        dict(
e3ffab
             desc='Create %r' % service1,
e3ffab
             command=('service_add', [service1_no_realm], dict(force=True)),
e3ffab
             expected=dict(
e3ffab
@@ -882,6 +905,8 @@ class test_service_allowed_to(Declarative):
e3ffab
                 failed=dict(
e3ffab
                     ipaallowedtoperform_read_keys=dict(
e3ffab
                         group=[],
e3ffab
+                        host=[],
e3ffab
+                        hostgroup=[],
e3ffab
                         user=[],
e3ffab
                     ),
e3ffab
                 ),
e3ffab
@@ -903,6 +928,8 @@ class test_service_allowed_to(Declarative):
e3ffab
                 failed=dict(
e3ffab
                     ipaallowedtoperform_read_keys=dict(
e3ffab
                         group=[],
e3ffab
+                        host=[],
e3ffab
+                        hostgroup=[],
e3ffab
                         user=[[user1, u'This entry is already a member']],
e3ffab
                     ),
e3ffab
                 ),
e3ffab
@@ -917,22 +944,27 @@ class test_service_allowed_to(Declarative):
e3ffab
         ),
e3ffab
 
e3ffab
         dict(
e3ffab
-            desc='Allow %r, %r to a retrieve keytab of %r' % (
e3ffab
-                group1, group2, service1),
e3ffab
+            desc='Allow %r, %r, %r to a retrieve keytab of %r' % (
e3ffab
+                group1, group2, fqdn1, service1),
e3ffab
             command=('service_allow_retrieve_keytab', [service1],
e3ffab
-                     dict(group=[group1, group2])),
e3ffab
+                     dict(group=[group1, group2], host=[fqdn1],
e3ffab
+                          hostgroup=[hostgroup1])),
e3ffab
             expected=dict(
e3ffab
                 failed=dict(
e3ffab
                     ipaallowedtoperform_read_keys=dict(
e3ffab
                         group=[],
e3ffab
+                        host=[],
e3ffab
+                        hostgroup=[],
e3ffab
                         user=[],
e3ffab
                     ),
e3ffab
                 ),
e3ffab
-                completed=2,
e3ffab
+                completed=4,
e3ffab
                 result=dict(
e3ffab
                     dn=service1dn,
e3ffab
                     ipaallowedtoperform_read_keys_user=[user1],
e3ffab
                     ipaallowedtoperform_read_keys_group=[group1, group2],
e3ffab
+                    ipaallowedtoperform_read_keys_host=[fqdn1],
e3ffab
+                    ipaallowedtoperform_read_keys_hostgroup=[hostgroup1],
e3ffab
                     krbprincipalname=[service1],
e3ffab
                     managedby_host=[fqdn1],
e3ffab
                 ),
e3ffab
@@ -947,6 +979,8 @@ class test_service_allowed_to(Declarative):
e3ffab
                 failed=dict(
e3ffab
                     ipaallowedtoperform_read_keys=dict(
e3ffab
                         group=[],
e3ffab
+                        host=[],
e3ffab
+                        hostgroup=[],
e3ffab
                         user=[[user2, u'This entry is not a member']],
e3ffab
                     ),
e3ffab
                 ),
e3ffab
@@ -955,6 +989,8 @@ class test_service_allowed_to(Declarative):
e3ffab
                     dn=service1dn,
e3ffab
                     ipaallowedtoperform_read_keys_user=[user1],
e3ffab
                     ipaallowedtoperform_read_keys_group=[group1, group2],
e3ffab
+                    ipaallowedtoperform_read_keys_host=[fqdn1],
e3ffab
+                    ipaallowedtoperform_read_keys_hostgroup=[hostgroup1],
e3ffab
                     krbprincipalname=[service1],
e3ffab
                     managedby_host=[fqdn1],
e3ffab
                 ),
e3ffab
@@ -969,6 +1005,8 @@ class test_service_allowed_to(Declarative):
e3ffab
                 failed=dict(
e3ffab
                     ipaallowedtoperform_read_keys=dict(
e3ffab
                         group=[],
e3ffab
+                        host=[],
e3ffab
+                        hostgroup=[],
e3ffab
                         user=[],
e3ffab
                     ),
e3ffab
                 ),
e3ffab
@@ -977,6 +1015,8 @@ class test_service_allowed_to(Declarative):
e3ffab
                     dn=service1dn,
e3ffab
                     ipaallowedtoperform_read_keys_user=[user1],
e3ffab
                     ipaallowedtoperform_read_keys_group=[group1],
e3ffab
+                    ipaallowedtoperform_read_keys_host=[fqdn1],
e3ffab
+                    ipaallowedtoperform_read_keys_hostgroup=[hostgroup1],
e3ffab
                     krbprincipalname=[service1],
e3ffab
                     managedby_host=[fqdn1],
e3ffab
                 ),
e3ffab
@@ -984,24 +1024,31 @@ class test_service_allowed_to(Declarative):
e3ffab
         ),
e3ffab
 
e3ffab
         dict(
e3ffab
-            desc='Allow %r, %r to a create keytab of %r' % (
e3ffab
-                group1, user1, service1),
e3ffab
+            desc='Allow %r, %r, %r to a create keytab of %r' % (
e3ffab
+                group1, user1, fqdn1, service1),
e3ffab
             command=('service_allow_create_keytab', [service1],
e3ffab
-                     dict(group=[group1, group2], user=[user1])),
e3ffab
+                     dict(group=[group1, group2], user=[user1], host=[fqdn1],
e3ffab
+                          hostgroup=[hostgroup1])),
e3ffab
             expected=dict(
e3ffab
                 failed=dict(
e3ffab
                     ipaallowedtoperform_write_keys=dict(
e3ffab
                         group=[],
e3ffab
+                        host=[],
e3ffab
+                        hostgroup=[],
e3ffab
                         user=[],
e3ffab
                     ),
e3ffab
                 ),
e3ffab
-                completed=3,
e3ffab
+                completed=5,
e3ffab
                 result=dict(
e3ffab
                     dn=service1dn,
e3ffab
                     ipaallowedtoperform_read_keys_user=[user1],
e3ffab
                     ipaallowedtoperform_read_keys_group=[group1],
e3ffab
+                    ipaallowedtoperform_read_keys_host=[fqdn1],
e3ffab
+                    ipaallowedtoperform_read_keys_hostgroup=[hostgroup1],
e3ffab
                     ipaallowedtoperform_write_keys_user=[user1],
e3ffab
                     ipaallowedtoperform_write_keys_group=[group1, group2],
e3ffab
+                    ipaallowedtoperform_write_keys_host=[fqdn1],
e3ffab
+                    ipaallowedtoperform_write_keys_hostgroup=[hostgroup1],
e3ffab
                     krbprincipalname=[service1],
e3ffab
                     managedby_host=[fqdn1],
e3ffab
                 ),
e3ffab
@@ -1011,12 +1058,15 @@ class test_service_allowed_to(Declarative):
e3ffab
         dict(
e3ffab
             desc='Duplicate add: %r, %r' % (user1, group1),
e3ffab
             command=('service_allow_create_keytab', [service1],
e3ffab
-                     dict(group=[group1], user=[user1])),
e3ffab
+                     dict(group=[group1], user=[user1], host=[fqdn1],
e3ffab
+                          hostgroup=[hostgroup1])),
e3ffab
             expected=dict(
e3ffab
                 failed=dict(
e3ffab
                     ipaallowedtoperform_write_keys=dict(
e3ffab
                         group=[[group1, u'This entry is already a member']],
e3ffab
+                        host=[[fqdn1, u'This entry is already a member']],
e3ffab
                         user=[[user1, u'This entry is already a member']],
e3ffab
+                        hostgroup=[[hostgroup1, u'This entry is already a member']],
e3ffab
                     ),
e3ffab
                 ),
e3ffab
                 completed=0,
e3ffab
@@ -1024,8 +1074,12 @@ class test_service_allowed_to(Declarative):
e3ffab
                     dn=service1dn,
e3ffab
                     ipaallowedtoperform_read_keys_user=[user1],
e3ffab
                     ipaallowedtoperform_read_keys_group=[group1],
e3ffab
+                    ipaallowedtoperform_read_keys_host=[fqdn1],
e3ffab
+                    ipaallowedtoperform_read_keys_hostgroup=[hostgroup1],
e3ffab
                     ipaallowedtoperform_write_keys_user=[user1],
e3ffab
                     ipaallowedtoperform_write_keys_group=[group1, group2],
e3ffab
+                    ipaallowedtoperform_write_keys_host=[fqdn1],
e3ffab
+                    ipaallowedtoperform_write_keys_hostgroup=[hostgroup1],
e3ffab
                     krbprincipalname=[service1],
e3ffab
                     managedby_host=[fqdn1],
e3ffab
                 ),
e3ffab
@@ -1040,6 +1094,8 @@ class test_service_allowed_to(Declarative):
e3ffab
                 failed=dict(
e3ffab
                     ipaallowedtoperform_write_keys=dict(
e3ffab
                         group=[],
e3ffab
+                        host=[],
e3ffab
+                        hostgroup=[],
e3ffab
                         user=[[user2, u'This entry is not a member']],
e3ffab
                     ),
e3ffab
                 ),
e3ffab
@@ -1048,8 +1104,12 @@ class test_service_allowed_to(Declarative):
e3ffab
                     dn=service1dn,
e3ffab
                     ipaallowedtoperform_read_keys_user=[user1],
e3ffab
                     ipaallowedtoperform_read_keys_group=[group1],
e3ffab
+                    ipaallowedtoperform_read_keys_host=[fqdn1],
e3ffab
+                    ipaallowedtoperform_read_keys_hostgroup=[hostgroup1],
e3ffab
                     ipaallowedtoperform_write_keys_user=[user1],
e3ffab
                     ipaallowedtoperform_write_keys_group=[group1, group2],
e3ffab
+                    ipaallowedtoperform_write_keys_host=[fqdn1],
e3ffab
+                    ipaallowedtoperform_write_keys_hostgroup=[hostgroup1],
e3ffab
                     krbprincipalname=[service1],
e3ffab
                     managedby_host=[fqdn1],
e3ffab
                 ),
e3ffab
@@ -1064,6 +1124,8 @@ class test_service_allowed_to(Declarative):
e3ffab
                 failed=dict(
e3ffab
                     ipaallowedtoperform_write_keys=dict(
e3ffab
                         group=[],
e3ffab
+                        host=[],
e3ffab
+                        hostgroup=[],
e3ffab
                         user=[],
e3ffab
                     ),
e3ffab
                 ),
e3ffab
@@ -1072,8 +1134,12 @@ class test_service_allowed_to(Declarative):
e3ffab
                     dn=service1dn,
e3ffab
                     ipaallowedtoperform_read_keys_user=[user1],
e3ffab
                     ipaallowedtoperform_read_keys_group=[group1],
e3ffab
+                    ipaallowedtoperform_read_keys_host=[fqdn1],
e3ffab
+                    ipaallowedtoperform_read_keys_hostgroup=[hostgroup1],
e3ffab
                     ipaallowedtoperform_write_keys_user=[user1],
e3ffab
                     ipaallowedtoperform_write_keys_group=[group1],
e3ffab
+                    ipaallowedtoperform_write_keys_host=[fqdn1],
e3ffab
+                    ipaallowedtoperform_write_keys_hostgroup=[hostgroup1],
e3ffab
                     krbprincipalname=[service1],
e3ffab
                     managedby_host=[fqdn1],
e3ffab
                 ),
e3ffab
@@ -1091,8 +1157,12 @@ class test_service_allowed_to(Declarative):
e3ffab
                     has_keytab=False,
e3ffab
                     ipaallowedtoperform_read_keys_user=[user1],
e3ffab
                     ipaallowedtoperform_read_keys_group=[group1],
e3ffab
+                    ipaallowedtoperform_read_keys_host=[fqdn1],
e3ffab
+                    ipaallowedtoperform_read_keys_hostgroup=[hostgroup1],
e3ffab
                     ipaallowedtoperform_write_keys_user=[user1],
e3ffab
                     ipaallowedtoperform_write_keys_group=[group1],
e3ffab
+                    ipaallowedtoperform_write_keys_host=[fqdn1],
e3ffab
+                    ipaallowedtoperform_write_keys_hostgroup=[hostgroup1],
e3ffab
                     krbprincipalname=[service1],
e3ffab
                     managedby_host=[fqdn1],
e3ffab
                 ),
e3ffab
@@ -1110,8 +1180,12 @@ class test_service_allowed_to(Declarative):
e3ffab
                 result=dict(
e3ffab
                     ipaallowedtoperform_read_keys_user=[user1],
e3ffab
                     ipaallowedtoperform_read_keys_group=[group1],
e3ffab
+                    ipaallowedtoperform_read_keys_host=[fqdn1],
e3ffab
+                    ipaallowedtoperform_read_keys_hostgroup=[hostgroup1],
e3ffab
                     ipaallowedtoperform_write_keys_user=[user1],
e3ffab
                     ipaallowedtoperform_write_keys_group=[group1],
e3ffab
+                    ipaallowedtoperform_write_keys_host=[fqdn1],
e3ffab
+                    ipaallowedtoperform_write_keys_hostgroup=[hostgroup1],
e3ffab
                     ipakrbokasdelegate=True,
e3ffab
                     krbprincipalname=[service1],
e3ffab
                     krbticketflags=[u'1048704'],
e3ffab
-- 
e3ffab
2.1.0
e3ffab