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