summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ACI.txt6
-rw-r--r--API.txt93
-rw-r--r--VERSION4
-rw-r--r--ipalib/util.py71
-rw-r--r--ipaserver/plugins/baseuser.py39
-rw-r--r--ipaserver/plugins/host.py51
-rw-r--r--ipaserver/plugins/service.py53
-rw-r--r--ipaserver/plugins/user.py24
8 files changed, 299 insertions, 42 deletions
diff --git a/ACI.txt b/ACI.txt
index 09e4ee7fc..fddd5987f 100644
--- a/ACI.txt
+++ b/ACI.txt
@@ -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";)
diff --git a/API.txt b/API.txt
index 5d99f5a0b..7d82d353a 100644
--- a/API.txt
+++ b/API.txt
@@ -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
diff --git a/VERSION b/VERSION
index dd2e1aba1..b9b5485bc 100644
--- a/VERSION
+++ b/VERSION
@@ -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"')