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