]> git.proxmox.com Git - pve-access-control.git/blame - PVE/API2/ACL.pm
PVE::AccessControl: register userid with completion
[pve-access-control.git] / PVE / API2 / ACL.pm
CommitLineData
2c3a6c0a
DM
1package PVE::API2::ACL;
2
3use strict;
4use warnings;
5use PVE::Cluster qw (cfs_read_file cfs_write_file);
6use PVE::Tools qw(split_list);
7use PVE::AccessControl;
8use PVE::Exception qw(raise_param_exc);
9
10use PVE::SafeSyslog;
11
2c3a6c0a
DM
12use PVE::RESTHandler;
13
14use 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
1841;