From 59ee6314afc7f0f7735ab1349caa970f0f00d78a Mon Sep 17 00:00:00 2001 From: Petr Vobornik Date: Thu, 2 Oct 2014 16:57:08 +0200 Subject: keytab manipulation permission management Adds new API: ipa host-allow-retrieve-keytab HOSTNAME --users=STR --groups STR ipa host-disallow-retrieve-keytab HOSTNAME --users=STR --groups STR ipa host-allow-create-keytab HOSTNAME --users=STR --groups STR ipa host-disallow-create-keytab HOSTNAME --users=STR --groups STR ipa service-allow-retrieve-keytab PRINCIPAL --users=STR --groups STR ipa service-disallow-retrieve-keytab PRINCIPAL --users=STR --groups STR ipa service-allow-create-keytab PRINCIPAL --users=STR --groups STR ipa service-disallow-create-keytab PRINCIPAL --users=STR --groups STR these methods add or remove user or group DNs in `ipaallowedtoperform` attr with `read_keys` and `write_keys` subtypes. service|host-mod|show outputs these attrs only with --all option as: Users allowed to retrieve keytab: user1 Groups allowed to retrieve keytab: group1 Users allowed to create keytab: user1 Groups allowed to create keytab: group1 Adding of object class is implemented as a reusable method since this code is used on many places and most likely will be also used in new features. Older code may be refactored later. https://fedorahosted.org/freeipa/ticket/4419 Reviewed-By: Jan Cholasta --- ipalib/plugins/host.py | 116 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 112 insertions(+), 4 deletions(-) (limited to 'ipalib/plugins/host.py') diff --git a/ipalib/plugins/host.py b/ipalib/plugins/host.py index 91fb75b87..c4d4bdf64 100644 --- a/ipalib/plugins/host.py +++ b/ipalib/plugins/host.py @@ -28,10 +28,11 @@ from ipalib.plugins.baseldap import (LDAPQuery, LDAPObject, LDAPCreate, LDAPDelete, LDAPUpdate, LDAPSearch, LDAPRetrieve, LDAPAddMember, LDAPRemoveMember, host_is_master, - pkey_to_value) + pkey_to_value, add_missing_object_class) from ipalib.plugins.service import (split_principal, validate_certificate, set_certificate_attrs, ticket_flags_params, update_krbticketflags, - set_kerberos_attrs) + set_kerberos_attrs, rename_ipaallowedtoperform_from_ldap, + rename_ipaallowedtoperform_to_ldap) from ipalib.plugins.dns import (dns_container_exists, _record_types, add_records_for_host_validation, add_records_for_host, get_reverse_zone) @@ -102,6 +103,9 @@ EXAMPLES: """) + _(""" Add a host that can manage this host's keytab and certificate: ipa host-add-managedby --hosts=test2 test +""") + _(""" + Allow user to create a keytab: + ipa host-allow-create-keytab test2 --users=tuser1 """) register = Registry() @@ -201,6 +205,24 @@ host_output_params = ( Str('sshpubkeyfp*', label=_('SSH public key fingerprint'), ), + Str('ipaallowedtoperform_read_keys_user', + label=_('Users allowed to retrieve keytab'), + ), + Str('ipaallowedtoperform_read_keys_group', + label=_('Groups allowed to retrieve keytab'), + ), + Str('ipaallowedtoperform_write_keys_user', + label=_('Users allowed to create keytab'), + ), + Str('ipaallowedtoperform_write_keys_group', + label=_('Groups allowed to create keytab'), + ), + Str('ipaallowedtoperform_read_keys', + label=_('Failed allowed to retrieve keytab'), + ), + Str('ipaallowedtoperform_write_keys', + label=_('Failed allowed to create keytab'), + ), ) @@ -241,17 +263,18 @@ class host(LDAPObject): object_name = _('host') object_name_plural = _('hosts') object_class = ['ipaobject', 'nshost', 'ipahost', 'pkiuser', 'ipaservice'] + possible_objectclasses = ['ipaallowedoperations'] permission_filter_objectclasses = ['ipahost'] # object_class_config = 'ipahostobjectclasses' search_attributes = [ 'fqdn', 'description', 'l', 'nshostlocation', 'krbprincipalname', - 'nshardwareplatform', 'nsosversion', 'managedby' + 'nshardwareplatform', 'nsosversion', 'managedby', 'ipaallowedtoperform' ] default_attributes = [ 'fqdn', 'description', 'l', 'nshostlocation', 'krbprincipalname', 'nshardwareplatform', 'nsosversion', 'usercertificate', 'memberof', 'managedby', 'memberindirect', 'memberofindirect', 'macaddress', - 'userclass' + 'userclass', 'ipaallowedtoperform' ] uuid_attribute = 'ipauniqueid' attribute_members = { @@ -261,6 +284,8 @@ class host(LDAPObject): 'managing': ['host'], 'memberofindirect': ['hostgroup', 'netgroup', 'role', 'hbacrule', 'sudorule'], + 'ipaallowedtoperform_read_keys': ['user', 'group'], + 'ipaallowedtoperform_write_keys': ['user', 'group'], } bindable = True relationships = { @@ -268,6 +293,8 @@ class host(LDAPObject): 'enrolledby': ('Enrolled by', 'enroll_by_', 'not_enroll_by_'), 'managedby': ('Managed by', 'man_by_', 'not_man_by_'), 'managing': ('Managing', 'man_', 'not_man_'), + 'ipaallowedtoperform_read_keys': ('Allow to retrieve keytab by', 'retrieve_keytab_by_', 'not_retrieve_keytab_by_'), + 'ipaallowedtoperform_write_keys': ('Allow to create keytab by', 'write_keytab_by_', 'not_write_keytab_by'), } password_attributes = [('userpassword', 'has_password'), ('krbprincipalkey', 'has_keytab')] @@ -344,6 +371,14 @@ class host(LDAPObject): ], 'default_privileges': {'Host Administrators', 'Host Enrollment'}, }, + 'System: Manage Host Keytab Permissions': { + 'ipapermright': {'read', 'search', 'compare', 'write'}, + 'ipapermdefaultattr': { + 'ipaallowedtoperform;write_keys', + 'ipaallowedtoperform;read_keys', 'objectclass' + }, + 'default_privileges': {'Host Administrators'}, + }, 'System: Modify Hosts': { 'ipapermright': {'write'}, 'ipapermdefaultattr': { @@ -629,6 +664,7 @@ class host_add(LDAPCreate): ) set_certificate_attrs(entry_attrs) set_kerberos_attrs(entry_attrs, options) + rename_ipaallowedtoperform_from_ldap(entry_attrs, options) if options.get('all', False): entry_attrs['managing'] = self.obj.get_managed_hosts(dn) @@ -888,6 +924,7 @@ class host_mod(LDAPUpdate): entry_attrs['randompassword'] = unicode(getattr(context, 'randompassword')) set_certificate_attrs(entry_attrs) set_kerberos_attrs(entry_attrs, options) + rename_ipaallowedtoperform_from_ldap(entry_attrs, options) self.obj.get_password_attributes(ldap, dn, entry_attrs) if entry_attrs['has_password']: # If an OTP is set there is no keytab, at least not one @@ -974,6 +1011,7 @@ class host_find(LDAPSearch): for entry_attrs in entries: set_certificate_attrs(entry_attrs) set_kerberos_attrs(entry_attrs, options) + rename_ipaallowedtoperform_from_ldap(entry_attrs, options) self.obj.get_password_attributes(ldap, entry_attrs.dn, entry_attrs) self.obj.suppress_netgroup_memberof(ldap, entry_attrs) if entry_attrs['has_password']: @@ -1012,6 +1050,7 @@ class host_show(LDAPRetrieve): set_certificate_attrs(entry_attrs) set_kerberos_attrs(entry_attrs, options) + rename_ipaallowedtoperform_from_ldap(entry_attrs, options) if options.get('all', False): entry_attrs['managing'] = self.obj.get_managed_hosts(dn) @@ -1159,3 +1198,72 @@ class host_remove_managedby(LDAPRemoveMember): self.obj.suppress_netgroup_memberof(ldap, entry_attrs) return (completed, dn) + +@register() +class host_allow_retrieve_keytab(LDAPAddMember): + __doc__ = _('Allow users or groups to retrieve a keytab of this host.') + member_attributes = ['ipaallowedtoperform_read_keys'] + has_output_params = LDAPAddMember.has_output_params + host_output_params + + def pre_callback(self, ldap, dn, found, not_found, *keys, **options): + rename_ipaallowedtoperform_to_ldap(found) + rename_ipaallowedtoperform_to_ldap(not_found) + add_missing_object_class(ldap, u'ipaallowedoperations', dn) + return dn + + def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options): + rename_ipaallowedtoperform_from_ldap(entry_attrs, options) + rename_ipaallowedtoperform_from_ldap(failed, options) + return (completed, dn) + + +@register() +class host_disallow_retrieve_keytab(LDAPRemoveMember): + __doc__ = _('Disallow users or groups to retrieve a keytab of this host.') + member_attributes = ['ipaallowedtoperform_read_keys'] + has_output_params = LDAPRemoveMember.has_output_params + host_output_params + + def pre_callback(self, ldap, dn, found, not_found, *keys, **options): + rename_ipaallowedtoperform_to_ldap(found) + rename_ipaallowedtoperform_to_ldap(not_found) + return dn + + def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options): + rename_ipaallowedtoperform_from_ldap(entry_attrs, options) + rename_ipaallowedtoperform_from_ldap(failed, options) + return (completed, dn) + + +@register() +class host_allow_create_keytab(LDAPAddMember): + __doc__ = _('Allow users or groups to create a keytab of this host.') + member_attributes = ['ipaallowedtoperform_write_keys'] + has_output_params = LDAPAddMember.has_output_params + host_output_params + + def pre_callback(self, ldap, dn, found, not_found, *keys, **options): + rename_ipaallowedtoperform_to_ldap(found) + rename_ipaallowedtoperform_to_ldap(not_found) + add_missing_object_class(ldap, u'ipaallowedoperations', dn) + return dn + + def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options): + rename_ipaallowedtoperform_from_ldap(entry_attrs, options) + rename_ipaallowedtoperform_from_ldap(failed, options) + return (completed, dn) + + +@register() +class host_disallow_create_keytab(LDAPRemoveMember): + __doc__ = _('Disallow users or groups to create a keytab of this host.') + member_attributes = ['ipaallowedtoperform_write_keys'] + has_output_params = LDAPRemoveMember.has_output_params + host_output_params + + def pre_callback(self, ldap, dn, found, not_found, *keys, **options): + rename_ipaallowedtoperform_to_ldap(found) + rename_ipaallowedtoperform_to_ldap(not_found) + return dn + + def post_callback(self, ldap, completed, failed, dn, entry_attrs, *keys, **options): + rename_ipaallowedtoperform_from_ldap(entry_attrs, options) + rename_ipaallowedtoperform_from_ldap(failed, options) + return (completed, dn) -- cgit