]> git.proxmox.com Git - pve-firewall.git/blame - src/PVE/API2/Firewall/VM.pm
added the 'ipfilter' option
[pve-firewall.git] / src / PVE / API2 / Firewall / VM.pm
CommitLineData
b6b8e6ad 1package PVE::API2::Firewall::VMBase;
e7b35711
DM
2
3use strict;
4use warnings;
5use PVE::JSONSchema qw(get_standard_option);
6use PVE::Cluster;
7use PVE::Firewall;
464f933e 8use PVE::API2::Firewall::Rules;
e76a9f53 9use PVE::API2::Firewall::Aliases;
e7b35711
DM
10
11use Data::Dumper; # fixme: remove
12
13use base qw(PVE::RESTHandler);
14
2822f5c4
DM
15my $option_properties = {
16 enable => {
17 description => "Enable host firewall rules.",
18 type => 'boolean',
19 optional => 1,
20 },
44269d27
DM
21 macfilter => {
22 description => "Enable/disable MAC address filter.",
23 type => 'boolean',
24 optional => 1,
25 },
26 dhcp => {
27 description => "Enable DHCP.",
28 type => 'boolean',
29 optional => 1,
30 },
a83abe93
WB
31 ndp => {
32 description => "Enable NDP.",
33 type => 'boolean',
34 optional => 1,
35 },
d7aa51ac
WB
36 radv => {
37 description => "Allow sending Router Advertisement.",
38 type => 'boolean',
39 optional => 1,
40 },
74601077
WB
41 ipfilter => {
42 description => "Enable default IP filters. " .
43 "This is equivalent to adding an empty ipfilter-net<id> ipset " .
44 "for every interface. Such ipsets implicitly contain sane default " .
45 "restrictions such as restricting IPv6 link local addresses to " .
46 "the one derived from the interface's MAC address.",
47 type => 'boolean',
48 optional => 1,
49 },
2822f5c4
DM
50 policy_in => {
51 description => "Input policy.",
52 type => 'string',
53 optional => 1,
54 enum => ['ACCEPT', 'REJECT', 'DROP'],
55 },
56 policy_out => {
57 description => "Output policy.",
58 type => 'string',
59 optional => 1,
60 enum => ['ACCEPT', 'REJECT', 'DROP'],
61 },
44269d27
DM
62 log_level_in => get_standard_option('pve-fw-loglevel', {
63 description => "Log level for incoming traffic." }),
64 log_level_out => get_standard_option('pve-fw-loglevel', {
65 description => "Log level for outgoing traffic." }),
66
2822f5c4
DM
67};
68
69my $add_option_properties = sub {
70 my ($properties) = @_;
71
72 foreach my $k (keys %$option_properties) {
73 $properties->{$k} = $option_properties->{$k};
74 }
75
76 return $properties;
77};
b6b8e6ad
DM
78
79sub register_handlers {
80 my ($class, $rule_env) = @_;
81
82 $class->register_method({
83 name => 'index',
84 path => '',
85 method => 'GET',
86 permissions => { user => 'all' },
87 description => "Directory index.",
88 parameters => {
89 additionalProperties => 0,
90 properties => {
91 node => get_standard_option('pve-node'),
92 vmid => get_standard_option('pve-vmid'),
93 },
e7b35711 94 },
b6b8e6ad
DM
95 returns => {
96 type => 'array',
97 items => {
98 type => "object",
99 properties => {},
2822f5c4 100 },
b6b8e6ad
DM
101 links => [ { rel => 'child', href => "{name}" } ],
102 },
103 code => sub {
104 my ($param) = @_;
e7b35711 105
b6b8e6ad
DM
106 my $result = [
107 { name => 'rules' },
108 { name => 'aliases' },
947d6ea2
DM
109 { name => 'ipset' },
110 { name => 'refs' },
b6b8e6ad
DM
111 { name => 'options' },
112 ];
e7b35711 113
b6b8e6ad
DM
114 return $result;
115 }});
2822f5c4 116
b6b8e6ad
DM
117
118 $class->register_method({
119 name => 'get_options',
120 path => 'options',
121 method => 'GET',
122 description => "Get VM firewall options.",
123 proxyto => 'node',
16c8f5d7
DM
124 permissions => {
125 check => ['perm', '/vms/{vmid}', [ 'VM.Audit' ]],
126 },
b6b8e6ad
DM
127 parameters => {
128 additionalProperties => 0,
129 properties => {
130 node => get_standard_option('pve-node'),
131 vmid => get_standard_option('pve-vmid'),
2822f5c4
DM
132 },
133 },
b6b8e6ad 134 returns => {
2822f5c4 135 type => "object",
b6b8e6ad
DM
136 #additionalProperties => 1,
137 properties => $option_properties,
138 },
139 code => sub {
140 my ($param) = @_;
141
42ec8178
DM
142 my $cluster_conf = PVE::Firewall::load_clusterfw_conf();
143 my $vmfw_conf = PVE::Firewall::load_vmfw_conf($cluster_conf, $rule_env, $param->{vmid});
b6b8e6ad
DM
144
145 return PVE::Firewall::copy_opject_with_digest($vmfw_conf->{options});
146 }});
147
148 $class->register_method({
149 name => 'set_options',
150 path => 'options',
151 method => 'PUT',
152 description => "Set Firewall options.",
153 protected => 1,
154 proxyto => 'node',
16c8f5d7
DM
155 permissions => {
156 check => ['perm', '/vms/{vmid}', [ 'VM.Config.Network' ]],
157 },
b6b8e6ad
DM
158 parameters => {
159 additionalProperties => 0,
160 properties => &$add_option_properties({
161 node => get_standard_option('pve-node'),
162 vmid => get_standard_option('pve-vmid'),
163 delete => {
164 type => 'string', format => 'pve-configid-list',
165 description => "A list of settings you want to delete.",
166 optional => 1,
2822f5c4 167 },
b6b8e6ad
DM
168 digest => get_standard_option('pve-config-digest'),
169 }),
170 },
171 returns => { type => "null" },
172 code => sub {
173 my ($param) = @_;
174
42ec8178
DM
175
176 my $cluster_conf = PVE::Firewall::load_clusterfw_conf();
177 my $vmfw_conf = PVE::Firewall::load_vmfw_conf($cluster_conf, $rule_env, $param->{vmid});
b6b8e6ad
DM
178
179 my (undef, $digest) = PVE::Firewall::copy_opject_with_digest($vmfw_conf->{options});
180 PVE::Tools::assert_if_modified($digest, $param->{digest});
181
182 if ($param->{delete}) {
183 foreach my $opt (PVE::Tools::split_list($param->{delete})) {
184 raise_param_exc({ delete => "no such option '$opt'" })
185 if !$option_properties->{$opt};
186 delete $vmfw_conf->{options}->{$opt};
2822f5c4
DM
187 }
188 }
2822f5c4 189
b6b8e6ad
DM
190 if (defined($param->{enable})) {
191 $param->{enable} = $param->{enable} ? 1 : 0;
192 }
193
194 foreach my $k (keys %$option_properties) {
195 next if !defined($param->{$k});
196 $vmfw_conf->{options}->{$k} = $param->{$k};
197 }
198
199 PVE::Firewall::save_vmfw_conf($param->{vmid}, $vmfw_conf);
200
201 return undef;
202 }});
2822f5c4 203
b6b8e6ad
DM
204 $class->register_method({
205 name => 'log',
206 path => 'log',
207 method => 'GET',
208 description => "Read firewall log",
209 proxyto => 'node',
210 permissions => {
211 check => ['perm', '/vms/{vmid}', [ 'VM.Console' ]],
212 },
213 protected => 1,
214 parameters => {
215 additionalProperties => 0,
216 properties => {
217 node => get_standard_option('pve-node'),
218 vmid => get_standard_option('pve-vmid'),
219 start => {
220 type => 'integer',
221 minimum => 0,
222 optional => 1,
223 },
224 limit => {
225 type => 'integer',
226 minimum => 0,
227 optional => 1,
228 },
229 },
230 },
231 returns => {
232 type => 'array',
233 items => {
234 type => "object",
235 properties => {
236 n => {
237 description=> "Line number",
238 type=> 'integer',
239 },
240 t => {
241 description=> "Line text",
242 type => 'string',
243 }
244 }
245 }
246 },
247 code => sub {
248 my ($param) = @_;
e7b35711 249
b6b8e6ad
DM
250 my $rpcenv = PVE::RPCEnvironment::get();
251 my $user = $rpcenv->get_user();
252 my $vmid = $param->{vmid};
253
254 my ($count, $lines) = PVE::Tools::dump_logfile("/var/log/pve-firewall.log",
255 $param->{start}, $param->{limit},
256 "^$vmid ");
257
258 $rpcenv->set_result_attrib('total', $count);
2822f5c4 259
b6b8e6ad
DM
260 return $lines;
261 }});
947d6ea2
DM
262
263
264 $class->register_method({
265 name => 'refs',
266 path => 'refs',
267 method => 'GET',
268 description => "Lists possible IPSet/Alias reference which are allowed in source/dest properties.",
16c8f5d7
DM
269 permissions => {
270 check => ['perm', '/vms/{vmid}', [ 'VM.Audit' ]],
271 },
947d6ea2
DM
272 parameters => {
273 additionalProperties => 0,
274 properties => {
275 node => get_standard_option('pve-node'),
276 vmid => get_standard_option('pve-vmid'),
f2c0865c
DM
277 type => {
278 description => "Only list references of specified type.",
279 type => 'string',
280 enum => ['alias', 'ipset'],
281 optional => 1,
282 },
947d6ea2
DM
283 },
284 },
285 returns => {
286 type => 'array',
287 items => {
288 type => "object",
289 properties => {
290 type => {
291 type => 'string',
292 enum => ['alias', 'ipset'],
293 },
294 name => {
295 type => 'string',
296 },
297 comment => {
298 type => 'string',
299 optional => 1,
300 },
301 },
302 },
303 },
304 code => sub {
305 my ($param) = @_;
306
307 my $cluster_conf = PVE::Firewall::load_clusterfw_conf();
308 my $fw_conf = PVE::Firewall::load_vmfw_conf($cluster_conf, $rule_env, $param->{vmid});
309
310 my $ipsets = {};
311 my $aliases = {};
312
313 foreach my $conf (($cluster_conf, $fw_conf)) {
314 next if !$conf;
f2c0865c
DM
315 if (!$param->{type} || $param->{type} eq 'ipset') {
316 foreach my $name (keys %{$conf->{ipset}}) {
317 my $data = {
318 type => 'ipset',
319 name => $name,
320 ref => "+$name",
321 };
322 if (my $comment = $conf->{ipset_comments}->{$name}) {
323 $data->{comment} = $comment;
324 }
325 $ipsets->{$name} = $data;
947d6ea2 326 }
947d6ea2
DM
327 }
328
f2c0865c
DM
329 if (!$param->{type} || $param->{type} eq 'alias') {
330 foreach my $name (keys %{$conf->{aliases}}) {
331 my $e = $conf->{aliases}->{$name};
332 my $data = {
333 type => 'alias',
334 name => $name,
335 ref => $name,
336 };
337 $data->{comment} = $e->{comment} if $e->{comment};
338 $aliases->{$name} = $data;
339 }
947d6ea2
DM
340 }
341 }
342
343 my $res = [];
344 foreach my $e (values %$ipsets) { push @$res, $e; };
345 foreach my $e (values %$aliases) { push @$res, $e; };
346
347 return $res;
348 }});
b6b8e6ad
DM
349}
350
351package PVE::API2::Firewall::VM;
352
353use strict;
354use warnings;
355
356use base qw(PVE::API2::Firewall::VMBase);
357
358__PACKAGE__->register_method ({
359 subclass => "PVE::API2::Firewall::VMRules",
360 path => 'rules',
361});
362
363__PACKAGE__->register_method ({
364 subclass => "PVE::API2::Firewall::VMAliases",
365 path => 'aliases',
366});
367
1210ae94
DM
368__PACKAGE__->register_method ({
369 subclass => "PVE::API2::Firewall::VMIPSetList",
370 path => 'ipset',
371});
372
b6b8e6ad
DM
373__PACKAGE__->register_handlers('vm');
374
375package PVE::API2::Firewall::CT;
376
377use strict;
378use warnings;
379
380use base qw(PVE::API2::Firewall::VMBase);
381
382__PACKAGE__->register_method ({
383 subclass => "PVE::API2::Firewall::CTRules",
384 path => 'rules',
385});
386
387__PACKAGE__->register_method ({
388 subclass => "PVE::API2::Firewall::CTAliases",
389 path => 'aliases',
390});
391
1210ae94
DM
392__PACKAGE__->register_method ({
393 subclass => "PVE::API2::Firewall::CTIPSetList",
394 path => 'ipset',
395});
396
b6b8e6ad 397__PACKAGE__->register_handlers('vm');
e7b35711
DM
398
3991;