]> git.proxmox.com Git - pve-firewall.git/blame - src/PVE/API2/Firewall/VM.pm
api: Add optional parameters `since` and `until` for timestamp filter
[pve-firewall.git] / src / PVE / API2 / Firewall / VM.pm
CommitLineData
b6b8e6ad 1package PVE::API2::Firewall::VMBase;
e7b35711
DM
2
3use strict;
4use warnings;
f6163c2e
TL
5
6use PVE::Exception qw(raise_param_exc);
e7b35711
DM
7use PVE::JSONSchema qw(get_standard_option);
8use PVE::Cluster;
9use PVE::Firewall;
464f933e 10use PVE::API2::Firewall::Rules;
e76a9f53 11use PVE::API2::Firewall::Aliases;
e7b35711 12
e7b35711
DM
13
14use base qw(PVE::RESTHandler);
15
e313afe0 16my $option_properties = $PVE::Firewall::vm_option_properties;
2822f5c4
DM
17
18my $add_option_properties = sub {
19 my ($properties) = @_;
20
21 foreach my $k (keys %$option_properties) {
22 $properties->{$k} = $option_properties->{$k};
23 }
75a12a9d 24
2822f5c4
DM
25 return $properties;
26};
b6b8e6ad
DM
27
28sub 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 },
e7b35711 43 },
b6b8e6ad
DM
44 returns => {
45 type => 'array',
46 items => {
47 type => "object",
48 properties => {},
2822f5c4 49 },
b6b8e6ad
DM
50 links => [ { rel => 'child', href => "{name}" } ],
51 },
52 code => sub {
53 my ($param) = @_;
e7b35711 54
b6b8e6ad
DM
55 my $result = [
56 { name => 'rules' },
57 { name => 'aliases' },
947d6ea2
DM
58 { name => 'ipset' },
59 { name => 'refs' },
b6b8e6ad
DM
60 { name => 'options' },
61 ];
e7b35711 62
b6b8e6ad
DM
63 return $result;
64 }});
2822f5c4 65
b6b8e6ad
DM
66
67 $class->register_method({
68 name => 'get_options',
69 path => 'options',
70 method => 'GET',
71 description => "Get VM firewall options.",
72 proxyto => 'node',
16c8f5d7
DM
73 permissions => {
74 check => ['perm', '/vms/{vmid}', [ 'VM.Audit' ]],
75 },
b6b8e6ad
DM
76 parameters => {
77 additionalProperties => 0,
78 properties => {
79 node => get_standard_option('pve-node'),
80 vmid => get_standard_option('pve-vmid'),
2822f5c4
DM
81 },
82 },
b6b8e6ad 83 returns => {
2822f5c4 84 type => "object",
b6b8e6ad
DM
85 #additionalProperties => 1,
86 properties => $option_properties,
87 },
88 code => sub {
89 my ($param) = @_;
90
42ec8178
DM
91 my $cluster_conf = PVE::Firewall::load_clusterfw_conf();
92 my $vmfw_conf = PVE::Firewall::load_vmfw_conf($cluster_conf, $rule_env, $param->{vmid});
b6b8e6ad
DM
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',
16c8f5d7
DM
104 permissions => {
105 check => ['perm', '/vms/{vmid}', [ 'VM.Config.Network' ]],
106 },
b6b8e6ad
DM
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,
2822f5c4 116 },
b6b8e6ad
DM
117 digest => get_standard_option('pve-config-digest'),
118 }),
119 },
120 returns => { type => "null" },
121 code => sub {
122 my ($param) = @_;
123
a38849e6
FG
124 PVE::Firewall::lock_vmfw_conf($param->{vmid}, 10, sub {
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 }
2822f5c4 137 }
2822f5c4 138
a38849e6
FG
139 if (defined($param->{enable})) {
140 $param->{enable} = $param->{enable} ? 1 : 0;
141 }
b6b8e6ad 142
a38849e6
FG
143 foreach my $k (keys %$option_properties) {
144 next if !defined($param->{$k});
145 $vmfw_conf->{options}->{$k} = $param->{$k};
146 }
b6b8e6ad 147
a38849e6
FG
148 PVE::Firewall::save_vmfw_conf($param->{vmid}, $vmfw_conf);
149 });
75a12a9d 150
b6b8e6ad
DM
151 return undef;
152 }});
2822f5c4 153
b6b8e6ad 154 $class->register_method({
75a12a9d
TL
155 name => 'log',
156 path => 'log',
b6b8e6ad
DM
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 },
8bd9b3e4
CE
179 since => {
180 type => 'integer',
181 minimum => 0,
182 description => "Display log since this UNIX epoch.",
183 optional => 1,
184 },
185 until => {
186 type => 'integer',
187 minimum => 0,
188 description => "Display log until this UNIX epoch.",
189 optional => 1,
190 },
b6b8e6ad
DM
191 },
192 },
193 returns => {
194 type => 'array',
75a12a9d 195 items => {
b6b8e6ad
DM
196 type => "object",
197 properties => {
198 n => {
199 description=> "Line number",
200 type=> 'integer',
201 },
202 t => {
203 description=> "Line text",
204 type => 'string',
205 }
206 }
207 }
208 },
209 code => sub {
210 my ($param) = @_;
e7b35711 211
b6b8e6ad
DM
212 my $rpcenv = PVE::RPCEnvironment::get();
213 my $user = $rpcenv->get_user();
8bd9b3e4
CE
214 my $filename = "/var/log/pve-firewall.log";
215 my $vmid = $param->{'vmid'};
216
217 my $callback = sub {
218 my ($line) = @_;
219 my $reg = "^$vmid ";
220 return $line =~ m/$reg/;
221 };
b6b8e6ad 222
8bd9b3e4
CE
223 my ($count, $lines) = PVE::Firewall::Helpers::dump_fw_logfile(
224 $filename, $param, $callback);
75a12a9d 225
b6b8e6ad 226 $rpcenv->set_result_attrib('total', $count);
75a12a9d
TL
227
228 return $lines;
b6b8e6ad 229 }});
947d6ea2
DM
230
231
232 $class->register_method({
233 name => 'refs',
234 path => 'refs',
235 method => 'GET',
236 description => "Lists possible IPSet/Alias reference which are allowed in source/dest properties.",
16c8f5d7
DM
237 permissions => {
238 check => ['perm', '/vms/{vmid}', [ 'VM.Audit' ]],
239 },
947d6ea2
DM
240 parameters => {
241 additionalProperties => 0,
242 properties => {
243 node => get_standard_option('pve-node'),
244 vmid => get_standard_option('pve-vmid'),
f2c0865c
DM
245 type => {
246 description => "Only list references of specified type.",
247 type => 'string',
248 enum => ['alias', 'ipset'],
249 optional => 1,
250 },
947d6ea2
DM
251 },
252 },
253 returns => {
254 type => 'array',
255 items => {
256 type => "object",
75a12a9d 257 properties => {
947d6ea2
DM
258 type => {
259 type => 'string',
260 enum => ['alias', 'ipset'],
261 },
262 name => {
263 type => 'string',
264 },
75a12a9d 265 comment => {
947d6ea2
DM
266 type => 'string',
267 optional => 1,
268 },
269 },
270 },
271 },
272 code => sub {
273 my ($param) = @_;
75a12a9d 274
947d6ea2
DM
275 my $cluster_conf = PVE::Firewall::load_clusterfw_conf();
276 my $fw_conf = PVE::Firewall::load_vmfw_conf($cluster_conf, $rule_env, $param->{vmid});
277
278 my $ipsets = {};
279 my $aliases = {};
280
281 foreach my $conf (($cluster_conf, $fw_conf)) {
282 next if !$conf;
f2c0865c
DM
283 if (!$param->{type} || $param->{type} eq 'ipset') {
284 foreach my $name (keys %{$conf->{ipset}}) {
75a12a9d 285 my $data = {
f2c0865c
DM
286 type => 'ipset',
287 name => $name,
288 ref => "+$name",
289 };
290 if (my $comment = $conf->{ipset_comments}->{$name}) {
291 $data->{comment} = $comment;
292 }
293 $ipsets->{$name} = $data;
947d6ea2 294 }
947d6ea2
DM
295 }
296
f2c0865c
DM
297 if (!$param->{type} || $param->{type} eq 'alias') {
298 foreach my $name (keys %{$conf->{aliases}}) {
299 my $e = $conf->{aliases}->{$name};
75a12a9d 300 my $data = {
f2c0865c
DM
301 type => 'alias',
302 name => $name,
303 ref => $name,
304 };
305 $data->{comment} = $e->{comment} if $e->{comment};
306 $aliases->{$name} = $data;
307 }
947d6ea2
DM
308 }
309 }
310
311 my $res = [];
312 foreach my $e (values %$ipsets) { push @$res, $e; };
313 foreach my $e (values %$aliases) { push @$res, $e; };
75a12a9d
TL
314
315 return $res;
947d6ea2 316 }});
b6b8e6ad
DM
317}
318
319package PVE::API2::Firewall::VM;
320
321use strict;
322use warnings;
323
324use base qw(PVE::API2::Firewall::VMBase);
325
326__PACKAGE__->register_method ({
75a12a9d 327 subclass => "PVE::API2::Firewall::VMRules",
b6b8e6ad
DM
328 path => 'rules',
329});
330
331__PACKAGE__->register_method ({
75a12a9d 332 subclass => "PVE::API2::Firewall::VMAliases",
b6b8e6ad
DM
333 path => 'aliases',
334});
335
1210ae94 336__PACKAGE__->register_method ({
75a12a9d 337 subclass => "PVE::API2::Firewall::VMIPSetList",
1210ae94
DM
338 path => 'ipset',
339});
340
b6b8e6ad
DM
341__PACKAGE__->register_handlers('vm');
342
343package PVE::API2::Firewall::CT;
344
345use strict;
346use warnings;
347
348use base qw(PVE::API2::Firewall::VMBase);
349
350__PACKAGE__->register_method ({
75a12a9d 351 subclass => "PVE::API2::Firewall::CTRules",
b6b8e6ad
DM
352 path => 'rules',
353});
354
355__PACKAGE__->register_method ({
75a12a9d 356 subclass => "PVE::API2::Firewall::CTAliases",
b6b8e6ad
DM
357 path => 'aliases',
358});
359
1210ae94 360__PACKAGE__->register_method ({
75a12a9d 361 subclass => "PVE::API2::Firewall::CTIPSetList",
1210ae94
DM
362 path => 'ipset',
363});
364
b6b8e6ad 365__PACKAGE__->register_handlers('vm');
e7b35711
DM
366
3671;