allow dots in access paths
[pve-access-control.git] / PVE / API2 / Domains.pm
1 package PVE::API2::Domains;
2
3 use strict;
4 use warnings;
5 use PVE::Tools qw(extract_param);
6 use PVE::Cluster qw (cfs_read_file cfs_write_file);
7 use PVE::AccessControl;
8 use PVE::JSONSchema qw(get_standard_option);
9
10 use PVE::SafeSyslog;
11 use PVE::RESTHandler;
12 use PVE::Auth::Plugin;
13
14 my $domainconfigfile = "domains.cfg";
15
16 use base qw(PVE::RESTHandler);
17
18 __PACKAGE__->register_method ({
19     name => 'index', 
20     path => '', 
21     method => 'GET',
22     description => "Authentication domain index.",
23     permissions => { 
24         description => "Anyone can access that, because we need that list for the login box (before the user is authenticated).",
25         user => 'world', 
26     },
27     parameters => {
28         additionalProperties => 0,
29         properties => {},
30     },
31     returns => {
32         type => 'array',
33         items => {
34             type => "object",
35             properties => {
36                 realm => { type => 'string' },
37                 comment => { type => 'string', optional => 1 },
38             },
39         },
40         links => [ { rel => 'child', href => "{realm}" } ],
41     },
42     code => sub {
43         my ($param) = @_;
44     
45         my $res = [];
46
47         my $cfg = cfs_read_file($domainconfigfile);
48         my $ids = $cfg->{ids};
49
50         foreach my $realm (keys %$ids) {
51             my $d = $ids->{$realm};
52             my $entry = { realm => $realm, type => $d->{type} };
53             $entry->{comment} = $d->{comment} if $d->{comment};
54             $entry->{default} = 1 if $d->{default};
55             push @$res, $entry;
56         }
57
58         return $res;
59     }});
60
61 __PACKAGE__->register_method ({
62     name => 'create', 
63     protected => 1,
64     path => '', 
65     method => 'POST',
66     permissions => { 
67         check => ['perm', '/access/realm', ['Realm.Allocate']],
68     },
69     description => "Add an authentication server.",
70     parameters => PVE::Auth::Plugin->createSchema(),
71     returns => { type => 'null' },
72     code => sub {
73         my ($param) = @_;
74
75         PVE::Auth::Plugin::lock_domain_config(
76             sub {
77                         
78                 my $cfg = cfs_read_file($domainconfigfile);
79                 my $ids = $cfg->{ids};
80
81                 my $realm = extract_param($param, 'realm');
82                 my $type = $param->{type};
83         
84                 die "domain '$realm' already exists\n" 
85                     if $ids->{$realm};
86
87                 die "unable to use reserved name '$realm'\n"
88                     if ($realm eq 'pam' || $realm eq 'pve');
89
90                 die "unable to create builtin type '$type'\n"
91                     if ($type eq 'pam' || $type eq 'pve');
92
93                 my $plugin = PVE::Auth::Plugin->lookup($type);
94                 my $config = $plugin->check_config($realm, $param, 1, 1);
95
96                 if ($config->{default}) {
97                     foreach my $r (keys %$ids) {
98                         delete $ids->{$r}->{default};
99                     }
100                 }
101
102                 $ids->{$realm} = $config;
103
104                 cfs_write_file($domainconfigfile, $cfg);
105             }, "add auth server failed");
106
107         return undef;
108     }});
109
110 __PACKAGE__->register_method ({
111     name => 'update', 
112     path => '{realm}', 
113     method => 'PUT',
114     permissions => { 
115         check => ['perm', '/access/realm', ['Realm.Allocate']],
116     },
117     description => "Update authentication server settings.",
118     protected => 1,
119     parameters => PVE::Auth::Plugin->updateSchema(),
120     returns => { type => 'null' },
121     code => sub {
122         my ($param) = @_;
123
124         PVE::Auth::Plugin::lock_domain_config(
125             sub {
126                         
127                 my $cfg = cfs_read_file($domainconfigfile);
128                 my $ids = $cfg->{ids};
129
130                 my $digest = extract_param($param, 'digest');
131                 PVE::SectionConfig::assert_if_modified($cfg, $digest);
132
133                 my $realm = extract_param($param, 'realm');
134
135                 die "unable to modify bultin domain '$realm'\n"
136                     if ($realm eq 'pam' || $realm eq 'pve');
137
138                 die "domain '$realm' does not exist\n" 
139                     if !$ids->{$realm};
140
141                 my $delete_str = extract_param($param, 'delete');
142                 die "no options specified\n" if !$delete_str && !scalar(keys %$param);
143
144                 foreach my $opt (PVE::Tools::split_list($delete_str)) {
145                     delete $ids->{$realm}->{$opt};
146                 }
147         
148                 my $plugin = PVE::Auth::Plugin->lookup($ids->{$realm}->{type});
149                 my $config = $plugin->check_config($realm, $param, 0, 1);
150
151                 if ($config->{default}) {
152                     foreach my $r (keys %$ids) {
153                         delete $ids->{$r}->{default};
154                     }
155                 }
156
157                 foreach my $p (keys %$config) {
158                     $ids->{$realm}->{$p} = $config->{$p};
159                 }
160
161                 cfs_write_file($domainconfigfile, $cfg);
162             }, "update auth server failed");
163
164         return undef;
165     }});
166
167 # fixme: return format!
168 __PACKAGE__->register_method ({
169     name => 'read', 
170     path => '{realm}', 
171     method => 'GET',
172     description => "Get auth server configuration.",
173     permissions => { 
174         check => ['perm', '/access/realm', ['Realm.Allocate', 'Sys.Audit'], any => 1],
175     },
176     parameters => {
177         additionalProperties => 0,
178         properties => {
179             realm =>  get_standard_option('realm'),
180         },
181     },
182     returns => {},
183     code => sub {
184         my ($param) = @_;
185
186         my $cfg = cfs_read_file($domainconfigfile);
187
188         my $realm = $param->{realm};
189         
190         my $data = $cfg->{ids}->{$realm};
191         die "domain '$realm' does not exist\n" if !$data;
192
193         $data->{digest} = $cfg->{digest};
194
195         return $data;
196     }});
197
198
199 __PACKAGE__->register_method ({
200     name => 'delete', 
201     path => '{realm}', 
202     method => 'DELETE',
203     permissions => { 
204         check => ['perm', '/access/realm', ['Realm.Allocate']],
205     },
206     description => "Delete an authentication server.",
207     protected => 1,
208     parameters => {
209         additionalProperties => 0,
210         properties => {
211             realm =>  get_standard_option('realm'),
212         }
213     },
214     returns => { type => 'null' },
215     code => sub {
216         my ($param) = @_;
217
218         PVE::Auth::Plugin::lock_domain_config(
219             sub {
220
221                 my $cfg = cfs_read_file($domainconfigfile);
222                 my $ids = $cfg->{ids};
223
224                 my $realm = $param->{realm};
225         
226                 die "domain '$realm' does not exist\n" if !$ids->{$realm};
227
228                 delete $ids->{$realm};
229
230                 cfs_write_file($domainconfigfile, $cfg);
231             }, "delete auth server failed");
232         
233         return undef;
234     }});
235
236 1;