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