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