mirror of https://github.com/OpenIdentityPlatform/OpenDJ.git

maximthomas
02.10.2024 989a3319425a5e032c32a14e83c2aa4b8795f9e0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
<?xml version="1.0" encoding="UTF-8"?>
<!--
  ! CCPL HEADER START
  !
  ! This work is licensed under the Creative Commons
  ! Attribution-NonCommercial-NoDerivs 3.0 Unported License.
  ! To view a copy of this license, visit
  ! http://creativecommons.org/licenses/by-nc-nd/3.0/
  ! or send a letter to Creative Commons, 444 Castro Street,
  ! Suite 900, Mountain View, California, 94041, USA.
  !
  ! You can also obtain a copy of the license at
  ! trunk/opendj3/legal-notices/CC-BY-NC-ND.txt.
  ! See the License for the specific language governing permissions
  ! and limitations under the License.
  !
  ! If applicable, add the following below this CCPL HEADER, with the fields
  ! enclosed by brackets "[]" replaced with your own identifying information:
  !      Portions Copyright [yyyy] [name of copyright owner]
  !
  ! CCPL HEADER END
  !
  !      Copyright 2011-2013 ForgeRock AS
  !    
-->
<chapter xml:id='chap-groups'
 xmlns='http://docbook.org/ns/docbook' version='5.0' xml:lang='en'
 xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'
 xsi:schemaLocation='http://docbook.org/ns/docbook http://docbook.org/xml/5.0/xsd/docbook.xsd'
 xmlns:xlink='http://www.w3.org/1999/xlink'
 xmlns:xinclude='http://www.w3.org/2001/XInclude'>
 <title>Working With Groups of Entries</title>
 
 <para>OpenDJ supports several methods of grouping entries in the directory.
 Static groups list their members, whereas dynamic groups look up their
 membership based on an LDAP filter. OpenDJ also supports virtual static
 groups, which uses a dynamic group style definition, but allows applications
 to list group members as if the group were static.</para>
 
 <para>When listing entries in static groups, you must also have a mechanism
 for removing entries from the list when they are deleted or modified in ways
 that end their membership. OpenDJ makes that possible with
 <emphasis>referential integrity</emphasis> functionality.</para>
 
 <para>This chapter demonstrates how to work with groups.</para>
 
 <tip>
  <para>The examples in this chapter assume that an
  <literal>ou=Groups,dc=example,dc=com</literal> entry already exists. If you
  imported data from <link xlink:href="http://opendj.forgerock.org/Example.ldif"
  xlink:show="new">Example.ldif</link>, then you already have the entry. If you
  generated data during setup and did not create an organizational unit for
  groups yet, create the entry before you try the examples.</para>
 
  <screen>$ ldapmodify
 --defaultAdd
 --port 1389
 --bindDN "cn=Directory Manager"
 --bindPassword password
dn: ou=Groups,dc=example,dc=com
objectClass: organizationalunit
objectClass: top
ou: Groups
 
Processing ADD request for ou=Groups,dc=example,dc=com
ADD operation successful for DN ou=Groups,dc=example,dc=com</screen>
 </tip>
 
 <section xml:id="static-groups">
  <title>Creating Static Groups</title>
  <indexterm>
   <primary>Groups</primary>
   <secondary>Static</secondary>
  </indexterm>
  
  <para>A <firstterm>static group</firstterm> is expressed as an entry
  that enumerates all the entries that belong to the group. Static group
  entries grow as their membership increases.</para>
  
  <para>Static group entries can take the standard object class
  <literal>groupOfNames</literal> where each <literal>member</literal>
  attribute value is a distinguished name of an entry, or
  <literal>groupOfUniqueNames</literal> where each
  <literal>uniqueMember</literal> attribute value has Name and Optional UID
  syntax.<footnote><para>Name and Optional UID syntax values are a DN optionally
  followed by <literal>#<replaceable>BitString</replaceable></literal>. The
  <replaceable>BitString</replaceable>, such as <literal>'0101111101'B</literal>,
  serves to distinguish the entry from another entry having the same DN, which
  can occur when the original entry was deleted and a new entry created with the
  same DN.</para></footnote> Like other LDAP attributes,
  <literal>member</literal> and <literal>uniqueMember</literal> attributes take
  sets of unique values.</para>
 
  <para>Static group entries can also have the object class
  <literal>groupOfEntries</literal>, which is like
  <literal>groupOfNames</literal> except that it is designed to allow
  groups not to have members.</para>
 
  <para>When creating a group entry, use <literal>groupOfNames</literal> or
  <literal>groupOfEntries</literal> where possible.</para>
  
  <para>To create a static group, add a group entry such as the following
  to the directory.</para>
 
  <screen>$ cat static.ldif 
