]>
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";
33 #return ($fw_conf, $rules);
37 my ($class, $param, $fw_conf, $rules) = @_;
39 die "implement this in subclass";
42 my $additional_param_hash = {};
44 sub additional_parameters
{
45 my ($class, $new_value) = @_;
47 if (defined($new_value)) {
48 $additional_param_hash->{$class} = $new_value;
53 my $org = $additional_param_hash->{$class} || {};
54 foreach my $p (keys %$org) { $copy->{$p} = $org->{$p}; }
58 sub register_get_ipset
{
61 my $properties = $class->additional_parameters();
63 $properties->{name
} = $api_properties->{name
};
65 $class->register_method({
69 description
=> "List IPSet content",
71 additionalProperties
=> 0,
72 properties
=> $properties,
90 digest
=> get_standard_option
('pve-config-digest', { optional
=> 0} ),
93 links
=> [ { rel
=> 'child', href
=> "{cidr}" } ],
98 my ($fw_conf, $ipset) = $class->load_config($param);
100 return PVE
::Firewall
::copy_list_with_digest
($ipset);
104 sub register_create_ip
{
107 my $properties = $class->additional_parameters();
109 $properties->{name
} = $api_properties->{name
};
110 $properties->{cidr
} = $api_properties->{cidr
};
111 $properties->{nomatch
} = $api_properties->{nomatch
};
112 $properties->{comment
} = $api_properties->{comment
};
114 $class->register_method({
118 description
=> "Add IP or Network to IPSet.",
121 additionalProperties
=> 0,
122 properties
=> $properties,
124 returns
=> { type
=> "null" },
128 my ($fw_conf, $ipset) = $class->load_config($param);
130 my $cidr = $param->{cidr
};
132 foreach my $entry (@$ipset) {
133 raise_param_exc
({ cidr
=> "address '$cidr' already exists" })
134 if $entry->{cidr
} eq $cidr;
137 my $data = { cidr
=> $cidr };
138 $data->{nomatch
} = 1 if $param->{nomatch
};
139 $data->{comment
} = $param->{comment
} if $param->{comment
};
141 unshift @$ipset, $data;
143 $class->save_ipset($param, $fw_conf, $ipset);
149 sub register_read_ip
{
152 my $properties = $class->additional_parameters();
154 $properties->{name
} = $api_properties->{name
};
155 $properties->{cidr
} = $api_properties->{cidr
};
157 $class->register_method({
161 description
=> "Read IP or Network settings from IPSet.",
164 additionalProperties
=> 0,
165 properties
=> $properties,
167 returns
=> { type
=> "object" },
171 my ($fw_conf, $ipset) = $class->load_config($param);
173 my $list = PVE
::Firewall
::copy_list_with_digest
($ipset);
175 foreach my $entry (@$list) {
176 if ($entry->{cidr
} eq $param->{cidr
}) {
181 raise_param_exc
({ cidr
=> "no such IP/Network" });
185 sub register_update_ip
{
188 my $properties = $class->additional_parameters();
190 $properties->{name
} = $api_properties->{name
};
191 $properties->{cidr
} = $api_properties->{cidr
};
192 $properties->{nomatch
} = $api_properties->{nomatch
};
193 $properties->{comment
} = $api_properties->{comment
};
194 $properties->{digest
} = get_standard_option
('pve-config-digest');
196 $class->register_method({
200 description
=> "Update IP or Network settings",
203 additionalProperties
=> 0,
204 properties
=> $properties,
206 returns
=> { type
=> "null" },
210 my ($fw_conf, $ipset) = $class->load_config($param);
212 my (undef, $digest) = PVE
::Firewall
::copy_list_with_digest
($ipset);
213 PVE
::Tools
::assert_if_modified
($digest, $param->{digest
});
214 warn "TEST:$digest:$param->{digest}:\n";
216 foreach my $entry (@$ipset) {
217 if($entry->{cidr
} eq $param->{cidr
}) {
218 $entry->{nomatch
} = $param->{nomatch
};
219 $entry->{comment
} = $param->{comment
};
220 $class->save_ipset($param, $fw_conf, $ipset);
225 raise_param_exc
({ cidr
=> "no such IP/Network" });
229 sub register_delete_ip
{
232 my $properties = $class->additional_parameters();
234 $properties->{name
} = $api_properties->{name
};
235 $properties->{cidr
} = $api_properties->{cidr
};
236 $properties->{digest
} = get_standard_option
('pve-config-digest');
238 $class->register_method({
242 description
=> "Remove IP or Network from IPSet.",
245 additionalProperties
=> 0,
246 properties
=> $properties,
248 returns
=> { type
=> "null" },
252 my ($fw_conf, $ipset) = $class->load_config($param);
254 my (undef, $digest) = PVE
::Firewall
::copy_list_with_digest
($ipset);
255 PVE
::Tools
::assert_if_modified
($digest, $param->{digest
});
259 foreach my $entry (@$ipset) {
260 push @$new, $entry if $entry->{cidr
} ne $param->{cidr
};
263 $class->save_ipset($param, $fw_conf, $new);
269 sub register_handlers
{
272 $class->register_get_ipset();
273 $class->register_create_ip();
274 $class->register_read_ip();
275 $class->register_update_ip();
276 $class->register_delete_ip();
279 package PVE
::API2
::Firewall
::ClusterIPset
;
284 use base
qw(PVE::API2::Firewall::IPSetBase);
287 my ($class, $param) = @_;
289 my $fw_conf = PVE
::Firewall
::load_clusterfw_conf
();
290 my $ipset = $fw_conf->{ipset
}->{$param->{name
}};
291 die "no such IPSet '$param->{name}'\n" if !defined($ipset);
293 return ($fw_conf, $ipset);
297 my ($class, $param, $fw_conf, $ipset) = @_;
299 $fw_conf->{ipset
}->{$param->{name
}} = $ipset;
300 PVE
::Firewall
::save_clusterfw_conf
($fw_conf);
303 __PACKAGE__-
>register_handlers();
305 package PVE
::API2
::Firewall
::BaseIPSetList
;
309 use PVE
::JSONSchema
qw(get_standard_option);
310 use PVE
::Exception
qw(raise_param_exc);
313 use base
qw(PVE::RESTHandler);
315 my $get_ipset_list = sub {
319 foreach my $name (keys %{$fw_conf->{ipset
}}) {
323 if (my $comment = $fw_conf->{ipset_comments
}->{$name}) {
324 $data->{comment
} = $comment;
329 my ($list, $digest) = PVE
::Firewall
::copy_list_with_digest
($res);
331 return wantarray ?
($list, $digest) : $list;
337 $class->register_method({
338 name
=> 'ipset_index',
341 description
=> "List IPSets",
343 additionalProperties
=> 0,
350 name
=> get_standard_option
('ipset-name'),
351 digest
=> get_standard_option
('pve-config-digest', { optional
=> 0} ),
358 links
=> [ { rel
=> 'child', href
=> "{name}" } ],
363 my $fw_conf = $class->load_config();
365 return &$get_ipset_list($fw_conf);
369 sub register_create
{
372 $class->register_method({
373 name
=> 'create_ipset',
376 description
=> "Create new IPSet",
379 additionalProperties
=> 0,
381 name
=> get_standard_option
('ipset-name'),
386 rename => get_standard_option
('ipset-name', {
387 description
=> "Rename an existing IPSet. You can set 'rename' to the same value as 'name' to update the 'comment' of an existing IPSet.",
390 digest
=> get_standard_option
('pve-config-digest'),
393 returns
=> { type
=> 'null' },
397 my $fw_conf = $class->load_config();
399 if ($param->{rename}) {
400 my (undef, $digest) = &$get_ipset_list($fw_conf);
401 PVE
::Tools
::assert_if_modified
($digest, $param->{digest
});
403 raise_param_exc
({ name
=> "IPSet '$param->{rename}' does not exists" })
404 if !$fw_conf->{ipset
}->{$param->{rename}};
406 my $data = delete $fw_conf->{ipset
}->{$param->{rename}};
407 $fw_conf->{ipset
}->{$param->{name
}} = $data;
408 if (my $comment = delete $fw_conf->{ipset_comments
}->{$param->{rename}}) {
409 $fw_conf->{ipset_comments
}->{$param->{name
}} = $comment;
411 $fw_conf->{ipset_comments
}->{$param->{name
}} = $param->{comment
} if defined($param->{comment
});
413 foreach my $name (keys %{$fw_conf->{ipset
}}) {
414 raise_param_exc
({ name
=> "IPSet '$name' already exists" })
415 if $name eq $param->{name
};
418 $fw_conf->{ipset
}->{$param->{name
}} = [];
419 $fw_conf->{ipset_comments
}->{$param->{name
}} = $param->{comment
} if defined($param->{comment
});
422 $class->save_config($fw_conf);
428 sub register_delete
{
431 $class->register_method({
432 name
=> 'delete_ipset',
435 description
=> "Delete IPSet",
438 additionalProperties
=> 0,
440 name
=> get_standard_option
('ipset-name'),
441 digest
=> get_standard_option
('pve-config-digest'),
444 returns
=> { type
=> 'null' },
448 my $fw_conf = $class->load_config();
450 return undef if !$fw_conf->{ipset
}->{$param->{name
}};
452 my (undef, $digest) = &$get_ipset_list($fw_conf);
453 PVE
::Tools
::assert_if_modified
($digest, $param->{digest
});
455 die "IPSet '$param->{name}' is not empty\n"
456 if scalar(@{$fw_conf->{ipset
}->{$param->{name
}}});
458 delete $fw_conf->{ipset
}->{$param->{name
}};
460 $class->save_config($fw_conf);
466 sub register_handlers
{
469 $class->register_index();
470 $class->register_create();
471 $class->register_delete();
474 package PVE
::API2
::Firewall
::ClusterIPSetList
;
480 use base
qw(PVE::API2::Firewall::BaseIPSetList);
485 return PVE
::Firewall
::load_clusterfw_conf
();
489 my ($class, $fw_conf) = @_;
491 PVE
::Firewall
::save_clusterfw_conf
($fw_conf);
494 __PACKAGE__-
>register_handlers();
496 __PACKAGE__-
>register_method ({
497 subclass
=> "PVE::API2::Firewall::ClusterIPset",
499 # set fragment delimiter (no subdirs) - we need that, because CIDR address contain a slash '/'
500 fragmentDelimiter
=> '',