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);
9 use PVE
::JSONSchema
qw(get_standard_option register_standard_option);
15 use base
qw(PVE::RESTHandler);
17 register_standard_option
('acl-propagate', {
18 description
=> "Allow to propagate (inherit) permissions.",
23 register_standard_option
('acl-path', {
24 description
=> "Access control path",
28 __PACKAGE__-
>register_method ({
32 description
=> "Get Access Control List (ACLs).",
34 description
=> "The returned list is restricted to objects where you have rights to modify permissions.",
38 additionalProperties
=> 0,
45 additionalProperties
=> 0,
47 propagate
=> get_standard_option
('acl-propagate'),
48 path
=> get_standard_option
('acl-path'),
49 type
=> { type
=> 'string', enum
=> ['user', 'group', 'token'] },
50 ugid
=> { type
=> 'string' },
51 roleid
=> { type
=> 'string' },
58 my $rpcenv = PVE
::RPCEnvironment
::get
();
59 my $authuser = $rpcenv->get_user();
62 my $usercfg = $rpcenv->{user_cfg
};
63 if (!$usercfg || !$usercfg->{acl_root
}) {
67 my $audit = $rpcenv->check($authuser, '/access', ['Sys.Audit'], 1);
69 my $root = $usercfg->{acl_root
};
70 PVE
::AccessControl
::iterate_acl_tree
("/", $root, sub {
71 my ($path, $node) = @_;
72 foreach my $type (qw(user group token)) {
73 my $d = $node->{"${type}s"};
75 next if !($audit || $rpcenv->check_perm_modify($authuser, $path, 1));
76 foreach my $id (keys %$d) {
77 foreach my $role (keys %{$d->{$id}}) {
78 my $propagate = $d->{$id}->{$role};
84 propagate
=> $propagate,
94 __PACKAGE__-
>register_method ({
100 check
=> ['perm-modify', '{path}'],
102 description
=> "Update Access Control List (add or remove permissions).",
104 additionalProperties
=> 0,
106 propagate
=> get_standard_option
('acl-propagate'),
107 path
=> get_standard_option
('acl-path'),
109 description
=> "List of users.",
110 type
=> 'string', format
=> 'pve-userid-list',
114 description
=> "List of groups.",
115 type
=> 'string', format
=> 'pve-groupid-list',
119 description
=> "List of API tokens.",
120 type
=> 'string', format
=> 'pve-tokenid-list',
124 description
=> "List of roles.",
125 type
=> 'string', format
=> 'pve-roleid-list',
128 description
=> "Remove permissions (instead of adding it).",
134 returns
=> { type
=> 'null' },
138 if (!($param->{users
} || $param->{groups
} || $param->{tokens
})) {
139 raise_param_exc
({ map { $_ => "either 'users', 'groups' or 'tokens' is required." } qw(users groups tokens) });
142 my $path = PVE
::AccessControl
::normalize_path
($param->{path
});
143 raise_param_exc
({ path
=> "invalid ACL path '$param->{path}'" }) if !$path;
145 if (!$param->{delete} && !PVE
::AccessControl
::check_path
($path)) {
146 raise_param_exc
({ path
=> "invalid ACL path '$param->{path}'" });
149 PVE
::AccessControl
::lock_user_config
(
152 my $cfg = cfs_read_file
("user.cfg");
156 if (defined($param->{propagate
})) {
157 $propagate = $param->{propagate
} ?
1 : 0;
160 my $node = PVE
::AccessControl
::find_acl_tree_node
($cfg->{acl_root
}, $path);
162 foreach my $role (split_list
($param->{roles
})) {
163 die "role '$role' does not exist\n"
164 if !$cfg->{roles
}->{$role};
166 foreach my $group (split_list
($param->{groups
})) {
168 die "group '$group' does not exist\n"
169 if !$cfg->{groups
}->{$group};
171 if ($param->{delete}) {
172 delete($node->{groups
}->{$group}->{$role});
174 $node->{groups
}->{$group}->{$role} = $propagate;
178 foreach my $userid (split_list
($param->{users
})) {
179 my $username = PVE
::AccessControl
::verify_username
($userid);
181 die "user '$username' does not exist\n"
182 if !$cfg->{users
}->{$username};
184 if ($param->{delete}) {
185 delete ($node->{users
}->{$username}->{$role});
187 $node->{users
}->{$username}->{$role} = $propagate;
191 foreach my $tokenid (split_list
($param->{tokens
})) {
192 my ($username, $token) = PVE
::AccessControl
::split_tokenid
($tokenid);
193 PVE
::AccessControl
::check_token_exist
($cfg, $username, $token);
195 if ($param->{delete}) {
196 delete $node->{tokens
}->{$tokenid}->{$role};
198 $node->{tokens
}->{$tokenid}->{$role} = $propagate;
203 cfs_write_file
("user.cfg", $cfg);
204 }, "ACL update failed");