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