summaryrefslogtreecommitdiff
path: root/rt/lib/t/regression/18stale_delegations_cleanup.t
blob: 84e666eee5fc2c5d89832541be6b2908100be938 (plain)
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
#!/usr/bin/perl -w

# Regression test suite for http://rt3.fsck.com/Ticket/Display.html?id=6184
# and related corner cases related to cleanup of delegated ACEs when
# the delegator loses the right to delegate.  This causes complexities
# due to the fact that multiple ACEs can grant different delegation
# rights to a principal, and because DelegateRights and SuperUser can
# themselves be delegated.

# The case where the "parent" delegated ACE is removed is handled in
# the embedded regression tests in lib/RT/ACE_Overlay.pm .

use Test::More qw(no_plan);

use RT;

ok( RT::LoadConfig, "Locating config files" );
ok( RT::Init,       "Basic initialization and DB connectivity" );

my ($u1, $u2, $g1, $g2, $g3, $pg1, $pg2, $ace, @groups, @users, @principals);
@groups = (\$g1, \$g2, \$g3, \$pg1, \$pg2);
@users = (\$u1, \$u2);
@principals = (@groups, @users);

my($ret, $msg);

$u1 = RT::User->new($RT::SystemUser);
( $ret, $msg ) = $u1->LoadOrCreateByEmail('delegtest1@example.com');
ok( $ret, "Load / Create test user 1: $msg" );
$u1->SetPrivileged(1);
$u2 = RT::User->new($RT::SystemUser);
( $ret, $msg ) = $u2->LoadOrCreateByEmail('delegtest2@example.com');
ok( $ret, "Load / Create test user 2: $msg" );
$u2->SetPrivileged(1);
$g1 = RT::Group->new($RT::SystemUser);
( $ret, $msg) = $g1->LoadUserDefinedGroup('dg1');
unless ($ret) {
    ( $ret, $msg ) = $g1->CreateUserDefinedGroup( Name => 'dg1' );
}
ok( $ret, "Load / Create test group 1: $msg" );
$g2 = RT::Group->new($RT::SystemUser);
( $ret, $msg) = $g2->LoadUserDefinedGroup('dg2');
unless ($ret) {
    ( $ret, $msg ) = $g2->CreateUserDefinedGroup( Name => 'dg2' );
}
ok( $ret, "Load / Create test group 2: $msg" );
$g3 = RT::Group->new($RT::SystemUser);
( $ret, $msg) = $g3->LoadUserDefinedGroup('dg3');
unless ($ret) {
    ( $ret, $msg ) = $g3->CreateUserDefinedGroup( Name => 'dg3' );
}
ok( $ret, "Load / Create test group 3: $msg" );
$pg1 = RT::Group->new($RT::SystemUser);
( $ret, $msg ) = $pg1->LoadPersonalGroup( Name => 'dpg1',
					  User => $u1->PrincipalId );
unless ($ret) {
    ( $ret, $msg ) = $pg1->CreatePersonalGroup( Name => 'dpg1',
						PrincipalId => $u1->PrincipalId );
}
ok( $ret, "Load / Create test personal group 1: $msg" );
$pg2 = RT::Group->new($RT::SystemUser);
( $ret, $msg ) = $pg2->LoadPersonalGroup( Name => 'dpg2',
					  User => $u2->PrincipalId );
unless ($ret) {
    ( $ret, $msg ) = $pg2->CreatePersonalGroup( Name => 'dpg2',
						PrincipalId => $u2->PrincipalId );
}
ok( $ret, "Load / Create test personal group 2: $msg" );



# Basic case: u has global DelegateRights through g1 and ShowConfigTab
# through g2; then u is removed from g1.

clear_acls_and_groups();

( $ret, $msg ) = $g1->PrincipalObj->GrantRight( Right => 'DelegateRights' );
ok( $ret, "Grant DelegateRights to g1: $msg" );
( $ret, $msg ) = $g2->PrincipalObj->GrantRight( Right => 'ShowConfigTab' );
ok( $ret, "Grant ShowConfigTab to g2: $msg" );
( $ret, $msg ) = $g1->AddMember( $u1->PrincipalId );
ok( $ret, "Add test user 1 to g1: $msg" );
ok(
    $u1->PrincipalObj->HasRight(
        Right  => 'DelegateRights',
        Object => $RT::System
    ),
    "test user 1 has DelegateRights after joining g1"
);
( $ret, $msg ) = $g2->AddMember( $u1->PrincipalId );
ok( $ret, "Add test user 1 to g2: $msg" );
ok(
    $u1->PrincipalObj->HasRight(
        Right  => 'ShowConfigTab',
        Object => $RT::System
    ),
    "test user 1 has ShowConfigTab after joining g2"
);

