mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
Add plugin to manage service constraint delegations
Service Constraints are the delegation model used by ipa-kdb to grant service A to obtain a TGT for a user against service B. https://fedorahosted.org/freeipa/ticket/3644 Reviewed-By: Martin Basti <mbasti@redhat.com>
This commit is contained in:
committed by
Jan Cholasta
parent
7f7c247bb5
commit
a92328452d
16
ACI.txt
16
ACI.txt
@@ -212,6 +212,22 @@ dn: cn=services,cn=accounts,dc=ipa,dc=example
|
|||||||
aci: (targetattr = "createtimestamp || entryusn || ipakrbauthzdata || ipakrbprincipalalias || ipauniqueid || krbcanonicalname || krblastpwdchange || krbobjectreferences || krbpasswordexpiration || krbprincipalaliases || krbprincipalexpiration || krbprincipalname || managedby || memberof || modifytimestamp || objectclass || usercertificate")(targetfilter = "(objectclass=ipaservice)")(version 3.0;acl "permission:System: Read Services";allow (compare,read,search) userdn = "ldap:///all";)
|
aci: (targetattr = "createtimestamp || entryusn || ipakrbauthzdata || ipakrbprincipalalias || ipauniqueid || krbcanonicalname || krblastpwdchange || krbobjectreferences || krbpasswordexpiration || krbprincipalaliases || krbprincipalexpiration || krbprincipalname || managedby || memberof || modifytimestamp || objectclass || usercertificate")(targetfilter = "(objectclass=ipaservice)")(version 3.0;acl "permission:System: Read Services";allow (compare,read,search) userdn = "ldap:///all";)
|
||||||
dn: cn=services,cn=accounts,dc=ipa,dc=example
|
dn: cn=services,cn=accounts,dc=ipa,dc=example
|
||||||
aci: (targetfilter = "(objectclass=ipaservice)")(version 3.0;acl "permission:System: Remove Services";allow (delete) groupdn = "ldap:///cn=System: Remove Services,cn=permissions,cn=pbac,dc=ipa,dc=example";)
|
aci: (targetfilter = "(objectclass=ipaservice)")(version 3.0;acl "permission:System: Remove Services";allow (delete) groupdn = "ldap:///cn=System: Remove Services,cn=permissions,cn=pbac,dc=ipa,dc=example";)
|
||||||
|
dn: cn=s4u2proxy,cn=etc,dc=ipa,dc=example
|
||||||
|
aci: (targetfilter = "(objectclass=groupofprincipals)")(version 3.0;acl "permission:System: Add Service Delegations";allow (add) groupdn = "ldap:///cn=System: Add Service Delegations,cn=permissions,cn=pbac,dc=ipa,dc=example";)
|
||||||
|
dn: cn=s4u2proxy,cn=etc,dc=ipa,dc=example
|
||||||
|
aci: (targetattr = "ipaallowedtarget || memberprincipal")(targetfilter = "(objectclass=groupofprincipals)")(version 3.0;acl "permission:System: Modify Service Delegation Membership";allow (write) groupdn = "ldap:///cn=System: Modify Service Delegation Membership,cn=permissions,cn=pbac,dc=ipa,dc=example";)
|
||||||
|
dn: cn=s4u2proxy,cn=etc,dc=ipa,dc=example
|
||||||
|
aci: (targetattr = "cn || createtimestamp || entryusn || ipaallowedtarget || memberprincipal || modifytimestamp || objectclass")(targetfilter = "(objectclass=groupofprincipals)")(version 3.0;acl "permission:System: Read Service Delegations";allow (compare,read,search) groupdn = "ldap:///cn=System: Read Service Delegations,cn=permissions,cn=pbac,dc=ipa,dc=example";)
|
||||||
|
dn: cn=s4u2proxy,cn=etc,dc=ipa,dc=example
|
||||||
|
aci: (targetfilter = "(objectclass=groupofprincipals)")(version 3.0;acl "permission:System: Remove Service Delegations";allow (delete) groupdn = "ldap:///cn=System: Remove Service Delegations,cn=permissions,cn=pbac,dc=ipa,dc=example";)
|
||||||
|
dn: cn=s4u2proxy,cn=etc,dc=ipa,dc=example
|
||||||
|
aci: (targetfilter = "(objectclass=groupofprincipals)")(version 3.0;acl "permission:System: Add Service Delegations";allow (add) groupdn = "ldap:///cn=System: Add Service Delegations,cn=permissions,cn=pbac,dc=ipa,dc=example";)
|
||||||
|
dn: cn=s4u2proxy,cn=etc,dc=ipa,dc=example
|
||||||
|
aci: (targetattr = "ipaallowedtarget || memberprincipal")(targetfilter = "(objectclass=groupofprincipals)")(version 3.0;acl "permission:System: Modify Service Delegation Membership";allow (write) groupdn = "ldap:///cn=System: Modify Service Delegation Membership,cn=permissions,cn=pbac,dc=ipa,dc=example";)
|
||||||
|
dn: cn=s4u2proxy,cn=etc,dc=ipa,dc=example
|
||||||
|
aci: (targetattr = "cn || createtimestamp || entryusn || ipaallowedtarget || memberprincipal || modifytimestamp || objectclass")(targetfilter = "(objectclass=groupofprincipals)")(version 3.0;acl "permission:System: Read Service Delegations";allow (compare,read,search) groupdn = "ldap:///cn=System: Read Service Delegations,cn=permissions,cn=pbac,dc=ipa,dc=example";)
|
||||||
|
dn: cn=s4u2proxy,cn=etc,dc=ipa,dc=example
|
||||||
|
aci: (targetfilter = "(objectclass=groupofprincipals)")(version 3.0;acl "permission:System: Remove Service Delegations";allow (delete) groupdn = "ldap:///cn=System: Remove Service Delegations,cn=permissions,cn=pbac,dc=ipa,dc=example";)
|
||||||
dn: cn=staged users,cn=accounts,cn=provisioning,dc=ipa,dc=example
|
dn: cn=staged users,cn=accounts,cn=provisioning,dc=ipa,dc=example
|
||||||
aci: (targetattr = "*")(target = "ldap:///uid=*,cn=staged users,cn=accounts,cn=provisioning,dc=ipa,dc=example")(targetfilter = "(objectclass=*)")(version 3.0;acl "permission:System: Add Stage Users by Provisioning and Administrators";allow (add) groupdn = "ldap:///cn=System: Add Stage Users by Provisioning and Administrators,cn=permissions,cn=pbac,dc=ipa,dc=example";)
|
aci: (targetattr = "*")(target = "ldap:///uid=*,cn=staged users,cn=accounts,cn=provisioning,dc=ipa,dc=example")(targetfilter = "(objectclass=*)")(version 3.0;acl "permission:System: Add Stage Users by Provisioning and Administrators";allow (add) groupdn = "ldap:///cn=System: Add Stage Users by Provisioning and Administrators,cn=permissions,cn=pbac,dc=ipa,dc=example";)
|
||||||
dn: cn=staged users,cn=accounts,cn=provisioning,dc=ipa,dc=example
|
dn: cn=staged users,cn=accounts,cn=provisioning,dc=ipa,dc=example
|
||||||
|
|||||||
153
API.txt
153
API.txt
@@ -3730,6 +3730,159 @@ option: Str('version?', exclude='webui')
|
|||||||
output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
|
output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
|
||||||
output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
|
output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
|
||||||
output: PrimaryKey('value', None, None)
|
output: PrimaryKey('value', None, None)
|
||||||
|
command: servicedelegationrule_add
|
||||||
|
args: 1,6,3
|
||||||
|
arg: Str('cn', attribute=True, cli_name='delegation_name', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_ .-]{0,253}[a-zA-Z0-9_.-]?$', primary_key=True, required=True)
|
||||||
|
option: Str('addattr*', cli_name='addattr', exclude='webui')
|
||||||
|
option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
|
||||||
|
option: Flag('no_members', autofill=True, default=False, exclude='webui')
|
||||||
|
option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
|
||||||
|
option: Str('setattr*', cli_name='setattr', exclude='webui')
|
||||||
|
option: Str('version?', exclude='webui')
|
||||||
|
output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
|
||||||
|
output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
|
||||||
|
output: PrimaryKey('value', None, None)
|
||||||
|
command: servicedelegationrule_add_member
|
||||||
|
args: 1,5,3
|
||||||
|
arg: Str('cn', attribute=True, cli_name='delegation_name', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_ .-]{0,253}[a-zA-Z0-9_.-]?$', primary_key=True, query=True, required=True)
|
||||||
|
option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
|
||||||
|
option: Flag('no_members', autofill=True, default=False, exclude='webui')
|
||||||
|
option: Str('principal*', alwaysask=True, cli_name='principals')
|
||||||
|
option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
|
||||||
|
option: Str('version?', exclude='webui')
|
||||||
|
output: Output('completed', <type 'int'>, None)
|
||||||
|
output: Output('failed', <type 'dict'>, None)
|
||||||
|
output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
|
||||||
|
command: servicedelegationrule_add_target
|
||||||
|
args: 1,5,3
|
||||||
|
arg: Str('cn', attribute=True, cli_name='delegation_name', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_ .-]{0,253}[a-zA-Z0-9_.-]?$', primary_key=True, query=True, required=True)
|
||||||
|
option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
|
||||||
|
option: Flag('no_members', autofill=True, default=False, exclude='webui')
|
||||||
|
option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
|
||||||
|
option: Str('servicedelegationtarget*', alwaysask=True, cli_name='servicedelegationtargets', csv=True)
|
||||||
|
option: Str('version?', exclude='webui')
|
||||||
|
output: Output('completed', <type 'int'>, None)
|
||||||
|
output: Output('failed', <type 'dict'>, None)
|
||||||
|
output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
|
||||||
|
command: servicedelegationrule_del
|
||||||
|
args: 1,2,3
|
||||||
|
arg: Str('cn', attribute=True, cli_name='delegation_name', maxlength=255, multivalue=True, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_ .-]{0,253}[a-zA-Z0-9_.-]?$', primary_key=True, query=True, required=True)
|
||||||
|
option: Flag('continue', autofill=True, cli_name='continue', default=False)
|
||||||
|
option: Str('version?', exclude='webui')
|
||||||
|
output: Output('result', <type 'dict'>, None)
|
||||||
|
output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
|
||||||
|
output: ListOfPrimaryKeys('value', None, None)
|
||||||
|
command: servicedelegationrule_find
|
||||||
|
args: 1,8,4
|
||||||
|
arg: Str('criteria?', noextrawhitespace=False)
|
||||||
|
option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
|
||||||
|
option: Str('cn', attribute=True, autofill=False, cli_name='delegation_name', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_ .-]{0,253}[a-zA-Z0-9_.-]?$', primary_key=True, query=True, required=False)
|
||||||
|
option: Flag('no_members', autofill=True, default=False, exclude='webui')
|
||||||
|
option: Flag('pkey_only?', autofill=True, default=False)
|
||||||
|
option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
|
||||||
|
option: Int('sizelimit?', autofill=False, minvalue=0)
|
||||||
|
option: Int('timelimit?', autofill=False, minvalue=0)
|
||||||
|
option: Str('version?', exclude='webui')
|
||||||
|
output: Output('count', <type 'int'>, None)
|
||||||
|
output: ListOfEntries('result', (<type 'list'>, <type 'tuple'>), Gettext('A list of LDAP entries', domain='ipa', localedir=None))
|
||||||
|
output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
|
||||||
|
output: Output('truncated', <type 'bool'>, None)
|
||||||
|
command: servicedelegationrule_remove_member
|
||||||
|
args: 1,5,3
|
||||||
|
arg: Str('cn', attribute=True, cli_name='delegation_name', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_ .-]{0,253}[a-zA-Z0-9_.-]?$', primary_key=True, query=True, required=True)
|
||||||
|
option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
|
||||||
|
option: Flag('no_members', autofill=True, default=False, exclude='webui')
|
||||||
|
option: Str('principal*', alwaysask=True, cli_name='principals')
|
||||||
|
option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
|
||||||
|
option: Str('version?', exclude='webui')
|
||||||
|
output: Output('completed', <type 'int'>, None)
|
||||||
|
output: Output('failed', <type 'dict'>, None)
|
||||||
|
output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
|
||||||
|
command: servicedelegationrule_remove_target
|
||||||
|
args: 1,5,3
|
||||||
|
arg: Str('cn', attribute=True, cli_name='delegation_name', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_ .-]{0,253}[a-zA-Z0-9_.-]?$', primary_key=True, query=True, required=True)
|
||||||
|
option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
|
||||||
|
option: Flag('no_members', autofill=True, default=False, exclude='webui')
|
||||||
|
option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
|
||||||
|
option: Str('servicedelegationtarget*', alwaysask=True, cli_name='servicedelegationtargets', csv=True)
|
||||||
|
option: Str('version?', exclude='webui')
|
||||||
|
output: Output('completed', <type 'int'>, None)
|
||||||
|
output: Output('failed', <type 'dict'>, None)
|
||||||
|
output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
|
||||||
|
command: servicedelegationrule_show
|
||||||
|
args: 1,5,3
|
||||||
|
arg: Str('cn', attribute=True, cli_name='delegation_name', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_ .-]{0,253}[a-zA-Z0-9_.-]?$', primary_key=True, query=True, required=True)
|
||||||
|
option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
|
||||||
|
option: Flag('no_members', autofill=True, default=False, exclude='webui')
|
||||||
|
option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
|
||||||
|
option: Flag('rights', autofill=True, default=False)
|
||||||
|
option: Str('version?', exclude='webui')
|
||||||
|
output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
|
||||||
|
output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
|
||||||
|
output: PrimaryKey('value', None, None)
|
||||||
|
command: servicedelegationtarget_add
|
||||||
|
args: 1,5,3
|
||||||
|
arg: Str('cn', attribute=True, cli_name='delegation_name', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_ .-]{0,253}[a-zA-Z0-9_.-]?$', primary_key=True, required=True)
|
||||||
|
option: Str('addattr*', cli_name='addattr', exclude='webui')
|
||||||
|
option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
|
||||||
|
option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
|
||||||
|
option: Str('setattr*', cli_name='setattr', exclude='webui')
|
||||||
|
option: Str('version?', exclude='webui')
|
||||||
|
output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
|
||||||
|
output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
|
||||||
|
output: PrimaryKey('value', None, None)
|
||||||
|
command: servicedelegationtarget_add_member
|
||||||
|
args: 1,4,3
|
||||||
|
arg: Str('cn', attribute=True, cli_name='delegation_name', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_ .-]{0,253}[a-zA-Z0-9_.-]?$', primary_key=True, query=True, required=True)
|
||||||
|
option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
|
||||||
|
option: Str('principal*', alwaysask=True, cli_name='principals')
|
||||||
|
option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
|
||||||
|
option: Str('version?', exclude='webui')
|
||||||
|
output: Output('completed', <type 'int'>, None)
|
||||||
|
output: Output('failed', <type 'dict'>, None)
|
||||||
|
output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
|
||||||
|
command: servicedelegationtarget_del
|
||||||
|
args: 1,2,3
|
||||||
|
arg: Str('cn', attribute=True, cli_name='delegation_name', maxlength=255, multivalue=True, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_ .-]{0,253}[a-zA-Z0-9_.-]?$', primary_key=True, query=True, required=True)
|
||||||
|
option: Flag('continue', autofill=True, cli_name='continue', default=False)
|
||||||
|
option: Str('version?', exclude='webui')
|
||||||
|
output: Output('result', <type 'dict'>, None)
|
||||||
|
output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
|
||||||
|
output: ListOfPrimaryKeys('value', None, None)
|
||||||
|
command: servicedelegationtarget_find
|
||||||
|
args: 1,7,4
|
||||||
|
arg: Str('criteria?', noextrawhitespace=False)
|
||||||
|
option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
|
||||||
|
option: Str('cn', attribute=True, autofill=False, cli_name='delegation_name', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_ .-]{0,253}[a-zA-Z0-9_.-]?$', primary_key=True, query=True, required=False)
|
||||||
|
option: Flag('pkey_only?', autofill=True, default=False)
|
||||||
|
option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
|
||||||
|
option: Int('sizelimit?', autofill=False, minvalue=0)
|
||||||
|
option: Int('timelimit?', autofill=False, minvalue=0)
|
||||||
|
option: Str('version?', exclude='webui')
|
||||||
|
output: Output('count', <type 'int'>, None)
|
||||||
|
output: ListOfEntries('result', (<type 'list'>, <type 'tuple'>), Gettext('A list of LDAP entries', domain='ipa', localedir=None))
|
||||||
|
output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
|
||||||
|
output: Output('truncated', <type 'bool'>, None)
|
||||||
|
command: servicedelegationtarget_remove_member
|
||||||
|
args: 1,4,3
|
||||||
|
arg: Str('cn', attribute=True, cli_name='delegation_name', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_ .-]{0,253}[a-zA-Z0-9_.-]?$', primary_key=True, query=True, required=True)
|
||||||
|
option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
|
||||||
|
option: Str('principal*', alwaysask=True, cli_name='principals')
|
||||||
|
option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
|
||||||
|
option: Str('version?', exclude='webui')
|
||||||
|
output: Output('completed', <type 'int'>, None)
|
||||||
|
output: Output('failed', <type 'dict'>, None)
|
||||||
|
output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
|
||||||
|
command: servicedelegationtarget_show
|
||||||
|
args: 1,4,3
|
||||||
|
arg: Str('cn', attribute=True, cli_name='delegation_name', maxlength=255, multivalue=False, pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_ .-]{0,253}[a-zA-Z0-9_.-]?$', primary_key=True, query=True, required=True)
|
||||||
|
option: Flag('all', autofill=True, cli_name='all', default=False, exclude='webui')
|
||||||
|
option: Flag('raw', autofill=True, cli_name='raw', default=False, exclude='webui')
|
||||||
|
option: Flag('rights', autofill=True, default=False)
|
||||||
|
option: Str('version?', exclude='webui')
|
||||||
|
output: Entry('result', <type 'dict'>, Gettext('A dictionary representing an LDAP entry', domain='ipa', localedir=None))
|
||||||
|
output: Output('summary', (<type 'unicode'>, <type 'NoneType'>), None)
|
||||||
|
output: PrimaryKey('value', None, None)
|
||||||
command: sidgen_was_run
|
command: sidgen_was_run
|
||||||
args: 0,1,1
|
args: 0,1,1
|
||||||
option: Str('version?', exclude='webui')
|
option: Str('version?', exclude='webui')
|
||||||
|
|||||||
4
VERSION
4
VERSION
@@ -90,5 +90,5 @@ IPA_DATA_VERSION=20100614120000
|
|||||||
# #
|
# #
|
||||||
########################################################
|
########################################################
|
||||||
IPA_API_VERSION_MAJOR=2
|
IPA_API_VERSION_MAJOR=2
|
||||||
IPA_API_VERSION_MINOR=122
|
IPA_API_VERSION_MINOR=123
|
||||||
# Last change: ftweedal - allow multiple host/service certificates
|
# Last change: rcritten - added service constraint delegation plugin
|
||||||
|
|||||||
@@ -182,3 +182,12 @@ default:nsSystemIndex: false
|
|||||||
only:nsIndexType: eq
|
only:nsIndexType: eq
|
||||||
only:nsIndexType: pres
|
only:nsIndexType: pres
|
||||||
only:nsIndexType: sub
|
only:nsIndexType: sub
|
||||||
|
|
||||||
|
dn: cn=ipaallowedtarget,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
|
||||||
|
default:cn: ipaallowedtarget
|
||||||
|
default:ObjectClass: top
|
||||||
|
default:ObjectClass: nsIndex
|
||||||
|
default:nsSystemIndex: false
|
||||||
|
only:nsIndexType: eq
|
||||||
|
only:nsIndexType: pres
|
||||||
|
only:nsIndexType: sub
|
||||||
|
|||||||
@@ -16,3 +16,4 @@ add: referint-membership-attr: ipasudorunas
|
|||||||
add: referint-membership-attr: ipasudorunasgroup
|
add: referint-membership-attr: ipasudorunasgroup
|
||||||
add: referint-membership-attr: ipatokenradiusconfiglink
|
add: referint-membership-attr: ipatokenradiusconfiglink
|
||||||
add: referint-membership-attr: ipaassignedidview
|
add: referint-membership-attr: ipaassignedidview
|
||||||
|
add: referint-membership-attr: ipaallowedtarget
|
||||||
|
|||||||
537
ipalib/plugins/servicedelegation.py
Normal file
537
ipalib/plugins/servicedelegation.py
Normal file
@@ -0,0 +1,537 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2015 FreeIPA Contributors see COPYING for license
|
||||||
|
#
|
||||||
|
|
||||||
|
from ipalib import api
|
||||||
|
from ipalib import Str
|
||||||
|
from ipalib.plugable import Registry
|
||||||
|
from ipalib.plugins.baseldap import *
|
||||||
|
from ipalib.plugins.service import normalize_principal
|
||||||
|
from ipalib import _, ngettext
|
||||||
|
|
||||||
|
__doc__ = _("""
|
||||||
|
Service Constrained Delegation
|
||||||
|
|
||||||
|
Manage rules to allow constrained delegation of credentials so
|
||||||
|
that a service can impersonate a user when communicating with another
|
||||||
|
service without requiring the user to actually forward their TGT.
|
||||||
|
This makes for a much better method of delegating credentials as it
|
||||||
|
prevents exposure of the short term secret of the user.
|
||||||
|
|
||||||
|
The naming convention is to append the word "target" or "targets" to
|
||||||
|
a matching rule name. This is not mandatory but helps conceptually
|
||||||
|
to associate rules and targets.
|
||||||
|
|
||||||
|
A rule consists of two things:
|
||||||
|
- A list of targets the rule applies to
|
||||||
|
- A list of memberPrincipals that are allowed to delegate for
|
||||||
|
those targets
|
||||||
|
|
||||||
|
A target consists of a list of principals that can be delegated.
|
||||||
|
|
||||||
|
In English, a rule says that this principal can delegate as this
|
||||||
|
list of principals, as defined by these targets.
|
||||||
|
|
||||||
|
EXAMPLES:
|
||||||
|
|
||||||
|
Add a new constrained delegation rule:
|
||||||
|
ipa servicedelegationrule-add ftp-delegation
|
||||||
|
|
||||||
|
Add a new constrained delegation target:
|
||||||
|
ipa servicedelegationtarget-add ftp-delegation-target
|
||||||
|
|
||||||
|
Add a principal to the rule:
|
||||||
|
ipa servicedelegationrule-add-member --principals=ftp/ipa.example.com \
|
||||||
|
ftp-delegation
|
||||||
|
|
||||||
|
Add our target to the rule:
|
||||||
|
ipa servicedelegationrule-add-target \
|
||||||
|
--servicedelegationtargets=ftp-delegation-target ftp-delegation
|
||||||
|
|
||||||
|
Add a principal to the target:
|
||||||
|
ipa servicedelegationtarget-add-member --principals=ldap/ipa.example.com \
|
||||||
|
ftp-delegation-target
|
||||||
|
|
||||||
|
Display information about a named delegation rule and target:
|
||||||
|
ipa servicedelegationrule_show ftp-delegation
|
||||||
|
ipa servicedelegationtarget_show ftp-delegation-target
|
||||||
|
|
||||||
|
Remove a constrained delegation:
|
||||||
|
ipa servicedelegationrule-del ftp-delegation-target
|
||||||
|
ipa servicedelegationtarget-del ftp-delegation
|
||||||
|
|
||||||
|
In this example the ftp service can get a TGT for the ldap service on
|
||||||
|
the bound user's behalf.
|
||||||
|
|
||||||
|
It is strongly discouraged to modify the delegations that ship with
|
||||||
|
IPA, ipa-http-delegation and its targets ipa-cifs-delegation-targets and
|
||||||
|
ipa-ldap-delegation-targets. Incorrect changes can remove the ablity
|
||||||
|
to delegate, causing the framework to stop functioning.
|
||||||
|
""")
|
||||||
|
|
||||||
|
register = Registry()
|
||||||
|
|
||||||
|
PROTECTED_CONSTRAINT_RULES = (
|
||||||
|
u'ipa-http-delegation',
|
||||||
|
)
|
||||||
|
|
||||||
|
PROTECTED_CONSTRAINT_TARGETS = (
|
||||||
|
u'ipa-cifs-delegation-targets',
|
||||||
|
u'ipa-ldap-delegation-targets',
|
||||||
|
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
output_params = (
|
||||||
|
Str(
|
||||||
|
'ipaallowedtarget_servicedelegationtarget',
|
||||||
|
label=_('Allowed Target'),
|
||||||
|
),
|
||||||
|
Str(
|
||||||
|
'ipaallowedtoimpersonate',
|
||||||
|
label=_('Allowed to Impersonate'),
|
||||||
|
),
|
||||||
|
Str(
|
||||||
|
'memberprincipal',
|
||||||
|
label=_('Member principals'),
|
||||||
|
),
|
||||||
|
Str(
|
||||||
|
'failed_memberprincipal',
|
||||||
|
label=_('Failed members'),
|
||||||
|
),
|
||||||
|
Str(
|
||||||
|
'ipaallowedtarget',
|
||||||
|
label=_('Failed targets'),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class servicedelegation(LDAPObject):
|
||||||
|
"""
|
||||||
|
Service Constrained Delegation base object.
|
||||||
|
|
||||||
|
This jams a couple of concepts into a single plugin because the
|
||||||
|
data is all stored in one place. There is a "rule" which has the
|
||||||
|
objectclass ipakrb5delegationacl. This is the entry that controls
|
||||||
|
the delegation. Other entries that lack this objectclass are
|
||||||
|
targets and define what services can be impersonated.
|
||||||
|
"""
|
||||||
|
container_dn = api.env.container_s4u2proxy
|
||||||
|
object_class = ['groupofprincipals', 'top']
|
||||||
|
|
||||||
|
managed_permissions = {
|
||||||
|
'System: Read Service Delegations': {
|
||||||
|
'ipapermbindruletype': 'permission',
|
||||||
|
'ipapermright': {'read', 'search', 'compare'},
|
||||||
|
'ipapermtargetfilter': {'(objectclass=groupofprincipals)'},
|
||||||
|
'ipapermdefaultattr': {
|
||||||
|
'cn', 'objectclass', 'memberprincipal',
|
||||||
|
'ipaallowedtarget',
|
||||||
|
},
|
||||||
|
'default_privileges': {'Service Administrators'},
|
||||||
|
},
|
||||||
|
'System: Add Service Delegations': {
|
||||||
|
'ipapermright': {'add'},
|
||||||
|
'ipapermtargetfilter': {'(objectclass=groupofprincipals)'},
|
||||||
|
'default_privileges': {'Service Administrators'},
|
||||||
|
},
|
||||||
|
'System: Remove Service Delegations': {
|
||||||
|
'ipapermright': {'delete'},
|
||||||
|
'ipapermtargetfilter': {'(objectclass=groupofprincipals)'},
|
||||||
|
'default_privileges': {'Service Administrators'},
|
||||||
|
},
|
||||||
|
'System: Modify Service Delegation Membership': {
|
||||||
|
'ipapermright': {'write'},
|
||||||
|
'ipapermtargetfilter': {'(objectclass=groupofprincipals)'},
|
||||||
|
'ipapermdefaultattr': {'memberprincipal', 'ipaallowedtarget'},
|
||||||
|
'default_privileges': {'Service Administrators'},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
rdn_is_primary_key = True
|
||||||
|
|
||||||
|
takes_params = (
|
||||||
|
Str(
|
||||||
|
'cn',
|
||||||
|
pattern='^[a-zA-Z0-9_.][a-zA-Z0-9_ .-]{0,253}[a-zA-Z0-9_.-]?$',
|
||||||
|
pattern_errmsg='may only include letters, numbers, _, -, ., '
|
||||||
|
'and a space inside',
|
||||||
|
maxlength=255,
|
||||||
|
cli_name='delegation_name',
|
||||||
|
label=_('Delegation name'),
|
||||||
|
primary_key=True,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class servicedelegation_add_member(LDAPAddMember):
|
||||||
|
__doc__ = _('Add target to a named service delegation.')
|
||||||
|
member_attrs = ['memberprincipal']
|
||||||
|
member_attributes = []
|
||||||
|
member_names = {}
|
||||||
|
principal_attr = 'memberprincipal'
|
||||||
|
principal_failedattr = 'failed_memberprincipal'
|
||||||
|
|
||||||
|
has_output_params = LDAPAddMember.has_output_params + output_params
|
||||||
|
|
||||||
|
def get_options(self):
|
||||||
|
for option in super(servicedelegation_add_member, self).get_options():
|
||||||
|
yield option
|
||||||
|
for attr in self.member_attrs:
|
||||||
|
name = self.member_names[attr]
|
||||||
|
doc = self.member_param_doc % name
|
||||||
|
yield Str('%s*' % name, cli_name='%ss' % name, doc=doc,
|
||||||
|
label=_('member %s') % name, alwaysask=True)
|
||||||
|
|
||||||
|
def get_member_dns(self, **options):
|
||||||
|
"""
|
||||||
|
There are no member_dns to return. memberPrincipal needs
|
||||||
|
special handling since it is just a principal, not a
|
||||||
|
full dn.
|
||||||
|
"""
|
||||||
|
return dict(), dict()
|
||||||
|
|
||||||
|
def post_callback(self, ldap, completed, failed, dn, entry_attrs,
|
||||||
|
*keys, **options):
|
||||||
|
"""
|
||||||
|
Add memberPrincipal values. This is done afterward because it isn't
|
||||||
|
a DN and the LDAPAddMember method explicitly only handles DNs.
|
||||||
|
|
||||||
|
A separate fake attribute name is used for failed members. This is
|
||||||
|
a reverse of the way this is typically handled in the *Member
|
||||||
|
routines, where a successful addition will be represented as
|
||||||
|
member/memberof_<attribute>. In this case, because memberPrincipal
|
||||||
|
isn't a DN, I'm doing the reverse, and creating a fake failed
|
||||||
|
attribute instead.
|
||||||
|
"""
|
||||||
|
ldap = self.obj.backend
|
||||||
|
members = []
|
||||||
|
failed[self.principal_failedattr] = {}
|
||||||
|
failed[self.principal_failedattr][self.principal_attr] = []
|
||||||
|
names = options.get(self.member_names[self.principal_attr], [])
|
||||||
|
ldap_obj = self.api.Object['service']
|
||||||
|
if names:
|
||||||
|
for name in names:
|
||||||
|
if not name:
|
||||||
|
continue
|
||||||
|
name = normalize_principal(name)
|
||||||
|
obj_dn = ldap_obj.get_dn(name)
|
||||||
|
try:
|
||||||
|
ldap.get_entry(obj_dn, ['krbprincipalname'])
|
||||||
|
except errors.NotFound as e:
|
||||||
|
failed[self.principal_failedattr][
|
||||||
|
self.principal_attr].append((name, unicode(e)))
|
||||||
|
continue
|
||||||
|
try:
|
||||||
|
if name not in entry_attrs.get(self.principal_attr, []):
|
||||||
|
members.append(name)
|
||||||
|
else:
|
||||||
|
raise errors.AlreadyGroupMember()
|
||||||
|
except errors.PublicError as e:
|
||||||
|
failed[self.principal_failedattr][
|
||||||
|
self.principal_attr].append((name, unicode(e)))
|
||||||
|
else:
|
||||||
|
completed += 1
|
||||||
|
|
||||||
|
if members:
|
||||||
|
value = entry_attrs.setdefault(self.principal_attr, [])
|
||||||
|
value.extend(members)
|
||||||
|
|
||||||
|
try:
|
||||||
|
ldap.update_entry(entry_attrs)
|
||||||
|
except errors.EmptyModlist:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return completed, dn
|
||||||
|
|
||||||
|
|
||||||
|
class servicedelegation_remove_member(LDAPRemoveMember):
|
||||||
|
__doc__ = _('Remove member from a named service delegation.')
|
||||||
|
|
||||||
|
member_attrs = ['memberprincipal']
|
||||||
|
member_attributes = []
|
||||||
|
member_names = {}
|
||||||
|
principal_attr = 'memberprincipal'
|
||||||
|
principal_failedattr = 'failed_memberprincipal'
|
||||||
|
|
||||||
|
has_output_params = LDAPRemoveMember.has_output_params + output_params
|
||||||
|
|
||||||
|
def get_options(self):
|
||||||
|
for option in super(
|
||||||
|
servicedelegation_remove_member, self).get_options():
|
||||||
|
yield option
|
||||||
|
for attr in self.member_attrs:
|
||||||
|
name = self.member_names[attr]
|
||||||
|
doc = self.member_param_doc % name
|
||||||
|
yield Str('%s*' % name, cli_name='%ss' % name, doc=doc,
|
||||||
|
label=_('member %s') % name, alwaysask=True)
|
||||||
|
|
||||||
|
def get_member_dns(self, **options):
|
||||||
|
"""
|
||||||
|
Need to ignore memberPrincipal for now and handle the difference
|
||||||
|
in objectclass between a rule and a target.
|
||||||
|
"""
|
||||||
|
dns = {}
|
||||||
|
failed = {}
|
||||||
|
for attr in self.member_attrs:
|
||||||
|
dns[attr] = {}
|
||||||
|
if attr.lower() == 'memberprincipal':
|
||||||
|
# This will be handled later. memberprincipal isn't a
|
||||||
|
# DN so will blow up in assertions in baseldap.
|
||||||
|
continue
|
||||||
|
failed[attr] = {}
|
||||||
|
for ldap_obj_name in self.obj.attribute_members[attr]:
|
||||||
|
dns[attr][ldap_obj_name] = []
|
||||||
|
failed[attr][ldap_obj_name] = []
|
||||||
|
names = options.get(self.member_names[attr], [])
|
||||||
|
if not names:
|
||||||
|
continue
|
||||||
|
for name in names:
|
||||||
|
if not name:
|
||||||
|
continue
|
||||||
|
ldap_obj = self.api.Object[ldap_obj_name]
|
||||||
|
try:
|
||||||
|
dns[attr][ldap_obj_name].append(ldap_obj.get_dn(name))
|
||||||
|
except errors.PublicError as e:
|
||||||
|
failed[attr][ldap_obj_name].append((name, unicode(e)))
|
||||||
|
return dns, failed
|
||||||
|
|
||||||
|
def post_callback(self, ldap, completed, failed, dn, entry_attrs,
|
||||||
|
*keys, **options):
|
||||||
|
"""
|
||||||
|
Remove memberPrincipal values. This is done afterward because it
|
||||||
|
isn't a DN and the LDAPAddMember method explicitly only handles DNs.
|
||||||
|
|
||||||
|
See servicedelegation_add_member() for an explanation of what
|
||||||
|
failedattr is.
|
||||||
|
"""
|
||||||
|
ldap = self.obj.backend
|
||||||
|
failed[self.principal_failedattr] = {}
|
||||||
|
failed[self.principal_failedattr][self.principal_attr] = []
|
||||||
|
names = options.get(self.member_names[self.principal_attr], [])
|
||||||
|
if names:
|
||||||
|
for name in names:
|
||||||
|
if not name:
|
||||||
|
continue
|
||||||
|
name = normalize_principal(name)
|
||||||
|
try:
|
||||||
|
if name in entry_attrs.get(self.principal_attr, []):
|
||||||
|
entry_attrs[self.principal_attr].remove(name)
|
||||||
|
else:
|
||||||
|
raise errors.NotGroupMember()
|
||||||
|
except errors.PublicError as e:
|
||||||
|
failed[self.principal_failedattr][
|
||||||
|
self.principal_attr].append((name, unicode(e)))
|
||||||
|
else:
|
||||||
|
completed += 1
|
||||||
|
|
||||||
|
try:
|
||||||
|
ldap.update_entry(entry_attrs)
|
||||||
|
except errors.EmptyModlist:
|
||||||
|
pass
|
||||||
|
|
||||||
|
return completed, dn
|
||||||
|
|
||||||
|
|
||||||
|
@register()
|
||||||
|
class servicedelegationrule(servicedelegation):
|
||||||
|
"""
|
||||||
|
A service delegation rule. This is the ACL that controls
|
||||||
|
what can be delegated to whom.
|
||||||
|
"""
|
||||||
|
object_name = _('service delegation rule')
|
||||||
|
object_name_plural = _('service delegation rules')
|
||||||
|
object_class = ['ipakrb5delegationacl', 'groupofprincipals', 'top']
|
||||||
|
default_attributes = [
|
||||||
|
'cn', 'memberprincipal', 'ipaallowedtarget',
|
||||||
|
'ipaallowedtoimpersonate',
|
||||||
|
]
|
||||||
|
attribute_members = {
|
||||||
|
# memberprincipal is not listed because it isn't a DN
|
||||||
|
'ipaallowedtarget': ['servicedelegationtarget'],
|
||||||
|
}
|
||||||
|
|
||||||
|
label = _('Service delegation rules')
|
||||||
|
label_singular = _('Service delegation rule')
|
||||||
|
|
||||||
|
|
||||||
|
@register()
|
||||||
|
class servicedelegationrule_add(LDAPCreate):
|
||||||
|
__doc__ = _('Create a new service delegation rule.')
|
||||||
|
|
||||||
|
msg_summary = _('Added service delegation rule "%(value)s"')
|
||||||
|
|
||||||
|
|
||||||
|
@register()
|
||||||
|
class servicedelegationrule_del(LDAPDelete):
|
||||||
|
__doc__ = _('Delete service delegation.')
|
||||||
|
|
||||||
|
msg_summary = _('Deleted service delegation "%(value)s"')
|
||||||
|
|
||||||
|
def pre_callback(self, ldap, dn, *keys, **options):
|
||||||
|
assert isinstance(dn, DN)
|
||||||
|
if keys[0] in PROTECTED_CONSTRAINT_RULES:
|
||||||
|
raise errors.ProtectedEntryError(
|
||||||
|
label=_(u'service delegation rule'),
|
||||||
|
key=keys[0],
|
||||||
|
reason=_(u'privileged service delegation rule')
|
||||||
|
)
|
||||||
|
return dn
|
||||||
|
|
||||||
|
|
||||||
|
@register()
|
||||||
|
class servicedelegationrule_find(LDAPSearch):
|
||||||
|
__doc__ = _('Search for service delegations rule.')
|
||||||
|
|
||||||
|
has_output_params = LDAPSearch.has_output_params + output_params
|
||||||
|
|
||||||
|
msg_summary = ngettext(
|
||||||
|
'%(count)d service delegation rule matched',
|
||||||
|
'%(count)d service delegation rules matched', 0
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@register()
|
||||||
|
class servicedelegationrule_show(LDAPRetrieve):
|
||||||
|
__doc__ = _('Display information about a named service delegation rule.')
|
||||||
|
|
||||||
|
has_output_params = LDAPRetrieve.has_output_params + output_params
|
||||||
|
|
||||||
|
|
||||||
|
@register()
|
||||||
|
class servicedelegationrule_add_member(servicedelegation_add_member):
|
||||||
|
__doc__ = _('Add member to a named service delegation rule.')
|
||||||
|
|
||||||
|
member_names = {
|
||||||
|
'memberprincipal': 'principal',
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@register()
|
||||||
|
class servicedelegationrule_remove_member(servicedelegation_remove_member):
|
||||||
|
__doc__ = _('Remove member from a named service delegation rule.')
|
||||||
|
member_names = {
|
||||||
|
'memberprincipal': 'principal',
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@register()
|
||||||
|
class servicedelegationrule_add_target(LDAPAddMember):
|
||||||
|
__doc__ = _('Add target to a named service delegation rule.')
|
||||||
|
|
||||||
|
member_attributes = ['ipaallowedtarget']
|
||||||
|
attribute_members = {
|
||||||
|
'ipaallowedtarget': ['servicedelegationtarget'],
|
||||||
|
}
|
||||||
|
has_output_params = LDAPAddMember.has_output_params + output_params
|
||||||
|
|
||||||
|
|
||||||
|
@register()
|
||||||
|
class servicedelegationrule_remove_target(LDAPRemoveMember):
|
||||||
|
__doc__ = _('Remove target from a named service delegation rule.')
|
||||||
|
member_attributes = ['ipaallowedtarget']
|
||||||
|
attribute_members = {
|
||||||
|
'ipaallowedtarget': ['servicedelegationtarget'],
|
||||||
|
}
|
||||||
|
has_output_params = LDAPRemoveMember.has_output_params + output_params
|
||||||
|
|
||||||
|
|
||||||
|
@register()
|
||||||
|
class servicedelegationtarget(servicedelegation):
|
||||||
|
object_name = _('service delegation target')
|
||||||
|
object_name_plural = _('service delegation targets')
|
||||||
|
object_class = ['groupofprincipals', 'top']
|
||||||
|
default_attributes = [
|
||||||
|
'cn', 'memberprincipal',
|
||||||
|
]
|
||||||
|
attribute_members = {}
|
||||||
|
|
||||||
|
label = _('Service delegation targets')
|
||||||
|
label_singular = _('Service delegation target')
|
||||||
|
|
||||||
|
|
||||||
|
@register()
|
||||||
|
class servicedelegationtarget_add(LDAPCreate):
|
||||||
|
__doc__ = _('Create a new service delegation target.')
|
||||||
|
|
||||||
|
msg_summary = _('Added service delegation target "%(value)s"')
|
||||||
|
|
||||||
|
|
||||||
|
@register()
|
||||||
|
class servicedelegationtarget_del(LDAPDelete):
|
||||||
|
__doc__ = _('Delete service delegation target.')
|
||||||
|
|
||||||
|
msg_summary = _('Deleted service delegation target "%(value)s"')
|
||||||
|
|
||||||
|
def pre_callback(self, ldap, dn, *keys, **options):
|
||||||
|
assert isinstance(dn, DN)
|
||||||
|
if keys[0] in PROTECTED_CONSTRAINT_TARGETS:
|
||||||
|
raise errors.ProtectedEntryError(
|
||||||
|
label=_(u'service delegation target'),
|
||||||
|
key=keys[0],
|
||||||
|
reason=_(u'privileged service delegation target')
|
||||||
|
)
|
||||||
|
return dn
|
||||||
|
|
||||||
|
|
||||||
|
@register()
|
||||||
|
class servicedelegationtarget_find(LDAPSearch):
|
||||||
|
__doc__ = _('Search for service delegation target.')
|
||||||
|
|
||||||
|
has_output_params = LDAPSearch.has_output_params + output_params
|
||||||
|
|
||||||
|
msg_summary = ngettext(
|
||||||
|
'%(count)d service delegation target matched',
|
||||||
|
'%(count)d service delegation targets matched', 0
|
||||||
|
)
|
||||||
|
|
||||||
|
def pre_callback(self, ldap, filters, attrs_list, base_dn, scope,
|
||||||
|
*args, **options):
|
||||||
|
"""
|
||||||
|
Exclude rules from the search output. A target contains a subset
|
||||||
|
of a rule objectclass.
|
||||||
|
"""
|
||||||
|
search_kw = self.args_options_2_entry(**options)
|
||||||
|
search_kw['objectclass'] = self.obj.object_class
|
||||||
|
attr_filter = ldap.make_filter(search_kw, rules=ldap.MATCH_ALL)
|
||||||
|
rule_kw = {'objectclass': 'ipakrb5delegationacl'}
|
||||||
|
target_filter = ldap.make_filter(rule_kw, rules=ldap.MATCH_NONE)
|
||||||
|
attr_filter = ldap.combine_filters(
|
||||||
|
(target_filter, attr_filter), rules=ldap.MATCH_ALL
|
||||||
|
)
|
||||||
|
|
||||||
|
search_kw = {}
|
||||||
|
term = args[-1]
|
||||||
|
for a in self.obj.default_attributes:
|
||||||
|
search_kw[a] = term
|
||||||
|
|
||||||
|
term_filter = ldap.make_filter(search_kw, exact=False)
|
||||||
|
|
||||||
|
sfilter = ldap.combine_filters(
|
||||||
|
(term_filter, attr_filter), rules=ldap.MATCH_ALL
|
||||||
|
)
|
||||||
|
return sfilter, base_dn, ldap.SCOPE_ONELEVEL
|
||||||
|
|
||||||
|
|
||||||
|
@register()
|
||||||
|
class servicedelegationtarget_show(LDAPRetrieve):
|
||||||
|
__doc__ = _('Display information about a named service delegation target.')
|
||||||
|
|
||||||
|
has_output_params = LDAPRetrieve.has_output_params + output_params
|
||||||
|
|
||||||
|
|
||||||
|
@register()
|
||||||
|
class servicedelegationtarget_add_member(servicedelegation_add_member):
|
||||||
|
__doc__ = _('Add member to a named service delegation target.')
|
||||||
|
|
||||||
|
member_names = {
|
||||||
|
'memberprincipal': 'principal',
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@register()
|
||||||
|
class servicedelegationtarget_remove_member(servicedelegation_remove_member):
|
||||||
|
__doc__ = _('Remove member from a named service delegation target.')
|
||||||
|
member_names = {
|
||||||
|
'memberprincipal': 'principal',
|
||||||
|
}
|
||||||
@@ -201,3 +201,14 @@ idoverridegroup = [
|
|||||||
u'top',
|
u'top',
|
||||||
u'ipaGroupOverride',
|
u'ipaGroupOverride',
|
||||||
]
|
]
|
||||||
|
|
||||||
|
servicedelegationrule = [
|
||||||
|
u'top',
|
||||||
|
u'groupofprincipals',
|
||||||
|
u'ipakrb5delegationacl',
|
||||||
|
]
|
||||||
|
|
||||||
|
servicedelegationtarget = [
|
||||||
|
u'top',
|
||||||
|
u'groupofprincipals',
|
||||||
|
]
|
||||||
|
|||||||
591
ipatests/test_xmlrpc/test_servicedelegation_plugin.py
Normal file
591
ipatests/test_xmlrpc/test_servicedelegation_plugin.py
Normal file
@@ -0,0 +1,591 @@
|
|||||||
|
#
|
||||||
|
# Copyright (C) 2015 FreeIPA Contributors see COPYING for license
|
||||||
|
#
|
||||||
|
"""
|
||||||
|
Test the `ipalib/plugins/serviceconstraint.py` module.
|
||||||
|
"""
|
||||||
|
|
||||||
|
from ipalib import api, errors
|
||||||
|
from ipatests.test_xmlrpc import objectclasses
|
||||||
|
from xmlrpc_test import Declarative
|
||||||
|
from ipapython.dn import DN
|
||||||
|
|
||||||
|
rule1 = u'test1'
|
||||||
|
rule2 = u'test rule two'
|
||||||
|
target1 = u'test1-targets'
|
||||||
|
target2 = u'test2-targets'
|
||||||
|
princ1 = u'HTTP/%s@%s' % (api.env.host, api.env.realm)
|
||||||
|
princ2 = u'ldap/%s@%s' % (api.env.host, api.env.realm)
|
||||||
|
|
||||||
|
|
||||||
|
def get_servicedelegation_dn(cn):
|
||||||
|
return DN(('cn', cn), api.env.container_s4u2proxy, api.env.basedn)
|
||||||
|
|
||||||
|
|
||||||
|
class test_servicedelegation(Declarative):
|
||||||
|
cleanup_commands = [
|
||||||
|
('servicedelegationrule_del', [rule1], {}),
|
||||||
|
('servicedelegationrule_del', [rule2], {}),
|
||||||
|
('servicedelegationtarget_del', [target1], {}),
|
||||||
|
('servicedelegationtarget_del', [target2], {}),
|
||||||
|
]
|
||||||
|
|
||||||
|
tests = [
|
||||||
|
|
||||||
|
################
|
||||||
|
# create rule1:
|
||||||
|
dict(
|
||||||
|
desc='Try to retrieve non-existent %r' % rule1,
|
||||||
|
command=('servicedelegationrule_show', [rule1], {}),
|
||||||
|
expected=errors.NotFound(
|
||||||
|
reason=u'%s: service delegation rule not found' % rule1
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
|
||||||
|
dict(
|
||||||
|
desc='Try to delete non-existent %r' % rule1,
|
||||||
|
command=('servicedelegationrule_del', [rule1], {}),
|
||||||
|
expected=errors.NotFound(
|
||||||
|
reason=u'%s: service delegation rule not found' % rule1
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
|
||||||
|
dict(
|
||||||
|
desc='Create %r' % rule1,
|
||||||
|
command=(
|
||||||
|
'servicedelegationrule_add', [rule1], {}
|
||||||
|
),
|
||||||
|
expected=dict(
|
||||||
|
value=rule1,
|
||||||
|
summary=u'Added service delegation rule "%s"' % rule1,
|
||||||
|
result=dict(
|
||||||
|
cn=[rule1],
|
||||||
|
objectclass=objectclasses.servicedelegationrule,
|
||||||
|
dn=get_servicedelegation_dn(rule1),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
|
||||||
|
dict(
|
||||||
|
desc='Try to create duplicate %r' % rule1,
|
||||||
|
command=(
|
||||||
|
'servicedelegationrule_add', [rule1], {}
|
||||||
|
),
|
||||||
|
expected=errors.DuplicateEntry(
|
||||||
|
message=u'service delegation rule with name "%s" '
|
||||||
|
'already exists' % rule1),
|
||||||
|
),
|
||||||
|
|
||||||
|
|
||||||
|
dict(
|
||||||
|
desc='Retrieve %r' % rule1,
|
||||||
|
command=('servicedelegationrule_show', [rule1], {}),
|
||||||
|
expected=dict(
|
||||||
|
value=rule1,
|
||||||
|
summary=None,
|
||||||
|
result=dict(
|
||||||
|
cn=[rule1],
|
||||||
|
dn=get_servicedelegation_dn(rule1),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
|
||||||
|
dict(
|
||||||
|
desc='Search for %r' % rule1,
|
||||||
|
command=('servicedelegationrule_find', [], dict(cn=rule1)),
|
||||||
|
expected=dict(
|
||||||
|
count=1,
|
||||||
|
truncated=False,
|
||||||
|
result=[
|
||||||
|
dict(
|
||||||
|
dn=get_servicedelegation_dn(rule1),
|
||||||
|
cn=[rule1],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
summary=u'1 service delegation rule matched',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
################
|
||||||
|
# create rule2:
|
||||||
|
dict(
|
||||||
|
desc='Create %r' % rule2,
|
||||||
|
command=(
|
||||||
|
'servicedelegationrule_add', [rule2], {}
|
||||||
|
),
|
||||||
|
expected=dict(
|
||||||
|
value=rule2,
|
||||||
|
summary=u'Added service delegation rule "%s"' % rule2,
|
||||||
|
result=dict(
|
||||||
|
cn=[rule2],
|
||||||
|
objectclass=objectclasses.servicedelegationrule,
|
||||||
|
dn=get_servicedelegation_dn(rule2),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
|
||||||
|
dict(
|
||||||
|
desc='Search for all rules',
|
||||||
|
command=('servicedelegationrule_find', [], {}),
|
||||||
|
expected=dict(
|
||||||
|
summary=u'3 service delegation rules matched',
|
||||||
|
count=3,
|
||||||
|
truncated=False,
|
||||||
|
result=[
|
||||||
|
{
|
||||||
|
'dn': get_servicedelegation_dn(u'ipa-http-delegation'),
|
||||||
|
'cn': [u'ipa-http-delegation'],
|
||||||
|
'memberprincipal': [princ1],
|
||||||
|
'ipaallowedtarget_servicedelegationtarget':
|
||||||
|
[u'ipa-ldap-delegation-targets',
|
||||||
|
u'ipa-cifs-delegation-targets']
|
||||||
|
},
|
||||||
|
dict(
|
||||||
|
dn=get_servicedelegation_dn(rule2),
|
||||||
|
cn=[rule2],
|
||||||
|
),
|
||||||
|
dict(
|
||||||
|
dn=get_servicedelegation_dn(rule1),
|
||||||
|
cn=[rule1],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
|
||||||
|
dict(
|
||||||
|
desc='Create target %r' % target1,
|
||||||
|
command=(
|
||||||
|
'servicedelegationtarget_add', [target1], {}
|
||||||
|
),
|
||||||
|
expected=dict(
|
||||||
|
value=target1,
|
||||||
|
summary=u'Added service delegation target "%s"' % target1,
|
||||||
|
result=dict(
|
||||||
|
cn=[target1],
|
||||||
|
objectclass=objectclasses.servicedelegationtarget,
|
||||||
|
dn=get_servicedelegation_dn(target1),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
|
||||||
|
dict(
|
||||||
|
desc='Create target %r' % target2,
|
||||||
|
command=(
|
||||||
|
'servicedelegationtarget_add', [target2], {}
|
||||||
|
),
|
||||||
|
expected=dict(
|
||||||
|
value=target2,
|
||||||
|
summary=u'Added service delegation target "%s"' % target2,
|
||||||
|
result=dict(
|
||||||
|
cn=[target2],
|
||||||
|
objectclass=objectclasses.servicedelegationtarget,
|
||||||
|
dn=get_servicedelegation_dn(target2),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
|
||||||
|
dict(
|
||||||
|
desc='Search for all targets',
|
||||||
|
command=('servicedelegationtarget_find', [], {}),
|
||||||
|
expected=dict(
|
||||||
|
summary=u'4 service delegation targets matched',
|
||||||
|
count=4,
|
||||||
|
truncated=False,
|
||||||
|
result=[
|
||||||
|
{
|
||||||
|
'dn': get_servicedelegation_dn(
|
||||||
|
u'ipa-cifs-delegation-targets'),
|
||||||
|
'cn': [u'ipa-cifs-delegation-targets'],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'dn': get_servicedelegation_dn(
|
||||||
|
u'ipa-ldap-delegation-targets'
|
||||||
|
),
|
||||||
|
'cn': [u'ipa-ldap-delegation-targets'],
|
||||||
|
'memberprincipal': [princ2],
|
||||||
|
},
|
||||||
|
dict(
|
||||||
|
dn=get_servicedelegation_dn(target1),
|
||||||
|
cn=[target1],
|
||||||
|
),
|
||||||
|
dict(
|
||||||
|
dn=get_servicedelegation_dn(target2),
|
||||||
|
cn=[target2],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
|
||||||
|
###############
|
||||||
|
# member stuff:
|
||||||
|
dict(
|
||||||
|
desc='Add member %r to %r' % (target1, rule1),
|
||||||
|
command=(
|
||||||
|
'servicedelegationrule_add_target', [rule1],
|
||||||
|
dict(servicedelegationtarget=target1)
|
||||||
|
),
|
||||||
|
expected=dict(
|
||||||
|
completed=1,
|
||||||
|
failed=dict(
|
||||||
|
ipaallowedtarget=dict(
|
||||||
|
servicedelegationtarget=tuple(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
result={
|
||||||
|
'dn': get_servicedelegation_dn(rule1),
|
||||||
|
'ipaallowedtarget_servicedelegationtarget': (target1,),
|
||||||
|
'cn': [rule1],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
|
||||||
|
dict(
|
||||||
|
desc='Add duplicate target %r to %r' % (target1, rule1),
|
||||||
|
command=(
|
||||||
|
'servicedelegationrule_add_target', [rule1],
|
||||||
|
dict(servicedelegationtarget=target1)
|
||||||
|
),
|
||||||
|
expected=dict(
|
||||||
|
completed=0,
|
||||||
|
failed=dict(
|
||||||
|
ipaallowedtarget=dict(
|
||||||
|
servicedelegationtarget=[
|
||||||
|
[target1, u'This entry is already a member']
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
result={
|
||||||
|
'dn': get_servicedelegation_dn(rule1),
|
||||||
|
'ipaallowedtarget_servicedelegationtarget': (target1,),
|
||||||
|
'cn': [rule1],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
|
||||||
|
dict(
|
||||||
|
desc='Add non-existent target %r to %r' % (u'notfound', rule1),
|
||||||
|
command=(
|
||||||
|
'servicedelegationrule_add_target', [rule1],
|
||||||
|
dict(servicedelegationtarget=u'notfound')
|
||||||
|
),
|
||||||
|
expected=dict(
|
||||||
|
completed=0,
|
||||||
|
failed=dict(
|
||||||
|
ipaallowedtarget=dict(
|
||||||
|
servicedelegationtarget=[
|
||||||
|
[u'notfound', u'no such entry']
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
result={
|
||||||
|
'dn': get_servicedelegation_dn(rule1),
|
||||||
|
'ipaallowedtarget_servicedelegationtarget': (target1,),
|
||||||
|
'cn': [rule1],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
|
||||||
|
dict(
|
||||||
|
desc='Remove a target %r from %r' % (target1, rule1),
|
||||||
|
command=(
|
||||||
|
'servicedelegationrule_remove_target', [rule1],
|
||||||
|
dict(servicedelegationtarget=target1)
|
||||||
|
),
|
||||||
|
expected=dict(
|
||||||
|
completed=1,
|
||||||
|
failed=dict(
|
||||||
|
ipaallowedtarget=dict(
|
||||||
|
servicedelegationtarget=tuple(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
result={
|
||||||
|
'dn': get_servicedelegation_dn(rule1),
|
||||||
|
'cn': [rule1],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
|
||||||
|
dict(
|
||||||
|
desc='Remove non-existent target %r from %r' % (
|
||||||
|
u'notfound', rule1
|
||||||
|
),
|
||||||
|
command=(
|
||||||
|
'servicedelegationrule_remove_target', [rule1],
|
||||||
|
dict(servicedelegationtarget=u'notfound')
|
||||||
|
),
|
||||||
|
expected=dict(
|
||||||
|
completed=0,
|
||||||
|
failed=dict(
|
||||||
|
ipaallowedtarget=dict(
|
||||||
|
servicedelegationtarget=[
|
||||||
|
[u'notfound', u'This entry is not a member']
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
result={
|
||||||
|
'dn': get_servicedelegation_dn(rule1),
|
||||||
|
'cn': [rule1],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
|
||||||
|
###############
|
||||||
|
# memberprincipal member stuff:
|
||||||
|
dict(
|
||||||
|
desc='Add memberprinc %r to %r' % (princ1, rule1),
|
||||||
|
command=(
|
||||||
|
'servicedelegationrule_add_member', [rule1],
|
||||||
|
dict(principal=princ1)
|
||||||
|
),
|
||||||
|
expected=dict(
|
||||||
|
completed=1,
|
||||||
|
failed=dict(
|
||||||
|
failed_memberprincipal=dict(
|
||||||
|
memberprincipal=tuple(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
result={
|
||||||
|
'dn': get_servicedelegation_dn(rule1),
|
||||||
|
'memberprincipal': (princ1,),
|
||||||
|
'cn': [rule1],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
|
||||||
|
dict(
|
||||||
|
desc='Add duplicate member %r to %r' % (princ1, rule1),
|
||||||
|
command=(
|
||||||
|
'servicedelegationrule_add_member', [rule1],
|
||||||
|
dict(principal=princ1)
|
||||||
|
),
|
||||||
|
expected=dict(
|
||||||
|
completed=0,
|
||||||
|
failed=dict(
|
||||||
|
failed_memberprincipal=dict(
|
||||||
|
memberprincipal=[
|
||||||
|
[princ1, u'This entry is already a member']
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
result={
|
||||||
|
'dn': get_servicedelegation_dn(rule1),
|
||||||
|
'memberprincipal': (princ1,),
|
||||||
|
'cn': [rule1],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
|
||||||
|
dict(
|
||||||
|
desc='Add non-existent member %r to %r' % (
|
||||||
|
u'HTTP/notfound', rule1
|
||||||
|
),
|
||||||
|
command=(
|
||||||
|
'servicedelegationrule_add_member', [rule1],
|
||||||
|
dict(principal=u'HTTP/notfound@%s' % api.env.realm)
|
||||||
|
),
|
||||||
|
expected=dict(
|
||||||
|
completed=0,
|
||||||
|
failed=dict(
|
||||||
|
failed_memberprincipal=dict(
|
||||||
|
memberprincipal=[
|
||||||
|
[u'HTTP/notfound@%s' % api.env.realm,
|
||||||
|
u'no such entry']
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
result={
|
||||||
|
'dn': get_servicedelegation_dn(rule1),
|
||||||
|
'memberprincipal': (princ1,),
|
||||||
|
'cn': [rule1],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
|
||||||
|
dict(
|
||||||
|
desc='Remove a member %r from %r' % (princ1, rule1),
|
||||||
|
command=(
|
||||||
|
'servicedelegationrule_remove_member', [rule1],
|
||||||
|
dict(principal=princ1)
|
||||||
|
),
|
||||||
|
expected=dict(
|
||||||
|
completed=1,
|
||||||
|
failed=dict(
|
||||||
|
failed_memberprincipal=dict(
|
||||||
|
memberprincipal=tuple(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
result={
|
||||||
|
'dn': get_servicedelegation_dn(rule1),
|
||||||
|
'memberprincipal': [],
|
||||||
|
'cn': [rule1],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
|
||||||
|
dict(
|
||||||
|
desc='Remove non-existent member %r from %r' % (
|
||||||
|
u'HTTP/notfound', rule1
|
||||||
|
),
|
||||||
|
command=(
|
||||||
|
'servicedelegationrule_remove_member', [rule1],
|
||||||
|
dict(principal=u'HTTP/notfound@%s' % api.env.realm)
|
||||||
|
),
|
||||||
|
expected=dict(
|
||||||
|
completed=0,
|
||||||
|
failed=dict(
|
||||||
|
failed_memberprincipal=dict(
|
||||||
|
memberprincipal=[
|
||||||
|
[u'HTTP/notfound@%s' % api.env.realm,
|
||||||
|
u'This entry is not a member']
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
result={
|
||||||
|
'dn': get_servicedelegation_dn(rule1),
|
||||||
|
'cn': [rule1],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
|
||||||
|
dict(
|
||||||
|
desc='Add memberprinc %r to %r' % (princ1, target1),
|
||||||
|
command=(
|
||||||
|
'servicedelegationtarget_add_member', [target1],
|
||||||
|
dict(principal=princ1)
|
||||||
|
),
|
||||||
|
expected=dict(
|
||||||
|
completed=1,
|
||||||
|
failed=dict(
|
||||||
|
failed_memberprincipal=dict(
|
||||||
|
memberprincipal=tuple(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
result={
|
||||||
|
'dn': get_servicedelegation_dn(target1),
|
||||||
|
'memberprincipal': (princ1,),
|
||||||
|
'cn': [target1],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
|
||||||
|
dict(
|
||||||
|
desc='Add duplicate member %r to %r' % (princ1, target1),
|
||||||
|
command=(
|
||||||
|
'servicedelegationtarget_add_member', [target1],
|
||||||
|
dict(principal=princ1)
|
||||||
|
),
|
||||||
|
expected=dict(
|
||||||
|
completed=0,
|
||||||
|
failed=dict(
|
||||||
|
failed_memberprincipal=dict(
|
||||||
|
memberprincipal=[
|
||||||
|
[princ1, u'This entry is already a member']
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
result={
|
||||||
|
'dn': get_servicedelegation_dn(target1),
|
||||||
|
'memberprincipal': (princ1,),
|
||||||
|
'cn': [target1],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
|
||||||
|
dict(
|
||||||
|
desc='Add non-existent member %r to %r' % (
|
||||||
|
u'HTTP/notfound', target1
|
||||||
|
),
|
||||||
|
command=(
|
||||||
|
'servicedelegationtarget_add_member', [target1],
|
||||||
|
dict(principal=u'HTTP/notfound@%s' % api.env.realm)
|
||||||
|
),
|
||||||
|
expected=dict(
|
||||||
|
completed=0,
|
||||||
|
failed=dict(
|
||||||
|
failed_memberprincipal=dict(
|
||||||
|
memberprincipal=[
|
||||||
|
[u'HTTP/notfound@%s' % api.env.realm,
|
||||||
|
u'no such entry']
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
result={
|
||||||
|
'dn': get_servicedelegation_dn(target1),
|
||||||
|
'memberprincipal': (princ1,),
|
||||||
|
'cn': [target1],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
|
||||||
|
dict(
|
||||||
|
desc='Remove a member %r from %r' % (princ1, target1),
|
||||||
|
command=(
|
||||||
|
'servicedelegationtarget_remove_member', [target1],
|
||||||
|
dict(principal=princ1)
|
||||||
|
),
|
||||||
|
expected=dict(
|
||||||
|
completed=1,
|
||||||
|
failed=dict(
|
||||||
|
failed_memberprincipal=dict(
|
||||||
|
memberprincipal=tuple(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
result={
|
||||||
|
'dn': get_servicedelegation_dn(target1),
|
||||||
|
'memberprincipal': [],
|
||||||
|
'cn': [target1],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
|
||||||
|
dict(
|
||||||
|
desc='Remove non-existent member %r from %r' % (
|
||||||
|
u'HTTP/notfound', target1
|
||||||
|
),
|
||||||
|
command=(
|
||||||
|
'servicedelegationtarget_remove_member', [target1],
|
||||||
|
dict(principal=u'HTTP/notfound@%s' % api.env.realm)
|
||||||
|
),
|
||||||
|
expected=dict(
|
||||||
|
completed=0,
|
||||||
|
failed=dict(
|
||||||
|
failed_memberprincipal=dict(
|
||||||
|
memberprincipal=[
|
||||||
|
[u'HTTP/notfound@%s' % api.env.realm,
|
||||||
|
u'This entry is not a member']
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
result={
|
||||||
|
'dn': get_servicedelegation_dn(target1),
|
||||||
|
'cn': [target1],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
]
|
||||||
Reference in New Issue
Block a user