configs: add locking helpers
[pve-firewall.git] / src / PVE / API2 / Firewall / Aliases.pm
CommitLineData
81d574a7
DM
1package PVE::API2::Firewall::AliasesBase;
2
3use strict;
4use warnings;
5use PVE::Exception qw(raise raise_param_exc);
6use PVE::JSONSchema qw(get_standard_option);
7
8use PVE::Firewall;
9
10use base qw(PVE::RESTHandler);
11
75a12a9d 12my $api_properties = {
81d574a7
DM
13 cidr => {
14 description => "Network/IP specification in CIDR format.",
ae029a88 15 type => 'string', format => 'IPorCIDR',
81d574a7
DM
16 },
17 name => get_standard_option('pve-fw-alias'),
cdc39d63
DM
18 rename => get_standard_option('pve-fw-alias', {
19 description => "Rename an existing alias.",
20 optional => 1,
21 }),
81d574a7
DM
22 comment => {
23 type => 'string',
24 optional => 1,
cdc39d63 25 },
81d574a7
DM
26};
27
28sub load_config {
29 my ($class, $param) = @_;
30
31 die "implement this in subclass";
32
33 #return ($fw_conf, $rules);
34}
35
36sub save_aliases {
37 my ($class, $param, $fw_conf, $aliases) = @_;
38
39 die "implement this in subclass";
40}
41
5679b3a8
DM
42sub rule_env {
43 my ($class, $param) = @_;
75a12a9d 44
5679b3a8
DM
45 die "implement this in subclass";
46}
47
81d574a7
DM
48my $additional_param_hash = {};
49
50sub additional_parameters {
51 my ($class, $new_value) = @_;
52
53 if (defined($new_value)) {
54 $additional_param_hash->{$class} = $new_value;
55 }
56
57 # return a copy
58 my $copy = {};
59 my $org = $additional_param_hash->{$class} || {};
60 foreach my $p (keys %$org) { $copy->{$p} = $org->{$p}; }
61 return $copy;
62}
63
64my $aliases_to_list = sub {
65 my ($aliases) = @_;
66
67 my $list = [];
68 foreach my $k (sort keys %$aliases) {
69 push @$list, $aliases->{$k};
70 }
71 return $list;
72};
73
74sub register_get_aliases {
75 my ($class) = @_;
76
77 my $properties = $class->additional_parameters();
78
79 $class->register_method({
80 name => 'get_aliases',
81 path => '',
82 method => 'GET',
83 description => "List aliases",
5679b3a8 84 permissions => PVE::Firewall::rules_audit_permissions($class->rule_env()),
81d574a7
DM
85 parameters => {
86 additionalProperties => 0,
87 properties => $properties,
88 },
89 returns => {
90 type => 'array',
91 items => {
92 type => "object",
93 properties => {
94 name => { type => 'string' },
95 cidr => { type => 'string' },
96 comment => {
97 type => 'string',
98 optional => 1,
99 },
75a12a9d 100 digest => get_standard_option('pve-config-digest', { optional => 0} ),
81d574a7
DM
101 },
102 },
103 links => [ { rel => 'child', href => "{name}" } ],
104 },
105 code => sub {
106 my ($param) = @_;
107
108 my ($fw_conf, $aliases) = $class->load_config($param);
109
110 my $list = &$aliases_to_list($aliases);
111
112 return PVE::Firewall::copy_list_with_digest($list);
113 }});
114}
115
116sub register_create_alias {
117 my ($class) = @_;
118
119 my $properties = $class->additional_parameters();
120
121 $properties->{name} = $api_properties->{name};
122 $properties->{cidr} = $api_properties->{cidr};
123 $properties->{comment} = $api_properties->{comment};
124
125 $class->register_method({
126 name => 'create_alias',
127 path => '',
128 method => 'POST',
129 description => "Create IP or Network Alias.",
5679b3a8 130 permissions => PVE::Firewall::rules_modify_permissions($class->rule_env()),
81d574a7
DM
131 protected => 1,
132 parameters => {
133 additionalProperties => 0,
134 properties => $properties,
135 },
136 returns => { type => "null" },
137 code => sub {
138 my ($param) = @_;
139
140 my ($fw_conf, $aliases) = $class->load_config($param);
141
142 my $name = lc($param->{name});
75a12a9d
TL
143
144 raise_param_exc({ name => "alias '$param->{name}' already exists" })
81d574a7 145 if defined($aliases->{$name});
75a12a9d 146
81d574a7
DM
147 my $data = { name => $param->{name}, cidr => $param->{cidr} };
148 $data->{comment} = $param->{comment} if $param->{comment};
149
150 $aliases->{$name} = $data;
151
152 $class->save_aliases($param, $fw_conf, $aliases);
153
154 return undef;
155 }});
156}
157
158sub register_read_alias {
159 my ($class) = @_;
160
161 my $properties = $class->additional_parameters();
162
163 $properties->{name} = $api_properties->{name};
75a12a9d 164
81d574a7
DM
165 $class->register_method({
166 name => 'read_alias',
167 path => '{name}',
168 method => 'GET',
169 description => "Read alias.",
5679b3a8 170 permissions => PVE::Firewall::rules_audit_permissions($class->rule_env()),
81d574a7
DM
171 parameters => {
172 additionalProperties => 0,
173 properties => $properties,
174 },
175 returns => { type => "object" },
176 code => sub {
177 my ($param) = @_;
178
179 my ($fw_conf, $aliases) = $class->load_config($param);
180
181 my $name = lc($param->{name});
182
183 raise_param_exc({ name => "no such alias" })
184 if !defined($aliases->{$name});
185
186 return $aliases->{$name};
187 }});
188}
189
190sub register_update_alias {
191 my ($class) = @_;
192
193 my $properties = $class->additional_parameters();
194
195 $properties->{name} = $api_properties->{name};
cdc39d63 196 $properties->{rename} = $api_properties->{rename};
81d574a7
DM
197 $properties->{cidr} = $api_properties->{cidr};
198 $properties->{comment} = $api_properties->{comment};
199 $properties->{digest} = get_standard_option('pve-config-digest');
200
201 $class->register_method({
202 name => 'update_alias',
203 path => '{name}',
204 method => 'PUT',
205 description => "Update IP or Network alias.",
5679b3a8 206 permissions => PVE::Firewall::rules_modify_permissions($class->rule_env()),
81d574a7
DM
207 protected => 1,
208 parameters => {
209 additionalProperties => 0,
210 properties => $properties,
211 },
212 returns => { type => "null" },
213 code => sub {
214 my ($param) = @_;
215
216 my ($fw_conf, $aliases) = $class->load_config($param);
217
218 my $list = &$aliases_to_list($aliases);
219
220 my (undef, $digest) = PVE::Firewall::copy_list_with_digest($list);
221
222 PVE::Tools::assert_if_modified($digest, $param->{digest});
223
224 my $name = lc($param->{name});
225
226 raise_param_exc({ name => "no such alias" }) if !$aliases->{$name};
227
228 my $data = { name => $param->{name}, cidr => $param->{cidr} };
229 $data->{comment} = $param->{comment} if $param->{comment};
230
231 $aliases->{$name} = $data;
232
13d39f19
ML
233 my $rename = $param->{rename};
234 $rename = lc($rename) if $rename;
cdc39d63
DM
235
236 if ($rename && ($name ne $rename)) {
75a12a9d 237 raise_param_exc({ name => "alias '$param->{rename}' already exists" })
cdc39d63
DM
238 if defined($aliases->{$rename});
239 $aliases->{$name}->{name} = $param->{rename};
240 $aliases->{$rename} = $aliases->{$name};
241 delete $aliases->{$name};
242 }
243
81d574a7 244 $class->save_aliases($param, $fw_conf, $aliases);
cdc39d63
DM
245
246 return undef;
81d574a7
DM
247 }});
248}
249
250sub register_delete_alias {
251 my ($class) = @_;
252
253 my $properties = $class->additional_parameters();
254
255 $properties->{name} = $api_properties->{name};
81d574a7
DM
256 $properties->{digest} = get_standard_option('pve-config-digest');
257
258 $class->register_method({
259 name => 'remove_alias',
260 path => '{name}',
261 method => 'DELETE',
262 description => "Remove IP or Network alias.",
5679b3a8 263 permissions => PVE::Firewall::rules_modify_permissions($class->rule_env()),
81d574a7
DM
264 protected => 1,
265 parameters => {
266 additionalProperties => 0,
267 properties => $properties,
268 },
269 returns => { type => "null" },
270 code => sub {
271 my ($param) = @_;
272
273 my ($fw_conf, $aliases) = $class->load_config($param);
274
275 my $list = &$aliases_to_list($aliases);
276 my (undef, $digest) = PVE::Firewall::copy_list_with_digest($list);
277 PVE::Tools::assert_if_modified($digest, $param->{digest});
278
279 my $name = lc($param->{name});
280 delete $aliases->{$name};
281
282 $class->save_aliases($param, $fw_conf, $aliases);
75a12a9d 283
81d574a7
DM
284 return undef;
285 }});
286}
287
288sub register_handlers {
289 my ($class) = @_;
290
291 $class->register_get_aliases();
292 $class->register_create_alias();
293 $class->register_read_alias();
294 $class->register_update_alias();
295 $class->register_delete_alias();
296}
297
298package PVE::API2::Firewall::ClusterAliases;
299
300use strict;
301use warnings;
302
303use base qw(PVE::API2::Firewall::AliasesBase);
304
5679b3a8
DM
305sub rule_env {
306 my ($class, $param) = @_;
75a12a9d 307
5679b3a8
DM
308 return 'cluster';
309}
310
81d574a7
DM
311sub load_config {
312 my ($class, $param) = @_;
313
314 my $fw_conf = PVE::Firewall::load_clusterfw_conf();
315 my $aliases = $fw_conf->{aliases};
316
317 return ($fw_conf, $aliases);
318}
319
320sub save_aliases {
321 my ($class, $param, $fw_conf, $aliases) = @_;
322
323 $fw_conf->{aliases} = $aliases;
324 PVE::Firewall::save_clusterfw_conf($fw_conf);
325}
326
327__PACKAGE__->register_handlers();
328
e76a9f53
DM
329package PVE::API2::Firewall::VMAliases;
330
331use strict;
332use warnings;
333use PVE::JSONSchema qw(get_standard_option);
334
335use base qw(PVE::API2::Firewall::AliasesBase);
336
5679b3a8
DM
337sub rule_env {
338 my ($class, $param) = @_;
75a12a9d 339
5679b3a8
DM
340 return 'vm';
341}
342
75a12a9d 343__PACKAGE__->additional_parameters({
e76a9f53 344 node => get_standard_option('pve-node'),
75a12a9d 345 vmid => get_standard_option('pve-vmid'),
e76a9f53
DM
346});
347
348sub load_config {
349 my ($class, $param) = @_;
350
42ec8178
DM
351 my $cluster_conf = PVE::Firewall::load_clusterfw_conf();
352 my $fw_conf = PVE::Firewall::load_vmfw_conf($cluster_conf, 'vm', $param->{vmid});
b6b8e6ad
DM
353 my $aliases = $fw_conf->{aliases};
354
355 return ($fw_conf, $aliases);
356}
357
358sub save_aliases {
359 my ($class, $param, $fw_conf, $aliases) = @_;
360
361 $fw_conf->{aliases} = $aliases;
362 PVE::Firewall::save_vmfw_conf($param->{vmid}, $fw_conf);
363}
364
365__PACKAGE__->register_handlers();
366
367package PVE::API2::Firewall::CTAliases;
368
369use strict;
370use warnings;
371use PVE::JSONSchema qw(get_standard_option);
372
373use base qw(PVE::API2::Firewall::AliasesBase);
374
5679b3a8
DM
375sub rule_env {
376 my ($class, $param) = @_;
75a12a9d 377
5679b3a8
DM
378 return 'ct';
379}
380
75a12a9d 381__PACKAGE__->additional_parameters({
b6b8e6ad 382 node => get_standard_option('pve-node'),
75a12a9d 383 vmid => get_standard_option('pve-vmid'),
b6b8e6ad
DM
384});
385
386sub load_config {
387 my ($class, $param) = @_;
388
42ec8178
DM
389 my $cluster_conf = PVE::Firewall::load_clusterfw_conf();
390 my $fw_conf = PVE::Firewall::load_vmfw_conf($cluster_conf, 'ct', $param->{vmid});
e76a9f53
DM
391 my $aliases = $fw_conf->{aliases};
392
393 return ($fw_conf, $aliases);
394}
395
396sub save_aliases {
397 my ($class, $param, $fw_conf, $aliases) = @_;
398
399 $fw_conf->{aliases} = $aliases;
400 PVE::Firewall::save_vmfw_conf($param->{vmid}, $fw_conf);
401}
402
403__PACKAGE__->register_handlers();
404
81d574a7 4051;