$ace = RT::ACE->new($u1);
( $ret, $msg ) = $ace->LoadByValues(
    RightName     => 'ShowConfigTab',
    Object        => $RT::System,
    PrincipalType => 'Group',
    PrincipalId   => $g2->PrincipalId
);
ok( $ret, "Look up ACE to be delegated: $msg" );
( $ret, $msg ) = $ace->Delegate( PrincipalId => $pg1->PrincipalId );
ok( $ret, "Delegate ShowConfigTab to pg1: $msg" );
ok(
    $pg1->PrincipalObj->HasRight(
        Right  => 'ShowConfigTab',
        Object => $RT::System
    ),
    "Test personal group 1 has ShowConfigTab right after delegation"
);

( $ret, $msg ) = $g1->DeleteMember( $u1->PrincipalId );
ok( $ret, "Delete test user 1 from g1: $msg" );
ok(
    not(
        $pg1->PrincipalObj->HasRight(
            Right  => 'ShowConfigTab',
            Object => $RT::System
        )
    ),
    "Test personal group 1 lacks ShowConfigTab right after user removed from g1"
);

# Basic case: u has global DelegateRights through g1 and ShowConfigTab
# through g2; then DelegateRights revoked from g1.

( $ret, $msg ) = $g1->AddMember( $u1->PrincipalId );
ok( $ret, "Add test user 1 to g1: $msg" );
( $ret, $msg ) = $ace->Delegate( PrincipalId => $pg1->PrincipalId );
ok( $ret, "Delegate ShowConfigTab to pg1: $msg" );
( $ret, $msg ) = $g1->PrincipalObj->RevokeRight( Right => 'DelegateRights' );
ok( $ret, "Revoke DelegateRights from g1: $msg" );
ok(
    not(
        $pg1->PrincipalObj->HasRight(
            Right  => 'ShowConfigTab',
            Object => $RT::System
        )
    ),
    "Test personal group 1 lacks ShowConfigTab right after DelegateRights revoked from g1"
);



# Corner case - restricted delegation: u has DelegateRights on pg1
# through g1 and AdminGroup on pg1 through g2; then DelegateRights
# revoked from g1.

clear_acls_and_groups();

( $ret, $msg ) = $g1->PrincipalObj->GrantRight( Right => 'DelegateRights',
					        Object => $pg1);
ok( $ret, "Grant DelegateRights on pg1 to g1: $msg" );
( $ret, $msg ) = $g2->PrincipalObj->GrantRight( Right => 'AdminGroup',
					        Object => $pg1);
ok( $ret, "Grant AdminGroup on pg1 to g2: $msg" );
( $ret, $msg ) = $g1->AddMember( $u1->PrincipalId );
ok( $ret, "Add test user 1 to g1: $msg" );
( $ret, $msg ) = $g2->AddMember( $u1->PrincipalId );
ok( $ret, "Add test user 1 to g2: $msg" );
ok( $u1->PrincipalObj->HasRight(
        Right  => 'DelegateRights',
        Object => $pg1 ),
    "test user 1 has DelegateRights on pg1 after joining g1" );
ok( not( $u1->PrincipalObj->HasRight(
            Right  => 'DelegateRights',
            Object => $RT::System )),
    "Test personal group 1 lacks global DelegateRights after joining g1" );
$ace = RT::ACE->new($u1);
( $ret, $msg ) = $ace->LoadByValues(
    RightName     => 'AdminGroup',
    Object        => $pg1,
    PrincipalType => 'Group',
    PrincipalId   => $g2->PrincipalId
);
ok( $ret, "Look up ACE to be delegated: $msg" );
( $ret, $msg ) = $ace->Delegate( PrincipalId => $pg1->PrincipalId );
ok( $ret, "Delegate AdminGroup on pg1 to pg1: $msg" );
ok( $pg1->PrincipalObj->HasRight(
        Right  => 'AdminGroup',
        Object => $pg1 ),
    "Test personal group 1 has AdminGroup right on pg1 after delegation" );
( $ret, $msg ) = $g1->PrincipalObj->RevokeRight ( Right => 'DelegateRights',
						  Object => $pg1 );
ok( $ret, "Revoke DelegateRights on pg1 from g1: $msg" );
ok( not( $pg1->PrincipalObj->HasRight(
            Right  => 'AdminGroup',
            Object => $pg1 )),
    "Test personal group 1 lacks AdminGroup right on pg1 after DelegateRights revoked from g1" );
