]>
Commit | Line | Data |
---|---|---|
2c3a6c0a DM |
1 | package PVE::API2::Role; |
2 | ||
3 | use strict; | |
4 | use warnings; | |
2c3a6c0a | 5 | |
d6fb84bf TL |
6 | use PVE::AccessControl (); |
7 | use PVE::Cluster qw(cfs_read_file cfs_write_file); | |
00b90e71 | 8 | use PVE::Exception qw(raise_param_exc); |
d6fb84bf | 9 | use PVE::JSONSchema qw(get_standard_option register_standard_option); |
2c3a6c0a DM |
10 | |
11 | use base qw(PVE::RESTHandler); | |
12 | ||
3a5ae7a0 SI |
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', | |
af5d7da7 | 20 | optional => 1, |
3a5ae7a0 SI |
21 | }); |
22 | ||
2c3a6c0a | 23 | __PACKAGE__->register_method ({ |
0a6e09fd PA |
24 | name => 'index', |
25 | path => '', | |
2c3a6c0a DM |
26 | method => 'GET', |
27 | description => "Role index.", | |
0a6e09fd | 28 | permissions => { |
82b63965 | 29 | user => 'all', |
96919234 | 30 | }, |
2c3a6c0a DM |
31 | parameters => { |
32 | additionalProperties => 0, | |
33 | properties => {}, | |
34 | }, | |
35 | returns => { | |
36 | type => 'array', | |
37 | items => { | |
38 | type => "object", | |
39 | properties => { | |
3a5ae7a0 SI |
40 | roleid => get_standard_option('role-id'), |
41 | privs => get_standard_option('role-privs'), | |
af5d7da7 | 42 | special => { type => 'boolean', optional => 1, default => 0 }, |
2c3a6c0a DM |
43 | }, |
44 | }, | |
45 | links => [ { rel => 'child', href => "{roleid}" } ], | |
46 | }, | |
47 | code => sub { | |
48 | my ($param) = @_; | |
0a6e09fd | 49 | |
2c3a6c0a DM |
50 | my $res = []; |
51 | ||
52 | my $usercfg = cfs_read_file("user.cfg"); | |
0a6e09fd | 53 | |
2c3a6c0a DM |
54 | foreach my $role (keys %{$usercfg->{roles}}) { |
55 | my $privs = join(',', sort keys %{$usercfg->{roles}->{$role}}); | |
186a4e15 WB |
56 | push @$res, { |
57 | roleid => $role, | |
58 | privs => $privs, | |
59 | special => PVE::AccessControl::role_is_special($role), | |
60 | }; | |
2c3a6c0a DM |
61 | } |
62 | ||
63 | return $res; | |
0a6e09fd | 64 | }}); |
2c3a6c0a DM |
65 | |
66 | __PACKAGE__->register_method ({ | |
0a6e09fd | 67 | name => 'create_role', |
2c3a6c0a | 68 | protected => 1, |
0a6e09fd | 69 | path => '', |
2c3a6c0a | 70 | method => 'POST', |
0a6e09fd | 71 | permissions => { |
96919234 DM |
72 | check => ['perm', '/access', ['Sys.Modify']], |
73 | }, | |
2c3a6c0a DM |
74 | description => "Create new role.", |
75 | parameters => { | |
0a6e09fd | 76 | additionalProperties => 0, |
2c3a6c0a | 77 | properties => { |
3a5ae7a0 SI |
78 | roleid => get_standard_option('role-id'), |
79 | privs => get_standard_option('role-privs'), | |
2c3a6c0a DM |
80 | }, |
81 | }, | |
82 | returns => { type => 'null' }, | |
83 | code => sub { | |
84 | my ($param) = @_; | |
85 | ||
00b90e71 TL |
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 | ||
43aa2489 TL |
94 | PVE::AccessControl::lock_user_config(sub { |
95 | my $usercfg = cfs_read_file("user.cfg"); | |
0a6e09fd | 96 | |
43aa2489 | 97 | die "role '$role' already exists\n" if $usercfg->{roles}->{$role}; |
2c3a6c0a | 98 | |
43aa2489 | 99 | $usercfg->{roles}->{$role} = {}; |
2c3a6c0a | 100 | |
43aa2489 | 101 | PVE::AccessControl::add_role_privs($role, $usercfg, $param->{privs}); |
2c3a6c0a | 102 | |
43aa2489 TL |
103 | cfs_write_file("user.cfg", $usercfg); |
104 | }, "create role failed"); | |
2c3a6c0a DM |
105 | |
106 | return undef; | |
0a6e09fd | 107 | }}); |
2c3a6c0a DM |
108 | |
109 | __PACKAGE__->register_method ({ | |
0a6e09fd | 110 | name => 'update_role', |
2c3a6c0a | 111 | protected => 1, |
0a6e09fd | 112 | path => '{roleid}', |
2c3a6c0a | 113 | method => 'PUT', |
0a6e09fd | 114 | permissions => { |
96919234 DM |
115 | check => ['perm', '/access', ['Sys.Modify']], |
116 | }, | |
3a5ae7a0 | 117 | description => "Update an existing role.", |
2c3a6c0a | 118 | parameters => { |
0a6e09fd | 119 | additionalProperties => 0, |
2c3a6c0a | 120 | properties => { |
3a5ae7a0 SI |
121 | roleid => get_standard_option('role-id'), |
122 | privs => get_standard_option('role-privs'), | |
123 | append => { type => 'boolean', optional => 1, requires => 'privs' }, | |
2c3a6c0a DM |
124 | }, |
125 | }, | |
126 | returns => { type => 'null' }, | |
127 | code => sub { | |
128 | my ($param) = @_; | |
129 | ||
deb63acf DC |
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 | ||
43aa2489 TL |
135 | PVE::AccessControl::lock_user_config(sub { |
136 | my $usercfg = cfs_read_file("user.cfg"); | |
0a6e09fd | 137 | |
43aa2489 | 138 | die "role '$role' does not exist\n" if !$usercfg->{roles}->{$role}; |
2c3a6c0a | 139 | |
43aa2489 | 140 | $usercfg->{roles}->{$role} = {} if !$param->{append}; |
2c3a6c0a | 141 | |
43aa2489 | 142 | PVE::AccessControl::add_role_privs($role, $usercfg, $param->{privs}); |
2c3a6c0a | 143 | |
43aa2489 TL |
144 | cfs_write_file("user.cfg", $usercfg); |
145 | }, "update role failed"); | |
2c3a6c0a DM |
146 | |
147 | return undef; | |
0a6e09fd | 148 | }}); |
2c3a6c0a | 149 | |
2c3a6c0a | 150 | __PACKAGE__->register_method ({ |
0a6e09fd PA |
151 | name => 'read_role', |
152 | path => '{roleid}', | |
2c3a6c0a | 153 | method => 'GET', |
0a6e09fd | 154 | permissions => { |
82b63965 | 155 | user => 'all', |
96919234 | 156 | }, |
2c3a6c0a DM |
157 | description => "Get role configuration.", |
158 | parameters => { | |
0a6e09fd | 159 | additionalProperties => 0, |
2c3a6c0a | 160 | properties => { |
3a5ae7a0 SI |
161 | roleid => get_standard_option('role-id'), |
162 | }, | |
163 | }, | |
164 | returns => { | |
165 | type => "object", | |
166 | additionalProperties => 0, | |
0fea3f16 | 167 | properties => PVE::AccessControl::create_priv_properties(), |
2c3a6c0a | 168 | }, |
2c3a6c0a DM |
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; | |
3a5ae7a0 SI |
181 | } |
182 | }); | |
2c3a6c0a DM |
183 | |
184 | __PACKAGE__->register_method ({ | |
0a6e09fd | 185 | name => 'delete_role', |
2c3a6c0a | 186 | protected => 1, |
0a6e09fd | 187 | path => '{roleid}', |
2c3a6c0a | 188 | method => 'DELETE', |
0a6e09fd | 189 | permissions => { |
96919234 DM |
190 | check => ['perm', '/access', ['Sys.Modify']], |
191 | }, | |
2c3a6c0a DM |
192 | description => "Delete role.", |
193 | parameters => { | |
0a6e09fd | 194 | additionalProperties => 0, |
2c3a6c0a | 195 | properties => { |
3a5ae7a0 SI |
196 | roleid => get_standard_option('role-id'), |
197 | }, | |
2c3a6c0a DM |
198 | }, |
199 | returns => { type => 'null' }, | |
200 | code => sub { | |
201 | my ($param) = @_; | |
202 | ||
e41cc73c | 203 | my $role = $param->{roleid}; |
2c3a6c0a | 204 | |
e41cc73c WB |
205 | die "auto-generated role '$role' cannot be deleted\n" |
206 | if PVE::AccessControl::role_is_special($role); | |
2c3a6c0a | 207 | |
43aa2489 TL |
208 | PVE::AccessControl::lock_user_config(sub { |
209 | my $usercfg = cfs_read_file("user.cfg"); | |
2c3a6c0a | 210 | |
43aa2489 | 211 | die "role '$role' does not exist\n" if !$usercfg->{roles}->{$role}; |
0a6e09fd | 212 | |
43aa2489 | 213 | delete ($usercfg->{roles}->{$role}); |
2c3a6c0a | 214 | |
43aa2489 | 215 | # fixme: delete role from acl? |
2c3a6c0a | 216 | |
43aa2489 TL |
217 | cfs_write_file("user.cfg", $usercfg); |
218 | }, "delete role failed"); | |
0a6e09fd | 219 | |
2c3a6c0a | 220 | return undef; |
3a5ae7a0 SI |
221 | } |
222 | }); | |
2c3a6c0a DM |
223 | |
224 | 1; |