1 package PVE::API2::ACL;
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);
12 use Data::Dumper; # fixme: remove
16 use base qw(PVE::RESTHandler);
18 __PACKAGE__->register_method ({
22 description => "Get Access Control List (ACLs).",
24 description => "The returned list is restricted to objects where you have rights to modify permissions.",
28 additionalProperties => 0,
35 additionalProperties => 0,
37 path => { type => 'string' },
38 type => { type => 'string', enum => ['user', 'group'] },
39 ugid => { type => 'string' },
40 roleid => { type => 'string' },
41 propagate => { type => 'boolean' },
48 my $rpcenv = PVE::RPCEnvironment::get();
49 my $authuser = $rpcenv->get_user();
52 my $usercfg = $rpcenv->{user_cfg};
53 if (!$usercfg || !$usercfg->{acl}) {
57 my $audit = $rpcenv->check($authuser, '/access', ['Sys.Audit'], 1);
59 my $acl = $usercfg->{acl};
60 foreach my $path (keys %$acl) {
61 foreach my $type (qw(users groups)) {
62 my $d = $acl->{$path}->{$type};
64 next if !($audit || $rpcenv->check_perm_modify($authuser, $path, 1));
65 foreach my $id (keys %$d) {
66 foreach my $role (keys %{$d->{$id}}) {
67 my $propagate = $d->{$id}->{$role};
70 type => $type eq 'groups' ? 'group' : 'user',
73 propagate => $propagate,
83 __PACKAGE__->register_method ({
89 check => ['perm-modify', '{path}'],
91 description => "Update Access Control List (add or remove permissions).",
93 additionalProperties => 0,
96 description => "Access control path",
100 description => "List of users.",
101 type => 'string', format => 'pve-userid-list',
105 description => "List of groups.",
106 type => 'string', format => 'pve-groupid-list',
110 description => "List of roles.",
111 type => 'string', format => 'pve-roleid-list',
114 description => "Allow to propagate (inherit) permissions.",
119 description => "Remove permissions (instead of adding it).",
125 returns => { type => 'null' },
129 if (!($param->{users} || $param->{groups})) {
131 users => "either 'users' or 'groups' is required.",
132 groups => "either 'users' or 'groups' is required." });
135 my $path = PVE::AccessControl::normalize_path($param->{path});
136 raise_param_exc({ path => "invalid ACL path '$param->{path}'" }) if !$path;
138 PVE::AccessControl::lock_user_config(
141 my $cfg = cfs_read_file("user.cfg");
143 my $propagate = $param->{propagate} ? 1 : 0;
145 foreach my $role (split_list($param->{roles})) {
146 die "role '$role' does not exist\n"
147 if !$cfg->{roles}->{$role};
149 foreach my $group (split_list($param->{groups})) {
151 die "group '$group' does not exist\n"
152 if !$cfg->{groups}->{$group};
154 if ($param->{delete}) {
155 delete($cfg->{acl}->{$path}->{groups}->{$group}->{$role});
157 $cfg->{acl}->{$path}->{groups}->{$group}->{$role} = $propagate;
161 foreach my $userid (split_list($param->{users})) {
162 my $username = PVE::AccessControl::verify_username($userid);
164 die "user '$username' does not exist\n"
165 if !$cfg->{users}->{$username};
167 if ($param->{delete}) {
168 delete($cfg->{acl}->{$path}->{users}->{$username}->{$role});
170 $cfg->{acl}->{$path}->{users}->{$username}->{$role} = $propagate;
175 cfs_write_file("user.cfg", $cfg);
176 }, "ACL update failed");