dn: cn=My Static Group,ou=Groups,dc=example,dc=com
cn: My Static Group
objectClass: groupOfNames
objectClass: top
ou: Groups
member: uid=ahunter,ou=People,dc=example,dc=com
member: uid=bjensen,ou=People,dc=example,dc=com
member: uid=tmorris,ou=People,dc=example,dc=com
 
$ ldapmodify
 --port 1389
 --bindDN "cn=Directory Manager"
 --bindPassword password
 --defaultAdd
 --filename static.ldif 
Processing ADD request for cn=My Static Group,ou=Groups,dc=example,dc=com
ADD operation successful for DN cn=My Static Group,ou=Groups,dc=example,dc=com</screen>
  
  <para>To change group membership, modify the values of the membership
  attribute.</para>
  
  <screen>$ cat add2grp.ldif 
dn: cn=My Static Group,ou=Groups,dc=example,dc=com
changetype: modify
add: member
member: uid=scarter,ou=People,dc=example,dc=com
 
$ ldapmodify
 --port 1389
 --bindDN "cn=Directory Manager"
 --bindPassword password
 --filename add2grp.ldif 
Processing MODIFY request for cn=My Static Group,ou=Groups,dc=example,dc=com
MODIFY operation successful for DN
 cn=My Static Group,ou=Groups,dc=example,dc=com
$ ldapsearch
 --port 1389
 --baseDN dc=example,dc=com
 "(cn=My Static Group)"
dn: cn=My Static Group,ou=Groups,dc=example,dc=com
ou: Groups
objectClass: groupOfNames
objectClass: top
member: uid=ahunter,ou=People,dc=example,dc=com
member: uid=bjensen,ou=People,dc=example,dc=com
member: uid=tmorris,ou=People,dc=example,dc=com
member: uid=scarter,ou=People,dc=example,dc=com
cn: My Static Group</screen>
 
  <para>RFC 4519 says a <literal>groupOfNames</literal> entry must have
  at least one member. Although OpenDJ allows you to create a
  <literal>groupOfNames</literal> without members, strictly speaking that
  behavior is not standard. Alternatively, you can use the
  <literal>groupOfEntries</literal> object class as shown in the following
  example.</para>
 
  <screen>$ cat group-of-entries.ldif
dn: cn=Initially Empty Static Group,ou=Groups,dc=example,dc=com
cn: Initially Empty Static Group
objectClass: groupOfEntries
objectClass: top
ou: Groups
 
$ ldapmodify
 --port 1389
 --bindDN "cn=Directory Manager"
 --bindPassword password
 --defaultAdd
 --filename group-of-entries.ldif
Processing ADD request for
 cn=Initially Empty Static Group,ou=Groups,dc=example,dc=com
ADD operation successful for DN
 cn=Initially Empty Static Group,ou=Groups,dc=example,dc=com
$ cat add-members.ldif
# Now add some members to the group.
dn: cn=Initially Empty Static Group,ou=Groups,dc=example,dc=com
changetype: modify
add: member
member: uid=ahunter,ou=People,dc=example,dc=com
member: uid=bjensen,ou=People,dc=example,dc=com
member: uid=tmorris,ou=People,dc=example,dc=com
member: uid=scarter,ou=People,dc=example,dc=com
 
$ ldapmodify
 --port 1389
 --bindDN "cn=Directory Manager"
 --bindPassword password
 --filename add-members.ldif
Processing MODIFY request for
 cn=Initially Empty Static Group,ou=Groups,dc=example,dc=com
