]> git.proxmox.com Git - pve-access-control.git/blame - src/test/parser_writer.pl
fix #4518: improve ACL computation performance
[pve-access-control.git] / src / test / parser_writer.pl
CommitLineData
7d1739ad
FG
1#!/usr/bin/perl -w
2
3use strict;
4
5use Test::More;
6use PVE::AccessControl;
7
8use Storable qw(dclone);
9
10PVE::AccessControl::create_roles();
11my $default_user_cfg = {};
12PVE::AccessControl::userconfig_force_defaults($default_user_cfg);
13
14my $add_default_user_properties = sub {
15 my ($user) = @_;
16
17 $user->{enable} = 1 if !defined($user->{enable});
18 $user->{expire} = 0 if !defined($user->{expire});
19 $user->{email} = undef if !defined($user->{email});
20
21 return $user;
22};
23
24sub default_roles {
25 my $roles = dclone($default_user_cfg->{roles});
26 return $roles;
27}
28
29sub default_roles_with {
30 my ($extra_roles) = @_;
31
32 my $roles = default_roles();
33
34 foreach my $r (@$extra_roles) {
35 my $role = dclone($r);
36 my $roleid = delete $role->{id};
37 $roles->{$roleid} = $role;
38 }
39
40 return $roles;
41}
42
43sub default_users {
44 my $users = dclone($default_user_cfg->{users});
45 return { map { $_ => $add_default_user_properties->($users->{$_}); } keys %$users};
46}
47
48sub default_users_with {
49 my ($extra_users) = @_;
50
51 my $users = default_users();
52
53 foreach my $u (@$extra_users) {
54 my $user = dclone($u);
55 my $userid = delete $user->{id};
56 $users->{$userid} = $add_default_user_properties->($user);
57 }
58
59 return $users;
60}
61
62sub default_groups {
63 return {};
64}
65
66sub default_groups_with {
67 my ($extra_groups) = @_;
68
69 my $groups = default_groups();
70
71 foreach my $g (@$extra_groups) {
72 my $group = dclone($g);
73 my $groupid = delete $group->{id};
74 $groups->{$groupid} = $group;
75 }
76
77 return $groups;
78}
79
80sub default_pools {
81 return {};
82}
83
84sub default_pools_with {
85 my ($extra_pools) = @_;
86
87 my $pools = default_pools();
88
89 foreach my $p (@$extra_pools) {
90 my $pool = dclone($p);
91 my $poolid = delete $pool->{id};
92 $pools->{$poolid} = $pool;
93 }
94
95 return $pools;
96}
97
98sub default_pool_vms_with {
99 my ($extra_pools) = @_;
100
101 my $vms = {};
102 foreach my $pool (@$extra_pools) {
103 foreach my $vmid (keys %{$pool->{vms}}) {
104 $vms->{$vmid} = $pool->{id};
105 }
106 }
107 return $vms;
108}
109
110sub default_acls {
111 return {};
112}
113
114# note: does not support merging paths!
115sub default_acls_with {
116 my ($extra_acls) = @_;
117
118 my $acls = default_acls();
119
120 foreach my $a (@$extra_acls) {
121 my $acl = dclone($a);
122 my $path = delete $acl->{path};
170cf17b
FG
123 my $split_path = [ split("/", $path) ];
124 my $node = $acls;
125 for my $p (@$split_path) {
126 next if !$p;
127 $node->{children} = {} if !$node->{children};
128 $node->{children}->{$p} = {} if !$node->{children}->{$p};
129 $node = $node->{children}->{$p};
130 }
131 %$node = ( %$acl );
7d1739ad
FG
132 }
133
134 return $acls;
135}
136
137my $default_cfg = {
138 test_pam => {
139 'id' => 'test@pam',
140 'enable' => 1,
141 'expire' => 0,
142 'email' => undef,
143 },
144 test2_pam => {
145 'id' => 'test2@pam',
146 'enable' => 1,
147 'expire' => 0,
148 'email' => undef,
149 },
150 test_pam_with_group => {
151 'id' => 'test@pam',
152 'enable' => 1,
153 'expire' => 0,
154 'email' => undef,
155 'groups' => { 'testgroup' => 1 },
156 },
157 test2_pam_with_group => {
158 'id' => 'test2@pam',
159 'enable' => 1,
160 'expire' => 0,
161 'email' => undef,
162 'groups' => { 'testgroup' => 1 },
163 },
164 test3_pam => {
165 'id' => 'test3@pam',
166 'enable' => 1,
167 'expire' => 0,
168 'email' => undef,
169 'groups' => { 'another' => 1 },
170 },
891f7afa
FG
171 test_pam_with_token => {
172 'id' => 'test@pam',
173 'enable' => 1,
174 'expire' => 0,
175 'email' => undef,
176 'tokens' => {
177 'full' => {
178 'privsep' => 0,
179 'expire' => 0,
180 },
181 },
182 },
183 test_pam2_with_token => {
184 'id' => 'test2@pam',
185 'enable' => 1,
186 'expire' => 0,
187 'email' => undef,
188 'tokens' => {
189 'full' => {
190 'privsep' => 0,
191 'expire' => 0,
192 },
193 'privsep' => {
194 'privsep' => 1,
195 'expire' => 0,
196 },
197 'expired' => {
198 'privsep' => 0,
199 'expire' => 1,
200 },
201 },
202 },
7d1739ad
FG
203 test_group_empty => {
204 'id' => 'testgroup',
205 users => {},
206 },
207 test_group_single_member => {
208 'id' => 'testgroup',
209 'users' => {
210 'test@pam' => 1,
211 },
212 },
213 test_group_members => {
214 'id' => 'testgroup',
215 'users' => {
216 'test@pam' => 1,
217 'test2@pam' => 1,
218 },
219 },
220 test_group_second => {
221 'id' => 'another',
222 users => {
223 'test3@pam' => 1,
224 },
225 },
226 test_role_single_priv => {
227 'id' => 'testrolesingle',
228 'VM.Allocate' => 1,
229 },
230 test_role_privs => {
231 'id' => 'testrole',
232 'VM.Allocate' => 1,
233 'Datastore.Audit' => 1,
234 },
235 test_pool_empty => {
236 'id' => 'testpool',
237 vms => {},
238 storage => {},
239 },
240 test_pool_members => {
241 'id' => 'testpool',
242 vms => { 123 => 1, 1234 => 1},
243 storage => { 'local' => 1, 'local-zfs' => 1},
244 },
245 test_pool_duplicate_vms => {
246 'id' => 'test_duplicate_vms',
247 vms => {},
248 storage => {},
249 },
250 test_pool_duplicate_storages => {
251 'id' => 'test_duplicate_storages',
252 vms => {},
253 storage => { 'local' => 1, 'local-zfs' => 1},
254 },
255 acl_simple_user => {
256 'path' => '/',
257 users => {
258 'test@pam' => {
259 'PVEVMAdmin' => 1,
260 },
261 },
262 },
263 acl_complex_users => {
264 'path' => '/storage',
265 users => {
266 'test2@pam' => {
267 'PVEDatastoreUser' => 1,
268 },
269 'test@pam' => {
270 'PVEDatastoreAdmin' => 1,
271 },
272 },
273 },
274 acl_complex_missing_user => {
275 'path' => '/storage',
276 users => {
277 'test2@pam' => {
278 'PVEDatastoreUser' => 1,
279 },
5654260e
DC
280 'test@pam' => {
281 'PVEDatastoreAdmin' => 1,
282 },
7d1739ad
FG
283 },
284 },
891f7afa
FG
285 acl_simple_token => {
286 'path' => '/',
287 tokens => {
288 'test@pam!full' => {
289 'PVEVMAdmin' => 1,
290 },
291 },
292 },
293 acl_complex_tokens => {
294 'path' => '/storage',
295 tokens => {
296 'test2@pam!privsep' => {
297 'PVEDatastoreUser' => 1,
298 },
299 'test2@pam!expired' => {
300 'PVEDatastoreAdmin' => 1,
301 },
302 'test@pam!full' => {
303 'PVEDatastoreAdmin' => 1,
304 },
305 },
306 },
307 acl_complex_missing_token => {
308 'path' => '/storage',
309 tokens => {
310 'test2@pam!expired' => {
311 'PVEDatastoreAdmin' => 1,
312 },
313 'test2@pam!privsep' => {
314 'PVEDatastoreUser' => 1,
315 },
316 },
317 },
7d1739ad
FG
318 acl_simple_group => {
319 'path' => '/',
320 groups => {
321 'testgroup' => {
322 'PVEVMAdmin' => 1,
323 },
324 },
325 },
326 acl_complex_groups => {
327 'path' => '/storage',
328 groups => {
329 'testgroup' => {
330 'PVEDatastoreAdmin' => 1,
331 },
332 'another' => {
333 'PVEDatastoreUser' => 1,
334 },
335 },
336 },
337 acl_simple_group_noprop => {
338 'path' => '/',
339 groups => {
340 'testgroup' => {
341 'PVEVMAdmin' => 0,
342 },
343 },
344 },
345 acl_complex_groups_noprop => {
346 'path' => '/storage',
347 groups => {
348 'testgroup' => {
349 'PVEDatastoreAdmin' => 0,
350 },
351 'another' => {
352 'PVEDatastoreUser' => 0,
353 },
354 },
355 },
356 acl_complex_missing_group => {
357 'path' => '/storage',
358 groups => {
5654260e
DC
359 'testgroup' => {
360 'PVEDatastoreAdmin' => 1,
361 },
7d1739ad
FG
362 'another' => {
363 'PVEDatastoreUser' => 1,
364 },
365 },
366 },
367 acl_missing_role => {
368 'path' => '/storage',
369 users => {
370 'test@pam' => {
371 'MissingRole' => 1,
372 },
373 },
374 },
375};
376
377$default_cfg->{'acl_complex_mixed_root'} = {
378 'path' => '/',
379 users => $default_cfg->{'acl_simple_user'}->{users},
380 groups => $default_cfg->{'acl_simple_group'}->{groups},
381};
382
383$default_cfg->{'acl_complex_mixed_storage'} = {
384 'path' => '/storage',
385 users => $default_cfg->{'acl_complex_users'}->{users},
386 groups => $default_cfg->{'acl_complex_groups'}->{groups},
387};
388
389$default_cfg->{'acl_complex_mixed_root_noprop'} = {
390 'path' => '/',
391 users => $default_cfg->{'acl_simple_user'}->{users},
392 groups => $default_cfg->{'acl_simple_group_noprop'}->{groups},
393};
394
395$default_cfg->{'acl_complex_mixed_storage_noprop'} = {
396 'path' => '/storage',
397 users => $default_cfg->{'acl_complex_users'}->{users},
398 groups => $default_cfg->{'acl_complex_groups_noprop'}->{groups},
399};
400
401my $default_raw = {
402 users => {
403 'root@pam' => 'user:root@pam:1:0::::::',
404 'test_pam' => 'user:test@pam:1:0::::::',
405 'test2_pam' => 'user:test2@pam:1:0::::::',
406 'test3_pam' => 'user:test3@pam:1:0::::::',
407 },
408 groups => {
409 'test_group_empty' => 'group:testgroup:::',
410 'test_group_single_member' => 'group:testgroup:test@pam::',
411 'test_group_members' => 'group:testgroup:test2@pam,test@pam::',
412 'test_group_members_out_of_order' => 'group:testgroup:test@pam,test2@pam::',
413 'test_group_second' => 'group:another:test3@pam::',
414 },
891f7afa
FG
415 tokens => {
416 'test_token_simple' => 'token:test@pam!full:0:0::',
417 'test_token_multi_full' => 'token:test2@pam!full:0:0::',
418 'test_token_multi_privsep' => 'token:test2@pam!privsep:0:1::',
419 'test_token_multi_expired' => 'token:test2@pam!expired:1:0::',
420 },
7d1739ad
FG
421 roles => {
422 'test_role_single_priv' => 'role:testrolesingle:VM.Allocate:',
423 'test_role_privs' => 'role:testrole:Datastore.Audit,VM.Allocate:',
424 'test_role_privs_out_of_order' => 'role:testrole:VM.Allocate,Datastore.Audit:',
425 'test_role_privs_duplicate' => 'role:testrole:VM.Allocate,Datastore.Audit,VM.Allocate:',
426 'test_role_privs_invalid' => 'role:testrole:VM.Invalid,Datastore.Audit,VM.Allocate:',
427 },
428 pools => {
429 'test_pool_empty' => 'pool:testpool::::',
430 'test_pool_invalid' => 'pool:testpool::non-numeric:inval!d:',
431 'test_pool_members' => 'pool:testpool::123,1234:local,local-zfs:',
432 'test_pool_duplicate_vms' => 'pool:test_duplicate_vms::123,1234::',
433 'test_pool_duplicate_vms_expected' => 'pool:test_duplicate_vms::::',
434 'test_pool_duplicate_storages' => 'pool:test_duplicate_storages:::local,local-zfs:',
435 },
436 acl => {
437 'acl_simple_user' => 'acl:1:/:test@pam:PVEVMAdmin:',
438 'acl_complex_users_1' => 'acl:1:/storage:test@pam:PVEDatastoreAdmin:',
439 'acl_complex_users_2' => 'acl:1:/storage:test2@pam:PVEDatastoreUser:',
891f7afa
FG
440 'acl_simple_token' => 'acl:1:/:test@pam!full:PVEVMAdmin:',
441 'acl_complex_tokens_1' => 'acl:1:/storage:test2@pam!expired,test@pam!full:PVEDatastoreAdmin:',
442 'acl_complex_tokens_2' => 'acl:1:/storage:test2@pam!privsep:PVEDatastoreUser:',
443 'acl_complex_tokens_1_missing' => 'acl:1:/storage:test2@pam!expired:PVEDatastoreAdmin:',
7d1739ad
FG
444 'acl_simple_group' => 'acl:1:/:@testgroup:PVEVMAdmin:',
445 'acl_complex_groups_1' => 'acl:1:/storage:@testgroup:PVEDatastoreAdmin:',
446 'acl_complex_groups_2' => 'acl:1:/storage:@another:PVEDatastoreUser:',
447 'acl_simple_group_noprop' => 'acl:0:/:@testgroup:PVEVMAdmin:',
448 'acl_complex_groups_1_noprop' => 'acl:0:/storage:@testgroup:PVEDatastoreAdmin:',
449 'acl_complex_groups_2_noprop' => 'acl:0:/storage:@another:PVEDatastoreUser:',
450 'acl_complex_mixed_1' => 'acl:1:/:@testgroup,test@pam:PVEVMAdmin:',
451 'acl_complex_mixed_2' => 'acl:1:/storage:@testgroup,test@pam:PVEDatastoreAdmin:',
452 'acl_complex_mixed_3' => 'acl:1:/storage:@another,test2@pam:PVEDatastoreUser:',
453 'acl_missing_role' => 'acl:1:/storage:test@pam:MissingRole:',
454 },
455};
456
457my $tests = [
458 {
459 name => "empty_config",
460 config => {},
461 expected_config => {
170cf17b 462 acl_root => default_acls(),
7d1739ad
FG
463 users => { 'root@pam' => { enable => 1 } },
464 roles => default_roles(),
465 },
466 raw => "",
467 expected_raw => "\n\n\n\n",
468 },
469 {
470 name => "default_config",
471 config => {
170cf17b 472 acl_root => default_acls(),
7d1739ad
FG
473 users => default_users(),
474 roles => default_roles(),
475 },
476 raw => $default_raw->{users}->{'root@pam'}."\n\n\n\n\n",
477 },
478 {
479 name => "group_empty",
480 config => {
170cf17b 481 acl_root => default_acls(),
7d1739ad
FG
482 users => default_users(),
483 roles => default_roles(),
484 groups => default_groups_with([$default_cfg->{'test_group_empty'}]),
485 },
486 raw => "".
487 $default_raw->{users}->{'root@pam'}."\n\n".
488 $default_raw->{groups}->{'test_group_empty'}."\n\n".
489 "\n\n",
490 },
491 {
492 name => "group_inexisting_member",
493 config => {
170cf17b 494 acl_root => default_acls(),
7d1739ad
FG
495 users => default_users(),
496 roles => default_roles(),
497 groups => default_groups_with([$default_cfg->{'test_group_empty'}]),
498 },
499 raw => "".
500 $default_raw->{users}->{'root@pam'}."\n\n".
501 "group:testgroup:does_not_exist::".
502 "\n\n\n\n",
503 expected_raw => "".
504 $default_raw->{users}->{'root@pam'}."\n\n".
505 $default_raw->{groups}->{'test_group_empty'}."\n\n".
506 "\n\n",
507 },
508 {
509 name => "group_invalid_member",
510 expected_config => {
170cf17b 511 acl_root => default_acls(),
7d1739ad
FG
512 users => default_users(),
513 roles => default_roles(),
514 },
515 raw => "".
516 $default_raw->{users}->{'root@pam'}."\n\n".
517 'group:inval!d:root@pam:'.
518 "\n\n",
519 },
520 {
521 name => "group_with_one_member",
522 config => {
170cf17b 523 acl_root => default_acls(),
7d1739ad
FG
524 users => default_users_with([$default_cfg->{test_pam_with_group}]),
525 roles => default_roles(),
526 groups => default_groups_with([$default_cfg->{'test_group_single_member'}]),
527 },
528 raw => "".
529 $default_raw->{users}->{'root@pam'}."\n".
530 $default_raw->{users}->{'test_pam'}."\n\n".
531 $default_raw->{groups}->{'test_group_single_member'}."\n\n".
532 "\n\n",
533 },
534 {
535 name => "group_with_members",
536 config => {
170cf17b 537 acl_root => default_acls(),
7d1739ad
FG
538 users => default_users_with([$default_cfg->{test_pam_with_group}, $default_cfg->{test2_pam_with_group}]),
539 roles => default_roles(),
540 groups => default_groups_with([$default_cfg->{'test_group_members'}]),
541 },
542 raw => "".
543 $default_raw->{users}->{'root@pam'}."\n".
544 $default_raw->{users}->{'test2_pam'}."\n".
545 $default_raw->{users}->{'test_pam'}."\n\n".
546 $default_raw->{groups}->{'test_group_members'}."\n\n".
547 "\n\n",
548 },
891f7afa
FG
549 {
550 name => "token_simple",
551 config => {
170cf17b 552 acl_root => default_acls(),
891f7afa
FG
553 users => default_users_with([$default_cfg->{test_pam_with_token}]),
554 roles => default_roles(),
555 },
556 raw => "".
557 $default_raw->{users}->{'root@pam'}."\n".
558 $default_raw->{users}->{'test_pam'}."\n".
559 $default_raw->{tokens}->{'test_token_simple'}."\n\n\n\n\n",
560 },
561 {
562 name => "token_multi",
563 config => {
170cf17b 564 acl_root => default_acls(),
891f7afa
FG
565 users => default_users_with([$default_cfg->{test_pam_with_token}, $default_cfg->{test_pam2_with_token}]),
566 roles => default_roles(),
567 },
568 raw => "".
569 $default_raw->{users}->{'root@pam'}."\n".
570 $default_raw->{users}->{'test2_pam'}."\n".
571 $default_raw->{tokens}->{'test_token_multi_expired'}."\n".
572 $default_raw->{tokens}->{'test_token_multi_full'}."\n".
573 $default_raw->{tokens}->{'test_token_multi_privsep'}."\n".
574 $default_raw->{users}->{'test_pam'}."\n".
575 $default_raw->{tokens}->{'test_token_simple'}."\n".
576 "\n\n\n\n",
577 },
7d1739ad
FG
578 {
579 name => "custom_role_with_single_priv",
580 config => {
170cf17b 581 acl_root => default_acls(),
7d1739ad
FG
582 users => default_users(),
583 roles => default_roles_with([$default_cfg->{test_role_single_priv}]),
584 },
585 raw => "".
586 $default_raw->{users}->{'root@pam'}."\n\n\n\n".
587 $default_raw->{roles}->{'test_role_single_priv'}."\n\n",
588 },
589 {
590 name => "custom_role_with_privs",
591 config => {
170cf17b 592 acl_root => default_acls(),
7d1739ad
FG
593 users => default_users(),
594 roles => default_roles_with([$default_cfg->{test_role_privs}]),
595 },
596 raw => "".
597 $default_raw->{users}->{'root@pam'}."\n\n\n\n".
598 $default_raw->{roles}->{'test_role_privs'}."\n\n",
599 },
600 {
601 name => "custom_role_with_duplicate_privs",
602 config => {
170cf17b 603 acl_root => default_acls(),
7d1739ad
FG
604 users => default_users(),
605 roles => default_roles_with([$default_cfg->{test_role_privs}]),
606 },
607 raw => "".
608 $default_raw->{users}->{'root@pam'}."\n\n\n\n".
609 $default_raw->{roles}->{'test_role_privs_duplicate'}."\n\n",
610 expected_raw => "".
611 $default_raw->{users}->{'root@pam'}."\n\n\n\n".
612 $default_raw->{roles}->{'test_role_privs'}."\n\n",
613 },
614 {
615 name => "custom_role_with_invalid_priv",
616 config => {
170cf17b 617 acl_root => default_acls(),
7d1739ad
FG
618 users => default_users(),
619 roles => default_roles_with([$default_cfg->{test_role_privs}]),
620 },
621 raw => "".
622 $default_raw->{users}->{'root@pam'}."\n\n\n\n".
623 $default_raw->{roles}->{'test_role_privs_invalid'}."\n\n",
624 expected_raw => "".
625 $default_raw->{users}->{'root@pam'}."\n\n\n\n".
626 $default_raw->{roles}->{'test_role_privs'}."\n\n",
627 },
628 {
629 name => "pool_empty",
630 config => {
170cf17b 631 acl_root => default_acls(),
7d1739ad
FG
632 users => default_users(),
633 roles => default_roles(),
634 pools => default_pools_with([$default_cfg->{test_pool_empty}]),
635 },
636 raw => "".
637 $default_raw->{users}->{'root@pam'}."\n\n\n".
638 $default_raw->{pools}->{'test_pool_empty'}."\n\n\n",
639 },
640 {
641 name => "pool_invalid",
642 config => {
170cf17b 643 acl_root => default_acls(),
7d1739ad
FG
644 users => default_users(),
645 roles => default_roles(),
646 pools => default_pools_with([$default_cfg->{test_pool_empty}]),
647 },
648 raw => "".
649 $default_raw->{users}->{'root@pam'}."\n\n\n".
650 $default_raw->{pools}->{'test_pool_invalid'}."\n\n\n",
651 expected_raw => "".
652 $default_raw->{users}->{'root@pam'}."\n\n\n".
653 $default_raw->{pools}->{'test_pool_empty'}."\n\n\n",
654 },
655 {
656 name => "pool_members",
657 config => {
170cf17b 658 acl_root => default_acls(),
7d1739ad
FG
659 users => default_users(),
660 roles => default_roles(),
661 pools => default_pools_with([$default_cfg->{test_pool_members}]),
662 vms => default_pool_vms_with([$default_cfg->{test_pool_members}]),
663 },
664 raw => "".
665 $default_raw->{users}->{'root@pam'}."\n\n\n".
666 $default_raw->{pools}->{'test_pool_members'}."\n\n\n",
667 },
668 {
669 name => "pool_duplicate_members",
670 config => {
170cf17b 671 acl_root => default_acls(),
7d1739ad
FG
672 users => default_users(),
673 roles => default_roles(),
674 pools => default_pools_with([$default_cfg->{test_pool_members}, $default_cfg->{test_pool_duplicate_vms}, $default_cfg->{test_pool_duplicate_storages}]),
675 vms => default_pool_vms_with([$default_cfg->{test_pool_members}]),
676 },
677 raw => "".
678 $default_raw->{users}->{'root@pam'}."\n\n\n".
679 $default_raw->{pools}->{'test_pool_members'}."\n".
680 $default_raw->{pools}->{'test_pool_duplicate_vms'}."\n".
681 $default_raw->{pools}->{'test_pool_duplicate_storages'}."\n",
682 expected_raw => "".
683 $default_raw->{users}->{'root@pam'}."\n\n\n".
684 $default_raw->{pools}->{'test_pool_duplicate_storages'}."\n".
685 $default_raw->{pools}->{'test_pool_duplicate_vms_expected'}."\n".
686 $default_raw->{pools}->{'test_pool_members'}."\n\n\n",
687 },
688 {
689 name => "acl_simple_user",
690 config => {
691 users => default_users_with([$default_cfg->{test_pam}]),
692 roles => default_roles(),
170cf17b 693 acl_root => default_acls_with([$default_cfg->{acl_simple_user}]),
7d1739ad
FG
694 },
695 raw => "".
696 $default_raw->{users}->{'root@pam'}."\n".
697 $default_raw->{users}->{'test_pam'}."\n\n\n\n\n".
698 $default_raw->{acl}->{'acl_simple_user'}."\n",
699 },
700 {
701 name => "acl_complex_users",
702 config => {
703 users => default_users_with([$default_cfg->{test_pam}, $default_cfg->{'test2_pam'}]),
704 roles => default_roles(),
170cf17b 705 acl_root => default_acls_with([$default_cfg->{acl_simple_user}, $default_cfg->{acl_complex_users}]),
7d1739ad
FG
706 },
707 raw => "".
708 $default_raw->{users}->{'root@pam'}."\n".
709 $default_raw->{users}->{'test2_pam'}."\n".
710 $default_raw->{users}->{'test_pam'}."\n\n\n\n\n".
711 $default_raw->{acl}->{'acl_simple_user'}."\n".
712 $default_raw->{acl}->{'acl_complex_users_1'}."\n".
713 $default_raw->{acl}->{'acl_complex_users_2'}."\n",
714 },
715 {
716 name => "acl_complex_missing_user",
717 config => {
718 users => default_users_with([$default_cfg->{test2_pam}]),
719 roles => default_roles(),
170cf17b 720 acl_root => default_acls_with([$default_cfg->{acl_simple_user}, $default_cfg->{acl_complex_missing_user}]),
7d1739ad
FG
721 },
722 raw => "".
723 $default_raw->{users}->{'root@pam'}."\n".
724 $default_raw->{users}->{'test2_pam'}."\n\n\n\n\n".
725 $default_raw->{acl}->{'acl_simple_user'}."\n".
726 $default_raw->{acl}->{'acl_complex_users_1'}."\n".
727 $default_raw->{acl}->{'acl_complex_users_2'}."\n",
7d1739ad
FG
728 },
729 {
730 name => "acl_simple_group",
731 config => {
732 users => default_users_with([$default_cfg->{test_pam_with_group}]),
733 groups => default_groups_with([$default_cfg->{'test_group_single_member'}]),
734 roles => default_roles(),
170cf17b 735 acl_root => default_acls_with([$default_cfg->{acl_simple_group}]),
7d1739ad
FG
736 },
737 raw => "".
738 $default_raw->{users}->{'root@pam'}."\n".
739 $default_raw->{users}->{'test_pam'}."\n\n".
740 $default_raw->{groups}->{'test_group_single_member'}."\n\n\n\n".
741 $default_raw->{acl}->{'acl_simple_group'}."\n",
742 },
743 {
744 name => "acl_complex_groups",
745 config => {
746 users => default_users_with([$default_cfg->{test_pam_with_group}, $default_cfg->{'test2_pam_with_group'}, $default_cfg->{'test3_pam'}]),
747 groups => default_groups_with([$default_cfg->{'test_group_members'}, $default_cfg->{'test_group_second'}]),
748 roles => default_roles(),
170cf17b 749 acl_root => default_acls_with([$default_cfg->{acl_simple_group}, $default_cfg->{acl_complex_groups}]),
7d1739ad
FG
750 },
751 raw => "".
752 $default_raw->{users}->{'root@pam'}."\n".
753 $default_raw->{users}->{'test2_pam'}."\n".
754 $default_raw->{users}->{'test3_pam'}."\n".
755 $default_raw->{users}->{'test_pam'}."\n\n".
756 $default_raw->{groups}->{'test_group_second'}."\n".
757 $default_raw->{groups}->{'test_group_members'}."\n\n\n\n".
758 $default_raw->{acl}->{'acl_simple_group'}."\n".
759 $default_raw->{acl}->{'acl_complex_groups_1'}."\n".
760 $default_raw->{acl}->{'acl_complex_groups_2'}."\n",
761 },
762 {
763 name => "acl_complex_missing_group",
764 config => {
765 users => default_users_with([$default_cfg->{test_pam}, $default_cfg->{'test2_pam'}, $default_cfg->{'test3_pam'}]),
766 groups => default_groups_with([$default_cfg->{'test_group_second'}]),
767 roles => default_roles(),
170cf17b 768 acl_root => default_acls_with([$default_cfg->{acl_simple_group}, $default_cfg->{acl_complex_missing_group}]),
7d1739ad
FG
769 },
770 raw => "".
771 $default_raw->{users}->{'root@pam'}."\n".
772 $default_raw->{users}->{'test2_pam'}."\n".
773 $default_raw->{users}->{'test3_pam'}."\n".
774 $default_raw->{users}->{'test_pam'}."\n\n".
775 $default_raw->{groups}->{'test_group_second'}."\n".
776 $default_raw->{acl}->{'acl_simple_group'}."\n".
777 $default_raw->{acl}->{'acl_complex_groups_1'}."\n".
778 $default_raw->{acl}->{'acl_complex_groups_2'}."\n",
779 expected_raw => "".
780 $default_raw->{users}->{'root@pam'}."\n".
781 $default_raw->{users}->{'test2_pam'}."\n".
782 $default_raw->{users}->{'test3_pam'}."\n".
783 $default_raw->{users}->{'test_pam'}."\n\n".
784 $default_raw->{groups}->{'test_group_second'}."\n\n\n\n".
5654260e
DC
785 $default_raw->{acl}->{'acl_simple_group'}."\n".
786 $default_raw->{acl}->{'acl_complex_groups_1'}."\n".
7d1739ad
FG
787 $default_raw->{acl}->{'acl_complex_groups_2'}."\n",
788 },
891f7afa
FG
789 {
790 name => "acl_simple_token",
791 config => {
792 users => default_users_with([$default_cfg->{test_pam_with_token}]),
793 roles => default_roles(),
170cf17b 794 acl_root => default_acls_with([$default_cfg->{acl_simple_token}]),
891f7afa
FG
795 },
796 raw => "".
797 $default_raw->{users}->{'root@pam'}."\n".
798 $default_raw->{users}->{'test_pam'}."\n".
799 $default_raw->{tokens}->{'test_token_simple'}."\n\n\n\n\n".
800 $default_raw->{acl}->{'acl_simple_token'}."\n",
801 },
802 {
803 name => "acl_complex_tokens",
804 config => {
805 users => default_users_with([$default_cfg->{test_pam_with_token}, $default_cfg->{'test_pam2_with_token'}]),
806 roles => default_roles(),
170cf17b 807 acl_root => default_acls_with([$default_cfg->{acl_simple_token}, $default_cfg->{acl_complex_tokens}]),
891f7afa
FG
808 },
809 raw => "".
810 $default_raw->{users}->{'root@pam'}."\n".
811 $default_raw->{users}->{'test2_pam'}."\n".
812 $default_raw->{tokens}->{'test_token_multi_expired'}."\n".
813 $default_raw->{tokens}->{'test_token_multi_full'}."\n".
814 $default_raw->{tokens}->{'test_token_multi_privsep'}."\n".
815 $default_raw->{users}->{'test_pam'}."\n".
816 $default_raw->{tokens}->{'test_token_simple'}."\n\n\n\n\n".
817 $default_raw->{acl}->{'acl_simple_token'}."\n".
818 $default_raw->{acl}->{'acl_complex_tokens_1'}."\n".
819 $default_raw->{acl}->{'acl_complex_tokens_2'}."\n",
820 },
821 {
822 name => "acl_complex_missing_token",
823 config => {
824 users => default_users_with([$default_cfg->{test_pam}, $default_cfg->{test_pam2_with_token}]),
825 roles => default_roles(),
170cf17b 826 acl_root => default_acls_with([$default_cfg->{acl_complex_missing_token}]),
891f7afa
FG
827 },
828 raw => "".
829 $default_raw->{users}->{'root@pam'}."\n".
830 $default_raw->{users}->{'test2_pam'}."\n".
831 $default_raw->{tokens}->{'test_token_multi_expired'}."\n".
832 $default_raw->{tokens}->{'test_token_multi_full'}."\n".
833 $default_raw->{tokens}->{'test_token_multi_privsep'}."\n".
834 $default_raw->{users}->{'test_pam'}."\n".
835 $default_raw->{acl}->{'acl_simple_token'}."\n".
836 $default_raw->{acl}->{'acl_complex_tokens_1'}."\n".
837 $default_raw->{acl}->{'acl_complex_tokens_2'}."\n",
838 expected_raw => "".
839 $default_raw->{users}->{'root@pam'}."\n".
840 $default_raw->{users}->{'test2_pam'}."\n".
841 $default_raw->{tokens}->{'test_token_multi_expired'}."\n".
842 $default_raw->{tokens}->{'test_token_multi_full'}."\n".
843 $default_raw->{tokens}->{'test_token_multi_privsep'}."\n".
844 $default_raw->{users}->{'test_pam'}."\n\n\n\n\n".
845 $default_raw->{acl}->{'acl_complex_tokens_1_missing'}."\n".
846 $default_raw->{acl}->{'acl_complex_tokens_2'}."\n",
847 },
7d1739ad
FG
848 {
849 name => "acl_missing_role",
850 config => {
851 users => default_users_with([$default_cfg->{test_pam}]),
852 roles => default_roles(),
170cf17b 853 acl_root => default_acls_with([$default_cfg->{acl_simple_user}]),
7d1739ad
FG
854 },
855 raw => "".
856 $default_raw->{users}->{'root@pam'}."\n".
857 $default_raw->{users}->{'test_pam'}."\n\n\n\n\n".
858 $default_raw->{acl}->{'acl_simple_user'}."\n".
859 $default_raw->{acl}->{'acl_missing_role'}."\n",
21f523a5
FG
860 expected_raw => "".
861 $default_raw->{users}->{'root@pam'}."\n".
862 $default_raw->{users}->{'test_pam'}."\n\n\n\n\n".
863 $default_raw->{acl}->{'acl_simple_user'}."\n",
7d1739ad
FG
864 },
865 {
866 name => "acl_complex_mixed",
867 config => {
868 users => default_users_with([$default_cfg->{test_pam_with_group}, $default_cfg->{'test2_pam_with_group'}, $default_cfg->{'test3_pam'}]),
869 groups => default_groups_with([$default_cfg->{'test_group_members'}, $default_cfg->{'test_group_second'}]),
870 roles => default_roles(),
170cf17b 871 acl_root => default_acls_with([
7d1739ad
FG
872 $default_cfg->{acl_complex_mixed_root},
873 $default_cfg->{acl_complex_mixed_storage},
874 ]),
875 },
876 raw => "".
877 $default_raw->{users}->{'root@pam'}."\n".
878 $default_raw->{users}->{'test2_pam'}."\n".
879 $default_raw->{users}->{'test3_pam'}."\n".
880 $default_raw->{users}->{'test_pam'}."\n\n".
881 $default_raw->{groups}->{'test_group_second'}."\n".
882 $default_raw->{groups}->{'test_group_members'}."\n\n\n\n".
883 $default_raw->{acl}->{'acl_simple_group'}."\n".
884 $default_raw->{acl}->{'acl_complex_groups_1'}."\n".
885 $default_raw->{acl}->{'acl_complex_groups_2'}."\n".
886 $default_raw->{acl}->{'acl_simple_user'}."\n".
887 $default_raw->{acl}->{'acl_complex_users_1'}."\n".
888 $default_raw->{acl}->{'acl_complex_users_2'}."\n",
889 expected_raw => "".
890 $default_raw->{users}->{'root@pam'}."\n".
891 $default_raw->{users}->{'test2_pam'}."\n".
892 $default_raw->{users}->{'test3_pam'}."\n".
893 $default_raw->{users}->{'test_pam'}."\n\n".
894 $default_raw->{groups}->{'test_group_second'}."\n".
895 $default_raw->{groups}->{'test_group_members'}."\n\n\n\n".
896 $default_raw->{acl}->{'acl_complex_mixed_1'}."\n".
897 $default_raw->{acl}->{'acl_complex_mixed_2'}."\n".
898 $default_raw->{acl}->{'acl_complex_mixed_3'}."\n",
899 },
900 {
901 name => "acl_complex_mixed_prop_noprop_no_merge_sort_by_path",
902 config => {
903 users => default_users_with([$default_cfg->{test_pam_with_group}, $default_cfg->{'test2_pam_with_group'}, $default_cfg->{'test3_pam'}]),
904 groups => default_groups_with([$default_cfg->{'test_group_members'}, $default_cfg->{'test_group_second'}]),
905 roles => default_roles(),
170cf17b 906 acl_root => default_acls_with([
7d1739ad
FG
907 $default_cfg->{acl_complex_mixed_root_noprop},
908 $default_cfg->{acl_complex_mixed_storage_noprop},
909 ]),
910 },
911 raw => "".
912 $default_raw->{users}->{'root@pam'}."\n".
913 $default_raw->{users}->{'test2_pam'}."\n".
914 $default_raw->{users}->{'test3_pam'}."\n".
915 $default_raw->{users}->{'test_pam'}."\n\n".
916 $default_raw->{groups}->{'test_group_second'}."\n".
917 $default_raw->{groups}->{'test_group_members'}."\n\n\n\n".
918 $default_raw->{acl}->{'acl_simple_group_noprop'}."\n".
919 $default_raw->{acl}->{'acl_simple_user'}."\n".
920 $default_raw->{acl}->{'acl_complex_groups_1_noprop'}."\n".
921 $default_raw->{acl}->{'acl_complex_groups_2_noprop'}."\n".
922 $default_raw->{acl}->{'acl_complex_users_1'}."\n".
923 $default_raw->{acl}->{'acl_complex_users_2'}."\n",
924 },
925 {
926 name => "sort_roles_and_privs",
927 raw => "".
928 $default_raw->{users}->{'root@pam'}."\n".
929 $default_raw->{roles}->{'test_role_single_priv'}."\n\n".
930 $default_raw->{roles}->{'test_role_privs_out_of_order'}."\n\n",
931 expected_raw => "".
932 $default_raw->{users}->{'root@pam'}."\n\n\n\n".
933 $default_raw->{roles}->{'test_role_privs'}."\n".
934 $default_raw->{roles}->{'test_role_single_priv'}."\n\n",
935 },
936 {
937 name => "sort_users_and_group_members",
938 raw => "".
939 $default_raw->{users}->{'test2_pam'}."\n".
940 $default_raw->{users}->{'root@pam'}."\n".
941 $default_raw->{users}->{'test_pam'}."\n\n".
942 $default_raw->{groups}->{'test_group_members_out_of_order'}."\n\n".
943 "\n\n",
944 expected_raw => "".
945 $default_raw->{users}->{'root@pam'}."\n".
946 $default_raw->{users}->{'test2_pam'}."\n".
947 $default_raw->{users}->{'test_pam'}."\n\n".
948 $default_raw->{groups}->{'test_group_members'}."\n\n".
949 "\n\n",
950 },
951 {
952 name => "sort_user_groups_and_acls",
953 raw => "".
954 $default_raw->{users}->{'test2_pam'}."\n".
955 $default_raw->{users}->{'root@pam'}."\n".
956 $default_raw->{users}->{'test_pam'}."\n\n".
957 $default_raw->{users}->{'test3_pam'}."\n".
958 $default_raw->{groups}->{'test_group_members_out_of_order'}."\n\n\n\n".
959 $default_raw->{groups}->{'test_group_second'}."\n".
960 $default_raw->{acl}->{'acl_simple_user'}."\n".
961 $default_raw->{acl}->{'acl_simple_group'}."\n".
962 $default_raw->{acl}->{'acl_complex_users_1'}."\n".
963 $default_raw->{acl}->{'acl_complex_users_2'}."\n".
964 $default_raw->{acl}->{'acl_complex_groups_1'}."\n".
965 $default_raw->{acl}->{'acl_complex_groups_2'}."\n",
966 expected_raw => "".
967 $default_raw->{users}->{'root@pam'}."\n".
968 $default_raw->{users}->{'test2_pam'}."\n".
969 $default_raw->{users}->{'test3_pam'}."\n".
970 $default_raw->{users}->{'test_pam'}."\n\n".
971 $default_raw->{groups}->{'test_group_second'}."\n".
972 $default_raw->{groups}->{'test_group_members'}."\n\n\n\n".
973 $default_raw->{acl}->{'acl_complex_mixed_1'}."\n".
974 $default_raw->{acl}->{'acl_complex_mixed_2'}."\n".
975 $default_raw->{acl}->{'acl_complex_mixed_3'}."\n",
976 },
977 {
978 name => 'default_values',
979 config => {
980 users => {
981 'root@pam' => {
982 enable => 0,
983 expire => 0,
984 email => undef,
985 },
986 'test@pam' => {
987 enable => 0,
988 expire => 0,
989 email => undef,
891f7afa
FG
990 tokens => {
991 'test' => {
992 expire => 0,
993 privsep => 0,
994 },
995 },
7d1739ad
FG
996 },
997 },
998 roles => default_roles_with([{ id => 'testrole' }]),
999 groups => default_groups_with([$default_cfg->{test_group_empty}]),
1000 pools => default_pools_with([$default_cfg->{test_pool_empty}]),
170cf17b 1001 acl_root => {},
7d1739ad
FG
1002 },
1003 raw => "".
1004 'user:root@pam'."\n".
891f7afa
FG
1005 'user:test@pam'."\n".
1006 'token:test@pam!test'."\n\n".
7d1739ad
FG
1007 'group:testgroup'."\n\n".
1008 'pool:testpool'."\n\n".
1009 'role:testrole'."\n\n".
1010 'acl::/:',
1011 expected_raw => "".
1012 'user:root@pam:0:0::::::'."\n".
891f7afa
FG
1013 'user:test@pam:0:0::::::'."\n".
1014 'token:test@pam!test:0:0::'."\n\n".
7d1739ad
FG
1015 'group:testgroup:::'."\n\n".
1016 'pool:testpool::::'."\n\n".
1017 'role:testrole::'."\n\n",
1018 },
1019];
1020
1021
1022my $number_of_tests_run = 0;
1023foreach my $t (@$tests) {
1024 my $expected_config = $t->{expected_config} // $t->{config};
1025 my $expected_raw = $t->{expected_raw} // $t->{raw};
1026 if (defined($t->{raw})) {
1027 my $parsed = PVE::AccessControl::parse_user_config($t->{name}, $t->{raw});
1028 if (defined($expected_config)) {
1029 is_deeply($parsed, $expected_config, "$t->{name}_parse");
1030 $number_of_tests_run++;
1031 }
1032 if (defined($t->{expected_raw}) && !defined($t->{config})) {
1033 is(PVE::AccessControl::write_user_config($t->{name}, $parsed), $t->{expected_raw}, "$t->{name}_rewrite");
1034 $number_of_tests_run++;
1035 }
1036
1037 }
1038 if (defined($t->{config})) {
1039 my $written = PVE::AccessControl::write_user_config($t->{name}, $t->{config});
1040 if (defined($expected_raw)) {
1041 is($written, $expected_raw, "$t->{name}_write");
1042 $number_of_tests_run++;
1043 }
1044 if (defined($t->{expected_config}) && !defined($t->{raw})) {
1045 is_deeply(PVE::AccessControl::parse_user_config($t->{name}, $t->{written}), $t->{expected_config}, "$t->{name}_reparse");
1046 $number_of_tests_run++;
1047 }
1048 }
1049};
1050
1051done_testing( $number_of_tests_run);