mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
Add group membership management
A group membership manager is a user or a group that can add members to a group or remove members from a group or host group. Fixes: https://pagure.io/freeipa/issue/8114 Signed-off-by: Christian Heimes <cheimes@redhat.com> Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
This commit is contained in:
parent
87c24ebd34
commit
f0a1f084b6
8
ACI.txt
8
ACI.txt
@ -99,7 +99,7 @@ aci: (targetattr = "ipaexternalmember")(targetfilter = "(objectclass=ipaexternal
|
||||
dn: cn=groups,cn=accounts,dc=ipa,dc=example
|
||||
aci: (targetattr = "member")(targetfilter = "(&(!(cn=admins))(objectclass=ipausergroup))")(version 3.0;acl "permission:System: Modify Group Membership";allow (write) groupdn = "ldap:///cn=System: Modify Group Membership,cn=permissions,cn=pbac,dc=ipa,dc=example";)
|
||||
dn: cn=groups,cn=accounts,dc=ipa,dc=example
|
||||
aci: (targetattr = "cn || description || gidnumber || ipauniqueid || mepmanagedby || objectclass")(targetfilter = "(|(objectclass=ipausergroup)(objectclass=posixgroup))")(version 3.0;acl "permission:System: Modify Groups";allow (write) groupdn = "ldap:///cn=System: Modify Groups,cn=permissions,cn=pbac,dc=ipa,dc=example";)
|
||||
aci: (targetattr = "cn || description || gidnumber || ipauniqueid || membermanager || mepmanagedby || objectclass")(targetfilter = "(|(objectclass=ipausergroup)(objectclass=posixgroup))")(version 3.0;acl "permission:System: Modify Groups";allow (write) groupdn = "ldap:///cn=System: Modify Groups,cn=permissions,cn=pbac,dc=ipa,dc=example";)
|
||||
dn: cn=groups,cn=accounts,dc=ipa,dc=example
|
||||
aci: (targetattr = "ipaexternalmember")(targetfilter = "(|(objectclass=ipausergroup)(objectclass=posixgroup))")(version 3.0;acl "permission:System: Read External Group Membership";allow (compare,read,search) userdn = "ldap:///all";)
|
||||
dn: dc=ipa,dc=example
|
||||
@ -109,7 +109,7 @@ aci: (targetattr = "member || memberhost || memberof || memberuid || memberuser"
|
||||
dn: dc=ipa,dc=example
|
||||
aci: (targetattr = "cn || createtimestamp || entryusn || gidnumber || memberuid || modifytimestamp || objectclass")(target = "ldap:///cn=groups,cn=*,cn=views,cn=compat,dc=ipa,dc=example")(version 3.0;acl "permission:System: Read Group Views Compat Tree";allow (compare,read,search) userdn = "ldap:///anyone";)
|
||||
dn: cn=groups,cn=accounts,dc=ipa,dc=example
|
||||
aci: (targetattr = "businesscategory || cn || createtimestamp || description || entryusn || gidnumber || ipaexternalmember || ipantsecurityidentifier || ipauniqueid || mepmanagedby || modifytimestamp || o || objectclass || ou || owner || seealso")(targetfilter = "(|(objectclass=ipausergroup)(objectclass=posixgroup))")(version 3.0;acl "permission:System: Read Groups";allow (compare,read,search) userdn = "ldap:///anyone";)
|
||||
aci: (targetattr = "businesscategory || cn || createtimestamp || description || entryusn || gidnumber || ipaexternalmember || ipantsecurityidentifier || ipauniqueid || membermanager || mepmanagedby || modifytimestamp || o || objectclass || ou || owner || seealso")(targetfilter = "(|(objectclass=ipausergroup)(objectclass=posixgroup))")(version 3.0;acl "permission:System: Read Groups";allow (compare,read,search) userdn = "ldap:///anyone";)
|
||||
dn: cn=groups,cn=accounts,dc=ipa,dc=example
|
||||
aci: (targetfilter = "(|(objectclass=ipausergroup)(objectclass=posixgroup))")(version 3.0;acl "permission:System: Remove Groups";allow (delete) groupdn = "ldap:///cn=System: Remove Groups,cn=permissions,cn=pbac,dc=ipa,dc=example";)
|
||||
dn: cn=hbac,dc=ipa,dc=example
|
||||
@ -169,11 +169,11 @@ aci: (targetfilter = "(objectclass=ipahostgroup)")(version 3.0;acl "permission:S
|
||||
dn: cn=hostgroups,cn=accounts,dc=ipa,dc=example
|
||||
aci: (targetattr = "member")(targetfilter = "(&(!(cn=ipaservers))(objectclass=ipahostgroup))")(version 3.0;acl "permission:System: Modify Hostgroup Membership";allow (write) groupdn = "ldap:///cn=System: Modify Hostgroup Membership,cn=permissions,cn=pbac,dc=ipa,dc=example";)
|
||||
dn: cn=hostgroups,cn=accounts,dc=ipa,dc=example
|
||||
aci: (targetattr = "cn || description")(targetfilter = "(objectclass=ipahostgroup)")(version 3.0;acl "permission:System: Modify Hostgroups";allow (write) groupdn = "ldap:///cn=System: Modify Hostgroups,cn=permissions,cn=pbac,dc=ipa,dc=example";)
|
||||
aci: (targetattr = "cn || description || membermanager")(targetfilter = "(objectclass=ipahostgroup)")(version 3.0;acl "permission:System: Modify Hostgroups";allow (write) groupdn = "ldap:///cn=System: Modify Hostgroups,cn=permissions,cn=pbac,dc=ipa,dc=example";)
|
||||
dn: cn=hostgroups,cn=accounts,dc=ipa,dc=example
|
||||
aci: (targetattr = "member || memberhost || memberof || memberuser")(targetfilter = "(objectclass=ipahostgroup)")(version 3.0;acl "permission:System: Read Hostgroup Membership";allow (compare,read,search) userdn = "ldap:///all";)
|
||||
dn: cn=hostgroups,cn=accounts,dc=ipa,dc=example
|
||||
aci: (targetattr = "businesscategory || cn || createtimestamp || description || entryusn || ipauniqueid || modifytimestamp || o || objectclass || ou || owner || seealso")(targetfilter = "(objectclass=ipahostgroup)")(version 3.0;acl "permission:System: Read Hostgroups";allow (compare,read,search) userdn = "ldap:///all";)
|
||||
aci: (targetattr = "businesscategory || cn || createtimestamp || description || entryusn || ipauniqueid || membermanager || modifytimestamp || o || objectclass || ou || owner || seealso")(targetfilter = "(objectclass=ipahostgroup)")(version 3.0;acl "permission:System: Read Hostgroups";allow (compare,read,search) userdn = "ldap:///all";)
|
||||
dn: cn=hostgroups,cn=accounts,dc=ipa,dc=example
|
||||
aci: (targetfilter = "(objectclass=ipahostgroup)")(version 3.0;acl "permission:System: Remove Hostgroups";allow (delete) groupdn = "ldap:///cn=System: Remove Hostgroups,cn=permissions,cn=pbac,dc=ipa,dc=example";)
|
||||
dn: cn=views,cn=accounts,dc=ipa,dc=example
|
||||
|
64
API.txt
64
API.txt
@ -1972,6 +1972,18 @@ option: Str('version?')
|
||||
output: Output('completed', type=[<type 'int'>])
|
||||
output: Output('failed', type=[<type 'dict'>])
|
||||
output: Entry('result')
|
||||
command: group_add_member_manager/1
|
||||
args: 1,6,3
|
||||
arg: Str('cn', cli_name='group_name')
|
||||
option: Flag('all', autofill=True, cli_name='all', default=False)
|
||||
option: Str('group*', alwaysask=True, cli_name='groups')
|
||||
option: Flag('no_members', autofill=True, default=False)
|
||||
option: Flag('raw', autofill=True, cli_name='raw', default=False)
|
||||
option: Str('user*', alwaysask=True, cli_name='users')
|
||||
option: Str('version?')
|
||||
output: Output('completed', type=[<type 'int'>])
|
||||
output: Output('failed', type=[<type 'dict'>])
|
||||
output: Entry('result')
|
||||
command: group_del/1
|
||||
args: 1,2,3
|
||||
arg: Str('cn+', cli_name='group_name')
|
||||
@ -1988,7 +2000,7 @@ output: Output('result', type=[<type 'bool'>])
|
||||
output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
|
||||
output: PrimaryKey('value')
|
||||
command: group_find/1
|
||||
args: 1,30,4
|
||||
args: 1,34,4
|
||||
arg: Str('criteria?')
|
||||
option: Flag('all', autofill=True, cli_name='all', default=False)
|
||||
option: Str('cn?', autofill=False, cli_name='group_name')
|
||||
@ -2001,6 +2013,8 @@ option: Str('in_hbacrule*', cli_name='in_hbacrules')
|
||||
option: Str('in_netgroup*', cli_name='in_netgroups')
|
||||
option: Str('in_role*', cli_name='in_roles')
|
||||
option: Str('in_sudorule*', cli_name='in_sudorules')
|
||||
option: Str('membermanager_group*', cli_name='membermanager_groups')
|
||||
option: Str('membermanager_user*', cli_name='membermanager_users')
|
||||
option: Str('no_group*', cli_name='no_groups')
|
||||
option: Flag('no_members', autofill=True, default=True)
|
||||
option: Principal('no_service*', cli_name='no_services')
|
||||
@ -2011,6 +2025,8 @@ option: Str('not_in_hbacrule*', cli_name='not_in_hbacrules')
|
||||
option: Str('not_in_netgroup*', cli_name='not_in_netgroups')
|
||||
option: Str('not_in_role*', cli_name='not_in_roles')
|
||||
option: Str('not_in_sudorule*', cli_name='not_in_sudorules')
|
||||
option: Str('not_membermanager_group*', cli_name='not_membermanager_groups')
|
||||
option: Str('not_membermanager_user*', cli_name='not_membermanager_users')
|
||||
option: Flag('pkey_only?', autofill=True, default=False)
|
||||
option: Flag('posix', autofill=True, cli_name='posix', default=False)
|
||||
option: Flag('private', autofill=True, cli_name='private', default=False)
|
||||
@ -2057,6 +2073,18 @@ option: Str('version?')
|
||||
output: Output('completed', type=[<type 'int'>])
|
||||
output: Output('failed', type=[<type 'dict'>])
|
||||
output: Entry('result')
|
||||
command: group_remove_member_manager/1
|
||||
args: 1,6,3
|
||||
arg: Str('cn', cli_name='group_name')
|
||||
option: Flag('all', autofill=True, cli_name='all', default=False)
|
||||
option: Str('group*', alwaysask=True, cli_name='groups')
|
||||
option: Flag('no_members', autofill=True, default=False)
|
||||
option: Flag('raw', autofill=True, cli_name='raw', default=False)
|
||||
option: Str('user*', alwaysask=True, cli_name='users')
|
||||
option: Str('version?')
|
||||
output: Output('completed', type=[<type 'int'>])
|
||||
output: Output('failed', type=[<type 'dict'>])
|
||||
output: Entry('result')
|
||||
command: group_show/1
|
||||
args: 1,5,3
|
||||
arg: Str('cn', cli_name='group_name')
|
||||
@ -2708,6 +2736,18 @@ option: Str('version?')
|
||||
output: Output('completed', type=[<type 'int'>])
|
||||
output: Output('failed', type=[<type 'dict'>])
|
||||
output: Entry('result')
|
||||
command: hostgroup_add_member_manager/1
|
||||
args: 1,6,3
|
||||
arg: Str('cn', cli_name='hostgroup_name')
|
||||
option: Flag('all', autofill=True, cli_name='all', default=False)
|
||||
option: Str('group*', alwaysask=True, cli_name='groups')
|
||||
option: Flag('no_members', autofill=True, default=False)
|
||||
option: Flag('raw', autofill=True, cli_name='raw', default=False)
|
||||
option: Str('user*', alwaysask=True, cli_name='users')
|
||||
option: Str('version?')
|
||||
output: Output('completed', type=[<type 'int'>])
|
||||
output: Output('failed', type=[<type 'dict'>])
|
||||
output: Entry('result')
|
||||
command: hostgroup_del/1
|
||||
args: 1,2,3
|
||||
arg: Str('cn+', cli_name='hostgroup_name')
|
||||
@ -2717,7 +2757,7 @@ output: Output('result', type=[<type 'dict'>])
|
||||
output: Output('summary', type=[<type 'unicode'>, <type 'NoneType'>])
|
||||
output: ListOfPrimaryKeys('value')
|
||||
command: hostgroup_find/1
|
||||
args: 1,21,4
|
||||
args: 1,25,4
|
||||
arg: Str('criteria?')
|
||||
option: Flag('all', autofill=True, cli_name='all', default=False)
|
||||
option: Str('cn?', autofill=False, cli_name='hostgroup_name')
|
||||
@ -2728,6 +2768,8 @@ option: Str('in_hbacrule*', cli_name='in_hbacrules')
|
||||
option: Str('in_hostgroup*', cli_name='in_hostgroups')
|
||||
option: Str('in_netgroup*', cli_name='in_netgroups')
|
||||
option: Str('in_sudorule*', cli_name='in_sudorules')
|
||||
option: Str('membermanager_group*', cli_name='membermanager_groups')
|
||||
option: Str('membermanager_user*', cli_name='membermanager_users')
|
||||
option: Str('no_host*', cli_name='no_hosts')
|
||||
option: Str('no_hostgroup*', cli_name='no_hostgroups')
|
||||
option: Flag('no_members', autofill=True, default=True)
|
||||
@ -2735,6 +2777,8 @@ option: Str('not_in_hbacrule*', cli_name='not_in_hbacrules')
|
||||
option: Str('not_in_hostgroup*', cli_name='not_in_hostgroups')
|
||||
option: Str('not_in_netgroup*', cli_name='not_in_netgroups')
|
||||
option: Str('not_in_sudorule*', cli_name='not_in_sudorules')
|
||||
option: Str('not_membermanager_group*', cli_name='not_membermanager_groups')
|
||||
option: Str('not_membermanager_user*', cli_name='not_membermanager_users')
|
||||
option: Flag('pkey_only?', autofill=True, default=False)
|
||||
option: Flag('raw', autofill=True, cli_name='raw', default=False)
|
||||
option: Int('sizelimit?', autofill=False)
|
||||
@ -2771,6 +2815,18 @@ option: Str('version?')
|
||||
output: Output('completed', type=[<type 'int'>])
|
||||
output: Output('failed', type=[<type 'dict'>])
|
||||
output: Entry('result')
|
||||
command: hostgroup_remove_member_manager/1
|
||||
args: 1,6,3
|
||||
arg: Str('cn', cli_name='hostgroup_name')
|
||||
option: Flag('all', autofill=True, cli_name='all', default=False)
|
||||
option: Str('group*', alwaysask=True, cli_name='groups')
|
||||
option: Flag('no_members', autofill=True, default=False)
|
||||
option: Flag('raw', autofill=True, cli_name='raw', default=False)
|
||||
option: Str('user*', alwaysask=True, cli_name='users')
|
||||
option: Str('version?')
|
||||
output: Output('completed', type=[<type 'int'>])
|
||||
output: Output('failed', type=[<type 'dict'>])
|
||||
output: Entry('result')
|
||||
command: hostgroup_show/1
|
||||
args: 1,5,3
|
||||
arg: Str('cn', cli_name='hostgroup_name')
|
||||
@ -6739,11 +6795,13 @@ default: env/1
|
||||
default: group/1
|
||||
default: group_add/1
|
||||
default: group_add_member/1
|
||||
default: group_add_member_manager/1
|
||||
default: group_del/1
|
||||
default: group_detach/1
|
||||
default: group_find/1
|
||||
default: group_mod/1
|
||||
default: group_remove_member/1
|
||||
default: group_remove_member_manager/1
|
||||
default: group_show/1
|
||||
default: hbacrule/1
|
||||
default: hbacrule_add/1
|
||||
@ -6796,10 +6854,12 @@ default: host_show/1
|
||||
default: hostgroup/1
|
||||
default: hostgroup_add/1
|
||||
default: hostgroup_add_member/1
|
||||
default: hostgroup_add_member_manager/1
|
||||
default: hostgroup_del/1
|
||||
default: hostgroup_find/1
|
||||
default: hostgroup_mod/1
|
||||
default: hostgroup_remove_member/1
|
||||
default: hostgroup_remove_member_manager/1
|
||||
default: hostgroup_show/1
|
||||
default: i18n_messages/1
|
||||
default: idoverridegroup/1
|
||||
|
@ -86,9 +86,8 @@ define(IPA_DATA_VERSION, 20100614120000)
|
||||
# #
|
||||
########################################################
|
||||
define(IPA_API_VERSION_MAJOR, 2)
|
||||
define(IPA_API_VERSION_MINOR, 234)
|
||||
# Last change: Added new auth indicators to ipauserauthtype and krbprincipalauthind.
|
||||
# Converted krbprincipalauthind from Str() to StrEnum()
|
||||
define(IPA_API_VERSION_MINOR, 235)
|
||||
# Last change: Add memberManager to groups.
|
||||
|
||||
########################################################
|
||||
# Following values are auto-generated from values above
|
||||
|
130
doc/designs/membermanager.md
Normal file
130
doc/designs/membermanager.md
Normal file
@ -0,0 +1,130 @@
|
||||
# Member Manager for group membership
|
||||
|
||||
## Overview
|
||||
|
||||
A member manager is a principal that is able to manage members of a
|
||||
group. Member managers are able to add new members to a group or remove
|
||||
existing members from a group. They cannot modify additional attributes
|
||||
of a group as a part of the member manager role.
|
||||
|
||||
Member management is implemented for *user groups* and *host groups*.
|
||||
Membership can be managed by users or user groups. Member managers are
|
||||
independent from members. A principal can be a member manager of a
|
||||
group without being a member of a group.
|
||||
|
||||
|
||||
## Use Cases
|
||||
|
||||
An administrator can use member management feature to delegate some
|
||||
control over user groups and host groups to users. For example a
|
||||
project manager is now able to add new team members to a project group.
|
||||
|
||||
A NFS admin with member management capability for a host group is able
|
||||
to indirectly influence an HBAC rules and control which hosts can
|
||||
connect to an NFS file share.
|
||||
|
||||
## Implementation
|
||||
|
||||
The user group commands and host group commands are extended to handle
|
||||
member managers. The plugin classes grow two additional sub commands,
|
||||
one for adding and one for removing member managers. The show command
|
||||
prints member manager users and member manager groups. The find command
|
||||
can search by member manager.
|
||||
|
||||
Member managers are stored in a new LDAP attribute ``memberManager``
|
||||
with OID 2.16.840.1.113730.3.8.23.1. It is multi-valued and contains
|
||||
DNs of users and groups which can manage members of the group. The
|
||||
attribute can be added to entries with object class ``ipaUserGroup``
|
||||
or ``ipaHostGroup``. The attribute is indexed and its membership
|
||||
controlled by referential integrity postoperation plugin.
|
||||
New userattr ACIs grant principals with user DN or group DN in
|
||||
``memberManager`` write permission to the ``member`` attribute of the
|
||||
group.
|
||||
|
||||
The ``memberManager`` attribute is protected by the generic read and
|
||||
modify permissions for each type of group. It is readable by everybody
|
||||
with ``System: Read Groups`` / ``System: Read Hostgroups`` permission
|
||||
and writable by everybody with ``System: Modify Groups`` /
|
||||
``System: Modify Hostgroups`` permission.
|
||||
|
||||
|
||||
## Examples
|
||||
|
||||
Add example user and groups:
|
||||
|
||||
```
|
||||
$ kinit admin
|
||||
$ ipa user-add john --first John --last Doe --random
|
||||
$ ipa user-add tom --first Tom --last Doe --random
|
||||
$ ipa group-add project
|
||||
$ ipa group-add project_admins
|
||||
```
|
||||
|
||||
Make user and group member managers:
|
||||
|
||||
```
|
||||
$ ipa group-add-member-manager project --users=john
|
||||
$ ipa group-add-member-manager project --groups=project_admins
|
||||
```
|
||||
|
||||
Show group:
|
||||
|
||||
```
|
||||
$ ipa group-show project
|
||||
Group name: project
|
||||
GID: 787600003
|
||||
Membership managed by groups: project_admins
|
||||
Membership managed by users: john
|
||||
```
|
||||
|
||||
Find groups by member managers:
|
||||
|
||||
```
|
||||
$ ipa group-find --membermanager-users=john
|
||||
---------------
|
||||
1 group matched
|
||||
---------------
|
||||
Group name: project
|
||||
GID: 787600003
|
||||
----------------------------
|
||||
Number of entries returned 1
|
||||
----------------------------
|
||||
$ ipa group-find --membermanager-groups=project_admins
|
||||
---------------
|
||||
1 group matched
|
||||
---------------
|
||||
Group name: project
|
||||
GID: 787600003
|
||||
----------------------------
|
||||
Number of entries returned 1
|
||||
----------------------------
|
||||
```
|
||||
|
||||
Use member management capability:
|
||||
|
||||
```
|
||||
$ kinit john
|
||||
$ ipa group-add-member project --users=tom
|
||||
Group name: project
|
||||
GID: 787600003
|
||||
Member users: tom
|
||||
Membership managed by groups: project_admins
|
||||
Membership managed by users: john
|
||||
-------------------------
|
||||
Number of members added 1
|
||||
-------------------------
|
||||
```
|
||||
|
||||
Remove member management capability:
|
||||
|
||||
```
|
||||
$ kinit admin
|
||||
$ ipa group-remove-member-manager project --groups=project_admins
|
||||
Group name: project
|
||||
GID: 787600003
|
||||
Member users: tom
|
||||
Membership managed by users: john
|
||||
---------------------------
|
||||
Number of members removed 1
|
||||
---------------------------
|
||||
```
|
@ -2,6 +2,7 @@
|
||||
##
|
||||
## Attributes: 2.16.840.1.113730.3.8.3 - V2 base attributres
|
||||
## ObjectClasses: 2.16.840.1.113730.3.8.4 - V2 base objectclasses
|
||||
## Attributes: 2.16.840.1.113730.3.8.23 - V4 base attributes
|
||||
##
|
||||
dn: cn=schema
|
||||
attributeTypes: (2.16.840.1.113730.3.8.3.1 NAME 'ipaUniqueID' DESC 'Unique identifier' EQUALITY caseIgnoreMatch ORDERING caseIgnoreOrderingMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'IPA v2' )
|
||||
@ -21,8 +22,10 @@ objectClasses: (2.16.840.1.113730.3.8.4.14 NAME 'ipaEntitlement' DESC 'IPA Entit
|
||||
objectClasses: (2.16.840.1.113730.3.8.4.15 NAME 'ipaPermission' DESC 'IPA Permission objectclass' AUXILIARY MAY ( ipaPermissionType ) X-ORIGIN 'IPA v2' )
|
||||
objectClasses: (2.16.840.1.113730.3.8.4.2 NAME 'ipaService' DESC 'IPA service objectclass' AUXILIARY MAY ( memberOf $ managedBy $ ipaKrbAuthzData) X-ORIGIN 'IPA v2' )
|
||||
objectClasses: (2.16.840.1.113730.3.8.4.3 NAME 'nestedGroup' DESC 'Group that supports nesting' SUP groupOfNames STRUCTURAL MAY memberOf X-ORIGIN 'IPA v2' )
|
||||
objectClasses: (2.16.840.1.113730.3.8.4.4 NAME 'ipaUserGroup' DESC 'IPA user group object class' SUP nestedGroup STRUCTURAL X-ORIGIN 'IPA v2' )
|
||||
objectClasses: (2.16.840.1.113730.3.8.4.5 NAME 'ipaHostGroup' DESC 'IPA host group object class' SUP nestedGroup STRUCTURAL X-ORIGIN 'IPA v2' )
|
||||
# Same for memberManager except it's actually v4 attribute
|
||||
attributeTypes: (2.16.840.1.113730.3.8.23.1 NAME 'memberManager' DESC 'DNs of entries allowed to manage group membership' SUP distinguishedName EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 X-ORIGIN 'IPA v4')
|
||||
objectClasses: (2.16.840.1.113730.3.8.4.4 NAME 'ipaUserGroup' DESC 'IPA user group object class' SUP nestedGroup STRUCTURAL MAY memberManager X-ORIGIN 'IPA v2' )
|
||||
objectClasses: (2.16.840.1.113730.3.8.4.5 NAME 'ipaHostGroup' DESC 'IPA host group object class' SUP nestedGroup STRUCTURAL MAY memberManager X-ORIGIN 'IPA v2' )
|
||||
attributeTypes: (2.16.840.1.113730.3.8.3.5 NAME 'memberUser' DESC 'Reference to a principal that performs an action (usually user).' SUP distinguishedName EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 X-ORIGIN 'IPA v2' )
|
||||
attributeTypes: (2.16.840.1.113730.3.8.3.6 NAME 'userCategory' DESC 'Additional classification for users' EQUALITY caseIgnoreMatch ORDERING caseIgnoreOrderingMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 X-ORIGIN 'IPA v2' )
|
||||
attributeTypes: (2.16.840.1.113730.3.8.3.7 NAME 'memberHost' DESC 'Reference to a device where the operation takes place (usually host).' SUP distinguishedName EQUALITY distinguishedNameMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.12 X-ORIGIN 'IPA v2' )
|
||||
|
@ -70,6 +70,19 @@ changetype: modify
|
||||
add: aci
|
||||
aci: (targetattr = "krbPrincipalKey || krbLastPwdChange")(target = "ldap:///fqdn=*,cn=computers,cn=accounts,$SUFFIX")(version 3.0;acl "Admins can manage host keytab";allow (write) groupdn = "ldap:///cn=admins,cn=groups,cn=accounts,$SUFFIX";)
|
||||
|
||||
# Allow member managers to modify members of user groups
|
||||
dn: cn=groups,cn=accounts,$SUFFIX
|
||||
changetype: modify
|
||||
add: aci
|
||||
aci: (targetattr = "member")(targetfilter = "(objectclass=ipaUserGroup)")(version 3.0; acl "Allow member managers to modify members of user groups"; allow (write) userattr = "memberManager#USERDN" or userattr = "memberManager#GROUPDN";)
|
||||
|
||||
# Allow member managers to modify members of a host group
|
||||
dn: cn=hostgroups,cn=accounts,$SUFFIX
|
||||
changetype: modify
|
||||
add: aci
|
||||
aci: (targetattr = "member")(targetfilter = "(objectclass=ipaHostGroup)")(version 3.0; acl "Allow member managers to modify members of host groups"; allow (write) userattr = "memberManager#USERDN" or userattr = "memberManager#GROUPDN";)
|
||||
|
||||
|
||||
# This is used for the host/service one-time passwordn and keytab indirectors.
|
||||
# We can do a query on a DN to see if an attribute exists.
|
||||
dn: cn=accounts,$SUFFIX
|
||||
|
@ -417,3 +417,12 @@ objectClass: top
|
||||
objectClass: nsIndex
|
||||
nsSystemIndex: false
|
||||
nsIndexType: eq
|
||||
|
||||
dn: cn=memberManager,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
|
||||
changetype: add
|
||||
cn: memberManager
|
||||
objectClass: top
|
||||
objectClass: nsIndex
|
||||
nsSystemIndex: false
|
||||
nsIndexType: eq
|
||||
nsIndexType: pres
|
||||
|
@ -442,7 +442,8 @@ exp.entity_builder = IPA.entity_builder = function(entity) {
|
||||
'member',
|
||||
'settings',
|
||||
'memberof',
|
||||
'managedby'
|
||||
'managedby',
|
||||
'membermanager'
|
||||
];
|
||||
|
||||
/**
|
||||
|
@ -151,6 +151,20 @@ return {
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
$type: 'association',
|
||||
name: 'membermanager_group',
|
||||
associator: IPA.serial_associator,
|
||||
add_title: '@i18n:objects.group.add_membermanager_group',
|
||||
remove_title: '@i18n:objects.group.remove_membermanager_group'
|
||||
},
|
||||
{
|
||||
$type: 'association',
|
||||
name: 'membermanager_user',
|
||||
associator: IPA.serial_associator,
|
||||
add_title: '@i18n:objects.group.add_membermanager_user',
|
||||
remove_title: '@i18n:objects.group.remove_membermanager_user'
|
||||
},
|
||||
{
|
||||
$type: 'association',
|
||||
name: 'memberof_group',
|
||||
|
@ -63,15 +63,31 @@ return {
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
$type: 'association',
|
||||
name: 'membermanager_group',
|
||||
associator: IPA.serial_associator,
|
||||
add_title: '@i18n:objects.hostgroup.add_membermanager_group',
|
||||
remove_title: '@i18n:objects.hostgroup.remove_membermanager_group'
|
||||
},
|
||||
{
|
||||
$type: 'association',
|
||||
name: 'membermanager_user',
|
||||
associator: IPA.serial_associator,
|
||||
add_title: '@i18n:objects.hostgroup.add_membermanager_user',
|
||||
remove_title: '@i18n:objects.hostgroup.remove_membermanager_user'
|
||||
},
|
||||
{
|
||||
$type: 'association',
|
||||
name: 'member_host',
|
||||
associator: IPA.serial_associator,
|
||||
add_title: '@i18n:objects.hostgroup.add_hosts',
|
||||
remove_title: '@i18n:objects.hostgroup.remove_hosts'
|
||||
},
|
||||
{
|
||||
$type: 'association',
|
||||
name: 'member_hostgroup',
|
||||
associator: IPA.serial_associator,
|
||||
add_title: '@i18n:objects.hostgroup.add_hostgroups',
|
||||
remove_title: '@i18n:objects.hostgroup.remove_hostgroups'
|
||||
},
|
||||
|
@ -132,6 +132,14 @@ add:aci: (targetfilter="(|(objectclass=ipaHost)(objectclass=ipaService))")(targe
|
||||
dn: $SUFFIX
|
||||
add:aci:(targetattr = "usercertificate")(version 3.0;acl "selfservice:Users can manage their own X.509 certificates";allow (write) userdn = "ldap:///self";)
|
||||
|
||||
# Allow member managers to modify members of user groups
|
||||
dn: cn=groups,cn=accounts,$SUFFIX
|
||||
add:aci: (targetattr = "member")(targetfilter = "(objectclass=ipaUserGroup)")(version 3.0; acl "Allow member managers to modify members of user groups"; allow (write) userattr = "memberManager#USERDN";)
|
||||
|
||||
# Allow member managers to modify members of host groups
|
||||
dn: cn=hostgroups,cn=accounts,$SUFFIX
|
||||
add:aci: (targetattr = "member")(targetfilter = "(objectclass=ipaHostGroup)")(version 3.0; acl "Allow member managers to modify members of host groups"; allow (write) userattr = "memberManager#USERDN";)
|
||||
|
||||
# Hosts can add and delete their own services
|
||||
dn: cn=services,cn=accounts,$SUFFIX
|
||||
remove:aci: (target = "ldap:///krbprincipalname=*/($$dn)@$REALM,cn=services,cn=accounts,$SUFFIX")(targetfilter = "(objectClass=ipaKrbPrincipal)")(version 3.0;acl "Hosts can add own services"; allow(add) userdn="ldap:///fqdn=($$dn),cn=computers,cn=accounts,$SUFFIX";)
|
||||
|
@ -380,3 +380,11 @@ default: objectClass: top
|
||||
default: objectClass: nsIndex
|
||||
default: nsSystemIndex: false
|
||||
default: nsIndexType: eq
|
||||
|
||||
dn: cn=memberManager,cn=index,cn=userRoot,cn=ldbm database,cn=plugins,cn=config
|
||||
default: cn: memberManager
|
||||
default: objectClass: top
|
||||
default: objectClass: nsIndex
|
||||
default: nsSystemIndex: false
|
||||
default: nsIndexType: eq
|
||||
default: nsIndexType: pres
|
||||
|
@ -20,3 +20,4 @@ add: referint-membership-attr: ipaallowedtarget
|
||||
add: referint-membership-attr: ipamemberca
|
||||
add: referint-membership-attr: ipamembercertprofile
|
||||
add: referint-membership-attr: ipalocation
|
||||
add: referint-membership-attr: membermanager
|
||||
|
@ -564,6 +564,11 @@ class LDAPObject(Object):
|
||||
'memberofindirect': (
|
||||
'Indirect Member Of', None, 'not_in_indirect_'
|
||||
),
|
||||
'membermanager': (
|
||||
'Group membership managed by',
|
||||
'membermanager_',
|
||||
'not_membermanager_'
|
||||
),
|
||||
}
|
||||
label = _('Entry')
|
||||
label_singular = _('Entry')
|
||||
|
@ -114,6 +114,15 @@ EXAMPLES:
|
||||
Display information about a named group.
|
||||
ipa group-show localadmins
|
||||
|
||||
Group membership managers are users or groups that can add members to a
|
||||
group or remove members from a group.
|
||||
|
||||
Allow user "test2" to add or remove members from group "localadmins":
|
||||
ipa group-add-member-manager --users=test2 localadmins
|
||||
|
||||
Revoke membership management rights for user "test2" from "localadmins":
|
||||
ipa group-remove-member-manager --users=test2 localadmins
|
||||
|
||||
External group membership is designed to allow users from trusted domains
|
||||
to be mapped to local POSIX groups in order to actually use IPA resources.
|
||||
External members should be added to groups that specifically created as
|
||||
@ -159,6 +168,22 @@ ipaexternalmember_param = Str('ipaexternalmember*',
|
||||
)
|
||||
|
||||
|
||||
group_output_params = (
|
||||
Str(
|
||||
'membermanager_group',
|
||||
label='Membership managed by groups',
|
||||
),
|
||||
Str(
|
||||
'membermanager_user',
|
||||
label='Membership managed by users',
|
||||
),
|
||||
Str(
|
||||
'membermanager',
|
||||
label=_('Failed membermanager'),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@register()
|
||||
class group(LDAPObject):
|
||||
"""
|
||||
@ -175,10 +200,12 @@ class group(LDAPObject):
|
||||
default_attributes = [
|
||||
'cn', 'description', 'gidnumber', 'member', 'memberof',
|
||||
'memberindirect', 'memberofindirect', 'ipaexternalmember',
|
||||
'membermanager',
|
||||
]
|
||||
uuid_attribute = 'ipauniqueid'
|
||||
attribute_members = {
|
||||
'member': ['user', 'group', 'service'],
|
||||
'membermanager': ['user', 'group'],
|
||||
'memberof': ['group', 'netgroup', 'role', 'hbacrule', 'sudorule'],
|
||||
'memberindirect': ['user', 'group', 'service'],
|
||||
'memberofindirect': ['group', 'netgroup', 'role', 'hbacrule',
|
||||
@ -194,7 +221,7 @@ class group(LDAPObject):
|
||||
'businesscategory', 'cn', 'description', 'gidnumber',
|
||||
'ipaexternalmember', 'ipauniqueid', 'mepmanagedby', 'o',
|
||||
'objectclass', 'ou', 'owner', 'seealso',
|
||||
'ipantsecurityidentifier'
|
||||
'ipantsecurityidentifier', 'membermanager',
|
||||
},
|
||||
},
|
||||
'System: Read Group Membership': {
|
||||
@ -248,7 +275,7 @@ class group(LDAPObject):
|
||||
'ipapermright': {'write'},
|
||||
'ipapermdefaultattr': {
|
||||
'cn', 'description', 'gidnumber', 'ipauniqueid',
|
||||
'mepmanagedby', 'objectclass'
|
||||
'mepmanagedby', 'objectclass', 'membermanager',
|
||||
},
|
||||
'replaces': [
|
||||
'(targetattr = "cn || description || gidnumber || objectclass || mepmanagedby || ipauniqueid")(target = "ldap:///cn=*,cn=groups,cn=accounts,$SUFFIX")(version 3.0;acl "permission:Modify Groups";allow (write) groupdn = "ldap:///cn=Modify Groups,cn=permissions,cn=pbac,$SUFFIX";)',
|
||||
@ -316,6 +343,7 @@ class group(LDAPObject):
|
||||
class group_add(LDAPCreate):
|
||||
__doc__ = _('Create a new group.')
|
||||
|
||||
has_output_params = LDAPCreate.has_output_params + group_output_params
|
||||
msg_summary = _('Added group "%(value)s"')
|
||||
|
||||
takes_options = LDAPCreate.takes_options + (
|
||||
@ -397,6 +425,7 @@ class group_del(LDAPDelete):
|
||||
class group_mod(LDAPUpdate):
|
||||
__doc__ = _('Modify a group.')
|
||||
|
||||
has_output_params = LDAPUpdate.has_output_params + group_output_params
|
||||
msg_summary = _('Modified group "%(value)s"')
|
||||
|
||||
takes_options = LDAPUpdate.takes_options + (
|
||||
@ -468,8 +497,9 @@ class group_mod(LDAPUpdate):
|
||||
class group_find(LDAPSearch):
|
||||
__doc__ = _('Search for groups.')
|
||||
|
||||
member_attributes = ['member', 'memberof']
|
||||
member_attributes = ['member', 'memberof', 'membermanager']
|
||||
|
||||
has_output_params = LDAPSearch.has_output_params + group_output_params
|
||||
msg_summary = ngettext(
|
||||
'%(count)d group matched', '%(count)d groups matched', 0
|
||||
)
|
||||
@ -538,6 +568,8 @@ class group_find(LDAPSearch):
|
||||
class group_show(LDAPRetrieve):
|
||||
__doc__ = _('Display information about a named group.')
|
||||
|
||||
has_output_params = LDAPRetrieve.has_output_params + group_output_params
|
||||
|
||||
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
|
||||
assert isinstance(dn, DN)
|
||||
if ('ipaexternalmember' in entry_attrs and
|
||||
@ -736,3 +768,21 @@ class group_detach(LDAPQuery):
|
||||
result=True,
|
||||
value=pkey_to_value(keys[0], options),
|
||||
)
|
||||
|
||||
|
||||
@register()
|
||||
class group_add_member_manager(LDAPAddMember):
|
||||
__doc__ = _('Add users that can manage members of this group.')
|
||||
|
||||
has_output_params = LDAPAddMember.has_output_params + group_output_params
|
||||
member_attributes = ['membermanager']
|
||||
|
||||
|
||||
@register()
|
||||
class group_remove_member_manager(LDAPRemoveMember):
|
||||
__doc__ = _('Remove users that can manage members of this group.')
|
||||
|
||||
has_output_params = (
|
||||
LDAPRemoveMember.has_output_params + group_output_params
|
||||
)
|
||||
member_attributes = ['membermanager']
|
||||
|
@ -58,6 +58,12 @@ EXAMPLES:
|
||||
Display a host group:
|
||||
ipa hostgroup-show baltimore
|
||||
|
||||
Add a member manager:
|
||||
ipa hostgroup-add-member-manager --users=user1 baltimore
|
||||
|
||||
Remove a member manager
|
||||
ipa hostgroup-remove-member-manager --users=user1 baltimore
|
||||
|
||||
Delete a hostgroup:
|
||||
ipa hostgroup-del baltimore
|
||||
""")
|
||||
@ -75,6 +81,22 @@ register = Registry()
|
||||
PROTECTED_HOSTGROUPS = (u'ipaservers',)
|
||||
|
||||
|
||||
hostgroup_output_params = (
|
||||
Str(
|
||||
'membermanager_group',
|
||||
label='Membership managed by groups',
|
||||
),
|
||||
Str(
|
||||
'membermanager_user',
|
||||
label='Membership managed by users',
|
||||
),
|
||||
Str(
|
||||
'membermanager',
|
||||
label=_('Failed membermanager'),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
@register()
|
||||
class hostgroup(LDAPObject):
|
||||
"""
|
||||
@ -86,12 +108,14 @@ class hostgroup(LDAPObject):
|
||||
object_class = ['ipaobject', 'ipahostgroup']
|
||||
permission_filter_objectclasses = ['ipahostgroup']
|
||||
search_attributes = ['cn', 'description', 'member', 'memberof']
|
||||
default_attributes = ['cn', 'description', 'member', 'memberof',
|
||||
'memberindirect', 'memberofindirect',
|
||||
default_attributes = [
|
||||
'cn', 'description', 'member', 'memberof', 'memberindirect',
|
||||
'memberofindirect', 'membermanager',
|
||||
]
|
||||
uuid_attribute = 'ipauniqueid'
|
||||
attribute_members = {
|
||||
'member': ['host', 'hostgroup'],
|
||||
'membermanager': ['user', 'group'],
|
||||
'memberof': ['hostgroup', 'netgroup', 'hbacrule', 'sudorule'],
|
||||
'memberindirect': ['host', 'hostgroup'],
|
||||
'memberofindirect': ['hostgroup', 'hbacrule', 'sudorule'],
|
||||
@ -103,7 +127,7 @@ class hostgroup(LDAPObject):
|
||||
'ipapermright': {'read', 'search', 'compare'},
|
||||
'ipapermdefaultattr': {
|
||||
'businesscategory', 'cn', 'description', 'ipauniqueid', 'o',
|
||||
'objectclass', 'ou', 'owner', 'seealso',
|
||||
'objectclass', 'ou', 'owner', 'seealso', 'membermanager',
|
||||
},
|
||||
},
|
||||
'System: Read Hostgroup Membership': {
|
||||
@ -135,7 +159,7 @@ class hostgroup(LDAPObject):
|
||||
},
|
||||
'System: Modify Hostgroups': {
|
||||
'ipapermright': {'write'},
|
||||
'ipapermdefaultattr': {'cn', 'description'},
|
||||
'ipapermdefaultattr': {'cn', 'description', 'membermanager'},
|
||||
'replaces': [
|
||||
'(targetattr = "cn || description")(target = "ldap:///cn=*,cn=hostgroups,cn=accounts,$SUFFIX")(version 3.0; acl "permission:Modify Hostgroups";allow (write) groupdn = "ldap:///cn=Modify Hostgroups,cn=permissions,cn=pbac,$SUFFIX";)',
|
||||
],
|
||||
@ -194,6 +218,7 @@ class hostgroup(LDAPObject):
|
||||
class hostgroup_add(LDAPCreate):
|
||||
__doc__ = _('Add a new hostgroup.')
|
||||
|
||||
has_output_params = LDAPCreate.has_output_params + hostgroup_output_params
|
||||
msg_summary = _('Added hostgroup "%(value)s"')
|
||||
|
||||
def pre_callback(self, ldap, dn, entry_attrs, attrs_list, *keys, **options):
|
||||
@ -248,6 +273,7 @@ class hostgroup_del(LDAPDelete):
|
||||
class hostgroup_mod(LDAPUpdate):
|
||||
__doc__ = _('Modify a hostgroup.')
|
||||
|
||||
has_output_params = LDAPUpdate.has_output_params + hostgroup_output_params
|
||||
msg_summary = _('Modified hostgroup "%(value)s"')
|
||||
|
||||
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
|
||||
@ -260,7 +286,8 @@ class hostgroup_mod(LDAPUpdate):
|
||||
class hostgroup_find(LDAPSearch):
|
||||
__doc__ = _('Search for hostgroups.')
|
||||
|
||||
member_attributes = ['member', 'memberof']
|
||||
member_attributes = ['member', 'memberof', 'membermanager']
|
||||
has_output_params = LDAPSearch.has_output_params + hostgroup_output_params
|
||||
msg_summary = ngettext(
|
||||
'%(count)d hostgroup matched', '%(count)d hostgroups matched', 0
|
||||
)
|
||||
@ -277,6 +304,10 @@ class hostgroup_find(LDAPSearch):
|
||||
class hostgroup_show(LDAPRetrieve):
|
||||
__doc__ = _('Display information about a hostgroup.')
|
||||
|
||||
has_output_params = (
|
||||
LDAPRetrieve.has_output_params + hostgroup_output_params
|
||||
)
|
||||
|
||||
def post_callback(self, ldap, dn, entry_attrs, *keys, **options):
|
||||
assert isinstance(dn, DN)
|
||||
self.obj.suppress_netgroup_memberof(ldap, dn, entry_attrs)
|
||||
@ -313,3 +344,23 @@ class hostgroup_remove_member(LDAPRemoveMember):
|
||||
assert isinstance(dn, DN)
|
||||
self.obj.suppress_netgroup_memberof(ldap, dn, entry_attrs)
|
||||
return (completed, dn)
|
||||
|
||||
|
||||
@register()
|
||||
class hostgroup_add_member_manager(LDAPAddMember):
|
||||
__doc__ = _('Add users that can manage members of this hostgroup.')
|
||||
|
||||
has_output_params = (
|
||||
LDAPAddMember.has_output_params + hostgroup_output_params
|
||||
)
|
||||
member_attributes = ['membermanager']
|
||||
|
||||
|
||||
@register()
|
||||
class hostgroup_remove_member_manager(LDAPRemoveMember):
|
||||
__doc__ = _('Remove users that can manage members of this hostgroup.')
|
||||
|
||||
has_output_params = (
|
||||
LDAPRemoveMember.has_output_params + hostgroup_output_params
|
||||
)
|
||||
member_attributes = ['membermanager']
|
||||
|
@ -301,6 +301,7 @@ class i18n_messages(Command):
|
||||
"managedby": _("${primary_key} is managed by:"),
|
||||
"member": _("${primary_key} members:"),
|
||||
"memberof": _("${primary_key} is a member of:"),
|
||||
"membermanager": _("${primary_key} member managers:"),
|
||||
},
|
||||
"facets": {
|
||||
"details": _("Settings"),
|
||||
@ -814,6 +815,22 @@ class i18n_messages(Command):
|
||||
"add_users": _(
|
||||
"Add users into user group '${primary_key}'"
|
||||
),
|
||||
"add_membermanager_group": _(
|
||||
"Add groups as member managers for user group "
|
||||
"'${primary_key}'"
|
||||
),
|
||||
"remove_membermanager_group": _(
|
||||
"Remove groups from member managers for user group "
|
||||
"'${primary_key}'"
|
||||
),
|
||||
"add_membermanager_user": _(
|
||||
"Add users as member managers for user group "
|
||||
"'${primary_key}'"
|
||||
),
|
||||
"remove_membermanager_user": _(
|
||||
"Remove users from member managers for user group "
|
||||
"'${primary_key}'"
|
||||
),
|
||||
"details": _("Group Settings"),
|
||||
"external": _("External"),
|
||||
"groups": _("Groups"),
|
||||
@ -1026,6 +1043,22 @@ class i18n_messages(Command):
|
||||
"add_into_sudo": _(
|
||||
"Add host group '${primary_key}' into sudo rules"
|
||||
),
|
||||
"add_membermanager_group": _(
|
||||
"Add groups as member managers for host group "
|
||||
"'${primary_key}'"
|
||||
),
|
||||
"remove_membermanager_group": _(
|
||||
"Remove groups from member managers for host group "
|
||||
"'${primary_key}'"
|
||||
),
|
||||
"add_membermanager_user": _(
|
||||
"Add users as member managers for host group "
|
||||
"'${primary_key}'"
|
||||
),
|
||||
"remove_membermanager_user": _(
|
||||
"Remove users from member managers for host group "
|
||||
"'${primary_key}'"
|
||||
),
|
||||
"host_group": _("Host Groups"),
|
||||
"identity": _("Host Group Settings"),
|
||||
"remove": _("Remove host groups"),
|
||||
|
Loading…
Reference in New Issue
Block a user