MODIFY operation successful for DN
 cn=Initially Empty Static Group,ou=Groups,dc=example,dc=com</screen>
 </section>
 
 <section xml:id="dynamic-groups">
  <title>Creating Dynamic Groups</title>
  <indexterm>
   <primary>Groups</primary>
   <secondary>Dynamic</secondary>
  </indexterm>
  
  <para>A <firstterm>dynamic group</firstterm> specifies members using
  LDAP URLs. Dynamic groups entries can stay small even as their
  membership increases.</para>
  
  <para>Dynamic group entries take the <literal>groupOfURLs</literal>
  object class, with one or more <literal>memberURL</literal> values
  specifying LDAP URLs to identify group members.</para>
  
  <para>To create a dynamic group, add a group entry such as the following to
  the directory.</para>
 
  <para>The following example builds a dynamic group of entries effectively
  matching the filter <literal>"(l=Cupertino)"</literal> (users whose location
  is Cupertino). Change the filter if your data is different, and so no
  entries have <literal>l: Cupertino</literal>.</para>
 
  <screen>$ cat dynamic.ldif
dn: cn=My Dynamic Group,ou=Groups,dc=example,dc=com
cn: My Dynamic Group
objectClass: top
objectClass: groupOfURLs
ou: Groups
memberURL: ldap:///ou=People,dc=example,dc=com??sub?l=Cupertino
 
$ ldapmodify
 --port 1389
 --bindDN "cn=Directory Manager"
 --bindPassword password
 --defaultAdd
 --filename dynamic.ldif 
Processing ADD request for cn=My Dynamic Group,ou=Groups,dc=example,dc=com
ADD operation successful for DN cn=My Dynamic Group,ou=Groups,dc=example,dc=com</screen>
  
  <para>Group membership changes dynamically as entries change to match the
  <literal>memberURL</literal> values.</para>
  
  <screen>$ ldapsearch
 --port 1389
 --baseDN dc=example,dc=com
 "(&amp;(uid=*jensen)(isMemberOf=cn=My Dynamic Group,ou=Groups,dc=example,dc=com))"
 mail
dn: uid=bjensen,ou=People,dc=example,dc=com
mail: bjensen@example.com
 
dn: uid=rjensen,ou=People,dc=example,dc=com
mail: rjensen@example.com
 
$ ldapmodify
 --port 1389
 --bindDN "cn=Directory Manager"
 --bindPassword password
dn: uid=ajensen,ou=People,dc=example,dc=com
changetype: modify
replace: l
l: Cupertino
 
Processing MODIFY request for uid=ajensen,ou=People,dc=example,dc=com
MODIFY operation successful for DN uid=ajensen,ou=People,dc=example,dc=com
^D
$ ldapsearch
 --port 1389
 --baseDN dc=example,dc=com
 "(&amp;(uid=*jensen)(isMemberOf=cn=My Dynamic Group,ou=Groups,dc=example,dc=com))"
 mail
dn: uid=ajensen,ou=People,dc=example,dc=com
mail: ajensen@example.com
 
dn: uid=bjensen,ou=People,dc=example,dc=com
mail: bjensen@example.com
 
dn: uid=rjensen,ou=People,dc=example,dc=com
mail: rjensen@example.com</screen>
 </section>
 
 <section xml:id="virtual-static-groups">
  <title>Creating Virtual Static Groups</title>
  <indexterm>
   <primary>Groups</primary>
   <secondary>Virtual static</secondary>
  </indexterm>
  
  <para>OpenDJ lets you create <firstterm>virtual static groups</firstterm>,
  which let applications see dynamic groups as what appear to be static
  groups.</para>
  
  <para>The virtual static group takes auxiliary object class
  <literal>ds-virtual-static-group</literal>. Virtual static groups also take
  either the object class <literal>groupOfNames</literal>, or
  <literal>groupOfUniqueNames</literal>, but instead of having
  <literal>member</literal> or <literal>uniqueMember</literal> attributes,
  have <literal>ds-target-group-dn</literal> attributes pointing to other
  groups.</para>
  
  <para>Generating the list of members can be resource intensive for large
  groups, so by default you cannot retrieve the list of members. You can
  change this with the <command>dsconfig</command> command by setting the
  <literal>Virtual Static member</literal> or
  <literal>Virtual Static uniqueMember</literal> property.</para>
  
  <screen>$ dsconfig
 set-virtual-attribute-prop
 --port 4444
 --hostname opendj.example.com
 --bindDN "cn=Directory Manager"
 --bindPassword password
 --name "Virtual Static member"
 --set allow-retrieving-membership:true
 --trustAll
 --no-prompt</screen>
  
  <para>The following example creates a virtual static group, and reads the
  group entry with all members.</para>
  
  <screen>$ cat virtual.ldif 