( $ret, $msg ) = $g1->PrincipalObj->GrantRight( Right => 'DelegateRights',
					        Object => $pg1);

# Corner case - restricted delegation: u has DelegateRights on pg1
# through g1 and AdminGroup on pg1 through g2; then u removed from g1.

ok( $ret, "Grant DelegateRights on pg1 to g1: $msg" );
( $ret, $msg ) = $ace->Delegate( PrincipalId => $pg1->PrincipalId );
ok( $ret, "Delegate AdminGroup on pg1 to pg1: $msg" );
ok( $pg1->PrincipalObj->HasRight(
        Right  => 'AdminGroup',
        Object => $pg1 ),
    "Test personal group 1 has AdminGroup right on pg1 after delegation" );
( $ret, $msg ) = $g1->DeleteMember( $u1->PrincipalId );
ok( $ret, "Delete test user 1 from g1: $msg" );
ok( not( $pg1->PrincipalObj->HasRight(
            Right  => 'AdminGroup',
            Object => $pg1 )),
    "Test personal group 1 lacks AdminGroup right on pg1 after user removed from g1" );

clear_acls_and_groups();



# Corner case - multiple delegation rights: u has global
# DelegateRights directly and DelegateRights on pg1 through g1, and
# AdminGroup on pg1 through g2; then u removed from g1 (delegation
# should remain); then DelegateRights revoked from u (delegation
# should not remain).

( $ret, $msg ) = $g1->PrincipalObj->GrantRight( Right => 'DelegateRights',
					        Object => $pg1);
ok( $ret, "Grant DelegateRights on pg1 to g1: $msg" );
( $ret, $msg ) = $g2->PrincipalObj->GrantRight( Right => 'AdminGroup',
					        Object => $pg1);
ok( $ret, "Grant AdminGroup on pg1 to g2: $msg" );
( $ret, $msg ) = $u1->PrincipalObj->GrantRight( Right => 'DelegateRights',
					       Object => $RT::System);
ok( $ret, "Grant DelegateRights to user: $msg" );
( $ret, $msg ) = $g1->AddMember( $u1->PrincipalId );
ok( $ret, "Add test user 1 to g1: $msg" );
( $ret, $msg ) = $g2->AddMember( $u1->PrincipalId );
ok( $ret, "Add test user 1 to g2: $msg" );
$ace = RT::ACE->new($u1);
( $ret, $msg ) = $ace->LoadByValues(
    RightName     => 'AdminGroup',
    Object        => $pg1,
    PrincipalType => 'Group',
    PrincipalId   => $g2->PrincipalId
);
ok( $ret, "Look up ACE to be delegated: $msg" );
( $ret, $msg ) = $ace->Delegate( PrincipalId => $pg1->PrincipalId );
ok( $ret, "Delegate AdminGroup on pg1 to pg1: $msg" );
( $ret, $msg ) = $g1->DeleteMember( $u1->PrincipalId );
ok( $ret, "Delete test user 1 from g1: $msg" );
ok( $pg1->PrincipalObj->HasRight(Right  => 'AdminGroup',
				Object => $pg1),
    "Test personal group 1 retains AdminGroup right on pg1 after user removed from g1" );
( $ret, $msg ) = $u1->PrincipalObj->RevokeRight( Right => 'DelegateRights',
						Object => $RT::System );
ok( not ($pg1->PrincipalObj->HasRight(Right  => 'AdminGroup',
				     Object => $pg1)),
    "Test personal group 1 lacks AdminGroup right on pg1 after DelegateRights revoked");

# Corner case - multiple delegation rights and selectivity: u has
# DelegateRights globally and on g2 directly and DelegateRights on pg1
# through g1, and AdminGroup on pg1 through g2; then global
# DelegateRights revoked from u (delegation should remain),
# DelegateRights on g2 revoked from u (delegation should remain), and
# u removed from g1 (delegation should not remain).

( $ret, $msg ) = $g1->AddMember( $u1->PrincipalId );
ok( $ret, "Add test user 1 to g1: $msg" );
( $ret, $msg ) = $u1->PrincipalObj->GrantRight( Right => 'DelegateRights',
					       Object => $RT::System);
ok( $ret, "Grant DelegateRights to user: $msg" );
( $ret, $msg ) = $u1->PrincipalObj->GrantRight( Right => 'DelegateRights',
					       Object => $g2);
ok( $ret, "Grant DelegateRights on g2 to user: $msg" );
( $ret, $msg ) = $ace->Delegate( PrincipalId => $pg1->PrincipalId );
ok( $ret, "Delegate AdminGroup on pg1 to pg1: $msg" );
( $ret, $msg ) = $u1->PrincipalObj->RevokeRight( Right => 'DelegateRights',
						Object => $RT::System );
