rename user_enabled to check_user_enabled
[pve-access-control.git] / PVE / API2 / AccessControl.pm
CommitLineData
2c3a6c0a
DM
1package PVE::API2::AccessControl;
2
3use strict;
4use warnings;
5
6use PVE::SafeSyslog;
7use PVE::RPCEnvironment;
a427cecb 8use PVE::Cluster qw(cfs_read_file);
2c3a6c0a
DM
9use PVE::RESTHandler;
10use PVE::AccessControl;
11use PVE::JSONSchema qw(get_standard_option);
12use PVE::API2::Domains;
13use PVE::API2::User;
14use PVE::API2::Group;
15use PVE::API2::Role;
16use PVE::API2::ACL;
17
18use base qw(PVE::RESTHandler);
19
20__PACKAGE__->register_method ({
21 subclass => "PVE::API2::User",
22 path => 'users',
23});
24
25__PACKAGE__->register_method ({
26 subclass => "PVE::API2::Group",
27 path => 'groups',
28});
29
30__PACKAGE__->register_method ({
31 subclass => "PVE::API2::Role",
32 path => 'roles',
33});
34
35__PACKAGE__->register_method ({
36 subclass => "PVE::API2::ACL",
37 path => 'acl',
38});
39
40__PACKAGE__->register_method ({
41 subclass => "PVE::API2::Domains",
42 path => 'domains',
43});
44
45__PACKAGE__->register_method ({
46 name => 'index',
47 path => '',
48 method => 'GET',
49 description => "Directory index.",
50 parameters => {
51 additionalProperties => 0,
52 properties => {},
53 },
54 returns => {
55 type => 'array',
56 items => {
57 type => "object",
58 properties => {
59 subdir => { type => 'string' },
60 },
61 },
62 links => [ { rel => 'child', href => "{subdir}" } ],
63 },
64 code => sub {
65 my ($param) = @_;
66
67 my $res = [];
68
69 my $ma = __PACKAGE__->method_attributes();
70
71 foreach my $info (@$ma) {
72 next if !$info->{subclass};
73
74 my $subpath = $info->{match_re}->[0];
75
76 push @$res, { subdir => $subpath };
77 }
78
79 push @$res, { subdir => 'ticket' };
80
81 return $res;
82 }});
83
84__PACKAGE__->register_method ({
85 name => 'create_ticket',
86 path => 'ticket',
87 method => 'POST',
88 permissions => { user => 'world' },
89 protected => 1, # else we can't access shadow files
90 description => "Create authentication ticket.",
91 parameters => {
92 additionalProperties => 0,
93 properties => {
94 username => {
95 description => "User name",
96 type => 'string',
97 maxLength => 64,
98 },
99 realm => get_standard_option('realm', {
100 description => "You can optionally pass the realm using this parameter. Normally the realm is simply added to the username <username>\@<relam>.",
101 optional => 1}),
102 password => {
103 description => "The secret password. This can also be a valid ticket.",
104 type => 'string',
105 },
106 path => {
107 description => "Only create ticket if user have access 'privs' on 'path'",
108 type => 'string',
109 requires => 'privs',
110 optional => 1,
111 maxLength => 64,
112 },
113 privs => {
114 description => "Only create ticket if user have access 'privs' on 'path'",
115 type => 'string' , format => 'pve-priv-list',
116 requires => 'path',
117 optional => 1,
118 maxLength => 64,
119 },
120 }
121 },
122 returns => {
123 type => "object",
124 properties => {
125 ticket => { type => 'string' },
126 username => { type => 'string' },
127 CSRFPreventionToken => { type => 'string' },
128 }
129 },
130 code => sub {
131 my ($param) = @_;
132
133 my $username = $param->{username};
134 $username .= "\@$param->{realm}" if $param->{realm};
135
136 my $rpcenv = PVE::RPCEnvironment::get();
137 my $clientip = $rpcenv->get_client_ip() || '';
138
139 my $ticket;
140 my $token;
141 eval {
142
7070c1ae
DM
143 # test if user exists and is enabled
144 $rpcenv->check_user_enabled($username);
145
2c3a6c0a
DM
146 if ($param->{path} && $param->{privs}) {
147 my $privs = [ PVE::Tools::split_list($param->{privs}) ];
148 my $path = PVE::AccessControl::normalize_path($param->{path});
149 if (!($path && scalar(@$privs) && $rpcenv->check($username, $path, $privs))) {
150 die "no permission ($param->{path}, $param->{privs})\n";
151 }
152 }
153
154 my $tmp;
155 if (($tmp = PVE::AccessControl::verify_ticket($param->{password}, 1)) &&
d8a56966 156 ($tmp eq 'root@pam' || $tmp eq $username)) {
2c3a6c0a 157 # got valid ticket
d8a56966 158 # Note: root@pam can create tickets for other users
66b7e98d 159
2c3a6c0a
DM
160 } else {
161 $username = PVE::AccessControl::authenticate_user($username, $param->{password});
162 }
163 $ticket = PVE::AccessControl::assemble_ticket($username);
164 $token = PVE::AccessControl::assemble_csrf_prevention_token($username);
165 };
166 if (my $err = $@) {
167 syslog('err', "authentication failure; rhost=$clientip user=$username msg=$err");
168 die $err;
169 }
170
171 PVE::Cluster::log_msg('info', 'root@pam', "successful auth for user '$username'");
172
173 return {
174 ticket => $ticket,
175 username => $username,
176 CSRFPreventionToken => $token,
177 };
178 }});
179
1801;