diff options
-rw-r--r-- | ACI.txt | 4 | ||||
-rw-r--r-- | API.txt | 96 | ||||
-rw-r--r-- | VERSION | 4 | ||||
-rw-r--r-- | ipalib/plugins/baseldap.py | 17 | ||||
-rw-r--r-- | ipalib/plugins/host.py | 116 | ||||
-rw-r--r-- | ipalib/plugins/service.py | 134 |
6 files changed, 360 insertions, 11 deletions
@@ -95,6 +95,8 @@ aci: (targetattr = "userpassword")(targetfilter = "(objectclass=ipahost)")(versi dn: cn=computers,cn=accounts,dc=ipa,dc=example aci: (targetattr = "krblastpwdchange || krbprincipalkey")(targetfilter = "(objectclass=ipahost)")(version 3.0;acl "permission:System: Manage Host Keytab";allow (write) groupdn = "ldap:///cn=System: Manage Host Keytab,cn=permissions,cn=pbac,dc=ipa,dc=example";) dn: cn=computers,cn=accounts,dc=ipa,dc=example +aci: (targetattr = "createtimestamp || entryusn || ipaallowedtoperform;read_keys || ipaallowedtoperform;write_keys || modifytimestamp || objectclass")(targetfilter = "(objectclass=ipahost)")(version 3.0;acl "permission:System: Manage Host Keytab Permissions";allow (compare,read,search,write) groupdn = "ldap:///cn=System: Manage Host Keytab Permissions,cn=permissions,cn=pbac,dc=ipa,dc=example";) +dn: cn=computers,cn=accounts,dc=ipa,dc=example aci: (targetattr = "ipasshpubkey")(targetfilter = "(objectclass=ipahost)")(version 3.0;acl "permission:System: Manage Host SSH Public Keys";allow (write) groupdn = "ldap:///cn=System: Manage Host SSH Public Keys,cn=permissions,cn=pbac,dc=ipa,dc=example";) dn: cn=computers,cn=accounts,dc=ipa,dc=example aci: (targetattr = "description || ipaassignedidview || l || macaddress || nshardwareplatform || nshostlocation || nsosversion || userclass")(targetfilter = "(objectclass=ipahost)")(version 3.0;acl "permission:System: Modify Hosts";allow (write) groupdn = "ldap:///cn=System: Modify Hosts,cn=permissions,cn=pbac,dc=ipa,dc=example";) @@ -193,6 +195,8 @@ aci: (targetfilter = "(objectclass=ipaservice)")(version 3.0;acl "permission:Sys dn: cn=services,cn=accounts,dc=ipa,dc=example aci: (targetattr = "krblastpwdchange || krbprincipalkey")(targetfilter = "(objectclass=ipaservice)")(version 3.0;acl "permission:System: Manage Service Keytab";allow (write) groupdn = "ldap:///cn=System: Manage Service Keytab,cn=permissions,cn=pbac,dc=ipa,dc=example";) dn: cn=services,cn=accounts,dc=ipa,dc=example +aci: (targetattr = "createtimestamp || entryusn || ipaallowedtoperform;read_keys || ipaallowedtoperform;write_keys || modifytimestamp || objectclass")(targetfilter = "(objectclass=ipaservice)")(version 3.0;acl "permission:System: Manage Service Keytab Permissions";allow (compare,read,search,write) groupdn = "ldap:///cn=System: Manage Service Keytab Permissions,cn=permissions,cn=pbac,dc=ipa,dc=example";) +dn: cn=services,cn=accounts,dc=ipa,dc=example aci: (targetattr = "usercertificate")(targetfilter = "(objectclass=ipaservice)")(version 3.0;acl "permission:System: Modify Services";allow (write) groupdn = "ldap:///cn=System: Modify Services,cn=permissions,cn=pbac,dc=ipa,dc=example";) dn: cn=services,cn=accounts,dc=ipa,dc=example aci: (targetattr = "createtimestamp || entryusn || ipakrbauthzdata || ipakrbprincipalalias || ipauniqueid || krbcanonicalname || krblastpwdchange || krbobjectreferences || krbpasswordexpiration || krbprincipalaliases || krbprincipalexpiration || krbprincipalname || managedby || memberof || modifytimestamp || objectclass || usercertificate")(targetfilter = "(objectclass=ipaservice)")(version 3.0;acl "permission:System: Read Services";allow (compare,read,search) userdn = "ldap:///all";) @@ -1825,6 +1825,30 @@ option: Str('version?', exclude='webui') output: Output('completed', <type 'int'>, None) output: Output('failed', <type 'dict'>, None) output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None)) +command: host_allow_create_keytab +args: 1,6,3 +arg: Str('fqdn', attribute=True, cli_name='hostname', multivalue=False, primary_key=True, query=True, required=True) +option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui') +option: Str('group*', alwaysask=True, cli_name='groups', csv=True) +option: Flag('no_members', autofill=True, default=False, exclude='webui') +option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui') +option: Str('user*', alwaysask=True, cli_name='users', csv=True) +option: Str('version?', exclude='webui') +output: Output('completed', <type 'int'>, None) +output: Output('failed', <type 'dict'>, None) +output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None)) +command: host_allow_retrieve_keytab +args: 1,6,3 +arg: Str('fqdn', attribute=True, cli_name='hostname', multivalue=False, primary_key=True, query=True, required=True) +option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui') +option: Str('group*', alwaysask=True, cli_name='groups', csv=True) +option: Flag('no_members', autofill=True, default=False, exclude='webui') +option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui') +option: Str('user*', alwaysask=True, cli_name='users', csv=True) +option: Str('version?', exclude='webui') +output: Output('completed', <type 'int'>, None) +output: Output('failed', <type 'dict'>, None) +output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None)) command: host_del args: 1,3,3 arg: Str('fqdn', attribute=True, cli_name='hostname', multivalue=True, primary_key=True, query=True, required=True) @@ -1841,6 +1865,30 @@ option: Str('version?', exclude='webui') output: Output('result', <type 'bool'>, None) output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None) output: PrimaryKey('value', None, None) +command: host_disallow_create_keytab +args: 1,6,3 +arg: Str('fqdn', attribute=True, cli_name='hostname', multivalue=False, primary_key=True, query=True, required=True) +option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui') +option: Str('group*', alwaysask=True, cli_name='groups', csv=True) +option: Flag('no_members', autofill=True, default=False, exclude='webui') +option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui') +option: Str('user*', alwaysask=True, cli_name='users', csv=True) +option: Str('version?', exclude='webui') +output: Output('completed', <type 'int'>, None) +output: Output('failed', <type 'dict'>, None) +output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None)) +command: host_disallow_retrieve_keytab +args: 1,6,3 +arg: Str('fqdn', attribute=True, cli_name='hostname', multivalue=False, primary_key=True, query=True, required=True) +option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui') +option: Str('group*', alwaysask=True, cli_name='groups', csv=True) +option: Flag('no_members', autofill=True, default=False, exclude='webui') +option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui') +option: Str('user*', alwaysask=True, cli_name='users', csv=True) +option: Str('version?', exclude='webui') +output: Output('completed', <type 'int'>, None) +output: Output('failed', <type 'dict'>, None) +output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None)) command: host_find args: 1,34,4 arg: Str('criteria?', noextrawhitespace=False) @@ -3479,6 +3527,30 @@ option: Str('version?', exclude='webui') output: Output('completed', <type 'int'>, None) output: Output('failed', <type 'dict'>, None) output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None)) +command: service_allow_create_keytab +args: 1,6,3 +arg: Str('krbprincipalname', attribute=True, cli_name='principal', multivalue=False, primary_key=True, query=True, required=True) +option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui') +option: Str('group*', alwaysask=True, cli_name='groups', csv=True) +option: Flag('no_members', autofill=True, default=False, exclude='webui') +option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui') +option: Str('user*', alwaysask=True, cli_name='users', csv=True) +option: Str('version?', exclude='webui') +output: Output('completed', <type 'int'>, None) +output: Output('failed', <type 'dict'>, None) +output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None)) +command: service_allow_retrieve_keytab +args: 1,6,3 +arg: Str('krbprincipalname', attribute=True, cli_name='principal', multivalue=False, primary_key=True, query=True, required=True) +option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui') +option: Str('group*', alwaysask=True, cli_name='groups', csv=True) +option: Flag('no_members', autofill=True, default=False, exclude='webui') +option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui') +option: Str('user*', alwaysask=True, cli_name='users', csv=True) +option: Str('version?', exclude='webui') +output: Output('completed', <type 'int'>, None) +output: Output('failed', <type 'dict'>, None) +output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None)) command: service_del args: 1,2,3 arg: Str('krbprincipalname', attribute=True, cli_name='principal', multivalue=True, primary_key=True, query=True, required=True) @@ -3494,6 +3566,30 @@ option: Str('version?', exclude='webui') output: Output('result', <type 'bool'>, None) output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None) output: PrimaryKey('value', None, None) +command: service_disallow_create_keytab +args: 1,6,3 +arg: Str('krbprincipalname', attribute=True, cli_name='principal', multivalue=False, primary_key=True, query=True, required=True) +option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui') +option: Str('group*', alwaysask=True, cli_name='groups', csv=True) +option: Flag('no_members', autofill=True, default=False, exclude='webui') +option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui') +option: Str('user*', alwaysask=True, cli_name='users', csv=True) +option: Str('version?', exclude='webui') +output: Output('completed', <type 'int'>, None) +output: Output('failed', <type 'dict'>, None) +output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None)) +command: service_disallow_retrieve_keytab +args: 1,6,3 +arg: Str('krbprincipalname', attribute=True, cli_name='principal', multivalue=False, primary_key=True, query=True, required=True) +option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui') +option: Str('group*', alwaysask=True, cli_name='groups', csv=True) +option: Flag('no_members', autofill=True, default=False, exclude='webui') +option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui') +option: Str('user*', alwaysask=True, cli_name='users', csv=True) +option: Str('version?', exclude='webui') +output: Output('completed', <type 'int'>, None) +output: Output('failed', <type 'dict'>, None) +output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None)) command: service_find args: 1,11,4 arg: Str('criteria?', noextrawhitespace=False) @@ -90,5 +90,5 @@ IPA_DATA_VERSION=20100614120000 # # ######################################################## IPA_API_VERSION_MAJOR=2 -IPA_API_VERSION_MINOR=107 -# Last change: jcholast - add ca_is_enabled +IPA_API_VERSION_MINOR=108 +# Last change: pvoborni - manage authorization of keytab operations diff --git a/ipalib/plugins/baseldap.py b/ipalib/plugins/baseldap.py index e589a5321..375441c0f 100644 --- a/ipalib/plugins/baseldap.py +++ b/ipalib/plugins/baseldap.py @@ -494,6 +494,23 @@ def host_is_master(ldap, fqdn): return +def add_missing_object_class(ldap, objectclass, dn, entry_attrs=None, update=True): + """ + Add object class if missing into entry. Fetches entry if not passed. Updates + the entry by default. + + Returns the entry + """ + + if not entry_attrs: + entry_attrs = ldap.get_entry(dn, ['objectclass']) + if (objectclass.lower() not in (o.lower() for o in entry_attrs['objectclass'])): + entry_attrs['objectclass'].append(objectclass) + if update: + ldap.update_entry(entry_attrs) + return entry_attrs + + class LDAPObject(Object): """ Object representing a LDAP entry. 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) diff --git a/ipalib/plugins/service.py b/ipalib/plugins/service.py index 55f412625..2f7035444 100644 --- a/ipalib/plugins/service.py +++ b/ipalib/plugins/service.py @@ -86,7 +86,10 @@ EXAMPLES: Request a certificate for an IPA service: ipa cert-request --principal=HTTP/web.example.com example.csr - +""") + _(""" + Allow user to create a keytab: + ipa service-allow-create-keytab HTTP/web.example.com --users=tuser1 +""") + _(""" Generate and retrieve a keytab for an IPA service: ipa-getkeytab -s ipa.example.com -p HTTP/web.example.com -k /etc/httpd/httpd.keytab @@ -127,7 +130,25 @@ output_params = ( ), Str('revocation_reason?', label=_('Revocation reason'), - ) + ), + 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'), + ), ) ticket_flags_params = ( @@ -290,6 +311,23 @@ def set_kerberos_attrs(entry_attrs, options): if name in options or all_opt: entry_attrs[name] = bool(ticket_flags & value) +def rename_ipaallowedtoperform_from_ldap(entry_attrs, options): + if options.get('raw', False): + return + + for subtype in ('read_keys', 'write_keys'): + name = 'ipaallowedtoperform;%s' % subtype + if name in entry_attrs: + new_name = 'ipaallowedtoperform_%s' % subtype + entry_attrs[new_name] = entry_attrs.pop(name) + +def rename_ipaallowedtoperform_to_ldap(entry_attrs): + for subtype in ('read_keys', 'write_keys'): + name = 'ipaallowedtoperform_%s' % subtype + if name in entry_attrs: + new_name = 'ipaallowedtoperform;%s' % subtype + entry_attrs[new_name] = entry_attrs.pop(name) + @register() class service(LDAPObject): """ @@ -302,19 +340,24 @@ class service(LDAPObject): 'krbprincipal', 'krbprincipalaux', 'krbticketpolicyaux', 'ipaobject', 'ipaservice', 'pkiuser' ] - possible_objectclasses = ['ipakrbprincipal'] + possible_objectclasses = ['ipakrbprincipal', 'ipaallowedoperations'] permission_filter_objectclasses = ['ipaservice'] - search_attributes = ['krbprincipalname', 'managedby', 'ipakrbauthzdata'] + search_attributes = ['krbprincipalname', 'managedby', 'ipakrbauthzdata', + 'ipaallowedtoperform'] default_attributes = ['krbprincipalname', 'usercertificate', 'managedby', - 'ipakrbauthzdata', 'memberof'] + 'ipakrbauthzdata', 'memberof', 'ipaallowedtoperform'] uuid_attribute = 'ipauniqueid' attribute_members = { 'managedby': ['host'], 'memberof': ['role'], + 'ipaallowedtoperform_read_keys': ['user', 'group'], + 'ipaallowedtoperform_write_keys': ['user', 'group'], } bindable = True relationships = { 'managedby': ('Managed by', 'man_by_', 'not_man_by_'), + '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 = [('krbprincipalkey', 'has_keytab')] managed_permissions = { @@ -346,6 +389,14 @@ class service(LDAPObject): ], 'default_privileges': {'Service Administrators', 'Host Administrators'}, }, + 'System: Manage Service Keytab Permissions': { + 'ipapermright': {'read', 'search', 'compare', 'write'}, + 'ipapermdefaultattr': { + 'ipaallowedtoperform;write_keys', + 'ipaallowedtoperform;read_keys', 'objectclass' + }, + 'default_privileges': {'Service Administrators', 'Host Administrators'}, + }, 'System: Modify Services': { 'ipapermright': {'write'}, 'ipapermdefaultattr': {'usercertificate'}, @@ -469,6 +520,7 @@ class service_add(LDAPCreate): def post_callback(self, ldap, dn, entry_attrs, *keys, **options): set_kerberos_attrs(entry_attrs, options) + rename_ipaallowedtoperform_from_ldap(entry_attrs, options) return dn @@ -561,6 +613,7 @@ class service_mod(LDAPUpdate): assert isinstance(dn, DN) set_certificate_attrs(entry_attrs) set_kerberos_attrs(entry_attrs, options) + rename_ipaallowedtoperform_from_ldap(entry_attrs, options) return dn @@ -598,6 +651,7 @@ class service_find(LDAPSearch): self.obj.get_password_attributes(ldap, entry_attrs.dn, entry_attrs) set_certificate_attrs(entry_attrs) set_kerberos_attrs(entry_attrs, options) + rename_ipaallowedtoperform_from_ldap(entry_attrs, options) return truncated @@ -620,6 +674,7 @@ class service_show(LDAPRetrieve): set_certificate_attrs(entry_attrs) set_kerberos_attrs(entry_attrs, options) + rename_ipaallowedtoperform_from_ldap(entry_attrs, options) return dn @@ -654,6 +709,75 @@ class service_remove_host(LDAPRemoveMember): has_output_params = LDAPRemoveMember.has_output_params + output_params +@register() +class service_allow_retrieve_keytab(LDAPAddMember): + __doc__ = _('Allow users or groups to retrieve a keytab of this service.') + member_attributes = ['ipaallowedtoperform_read_keys'] + has_output_params = LDAPAddMember.has_output_params + 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 service_disallow_retrieve_keytab(LDAPRemoveMember): + __doc__ = _('Disallow users or groups to retrieve a keytab of this service.') + member_attributes = ['ipaallowedtoperform_read_keys'] + has_output_params = LDAPRemoveMember.has_output_params + 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 service_allow_create_keytab(LDAPAddMember): + __doc__ = _('Allow users or groups to create a keytab of this service.') + member_attributes = ['ipaallowedtoperform_write_keys'] + has_output_params = LDAPAddMember.has_output_params + 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 service_disallow_create_keytab(LDAPRemoveMember): + __doc__ = _('Disallow users or groups to create a keytab of this service.') + member_attributes = ['ipaallowedtoperform_write_keys'] + has_output_params = LDAPRemoveMember.has_output_params + 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 service_disable(LDAPQuery): |