always pass cluster_conf to load_vmfw_conf
[pve-firewall.git] / src / PVE / API2 / Firewall / Aliases.pm
1 package PVE::API2::Firewall::AliasesBase;
2
3 use strict;
4 use warnings;
5 use PVE::Exception qw(raise raise_param_exc);
6 use PVE::JSONSchema qw(get_standard_option);
7
8 use PVE::Firewall;
9
10 use base qw(PVE::RESTHandler);
11
12 my $api_properties = { 
13     cidr => {
14         description => "Network/IP specification in CIDR format.",
15         type => 'string', format => 'IPv4orCIDR',
16     },
17     name => get_standard_option('pve-fw-alias'),
18     rename => get_standard_option('pve-fw-alias', {
19         description => "Rename an existing alias.",
20         optional => 1,
21     }),
22     comment => {
23         type => 'string',
24         optional => 1,
25     },
26 };
27
28 sub load_config {
29     my ($class, $param) = @_;
30
31     die "implement this in subclass";
32
33     #return ($fw_conf, $rules);
34 }
35
36 sub save_aliases {
37     my ($class, $param, $fw_conf, $aliases) = @_;
38
39     die "implement this in subclass";
40 }
41
42 my $additional_param_hash = {};
43
44 sub additional_parameters {
45     my ($class, $new_value) = @_;
46
47     if (defined($new_value)) {
48         $additional_param_hash->{$class} = $new_value;
49     }
50
51     # return a copy
52     my $copy = {};
53     my $org = $additional_param_hash->{$class} || {};
54     foreach my $p (keys %$org) { $copy->{$p} = $org->{$p}; }
55     return $copy;
56 }
57
58 my $aliases_to_list = sub {
59     my ($aliases) = @_;
60
61     my $list = [];
62     foreach my $k (sort keys %$aliases) {
63         push @$list, $aliases->{$k};
64     }
65     return $list;
66 };
67
68 sub register_get_aliases {
69     my ($class) = @_;
70
71     my $properties = $class->additional_parameters();
72
73     $class->register_method({
74         name => 'get_aliases',
75         path => '',
76         method => 'GET',
77         description => "List aliases",
78         parameters => {
79             additionalProperties => 0,
80             properties => $properties,
81         },
82         returns => {
83             type => 'array',
84             items => {
85                 type => "object",
86                 properties => {
87                     name => { type => 'string' },
88                     cidr => { type => 'string' },
89                     comment => {
90                         type => 'string',
91                         optional => 1,
92                     },
93                     digest => get_standard_option('pve-config-digest', { optional => 0} ),      
94                 },
95             },
96             links => [ { rel => 'child', href => "{name}" } ],
97         },
98         code => sub {
99             my ($param) = @_;
100
101             my ($fw_conf, $aliases) = $class->load_config($param);
102
103             my $list = &$aliases_to_list($aliases);
104
105             return PVE::Firewall::copy_list_with_digest($list);
106         }});
107 }
108
109 sub register_create_alias {
110     my ($class) = @_;
111
112     my $properties = $class->additional_parameters();
113
114     $properties->{name} = $api_properties->{name};
115     $properties->{cidr} = $api_properties->{cidr};
116     $properties->{comment} = $api_properties->{comment};
117
118     $class->register_method({
119         name => 'create_alias',
120         path => '',
121         method => 'POST',
122         description => "Create IP or Network Alias.",
123         protected => 1,
124         parameters => {
125             additionalProperties => 0,
126             properties => $properties,
127         },
128         returns => { type => "null" },
129         code => sub {
130             my ($param) = @_;
131
132             my ($fw_conf, $aliases) = $class->load_config($param);
133
134             my $name = lc($param->{name});
135             
136             raise_param_exc({ name => "alias '$param->{name}' already exists" }) 
137                 if defined($aliases->{$name});
138             
139             my $data = { name => $param->{name}, cidr => $param->{cidr} };
140             $data->{comment} = $param->{comment} if $param->{comment};
141
142             $aliases->{$name} = $data;
143
144             $class->save_aliases($param, $fw_conf, $aliases);
145
146             return undef;
147         }});
148 }
149
150 sub register_read_alias {
151     my ($class) = @_;
152
153     my $properties = $class->additional_parameters();
154
155     $properties->{name} = $api_properties->{name};
156     
157     $class->register_method({
158         name => 'read_alias',
159         path => '{name}',
160         method => 'GET',
161         description => "Read alias.",
162         parameters => {
163             additionalProperties => 0,
164             properties => $properties,
165         },
166         returns => { type => "object" },
167         code => sub {
168             my ($param) = @_;
169
170             my ($fw_conf, $aliases) = $class->load_config($param);
171
172             my $name = lc($param->{name});
173
174             raise_param_exc({ name => "no such alias" })
175                 if !defined($aliases->{$name});
176
177             return $aliases->{$name};
178         }});
179 }
180
181 sub register_update_alias {
182     my ($class) = @_;
183
184     my $properties = $class->additional_parameters();
185
186     $properties->{name} = $api_properties->{name};
187     $properties->{rename} = $api_properties->{rename};
188     $properties->{cidr} = $api_properties->{cidr};
189     $properties->{comment} = $api_properties->{comment};
190     $properties->{digest} = get_standard_option('pve-config-digest');
191
192     $class->register_method({
193         name => 'update_alias',
194         path => '{name}',
195         method => 'PUT',
196         description => "Update IP or Network alias.",
197         protected => 1,
198         parameters => {
199             additionalProperties => 0,
200             properties => $properties,
201         },
202         returns => { type => "null" },
203         code => sub {
204             my ($param) = @_;
205
206             my ($fw_conf, $aliases) = $class->load_config($param);
207
208             my $list = &$aliases_to_list($aliases);
209
210             my (undef, $digest) = PVE::Firewall::copy_list_with_digest($list);
211
212             PVE::Tools::assert_if_modified($digest, $param->{digest});
213
214             my $name = lc($param->{name});
215
216             raise_param_exc({ name => "no such alias" }) if !$aliases->{$name};
217
218             my $data = { name => $param->{name}, cidr => $param->{cidr} };
219             $data->{comment} = $param->{comment} if $param->{comment};
220
221             $aliases->{$name} = $data;
222
223             my $rename = lc($param->{rename});
224
225             if ($rename && ($name ne $rename)) {
226                 raise_param_exc({ name => "alias '$param->{rename}' already exists" }) 
227                     if defined($aliases->{$rename});
228                 $aliases->{$name}->{name} = $param->{rename};
229                 $aliases->{$rename} = $aliases->{$name};
230                 delete $aliases->{$name};
231             }
232
233             $class->save_aliases($param, $fw_conf, $aliases);
234
235             return undef;
236         }});
237 }
238
239 sub register_delete_alias {
240     my ($class) = @_;
241
242     my $properties = $class->additional_parameters();
243
244     $properties->{name} = $api_properties->{name};
245     $properties->{digest} = get_standard_option('pve-config-digest');
246
247     $class->register_method({
248         name => 'remove_alias',
249         path => '{name}',
250         method => 'DELETE',
251         description => "Remove IP or Network alias.",
252         protected => 1,
253         parameters => {
254             additionalProperties => 0,
255             properties => $properties,
256         },
257         returns => { type => "null" },
258         code => sub {
259             my ($param) = @_;
260
261             my ($fw_conf, $aliases) = $class->load_config($param);
262
263             my $list = &$aliases_to_list($aliases);
264             my (undef, $digest) = PVE::Firewall::copy_list_with_digest($list);
265             PVE::Tools::assert_if_modified($digest, $param->{digest});
266
267             my $name = lc($param->{name});
268             delete $aliases->{$name};
269
270             $class->save_aliases($param, $fw_conf, $aliases);
271             
272             return undef;
273         }});
274 }
275
276 sub register_handlers {
277     my ($class) = @_;
278
279     $class->register_get_aliases();
280     $class->register_create_alias();
281     $class->register_read_alias();
282     $class->register_update_alias();
283     $class->register_delete_alias();
284 }
285
286 package PVE::API2::Firewall::ClusterAliases;
287
288 use strict;
289 use warnings;
290
291 use base qw(PVE::API2::Firewall::AliasesBase);
292
293 sub load_config {
294     my ($class, $param) = @_;
295
296     my $fw_conf = PVE::Firewall::load_clusterfw_conf();
297     my $aliases = $fw_conf->{aliases};
298
299     return ($fw_conf, $aliases);
300 }
301
302 sub save_aliases {
303     my ($class, $param, $fw_conf, $aliases) = @_;
304
305     $fw_conf->{aliases} = $aliases;
306     PVE::Firewall::save_clusterfw_conf($fw_conf);
307 }
308
309 __PACKAGE__->register_handlers();
310
311 package PVE::API2::Firewall::VMAliases;
312
313 use strict;
314 use warnings;
315 use PVE::JSONSchema qw(get_standard_option);
316
317 use base qw(PVE::API2::Firewall::AliasesBase);
318
319 __PACKAGE__->additional_parameters({ 
320     node => get_standard_option('pve-node'),
321     vmid => get_standard_option('pve-vmid'),                               
322 });
323
324 sub load_config {
325     my ($class, $param) = @_;
326
327     my $cluster_conf = PVE::Firewall::load_clusterfw_conf();
328     my $fw_conf = PVE::Firewall::load_vmfw_conf($cluster_conf, 'vm', $param->{vmid});
329     my $aliases = $fw_conf->{aliases};
330
331     return ($fw_conf, $aliases);
332 }
333
334 sub save_aliases {
335     my ($class, $param, $fw_conf, $aliases) = @_;
336
337     $fw_conf->{aliases} = $aliases;
338     PVE::Firewall::save_vmfw_conf($param->{vmid}, $fw_conf);
339 }
340
341 __PACKAGE__->register_handlers();
342
343 package PVE::API2::Firewall::CTAliases;
344
345 use strict;
346 use warnings;
347 use PVE::JSONSchema qw(get_standard_option);
348
349 use base qw(PVE::API2::Firewall::AliasesBase);
350
351 __PACKAGE__->additional_parameters({ 
352     node => get_standard_option('pve-node'),
353     vmid => get_standard_option('pve-vmid'),                               
354 });
355
356 sub load_config {
357     my ($class, $param) = @_;
358
359     my $cluster_conf = PVE::Firewall::load_clusterfw_conf();
360     my $fw_conf = PVE::Firewall::load_vmfw_conf($cluster_conf, 'ct', $param->{vmid});
361     my $aliases = $fw_conf->{aliases};
362
363     return ($fw_conf, $aliases);
364 }
365
366 sub save_aliases {
367     my ($class, $param, $fw_conf, $aliases) = @_;
368
369     $fw_conf->{aliases} = $aliases;
370     PVE::Firewall::save_vmfw_conf($param->{vmid}, $fw_conf);
371 }
372
373 __PACKAGE__->register_handlers();
374
375 1;