]> git.proxmox.com Git - pve-access-control.git/blob - src/PVE/API2/Role.pm
bump version to 8.1.4
[pve-access-control.git] / src / PVE / API2 / Role.pm
1 package PVE::API2::Role;
2
3 use strict;
4 use warnings;
5
6 use PVE::AccessControl ();
7 use PVE::Cluster qw(cfs_read_file cfs_write_file);
8 use PVE::Exception qw(raise_param_exc);
9 use PVE::JSONSchema qw(get_standard_option register_standard_option);
10
11 use base qw(PVE::RESTHandler);
12
13 register_standard_option('role-id', {
14 type => 'string',
15 format => 'pve-roleid',
16 });
17 register_standard_option('role-privs', {
18 type => 'string' ,
19 format => 'pve-priv-list',
20 optional => 1,
21 });
22
23 __PACKAGE__->register_method ({
24 name => 'index',
25 path => '',
26 method => 'GET',
27 description => "Role index.",
28 permissions => {
29 user => 'all',
30 },
31 parameters => {
32 additionalProperties => 0,
33 properties => {},
34 },
35 returns => {
36 type => 'array',
37 items => {
38 type => "object",
39 properties => {
40 roleid => get_standard_option('role-id'),
41 privs => get_standard_option('role-privs'),
42 special => { type => 'boolean', optional => 1, default => 0 },
43 },
44 },
45 links => [ { rel => 'child', href => "{roleid}" } ],
46 },
47 code => sub {
48 my ($param) = @_;
49
50 my $res = [];
51
52 my $usercfg = cfs_read_file("user.cfg");
53
54 foreach my $role (keys %{$usercfg->{roles}}) {
55 my $privs = join(',', sort keys %{$usercfg->{roles}->{$role}});
56 push @$res, {
57 roleid => $role,
58 privs => $privs,
59 special => PVE::AccessControl::role_is_special($role),
60 };
61 }
62
63 return $res;
64 }});
65
66 __PACKAGE__->register_method ({
67 name => 'create_role',
68 protected => 1,
69 path => '',
70 method => 'POST',
71 permissions => {
72 check => ['perm', '/access', ['Sys.Modify']],
73 },
74 description => "Create new role.",
75 parameters => {
76 additionalProperties => 0,
77 properties => {
78 roleid => get_standard_option('role-id'),
79 privs => get_standard_option('role-privs'),
80 },
81 },
82 returns => { type => 'null' },
83 code => sub {
84 my ($param) = @_;
85
86 my $role = $param->{roleid};
87
88 if ($role =~ /^PVE/i) {
89 raise_param_exc({
90 roleid => "cannot use role ID starting with the (case-insensitive) 'PVE' namespace",
91 });
92 }
93
94 PVE::AccessControl::lock_user_config(sub {
95 my $usercfg = cfs_read_file("user.cfg");
96
97 die "role '$role' already exists\n" if $usercfg->{roles}->{$role};
98
99 $usercfg->{roles}->{$role} = {};
100
101 PVE::AccessControl::add_role_privs($role, $usercfg, $param->{privs});
102
103 cfs_write_file("user.cfg", $usercfg);
104 }, "create role failed");
105
106 return undef;
107 }});
108
109 __PACKAGE__->register_method ({
110 name => 'update_role',
111 protected => 1,
112 path => '{roleid}',
113 method => 'PUT',
114 permissions => {
115 check => ['perm', '/access', ['Sys.Modify']],
116 },
117 description => "Update an existing role.",
118 parameters => {
119 additionalProperties => 0,
120 properties => {
121 roleid => get_standard_option('role-id'),
122 privs => get_standard_option('role-privs'),
123 append => { type => 'boolean', optional => 1, requires => 'privs' },
124 },
125 },
126 returns => { type => 'null' },
127 code => sub {
128 my ($param) = @_;
129
130 my $role = $param->{roleid};
131
132 die "auto-generated role '$role' cannot be modified\n"
133 if PVE::AccessControl::role_is_special($role);
134
135 PVE::AccessControl::lock_user_config(sub {
136 my $usercfg = cfs_read_file("user.cfg");
137
138 die "role '$role' does not exist\n" if !$usercfg->{roles}->{$role};
139
140 $usercfg->{roles}->{$role} = {} if !$param->{append};
141
142 PVE::AccessControl::add_role_privs($role, $usercfg, $param->{privs});
143
144 cfs_write_file("user.cfg", $usercfg);
145 }, "update role failed");
146
147 return undef;
148 }});
149
150 __PACKAGE__->register_method ({
151 name => 'read_role',
152 path => '{roleid}',
153 method => 'GET',
154 permissions => {
155 user => 'all',
156 },
157 description => "Get role configuration.",
158 parameters => {
159 additionalProperties => 0,
160 properties => {
161 roleid => get_standard_option('role-id'),
162 },
163 },
164 returns => {
165 type => "object",
166 additionalProperties => 0,
167 properties => PVE::AccessControl::create_priv_properties(),
168 },
169 code => sub {
170 my ($param) = @_;
171
172 my $usercfg = cfs_read_file("user.cfg");
173
174 my $role = $param->{roleid};
175
176 my $data = $usercfg->{roles}->{$role};
177
178 die "role '$role' does not exist\n" if !$data;
179
180 return $data;
181 }
182 });
183
184 __PACKAGE__->register_method ({
185 name => 'delete_role',
186 protected => 1,
187 path => '{roleid}',
188 method => 'DELETE',
189 permissions => {
190 check => ['perm', '/access', ['Sys.Modify']],
191 },
192 description => "Delete role.",
193 parameters => {
194 additionalProperties => 0,
195 properties => {
196 roleid => get_standard_option('role-id'),
197 },
198 },
199 returns => { type => 'null' },
200 code => sub {
201 my ($param) = @_;
202
203 my $role = $param->{roleid};
204
205 die "auto-generated role '$role' cannot be deleted\n"
206 if PVE::AccessControl::role_is_special($role);
207
208 PVE::AccessControl::lock_user_config(sub {
209 my $usercfg = cfs_read_file("user.cfg");
210
211 die "role '$role' does not exist\n" if !$usercfg->{roles}->{$role};
212
213 delete ($usercfg->{roles}->{$role});
214
215 # fixme: delete role from acl?
216
217 cfs_write_file("user.cfg", $usercfg);
218 }, "delete role failed");
219
220 return undef;
221 }
222 });
223
224 1;