ok( $pg1->PrincipalObj->HasRight(Right  => 'AdminGroup',
				Object => $pg1),
    "Test personal group 1 retains AdminGroup right on pg1 after global DelegateRights revoked" );
( $ret, $msg ) = $u1->PrincipalObj->RevokeRight( Right => 'DelegateRights',
						Object => $g2 );
ok( $pg1->PrincipalObj->HasRight(Right  => 'AdminGroup',
				Object => $pg1),
    "Test personal group 1 retains AdminGroup right on pg1 after DelegateRights on g2 revoked" );
( $ret, $msg ) = $g1->DeleteMember( $u1->PrincipalId );
ok( $ret, "Delete test user 1 from g1: $msg" );
ok( not ($pg1->PrincipalObj->HasRight(Right  => 'AdminGroup',
				     Object => $pg1)),
    "Test personal group 1 lacks AdminGroup right on pg1 after user removed from g1");



# Corner case - indirect delegation rights: u has DelegateRights
# through g1 via g3, and ShowConfigTab via g2; then g3 removed from
# g1.

clear_acls_and_groups();

( $ret, $msg ) = $g1->PrincipalObj->GrantRight( Right => 'DelegateRights' );
ok( $ret, "Grant DelegateRights to g1: $msg" );
( $ret, $msg ) = $g2->PrincipalObj->GrantRight( Right => 'ShowConfigTab' );
ok( $ret, "Grant ShowConfigTab to g2: $msg" );
( $ret, $msg ) = $g1->AddMember( $g3->PrincipalId );
ok( $ret, "Add g3 to g1: $msg" );
( $ret, $msg ) = $g3->AddMember( $u1->PrincipalId );
ok( $ret, "Add test user 1 to g3: $msg" );
( $ret, $msg ) = $g2->AddMember( $u1->PrincipalId );
ok( $ret, "Add test user 1 to g2: $msg" );

$ace = RT::ACE->new($u1);
( $ret, $msg ) = $ace->LoadByValues(
    RightName     => 'ShowConfigTab',
    Object        => $RT::System,
    PrincipalType => 'Group',
    PrincipalId   => $g2->PrincipalId
);
ok( $ret, "Look up ACE to be delegated: $msg" );
( $ret, $msg ) = $ace->Delegate( PrincipalId => $pg1->PrincipalId );
ok( $ret, "Delegate ShowConfigTab to pg1: $msg" );

( $ret, $msg ) = $g1->DeleteMember( $g3->PrincipalId );
ok( $ret, "Delete g3 from g1: $msg" );
ok( not ($pg1->PrincipalObj->HasRight(Right  => 'ShowConfigTab',
				     Object => $RT::System)),
	 "Test personal group 1 lacks ShowConfigTab right after g3 removed from g1");

# Corner case - indirect delegation rights: u has DelegateRights
# through g1 via g3, and ShowConfigTab via g2; then DelegateRights
# revoked from g1.

( $ret, $msg ) = $g1->AddMember( $g3->PrincipalId );
ok( $ret, "Add g3 to g1: $msg" );
( $ret, $msg ) = $ace->Delegate( PrincipalId => $pg1->PrincipalId );
ok( $ret, "Delegate ShowConfigTab to pg1: $msg" );
( $ret, $msg ) = $g1->PrincipalObj->RevokeRight ( Right => 'DelegateRights' );
ok( $ret, "Revoke DelegateRights from g1: $msg" );

ok( not ($pg1->PrincipalObj->HasRight(Right  => 'ShowConfigTab',
				     Object => $RT::System)),
	 "Test personal group 1 lacks ShowConfigTab right after DelegateRights revoked from g1");



# Corner case - delegation of DelegateRights: u1 has DelegateRights
# via g1 and delegates DelegateRights to pg1; u2 has DelegateRights
# via pg1 and ShowConfigTab via g2; then u1 removed from g1.

clear_acls_and_groups();

