diff options
-rw-r--r-- | ACI.txt | 6 | ||||
-rw-r--r-- | API.txt | 93 | ||||
-rw-r--r-- | VERSION | 4 | ||||
-rw-r--r-- | ipalib/util.py | 71 | ||||
-rw-r--r-- | ipaserver/plugins/baseuser.py | 39 | ||||
-rw-r--r-- | ipaserver/plugins/host.py | 51 | ||||
-rw-r--r-- | ipaserver/plugins/service.py | 53 | ||||
-rw-r--r-- | ipaserver/plugins/user.py | 24 |
8 files changed, 299 insertions, 42 deletions
@@ -135,6 +135,8 @@ aci: (targetattr = "krblastpwdchange || krbprincipalkey")(targetfilter = "(&(!(m 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 = "krbcanonicalname || krbprincipalname")(targetfilter = "(objectclass=ipahost)")(version 3.0;acl "permission:System: Manage Host Principals";allow (write) groupdn = "ldap:///cn=System: Manage Host Principals,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 || krbprincipalauthind || 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";) @@ -249,6 +251,8 @@ aci: (targetattr = "krblastpwdchange || krbprincipalkey")(targetfilter = "(objec 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 = "krbcanonicalname || krbprincipalname")(targetfilter = "(objectclass=ipaservice)")(version 3.0;acl "permission:System: Manage Service Principals";allow (write) groupdn = "ldap:///cn=System: Manage Service Principals,cn=permissions,cn=pbac,dc=ipa,dc=example";) +dn: cn=services,cn=accounts,dc=ipa,dc=example aci: (targetattr = "krbprincipalauthind || 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 || krbprincipalauthind || 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";) @@ -335,6 +339,8 @@ aci: (targetattr = "krbprincipalkey || passwordhistory || sambalmpassword || sam dn: cn=users,cn=accounts,dc=ipa,dc=example aci: (targetattr = "usercertificate")(targetfilter = "(objectclass=posixaccount)")(version 3.0;acl "permission:System: Manage User Certificates";allow (write) groupdn = "ldap:///cn=System: Manage User Certificates,cn=permissions,cn=pbac,dc=ipa,dc=example";) dn: cn=users,cn=accounts,dc=ipa,dc=example +aci: (targetattr = "krbcanonicalname || krbprincipalname")(targetfilter = "(objectclass=posixaccount)")(version 3.0;acl "permission:System: Manage User Principals";allow (write) groupdn = "ldap:///cn=System: Manage User Principals,cn=permissions,cn=pbac,dc=ipa,dc=example";) +dn: cn=users,cn=accounts,dc=ipa,dc=example aci: (targetattr = "ipasshpubkey")(targetfilter = "(objectclass=posixaccount)")(version 3.0;acl "permission:System: Manage User SSH Public Keys";allow (write) groupdn = "ldap:///cn=System: Manage User SSH Public Keys,cn=permissions,cn=pbac,dc=ipa,dc=example";) dn: cn=users,cn=accounts,dc=ipa,dc=example aci: (targetattr = "businesscategory || carlicense || cn || departmentnumber || description || displayname || employeenumber || employeetype || facsimiletelephonenumber || gecos || givenname || homephone || inetuserhttpurl || initials || l || labeleduri || loginshell || mail || manager || mepmanagedentry || mobile || objectclass || ou || pager || postalcode || preferredlanguage || roomnumber || secretary || seealso || sn || st || street || telephonenumber || title || userclass")(targetfilter = "(objectclass=posixaccount)")(version 3.0;acl "permission:System: Modify Users";allow (write) groupdn = "ldap:///cn=System: Modify Users,cn=permissions,cn=pbac,dc=ipa,dc=example";) @@ -2310,6 +2310,17 @@ option: Str('version?') output: Output('completed', type=[<type 'int'>]) output: Output('failed', type=[<type 'dict'>]) output: Entry('result') +command: host_add_principal/1 +args: 2,4,3 +arg: Str('fqdn', cli_name='hostname') +arg: Principal('krbprincipalname+', alwaysask=True) +option: Flag('all', autofill=True, cli_name='all', default=False) +option: Flag('no_members', autofill=True, default=False) +option: Flag('raw', autofill=True, cli_name='raw', default=False) +option: Str('version?') +output: Entry('result') +output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>]) +output: PrimaryKey('value') command: host_allow_create_keytab/1 args: 1,8,3 arg: Str('fqdn', cli_name='hostname') @@ -2436,7 +2447,7 @@ option: Bool('ipakrbokasdelegate?', autofill=False, cli_name='ok_as_delegate') option: Bool('ipakrbrequirespreauth?', autofill=False, cli_name='requires_pre_auth') option: Str('ipasshpubkey*', autofill=False, cli_name='sshpubkey') option: Str('krbprincipalauthind*', autofill=False, cli_name='auth_ind') -option: Principal('krbprincipalname?', cli_name='principalname') +option: Principal('krbprincipalname*', autofill=False) option: Str('l?', autofill=False, cli_name='locality') option: Str('macaddress*', autofill=False) option: Flag('no_members', autofill=True, default=False) @@ -2477,6 +2488,17 @@ option: Str('version?') output: Output('completed', type=[<type 'int'>]) output: Output('failed', type=[<type 'dict'>]) output: Entry('result') +command: host_remove_principal/1 +args: 2,4,3 +arg: Str('fqdn', cli_name='hostname') +arg: Principal('krbprincipalname+', alwaysask=True) +option: Flag('all', autofill=True, cli_name='all', default=False) +option: Flag('no_members', autofill=True, default=False) +option: Flag('raw', autofill=True, cli_name='raw', default=False) +option: Str('version?') +output: Entry('result') +output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>]) +output: PrimaryKey('value') command: host_show/1 args: 1,6,3 arg: Str('fqdn', cli_name='hostname') @@ -4309,6 +4331,17 @@ option: Str('version?') output: Output('completed', type=[<type 'int'>]) output: Output('failed', type=[<type 'dict'>]) output: Entry('result') +command: service_add_principal/1 +args: 2,4,3 +arg: Principal('krbcanonicalname', cli_name='canonical_principal') +arg: Principal('krbprincipalname+', alwaysask=True, cli_name='principal') +option: Flag('all', autofill=True, cli_name='all', default=False) +option: Flag('no_members', autofill=True, default=False) +option: Flag('raw', autofill=True, cli_name='raw', default=False) +option: Str('version?') +output: Entry('result') +output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>]) +output: PrimaryKey('value') command: service_allow_create_keytab/1 args: 1,8,3 arg: Principal('krbcanonicalname', cli_name='canonical_principal') @@ -4387,7 +4420,7 @@ option: Flag('all', autofill=True, cli_name='all', default=False) option: StrEnum('ipakrbauthzdata*', autofill=False, cli_name='pac_type', values=[u'MS-PAC', u'PAD', u'NONE']) option: Principal('krbcanonicalname?', autofill=False, cli_name='canonical_principal') option: Str('krbprincipalauthind*', autofill=False, cli_name='auth_ind') -option: Principal('krbprincipalname?', autofill=False, cli_name='principal') +option: Principal('krbprincipalname*', autofill=False, cli_name='principal') option: Str('man_by_host*', cli_name='man_by_hosts') option: Flag('no_members', autofill=True, default=True) option: Str('not_man_by_host*', cli_name='not_man_by_hosts') @@ -4401,7 +4434,7 @@ output: ListOfEntries('result') output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>]) output: Output('truncated', type=[<type 'bool'>]) command: service_mod/1 -args: 1,13,3 +args: 1,14,3 arg: Principal('krbcanonicalname', cli_name='canonical_principal') option: Str('addattr*', cli_name='addattr') option: Flag('all', autofill=True, cli_name='all', default=False) @@ -4410,6 +4443,7 @@ option: StrEnum('ipakrbauthzdata*', autofill=False, cli_name='pac_type', values= option: Bool('ipakrbokasdelegate?', autofill=False, cli_name='ok_as_delegate') option: Bool('ipakrbrequirespreauth?', autofill=False, cli_name='requires_pre_auth') option: Str('krbprincipalauthind*', autofill=False, cli_name='auth_ind') +option: Principal('krbprincipalname*', autofill=False, cli_name='principal') option: Flag('no_members', autofill=True, default=False) option: Flag('raw', autofill=True, cli_name='raw', default=False) option: Flag('rights', autofill=True, default=False) @@ -4441,6 +4475,17 @@ option: Str('version?') output: Output('completed', type=[<type 'int'>]) output: Output('failed', type=[<type 'dict'>]) output: Entry('result') +command: service_remove_principal/1 +args: 2,4,3 +arg: Principal('krbcanonicalname', cli_name='canonical_principal') +arg: Principal('krbprincipalname+', alwaysask=True, cli_name='principal') +option: Flag('all', autofill=True, cli_name='all', default=False) +option: Flag('no_members', autofill=True, default=False) +option: Flag('raw', autofill=True, cli_name='raw', default=False) +option: Str('version?') +output: Entry('result') +output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>]) +output: PrimaryKey('value') command: service_show/1 args: 1,6,3 arg: Principal('krbcanonicalname', cli_name='canonical_principal') @@ -4647,7 +4692,7 @@ option: Str('ipatokenradiusconfiglink?', cli_name='radius') option: Str('ipatokenradiususername?', cli_name='radius_username') option: StrEnum('ipauserauthtype*', cli_name='user_auth_type', values=[u'password', u'radius', u'otp']) option: DateTime('krbprincipalexpiration?', cli_name='principal_expiration') -option: Principal('krbprincipalname?', autofill=True, cli_name='principal') +option: Principal('krbprincipalname*', autofill=True, cli_name='principal') option: Str('l?', cli_name='city') option: Str('loginshell?', cli_name='shell') option: Str('mail*', cli_name='email') @@ -4718,7 +4763,7 @@ option: Str('ipatokenradiusconfiglink?', autofill=False, cli_name='radius') option: Str('ipatokenradiususername?', autofill=False, cli_name='radius_username') option: StrEnum('ipauserauthtype*', autofill=False, cli_name='user_auth_type', values=[u'password', u'radius', u'otp']) option: DateTime('krbprincipalexpiration?', autofill=False, cli_name='principal_expiration') -option: Principal('krbprincipalname?', autofill=False, cli_name='principal') +option: Principal('krbprincipalname*', autofill=False, cli_name='principal') option: Str('l?', autofill=False, cli_name='city') option: Str('loginshell?', autofill=False, cli_name='shell') option: Str('mail*', autofill=False, cli_name='email') @@ -4754,7 +4799,7 @@ output: ListOfEntries('result') output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>]) output: Output('truncated', type=[<type 'bool'>]) command: stageuser_mod/1 -args: 1,45,3 +args: 1,46,3 arg: Str('uid', cli_name='login') option: Str('addattr*', cli_name='addattr') option: Flag('all', autofill=True, cli_name='all', default=False) @@ -4776,6 +4821,7 @@ option: Str('ipatokenradiusconfiglink?', autofill=False, cli_name='radius') option: Str('ipatokenradiususername?', autofill=False, cli_name='radius_username') option: StrEnum('ipauserauthtype*', autofill=False, cli_name='user_auth_type', values=[u'password', u'radius', u'otp']) option: DateTime('krbprincipalexpiration?', autofill=False, cli_name='principal_expiration') +option: Principal('krbprincipalname*', autofill=False, cli_name='principal') option: Str('l?', autofill=False, cli_name='city') option: Str('loginshell?', autofill=False, cli_name='shell') option: Str('mail*', autofill=False, cli_name='email') @@ -5634,7 +5680,7 @@ option: Str('ipatokenradiusconfiglink?', cli_name='radius') option: Str('ipatokenradiususername?', cli_name='radius_username') option: StrEnum('ipauserauthtype*', cli_name='user_auth_type', values=[u'password', u'radius', u'otp']) option: DateTime('krbprincipalexpiration?', cli_name='principal_expiration') -option: Principal('krbprincipalname?', autofill=True, cli_name='principal') +option: Principal('krbprincipalname*', autofill=True, cli_name='principal') option: Str('l?', cli_name='city') option: Str('loginshell?', cli_name='shell') option: Str('mail*', cli_name='email') @@ -5685,6 +5731,17 @@ option: Str('version?') output: Output('completed', type=[<type 'int'>]) output: Output('failed', type=[<type 'dict'>]) output: Entry('result') +command: user_add_principal/1 +args: 2,4,3 +arg: Str('uid', cli_name='login') +arg: Principal('krbprincipalname+', alwaysask=True, autofill=True, cli_name='principal') +option: Flag('all', autofill=True, cli_name='all', default=False) +option: Flag('no_members', autofill=True, default=False) +option: Flag('raw', autofill=True, cli_name='raw', default=False) +option: Str('version?') +output: Entry('result') +output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>]) +output: PrimaryKey('value') command: user_del/1 args: 1,3,3 arg: Str('uid+', cli_name='login') @@ -5733,7 +5790,7 @@ option: Str('ipatokenradiusconfiglink?', autofill=False, cli_name='radius') option: Str('ipatokenradiususername?', autofill=False, cli_name='radius_username') option: StrEnum('ipauserauthtype*', autofill=False, cli_name='user_auth_type', values=[u'password', u'radius', u'otp']) option: DateTime('krbprincipalexpiration?', autofill=False, cli_name='principal_expiration') -option: Principal('krbprincipalname?', autofill=False, cli_name='principal') +option: Principal('krbprincipalname*', autofill=False, cli_name='principal') option: Str('l?', autofill=False, cli_name='city') option: Str('loginshell?', autofill=False, cli_name='shell') option: Str('mail*', autofill=False, cli_name='email') @@ -5772,7 +5829,7 @@ output: ListOfEntries('result') output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>]) output: Output('truncated', type=[<type 'bool'>]) command: user_mod/1 -args: 1,46,3 +args: 1,47,3 arg: Str('uid', cli_name='login') option: Str('addattr*', cli_name='addattr') option: Flag('all', autofill=True, cli_name='all', default=False) @@ -5794,6 +5851,7 @@ option: Str('ipatokenradiusconfiglink?', autofill=False, cli_name='radius') option: Str('ipatokenradiususername?', autofill=False, cli_name='radius_username') option: StrEnum('ipauserauthtype*', autofill=False, cli_name='user_auth_type', values=[u'password', u'radius', u'otp']) option: DateTime('krbprincipalexpiration?', autofill=False, cli_name='principal_expiration') +option: Principal('krbprincipalname*', autofill=False, cli_name='principal') option: Str('l?', autofill=False, cli_name='city') option: Str('loginshell?', autofill=False, cli_name='shell') option: Str('mail*', autofill=False, cli_name='email') @@ -5845,6 +5903,17 @@ option: Str('version?') output: Output('completed', type=[<type 'int'>]) output: Output('failed', type=[<type 'dict'>]) output: Entry('result') +command: user_remove_principal/1 +args: 2,4,3 +arg: Str('uid', cli_name='login') +arg: Principal('krbprincipalname+', alwaysask=True, autofill=True, cli_name='principal') +option: Flag('all', autofill=True, cli_name='all', default=False) +option: Flag('no_members', autofill=True, default=False) +option: Flag('raw', autofill=True, cli_name='raw', default=False) +option: Str('version?') +output: Entry('result') +output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>]) +output: PrimaryKey('value') command: user_show/1 args: 1,6,3 arg: Str('uid', cli_name='login') @@ -6322,6 +6391,7 @@ default: host/1 default: host_add/1 default: host_add_cert/1 default: host_add_managedby/1 +default: host_add_principal/1 default: host_allow_create_keytab/1 default: host_allow_retrieve_keytab/1 default: host_del/1 @@ -6332,6 +6402,7 @@ default: host_find/1 default: host_mod/1 default: host_remove_cert/1 default: host_remove_managedby/1 +default: host_remove_principal/1 default: host_show/1 default: hostgroup/1 default: hostgroup_add/1 @@ -6491,6 +6562,7 @@ default: service/1 default: service_add/1 default: service_add_cert/1 default: service_add_host/1 +default: service_add_principal/1 default: service_allow_create_keytab/1 default: service_allow_retrieve_keytab/1 default: service_del/1 @@ -6501,6 +6573,7 @@ default: service_find/1 default: service_mod/1 default: service_remove_cert/1 default: service_remove_host/1 +default: service_remove_principal/1 default: service_show/1 default: servicedelegationrule/1 default: servicedelegationrule_add/1 @@ -6605,6 +6678,7 @@ default: user/1 default: user_add/1 default: user_add_cert/1 default: user_add_manager/1 +default: user_add_principal/1 default: user_del/1 default: user_disable/1 default: user_enable/1 @@ -6612,6 +6686,7 @@ default: user_find/1 default: user_mod/1 default: user_remove_cert/1 default: user_remove_manager/1 +default: user_remove_principal/1 default: user_show/1 default: user_stage/1 default: user_status/1 @@ -90,5 +90,5 @@ IPA_DATA_VERSION=20100614120000 # # ######################################################## IPA_API_VERSION_MAJOR=2 -IPA_API_VERSION_MINOR=207 -# Last change: mbabinsk: Make framework consider krbcanonicalname as service primary key +IPA_API_VERSION_MINOR=208 +# Last change: mbabinsk: Provide API for management of host, service, and user principal aliases diff --git a/ipalib/util.py b/ipalib/util.py index 67865eb04..d101514ca 100644 --- a/ipalib/util.py +++ b/ipalib/util.py @@ -912,3 +912,74 @@ def set_krbcanonicalname(entry_attrs): if ('krbprincipalname' in entry_attrs and 'krbcanonicalname' not in entry_attrs): entry_attrs['krbcanonicalname'] = entry_attrs['krbprincipalname'] + + +def ensure_last_krbprincipalname(ldap, entry_attrs, *keys): + """ + ensure that the LDAP entry has at least one value of krbprincipalname + and that this value is equal to krbcanonicalname + + :param ldap: LDAP connection object + :param entry_attrs: LDAP entry made prior to update + :param options: command options + """ + entry = ldap.get_entry( + entry_attrs.dn, ['krbcanonicalname', 'krbprincipalname']) + + krbcanonicalname = entry.single_value.get('krbcanonicalname', None) + + if krbcanonicalname in keys[-1]: + raise errors.ValidationError( + name='krbprincipalname', + error=_('at least one value equal to the canonical ' + 'principal name must be present') + ) + + +def ensure_krbcanonicalname_set(ldap, entry_attrs): + old_entry = ldap.get_entry( + entry_attrs.dn, + ['krbcanonicalname', 'krbprincipalname', 'objectclass']) + + if old_entry.single_value.get('krbcanonicalname', None) is not None: + return + + set_krbcanonicalname(old_entry) + + old_entry.pop('krbprincipalname', None) + old_entry.pop('objectclass', None) + + entry_attrs.update(old_entry) + + +def check_principal_realm_in_trust_namespace(api_instance, *keys): + """ + Check that principal name's suffix does not overlap with UPNs and realm + names of trusted forests. + + :param api_instance: API instance + :param suffixes: principal suffixes + + :raises: ValidationError if the suffix coincides with realm name, UPN + suffix or netbios name of trusted domains + """ + trust_objects = api_instance.Command.trust_find(u'', sizelimit=0)['result'] + + trust_suffix_namespace = set() + + for obj in trust_objects: + trust_suffix_namespace.update( + set(upn.lower() for upn in obj['ipantadditionalsuffixes'])) + + trust_suffix_namespace.update( + set((obj['cn'][0].lower(), obj['ipantflatname'][0].lower()))) + + for principal in keys[-1]: + realm = principal.realm + upn = principal.upn_suffix if principal.is_enterprise else None + + if realm in trust_suffix_namespace or upn in trust_suffix_namespace: + raise errors.ValidationError( + name='krbprincipalname', + error=_('realm or UPN suffix overlaps with trusted domain ' + 'namespace')) diff --git a/ipaserver/plugins/baseuser.py b/ipaserver/plugins/baseuser.py index cbb04aaad..c80d5ac0d 100644 --- a/ipaserver/plugins/baseuser.py +++ b/ipaserver/plugins/baseuser.py @@ -27,7 +27,8 @@ from ipalib.parameters import Principal from ipalib.plugable import Registry from .baseldap import ( DN, LDAPObject, LDAPCreate, LDAPUpdate, LDAPSearch, LDAPDelete, - LDAPRetrieve, LDAPAddMember, LDAPRemoveMember) + LDAPRetrieve, LDAPAddAttribute, LDAPRemoveAttribute, LDAPAddMember, + LDAPRemoveMember) from ipaserver.plugins.service import ( validate_certificate, validate_realm, normalize_principal) from ipalib.request import context @@ -42,7 +43,10 @@ from ipalib.util import ( remove_sshpubkey_from_output_post, remove_sshpubkey_from_output_list_post, add_sshpubkey_to_attrs_pre, - set_krbcanonicalname + set_krbcanonicalname, + check_principal_realm_in_trust_namespace, + ensure_last_krbprincipalname, + ensure_krbcanonicalname_set ) if six.PY3: @@ -212,14 +216,20 @@ class baseuser(LDAPObject): label=_('Login shell'), ), Principal( - 'krbprincipalname?', + 'krbcanonicalname?', + validate_realm, + label=_('Principal name'), + flags={'no_option', 'no_create', 'no_update', 'no_search'}, + normalizer=normalize_user_principal + ), + Principal( + 'krbprincipalname*', validate_realm, cli_name='principal', - label=_('Kerberos principal'), - default_from=lambda uid: kerberos.Principal.from_text( + label=_('Principal alias'), + default_from=lambda uid: kerberos.Principal( uid.lower(), realm=api.env.realm), autofill=True, - flags=['no_update'], normalizer=normalize_user_principal, ), DateTime('krbprincipalexpiration?', @@ -621,3 +631,20 @@ class baseuser_add_manager(LDAPAddMember): class baseuser_remove_manager(LDAPRemoveMember): member_attributes = ['manager'] + + +class baseuser_add_principal(LDAPAddAttribute): + attribute = 'krbprincipalname' + + def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + check_principal_realm_in_trust_namespace(self.api, *keys) + ensure_krbcanonicalname_set(ldap, entry_attrs) + return dn + + +class baseuser_remove_principal(LDAPRemoveAttribute): + attribute = 'krbprincipalname' + + def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + ensure_last_krbprincipalname(ldap, entry_attrs, *keys) + return dn diff --git a/ipaserver/plugins/host.py b/ipaserver/plugins/host.py index 11bddb505..1c1e934b9 100644 --- a/ipaserver/plugins/host.py +++ b/ipaserver/plugins/host.py @@ -35,7 +35,7 @@ from .baseldap import (LDAPQuery, LDAPObject, LDAPCreate, LDAPAddAttribute, LDAPRemoveAttribute, LDAPAddAttributeViaOption, LDAPRemoveAttributeViaOption) -from ipaserver.plugins.service import ( +from .service import ( validate_realm, normalize_principal, validate_certificate, set_certificate_attrs, ticket_flags_params, update_krbticketflags, set_kerberos_attrs, rename_ipaallowedtoperform_from_ldap, @@ -406,6 +406,12 @@ class host(LDAPObject): 'ipapermdefaultattr': {'usercertificate'}, 'default_privileges': {'Host Administrators', 'Host Enrollment'}, }, + 'System: Manage Host Principals': { + 'ipapermbindruletype': 'permission', + 'ipapermright': {'write'}, + 'ipapermdefaultattr': {'krbprincipalname', 'krbcanonicalname'}, + 'default_privileges': {'Host Administrators', 'Host Enrollment'}, + }, 'System: Manage Host Enrollment Password': { 'ipapermbindruletype': 'permission', 'ipapermright': {'write'}, @@ -515,11 +521,18 @@ class host(LDAPObject): flags={'virtual_attribute', 'no_create', 'no_update', 'no_search'}, ), Principal( - 'krbprincipalname?', + 'krbcanonicalname?', validate_realm, label=_('Principal name'), normalizer=normalize_principal, - flags=['no_create', 'no_update', 'no_search'], + flags={'no_create', 'no_update', 'no_search'}, + ), + Principal( + 'krbprincipalname*', + validate_realm, + label=_('Principal alias'), + normalizer=normalize_principal, + flags=['no_create', 'no_search'], ), Str('macaddress*', normalizer=lambda value: value.upper(), @@ -839,15 +852,6 @@ class host_mod(LDAPUpdate): member_attributes = ['managedby'] takes_options = LDAPUpdate.takes_options + ( - Principal( - 'krbprincipalname?', - validate_realm, - cli_name='principalname', - label=_('Principal name'), - doc=_('Kerberos principal name for this host'), - normalizer=normalize_principal, - attribute=True, - ), Flag('updatedns?', doc=_('Update DNS entries'), default=False, @@ -1332,3 +1336,26 @@ class host_remove_cert(LDAPRemoveAttributeViaOption): revoke_certs(options['usercertificate'], self.log) return dn + + +@register() +class host_add_principal(LDAPAddAttribute): + __doc__ = _('Add new principal alias to host entry') + msg_summary = _('Added new aliases to host "%(value)s"') + attribute = 'krbprincipalname' + + def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + util.check_principal_realm_in_trust_namespace(self.api, *keys) + util.ensure_krbcanonicalname_set(ldap, entry_attrs) + return dn + + +@register() +class host_remove_principal(LDAPRemoveAttribute): + __doc__ = _('Remove principal alias from a host entry') + msg_summary = _('Removed aliases from host "%(value)s"') + attribute = 'krbprincipalname' + + def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + util.ensure_last_krbprincipalname(ldap, entry_attrs, *keys) + return dn diff --git a/ipaserver/plugins/service.py b/ipaserver/plugins/service.py index 7b0832b23..417be0011 100644 --- a/ipaserver/plugins/service.py +++ b/ipaserver/plugins/service.py @@ -422,6 +422,13 @@ class service(LDAPObject): ], 'default_privileges': {'Service Administrators'}, }, + 'System: Manage Service Principals': { + 'ipapermright': {'write'}, + 'ipapermdefaultattr': {'krbprincipalname', 'krbcanonicalname'}, + 'default_privileges': { + 'Service Administrators', + }, + }, 'System: Remove Services': { 'ipapermright': {'delete'}, 'replaces': [ @@ -439,12 +446,22 @@ class service(LDAPObject): 'krbcanonicalname', validate_realm, cli_name='canonical_principal', - label=_('Principal'), + label=_('Principal name'), doc=_('Service principal'), primary_key=True, normalizer=normalize_principal, require_service=True ), + Principal( + 'krbprincipalname*', + validate_realm, + cli_name='principal', + label=_('Principal alias'), + doc=_('Service principal alias'), + normalizer=normalize_principal, + require_service=True, + flags={'no_create'} + ), Bytes('usercertificate*', validate_certificate, cli_name='certificate', label=_('Certificate'), @@ -503,16 +520,6 @@ class service(LDAPObject): " Use 'radius' to allow RADIUS-based 2FA authentications." " Other values may be used for custom configurations."), ), - Principal( - 'krbprincipalname', - validate_realm, - cli_name='principal', - label=_('Principal Alias'), - doc=_('Service principal alias'), - normalizer=normalize_principal, - require_service=True, - flags={'no_create', 'no_update'} - ), ) + ticket_flags_params def validate_ipakrbauthzdata(self, entry): @@ -819,7 +826,6 @@ class service_show(LDAPRetrieve): return dn - @register() class service_add_host(LDAPAddMember): __doc__ = _('Add hosts that can manage this service.') @@ -978,3 +984,26 @@ class service_remove_cert(LDAPRemoveAttributeViaOption): revoke_certs(options['usercertificate'], self.log) return dn + + +@register() +class service_add_principal(LDAPAddAttribute): + __doc__ = _('Add new principal alias to a service') + msg_summary = _('Added new aliases to the service principal "%(value)s"') + attribute = 'krbprincipalname' + + def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + util.check_principal_realm_in_trust_namespace(self.api, *keys) + util.ensure_krbcanonicalname_set(ldap, entry_attrs) + return dn + + +@register() +class service_remove_principal(LDAPRemoveAttribute): + __doc__ = _('Remove principal alias from a service') + msg_summary = _('Removed aliases to the service principal "%(value)s"') + attribute = 'krbprincipalname' + + def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): + util.ensure_last_krbprincipalname(ldap, entry_attrs, *keys) + return dn diff --git a/ipaserver/plugins/user.py b/ipaserver/plugins/user.py index c231847d5..b3ae7646f 100644 --- a/ipaserver/plugins/user.py +++ b/ipaserver/plugins/user.py @@ -43,7 +43,9 @@ from .baseuser import ( convert_nsaccountlock, fix_addressbook_permission_bindrule, baseuser_add_manager, - baseuser_remove_manager) + baseuser_remove_manager, + baseuser_add_principal, + baseuser_remove_principal) from .idviews import remove_ipaobject_overrides from ipalib.plugable import Registry from .baseldap import ( @@ -287,6 +289,14 @@ class user(baseuser): 'Modify Users and Reset passwords', }, }, + 'System: Manage User Principals': { + 'ipapermright': {'write'}, + 'ipapermdefaultattr': {'krbprincipalname', 'krbcanonicalname'}, + 'default_privileges': { + 'User Administrators', + 'Modify Users and Reset passwords', + }, + }, 'System: Modify Users': { 'ipapermright': {'write'}, 'ipapermdefaultattr': { @@ -1187,3 +1197,15 @@ class user_add_manager(baseuser_add_manager): @register() class user_remove_manager(baseuser_remove_manager): __doc__ = _("Remove a manager to the user entry") + + +@register() +class user_add_principal(baseuser_add_principal): + __doc__ = _('Add new principal alias to the user entry') + msg_summary = _('Added new aliases to user "%(value)s"') + + +@register() +class user_remove_principal(baseuser_remove_principal): + __doc__ = _('Remove principal alias from the user entry') + msg_summary = _('Removed aliases from user "%(value)s"') |