dn: cn=Virtual Static,ou=Groups,dc=example,dc=com
cn: Virtual Static
objectclass: top
objectclass: groupOfNames
objectclass: ds-virtual-static-group
ds-target-group-dn: cn=My Dynamic Group,ou=Groups,dc=example,dc=com
 
$ ldapmodify
 --port 1389
 --bindDN "cn=Directory Manager"
 --bindPassword password
 --defaultAdd
 --filename virtual.ldif
Processing ADD request for cn=Virtual Static,ou=Groups,dc=example,dc=com
ADD operation successful for DN cn=Virtual Static,ou=Groups,dc=example,dc=com
$ ldapsearch --port 1389 --baseDN dc=example,dc=com "(cn=Virtual Static)"
dn: cn=Virtual Static,ou=Groups,dc=example,dc=com
objectClass: groupOfNames
objectClass: ds-virtual-static-group
objectClass: top
member: uid=jwalker,ou=People,dc=example,dc=com
member: uid=jmuffly,ou=People,dc=example,dc=com
member: uid=tlabonte,ou=People,dc=example,dc=com
member: uid=dakers,ou=People,dc=example,dc=com
member: uid=jreuter,ou=People,dc=example,dc=com
member: uid=rfisher,ou=People,dc=example,dc=com
member: uid=pshelton,ou=People,dc=example,dc=com
member: uid=rjensen,ou=People,dc=example,dc=com
member: uid=jcampaig,ou=People,dc=example,dc=com
member: uid=mjablons,ou=People,dc=example,dc=com
member: uid=mlangdon,ou=People,dc=example,dc=com
member: uid=aknutson,ou=People,dc=example,dc=com
member: uid=bplante,ou=People,dc=example,dc=com
member: uid=awalker,ou=People,dc=example,dc=com
member: uid=smason,ou=People,dc=example,dc=com
member: uid=ewalker,ou=People,dc=example,dc=com
member: uid=dthorud,ou=People,dc=example,dc=com
member: uid=btalbot,ou=People,dc=example,dc=com
member: uid=tcruse,ou=People,dc=example,dc=com
member: uid=kcarter,ou=People,dc=example,dc=com
member: uid=aworrell,ou=People,dc=example,dc=com
member: uid=bjensen,ou=People,dc=example,dc=com
member: uid=ajensen,ou=People,dc=example,dc=com
member: uid=cwallace,ou=People,dc=example,dc=com
member: uid=mwhite,ou=People,dc=example,dc=com
member: uid=kschmith,ou=People,dc=example,dc=com
member: uid=mtalbot,ou=People,dc=example,dc=com
member: uid=tschmith,ou=People,dc=example,dc=com
member: uid=gfarmer,ou=People,dc=example,dc=com
member: uid=speterso,ou=People,dc=example,dc=com
member: uid=prose,ou=People,dc=example,dc=com
member: uid=jbourke,ou=People,dc=example,dc=com
member: uid=mtyler,ou=People,dc=example,dc=com
member: uid=abergin,ou=People,dc=example,dc=com
member: uid=mschneid,ou=People,dc=example,dc=com
cn: Virtual Static
ds-target-group-dn: cn=My Dynamic Group,ou=Groups,dc=example,dc=com</screen>
 </section>
 
 <section xml:id="group-membership">
  <title>Looking Up Group Membership</title>
  <indexterm>
   <primary>Groups</primary>
   <secondary>Membership</secondary>
  </indexterm>
  
  <para>OpenDJ lets you look up which groups a user belongs to by using the
  <literal>isMemberOf</literal> attribute.</para>
  
  <screen>$ ldapsearch
 --port 1389
 --baseDN dc=example,dc=com
 uid=bjensen
 isMemberOf
