]> git.proxmox.com Git - pve-firewall.git/blob - src/PVE/API2/Firewall/Cluster.pm
firewall instant API call apply
[pve-firewall.git] / src / PVE / API2 / Firewall / Cluster.pm
1 package PVE::API2::Firewall::Cluster;
2
3 use strict;
4 use warnings;
5 use PVE::Exception qw(raise raise_param_exc raise_perm_exc);
6 use PVE::JSONSchema qw(get_standard_option);
7
8 use PVE::Firewall;
9 use PVE::API2::Firewall::Aliases;
10 use PVE::API2::Firewall::Rules;
11 use PVE::API2::Firewall::Groups;
12 use PVE::API2::Firewall::IPSet;
13
14 #fixme: locking?
15
16 use Data::Dumper; # fixme: remove
17
18 use base qw(PVE::RESTHandler);
19
20 __PACKAGE__->register_method ({
21 subclass => "PVE::API2::Firewall::Groups",
22 path => 'groups',
23 });
24
25 __PACKAGE__->register_method ({
26 subclass => "PVE::API2::Firewall::ClusterRules",
27 path => 'rules',
28 });
29
30 __PACKAGE__->register_method ({
31 subclass => "PVE::API2::Firewall::ClusterIPSetList",
32 path => 'ipset',
33 });
34
35 __PACKAGE__->register_method ({
36 subclass => "PVE::API2::Firewall::ClusterAliases",
37 path => 'aliases',
38 });
39
40
41 __PACKAGE__->register_method({
42 name => 'index',
43 path => '',
44 method => 'GET',
45 permissions => { user => 'all' },
46 description => "Directory index.",
47 parameters => {
48 additionalProperties => 0,
49 },
50 returns => {
51 type => 'array',
52 items => {
53 type => "object",
54 properties => {},
55 },
56 links => [ { rel => 'child', href => "{name}" } ],
57 },
58 code => sub {
59 my ($param) = @_;
60
61 my $result = [
62 { name => 'aliases' },
63 { name => 'rules' },
64 { name => 'options' },
65 { name => 'groups' },
66 { name => 'ipset' },
67 { name => 'macros' },
68 { name => 'refs' },
69 ];
70
71 return $result;
72 }});
73
74 my $option_properties = {
75 enable => {
76 type => 'integer',
77 minimum => 0,
78 optional => 1,
79 },
80 policy_in => {
81 description => "Input policy.",
82 type => 'string',
83 optional => 1,
84 enum => ['ACCEPT', 'REJECT', 'DROP'],
85 },
86 policy_out => {
87 description => "Output policy.",
88 type => 'string',
89 optional => 1,
90 enum => ['ACCEPT', 'REJECT', 'DROP'],
91 },
92 };
93
94 my $add_option_properties = sub {
95 my ($properties) = @_;
96
97 foreach my $k (keys %$option_properties) {
98 $properties->{$k} = $option_properties->{$k};
99 }
100
101 return $properties;
102 };
103
104
105 __PACKAGE__->register_method({
106 name => 'get_options',
107 path => 'options',
108 method => 'GET',
109 description => "Get Firewall options.",
110 permissions => {
111 check => ['perm', '/', [ 'Sys.Audit' ]],
112 },
113 parameters => {
114 additionalProperties => 0,
115 },
116 returns => {
117 type => "object",
118 #additionalProperties => 1,
119 properties => $option_properties,
120 },
121 code => sub {
122 my ($param) = @_;
123
124 my $cluster_conf = PVE::Firewall::load_clusterfw_conf();
125
126 return PVE::Firewall::copy_opject_with_digest($cluster_conf->{options});
127 }});
128
129
130 __PACKAGE__->register_method({
131 name => 'set_options',
132 path => 'options',
133 method => 'PUT',
134 description => "Set Firewall options.",
135 protected => 1,
136 permissions => {
137 check => ['perm', '/', [ 'Sys.Modify' ]],
138 },
139 parameters => {
140 additionalProperties => 0,
141 properties => &$add_option_properties({
142 delete => {
143 type => 'string', format => 'pve-configid-list',
144 description => "A list of settings you want to delete.",
145 optional => 1,
146 },
147 digest => get_standard_option('pve-config-digest'),
148 }),
149 },
150 returns => { type => "null" },
151 code => sub {
152 my ($param) = @_;
153
154 my $cluster_conf = PVE::Firewall::load_clusterfw_conf();
155
156 my (undef, $digest) = PVE::Firewall::copy_opject_with_digest($cluster_conf->{options});
157 PVE::Tools::assert_if_modified($digest, $param->{digest});
158
159 if ($param->{delete}) {
160 foreach my $opt (PVE::Tools::split_list($param->{delete})) {
161 raise_param_exc({ delete => "no such option '$opt'" })
162 if !$option_properties->{$opt};
163 delete $cluster_conf->{options}->{$opt};
164 }
165 }
166
167 if (defined($param->{enable}) && ($param->{enable} > 1)) {
168 $param->{enable} = time();
169 }
170
171 foreach my $k (keys %$option_properties) {
172 next if !defined($param->{$k});
173 $cluster_conf->{options}->{$k} = $param->{$k};
174 }
175
176 PVE::Firewall::save_clusterfw_conf($cluster_conf);
177
178 # instant firewall update when using double (anti-lockout) API call
179 # -> not waiting for a firewall update at the first (timestamp enable) set
180 if (defined($param->{enable}) && ($param->{enable} > 1)) {
181 PVE::Firewall::update();
182 }
183
184 return undef;
185 }});
186
187 __PACKAGE__->register_method({
188 name => 'get_macros',
189 path => 'macros',
190 method => 'GET',
191 description => "List available macros",
192 permissions => { user => 'all' },
193 parameters => {
194 additionalProperties => 0,
195 },
196 returns => {
197 type => 'array',
198 items => {
199 type => "object",
200 properties => {
201 macro => {
202 description => "Macro name.",
203 type => 'string',
204 },
205 descr => {
206 description => "More verbose description (if available).",
207 type => 'string',
208 }
209 },
210 },
211 },
212 code => sub {
213 my ($param) = @_;
214
215 my $res = [];
216
217 my ($macros, $descr) = PVE::Firewall::get_macros();
218
219 foreach my $macro (keys %$macros) {
220 push @$res, { macro => $macro, descr => $descr->{$macro} || $macro };
221 }
222
223 return $res;
224 }});
225
226 __PACKAGE__->register_method({
227 name => 'refs',
228 path => 'refs',
229 method => 'GET',
230 description => "Lists possible IPSet/Alias reference which are allowed in source/dest properties.",
231 permissions => {
232 check => ['perm', '/', [ 'Sys.Audit' ]],
233 },
234 parameters => {
235 additionalProperties => 0,
236 properties => {
237 type => {
238 description => "Only list references of specified type.",
239 type => 'string',
240 enum => ['alias', 'ipset'],
241 optional => 1,
242 },
243 },
244 },
245 returns => {
246 type => 'array',
247 items => {
248 type => "object",
249 properties => {
250 type => {
251 type => 'string',
252 enum => ['alias', 'ipset'],
253 },
254 name => {
255 type => 'string',
256 },
257 ref => {
258 type => 'string',
259 },
260 comment => {
261 type => 'string',
262 optional => 1,
263 },
264 },
265 },
266 },
267 code => sub {
268 my ($param) = @_;
269
270 my $conf = PVE::Firewall::load_clusterfw_conf();
271
272 my $res = [];
273
274 if (!$param->{type} || $param->{type} eq 'ipset') {
275 foreach my $name (keys %{$conf->{ipset}}) {
276 my $data = {
277 type => 'ipset',
278 name => $name,
279 ref => "+$name",
280 };
281 if (my $comment = $conf->{ipset_comments}->{$name}) {
282 $data->{comment} = $comment;
283 }
284 push @$res, $data;
285 }
286 }
287
288 if (!$param->{type} || $param->{type} eq 'alias') {
289 foreach my $name (keys %{$conf->{aliases}}) {
290 my $e = $conf->{aliases}->{$name};
291 my $data = {
292 type => 'alias',
293 name => $name,
294 ref => $name,
295 };
296 $data->{comment} = $e->{comment} if $e->{comment};
297 push @$res, $data;
298 }
299 }
300
301 return $res;
302 }});
303
304 1;