]>
git.proxmox.com Git - pve-firewall.git/blob - src/PVE/API2/Firewall/IPSet.pm
1 package PVE
::API2
::Firewall
::IPSetBase
;
5 use PVE
::Exception
qw(raise raise_param_exc);
6 use PVE
::JSONSchema
qw(get_standard_option);
10 use base
qw(PVE::RESTHandler);
12 my $api_properties = {
14 description
=> "Network/IP specification in CIDR format.",
15 type
=> 'string', format
=> 'IPv4orCIDR',
17 name
=> get_standard_option
('ipset-name'),
29 my ($class, $param) = @_;
31 die "implement this in subclass";
35 my ($class, $param, $fw_conf, $rules) = @_;
37 die "implement this in subclass";
40 my $additional_param_hash = {};
42 sub additional_parameters
{
43 my ($class, $new_value) = @_;
45 if (defined($new_value)) {
46 $additional_param_hash->{$class} = $new_value;
51 my $org = $additional_param_hash->{$class} || {};
52 foreach my $p (keys %$org) { $copy->{$p} = $org->{$p}; }
56 sub register_get_ipset
{
59 my $properties = $class->additional_parameters();
61 $properties->{name
} = $api_properties->{name
};
63 $class->register_method({
67 description
=> "List IPSet content",
69 additionalProperties
=> 0,
70 properties
=> $properties,
88 digest
=> get_standard_option
('pve-config-digest', { optional
=> 0} ),
91 links
=> [ { rel
=> 'child', href
=> "{cidr}" } ],
96 my ($fw_conf, $ipset) = $class->load_config($param);
98 return PVE
::Firewall
::copy_list_with_digest
($ipset);
102 sub register_create_ip
{
105 my $properties = $class->additional_parameters();
107 $properties->{name
} = $api_properties->{name
};
108 $properties->{cidr
} = $api_properties->{cidr
};
109 $properties->{nomatch
} = $api_properties->{nomatch
};
110 $properties->{comment
} = $api_properties->{comment
};
112 $class->register_method({
116 description
=> "Add IP or Network to IPSet.",
119 additionalProperties
=> 0,
120 properties
=> $properties,
122 returns
=> { type
=> "null" },
126 my ($fw_conf, $ipset) = $class->load_config($param);
128 my $cidr = $param->{cidr
};
130 foreach my $entry (@$ipset) {
131 raise_param_exc
({ cidr
=> "address '$cidr' already exists" })
132 if $entry->{cidr
} eq $cidr;
135 my $data = { cidr
=> $cidr };
136 $data->{nomatch
} = 1 if $param->{nomatch
};
137 $data->{comment
} = $param->{comment
} if $param->{comment
};
139 unshift @$ipset, $data;
141 $class->save_ipset($param, $fw_conf, $ipset);
147 sub register_read_ip
{
150 my $properties = $class->additional_parameters();
152 $properties->{name
} = $api_properties->{name
};
153 $properties->{cidr
} = $api_properties->{cidr
};
155 $class->register_method({
159 description
=> "Read IP or Network settings from IPSet.",
162 additionalProperties
=> 0,
163 properties
=> $properties,
165 returns
=> { type
=> "object" },
169 my ($fw_conf, $ipset) = $class->load_config($param);
171 my $list = PVE
::Firewall
::copy_list_with_digest
($ipset);
173 foreach my $entry (@$list) {
174 if ($entry->{cidr
} eq $param->{cidr
}) {
179 raise_param_exc
({ cidr
=> "no such IP/Network" });
183 sub register_update_ip
{
186 my $properties = $class->additional_parameters();
188 $properties->{name
} = $api_properties->{name
};
189 $properties->{cidr
} = $api_properties->{cidr
};
190 $properties->{nomatch
} = $api_properties->{nomatch
};
191 $properties->{comment
} = $api_properties->{comment
};
192 $properties->{digest
} = get_standard_option
('pve-config-digest');
194 $class->register_method({
198 description
=> "Update IP or Network settings",
201 additionalProperties
=> 0,
202 properties
=> $properties,
204 returns
=> { type
=> "null" },
208 my ($fw_conf, $ipset) = $class->load_config($param);
210 my (undef, $digest) = PVE
::Firewall
::copy_list_with_digest
($ipset);
211 PVE
::Tools
::assert_if_modified
($digest, $param->{digest
});
212 warn "TEST:$digest:$param->{digest}:\n";
214 foreach my $entry (@$ipset) {
215 if($entry->{cidr
} eq $param->{cidr
}) {
216 $entry->{nomatch
} = $param->{nomatch
};
217 $entry->{comment
} = $param->{comment
};
218 $class->save_ipset($param, $fw_conf, $ipset);
223 raise_param_exc
({ cidr
=> "no such IP/Network" });
227 sub register_delete_ip
{
230 my $properties = $class->additional_parameters();
232 $properties->{name
} = $api_properties->{name
};
233 $properties->{cidr
} = $api_properties->{cidr
};
234 $properties->{digest
} = get_standard_option
('pve-config-digest');
236 $class->register_method({
240 description
=> "Remove IP or Network from IPSet.",
243 additionalProperties
=> 0,
244 properties
=> $properties,
246 returns
=> { type
=> "null" },
250 my ($fw_conf, $ipset) = $class->load_config($param);
252 my (undef, $digest) = PVE
::Firewall
::copy_list_with_digest
($ipset);
253 PVE
::Tools
::assert_if_modified
($digest, $param->{digest
});
257 foreach my $entry (@$ipset) {
258 push @$new, $entry if $entry->{cidr
} ne $param->{cidr
};
261 $class->save_ipset($param, $fw_conf, $new);
267 sub register_handlers
{
270 $class->register_get_ipset();
271 $class->register_create_ip();
272 $class->register_read_ip();
273 $class->register_update_ip();
274 $class->register_delete_ip();
277 package PVE
::API2
::Firewall
::ClusterIPset
;
282 use base
qw(PVE::API2::Firewall::IPSetBase);
285 my ($class, $param) = @_;
287 my $fw_conf = PVE
::Firewall
::load_clusterfw_conf
();
288 my $ipset = $fw_conf->{ipset
}->{$param->{name
}};
289 die "no such IPSet '$param->{name}'\n" if !defined($ipset);
291 return ($fw_conf, $ipset);
295 my ($class, $param, $fw_conf, $ipset) = @_;
297 $fw_conf->{ipset
}->{$param->{name
}} = $ipset;
298 PVE
::Firewall
::save_clusterfw_conf
($fw_conf);
301 __PACKAGE__-
>register_handlers();
303 package PVE
::API2
::Firewall
::BaseIPSetList
;
307 use PVE
::JSONSchema
qw(get_standard_option);
308 use PVE
::Exception
qw(raise_param_exc);
311 use base
qw(PVE::RESTHandler);
313 my $get_ipset_list = sub {
317 foreach my $name (keys %{$fw_conf->{ipset
}}) {
321 if (my $comment = $fw_conf->{ipset_comments
}->{$name}) {
322 $data->{comment
} = $comment;
327 my ($list, $digest) = PVE
::Firewall
::copy_list_with_digest
($res);
329 return wantarray ?
($list, $digest) : $list;
335 $class->register_method({
336 name
=> 'ipset_index',
339 description
=> "List IPSets",
341 additionalProperties
=> 0,
348 name
=> get_standard_option
('ipset-name'),
349 digest
=> get_standard_option
('pve-config-digest', { optional
=> 0} ),
356 links
=> [ { rel
=> 'child', href
=> "{name}" } ],
361 my $fw_conf = $class->load_config();
363 return &$get_ipset_list($fw_conf);
367 sub register_create
{
370 $class->register_method({
371 name
=> 'create_ipset',
374 description
=> "Create new IPSet",
377 additionalProperties
=> 0,
379 name
=> get_standard_option
('ipset-name'),
384 rename => get_standard_option
('ipset-name', {
385 description
=> "Rename an existing IPSet. You can set 'rename' to the same value as 'name' to update the 'comment' of an existing IPSet.",
388 digest
=> get_standard_option
('pve-config-digest'),
391 returns
=> { type
=> 'null' },
395 my $fw_conf = $class->load_config();
397 if ($param->{rename}) {
398 my (undef, $digest) = &$get_ipset_list($fw_conf);
399 PVE
::Tools
::assert_if_modified
($digest, $param->{digest
});
401 raise_param_exc
({ name
=> "IPSet '$param->{rename}' does not exists" })
402 if !$fw_conf->{ipset
}->{$param->{rename}};
404 my $data = delete $fw_conf->{ipset
}->{$param->{rename}};
405 $fw_conf->{ipset
}->{$param->{name
}} = $data;
406 if (my $comment = delete $fw_conf->{ipset_comments
}->{$param->{rename}}) {
407 $fw_conf->{ipset_comments
}->{$param->{name
}} = $comment;
409 $fw_conf->{ipset_comments
}->{$param->{name
}} = $param->{comment
} if defined($param->{comment
});
411 foreach my $name (keys %{$fw_conf->{ipset
}}) {
412 raise_param_exc
({ name
=> "IPSet '$name' already exists" })
413 if $name eq $param->{name
};
416 $fw_conf->{ipset
}->{$param->{name
}} = [];
417 $fw_conf->{ipset_comments
}->{$param->{name
}} = $param->{comment
} if defined($param->{comment
});
420 $class->save_config($fw_conf);
426 sub register_delete
{
429 $class->register_method({
430 name
=> 'delete_ipset',
433 description
=> "Delete IPSet",
436 additionalProperties
=> 0,
438 name
=> get_standard_option
('ipset-name'),
439 digest
=> get_standard_option
('pve-config-digest'),
442 returns
=> { type
=> 'null' },
446 my $fw_conf = $class->load_config();
448 return undef if !$fw_conf->{ipset
}->{$param->{name
}};
450 my (undef, $digest) = &$get_ipset_list($fw_conf);
451 PVE
::Tools
::assert_if_modified
($digest, $param->{digest
});
453 die "IPSet '$param->{name}' is not empty\n"
454 if scalar(@{$fw_conf->{ipset
}->{$param->{name
}}});
456 delete $fw_conf->{ipset
}->{$param->{name
}};
458 $class->save_config($fw_conf);
464 sub register_handlers
{
467 $class->register_index();
468 $class->register_create();
469 $class->register_delete();
472 package PVE
::API2
::Firewall
::ClusterIPSetList
;
478 use base
qw(PVE::API2::Firewall::BaseIPSetList);
483 return PVE
::Firewall
::load_clusterfw_conf
();
487 my ($class, $fw_conf) = @_;
489 PVE
::Firewall
::save_clusterfw_conf
($fw_conf);
492 __PACKAGE__-
>register_handlers();
494 __PACKAGE__-
>register_method ({
495 subclass
=> "PVE::API2::Firewall::ClusterIPset",
497 # set fragment delimiter (no subdirs) - we need that, because CIDR address contain a slash '/'
498 fragmentDelimiter
=> '',