]>
git.proxmox.com Git - pve-firewall.git/blob - src/PVE/API2/Firewall/IPSet.pm
56dd4f2ae01ada67438a3139b631cced55fb43ab
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 ($cluster_conf, $fw_conf, $ipset);
37 my ($class, $param, $fw_conf) = @_;
39 die "implement this in subclass";
43 my ($class, $param, $fw_conf, $ipset) = @_;
45 if (!defined($ipset)) {
46 delete $fw_conf->{ipset
}->{$param->{name
}};
48 $fw_conf->{ipset
}->{$param->{name
}} = $ipset;
51 $class->save_config($param, $fw_conf);
54 my $additional_param_hash = {};
56 sub additional_parameters
{
57 my ($class, $new_value) = @_;
59 if (defined($new_value)) {
60 $additional_param_hash->{$class} = $new_value;
65 my $org = $additional_param_hash->{$class} || {};
66 foreach my $p (keys %$org) { $copy->{$p} = $org->{$p}; }
70 sub register_get_ipset
{
73 my $properties = $class->additional_parameters();
75 $properties->{name
} = $api_properties->{name
};
77 $class->register_method({
81 description
=> "List IPSet content",
83 additionalProperties
=> 0,
84 properties
=> $properties,
102 digest
=> get_standard_option
('pve-config-digest', { optional
=> 0} ),
105 links
=> [ { rel
=> 'child', href
=> "{cidr}" } ],
110 my ($cluster_conf, $fw_conf, $ipset) = $class->load_config($param);
112 return PVE
::Firewall
::copy_list_with_digest
($ipset);
116 sub register_delete_ipset
{
119 my $properties = $class->additional_parameters();
121 $properties->{name
} = get_standard_option
('ipset-name');
123 $class->register_method({
124 name
=> 'delete_ipset',
127 description
=> "Delete IPSet",
130 additionalProperties
=> 0,
131 properties
=> $properties,
133 returns
=> { type
=> 'null' },
137 my ($cluster_conf, $fw_conf, $ipset) = $class->load_config($param);
139 die "IPSet '$param->{name}' is not empty\n"
142 $class->save_ipset($param, $fw_conf, undef);
148 sub register_create_ip
{
151 my $properties = $class->additional_parameters();
153 $properties->{name
} = $api_properties->{name
};
154 $properties->{cidr
} = $api_properties->{cidr
};
155 $properties->{nomatch
} = $api_properties->{nomatch
};
156 $properties->{comment
} = $api_properties->{comment
};
158 $class->register_method({
162 description
=> "Add IP or Network to IPSet.",
165 additionalProperties
=> 0,
166 properties
=> $properties,
168 returns
=> { type
=> "null" },
172 my ($cluster_conf, $fw_conf, $ipset) = $class->load_config($param);
174 my $cidr = $param->{cidr
};
176 foreach my $entry (@$ipset) {
177 raise_param_exc
({ cidr
=> "address '$cidr' already exists" })
178 if $entry->{cidr
} eq $cidr;
181 my $data = { cidr
=> $cidr };
182 $data->{nomatch
} = 1 if $param->{nomatch
};
183 $data->{comment
} = $param->{comment
} if $param->{comment
};
185 unshift @$ipset, $data;
187 $class->save_ipset($param, $fw_conf, $ipset);
193 sub register_read_ip
{
196 my $properties = $class->additional_parameters();
198 $properties->{name
} = $api_properties->{name
};
199 $properties->{cidr
} = $api_properties->{cidr
};
201 $class->register_method({
205 description
=> "Read IP or Network settings from IPSet.",
208 additionalProperties
=> 0,
209 properties
=> $properties,
211 returns
=> { type
=> "object" },
215 my ($cluster_conf, $fw_conf, $ipset) = $class->load_config($param);
217 my $list = PVE
::Firewall
::copy_list_with_digest
($ipset);
219 foreach my $entry (@$list) {
220 if ($entry->{cidr
} eq $param->{cidr
}) {
225 raise_param_exc
({ cidr
=> "no such IP/Network" });
229 sub register_update_ip
{
232 my $properties = $class->additional_parameters();
234 $properties->{name
} = $api_properties->{name
};
235 $properties->{cidr
} = $api_properties->{cidr
};
236 $properties->{nomatch
} = $api_properties->{nomatch
};
237 $properties->{comment
} = $api_properties->{comment
};
238 $properties->{digest
} = get_standard_option
('pve-config-digest');
240 $class->register_method({
244 description
=> "Update IP or Network settings",
247 additionalProperties
=> 0,
248 properties
=> $properties,
250 returns
=> { type
=> "null" },
254 my ($cluster_conf, $fw_conf, $ipset) = $class->load_config($param);
256 my (undef, $digest) = PVE
::Firewall
::copy_list_with_digest
($ipset);
257 PVE
::Tools
::assert_if_modified
($digest, $param->{digest
});
259 foreach my $entry (@$ipset) {
260 if($entry->{cidr
} eq $param->{cidr
}) {
261 $entry->{nomatch
} = $param->{nomatch
};
262 $entry->{comment
} = $param->{comment
};
263 $class->save_ipset($param, $fw_conf, $ipset);
268 raise_param_exc
({ cidr
=> "no such IP/Network" });
272 sub register_delete_ip
{
275 my $properties = $class->additional_parameters();
277 $properties->{name
} = $api_properties->{name
};
278 $properties->{cidr
} = $api_properties->{cidr
};
279 $properties->{digest
} = get_standard_option
('pve-config-digest');
281 $class->register_method({
285 description
=> "Remove IP or Network from IPSet.",
288 additionalProperties
=> 0,
289 properties
=> $properties,
291 returns
=> { type
=> "null" },
295 my ($cluster_conf, $fw_conf, $ipset) = $class->load_config($param);
297 my (undef, $digest) = PVE
::Firewall
::copy_list_with_digest
($ipset);
298 PVE
::Tools
::assert_if_modified
($digest, $param->{digest
});
302 foreach my $entry (@$ipset) {
303 push @$new, $entry if $entry->{cidr
} ne $param->{cidr
};
306 $class->save_ipset($param, $fw_conf, $new);
312 sub register_handlers
{
315 $class->register_delete_ipset();
316 $class->register_get_ipset();
317 $class->register_create_ip();
318 $class->register_read_ip();
319 $class->register_update_ip();
320 $class->register_delete_ip();
323 package PVE
::API2
::Firewall
::ClusterIPset
;
328 use base
qw(PVE::API2::Firewall::IPSetBase);
331 my ($class, $param) = @_;
333 my $fw_conf = PVE
::Firewall
::load_clusterfw_conf
();
334 my $ipset = $fw_conf->{ipset
}->{$param->{name
}};
335 die "no such IPSet '$param->{name}'\n" if !defined($ipset);
337 return (undef, $fw_conf, $ipset);
341 my ($class, $param, $fw_conf) = @_;
343 PVE
::Firewall
::save_clusterfw_conf
($fw_conf);
346 __PACKAGE__-
>register_handlers();
348 package PVE
::API2
::Firewall
::VMIPset
;
352 use PVE
::JSONSchema
qw(get_standard_option);
354 use base
qw(PVE::API2::Firewall::IPSetBase);
356 __PACKAGE__-
>additional_parameters({
357 node
=> get_standard_option
('pve-node'),
358 vmid
=> get_standard_option
('pve-vmid'),
362 my ($class, $param) = @_;
364 my $cluster_conf = PVE
::Firewall
::load_clusterfw_conf
();
365 my $fw_conf = PVE
::Firewall
::load_vmfw_conf
($cluster_conf, 'vm', $param->{vmid
});
366 my $ipset = $fw_conf->{ipset
}->{$param->{name
}};
367 die "no such IPSet '$param->{name}'\n" if !defined($ipset);
369 return ($cluster_conf, $fw_conf, $ipset);
373 my ($class, $param, $fw_conf) = @_;
375 PVE
::Firewall
::save_vmfw_conf
($param->{vmid
}, $fw_conf);
378 __PACKAGE__-
>register_handlers();
380 package PVE
::API2
::Firewall
::CTIPset
;
384 use PVE
::JSONSchema
qw(get_standard_option);
386 use base
qw(PVE::API2::Firewall::IPSetBase);
388 __PACKAGE__-
>additional_parameters({
389 node
=> get_standard_option
('pve-node'),
390 vmid
=> get_standard_option
('pve-vmid'),
394 my ($class, $param) = @_;
396 my $cluster_conf = PVE
::Firewall
::load_clusterfw_conf
();
397 my $fw_conf = PVE
::Firewall
::load_vmfw_conf
($cluster_conf, 'ct', $param->{vmid
});
398 my $ipset = $fw_conf->{ipset
}->{$param->{name
}};
399 die "no such IPSet '$param->{name}'\n" if !defined($ipset);
401 return ($cluster_conf, $fw_conf, $ipset);
405 my ($class, $param, $fw_conf) = @_;
407 PVE
::Firewall
::save_vmfw_conf
($param->{vmid
}, $fw_conf);
410 __PACKAGE__-
>register_handlers();
412 package PVE
::API2
::Firewall
::BaseIPSetList
;
416 use PVE
::JSONSchema
qw(get_standard_option);
417 use PVE
::Exception
qw(raise_param_exc);
420 use base
qw(PVE::RESTHandler);
423 my ($class, $param) = @_;
425 die "implement this in subclass";
427 #return ($cluster_conf, $fw_conf);
431 my ($class, $param, $fw_conf) = @_;
433 die "implement this in subclass";
436 my $additional_param_hash_list = {};
438 sub additional_parameters
{
439 my ($class, $new_value) = @_;
441 if (defined($new_value)) {
442 $additional_param_hash_list->{$class} = $new_value;
447 my $org = $additional_param_hash_list->{$class} || {};
448 foreach my $p (keys %$org) { $copy->{$p} = $org->{$p}; }
452 my $get_ipset_list = sub {
456 foreach my $name (keys %{$fw_conf->{ipset
}}) {
460 if (my $comment = $fw_conf->{ipset_comments
}->{$name}) {
461 $data->{comment
} = $comment;
466 my ($list, $digest) = PVE
::Firewall
::copy_list_with_digest
($res);
468 return wantarray ?
($list, $digest) : $list;
474 my $properties = $class->additional_parameters();
476 $class->register_method({
477 name
=> 'ipset_index',
480 description
=> "List IPSets",
482 additionalProperties
=> 0,
483 properties
=> $properties,
490 name
=> get_standard_option
('ipset-name'),
491 digest
=> get_standard_option
('pve-config-digest', { optional
=> 0} ),
498 links
=> [ { rel
=> 'child', href
=> "{name}" } ],
503 my ($cluster_conf, $fw_conf) = $class->load_config($param);
505 return &$get_ipset_list($fw_conf);
509 sub register_create
{
512 my $properties = $class->additional_parameters();
514 $properties->{name
} = get_standard_option
('ipset-name');
516 $properties->{comment
} = { type
=> 'string', optional
=> 1 };
518 $properties->{digest
} = get_standard_option
('pve-config-digest');
520 $properties->{rename} = get_standard_option
('ipset-name', {
521 description
=> "Rename an existing IPSet. You can set 'rename' to the same value as 'name' to update the 'comment' of an existing IPSet.",
524 $class->register_method({
525 name
=> 'create_ipset',
528 description
=> "Create new IPSet",
531 additionalProperties
=> 0,
532 properties
=> $properties,
534 returns
=> { type
=> 'null' },
538 my ($cluster_conf, $fw_conf) = $class->load_config($param);
540 if ($param->{rename}) {
541 my (undef, $digest) = &$get_ipset_list($fw_conf);
542 PVE
::Tools
::assert_if_modified
($digest, $param->{digest
});
544 raise_param_exc
({ name
=> "IPSet '$param->{rename}' does not exists" })
545 if !$fw_conf->{ipset
}->{$param->{rename}};
547 my $data = delete $fw_conf->{ipset
}->{$param->{rename}};
548 $fw_conf->{ipset
}->{$param->{name
}} = $data;
549 if (my $comment = delete $fw_conf->{ipset_comments
}->{$param->{rename}}) {
550 $fw_conf->{ipset_comments
}->{$param->{name
}} = $comment;
552 $fw_conf->{ipset_comments
}->{$param->{name
}} = $param->{comment
} if defined($param->{comment
});
554 foreach my $name (keys %{$fw_conf->{ipset
}}) {
555 raise_param_exc
({ name
=> "IPSet '$name' already exists" })
556 if $name eq $param->{name
};
559 $fw_conf->{ipset
}->{$param->{name
}} = [];
560 $fw_conf->{ipset_comments
}->{$param->{name
}} = $param->{comment
} if defined($param->{comment
});
563 $class->save_config($param, $fw_conf);
569 sub register_handlers
{
572 $class->register_index();
573 $class->register_create();
576 package PVE
::API2
::Firewall
::ClusterIPSetList
;
582 use base
qw(PVE::API2::Firewall::BaseIPSetList);
585 my ($class, $param) = @_;
587 my $cluster_conf = PVE
::Firewall
::load_clusterfw_conf
();
588 return (undef, $cluster_conf);
592 my ($class, $param, $fw_conf) = @_;
594 PVE
::Firewall
::save_clusterfw_conf
($fw_conf);
597 __PACKAGE__-
>register_handlers();
599 __PACKAGE__-
>register_method ({
600 subclass
=> "PVE::API2::Firewall::ClusterIPset",
602 # set fragment delimiter (no subdirs) - we need that, because CIDR address contain a slash '/'
603 fragmentDelimiter
=> '',
606 package PVE
::API2
::Firewall
::VMIPSetList
;
610 use PVE
::JSONSchema
qw(get_standard_option);
613 use base
qw(PVE::API2::Firewall::BaseIPSetList);
615 __PACKAGE__-
>additional_parameters({
616 node
=> get_standard_option
('pve-node'),
617 vmid
=> get_standard_option
('pve-vmid'),
621 my ($class, $param) = @_;
623 my $cluster_conf = PVE
::Firewall
::load_clusterfw_conf
();
624 my $fw_conf = PVE
::Firewall
::load_vmfw_conf
($cluster_conf, 'vm', $param->{vmid
});
625 return ($cluster_conf, $fw_conf);
629 my ($class, $param, $fw_conf) = @_;
631 PVE
::Firewall
::save_vmfw_conf
($param->{vmid
}, $fw_conf);
634 __PACKAGE__-
>register_handlers();
636 __PACKAGE__-
>register_method ({
637 subclass
=> "PVE::API2::Firewall::VMIPset",
639 # set fragment delimiter (no subdirs) - we need that, because CIDR address contain a slash '/'
640 fragmentDelimiter
=> '',
643 package PVE
::API2
::Firewall
::CTIPSetList
;
647 use PVE
::JSONSchema
qw(get_standard_option);
650 use base
qw(PVE::API2::Firewall::BaseIPSetList);
652 __PACKAGE__-
>additional_parameters({
653 node
=> get_standard_option
('pve-node'),
654 vmid
=> get_standard_option
('pve-vmid'),
658 my ($class, $param) = @_;
660 my $cluster_conf = PVE
::Firewall
::load_clusterfw_conf
();
661 my $fw_conf = PVE
::Firewall
::load_vmfw_conf
($cluster_conf, 'ct', $param->{vmid
});
662 return ($cluster_conf, $fw_conf);
666 my ($class, $param, $fw_conf) = @_;
668 PVE
::Firewall
::save_vmfw_conf
($param->{vmid
}, $fw_conf);
671 __PACKAGE__-
>register_handlers();
673 __PACKAGE__-
>register_method ({
674 subclass
=> "PVE::API2::Firewall::CTIPset",
676 # set fragment delimiter (no subdirs) - we need that, because CIDR address contain a slash '/'
677 fragmentDelimiter
=> '',