]> git.proxmox.com Git - pve-access-control.git/blame - src/PVE/API2/Role.pm
api: roles: forbid creatin new roles starting with "PVE" namespace
[pve-access-control.git] / src / PVE / API2 / Role.pm
CommitLineData
2c3a6c0a
DM
1package PVE::API2::Role;
2
3use strict;
4use warnings;
2c3a6c0a 5
d6fb84bf
TL
6use PVE::AccessControl ();
7use PVE::Cluster qw(cfs_read_file cfs_write_file);
00b90e71 8use PVE::Exception qw(raise_param_exc);
d6fb84bf 9use PVE::JSONSchema qw(get_standard_option register_standard_option);
2c3a6c0a
DM
10
11use base qw(PVE::RESTHandler);
12
3a5ae7a0
SI
13register_standard_option('role-id', {
14 type => 'string',
15 format => 'pve-roleid',
16});
17register_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
2241;