hydra-ldap 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|