]> git.proxmox.com Git - pve-firewall.git/blob - src/PVE/API2/Firewall/VM.pm
implement ipsets for VM/CT
[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 = {
16 enable => {
17 description => "Enable host firewall rules.",
18 type => 'boolean',
19 optional => 1,
20 },
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 },
31 policy_in => {
32 description => "Input policy.",
33 type => 'string',
34 optional => 1,
35 enum => ['ACCEPT', 'REJECT', 'DROP'],
36 },
37 policy_out => {
38 description => "Output policy.",
39 type => 'string',
40 optional => 1,
41 enum => ['ACCEPT', 'REJECT', 'DROP'],
42 },
43 log_level_in => get_standard_option('pve-fw-loglevel', {
44 description => "Log level for incoming traffic." }),
45 log_level_out => get_standard_option('pve-fw-loglevel', {
46 description => "Log level for outgoing traffic." }),
47
48 };
49
50 my $add_option_properties = sub {
51 my ($properties) = @_;
52
53 foreach my $k (keys %$option_properties) {
54 $properties->{$k} = $option_properties->{$k};
55 }
56
57 return $properties;
58 };
59
60 sub register_handlers {
61 my ($class, $rule_env) = @_;
62
63 $class->register_method({
64 name => 'index',
65 path => '',
66 method => 'GET',
67 permissions => { user => 'all' },
68 description => "Directory index.",
69 parameters => {
70 additionalProperties => 0,
71 properties => {
72 node => get_standard_option('pve-node'),
73 vmid => get_standard_option('pve-vmid'),
74 },
75 },
76 returns => {
77 type => 'array',
78 items => {
79 type => "object",
80 properties => {},
81 },
82 links => [ { rel => 'child', href => "{name}" } ],
83 },
84 code => sub {
85 my ($param) = @_;
86
87 my $result = [
88 { name => 'rules' },
89 { name => 'aliases' },
90 { name => 'options' },
91 ];
92
93 return $result;
94 }});
95
96
97 $class->register_method({
98 name => 'get_options',
99 path => 'options',
100 method => 'GET',
101 description => "Get VM firewall options.",
102 proxyto => 'node',
103 parameters => {
104 additionalProperties => 0,
105 properties => {
106 node => get_standard_option('pve-node'),
107 vmid => get_standard_option('pve-vmid'),
108 },
109 },
110 returns => {
111 type => "object",
112 #additionalProperties => 1,
113 properties => $option_properties,
114 },
115 code => sub {
116 my ($param) = @_;
117
118 my $vmfw_conf = PVE::Firewall::load_vmfw_conf($rule_env, $param->{vmid});
119
120 return PVE::Firewall::copy_opject_with_digest($vmfw_conf->{options});
121 }});
122
123 $class->register_method({
124 name => 'set_options',
125 path => 'options',
126 method => 'PUT',
127 description => "Set Firewall options.",
128 protected => 1,
129 proxyto => 'node',
130 parameters => {
131 additionalProperties => 0,
132 properties => &$add_option_properties({
133 node => get_standard_option('pve-node'),
134 vmid => get_standard_option('pve-vmid'),
135 delete => {
136 type => 'string', format => 'pve-configid-list',
137 description => "A list of settings you want to delete.",
138 optional => 1,
139 },
140 digest => get_standard_option('pve-config-digest'),
141 }),
142 },
143 returns => { type => "null" },
144 code => sub {
145 my ($param) = @_;
146
147 my $vmfw_conf = PVE::Firewall::load_vmfw_conf($rule_env, $param->{vmid});
148
149 my (undef, $digest) = PVE::Firewall::copy_opject_with_digest($vmfw_conf->{options});
150 PVE::Tools::assert_if_modified($digest, $param->{digest});
151
152 if ($param->{delete}) {
153 foreach my $opt (PVE::Tools::split_list($param->{delete})) {
154 raise_param_exc({ delete => "no such option '$opt'" })
155 if !$option_properties->{$opt};
156 delete $vmfw_conf->{options}->{$opt};
157 }
158 }
159
160 if (defined($param->{enable})) {
161 $param->{enable} = $param->{enable} ? 1 : 0;
162 }
163
164 foreach my $k (keys %$option_properties) {
165 next if !defined($param->{$k});
166 $vmfw_conf->{options}->{$k} = $param->{$k};
167 }
168
169 PVE::Firewall::save_vmfw_conf($param->{vmid}, $vmfw_conf);
170
171 return undef;
172 }});
173
174 $class->register_method({
175 name => 'log',
176 path => 'log',
177 method => 'GET',
178 description => "Read firewall log",
179 proxyto => 'node',
180 permissions => {
181 check => ['perm', '/vms/{vmid}', [ 'VM.Console' ]],
182 },
183 protected => 1,
184 parameters => {
185 additionalProperties => 0,
186 properties => {
187 node => get_standard_option('pve-node'),
188 vmid => get_standard_option('pve-vmid'),
189 start => {
190 type => 'integer',
191 minimum => 0,
192 optional => 1,
193 },
194 limit => {
195 type => 'integer',
196 minimum => 0,
197 optional => 1,
198 },
199 },
200 },
201 returns => {
202 type => 'array',
203 items => {
204 type => "object",
205 properties => {
206 n => {
207 description=> "Line number",
208 type=> 'integer',
209 },
210 t => {
211 description=> "Line text",
212 type => 'string',
213 }
214 }
215 }
216 },
217 code => sub {
218 my ($param) = @_;
219
220 my $rpcenv = PVE::RPCEnvironment::get();
221 my $user = $rpcenv->get_user();
222 my $vmid = $param->{vmid};
223
224 my ($count, $lines) = PVE::Tools::dump_logfile("/var/log/pve-firewall.log",
225 $param->{start}, $param->{limit},
226 "^$vmid ");
227
228 $rpcenv->set_result_attrib('total', $count);
229
230 return $lines;
231 }});
232 }
233
234 package PVE::API2::Firewall::VM;
235
236 use strict;
237 use warnings;
238
239 use base qw(PVE::API2::Firewall::VMBase);
240
241 __PACKAGE__->register_method ({
242 subclass => "PVE::API2::Firewall::VMRules",
243 path => 'rules',
244 });
245
246 __PACKAGE__->register_method ({
247 subclass => "PVE::API2::Firewall::VMAliases",
248 path => 'aliases',
249 });
250
251 __PACKAGE__->register_method ({
252 subclass => "PVE::API2::Firewall::VMIPSetList",
253 path => 'ipset',
254 });
255
256 __PACKAGE__->register_handlers('vm');
257
258 package PVE::API2::Firewall::CT;
259
260 use strict;
261 use warnings;
262
263 use base qw(PVE::API2::Firewall::VMBase);
264
265 __PACKAGE__->register_method ({
266 subclass => "PVE::API2::Firewall::CTRules",
267 path => 'rules',
268 });
269
270 __PACKAGE__->register_method ({
271 subclass => "PVE::API2::Firewall::CTAliases",
272 path => 'aliases',
273 });
274
275 __PACKAGE__->register_method ({
276 subclass => "PVE::API2::Firewall::CTIPSetList",
277 path => 'ipset',
278 });
279
280 __PACKAGE__->register_handlers('vm');
281
282 1;