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