hydra-ldap 0.0.3 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +2 -0
- data/README.md +52 -6
- data/config/hydra-ldap.yml +13 -6
- data/hydra-ldap-example.ldif +362 -0
- data/hydra-ldap.gemspec +2 -1
- data/lib/hydra-ldap.rb +87 -46
- data/lib/hydra/ldap/version.rb +1 -1
- data/spec/integration/ldap_spec.rb +85 -26
- data/spec/spec_helper.rb +2 -0
- metadata +36 -3
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -22,13 +22,59 @@ Create the config file (config/ldap.yml) by running:
|
|
22
22
|
|
23
23
|
<pre>rails generate hydra-ldap</pre>
|
24
24
|
|
25
|
+
Made the filters, attributes and result parsing all parameters as frequently as possible, to try and make this
|
26
|
+
usable to many LDAP directory set ups.
|
25
27
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
<pre>
|
30
|
-
|
31
|
-
|
28
|
+
It might be helpful to look at the hydra-ldap-example.ldif, config/hydra-ldap.yml and spec/integration/ldap_spec.rb to see what type of configuration the tests are running for comparison purposes.
|
29
|
+
|
30
|
+
The attributes here would change based on LDAP configuration.
|
31
|
+
<pre>
|
32
|
+
attrs = {
|
33
|
+
:cn => 'Test'
|
34
|
+
:objectclass => 'groupofnames'
|
35
|
+
:description => 'my test group contains users, and owners'
|
36
|
+
:owner => 'uid=abc123'
|
37
|
+
:member => ['john', 'jane', 'fido']
|
38
|
+
}
|
39
|
+
Hydra::LDAP.create_group(group_code, attributes{})
|
40
|
+
</pre>
|
41
|
+
|
42
|
+
Examples of how to customize the results being returned, print out the cn attribute for
|
43
|
+
the groups owned by this user (hoping these are helpful for NU).
|
44
|
+
<pre>
|
45
|
+
filter = Net::LDAP::Filter.construct("(owner=uid=quentin,ou=people,dc=example,dc=org)")
|
46
|
+
Hydra::LDAP.groups_owned_by_user(filter, ['owner', 'cn']){ |result| result.map{ |r| puts r[:cn].first } }
|
47
|
+
</pre>
|
48
|
+
|
49
|
+
<pre>
|
50
|
+
uid = 'uid'
|
51
|
+
filter=Net::LDAP::Filter.construct("(&(objectClass=groupofnames)(member=uid=#{uid}))")
|
52
|
+
attributes = ['cn']
|
53
|
+
Hydra::LDAP.groups_for_user(filter, attributes){ |result| result.map { |r| r[:cn].first }}
|
54
|
+
</pre>
|
55
|
+
|
56
|
+
<pre>
|
57
|
+
filter = Net::LDAP::Filter.construct("(cn=#{group_code})")
|
58
|
+
attributes = ['default attribute is description']
|
59
|
+
Hydra::LDAP.title_of_group(group_code, filter, attributes){ |result| result.first[:description].first }
|
60
|
+
</pre>
|
61
|
+
|
62
|
+
<pre>
|
63
|
+
filter = Net::LDAP::Filter.construct("(cn=#{group_code})")
|
64
|
+
Hydra::LDAP.users_for_group(group_code, filter, ['member']){ |result| result.first[:uniquemember].map{ |r| r.sub(/^uid=/, '') }}
|
65
|
+
</pre>
|
66
|
+
|
67
|
+
<pre>
|
68
|
+
filter = Net::LDAP::Filter.construct("(cn=#{group_code})")
|
69
|
+
Hydra::LDAP.owner_for_group(group_code, filter, ['owner']) { |result| result.first[:owner].map{ |r| r.sub(/^uid=/, '') }}
|
70
|
+
</pre>
|
71
|
+
|
72
|
+
These are all pretty similar to previous calls, if not the same signatures.
|
73
|
+
<pre>Hydra::LDAP.delete_group(group_code).should be_true</pre>
|
74
|
+
|
75
|
+
|
76
|
+
<pre>Hydra::LDAP.add_users_to_group(group_code, ['bruce', 'beth'])</pre>
|
77
|
+
<pre>Hydra::LDAP.remove_users_from_group(group_code, ['bruce'])</pre>
|
32
78
|
|
33
79
|
## Contributing
|
34
80
|
|
data/config/hydra-ldap.yml
CHANGED
@@ -1,9 +1,16 @@
|
|
1
1
|
test:
|
2
|
-
host:
|
3
|
-
port:
|
4
|
-
|
5
|
-
|
6
|
-
group_base: ou=groups,dc=example,dc=com
|
7
|
-
base: ou=people,dc=example,dc=com
|
2
|
+
host: localhost
|
3
|
+
port: 3897
|
4
|
+
group_base: ou=groups,dc=example,dc=org
|
5
|
+
base: ou=people,dc=example,dc=org
|
8
6
|
uid: uid
|
9
7
|
|
8
|
+
development:
|
9
|
+
host: localhost
|
10
|
+
port: 3897
|
11
|
+
group_base: ou=groups,dc=example,dc=org
|
12
|
+
base: ou=people,dc=example,dc=org
|
13
|
+
uid: uid
|
14
|
+
group_member: uniquemember # attribute name in a group to identify a member
|
15
|
+
group_owner: owner # attribute name to identify group owner
|
16
|
+
|
@@ -0,0 +1,362 @@
|
|
1
|
+
version: 1
|
2
|
+
|
3
|
+
dn: ou=people,dc=example,dc=org
|
4
|
+
objectClass: top
|
5
|
+
objectClass: organizationalUnit
|
6
|
+
ou: people
|
7
|
+
|
8
|
+
dn: ou=groups,dc=example,dc=org
|
9
|
+
objectClass: top
|
10
|
+
objectClass: organizationalUnit
|
11
|
+
ou: groups
|
12
|
+
|
13
|
+
|
14
|
+
dn: uid=aa729,ou=people,dc=example,dc=org
|
15
|
+
objectClass: top
|
16
|
+
objectClass: person
|
17
|
+
objectClass: organizationalPerson
|
18
|
+
objectClass: inetOrgPerson
|
19
|
+
cn: Alexandra Adams
|
20
|
+
sn: Adams
|
21
|
+
givenName: Alexandra
|
22
|
+
mail: alexandra@example.org
|
23
|
+
uid: aa729
|
24
|
+
# Password is "smada"
|
25
|
+
userpassword: {SHA}pGlmZX1VOEdHHb30HZezeVNFxGM=
|
26
|
+
|
27
|
+
dn: uid=bb459,ou=people,dc=example,dc=org
|
28
|
+
objectClass: top
|
29
|
+
objectClass: person
|
30
|
+
objectClass: organizationalPerson
|
31
|
+
objectClass: inetOrgPerson
|
32
|
+
cn: Belle Baldwin
|
33
|
+
sn: Baldwin
|
34
|
+
givenName: Belle
|
35
|
+
mail: belle@example.org
|
36
|
+
uid: bb459
|
37
|
+
# Password is "niwdlab"
|
38
|
+
userpassword: {SHA}LRif2N+5TDSaO/rdkH2HHF8fF74=
|
39
|
+
|
40
|
+
dn: uid=cc414,ou=people,dc=example,dc=org
|
41
|
+
objectClass: top
|
42
|
+
objectClass: person
|
43
|
+
objectClass: organizationalPerson
|
44
|
+
objectClass: inetOrgPerson
|
45
|
+
cn: Claire Carpenter
|
46
|
+
sn: Carpenter
|
47
|
+
givenName: Claire
|
48
|
+
mail: claire@example.org
|
49
|
+
uid: cc414
|
50
|
+
# Password is "retneprac"
|
51
|
+
userpassword: {SHA}UL/iS+2R7GhwbhXOWoTHd4/qoMA=
|
52
|
+
|
53
|
+
dn: uid=dd945,ou=people,dc=example,dc=org
|
54
|
+
objectClass: top
|
55
|
+
objectClass: person
|
56
|
+
objectClass: organizationalPerson
|
57
|
+
objectClass: inetOrgPerson
|
58
|
+
cn: Dorothy Dawson
|
59
|
+
sn: Dawson
|
60
|
+
givenName: Dorothy
|
61
|
+
mail: dorothy@example.org
|
62
|
+
uid: dd945
|
63
|
+
# Password is "noswad"
|
64
|
+
userpassword: {SHA}D0UlcTfbCddFLwih04ig4DEilAc=
|
65
|
+
|
66
|
+
dn: uid=ee855,ou=people,dc=example,dc=org
|
67
|
+
objectClass: top
|
68
|
+
objectClass: person
|
69
|
+
objectClass: organizationalPerson
|
70
|
+
objectClass: inetOrgPerson
|
71
|
+
cn: Elizabeth Emerson
|
72
|
+
sn: Emerson
|
73
|
+
givenName: Elizabeth
|
74
|
+
mail: elizabeth@example.org
|
75
|
+
uid: ee855
|
76
|
+
# Password is "nosreme"
|
77
|
+
userpassword: {SHA}pheE9wd/iTps6f8bJjM6AePjwrU=
|
78
|
+
|
79
|
+
dn: uid=ff531,ou=people,dc=example,dc=org
|
80
|
+
objectClass: top
|
81
|
+
objectClass: person
|
82
|
+
objectClass: organizationalPerson
|
83
|
+
objectClass: inetOrgPerson
|
84
|
+
cn: Freya Fuller
|
85
|
+
sn: Fuller
|
86
|
+
givenName: Freya
|
87
|
+
mail: freya@example.org
|
88
|
+
uid: ff531
|
89
|
+
# Password is "relluf"
|
90
|
+
userpassword: {SHA}HLU2WZjFf/PF0Pp4qSDzoB3x+bs=
|
91
|
+
|
92
|
+
dn: uid=gg855,ou=people,dc=example,dc=org
|
93
|
+
objectClass: top
|
94
|
+
objectClass: person
|
95
|
+
objectClass: organizationalPerson
|
96
|
+
objectClass: inetOrgPerson
|
97
|
+
cn: Grace Gonzales
|
98
|
+
sn: Gonzales
|
99
|
+
givenName: Grace
|
100
|
+
mail: grace@example.org
|
101
|
+
uid: gg855
|
102
|
+
# Password is "selaznog"
|
103
|
+
userpassword: {SHA}zT4oO9pFXIj+ISIc60bvM8A5+UQ=
|
104
|
+
|
105
|
+
dn: uid=hh153,ou=people,dc=example,dc=org
|
106
|
+
objectClass: top
|
107
|
+
objectClass: person
|
108
|
+
objectClass: organizationalPerson
|
109
|
+
objectClass: inetOrgPerson
|
110
|
+
cn: Hilda Hatfield
|
111
|
+
sn: Hatfield
|
112
|
+
givenName: Hilda
|
113
|
+
mail: hilda@example.org
|
114
|
+
uid: hh153
|
115
|
+
# Password is "dleiftah"
|
116
|
+
userpassword: {SHA}PTDJLPy4kwa7VZ/sGLyCPzZ7d3o=
|
117
|
+
|
118
|
+
dn: uid=ii711,ou=people,dc=example,dc=org
|
119
|
+
objectClass: top
|
120
|
+
objectClass: person
|
121
|
+
objectClass: organizationalPerson
|
122
|
+
objectClass: inetOrgPerson
|
123
|
+
cn: Iona Ingram
|
124
|
+
sn: Ingram
|
125
|
+
givenName: Iona
|
126
|
+
mail: iona@example.org
|
127
|
+
uid: ii711
|
128
|
+
# Password is "margni"
|
129
|
+
userpassword: {SHA}L7qElLblWuLNFPrFku60uCuCr7Q=
|
130
|
+
|
131
|
+
dn: uid=jj243,ou=people,dc=example,dc=org
|
132
|
+
objectClass: top
|
133
|
+
objectClass: person
|
134
|
+
objectClass: organizationalPerson
|
135
|
+
objectClass: inetOrgPerson
|
136
|
+
cn: Josephine Jackson
|
137
|
+
sn: Jackson
|
138
|
+
givenName: Josephine
|
139
|
+
mail: josephine@example.org
|
140
|
+
uid: jj243
|
141
|
+
# Password is "noskcaj"
|
142
|
+
userpassword: {SHA}ElqdCxdbvRNqXBgdUdkCmGZlQmk=
|
143
|
+
|
144
|
+
dn: uid=kk891,ou=people,dc=example,dc=org
|
145
|
+
objectClass: top
|
146
|
+
objectClass: person
|
147
|
+
objectClass: organizationalPerson
|
148
|
+
objectClass: inetOrgPerson
|
149
|
+
cn: Kelly Kline
|
150
|
+
sn: Kline
|
151
|
+
givenName: Kelly
|
152
|
+
mail: kelly@example.org
|
153
|
+
uid: kk891
|
154
|
+
# Password is "enilk"
|
155
|
+
userpassword: {SHA}WlNzQqBB/QoEKh3LRcLZHgnCGNw=
|
156
|
+
|
157
|
+
dn: uid=ll819,ou=people,dc=example,dc=org
|
158
|
+
objectClass: top
|
159
|
+
objectClass: person
|
160
|
+
objectClass: organizationalPerson
|
161
|
+
objectClass: inetOrgPerson
|
162
|
+
cn: Leah Lawrence
|
163
|
+
sn: Lawrence
|
164
|
+
givenName: Leah
|
165
|
+
mail: leah@example.org
|
166
|
+
uid: ll819
|
167
|
+
# Password is "ecnerwal"
|
168
|
+
userpassword: {SHA}CzyyPOSrIxgFCm24nSv2FA8wihQ=
|
169
|
+
|
170
|
+
dn: uid=mm405,ou=people,dc=example,dc=org
|
171
|
+
objectClass: top
|
172
|
+
objectClass: person
|
173
|
+
objectClass: organizationalPerson
|
174
|
+
objectClass: inetOrgPerson
|
175
|
+
cn: Mona Maddox
|
176
|
+
sn: Maddox
|
177
|
+
givenName: Mona
|
178
|
+
mail: mona@example.org
|
179
|
+
uid: mm405
|
180
|
+
# Password is "xoddam"
|
181
|
+
userpassword: {SHA}WiCnxkOb4kpy16ON7ZC6mD/iqII=
|
182
|
+
|
183
|
+
dn: uid=nn297,ou=people,dc=example,dc=org
|
184
|
+
objectClass: top
|
185
|
+
objectClass: person
|
186
|
+
objectClass: organizationalPerson
|
187
|
+
objectClass: inetOrgPerson
|
188
|
+
cn: Noel Nash
|
189
|
+
sn: Nash
|
190
|
+
givenName: Noel
|
191
|
+
mail: noel@example.org
|
192
|
+
uid: nn297
|
193
|
+
# Password is "hsan"
|
194
|
+
userpassword: {SHA}1zOsG076wDkikQbnK5vAMM1BM/o=
|
195
|
+
|
196
|
+
dn: uid=oo981,ou=people,dc=example,dc=org
|
197
|
+
objectClass: top
|
198
|
+
objectClass: person
|
199
|
+
objectClass: organizationalPerson
|
200
|
+
objectClass: inetOrgPerson
|
201
|
+
cn: Ophelia Osborn
|
202
|
+
sn: Osborn
|
203
|
+
givenName: Ophelia
|
204
|
+
mail: ophelia@example.org
|
205
|
+
uid: oo981
|
206
|
+
# Password is "nrobso"
|
207
|
+
userpassword: {SHA}w8mQw0kEa1UiWzMsNclD/LWzlgs=
|
208
|
+
|
209
|
+
dn: uid=pp468,ou=people,dc=example,dc=org
|
210
|
+
objectClass: top
|
211
|
+
objectClass: person
|
212
|
+
objectClass: organizationalPerson
|
213
|
+
objectClass: inetOrgPerson
|
214
|
+
cn: Penelope Patel
|
215
|
+
sn: Patel
|
216
|
+
givenName: Penelope
|
217
|
+
mail: penelope@example.org
|
218
|
+
uid: pp468
|
219
|
+
# Password is "letap"
|
220
|
+
userpassword: {SHA}p7jaVoRIV9o8gDPbN10sEhXaYHk=
|
221
|
+
|
222
|
+
dn: uid=qq612,ou=people,dc=example,dc=org
|
223
|
+
objectClass: top
|
224
|
+
objectClass: person
|
225
|
+
objectClass: organizationalPerson
|
226
|
+
objectClass: inetOrgPerson
|
227
|
+
cn: Quin Queen
|
228
|
+
sn: Queen
|
229
|
+
givenName: Quin
|
230
|
+
mail: quin@example.org
|
231
|
+
uid: qq612
|
232
|
+
# Password is "neeuq"
|
233
|
+
userpassword: {SHA}v9ibNIx42giCH4tQnwUHJy6LeJg=
|
234
|
+
|
235
|
+
dn: uid=rr477,ou=people,dc=example,dc=org
|
236
|
+
objectClass: top
|
237
|
+
objectClass: person
|
238
|
+
objectClass: organizationalPerson
|
239
|
+
objectClass: inetOrgPerson
|
240
|
+
cn: Ruth Rowland
|
241
|
+
sn: Rowland
|
242
|
+
givenName: Ruth
|
243
|
+
mail: ruth@example.org
|
244
|
+
uid: rr477
|
245
|
+
# Password is "dnalwor"
|
246
|
+
userpassword: {SHA}S3eMb2C/ctXzbFnlgcH7ZQ/fozU=
|
247
|
+
|
248
|
+
dn: uid=ss198,ou=people,dc=example,dc=org
|
249
|
+
objectClass: top
|
250
|
+
objectClass: person
|
251
|
+
objectClass: organizationalPerson
|
252
|
+
objectClass: inetOrgPerson
|
253
|
+
cn: Serena Solomon
|
254
|
+
sn: Solomon
|
255
|
+
givenName: Serena
|
256
|
+
mail: serena@example.org
|
257
|
+
uid: ss198
|
258
|
+
# Password is "nomolos"
|
259
|
+
userpassword: {SHA}EizIKlU79Kz1Y2WIV4deIh0MSA8=
|
260
|
+
|
261
|
+
dn: uid=tt882,ou=people,dc=example,dc=org
|
262
|
+
objectClass: top
|
263
|
+
objectClass: person
|
264
|
+
objectClass: organizationalPerson
|
265
|
+
objectClass: inetOrgPerson
|
266
|
+
cn: Talia Torres
|
267
|
+
sn: Torres
|
268
|
+
givenName: Talia
|
269
|
+
mail: talia@example.org
|
270
|
+
uid: tt882
|
271
|
+
# Password is "serrot"
|
272
|
+
userpassword: {SHA}yO0DcSZ4fTMcx3sTHnAPQGvMkwg=
|
273
|
+
|
274
|
+
dn: uid=uu972,ou=people,dc=example,dc=org
|
275
|
+
objectClass: top
|
276
|
+
objectClass: person
|
277
|
+
objectClass: organizationalPerson
|
278
|
+
objectClass: inetOrgPerson
|
279
|
+
cn: Ursula Underwood
|
280
|
+
sn: Underwood
|
281
|
+
givenName: Ursula
|
282
|
+
mail: ursula@example.org
|
283
|
+
uid: uu972
|
284
|
+
# Password is "doowrednu"
|
285
|
+
userpassword: {SHA}GQWGu8IvIEFU1PP34qGi5DyDF/c=
|
286
|
+
|
287
|
+
dn: uid=vv180,ou=people,dc=example,dc=org
|
288
|
+
objectClass: top
|
289
|
+
objectClass: person
|
290
|
+
objectClass: organizationalPerson
|
291
|
+
objectClass: inetOrgPerson
|
292
|
+
cn: Vera Vickers
|
293
|
+
sn: Vickers
|
294
|
+
givenName: Vera
|
295
|
+
mail: vera@example.org
|
296
|
+
uid: vv180
|
297
|
+
# Password is "srekciv"
|
298
|
+
userpassword: {SHA}3UrzY38O4R1GLK6ccSSfL4D0efQ=
|
299
|
+
|
300
|
+
dn: uid=ww369,ou=people,dc=example,dc=org
|
301
|
+
objectClass: top
|
302
|
+
objectClass: person
|
303
|
+
objectClass: organizationalPerson
|
304
|
+
objectClass: inetOrgPerson
|
305
|
+
cn: Wendy Wise
|
306
|
+
sn: Wise
|
307
|
+
givenName: Wendy
|
308
|
+
mail: wendy@example.org
|
309
|
+
uid: ww369
|
310
|
+
# Password is "esiw"
|
311
|
+
userpassword: {SHA}8gU4KSqUeeLRPov2tmXZXgOZw78=
|
312
|
+
|
313
|
+
dn: uid=xx396,ou=people,dc=example,dc=org
|
314
|
+
objectClass: top
|
315
|
+
objectClass: person
|
316
|
+
objectClass: organizationalPerson
|
317
|
+
objectClass: inetOrgPerson
|
318
|
+
cn: Xara Xiong
|
319
|
+
sn: Xiong
|
320
|
+
givenName: Xara
|
321
|
+
mail: xara@example.org
|
322
|
+
uid: xx396
|
323
|
+
# Password is "gnoix"
|
324
|
+
userpassword: {SHA}Yc2En2R/sbdjlEOitkLlkwY4jAY=
|
325
|
+
|
326
|
+
dn: uid=yy423,ou=people,dc=example,dc=org
|
327
|
+
objectClass: top
|
328
|
+
objectClass: person
|
329
|
+
objectClass: organizationalPerson
|
330
|
+
objectClass: inetOrgPerson
|
331
|
+
cn: Yvette Yates
|
332
|
+
sn: Yates
|
333
|
+
givenName: Yvette
|
334
|
+
mail: yvette@example.org
|
335
|
+
uid: yy423
|
336
|
+
# Password is "setay"
|
337
|
+
userpassword: {SHA}iKBhwF+Mbbct6mlmy6AvodIek3E=
|
338
|
+
|
339
|
+
dn: uid=zz882,ou=people,dc=example,dc=org
|
340
|
+
objectClass: top
|
341
|
+
objectClass: person
|
342
|
+
objectClass: organizationalPerson
|
343
|
+
objectClass: inetOrgPerson
|
344
|
+
cn: Zana Zimmerman
|
345
|
+
sn: Zimmerman
|
346
|
+
givenName: Zana
|
347
|
+
mail: zana@example.org
|
348
|
+
uid: zz882
|
349
|
+
# Password is "namremmiz"
|
350
|
+
userpassword: {SHA}KlsWojnknRWCHXGoBOTlEZxxrG8=
|
351
|
+
|
352
|
+
#dn: cn=group1,ou=people,dc=example,dc=org
|
353
|
+
dn: cn=group1,ou=groups,dc=example,dc=org
|
354
|
+
objectClass: top
|
355
|
+
objectclass: groupOfuniqueNames
|
356
|
+
cn: Group1
|
357
|
+
description: Test Group1
|
358
|
+
owner: uid=xx396,ou=people,dc=example,dc=org
|
359
|
+
uniqueMember: uid=zz882,ou=people,dc=example,dc=org
|
360
|
+
uniqueMember: uid=yy423,ou=people,dc=example,dc=org
|
361
|
+
uniqueMember: uid=ww369,ou=people,dc=example,dc=org
|
362
|
+
|
data/hydra-ldap.gemspec
CHANGED
@@ -9,10 +9,11 @@ Gem::Specification.new do |gem|
|
|
9
9
|
gem.homepage = "https://github.com/projecthydra/hydra-ldap"
|
10
10
|
|
11
11
|
gem.add_dependency('net-ldap')
|
12
|
+
gem.add_dependency('rails')
|
12
13
|
|
13
14
|
gem.add_development_dependency('rake')
|
14
15
|
gem.add_development_dependency('rspec')
|
15
|
-
|
16
|
+
gem.add_development_dependency('ladle')
|
16
17
|
|
17
18
|
gem.files = `git ls-files`.split($\)
|
18
19
|
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
data/lib/hydra-ldap.rb
CHANGED
@@ -3,17 +3,16 @@ require "net/ldap"
|
|
3
3
|
require 'active_support/core_ext/object/blank'
|
4
4
|
require 'active_support/core_ext/hash/indifferent_access'
|
5
5
|
require 'yaml'
|
6
|
+
require 'rails'
|
6
7
|
|
7
8
|
module Hydra
|
8
9
|
module LDAP
|
9
|
-
|
10
|
-
# Your code goes here...
|
11
10
|
class NoUsersError < StandardError; end
|
12
11
|
class MissingOwnerError < StandardError; end
|
13
12
|
class GroupNotFound < StandardError; end
|
14
13
|
|
15
14
|
def self.connection
|
16
|
-
@ldap_conn ||= Net::LDAP.new(ldap_connection_config)
|
15
|
+
@ldap_conn ||= Net::LDAP.new(ldap_connection_config)
|
17
16
|
end
|
18
17
|
|
19
18
|
def self.ldap_connection_config
|
@@ -31,8 +30,8 @@ module Hydra
|
|
31
30
|
end
|
32
31
|
|
33
32
|
def self.ldap_config
|
34
|
-
root =
|
35
|
-
env =
|
33
|
+
root = Rails.root || '.'
|
34
|
+
env = Rails.env || 'test'
|
36
35
|
@ldap_config ||= YAML::load(ERB.new(IO.read(File.join(root, 'config', 'hydra-ldap.yml'))).result)[env].with_indifferent_access
|
37
36
|
end
|
38
37
|
|
@@ -48,54 +47,73 @@ module Hydra
|
|
48
47
|
dn = "cn=#{code},#{group_base}"
|
49
48
|
end
|
50
49
|
|
51
|
-
def self.create_group(code, description, owner, users)
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
50
|
+
#def self.create_group(code, description, owner, users)
|
51
|
+
# dn => dn(code)
|
52
|
+
# attributes = {
|
53
|
+
# :cn => code,
|
54
|
+
# :objectclass => "groupofnames",
|
55
|
+
# :description => description,
|
56
|
+
# :member=>users.map {|u| "uid=#{u}"},
|
57
|
+
# :owner=>"uid=#{owner}"
|
58
|
+
# }
|
59
|
+
def self.create_group(code, attributes)
|
60
|
+
raise NoUsersError, "Unable to persist a group without users" unless attributes[:uniquemember]
|
61
|
+
raise MissingOwnerError, "Unable to persist a group without owner" unless attributes[:owner]
|
61
62
|
connection.add(:dn=>dn(code), :attributes=>attributes)
|
62
63
|
end
|
63
64
|
|
64
65
|
def self.delete_group(code)
|
65
|
-
|
66
|
+
connection.delete(:dn=>dn(code))
|
66
67
|
end
|
67
68
|
|
68
69
|
# same as
|
69
70
|
# ldapsearch -h ec2-107-20-53-121.compute-1.amazonaws.com -p 389 -x -b dc=example,dc=com -D "cn=admin,dc=example,dc=com" -W "(&(objectClass=groupofnames)(member=uid=vanessa))" cn
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
def self.
|
80
|
-
result =
|
81
|
-
result
|
71
|
+
# Northwestern passes attributes=['cn']
|
72
|
+
# PSU filter=Net::LDAP::Filter.eq('uid', uid)
|
73
|
+
# NW filter=Net::LDAP::Filter.construct("(&(objectClass=groupofnames)(member=uid=#{uid}))"))
|
74
|
+
def self.groups_for_user(filter, attributes=['psMemberOf'], &block)
|
75
|
+
result = connection.search(:base=>group_base, :filter => filter, :attributes => attributes)
|
76
|
+
block.call(result) if block_given?
|
77
|
+
end
|
78
|
+
|
79
|
+
# NW - return result.map{|r| r[:cn].first}
|
80
|
+
def self.groups_owned_by_user(filter, attributes=['cn'], &block)
|
81
|
+
result = connection.search(:base=>group_base, :filter=> filter, :attributes=>attributes)
|
82
|
+
block.call(result) if block_given?
|
83
|
+
end
|
84
|
+
|
85
|
+
# result[:description].first
|
86
|
+
def self.title_of_group(group_code, filter, attributes=['description'], &block)
|
87
|
+
if block_given?
|
88
|
+
find_group(group_code, filter, attributes, &block)
|
89
|
+
else
|
90
|
+
find_group(group_code, filter, attributes)
|
91
|
+
end
|
82
92
|
end
|
83
93
|
|
84
|
-
|
85
|
-
|
86
|
-
|
94
|
+
# result[:member].map { |v| v.sub(/^uid=/, '') }
|
95
|
+
def self.users_for_group(group_code, filter, attributes=['member'], &block)
|
96
|
+
if block_given?
|
97
|
+
find_group(group_code, filter, attributes, &block)
|
98
|
+
else
|
99
|
+
find_group(group_code, filter, attributes)
|
100
|
+
end
|
87
101
|
end
|
88
102
|
|
89
|
-
|
90
|
-
|
91
|
-
|
103
|
+
# result[:owner].first.sub(/^uid=/, '')
|
104
|
+
def self.owner_for_group(group_code, filter, attributes=['owner'], &block)
|
105
|
+
if block_given?
|
106
|
+
find_group(group_code, filter, attributes, &block)
|
107
|
+
else
|
108
|
+
find_group(group_code, filter, attributes)
|
109
|
+
end
|
92
110
|
end
|
93
111
|
|
94
112
|
def self.add_users_to_group(group_code, users)
|
95
113
|
invalidate_cache(group_code)
|
96
114
|
ops = []
|
97
115
|
users.each do |u|
|
98
|
-
ops << [:add, :
|
116
|
+
ops << [:add, ldap_config[:group_member], "uid=#{u}"]
|
99
117
|
end
|
100
118
|
connection.modify(:dn=>dn(group_code), :operations=>ops)
|
101
119
|
end
|
@@ -104,7 +122,7 @@ module Hydra
|
|
104
122
|
invalidate_cache(group_code)
|
105
123
|
ops = []
|
106
124
|
users.each do |u|
|
107
|
-
ops << [:delete, :
|
125
|
+
ops << [:delete, ldap_config[:group_member], "uid=#{u}"]
|
108
126
|
end
|
109
127
|
connection.modify(:dn=>dn(group_code), :operations=>ops)
|
110
128
|
end
|
@@ -113,18 +131,41 @@ module Hydra
|
|
113
131
|
@cache ||= {}
|
114
132
|
@cache[group_code] = nil
|
115
133
|
end
|
116
|
-
|
117
|
-
|
134
|
+
|
135
|
+
# NW result = connection.search(:base=>group_base, :filter=> Net::LDAP::Filter.construct("(&(objectClass=groupofnames)(cn=#{group_code}))"), :attributes=>['member', 'owner', 'description'])
|
136
|
+
# result.first.each do |k, v|
|
137
|
+
# val[k] = v
|
138
|
+
# end
|
139
|
+
def self.find_group(group_code, filter, attributes, &block)
|
118
140
|
@cache ||= {}
|
119
|
-
return @cache[group_code] if @cache[group_code]
|
120
|
-
result =
|
121
|
-
val = {}
|
141
|
+
return @cache[[group_code, filter, attributes]] if @cache[[group_code, filter, attributes]]
|
142
|
+
result = connection.search(:base=>group_base, :filter=> filter, :attributes=>attributes)
|
122
143
|
raise GroupNotFound, "Can't find group '#{group_code}' in ldap" unless result.first
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
144
|
+
@cache[[group_code, filter, attributes]] = result
|
145
|
+
block.call(result) if block_given?
|
146
|
+
end
|
147
|
+
|
148
|
+
def self.get_user(filter, attribute=[])
|
149
|
+
result = connection.search(:base=>treebase, :filter => filter, :attributes => attribute)
|
150
|
+
return result
|
151
|
+
end
|
152
|
+
|
153
|
+
# hits = connection.search(:base=>group_base, :filter=>Net::LDAP::Filter.eq('uid', uid))
|
154
|
+
def self.does_user_exist?(filter)
|
155
|
+
hits = connection.search(:base=>treebase, :filter=>filter)
|
156
|
+
return !hits.empty?
|
157
|
+
end
|
158
|
+
|
159
|
+
# hits = connection.search(:base=>group_base, :filter=>Net::LDAP::Filter.eq('uid', uid))
|
160
|
+
def self.is_user_unique?(filter)
|
161
|
+
hits = connection.search(:base=>treebase, :filter=>filter)
|
162
|
+
return hits.count == 1
|
163
|
+
end
|
164
|
+
|
165
|
+
# hits = connection.search(:base=>group_base, :filter=>Net::LDAP::Filter.eq('cn', cn))
|
166
|
+
def self.does_group_exist?(filter)
|
167
|
+
hits = connection.search(:base=>group_base, :filter=>filter)
|
168
|
+
return hits.count == 1
|
128
169
|
end
|
129
170
|
|
130
171
|
end
|
data/lib/hydra/ldap/version.rb
CHANGED
@@ -1,42 +1,101 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe 'Ldap service' do
|
4
|
-
before do
|
5
|
-
|
6
|
-
|
3
|
+
describe 'Ldap service' do
|
4
|
+
before(:all) do
|
5
|
+
tmpdir = ENV['TMPDIR'] || ENV['TEMPDIR'] || '/tmp'
|
6
|
+
@ldap_server = Ladle::Server.new(:port => 3897,
|
7
|
+
:domain => "dc=example,dc=org",
|
8
|
+
:allow_anonymous => true,
|
9
|
+
:verbose => false,
|
10
|
+
:ldif => 'hydra-ldap-example.ldif',
|
11
|
+
:tmpdir => tmpdir
|
12
|
+
).start
|
7
13
|
end
|
8
|
-
|
9
|
-
|
14
|
+
|
15
|
+
after(:all) do
|
16
|
+
@ldap_server.stop if @ldap_server
|
10
17
|
end
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
18
|
+
|
19
|
+
describe "Querying for users and attribute values" do
|
20
|
+
it "should return true dd945 exists" do
|
21
|
+
filter = Net::LDAP::Filter.eq('uid', 'dd945')
|
22
|
+
Hydra::LDAP.does_user_exist?(filter).should be_true
|
23
|
+
end
|
24
|
+
|
25
|
+
it "should return false abc123 does not exist" do
|
26
|
+
filter = Net::LDAP::Filter.eq('uid', 'abc123')
|
27
|
+
Hydra::LDAP.does_user_exist?(filter).should_not be_true
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should return true dd945 is unique user" do
|
31
|
+
filter = Net::LDAP::Filter.eq('uid', 'dd945')
|
32
|
+
Hydra::LDAP.is_user_unique?(filter).should be_true
|
33
|
+
end
|
34
|
+
|
35
|
+
it "should return user values for dd945" do
|
36
|
+
filter = Net::LDAP::Filter.eq('uid', 'dd945')
|
37
|
+
Hydra::LDAP.get_user(filter, ['givenName']).first[:givenname] == 'Dorothy'
|
38
|
+
end
|
15
39
|
end
|
16
40
|
|
17
|
-
describe "
|
41
|
+
describe "Query groups for group info" do
|
42
|
+
it "should find a group and map the result" do
|
43
|
+
group_code = 'Group1'
|
44
|
+
filter = Net::LDAP::Filter.construct("(cn=#{group_code})")
|
45
|
+
Hydra::LDAP.find_group(group_code, filter, ['cn']){ |result| result.first[:cn].first }.downcase.should == 'group1'
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should have description, users, owners of a group" do
|
49
|
+
group_code = 'Group1'
|
50
|
+
filter = Net::LDAP::Filter.construct("(cn=#{group_code})")
|
51
|
+
|
52
|
+
Hydra::LDAP.title_of_group(group_code, filter){ |result| result.first[:description].first }.should == 'Test Group1'
|
53
|
+
Hydra::LDAP.users_for_group(group_code, filter, ['uniquemember']){ |result| result.first[:uniquemember].map{ |r| r.sub(/^uid=/, '').sub(/,ou=people,dc=example,dc=org/, '') }}.should == ['zz882', 'yy423', 'ww369']
|
54
|
+
Hydra::LDAP.owner_for_group(group_code, filter, ['owner']) { |result| result.first[:owner].map{ |r| r.sub(/^uid=/, '').sub(/,ou=people,dc=example,dc=org/, '') }}.should == ['xx396']
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "Managing Groups" do
|
18
59
|
before do
|
19
|
-
|
20
|
-
|
60
|
+
attrs = {
|
61
|
+
:cn => 'PulpFiction',
|
62
|
+
:objectclass => 'groupofuniquenames',
|
63
|
+
:description => 'Pulp Fiction is a movie by quentin',
|
64
|
+
:owner => 'uid=quentin,ou=people,dc=example,dc=org',
|
65
|
+
:uniquemember => ['uid=samuel', 'uid=uma', 'uid=john']
|
66
|
+
}
|
67
|
+
Hydra::LDAP.create_group('PulpFiction', attrs).should be_true
|
21
68
|
end
|
69
|
+
|
22
70
|
after do
|
23
|
-
Hydra::LDAP.delete_group('
|
24
|
-
Hydra::LDAP.delete_group('justin3').should be_true
|
71
|
+
Hydra::LDAP.delete_group('PulpFiction').should be_true
|
25
72
|
end
|
26
|
-
|
27
|
-
|
73
|
+
|
74
|
+
it "should return a list of groups owned by quentin" do
|
75
|
+
attrs = {
|
76
|
+
:cn => 'TR',
|
77
|
+
:objectclass => 'groupofuniquenames',
|
78
|
+
:description => 'True Romance is another movie by Q',
|
79
|
+
:owner => 'uid=quentin,ou=people,dc=example,dc=org',
|
80
|
+
:uniquemember => ['uid=christian', 'uid=patricia', 'uid=dennis']
|
81
|
+
}
|
82
|
+
Hydra::LDAP.create_group('TrueRomance', attrs).should be_true
|
83
|
+
filter = Net::LDAP::Filter.construct("(owner=uid=quentin,ou=people,dc=example,dc=org)")
|
84
|
+
|
85
|
+
Hydra::LDAP.groups_owned_by_user(filter, ['owner', 'cn']){ |result| result.map{ |r| r[:cn].first } }.should == ['PulpFiction', 'TrueRomance']
|
86
|
+
|
87
|
+
Hydra::LDAP.delete_group('TrueRomance').should be_true
|
28
88
|
end
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
Hydra::LDAP.add_users_to_group('justin1', ['theresa', 'penelope']).should be_true
|
33
|
-
Hydra::LDAP.users_for_group('justin1').should == ['kacey', 'larry', 'ursula', 'theresa', 'penelope']
|
89
|
+
|
90
|
+
it "should add users to a group" do
|
91
|
+
Hydra::LDAP.add_users_to_group('PulpFiction', ['bruce', 'ving']).should be_true
|
34
92
|
end
|
35
|
-
|
36
|
-
describe "#removing_members" do
|
93
|
+
|
37
94
|
it "should remove users from the group" do
|
38
|
-
Hydra::LDAP.remove_users_from_group('
|
39
|
-
|
95
|
+
Hydra::LDAP.remove_users_from_group('PulpFiction', ['uma', 'john']).should be_true
|
96
|
+
group_code = 'PulpFiction'
|
97
|
+
filter = Net::LDAP::Filter.construct("(cn=#{group_code})")
|
98
|
+
Hydra::LDAP.users_for_group(group_code, filter, ['uniquemember']){ |result| result.first[:uniquemember].map{ |r| r.sub(/^uid=/, '').sub(/,ou=people,dc=example,dc=org/, '') }}.should == ['samuel']
|
40
99
|
end
|
41
100
|
end
|
42
101
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hydra-ldap
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-08-01 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: net-ldap
|
@@ -27,6 +27,22 @@ dependencies:
|
|
27
27
|
- - ! '>='
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: '0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: rails
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :runtime
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
30
46
|
- !ruby/object:Gem::Dependency
|
31
47
|
name: rake
|
32
48
|
requirement: !ruby/object:Gem::Requirement
|
@@ -59,6 +75,22 @@ dependencies:
|
|
59
75
|
- - ! '>='
|
60
76
|
- !ruby/object:Gem::Version
|
61
77
|
version: '0'
|
78
|
+
- !ruby/object:Gem::Dependency
|
79
|
+
name: ladle
|
80
|
+
requirement: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
type: :development
|
87
|
+
prerelease: false
|
88
|
+
version_requirements: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ! '>='
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
version: '0'
|
62
94
|
description: A gem for managing groups with ldap
|
63
95
|
email:
|
64
96
|
- justin.coyne@yourmediashelf.com
|
@@ -72,6 +104,7 @@ files:
|
|
72
104
|
- README.md
|
73
105
|
- Rakefile
|
74
106
|
- config/hydra-ldap.yml
|
107
|
+
- hydra-ldap-example.ldif
|
75
108
|
- hydra-ldap.gemspec
|
76
109
|
- lib/generators/hydra-ldap/config_generator.rb
|
77
110
|
- lib/generators/hydra-ldap/templates/hydra-ldap.yml
|
@@ -100,7 +133,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
100
133
|
version: '0'
|
101
134
|
requirements: []
|
102
135
|
rubyforge_project:
|
103
|
-
rubygems_version: 1.8.
|
136
|
+
rubygems_version: 1.8.23
|
104
137
|
signing_key:
|
105
138
|
specification_version: 3
|
106
139
|
summary: Create, Read and Update LDAP groups
|