dn: uid=bjensen,ou=People,dc=example,dc=com
isMemberOf: cn=My Static Group,ou=Groups,dc=example,dc=com
isMemberOf: cn=Virtual Static,ou=Groups,dc=example,dc=com
isMemberOf: cn=My Dynamic Group,ou=Groups,dc=example,dc=com</screen>
  
  <para>You must request <literal>isMemberOf</literal> explicitly.</para>
 </section>
 
 <section xml:id="referential-integrity">
  <title>Configuring Referential Integrity</title>
  <indexterm>
   <primary>Groups</primary>
   <secondary>Referential integrity</secondary>
  </indexterm>
  
  <para>When you delete or rename an entry that belongs to static groups, that
  entry's DN must be removed or changed in the list of each group to which it
  belongs. You can configure OpenDJ to resolve membership on your behalf after
  the change operation succeeds by enabling referential integrity.</para>
  
  <para>Referential integrity functionality is implemented as a plugin. The
  referential integrity plugin is disabled by default. To enable the plugin,
  use the <command>dsconfig</command> command.</para>
  
  <screen>$ dsconfig
 set-plugin-prop
 --port 4444
 --hostname opendj.example.com
 --bindDN "cn=Directory Manager"
 --bindPassword password
 --plugin-name "Referential Integrity"
 --set enabled:true
 --trustAll --no-prompt</screen>
 
  <para>With the plugin enabled, you can see OpenDJ referential integrity
  resolving group membership automatically.</para>
  
  <screen>$ ldapsearch --port 1389 --baseDN dc=example,dc=com "(cn=My Static Group)"
dn: cn=My Static Group,ou=Groups,dc=example,dc=com
ou: Groups
objectClass: groupOfNames
objectClass: top
member: uid=ahunter,ou=People,dc=example,dc=com
member: uid=bjensen,ou=People,dc=example,dc=com
member: uid=tmorris,ou=People,dc=example,dc=com
member: uid=scarter,ou=People,dc=example,dc=com
cn: My Static Group
 
$ ldapdelete
 --port 1389
 --bindDN "cn=Directory Manager"
 --bindPassword password
 uid=scarter,ou=People,dc=example,dc=com
Processing DELETE request for uid=scarter,ou=People,dc=example,dc=com
DELETE operation successful for DN uid=scarter,ou=People,dc=example,dc=com
$ ldapsearch --port 1389 --baseDN dc=example,dc=com "(cn=My Static Group)"
dn: cn=My Static Group,ou=Groups,dc=example,dc=com
ou: Groups
objectClass: groupOfNames
objectClass: top
cn: My Static Group
member: uid=ahunter,ou=People,dc=example,dc=com
member: uid=bjensen,ou=People,dc=example,dc=com
member: uid=tmorris,ou=People,dc=example,dc=com</screen>
 
 <para>By default the referential integrity plugin is configured to manage
 <literal>member</literal> and <literal>uniqueMember</literal> attributes.
 These attributes take values that are DNs, and are indexed for equality by
 default. Before you add an additional attribute to manage, make sure that
 it has DN syntax and that it is indexed for equality. OpenDJ requires that
 the attribute be indexed because an unindexed search for integrity would
 potentially consume too many of the server's resources. Attribute syntax is
 explained in the chapter on <link xlink:href="admin-guide#chap-schema"
 xlink:show="new" xlink:role="http://docbook.org/xlink/role/olink"><citetitle
 >Managing Schema</citetitle></link>. For instructions on indexing attributes,
 see the section on <link xlink:href="admin-guide#configure-indexes"
 xlink:show="new" xlink:role="http://docbook.org/xlink/role/olink"><citetitle
  >Configuring &amp; Rebuilding Indexes</citetitle></link>.</para>
 
 <para>You can also configure the referential integrity plugin to check that
 new entries added to groups actually exist in the directory by setting the
 <literal>check-references</literal> property to <literal>true</literal>. You
 can specify additional criteria once you have activated the check. To ensure
 that entries added must match a filter, set the
 <literal>check-references-filter-criteria</literal> to identify the attribute
 and the filter. For example, you can specify that group members must be person
 entries by setting <literal>check-references-filter-criteria</literal> to
 <literal>member:(objectclass=person)</literal>. To ensure that entries must be
 located in the same naming context, set
 <literal>check-references-scope-criteria</literal> to
 <literal>naming-context</literal>.</para>
 </section>
</chapter>