Migrate management framework plugins to use Principal parameter

All plugins will now use this parameter and common code for all operations on
Kerberos principals.  Additional semantic validators and normalizers were
added to determine or append a correct realm so that the previous behavior is
kept intact.

https://fedorahosted.org/freeipa/ticket/3864

Reviewed-By: David Kupka <dkupka@redhat.com>
Reviewed-By: Jan Cholasta <jcholast@redhat.com>
This commit is contained in:
Martin Babinsky 2016-06-23 18:54:49 +02:00 committed by Martin Basti
parent 974eb7b5ef
commit c2af032c03
12 changed files with 208 additions and 234 deletions

76
API.txt
View File

@ -738,14 +738,14 @@ option: Int('max_serial_number?', autofill=False)
option: Int('min_serial_number?', autofill=False) option: Int('min_serial_number?', autofill=False)
option: Str('no_host*', cli_name='no_hosts') option: Str('no_host*', cli_name='no_hosts')
option: Flag('no_members', autofill=True, default=True) option: Flag('no_members', autofill=True, default=True)
option: Str('no_service*', cli_name='no_services') option: Principal('no_service*', cli_name='no_services')
option: Str('no_user*', cli_name='no_users') option: Str('no_user*', cli_name='no_users')
option: Flag('pkey_only?', autofill=True, default=False) option: Flag('pkey_only?', autofill=True, default=False)
option: Flag('raw', autofill=True, cli_name='raw', default=False) option: Flag('raw', autofill=True, cli_name='raw', default=False)
option: Int('revocation_reason?', autofill=False) option: Int('revocation_reason?', autofill=False)
option: DateTime('revokedon_from?', autofill=False) option: DateTime('revokedon_from?', autofill=False)
option: DateTime('revokedon_to?', autofill=False) option: DateTime('revokedon_to?', autofill=False)
option: Str('service*', cli_name='services') option: Principal('service*', cli_name='services')
option: Int('sizelimit?') option: Int('sizelimit?')
option: Str('subject?', autofill=False) option: Str('subject?', autofill=False)
option: Int('timelimit?') option: Int('timelimit?')
@ -771,7 +771,7 @@ arg: Str('csr', cli_name='csr_file')
option: Flag('add', autofill=True, default=False) option: Flag('add', autofill=True, default=False)
option: Flag('all', autofill=True, cli_name='all', default=False) option: Flag('all', autofill=True, cli_name='all', default=False)
option: Str('cacn?', autofill=True, cli_name='ca', default=u'ipa') option: Str('cacn?', autofill=True, cli_name='ca', default=u'ipa')
option: Str('principal') option: Principal('principal')
option: Str('profile_id?') option: Str('profile_id?')
option: Flag('raw', autofill=True, cli_name='raw', default=False) option: Flag('raw', autofill=True, cli_name='raw', default=False)
option: Str('request_type', autofill=True, default=u'pkcs10') option: Str('request_type', autofill=True, default=u'pkcs10')
@ -2436,7 +2436,7 @@ option: Bool('ipakrbokasdelegate?', autofill=False, cli_name='ok_as_delegate')
option: Bool('ipakrbrequirespreauth?', autofill=False, cli_name='requires_pre_auth') option: Bool('ipakrbrequirespreauth?', autofill=False, cli_name='requires_pre_auth')
option: Str('ipasshpubkey*', autofill=False, cli_name='sshpubkey') option: Str('ipasshpubkey*', autofill=False, cli_name='sshpubkey')
option: Str('krbprincipalauthind*', autofill=False, cli_name='auth_ind') option: Str('krbprincipalauthind*', autofill=False, cli_name='auth_ind')
option: Str('krbprincipalname?', cli_name='principalname') option: Principal('krbprincipalname?', cli_name='principalname')
option: Str('l?', autofill=False, cli_name='locality') option: Str('l?', autofill=False, cli_name='locality')
option: Str('macaddress*', autofill=False) option: Str('macaddress*', autofill=False)
option: Flag('no_members', autofill=True, default=False) option: Flag('no_members', autofill=True, default=False)
@ -3401,7 +3401,7 @@ output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
output: PrimaryKey('value') output: PrimaryKey('value')
command: passwd/1 command: passwd/1
args: 3,2,3 args: 3,2,3
arg: Str('principal', autofill=True, cli_name='user') arg: Principal('principal', autofill=True, cli_name='user')
arg: Password('password') arg: Password('password')
arg: Password('current_password', autofill=True, confirm=False) arg: Password('current_password', autofill=True, confirm=False)
option: Password('otp?', confirm=False) option: Password('otp?', confirm=False)
@ -4271,7 +4271,7 @@ output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
output: PrimaryKey('value') output: PrimaryKey('value')
command: service_add/1 command: service_add/1
args: 1,12,3 args: 1,12,3
arg: Str('krbprincipalname', cli_name='principal') arg: Principal('krbprincipalname', cli_name='principal')
option: Str('addattr*', cli_name='addattr') option: Str('addattr*', cli_name='addattr')
option: Flag('all', autofill=True, cli_name='all', default=False) option: Flag('all', autofill=True, cli_name='all', default=False)
option: Flag('force', autofill=True, default=False) option: Flag('force', autofill=True, default=False)
@ -4289,7 +4289,7 @@ output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
output: PrimaryKey('value') output: PrimaryKey('value')
command: service_add_cert/1 command: service_add_cert/1
args: 1,5,3 args: 1,5,3
arg: Str('krbprincipalname', cli_name='principal') arg: Principal('krbprincipalname', cli_name='principal')
option: Flag('all', autofill=True, cli_name='all', default=False) option: Flag('all', autofill=True, cli_name='all', default=False)
option: Flag('no_members', autofill=True, default=False) option: Flag('no_members', autofill=True, default=False)
option: Flag('raw', autofill=True, cli_name='raw', default=False) option: Flag('raw', autofill=True, cli_name='raw', default=False)
@ -4300,7 +4300,7 @@ output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
output: PrimaryKey('value') output: PrimaryKey('value')
command: service_add_host/1 command: service_add_host/1
args: 1,5,3 args: 1,5,3
arg: Str('krbprincipalname', cli_name='principal') arg: Principal('krbprincipalname', cli_name='principal')
option: Flag('all', autofill=True, cli_name='all', default=False) option: Flag('all', autofill=True, cli_name='all', default=False)
option: Str('host*', alwaysask=True, cli_name='hosts') option: Str('host*', alwaysask=True, cli_name='hosts')
option: Flag('no_members', autofill=True, default=False) option: Flag('no_members', autofill=True, default=False)
@ -4311,7 +4311,7 @@ output: Output('failed', type=[<type 'dict'>])
output: Entry('result') output: Entry('result')
command: service_allow_create_keytab/1 command: service_allow_create_keytab/1
args: 1,8,3 args: 1,8,3
arg: Str('krbprincipalname', cli_name='principal') arg: Principal('krbprincipalname', cli_name='principal')
option: Flag('all', autofill=True, cli_name='all', default=False) option: Flag('all', autofill=True, cli_name='all', default=False)
option: Str('group*', alwaysask=True, cli_name='groups') option: Str('group*', alwaysask=True, cli_name='groups')
option: Str('host*', alwaysask=True, cli_name='hosts') option: Str('host*', alwaysask=True, cli_name='hosts')
@ -4325,7 +4325,7 @@ output: Output('failed', type=[<type 'dict'>])
output: Entry('result') output: Entry('result')
command: service_allow_retrieve_keytab/1 command: service_allow_retrieve_keytab/1
args: 1,8,3 args: 1,8,3
arg: Str('krbprincipalname', cli_name='principal') arg: Principal('krbprincipalname', cli_name='principal')
option: Flag('all', autofill=True, cli_name='all', default=False) option: Flag('all', autofill=True, cli_name='all', default=False)
option: Str('group*', alwaysask=True, cli_name='groups') option: Str('group*', alwaysask=True, cli_name='groups')
option: Str('host*', alwaysask=True, cli_name='hosts') option: Str('host*', alwaysask=True, cli_name='hosts')
@ -4339,7 +4339,7 @@ output: Output('failed', type=[<type 'dict'>])
output: Entry('result') output: Entry('result')
command: service_del/1 command: service_del/1
args: 1,2,3 args: 1,2,3
arg: Str('krbprincipalname+', cli_name='principal') arg: Principal('krbprincipalname+', cli_name='principal')
option: Flag('continue', autofill=True, cli_name='continue', default=False) option: Flag('continue', autofill=True, cli_name='continue', default=False)
option: Str('version?') option: Str('version?')
output: Output('result', type=[<type 'dict'>]) output: Output('result', type=[<type 'dict'>])
@ -4347,14 +4347,14 @@ output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
output: ListOfPrimaryKeys('value') output: ListOfPrimaryKeys('value')
command: service_disable/1 command: service_disable/1
args: 1,1,3 args: 1,1,3
arg: Str('krbprincipalname', cli_name='principal') arg: Principal('krbprincipalname', cli_name='principal')
option: Str('version?') option: Str('version?')
output: Output('result', type=[<type 'bool'>]) output: Output('result', type=[<type 'bool'>])
output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>]) output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
output: PrimaryKey('value') output: PrimaryKey('value')
command: service_disallow_create_keytab/1 command: service_disallow_create_keytab/1
args: 1,8,3 args: 1,8,3
arg: Str('krbprincipalname', cli_name='principal') arg: Principal('krbprincipalname', cli_name='principal')
option: Flag('all', autofill=True, cli_name='all', default=False) option: Flag('all', autofill=True, cli_name='all', default=False)
option: Str('group*', alwaysask=True, cli_name='groups') option: Str('group*', alwaysask=True, cli_name='groups')
option: Str('host*', alwaysask=True, cli_name='hosts') option: Str('host*', alwaysask=True, cli_name='hosts')
@ -4368,7 +4368,7 @@ output: Output('failed', type=[<type 'dict'>])
output: Entry('result') output: Entry('result')
command: service_disallow_retrieve_keytab/1 command: service_disallow_retrieve_keytab/1
args: 1,8,3 args: 1,8,3
arg: Str('krbprincipalname', cli_name='principal') arg: Principal('krbprincipalname', cli_name='principal')
option: Flag('all', autofill=True, cli_name='all', default=False) option: Flag('all', autofill=True, cli_name='all', default=False)
option: Str('group*', alwaysask=True, cli_name='groups') option: Str('group*', alwaysask=True, cli_name='groups')
option: Str('host*', alwaysask=True, cli_name='hosts') option: Str('host*', alwaysask=True, cli_name='hosts')
@ -4386,7 +4386,7 @@ arg: Str('criteria?')
option: Flag('all', autofill=True, cli_name='all', default=False) 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: StrEnum('ipakrbauthzdata*', autofill=False, cli_name='pac_type', values=[u'MS-PAC', u'PAD', u'NONE'])
option: Str('krbprincipalauthind*', autofill=False, cli_name='auth_ind') option: Str('krbprincipalauthind*', autofill=False, cli_name='auth_ind')
option: Str('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: Str('man_by_host*', cli_name='man_by_hosts')
option: Flag('no_members', autofill=True, default=True) option: Flag('no_members', autofill=True, default=True)
option: Str('not_man_by_host*', cli_name='not_man_by_hosts') option: Str('not_man_by_host*', cli_name='not_man_by_hosts')
@ -4401,7 +4401,7 @@ output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
output: Output('truncated', type=[<type 'bool'>]) output: Output('truncated', type=[<type 'bool'>])
command: service_mod/1 command: service_mod/1
args: 1,13,3 args: 1,13,3
arg: Str('krbprincipalname', cli_name='principal') arg: Principal('krbprincipalname', cli_name='principal')
option: Str('addattr*', cli_name='addattr') option: Str('addattr*', cli_name='addattr')
option: Flag('all', autofill=True, cli_name='all', default=False) option: Flag('all', autofill=True, cli_name='all', default=False)
option: Str('delattr*', cli_name='delattr') option: Str('delattr*', cli_name='delattr')
@ -4420,7 +4420,7 @@ output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
output: PrimaryKey('value') output: PrimaryKey('value')
command: service_remove_cert/1 command: service_remove_cert/1
args: 1,5,3 args: 1,5,3
arg: Str('krbprincipalname', cli_name='principal') arg: Principal('krbprincipalname', cli_name='principal')
option: Flag('all', autofill=True, cli_name='all', default=False) option: Flag('all', autofill=True, cli_name='all', default=False)
option: Flag('no_members', autofill=True, default=False) option: Flag('no_members', autofill=True, default=False)
option: Flag('raw', autofill=True, cli_name='raw', default=False) option: Flag('raw', autofill=True, cli_name='raw', default=False)
@ -4431,7 +4431,7 @@ output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
output: PrimaryKey('value') output: PrimaryKey('value')
command: service_remove_host/1 command: service_remove_host/1
args: 1,5,3 args: 1,5,3
arg: Str('krbprincipalname', cli_name='principal') arg: Principal('krbprincipalname', cli_name='principal')
option: Flag('all', autofill=True, cli_name='all', default=False) option: Flag('all', autofill=True, cli_name='all', default=False)
option: Str('host*', alwaysask=True, cli_name='hosts') option: Str('host*', alwaysask=True, cli_name='hosts')
option: Flag('no_members', autofill=True, default=False) option: Flag('no_members', autofill=True, default=False)
@ -4442,7 +4442,7 @@ output: Output('failed', type=[<type 'dict'>])
output: Entry('result') output: Entry('result')
command: service_show/1 command: service_show/1
args: 1,6,3 args: 1,6,3
arg: Str('krbprincipalname', cli_name='principal') arg: Principal('krbprincipalname', cli_name='principal')
option: Flag('all', autofill=True, cli_name='all', default=False) option: Flag('all', autofill=True, cli_name='all', default=False)
option: Flag('no_members', autofill=True, default=False) option: Flag('no_members', autofill=True, default=False)
option: Str('out?') option: Str('out?')
@ -4646,7 +4646,7 @@ option: Str('ipatokenradiusconfiglink?', cli_name='radius')
option: Str('ipatokenradiususername?', cli_name='radius_username') option: Str('ipatokenradiususername?', cli_name='radius_username')
option: StrEnum('ipauserauthtype*', cli_name='user_auth_type', values=[u'password', u'radius', u'otp']) option: StrEnum('ipauserauthtype*', cli_name='user_auth_type', values=[u'password', u'radius', u'otp'])
option: DateTime('krbprincipalexpiration?', cli_name='principal_expiration') option: DateTime('krbprincipalexpiration?', cli_name='principal_expiration')
option: Str('krbprincipalname?', autofill=True, cli_name='principal') option: Principal('krbprincipalname?', autofill=True, cli_name='principal')
option: Str('l?', cli_name='city') option: Str('l?', cli_name='city')
option: Str('loginshell?', cli_name='shell') option: Str('loginshell?', cli_name='shell')
option: Str('mail*', cli_name='email') option: Str('mail*', cli_name='email')
@ -4717,7 +4717,7 @@ option: Str('ipatokenradiusconfiglink?', autofill=False, cli_name='radius')
option: Str('ipatokenradiususername?', autofill=False, cli_name='radius_username') 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: 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: DateTime('krbprincipalexpiration?', autofill=False, cli_name='principal_expiration')
option: Str('krbprincipalname?', autofill=False, cli_name='principal') option: Principal('krbprincipalname?', autofill=False, cli_name='principal')
option: Str('l?', autofill=False, cli_name='city') option: Str('l?', autofill=False, cli_name='city')
option: Str('loginshell?', autofill=False, cli_name='shell') option: Str('loginshell?', autofill=False, cli_name='shell')
option: Str('mail*', autofill=False, cli_name='email') option: Str('mail*', autofill=False, cli_name='email')
@ -5633,7 +5633,7 @@ option: Str('ipatokenradiusconfiglink?', cli_name='radius')
option: Str('ipatokenradiususername?', cli_name='radius_username') option: Str('ipatokenradiususername?', cli_name='radius_username')
option: StrEnum('ipauserauthtype*', cli_name='user_auth_type', values=[u'password', u'radius', u'otp']) option: StrEnum('ipauserauthtype*', cli_name='user_auth_type', values=[u'password', u'radius', u'otp'])
option: DateTime('krbprincipalexpiration?', cli_name='principal_expiration') option: DateTime('krbprincipalexpiration?', cli_name='principal_expiration')
option: Str('krbprincipalname?', autofill=True, cli_name='principal') option: Principal('krbprincipalname?', autofill=True, cli_name='principal')
option: Str('l?', cli_name='city') option: Str('l?', cli_name='city')
option: Str('loginshell?', cli_name='shell') option: Str('loginshell?', cli_name='shell')
option: Str('mail*', cli_name='email') option: Str('mail*', cli_name='email')
@ -5732,7 +5732,7 @@ option: Str('ipatokenradiusconfiglink?', autofill=False, cli_name='radius')
option: Str('ipatokenradiususername?', autofill=False, cli_name='radius_username') 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: 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: DateTime('krbprincipalexpiration?', autofill=False, cli_name='principal_expiration')
option: Str('krbprincipalname?', autofill=False, cli_name='principal') option: Principal('krbprincipalname?', autofill=False, cli_name='principal')
option: Str('l?', autofill=False, cli_name='city') option: Str('l?', autofill=False, cli_name='city')
option: Str('loginshell?', autofill=False, cli_name='shell') option: Str('loginshell?', autofill=False, cli_name='shell')
option: Str('mail*', autofill=False, cli_name='email') option: Str('mail*', autofill=False, cli_name='email')
@ -5899,7 +5899,7 @@ option: Bytes('ipavaultsalt?', cli_name='salt')
option: StrEnum('ipavaulttype?', autofill=True, cli_name='type', default=u'symmetric', values=[u'standard', u'symmetric', u'asymmetric']) option: StrEnum('ipavaulttype?', autofill=True, cli_name='type', default=u'symmetric', values=[u'standard', u'symmetric', u'asymmetric'])
option: Flag('no_members', autofill=True, default=False) option: Flag('no_members', autofill=True, default=False)
option: Flag('raw', autofill=True, cli_name='raw', default=False) option: Flag('raw', autofill=True, cli_name='raw', default=False)
option: Str('service?') option: Principal('service?')
option: Str('setattr*', cli_name='setattr') option: Str('setattr*', cli_name='setattr')
option: Flag('shared?', autofill=True, default=False) option: Flag('shared?', autofill=True, default=False)
option: Str('username?', cli_name='user') option: Str('username?', cli_name='user')
@ -5914,7 +5914,7 @@ option: Flag('all', autofill=True, cli_name='all', default=False)
option: Str('group*', alwaysask=True, cli_name='groups') option: Str('group*', alwaysask=True, cli_name='groups')
option: Flag('no_members', autofill=True, default=False) option: Flag('no_members', autofill=True, default=False)
option: Flag('raw', autofill=True, cli_name='raw', default=False) option: Flag('raw', autofill=True, cli_name='raw', default=False)
option: Str('service?') option: Principal('service?')
option: Str('services*', alwaysask=True, cli_name='services') option: Str('services*', alwaysask=True, cli_name='services')
option: Flag('shared?', autofill=True, default=False) option: Flag('shared?', autofill=True, default=False)
option: Str('user*', alwaysask=True, cli_name='users') option: Str('user*', alwaysask=True, cli_name='users')
@ -5930,7 +5930,7 @@ option: Flag('all', autofill=True, cli_name='all', default=False)
option: Str('group*', alwaysask=True, cli_name='groups') option: Str('group*', alwaysask=True, cli_name='groups')
option: Flag('no_members', autofill=True, default=False) option: Flag('no_members', autofill=True, default=False)
option: Flag('raw', autofill=True, cli_name='raw', default=False) option: Flag('raw', autofill=True, cli_name='raw', default=False)
option: Str('service?') option: Principal('service?')
option: Str('services*', alwaysask=True, cli_name='services') option: Str('services*', alwaysask=True, cli_name='services')
option: Flag('shared?', autofill=True, default=False) option: Flag('shared?', autofill=True, default=False)
option: Str('user*', alwaysask=True, cli_name='users') option: Str('user*', alwaysask=True, cli_name='users')
@ -5945,7 +5945,7 @@ arg: Str('cn', cli_name='name')
option: Flag('all', autofill=True, cli_name='all', default=False) option: Flag('all', autofill=True, cli_name='all', default=False)
option: Bytes('nonce') option: Bytes('nonce')
option: Flag('raw', autofill=True, cli_name='raw', default=False) option: Flag('raw', autofill=True, cli_name='raw', default=False)
option: Str('service?') option: Principal('service?')
option: Bytes('session_key') option: Bytes('session_key')
option: Flag('shared?', autofill=True, default=False) option: Flag('shared?', autofill=True, default=False)
option: Str('username?', cli_name='user') option: Str('username?', cli_name='user')
@ -5958,7 +5958,7 @@ command: vault_del/1
args: 1,5,3 args: 1,5,3
arg: Str('cn+', cli_name='name') arg: Str('cn+', cli_name='name')
option: Flag('continue', autofill=True, cli_name='continue', default=False) option: Flag('continue', autofill=True, cli_name='continue', default=False)
option: Str('service?') option: Principal('service?')
option: Flag('shared?', autofill=True, default=False) option: Flag('shared?', autofill=True, default=False)
option: Str('username?', cli_name='user') option: Str('username?', cli_name='user')
option: Str('version?') option: Str('version?')
@ -5975,7 +5975,7 @@ option: StrEnum('ipavaulttype?', autofill=False, cli_name='type', default=u'symm
option: Flag('no_members', autofill=True, default=True) option: Flag('no_members', autofill=True, default=True)
option: Flag('pkey_only?', autofill=True, default=False) option: Flag('pkey_only?', autofill=True, default=False)
option: Flag('raw', autofill=True, cli_name='raw', default=False) option: Flag('raw', autofill=True, cli_name='raw', default=False)
option: Str('service?') option: Principal('service?')
option: Flag('services?', autofill=True, default=False) option: Flag('services?', autofill=True, default=False)
option: Flag('shared?', autofill=True, default=False) option: Flag('shared?', autofill=True, default=False)
option: Int('sizelimit?', autofill=False) option: Int('sizelimit?', autofill=False)
@ -6000,7 +6000,7 @@ option: StrEnum('ipavaulttype?', autofill=False, cli_name='type', default=u'symm
option: Flag('no_members', autofill=True, default=False) option: Flag('no_members', autofill=True, default=False)
option: Flag('raw', autofill=True, cli_name='raw', default=False) option: Flag('raw', autofill=True, cli_name='raw', default=False)
option: Flag('rights', autofill=True, default=False) option: Flag('rights', autofill=True, default=False)
option: Str('service?') option: Principal('service?')
option: Str('setattr*', cli_name='setattr') option: Str('setattr*', cli_name='setattr')
option: Flag('shared?', autofill=True, default=False) option: Flag('shared?', autofill=True, default=False)
option: Str('username?', cli_name='user') option: Str('username?', cli_name='user')
@ -6015,7 +6015,7 @@ option: Flag('all', autofill=True, cli_name='all', default=False)
option: Str('group*', alwaysask=True, cli_name='groups') option: Str('group*', alwaysask=True, cli_name='groups')
option: Flag('no_members', autofill=True, default=False) option: Flag('no_members', autofill=True, default=False)
option: Flag('raw', autofill=True, cli_name='raw', default=False) option: Flag('raw', autofill=True, cli_name='raw', default=False)
option: Str('service?') option: Principal('service?')
option: Str('services*', alwaysask=True, cli_name='services') option: Str('services*', alwaysask=True, cli_name='services')
option: Flag('shared?', autofill=True, default=False) option: Flag('shared?', autofill=True, default=False)
option: Str('user*', alwaysask=True, cli_name='users') option: Str('user*', alwaysask=True, cli_name='users')
@ -6031,7 +6031,7 @@ option: Flag('all', autofill=True, cli_name='all', default=False)
option: Str('group*', alwaysask=True, cli_name='groups') option: Str('group*', alwaysask=True, cli_name='groups')
option: Flag('no_members', autofill=True, default=False) option: Flag('no_members', autofill=True, default=False)
option: Flag('raw', autofill=True, cli_name='raw', default=False) option: Flag('raw', autofill=True, cli_name='raw', default=False)
option: Str('service?') option: Principal('service?')
option: Str('services*', alwaysask=True, cli_name='services') option: Str('services*', alwaysask=True, cli_name='services')
option: Flag('shared?', autofill=True, default=False) option: Flag('shared?', autofill=True, default=False)
option: Str('user*', alwaysask=True, cli_name='users') option: Str('user*', alwaysask=True, cli_name='users')
@ -6045,7 +6045,7 @@ args: 1,7,3
arg: Str('cn', cli_name='name') arg: Str('cn', cli_name='name')
option: Flag('all', autofill=True, cli_name='all', default=False) option: Flag('all', autofill=True, cli_name='all', default=False)
option: Flag('raw', autofill=True, cli_name='raw', default=False) option: Flag('raw', autofill=True, cli_name='raw', default=False)
option: Str('service?') option: Principal('service?')
option: Bytes('session_key') option: Bytes('session_key')
option: Flag('shared?', autofill=True, default=False) option: Flag('shared?', autofill=True, default=False)
option: Str('username?', cli_name='user') option: Str('username?', cli_name='user')
@ -6060,7 +6060,7 @@ option: Flag('all', autofill=True, cli_name='all', default=False)
option: Flag('no_members', autofill=True, default=False) option: Flag('no_members', autofill=True, default=False)
option: Flag('raw', autofill=True, cli_name='raw', default=False) option: Flag('raw', autofill=True, cli_name='raw', default=False)
option: Flag('rights', autofill=True, default=False) option: Flag('rights', autofill=True, default=False)
option: Str('service?') option: Principal('service?')
option: Flag('shared?', autofill=True, default=False) option: Flag('shared?', autofill=True, default=False)
option: Str('username?', cli_name='user') option: Str('username?', cli_name='user')
option: Str('version?') option: Str('version?')
@ -6082,7 +6082,7 @@ option: Flag('all', autofill=True, cli_name='all', default=False)
option: Str('group*', alwaysask=True, cli_name='groups') option: Str('group*', alwaysask=True, cli_name='groups')
option: Flag('no_members', autofill=True, default=False) option: Flag('no_members', autofill=True, default=False)
option: Flag('raw', autofill=True, cli_name='raw', default=False) option: Flag('raw', autofill=True, cli_name='raw', default=False)
option: Str('service?') option: Principal('service?')
option: Str('services*', alwaysask=True, cli_name='services') option: Str('services*', alwaysask=True, cli_name='services')
option: Flag('shared?', autofill=True, default=False) option: Flag('shared?', autofill=True, default=False)
option: Str('user*', alwaysask=True, cli_name='users') option: Str('user*', alwaysask=True, cli_name='users')
@ -6094,7 +6094,7 @@ output: Entry('result')
command: vaultcontainer_del/1 command: vaultcontainer_del/1
args: 0,5,3 args: 0,5,3
option: Flag('continue', autofill=True, cli_name='continue', default=False) option: Flag('continue', autofill=True, cli_name='continue', default=False)
option: Str('service?') option: Principal('service?')
option: Flag('shared?', autofill=True, default=False) option: Flag('shared?', autofill=True, default=False)
option: Str('username?', cli_name='user') option: Str('username?', cli_name='user')
option: Str('version?') option: Str('version?')
@ -6107,7 +6107,7 @@ option: Flag('all', autofill=True, cli_name='all', default=False)
option: Str('group*', alwaysask=True, cli_name='groups') option: Str('group*', alwaysask=True, cli_name='groups')
option: Flag('no_members', autofill=True, default=False) option: Flag('no_members', autofill=True, default=False)
option: Flag('raw', autofill=True, cli_name='raw', default=False) option: Flag('raw', autofill=True, cli_name='raw', default=False)
option: Str('service?') option: Principal('service?')
option: Str('services*', alwaysask=True, cli_name='services') option: Str('services*', alwaysask=True, cli_name='services')
option: Flag('shared?', autofill=True, default=False) option: Flag('shared?', autofill=True, default=False)
option: Str('user*', alwaysask=True, cli_name='users') option: Str('user*', alwaysask=True, cli_name='users')
@ -6122,7 +6122,7 @@ option: Flag('all', autofill=True, cli_name='all', default=False)
option: Flag('no_members', autofill=True, default=False) option: Flag('no_members', autofill=True, default=False)
option: Flag('raw', autofill=True, cli_name='raw', default=False) option: Flag('raw', autofill=True, cli_name='raw', default=False)
option: Flag('rights', autofill=True, default=False) option: Flag('rights', autofill=True, default=False)
option: Str('service?') option: Principal('service?')
option: Flag('shared?', autofill=True, default=False) option: Flag('shared?', autofill=True, default=False)
option: Str('username?', cli_name='user') option: Str('username?', cli_name='user')
option: Str('version?') option: Str('version?')

View File

@ -23,13 +23,16 @@ import six
from ipalib import api, errors from ipalib import api, errors
from ipalib import Flag, Int, Password, Str, Bool, StrEnum, DateTime, Bytes from ipalib import Flag, Int, Password, Str, Bool, StrEnum, DateTime, Bytes
from ipalib.parameters import Principal
from ipalib.plugable import Registry from ipalib.plugable import Registry
from .baseldap import ( from .baseldap import (
DN, LDAPObject, LDAPCreate, LDAPUpdate, LDAPSearch, LDAPDelete, DN, LDAPObject, LDAPCreate, LDAPUpdate, LDAPSearch, LDAPDelete,
LDAPRetrieve, LDAPAddMember, LDAPRemoveMember) LDAPRetrieve, LDAPAddMember, LDAPRemoveMember)
from .service import validate_certificate from ipaserver.plugins.service import (
validate_certificate, validate_realm, normalize_principal)
from ipalib.request import context from ipalib.request import context
from ipalib import _ from ipalib import _
from ipapython import kerberos
from ipapython.ipautil import ipa_generate_password from ipapython.ipautil import ipa_generate_password
from ipapython.ipavalidate import Email from ipapython.ipavalidate import Email
from ipalib.util import ( from ipalib.util import (
@ -93,45 +96,14 @@ def convert_nsaccountlock(entry_attrs):
nsaccountlock = Bool('temp') nsaccountlock = Bool('temp')
entry_attrs['nsaccountlock'] = nsaccountlock.convert(entry_attrs['nsaccountlock'][0]) entry_attrs['nsaccountlock'] = nsaccountlock.convert(entry_attrs['nsaccountlock'][0])
def split_principal(principal):
"""
Split the principal into its components and do some basic validation.
Automatically append our realm if it wasn't provided. def normalize_user_principal(value):
""" principal = kerberos.Principal(normalize_principal(value))
realm = None lowercase_components = ((principal.username.lower(),) +
parts = principal.split('@') principal.components[1:])
user = parts[0].lower()
if len(parts) > 2:
raise errors.MalformedUserPrincipal(principal=principal)
if len(parts) == 2:
realm = parts[1].upper()
# At some point we'll support multiple realms
if realm != api.env.realm:
raise errors.RealmMismatch()
else:
realm = api.env.realm
return (user, realm)
def validate_principal(ugettext, principal):
"""
All the real work is done in split_principal.
"""
(user, realm) = split_principal(principal)
return None
def normalize_principal(principal):
"""
Ensure that the name in the principal is lower-case. The realm is
upper-case by convention but it isn't required.
The principal is validated at this point.
"""
(user, realm) = split_principal(principal)
return unicode('%s@%s' % (user, realm))
return unicode(
kerberos.Principal(lowercase_components, realm=principal.realm))
def fix_addressbook_permission_bindrule(name, template, is_new, def fix_addressbook_permission_bindrule(name, template, is_new,
@ -239,13 +211,16 @@ class baseuser(LDAPObject):
cli_name='shell', cli_name='shell',
label=_('Login shell'), label=_('Login shell'),
), ),
Str('krbprincipalname?', validate_principal, Principal(
'krbprincipalname?',
validate_realm,
cli_name='principal', cli_name='principal',
label=_('Kerberos principal'), label=_('Kerberos principal'),
default_from=lambda uid: '%s@%s' % (uid.lower(), api.env.realm), default_from=lambda uid: kerberos.Principal.from_text(
uid.lower(), realm=api.env.realm),
autofill=True, autofill=True,
flags=['no_update'], flags=['no_update'],
normalizer=lambda value: normalize_principal(value), normalizer=normalize_user_principal,
), ),
DateTime('krbprincipalexpiration?', DateTime('krbprincipalexpiration?',
cli_name='principal_expiration', cli_name='principal_expiration',

View File

@ -3,6 +3,7 @@
# #
import pyhbac import pyhbac
import six
from ipalib import api, errors, output from ipalib import api, errors, output
from ipalib import Bool, Str, StrEnum from ipalib import Bool, Str, StrEnum
@ -13,10 +14,11 @@ from .baseldap import (
LDAPUpdate, LDAPRetrieve, LDAPAddMember, LDAPRemoveMember, LDAPUpdate, LDAPRetrieve, LDAPAddMember, LDAPRemoveMember,
global_output_params, pkey_to_value) global_output_params, pkey_to_value)
from .hbacrule import is_all from .hbacrule import is_all
from .service import normalize_principal, split_any_principal
from ipalib import _, ngettext from ipalib import _, ngettext
from ipapython.dn import DN from ipapython.dn import DN
if six.PY3:
unicode = str
__doc__ = _(""" __doc__ = _("""
Manage CA ACL rules. Manage CA ACL rules.
@ -58,24 +60,21 @@ register = Registry()
def _acl_make_request(principal_type, principal, ca_id, profile_id): def _acl_make_request(principal_type, principal, ca_id, profile_id):
"""Construct HBAC request for the given principal, CA and profile""" """Construct HBAC request for the given principal, CA and profile"""
service, name, realm = split_any_principal(principal)
req = pyhbac.HbacRequest() req = pyhbac.HbacRequest()
req.targethost.name = ca_id req.targethost.name = ca_id
req.service.name = profile_id req.service.name = profile_id
if principal_type == 'user': if principal_type == 'user' or principal_type == 'host':
req.user.name = name req.user.name = principal.username
elif principal_type == 'host':
req.user.name = name
elif principal_type == 'service': elif principal_type == 'service':
req.user.name = normalize_principal(principal) req.user.name = unicode(principal)
groups = [] groups = []
if principal_type == 'user': if principal_type == 'user':
user_obj = api.Command.user_show(name)['result'] user_obj = api.Command.user_show(principal.username)['result']
groups = user_obj.get('memberof_group', []) groups = user_obj.get('memberof_group', [])
groups += user_obj.get('memberofindirect_group', []) groups += user_obj.get('memberofindirect_group', [])
elif principal_type == 'host': elif principal_type == 'host':
host_obj = api.Command.host_show(name)['result'] host_obj = api.Command.host_show(principal.hostname)['result']
groups = host_obj.get('memberof_hostgroup', []) groups = host_obj.get('memberof_hostgroup', [])
groups += host_obj.get('memberofindirect_hostgroup', []) groups += host_obj.get('memberofindirect_hostgroup', [])
req.user.groups = sorted(set(groups)) req.user.groups = sorted(set(groups))

View File

@ -38,18 +38,18 @@ from ipalib import ngettext
from ipalib.constants import IPA_CA_CN from ipalib.constants import IPA_CA_CN
from ipalib.crud import Create, PKQuery, Retrieve, Search from ipalib.crud import Create, PKQuery, Retrieve, Search
from ipalib.frontend import Method, Object from ipalib.frontend import Method, Object
from ipalib.parameters import Bytes, DateTime, DNParam from ipalib.parameters import Bytes, DateTime, DNParam, Principal
from ipalib.plugable import Registry from ipalib.plugable import Registry
from .virtual import VirtualCommand from .virtual import VirtualCommand
from .baseldap import pkey_to_value from .baseldap import pkey_to_value
from .service import split_any_principal
from .certprofile import validate_profile_id from .certprofile import validate_profile_id
from .caacl import acl_evaluate from .caacl import acl_evaluate
from ipalib.text import _ from ipalib.text import _
from ipalib.request import context from ipalib.request import context
from ipalib import output from ipalib import output
from .service import validate_principal from ipapython import kerberos
from ipapython.dn import DN from ipapython.dn import DN
from ipaserver.plugins.service import normalize_principal, validate_realm
if six.PY3: if six.PY3:
unicode = str unicode = str
@ -216,35 +216,21 @@ def normalize_serial_number(num):
return unicode(num) return unicode(num)
def get_host_from_principal(principal):
"""
Given a principal with or without a realm return the
host portion.
"""
validate_principal(None, principal)
realm = principal.find('@')
slash = principal.find('/')
if realm == -1:
realm = len(principal)
hostname = principal[slash+1:realm]
return hostname
def ca_enabled_check(): def ca_enabled_check():
if not api.Command.ca_is_enabled()['result']: if not api.Command.ca_is_enabled()['result']:
raise errors.NotFound(reason=_('CA is not configured')) raise errors.NotFound(reason=_('CA is not configured'))
def caacl_check(principal_type, principal_string, ca, profile_id): def caacl_check(principal_type, principal, ca, profile_id):
principal_type_map = {USER: 'user', HOST: 'host', SERVICE: 'service'} principal_type_map = {USER: 'user', HOST: 'host', SERVICE: 'service'}
if not acl_evaluate( if not acl_evaluate(
principal_type_map[principal_type], principal_type_map[principal_type],
principal_string, ca, profile_id): principal, ca, profile_id):
raise errors.ACIError(info=_( raise errors.ACIError(info=_(
"Principal '%(principal)s' " "Principal '%(principal)s' "
"is not permitted to use CA '%(ca)s' " "is not permitted to use CA '%(ca)s' "
"with profile '%(profile_id)s' for certificate issuance." "with profile '%(profile_id)s' for certificate issuance."
) % dict( ) % dict(
principal=principal_string, principal=unicode(principal),
ca=ca, ca=ca,
profile_id=profile_id profile_id=profile_id
) )
@ -386,10 +372,12 @@ class cert_request(Create, BaseCertMethod, VirtualCommand):
operation="request certificate" operation="request certificate"
takes_options = ( takes_options = (
Str( Principal(
'principal', 'principal',
validate_realm,
label=_('Principal'), label=_('Principal'),
doc=_('Principal for this certificate (e.g. HTTP/test.example.com)'), doc=_('Principal for this certificate (e.g. HTTP/test.example.com)'),
normalizer=normalize_principal
), ),
Flag( Flag(
'add', 'add',
@ -432,27 +420,29 @@ class cert_request(Create, BaseCertMethod, VirtualCommand):
taskgroup (directly or indirectly via role membership). taskgroup (directly or indirectly via role membership).
""" """
principal_string = kw.get('principal') principal = kw.get('principal')
principal = split_any_principal(principal_string) principal_string = unicode(principal)
servicename, principal_name, realm = principal
if servicename is None: if principal.is_user:
principal_type = USER principal_type = USER
elif servicename == 'host': elif principal.is_host:
principal_type = HOST principal_type = HOST
else: else:
principal_type = SERVICE principal_type = SERVICE
bind_principal = split_any_principal(getattr(context, 'principal')) bind_principal = kerberos.Principal(
bind_service, bind_name, bind_realm = bind_principal getattr(context, 'principal'))
bind_principal_string = unicode(bind_principal)
if bind_service is None: if bind_principal.is_user:
bind_principal_type = USER bind_principal_type = USER
elif bind_service == 'host': elif bind_principal.is_host:
bind_principal_type = HOST bind_principal_type = HOST
else: else:
bind_principal_type = SERVICE bind_principal_type = SERVICE
if bind_principal != principal and bind_principal_type != HOST: if (bind_principal_string != principal_string and
bind_principal_type != HOST):
# Can the bound principal request certs for another principal? # Can the bound principal request certs for another principal?
self.check_access() self.check_access()
@ -463,7 +453,7 @@ class cert_request(Create, BaseCertMethod, VirtualCommand):
bypass_caacl = False bypass_caacl = False
if not bypass_caacl: if not bypass_caacl:
caacl_check(principal_type, principal_string, ca, profile_id) caacl_check(principal_type, principal, ca, profile_id)
try: try:
subject = pkcs10.get_subject(csr) subject = pkcs10.get_subject(csr)
@ -474,7 +464,8 @@ class cert_request(Create, BaseCertMethod, VirtualCommand):
error=_("Failure decoding Certificate Signing Request: %s") % e) error=_("Failure decoding Certificate Signing Request: %s") % e)
# self-service and host principals may bypass SAN permission check # self-service and host principals may bypass SAN permission check
if bind_principal != principal and bind_principal_type != HOST: if (bind_principal_string != principal_string
and bind_principal_type != HOST):
if '2.5.29.17' in extensions: if '2.5.29.17' in extensions:
self.check_access('request certificate with subjectaltname') self.check_access('request certificate with subjectaltname')
@ -486,9 +477,11 @@ class cert_request(Create, BaseCertMethod, VirtualCommand):
if principal_type == SERVICE: if principal_type == SERVICE:
principal_obj = api.Command['service_show'](principal_string, all=True) principal_obj = api.Command['service_show'](principal_string, all=True)
elif principal_type == HOST: elif principal_type == HOST:
principal_obj = api.Command['host_show'](principal_name, all=True) principal_obj = api.Command['host_show'](
principal.hostname, all=True)
elif principal_type == USER: elif principal_type == USER:
principal_obj = api.Command['user_show'](principal_name, all=True) principal_obj = api.Command['user_show'](
principal.username, all=True)
except errors.NotFound as e: except errors.NotFound as e:
if add: if add:
if principal_type == SERVICE: if principal_type == SERVICE:
@ -512,14 +505,14 @@ class cert_request(Create, BaseCertMethod, VirtualCommand):
error=_("No Common Name was found in subject of request.")) error=_("No Common Name was found in subject of request."))
if principal_type in (SERVICE, HOST): if principal_type in (SERVICE, HOST):
if cn.lower() != principal_name.lower(): if cn.lower() != principal.hostname.lower():
raise errors.ACIError( raise errors.ACIError(
info=_("hostname in subject of request '%(cn)s' " info=_("hostname in subject of request '%(cn)s' "
"does not match principal hostname '%(hostname)s'") "does not match principal hostname '%(hostname)s'")
% dict(cn=cn, hostname=principal_name)) % dict(cn=cn, hostname=principal.hostname))
elif principal_type == USER: elif principal_type == USER:
# check user name # check user name
if cn != principal_name: if cn != principal.username:
raise errors.ValidationError( raise errors.ValidationError(
name='csr', name='csr',
error=_("DN commonName does not match user's login") error=_("DN commonName does not match user's login")
@ -545,13 +538,11 @@ class cert_request(Create, BaseCertMethod, VirtualCommand):
if name_type == pkcs10.SAN_DNSNAME: if name_type == pkcs10.SAN_DNSNAME:
name = unicode(name) name = unicode(name)
alt_principal_obj = None alt_principal_obj = None
alt_principal_string = None alt_principal_string = unicode(principal)
try: try:
if principal_type == HOST: if principal_type == HOST:
alt_principal_string = 'host/%s@%s' % (name, realm)
alt_principal_obj = api.Command['host_show'](name, all=True) alt_principal_obj = api.Command['host_show'](name, all=True)
elif principal_type == SERVICE: elif principal_type == SERVICE:
alt_principal_string = '%s/%s@%s' % (servicename, name, realm)
alt_principal_obj = api.Command['service_show']( alt_principal_obj = api.Command['service_show'](
alt_principal_string, all=True) alt_principal_string, all=True)
elif principal_type == USER: elif principal_type == USER:
@ -574,11 +565,10 @@ class cert_request(Create, BaseCertMethod, VirtualCommand):
"Insufficient privilege to create a certificate " "Insufficient privilege to create a certificate "
"with subject alt name '%s'.") % name) "with subject alt name '%s'.") % name)
if alt_principal_string is not None and not bypass_caacl: if alt_principal_string is not None and not bypass_caacl:
caacl_check( caacl_check(principal_type, principal, ca, profile_id)
principal_type, alt_principal_string, ca, profile_id)
elif name_type in (pkcs10.SAN_OTHERNAME_KRB5PRINCIPALNAME, elif name_type in (pkcs10.SAN_OTHERNAME_KRB5PRINCIPALNAME,
pkcs10.SAN_OTHERNAME_UPN): pkcs10.SAN_OTHERNAME_UPN):
if split_any_principal(name) != principal: if name != principal_string:
raise errors.ACIError( raise errors.ACIError(
info=_("Principal '%s' in subject alt name does not " info=_("Principal '%s' in subject alt name does not "
"match requested principal") % name) "match requested principal") % name)
@ -619,9 +609,9 @@ class cert_request(Create, BaseCertMethod, VirtualCommand):
if principal_type == SERVICE: if principal_type == SERVICE:
api.Command['service_mod'](principal_string, **kwargs) api.Command['service_mod'](principal_string, **kwargs)
elif principal_type == HOST: elif principal_type == HOST:
api.Command['host_mod'](principal_name, **kwargs) api.Command['host_mod'](principal.hostname, **kwargs)
elif principal_type == USER: elif principal_type == USER:
api.Command['user_mod'](principal_name, **kwargs) api.Command['user_mod'](principal.username, **kwargs)
return dict( return dict(
result=result, result=result,
@ -748,10 +738,10 @@ class cert_show(Retrieve, CertMethod, VirtualCommand):
self.check_access() self.check_access()
except errors.ACIError as acierr: except errors.ACIError as acierr:
self.debug("Not granted by ACI to retrieve certificate, looking at principal") self.debug("Not granted by ACI to retrieve certificate, looking at principal")
bind_principal = getattr(context, 'principal') bind_principal = kerberos.Principal(getattr(context, 'principal'))
if not bind_principal.startswith('host/'): if not bind_principal.is_host:
raise acierr raise acierr
hostname = get_host_from_principal(bind_principal) hostname = bind_principal.hostname
ca_obj = api.Command.ca_show(options['cacn'])['result'] ca_obj = api.Command.ca_show(options['cacn'])['result']
issuer_dn = ca_obj['ipacasubjectdn'][0] issuer_dn = ca_obj['ipacasubjectdn'][0]

View File

@ -25,6 +25,7 @@ import six
from ipalib import api, errors, util from ipalib import api, errors, util
from ipalib import messages from ipalib import messages
from ipalib import Str, Flag, Bytes from ipalib import Str, Flag, Bytes
from ipalib.parameters import Principal
from ipalib.plugable import Registry from ipalib.plugable import Registry
from .baseldap import (LDAPQuery, LDAPObject, LDAPCreate, from .baseldap import (LDAPQuery, LDAPObject, LDAPCreate,
LDAPDelete, LDAPUpdate, LDAPSearch, LDAPDelete, LDAPUpdate, LDAPSearch,
@ -32,7 +33,8 @@ from .baseldap import (LDAPQuery, LDAPObject, LDAPCreate,
LDAPRemoveMember, host_is_master, LDAPRemoveMember, host_is_master,
pkey_to_value, add_missing_object_class, pkey_to_value, add_missing_object_class,
LDAPAddAttribute, LDAPRemoveAttribute) LDAPAddAttribute, LDAPRemoveAttribute)
from .service import (split_principal, validate_certificate, from ipaserver.plugins.service import (
validate_realm, normalize_principal, validate_certificate,
set_certificate_attrs, ticket_flags_params, update_krbticketflags, set_certificate_attrs, ticket_flags_params, update_krbticketflags,
set_kerberos_attrs, rename_ipaallowedtoperform_from_ldap, set_kerberos_attrs, rename_ipaallowedtoperform_from_ldap,
rename_ipaallowedtoperform_to_ldap, revoke_certs) rename_ipaallowedtoperform_to_ldap, revoke_certs)
@ -56,6 +58,7 @@ from ipapython.ipautil import ipa_generate_password, CheckedIPAddress
from ipapython.dnsutil import DNSName from ipapython.dnsutil import DNSName
from ipapython.ssh import SSHPublicKey from ipapython.ssh import SSHPublicKey
from ipapython.dn import DN from ipapython.dn import DN
from ipapython import kerberos
from functools import reduce from functools import reduce
if six.PY3: if six.PY3:
@ -509,8 +512,11 @@ class host(LDAPObject):
label=_('Revocation reason'), label=_('Revocation reason'),
flags={'virtual_attribute', 'no_create', 'no_update', 'no_search'}, flags={'virtual_attribute', 'no_create', 'no_update', 'no_search'},
), ),
Str('krbprincipalname?', Principal(
'krbprincipalname?',
validate_realm,
label=_('Principal name'), label=_('Principal name'),
normalizer=normalize_principal,
flags=['no_create', 'no_update', 'no_search'], flags=['no_create', 'no_update', 'no_search'],
), ),
Str('macaddress*', Str('macaddress*',
@ -758,8 +764,9 @@ class host_del(LDAPDelete):
break break
else: else:
for entry_attrs in services: for entry_attrs in services:
principal = entry_attrs['krbprincipalname'][0] principal = kerberos.Principal(
(service, hostname, realm) = split_principal(principal) entry_attrs['krbprincipalname'][0])
hostname = principal.hostname
if hostname.lower() == fqdn: if hostname.lower() == fqdn:
api.Command['service_del'](principal) api.Command['service_del'](principal)
updatedns = options.get('updatedns', False) updatedns = options.get('updatedns', False)
@ -830,10 +837,13 @@ class host_mod(LDAPUpdate):
member_attributes = ['managedby'] member_attributes = ['managedby']
takes_options = LDAPUpdate.takes_options + ( takes_options = LDAPUpdate.takes_options + (
Str('krbprincipalname?', Principal(
'krbprincipalname?',
validate_realm,
cli_name='principalname', cli_name='principalname',
label=_('Principal name'), label=_('Principal name'),
doc=_('Kerberos principal name for this host'), doc=_('Kerberos principal name for this host'),
normalizer=normalize_principal,
attribute=True, attribute=True,
), ),
Flag('updatedns?', Flag('updatedns?',
@ -1155,8 +1165,9 @@ class host_disable(LDAPQuery):
break break
else: else:
for entry_attrs in services: for entry_attrs in services:
principal = entry_attrs['krbprincipalname'][0] principal = kerberos.Principal(
(service, hostname, realm) = split_principal(principal) entry_attrs['krbprincipalname'][0])
hostname = principal.hostname
if hostname.lower() == fqdn: if hostname.lower() == fqdn:
try: try:
api.Command['service_disable'](principal) api.Command['service_disable'](principal)

View File

@ -17,15 +17,22 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import six
from ipalib import api, errors, krb_utils from ipalib import api, errors, krb_utils
from ipalib import Command from ipalib import Command
from ipalib import Str, Password from ipalib import Password
from ipalib import _ from ipalib import _
from ipalib import output from ipalib import output
from ipalib.parameters import Principal
from ipalib.plugable import Registry from ipalib.plugable import Registry
from .baseuser import validate_principal, normalize_principal
from ipalib.request import context from ipalib.request import context
from ipapython import kerberos
from ipapython.dn import DN from ipapython.dn import DN
from ipaserver.plugins.service import validate_realm, normalize_principal
if six.PY3:
unicode = str
__doc__ = _(""" __doc__ = _("""
Set a user's password Set a user's password
@ -59,7 +66,7 @@ def get_current_password(principal):
be ignored later. be ignored later.
""" """
current_principal = krb_utils.get_principal() current_principal = krb_utils.get_principal()
if current_principal == normalize_principal(principal): if current_principal == unicode(normalize_principal(principal)):
return None return None
else: else:
return MAGIC_VALUE return MAGIC_VALUE
@ -69,12 +76,14 @@ class passwd(Command):
__doc__ = _("Set a user's password.") __doc__ = _("Set a user's password.")
takes_args = ( takes_args = (
Str('principal', validate_principal, Principal(
'principal',
validate_realm,
cli_name='user', cli_name='user',
label=_('User name'), label=_('User name'),
primary_key=True, primary_key=True,
autofill=True, autofill=True,
default_from=lambda: krb_utils.get_principal(), default_from=lambda: kerberos.Principal(krb_utils.get_principal()),
normalizer=lambda value: normalize_principal(value), normalizer=lambda value: normalize_principal(value),
), ),
Password('password', Password('password',
@ -114,6 +123,8 @@ class passwd(Command):
""" """
ldap = self.api.Backend.ldap2 ldap = self.api.Backend.ldap2
principal = unicode(principal)
entry_attrs = ldap.find_entry_by_attr( entry_attrs = ldap.find_entry_by_attr(
'krbprincipalname', principal, 'posixaccount', [''], 'krbprincipalname', principal, 'posixaccount', [''],
DN(api.env.container_user, api.env.basedn) DN(api.env.container_user, api.env.basedn)

View File

@ -23,6 +23,7 @@ import six
from ipalib import api, errors, messages from ipalib import api, errors, messages
from ipalib import Bytes, StrEnum, Bool, Str, Flag from ipalib import Bytes, StrEnum, Bool, Str, Flag
from ipalib.parameters import Principal
from ipalib.plugable import Registry from ipalib.plugable import Registry
from .baseldap import ( from .baseldap import (
host_is_master, host_is_master,
@ -43,6 +44,7 @@ from ipalib import x509
from ipalib import _, ngettext from ipalib import _, ngettext
from ipalib import util from ipalib import util
from ipalib import output from ipalib import output
from ipapython import kerberos
from ipapython.dn import DN from ipapython.dn import DN
import nss.nss as nss import nss.nss as nss
@ -176,55 +178,29 @@ _ticket_flags_map = {
_ticket_flags_default = _ticket_flags_map['ipakrbrequirespreauth'] _ticket_flags_default = _ticket_flags_map['ipakrbrequirespreauth']
def split_any_principal(principal):
service = hostname = realm = None
# Break down the principal into its component parts, which may or def validate_realm(ugettext, principal):
# may not include the realm. """
sp = principal.split('/') Check that the principal's realm matches IPA realm if present
name_and_realm = None """
if len(sp) > 2: realm = principal.realm
raise errors.MalformedServicePrincipal(reason=_('unable to determine service')) if realm is not None and realm != api.env.realm:
elif len(sp) == 2: raise errors.RealmMismatch()
service = sp[0]
if len(service) == 0:
raise errors.MalformedServicePrincipal(reason=_('blank service'))
name_and_realm = sp[1]
else:
name_and_realm = sp[0]
sr = name_and_realm.split('@')
if len(sr) > 2:
raise errors.MalformedServicePrincipal(
reason=_('unable to determine realm'))
hostname = sr[0].lower() def normalize_principal(value):
if len(sr) == 2: """
realm = sr[1].upper() Ensure that the name in the principal is lower-case. The realm is
# At some point we'll support multiple realms upper-case by convention but it isn't required.
if realm != api.env.realm:
raise errors.RealmMismatch()
else:
realm = api.env.realm
# Note that realm may be None. The principal is validated at this point.
return service, hostname, realm """
try:
principal = kerberos.Principal(value, realm=api.env.realm)
except ValueError:
raise errors.ValidationError(
name='principal', reason=_("Malformed principal"))
def split_principal(principal):
service, name, realm = split_any_principal(principal)
if service is None:
raise errors.MalformedServicePrincipal(reason=_('missing service'))
return service, name, realm
def validate_principal(ugettext, principal):
(service, hostname, principal) = split_principal(principal)
return None
def normalize_principal(principal):
# The principal is already validated when it gets here
(service, hostname, realm) = split_principal(principal)
# Put the principal back together again
principal = '%s/%s@%s' % (service, hostname, realm)
return unicode(principal) return unicode(principal)
def validate_certificate(ugettext, cert): def validate_certificate(ugettext, cert):
@ -291,16 +267,16 @@ def set_certificate_attrs(entry_attrs):
entry_attrs['md5_fingerprint'] = unicode(nss.data_to_hex(nss.md5_digest(cert.der_data), 64)[0]) entry_attrs['md5_fingerprint'] = unicode(nss.data_to_hex(nss.md5_digest(cert.der_data), 64)[0])
entry_attrs['sha1_fingerprint'] = unicode(nss.data_to_hex(nss.sha1_digest(cert.der_data), 64)[0]) entry_attrs['sha1_fingerprint'] = unicode(nss.data_to_hex(nss.sha1_digest(cert.der_data), 64)[0])
def check_required_principal(ldap, hostname, service): def check_required_principal(ldap, principal):
""" """
Raise an error if the host of this prinicipal is an IPA master and one Raise an error if the host of this prinicipal is an IPA master and one
of the principals required for proper execution. of the principals required for proper execution.
""" """
try: try:
host_is_master(ldap, hostname) host_is_master(ldap, principal.hostname)
except errors.ValidationError as e: except errors.ValidationError as e:
service_types = ['HTTP', 'ldap', 'DNS', 'dogtagldap'] service_types = ['HTTP', 'ldap', 'DNS', 'dogtagldap']
if service in service_types: if principal.service_name in service_types:
raise errors.ValidationError(name='principal', error=_('This principal is required by the IPA master')) raise errors.ValidationError(name='principal', error=_('This principal is required by the IPA master'))
def update_krbticketflags(ldap, entry_attrs, attrs_list, options, existing): def update_krbticketflags(ldap, entry_attrs, attrs_list, options, existing):
@ -457,12 +433,15 @@ class service(LDAPObject):
label_singular = _('Service') label_singular = _('Service')
takes_params = ( takes_params = (
Str('krbprincipalname', validate_principal, Principal(
'krbprincipalname',
validate_realm,
cli_name='principal', cli_name='principal',
label=_('Principal'), label=_('Principal'),
doc=_('Service principal'), doc=_('Service principal'),
primary_key=True, primary_key=True,
normalizer=lambda value: normalize_principal(value), normalizer=normalize_principal,
require_service=True
), ),
Bytes('usercertificate*', validate_certificate, Bytes('usercertificate*', validate_certificate,
cli_name='certificate', cli_name='certificate',
@ -560,8 +539,10 @@ class service_add(LDAPCreate):
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options): def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
assert isinstance(dn, DN) assert isinstance(dn, DN)
(service, hostname, realm) = split_principal(keys[-1]) principal = keys[-1]
if service.lower() == 'host' and not options['force']: hostname = principal.hostname
if principal.is_host and not options['force']:
raise errors.HostService() raise errors.HostService()
try: try:
@ -619,8 +600,7 @@ class service_del(LDAPDelete):
# In the case of services we don't want IPA master services to be # In the case of services we don't want IPA master services to be
# deleted. This is a limited few though. If the user has their own # deleted. This is a limited few though. If the user has their own
# custom services allow them to manage them. # custom services allow them to manage them.
(service, hostname, realm) = split_principal(keys[-1]) check_required_principal(ldap, keys[-1])
check_required_principal(ldap, hostname, service)
if self.api.Command.ca_is_enabled()['result']: if self.api.Command.ca_is_enabled()['result']:
try: try:
entry_attrs = ldap.get_entry(dn, ['usercertificate']) entry_attrs = ldap.get_entry(dn, ['usercertificate'])
@ -647,8 +627,6 @@ class service_mod(LDAPUpdate):
self.obj.validate_ipakrbauthzdata(entry_attrs) self.obj.validate_ipakrbauthzdata(entry_attrs)
(service, hostname, realm) = split_principal(keys[-1])
# verify certificates # verify certificates
certs = entry_attrs.get('usercertificate') or [] certs = entry_attrs.get('usercertificate') or []
certs_der = [x509.normalize_certificate(c) for c in certs] certs_der = [x509.normalize_certificate(c) for c in certs]
@ -873,8 +851,7 @@ class service_disable(LDAPQuery):
dn = self.obj.get_dn(*keys, **options) dn = self.obj.get_dn(*keys, **options)
entry_attrs = ldap.get_entry(dn, ['usercertificate']) entry_attrs = ldap.get_entry(dn, ['usercertificate'])
(service, hostname, realm) = split_principal(keys[-1]) check_required_principal(ldap, keys[-1])
check_required_principal(ldap, hostname, service)
# See if we do any work at all here and if not raise an exception # See if we do any work at all here and if not raise an exception
done_work = False done_work = False

View File

@ -17,25 +17,31 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
import six
from ipalib.frontend import Command, Object from ipalib.frontend import Command, Object
from ipalib import api, errors from ipalib import api, errors
from ipalib import Bytes, Flag, Str, StrEnum from ipalib import Bytes, Flag, Str, StrEnum
from ipalib import output from ipalib import output
from ipalib.crud import PKQuery, Retrieve from ipalib.crud import PKQuery, Retrieve
from ipalib.parameters import Principal
from ipalib.plugable import Registry from ipalib.plugable import Registry
from .baseldap import LDAPObject, LDAPCreate, LDAPDelete,\ from .baseldap import LDAPObject, LDAPCreate, LDAPDelete,\
LDAPSearch, LDAPUpdate, LDAPRetrieve, LDAPAddMember, LDAPRemoveMember,\ LDAPSearch, LDAPUpdate, LDAPRetrieve, LDAPAddMember, LDAPRemoveMember,\
LDAPModMember, pkey_to_value LDAPModMember, pkey_to_value
from ipalib.request import context from ipalib.request import context
from .baseuser import split_principal from .service import normalize_principal, validate_realm
from .service import normalize_principal
from ipalib import _, ngettext from ipalib import _, ngettext
from ipapython import kerberos
from ipapython.dn import DN from ipapython.dn import DN
if api.env.in_server: if api.env.in_server:
import pki.account import pki.account
import pki.key import pki.key
if six.PY3:
unicode = str
__doc__ = _(""" __doc__ = _("""
Vaults Vaults
""") + _(""" """) + _("""
@ -191,8 +197,9 @@ EXAMPLES:
register = Registry() register = Registry()
vault_options = ( vault_options = (
Str( Principal(
'service?', 'service?',
validate_realm,
doc=_('Service name of the service vault'), doc=_('Service name of the service vault'),
normalizer=normalize_principal, normalizer=normalize_principal,
), ),
@ -342,17 +349,15 @@ class vaultcontainer(LDAPObject):
parent_dn = super(vaultcontainer, self).get_dn(*keys, **options) parent_dn = super(vaultcontainer, self).get_dn(*keys, **options)
if not count: if not count:
principal = getattr(context, 'principal') principal = kerberos.Principal(getattr(context, 'principal'))
if principal.startswith('host/'): if principal.is_host:
raise errors.NotImplementedError( raise errors.NotImplementedError(
reason=_('Host is not supported')) reason=_('Host is not supported'))
elif principal.is_service:
(name, realm) = split_principal(principal) service = unicode(principal)
if '/' in name:
service = principal
else: else:
user = name user = principal.username
if service: if service:
dn = DN(('cn', service), ('cn', 'services'), parent_dn) dn = DN(('cn', service), ('cn', 'services'), parent_dn)
@ -660,17 +665,15 @@ class vault(LDAPObject):
rdns = DN(*dn[:-len(container_dn)]) rdns = DN(*dn[:-len(container_dn)])
if not count: if not count:
principal = getattr(context, 'principal') principal = kerberos.Principal(getattr(context, 'principal'))
if principal.startswith('host/'): if principal.is_host:
raise errors.NotImplementedError( raise errors.NotImplementedError(
reason=_('Host is not supported')) reason=_('Host is not supported'))
elif principal.is_service:
(name, realm) = split_principal(principal) service = unicode(principal)
if '/' in name:
service = principal
else: else:
user = name user = principal.username
if service: if service:
parent_dn = DN(('cn', service), ('cn', 'services'), container_dn) parent_dn = DN(('cn', service), ('cn', 'services'), container_dn)
@ -770,12 +773,11 @@ class vault_add_internal(LDAPCreate):
raise errors.InvocationError( raise errors.InvocationError(
format=_('KRA service is not enabled')) format=_('KRA service is not enabled'))
principal = getattr(context, 'principal') principal = kerberos.Principal(getattr(context, 'principal'))
(name, realm) = split_principal(principal) if principal.is_service:
if '/' in name: owner_dn = self.api.Object.service.get_dn(unicode(principal))
owner_dn = self.api.Object.service.get_dn(name)
else: else:
owner_dn = self.api.Object.user.get_dn(name) owner_dn = self.api.Object.user.get_dn(principal.username)
parent_dn = DN(*dn[1:]) parent_dn = DN(*dn[1:])

View File

@ -357,6 +357,7 @@ class TestHostWithService(XMLRPC_test):
result=dict( result=dict(
dn=service1dn, dn=service1dn,
krbprincipalname=[service1], krbprincipalname=[service1],
krbcanonicalname=[service1],
objectclass=objectclasses.service, objectclass=objectclasses.service,
managedby_host=[host.fqdn], managedby_host=[host.fqdn],
ipauniqueid=[fuzzy_uuid], ipauniqueid=[fuzzy_uuid],

View File

@ -193,6 +193,7 @@ class test_service(Declarative):
result=dict( result=dict(
dn=service1dn, dn=service1dn,
krbprincipalname=[service1], krbprincipalname=[service1],
krbcanonicalname=[service1],
objectclass=objectclasses.service, objectclass=objectclasses.service,
ipauniqueid=[fuzzy_uuid], ipauniqueid=[fuzzy_uuid],
managedby_host=[fqdn1], managedby_host=[fqdn1],
@ -262,6 +263,7 @@ class test_service(Declarative):
dict( dict(
dn=service1dn, dn=service1dn,
krbprincipalname=[service1], krbprincipalname=[service1],
krbcanonicalname=service1,
managedby_host=[fqdn1], managedby_host=[fqdn1],
has_keytab=False, has_keytab=False,
), ),
@ -281,6 +283,7 @@ class test_service(Declarative):
dict( dict(
dn=service1dn, dn=service1dn,
krbprincipalname=[service1], krbprincipalname=[service1],
krbcanonicalname=service1,
has_keytab=False, has_keytab=False,
), ),
], ],
@ -619,7 +622,9 @@ class test_service(Declarative):
dict( dict(
desc='Create service with malformed principal "foo"', desc='Create service with malformed principal "foo"',
command=('service_add', [u'foo'], {}), command=('service_add', [u'foo'], {}),
expected=errors.MalformedServicePrincipal(reason='missing service') expected=errors.ValidationError(
name='principal',
error='Service principal is required')
), ),
@ -715,6 +720,7 @@ class test_service_in_role(Declarative):
result=dict( result=dict(
dn=service1dn, dn=service1dn,
krbprincipalname=[service1], krbprincipalname=[service1],
krbcanonicalname=[service1],
objectclass=objectclasses.service, objectclass=objectclasses.service,
ipauniqueid=[fuzzy_uuid], ipauniqueid=[fuzzy_uuid],
managedby_host=[fqdn1], managedby_host=[fqdn1],
@ -919,6 +925,7 @@ class test_service_allowed_to(Declarative):
result=dict( result=dict(
dn=service1dn, dn=service1dn,
krbprincipalname=[service1], krbprincipalname=[service1],
krbcanonicalname=[service1],
objectclass=objectclasses.service, objectclass=objectclasses.service,
ipauniqueid=[fuzzy_uuid], ipauniqueid=[fuzzy_uuid],
managedby_host=[fqdn1], managedby_host=[fqdn1],

View File

@ -345,9 +345,9 @@ class TestCreateInvalidAttributes(XMLRPC_test):
stageduser.ensure_missing() stageduser.ensure_missing()
command = stageduser.make_create_command( command = stageduser.make_create_command(
options={u'krbprincipalname': invalidrealm2}) options={u'krbprincipalname': invalidrealm2})
with raises_exact(errors.MalformedUserPrincipal( with raises_exact(errors.ConversionError(
message=u'Principal is not of the form user@REALM: \'%s\'' % name='principal', error="Malformed principal: '{}'".format(
invalidrealm2)): invalidrealm2))):
command() command()

View File

@ -806,8 +806,9 @@ class TestPrincipals(XMLRPC_test):
) )
command = testuser.make_create_command() command = testuser.make_create_command()
with raises_exact(errors.MalformedUserPrincipal( with raises_exact(errors.ConversionError(
principal=u'tuser1@BAD@NOTFOUND.ORG')): name='principal', error="Malformed principal: '{}'".format(
testuser.kwargs['krbprincipalname']))):
command() command()
def test_set_principal_expiration(self, user): def test_set_principal_expiration(self, user):