( $ret, $msg ) = $g1->PrincipalObj->GrantRight( Right => 'DelegateRights' );
ok( $ret, "Grant DelegateRights to g1: $msg" );
( $ret, $msg ) = $g2->PrincipalObj->GrantRight( Right => 'ShowConfigTab' );
ok( $ret, "Grant ShowConfigTab to g2: $msg" );
( $ret, $msg ) = $g1->AddMember( $u1->PrincipalId );
ok( $ret, "Add test user 1 to g1: $msg" );
$ace = RT::ACE->new($u1);
( $ret, $msg ) = $ace->LoadByValues(
    RightName     => 'DelegateRights',
    Object        => $RT::System,
    PrincipalType => 'Group',
    PrincipalId   => $g1->PrincipalId
);
ok( $ret, "Look up ACE to be delegated: $msg" );
( $ret, $msg ) = $ace->Delegate( PrincipalId => $pg1->PrincipalId );
ok( $ret, "Delegate DelegateRights to pg1: $msg" );

( $ret, $msg ) = $pg1->AddMember( $u2->PrincipalId );
ok( $ret, "Add test user 2 to pg1: $msg" );
( $ret, $msg ) = $g2->AddMember( $u2->PrincipalId );
ok( $ret, "Add test user 2 to g2: $msg" );
$ace = RT::ACE->new($u2);
( $ret, $msg ) = $ace->LoadByValues(
    RightName     => 'ShowConfigTab',
    Object        => $RT::System,
    PrincipalType => 'Group',
    PrincipalId   => $g2->PrincipalId
);
ok( $ret, "Look up ACE to be delegated: $msg" );
( $ret, $msg ) = $ace->Delegate( PrincipalId => $pg2->PrincipalId );
ok( $ret, "Delegate ShowConfigTab to pg2: $msg" );

ok( $pg2->PrincipalObj->HasRight(Right  => 'ShowConfigTab',
				 Object => $RT::System),
    "Test personal group 2 has ShowConfigTab right after delegation");
( $ret, $msg ) = $g1->DeleteMember( $u1->PrincipalId );
ok( $ret, "Delete u1 from g1: $msg" );
ok( not ($pg2->PrincipalObj->HasRight(Right  => 'ShowConfigTab',
				      Object => $RT::System)),
	 "Test personal group 2 lacks ShowConfigTab right after u1 removed from g1");

# Corner case - delegation of DelegateRights: u1 has DelegateRights
# via g1 and delegates DelegateRights to pg1; u2 has DelegateRights
# via pg1 and ShowConfigTab via g2; then DelegateRights revoked from
# g1.

( $ret, $msg ) = $g1->AddMember( $u1->PrincipalId );
ok( $ret, "Add u1 to g1: $msg" );
$ace = RT::ACE->new($u1);
( $ret, $msg ) = $ace->LoadByValues(
    RightName     => 'DelegateRights',
    Object        => $RT::System,
    PrincipalType => 'Group',
    PrincipalId   => $g1->PrincipalId
);
ok( $ret, "Look up ACE to be delegated: $msg" );
( $ret, $msg ) = $ace->Delegate( PrincipalId => $pg1->PrincipalId );
ok( $ret, "Delegate DelegateRights to pg1: $msg" );
$ace = RT::ACE->new($u2);
( $ret, $msg ) = $ace->LoadByValues(
    RightName     => 'ShowConfigTab',
    Object        => $RT::System,
    PrincipalType => 'Group',
    PrincipalId   => $g2->PrincipalId
);
ok( $ret, "Look up ACE to be delegated: $msg" );
( $ret, $msg ) = $ace->Delegate( PrincipalId => $pg2->PrincipalId );
ok( $ret, "Delegate ShowConfigTab to pg2: $msg" );

( $ret, $msg ) = $g1->PrincipalObj->RevokeRight ( Right => 'DelegateRights' );
ok( $ret, "Revoke DelegateRights from g1: $msg" );
ok( not ($pg2->PrincipalObj->HasRight(Right  => 'ShowConfigTab',
				      Object => $RT::System)),
	 "Test personal group 2 lacks ShowConfigTab right after DelegateRights revoked from g1");




#######

sub clear_acls_and_groups {
    # Revoke all rights granted to our cast
    my $acl = RT::ACL->new($RT::SystemUser);
    foreach (@principals) {
	$acl->LimitToPrincipal(Type => $$_->PrincipalObj->PrincipalType,
			       Id => $$_->PrincipalObj->Id);
    }
    while (my $ace = $acl->Next()) {
	$ace->Delete();
    }

    # Remove all group memberships
    my $members = RT::GroupMembers->new($RT::SystemUser);
    foreach (@groups) {
	$members->LimitToMembersOfGroup( $$_->PrincipalId );
    }
    while (my $member = $members->Next()) {
	$member->Delete();
    }

    $acl->RedoSearch();
    ok( $acl->Count() == 0,
       "All principals have no rights after clearing ACLs" );
    $members->RedoSearch();
    ok( $members->Count() == 0,
       "All groups have no members after clearing groups" );
}