]>
Commit | Line | Data |
---|---|---|
2c3a6c0a DM |
1 | package PVE::API2::ACL; |
2 | ||
3 | use strict; | |
4 | use warnings; | |
5 | use PVE::Cluster qw (cfs_read_file cfs_write_file); | |
6 | use PVE::Tools qw(split_list); | |
7 | use PVE::AccessControl; | |
8 | use PVE::Exception qw(raise_param_exc); | |
9 | ||
10 | use PVE::SafeSyslog; | |
11 | ||
2c3a6c0a DM |
12 | use PVE::RESTHandler; |
13 | ||
14 | use base qw(PVE::RESTHandler); | |
15 | ||
16 | __PACKAGE__->register_method ({ | |
0a6e09fd PA |
17 | name => 'read_acl', |
18 | path => '', | |
2c3a6c0a DM |
19 | method => 'GET', |
20 | description => "Get Access Control List (ACLs).", | |
0a6e09fd | 21 | permissions => { |
fc21a5c2 | 22 | description => "The returned list is restricted to objects where you have rights to modify permissions.", |
e3a3a0d7 | 23 | user => 'all', |
96919234 | 24 | }, |
2c3a6c0a DM |
25 | parameters => { |
26 | additionalProperties => 0, | |
27 | properties => {}, | |
28 | }, | |
29 | returns => { | |
30 | type => 'array', | |
31 | items => { | |
32 | type => "object", | |
33 | additionalProperties => 0, | |
34 | properties => { | |
35 | path => { type => 'string' }, | |
36 | type => { type => 'string', enum => ['user', 'group'] }, | |
37 | ugid => { type => 'string' }, | |
38 | roleid => { type => 'string' }, | |
39 | propagate => { type => 'boolean' }, | |
40 | }, | |
41 | }, | |
42 | }, | |
43 | code => sub { | |
44 | my ($param) = @_; | |
0a6e09fd | 45 | |
e3a3a0d7 DM |
46 | my $rpcenv = PVE::RPCEnvironment::get(); |
47 | my $authuser = $rpcenv->get_user(); | |
2c3a6c0a DM |
48 | my $res = []; |
49 | ||
e3a3a0d7 | 50 | my $usercfg = $rpcenv->{user_cfg}; |
2c3a6c0a | 51 | if (!$usercfg || !$usercfg->{acl}) { |
4384e19e | 52 | return $res; |
2c3a6c0a DM |
53 | } |
54 | ||
e3a3a0d7 DM |
55 | my $audit = $rpcenv->check($authuser, '/access', ['Sys.Audit'], 1); |
56 | ||
2c3a6c0a DM |
57 | my $acl = $usercfg->{acl}; |
58 | foreach my $path (keys %$acl) { | |
59 | foreach my $type (qw(users groups)) { | |
60 | my $d = $acl->{$path}->{$type}; | |
61 | next if !$d; | |
e3a3a0d7 | 62 | next if !($audit || $rpcenv->check_perm_modify($authuser, $path, 1)); |
2c3a6c0a DM |
63 | foreach my $id (keys %$d) { |
64 | foreach my $role (keys %{$d->{$id}}) { | |
65 | my $propagate = $d->{$id}->{$role}; | |
66 | push @$res, { | |
67 | path => $path, | |
68 | type => $type eq 'groups' ? 'group' : 'user', | |
69 | ugid => $id, | |
70 | roleid => $role, | |
71 | propagate => $propagate, | |
72 | }; | |
73 | } | |
74 | } | |
75 | } | |
76 | } | |
77 | ||
78 | return $res; | |
79 | }}); | |
80 | ||
81 | __PACKAGE__->register_method ({ | |
0a6e09fd | 82 | name => 'update_acl', |
2c3a6c0a | 83 | protected => 1, |
0a6e09fd | 84 | path => '', |
2c3a6c0a | 85 | method => 'PUT', |
0a6e09fd | 86 | permissions => { |
e3a3a0d7 | 87 | check => ['perm-modify', '{path}'], |
96919234 | 88 | }, |
2c3a6c0a DM |
89 | description => "Update Access Control List (add or remove permissions).", |
90 | parameters => { | |
0a6e09fd | 91 | additionalProperties => 0, |
2c3a6c0a DM |
92 | properties => { |
93 | path => { | |
94 | description => "Access control path", | |
95 | type => 'string', | |
96 | }, | |
0a6e09fd | 97 | users => { |
2c3a6c0a | 98 | description => "List of users.", |
0a6e09fd | 99 | type => 'string', format => 'pve-userid-list', |
2c3a6c0a DM |
100 | optional => 1, |
101 | }, | |
0a6e09fd | 102 | groups => { |
2c3a6c0a DM |
103 | description => "List of groups.", |
104 | type => 'string', format => 'pve-groupid-list', | |
0a6e09fd | 105 | optional => 1, |
2c3a6c0a | 106 | }, |
0a6e09fd | 107 | roles => { |
2c3a6c0a DM |
108 | description => "List of roles.", |
109 | type => 'string', format => 'pve-roleid-list', | |
110 | }, | |
0a6e09fd | 111 | propagate => { |
2c3a6c0a | 112 | description => "Allow to propagate (inherit) permissions.", |
0a6e09fd | 113 | type => 'boolean', |
2c3a6c0a | 114 | optional => 1, |
e2993b66 | 115 | default => 1, |
2c3a6c0a DM |
116 | }, |
117 | delete => { | |
118 | description => "Remove permissions (instead of adding it).", | |
0a6e09fd | 119 | type => 'boolean', |
2c3a6c0a DM |
120 | optional => 1, |
121 | }, | |
122 | }, | |
123 | }, | |
124 | returns => { type => 'null' }, | |
125 | code => sub { | |
126 | my ($param) = @_; | |
127 | ||
128 | if (!($param->{users} || $param->{groups})) { | |
0a6e09fd PA |
129 | raise_param_exc({ |
130 | users => "either 'users' or 'groups' is required.", | |
2c3a6c0a DM |
131 | groups => "either 'users' or 'groups' is required." }); |
132 | } | |
133 | ||
134 | my $path = PVE::AccessControl::normalize_path($param->{path}); | |
135 | raise_param_exc({ path => "invalid ACL path '$param->{path}'" }) if !$path; | |
136 | ||
137 | PVE::AccessControl::lock_user_config( | |
138 | sub { | |
0a6e09fd | 139 | |
2c3a6c0a DM |
140 | my $cfg = cfs_read_file("user.cfg"); |
141 | ||
e2993b66 | 142 | my $propagate = 1; |
0a6e09fd | 143 | |
e2993b66 DM |
144 | if (defined($param->{propagate})) { |
145 | $propagate = $param->{propagate} ? 1 : 0; | |
146 | } | |
2c3a6c0a DM |
147 | |
148 | foreach my $role (split_list($param->{roles})) { | |
0a6e09fd | 149 | die "role '$role' does not exist\n" |
2c3a6c0a DM |
150 | if !$cfg->{roles}->{$role}; |
151 | ||
152 | foreach my $group (split_list($param->{groups})) { | |
153 | ||
154 | die "group '$group' does not exist\n" | |
155 | if !$cfg->{groups}->{$group}; | |
156 | ||
157 | if ($param->{delete}) { | |
158 | delete($cfg->{acl}->{$path}->{groups}->{$group}->{$role}); | |
159 | } else { | |
160 | $cfg->{acl}->{$path}->{groups}->{$group}->{$role} = $propagate; | |
161 | } | |
162 | } | |
163 | ||
164 | foreach my $userid (split_list($param->{users})) { | |
165 | my $username = PVE::AccessControl::verify_username($userid); | |
166 | ||
167 | die "user '$username' does not exist\n" | |
168 | if !$cfg->{users}->{$username}; | |
169 | ||
170 | if ($param->{delete}) { | |
171 | delete($cfg->{acl}->{$path}->{users}->{$username}->{$role}); | |
172 | } else { | |
173 | $cfg->{acl}->{$path}->{users}->{$username}->{$role} = $propagate; | |
0a6e09fd | 174 | } |
2c3a6c0a DM |
175 | } |
176 | } | |
177 | ||
178 | cfs_write_file("user.cfg", $cfg); | |
179 | }, "ACL update failed"); | |
180 | ||
181 | return undef; | |
182 | }}); | |
183 | ||
184 | 1; |