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