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