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