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