]> git.proxmox.com Git - pve-firewall.git/blame - src/PVE/API2/Firewall/Rules.pm
implement delete parameter for rule update API
[pve-firewall.git] / src / PVE / API2 / Firewall / Rules.pm
CommitLineData
86791289
DM
1package PVE::API2::Firewall::RulesBase;
2
3use strict;
4use warnings;
5use PVE::JSONSchema qw(get_standard_option);
6
7use PVE::Firewall;
8
9use base qw(PVE::RESTHandler);
10
11my $api_properties = {
86791289
DM
12 pos => {
13 description => "Rule position.",
14 type => 'integer',
15 minimum => 0,
16 },
17};
18
19sub load_config {
20 my ($class, $param) = @_;
21
22 die "implement this in subclass";
23
24 #return ($fw_conf, $rules);
25}
26
27sub save_rules {
28 my ($class, $param, $fw_conf, $rules) = @_;
29
30 die "implement this in subclass";
31}
32
63c91681 33my $additional_param_hash = {};
86791289 34
63c91681 35sub additional_parameters {
86791289
DM
36 my ($class, $new_value) = @_;
37
63c91681
DM
38 if (defined($new_value)) {
39 $additional_param_hash->{$class} = $new_value;
40 }
86791289 41
63c91681
DM
42 # return a copy
43 my $copy = {};
44 my $org = $additional_param_hash->{$class} || {};
45 foreach my $p (keys %$org) { $copy->{$p} = $org->{$p}; }
46 return $copy;
86791289
DM
47}
48
49sub register_get_rules {
50 my ($class) = @_;
51
63c91681 52 my $properties = $class->additional_parameters();
86791289
DM
53
54 $class->register_method({
55 name => 'get_rules',
56 path => '',
57 method => 'GET',
58 description => "List rules.",
59 parameters => {
60 additionalProperties => 0,
61 properties => $properties,
62 },
63 returns => {
64 type => 'array',
65 items => {
66 type => "object",
67 properties => {
68 pos => {
69 type => 'integer',
70 }
71 },
72 },
73 links => [ { rel => 'child', href => "{pos}" } ],
74 },
75 code => sub {
76 my ($param) = @_;
77
78 my ($fw_conf, $rules) = $class->load_config($param);
79
80 my $digest = $fw_conf->{digest};
81
82 my $res = [];
83
84 my $ind = 0;
85 foreach my $rule (@$rules) {
86 push @$res, PVE::Firewall::cleanup_fw_rule($rule, $digest, $ind++);
87 }
88
89 return $res;
90 }});
91}
92
93sub register_get_rule {
94 my ($class) = @_;
95
63c91681 96 my $properties = $class->additional_parameters();
86791289
DM
97
98 $properties->{pos} = $api_properties->{pos};
99
86791289
DM
100 $class->register_method({
101 name => 'get_rule',
102 path => '{pos}',
103 method => 'GET',
104 description => "Get single rule data.",
105 parameters => {
106 additionalProperties => 0,
107 properties => $properties,
108 },
109 returns => {
110 type => "object",
111 properties => {
112 pos => {
113 type => 'integer',
114 }
115 },
116 },
117 code => sub {
118 my ($param) = @_;
119
120 my ($fw_conf, $rules) = $class->load_config($param);
121
122 my $digest = $fw_conf->{digest};
123 # fixme: check digest
124
125 die "no rule at position $param->{pos}\n" if $param->{pos} >= scalar(@$rules);
126
127 my $rule = $rules->[$param->{pos}];
128
129 return PVE::Firewall::cleanup_fw_rule($rule, $digest, $param->{pos});
130 }});
131}
132
133sub register_create_rule {
134 my ($class) = @_;
135
63c91681 136 my $properties = $class->additional_parameters();
86791289
DM
137
138 my $create_rule_properties = PVE::Firewall::add_rule_properties($properties);
3655b01f
DM
139 $create_rule_properties->{action}->{optional} = 0;
140 $create_rule_properties->{type}->{optional} = 0;
141
86791289
DM
142 $class->register_method({
143 name => 'create_rule',
144 path => '',
145 method => 'POST',
146 description => "Create new rule.",
147 protected => 1,
148 parameters => {
149 additionalProperties => 0,
150 properties => $create_rule_properties,
151 },
152 returns => { type => "null" },
153 code => sub {
154 my ($param) = @_;
155
156 my ($fw_conf, $rules) = $class->load_config($param);
157
158 my $digest = $fw_conf->{digest};
3655b01f
DM
159
160 my $rule = {};
86791289
DM
161
162 PVE::Firewall::copy_rule_data($rule, $param);
163
3655b01f
DM
164 $rule->{enable} = 0 if !defined($param->{enable});
165
86791289
DM
166 unshift @$rules, $rule;
167
168 $class->save_rules($param, $fw_conf, $rules);
169
170 return undef;
171 }});
172}
173
174sub register_update_rule {
175 my ($class) = @_;
176
63c91681 177 my $properties = $class->additional_parameters();
86791289
DM
178
179 $properties->{pos} = $api_properties->{pos};
180
86791289
DM
181 $properties->{moveto} = {
182 description => "Move rule to new position <moveto>. Other arguments are ignored.",
183 type => 'integer',
184 minimum => 0,
185 optional => 1,
186 };
187
5b7974df
DM
188 $properties->{delete} = {
189 type => 'string', format => 'pve-configid-list',
190 description => "A list of settings you want to delete.",
191 optional => 1,
192 };
193
86791289
DM
194 my $update_rule_properties = PVE::Firewall::add_rule_properties($properties);
195
196 $class->register_method({
197 name => 'update_rule',
198 path => '{pos}',
199 method => 'PUT',
200 description => "Modify rule data.",
201 protected => 1,
202 parameters => {
203 additionalProperties => 0,
204 properties => $update_rule_properties,
205 },
206 returns => { type => "null" },
207 code => sub {
208 my ($param) = @_;
209
210 my ($fw_conf, $rules) = $class->load_config($param);
211
212 my $digest = $fw_conf->{digest};
213 # fixme: check digest
214
215 die "no rule at position $param->{pos}\n" if $param->{pos} >= scalar(@$rules);
216
217 my $rule = $rules->[$param->{pos}];
218
219 my $moveto = $param->{moveto};
220 if (defined($moveto) && $moveto != $param->{pos}) {
221 my $newrules = [];
222 for (my $i = 0; $i < scalar(@$rules); $i++) {
223 next if $i == $param->{pos};
224 if ($i == $moveto) {
225 push @$newrules, $rule;
226 }
227 push @$newrules, $rules->[$i];
228 }
229 push @$newrules, $rule if $moveto >= scalar(@$rules);
230 $rules = $newrules;
231 } else {
3655b01f
DM
232 raise_param_exc({ type => "property is missing"})
233 if !defined($param->{type});
234 raise_param_exc({ action => "property is missing"})
235 if !defined($param->{action});
236
86791289 237 PVE::Firewall::copy_rule_data($rule, $param);
5b7974df
DM
238
239 PVE::Firewall::delete_rule_properties($rule, $param->{'delete'}) if $param->{'delete'};
86791289
DM
240 }
241
242 $class->save_rules($param, $fw_conf, $rules);
243
244 return undef;
245 }});
246}
247
248sub register_delete_rule {
249 my ($class) = @_;
250
63c91681 251 my $properties = $class->additional_parameters();
86791289
DM
252
253 $properties->{pos} = $api_properties->{pos};
254
86791289
DM
255 $class->register_method({
256 name => 'delete_rule',
257 path => '{pos}',
258 method => 'DELETE',
259 description => "Delete rule.",
260 protected => 1,
261 parameters => {
262 additionalProperties => 0,
263 properties => $properties,
264 },
265 returns => { type => "null" },
266 code => sub {
267 my ($param) = @_;
268
269 my ($fw_conf, $rules) = $class->load_config($param);
270
271 my $digest = $fw_conf->{digest};
272 # fixme: check digest
273
274 die "no rule at position $param->{pos}\n" if $param->{pos} >= scalar(@$rules);
275
276 splice(@$rules, $param->{pos}, 1);
277
278 $class->save_rules($param, $fw_conf, $rules);
279
280 return undef;
281 }});
282}
283
284sub register_handlers {
285 my ($class) = @_;
286
287 $class->register_get_rules();
288 $class->register_get_rule();
289 $class->register_create_rule();
290 $class->register_update_rule();
291 $class->register_delete_rule();
292}
293
294package PVE::API2::Firewall::GroupRules;
295
296use strict;
297use warnings;
298
299use base qw(PVE::API2::Firewall::RulesBase);
300
63c91681
DM
301__PACKAGE__->additional_parameters({ group => {
302 description => "Security group name.",
303 type => 'string',
304 maxLength => 20, # fixme: what length?
305}});
86791289
DM
306
307sub load_config {
308 my ($class, $param) = @_;
309
310 my $fw_conf = PVE::Firewall::load_clusterfw_conf();
311 my $rules = $fw_conf->{groups}->{$param->{group}};
312 die "no such security group '$param->{group}'\n" if !defined($rules);
313
314 return ($fw_conf, $rules);
315}
316
317sub save_rules {
318 my ($class, $param, $fw_conf, $rules) = @_;
319
320 $fw_conf->{groups}->{$param->{group}} = $rules;
321 PVE::Firewall::save_clusterfw_conf($fw_conf);
322}
323
63c91681 324__PACKAGE__->register_handlers();
86791289
DM
325
326package PVE::API2::Firewall::ClusterRules;
327
328use strict;
329use warnings;
330
331use base qw(PVE::API2::Firewall::RulesBase);
332
333sub load_config {
334 my ($class, $param) = @_;
335
336 my $fw_conf = PVE::Firewall::load_clusterfw_conf();
337 my $rules = $fw_conf->{rules};
338
339 return ($fw_conf, $rules);
340}
341
342sub save_rules {
343 my ($class, $param, $fw_conf, $rules) = @_;
344
345 $fw_conf->{rules} = $rules;
346 PVE::Firewall::save_clusterfw_conf($fw_conf);
347}
348
63c91681
DM
349__PACKAGE__->register_handlers();
350
351package PVE::API2::Firewall::HostRules;
352
353use strict;
354use warnings;
355use PVE::JSONSchema qw(get_standard_option);
356
357use base qw(PVE::API2::Firewall::RulesBase);
358
359__PACKAGE__->additional_parameters({ node => get_standard_option('pve-node')});
360
361sub load_config {
362 my ($class, $param) = @_;
363
364 my $fw_conf = PVE::Firewall::load_hostfw_conf();
365 my $rules = $fw_conf->{rules};
366
367 return ($fw_conf, $rules);
368}
369
370sub save_rules {
371 my ($class, $param, $fw_conf, $rules) = @_;
372
373 $fw_conf->{rules} = $rules;
374 PVE::Firewall::save_hostfw_conf($fw_conf);
375}
376
377__PACKAGE__->register_handlers();
86791289 378
464f933e
DM
379package PVE::API2::Firewall::VMRules;
380
381use strict;
382use warnings;
383use PVE::JSONSchema qw(get_standard_option);
384
385use base qw(PVE::API2::Firewall::RulesBase);
386
387__PACKAGE__->additional_parameters({
388 node => get_standard_option('pve-node'),
389 vmid => get_standard_option('pve-vmid'),
390});
391
392sub load_config {
393 my ($class, $param) = @_;
394
395 my $fw_conf = PVE::Firewall::load_vmfw_conf($param->{vmid});
396 my $rules = $fw_conf->{rules};
397
398 return ($fw_conf, $rules);
399}
400
401sub save_rules {
402 my ($class, $param, $fw_conf, $rules) = @_;
403
404 $fw_conf->{rules} = $rules;
405 PVE::Firewall::save_vmfw_conf($param->{vmid}, $fw_conf);
406}
407
408__PACKAGE__->register_handlers();
409
86791289 4101;