X-Git-Url: https://git.proxmox.com/?p=pve-firewall.git;a=blobdiff_plain;f=src%2FPVE%2FAPI2%2FFirewall%2FIPSet.pm;h=ec9326f475f77d271b26bbda272a59d22b1b5065;hp=72e7524b603ebb9a4b2ff6cef01ff78080b65722;hb=HEAD;hpb=0549601776b59d8dbf50b419218dfe3c489b5714 diff --git a/src/PVE/API2/Firewall/IPSet.pm b/src/PVE/API2/Firewall/IPSet.pm index 72e7524..ed92d87 100644 --- a/src/PVE/API2/Firewall/IPSet.pm +++ b/src/PVE/API2/Firewall/IPSet.pm @@ -132,6 +132,11 @@ sub register_delete_ipset { my $properties = $class->additional_parameters(); $properties->{name} = get_standard_option('ipset-name'); + $properties->{force} = { + type => 'boolean', + optional => 1, + description => 'Delete all members of the IPSet, if there are any.', + }; $class->register_method({ name => 'delete_ipset', @@ -148,12 +153,17 @@ sub register_delete_ipset { code => sub { my ($param) = @_; - my ($cluster_conf, $fw_conf, $ipset) = $class->load_config($param); + $class->lock_config($param, sub { + my ($param) = @_; + + my ($cluster_conf, $fw_conf, $ipset) = $class->load_config($param); - die "IPSet '$param->{name}' is not empty\n" - if scalar(@$ipset); + die "IPSet '$param->{name}' is not empty\n" + if scalar(@$ipset) && !$param->{force}; - $class->save_ipset($param, $fw_conf, undef); + $class->save_ipset($param, $fw_conf, undef); + + }); return undef; }}); @@ -184,30 +194,42 @@ sub register_create_ip { code => sub { my ($param) = @_; - my ($cluster_conf, $fw_conf, $ipset) = $class->load_config($param); + $class->lock_config($param, sub { + my ($param) = @_; + + my ($cluster_conf, $fw_conf, $ipset) = $class->load_config($param); + + my $cidr = $param->{cidr}; + if ($cidr =~ m@^(dc/|guest/)?(${PVE::Firewall::ip_alias_pattern})$@) { + my $scope = $1 // ""; + my $alias = $2; + # make sure alias exists (if $cidr is an alias) + PVE::Firewall::resolve_alias($cluster_conf, $fw_conf, $alias, $scope); + } else { + $cidr = PVE::Firewall::clean_cidr($cidr); + # normalize like config parser, otherwise duplicates might slip through + $cidr = PVE::Firewall::parse_ip_or_cidr($cidr); + } - my $cidr = $param->{cidr}; + foreach my $entry (@$ipset) { + raise_param_exc({ cidr => "address '$cidr' already exists" }) + if $entry->{cidr} eq $cidr; + } - foreach my $entry (@$ipset) { - raise_param_exc({ cidr => "address '$cidr' already exists" }) - if $entry->{cidr} eq $cidr; - } + raise_param_exc({ cidr => "a zero prefix is not allowed in ipset entries" }) + if $cidr =~ m!/0+$!; - raise_param_exc({ cidr => "a zero prefix is not allowed in ipset entries" }) - if $cidr =~ m!/0+$!; - # make sure alias exists (if $cidr is an alias) - PVE::Firewall::resolve_alias($cluster_conf, $fw_conf, $cidr) - if $cidr =~ m/^${PVE::Firewall::ip_alias_pattern}$/; + my $data = { cidr => $cidr }; - my $data = { cidr => $cidr }; + $data->{nomatch} = 1 if $param->{nomatch}; + $data->{comment} = $param->{comment} if $param->{comment}; - $data->{nomatch} = 1 if $param->{nomatch}; - $data->{comment} = $param->{comment} if $param->{comment}; + unshift @$ipset, $data; - unshift @$ipset, $data; + $class->save_ipset($param, $fw_conf, $ipset); - $class->save_ipset($param, $fw_conf, $ipset); + }); return undef; }}); @@ -276,19 +298,27 @@ sub register_update_ip { code => sub { my ($param) = @_; - my ($cluster_conf, $fw_conf, $ipset) = $class->load_config($param); + my $found = $class->lock_config($param, sub { + my ($param) = @_; - my (undef, $digest) = PVE::Firewall::copy_list_with_digest($ipset); - PVE::Tools::assert_if_modified($digest, $param->{digest}); + my ($cluster_conf, $fw_conf, $ipset) = $class->load_config($param); + + my (undef, $digest) = PVE::Firewall::copy_list_with_digest($ipset); + PVE::Tools::assert_if_modified($digest, $param->{digest}); - foreach my $entry (@$ipset) { - if($entry->{cidr} eq $param->{cidr}) { - $entry->{nomatch} = $param->{nomatch}; - $entry->{comment} = $param->{comment}; - $class->save_ipset($param, $fw_conf, $ipset); - return; + foreach my $entry (@$ipset) { + if($entry->{cidr} eq $param->{cidr}) { + $entry->{nomatch} = $param->{nomatch}; + $entry->{comment} = $param->{comment}; + $class->save_ipset($param, $fw_conf, $ipset); + return 1; + } } - } + + return 0; + }); + + return if $found; raise_param_exc({ cidr => "no such IP/Network" }); }}); @@ -318,18 +348,22 @@ sub register_delete_ip { code => sub { my ($param) = @_; - my ($cluster_conf, $fw_conf, $ipset) = $class->load_config($param); + $class->lock_config($param, sub { + my ($param) = @_; - my (undef, $digest) = PVE::Firewall::copy_list_with_digest($ipset); - PVE::Tools::assert_if_modified($digest, $param->{digest}); + my ($cluster_conf, $fw_conf, $ipset) = $class->load_config($param); - my $new = []; + my (undef, $digest) = PVE::Firewall::copy_list_with_digest($ipset); + PVE::Tools::assert_if_modified($digest, $param->{digest}); - foreach my $entry (@$ipset) { - push @$new, $entry if $entry->{cidr} ne $param->{cidr}; - } + my $new = []; - $class->save_ipset($param, $fw_conf, $new); + foreach my $entry (@$ipset) { + push @$new, $entry if $entry->{cidr} ne $param->{cidr}; + } + + $class->save_ipset($param, $fw_conf, $new); + }); return undef; }}); @@ -611,37 +645,41 @@ sub register_create { code => sub { my ($param) = @_; - my ($cluster_conf, $fw_conf) = $class->load_config($param); + $class->lock_config($param, sub { + my ($param) = @_; - if ($param->{rename}) { - my (undef, $digest) = &$get_ipset_list($fw_conf); - PVE::Tools::assert_if_modified($digest, $param->{digest}); + my ($cluster_conf, $fw_conf) = $class->load_config($param); - raise_param_exc({ name => "IPSet '$param->{rename}' does not exist" }) - if !$fw_conf->{ipset}->{$param->{rename}}; + if ($param->{rename}) { + my (undef, $digest) = &$get_ipset_list($fw_conf); + PVE::Tools::assert_if_modified($digest, $param->{digest}); - # prevent overwriting existing ipset - raise_param_exc({ name => "IPSet '$param->{name}' does already exist"}) - if $fw_conf->{ipset}->{$param->{name}} && - $param->{name} ne $param->{rename}; + raise_param_exc({ name => "IPSet '$param->{rename}' does not exist" }) + if !$fw_conf->{ipset}->{$param->{rename}}; - my $data = delete $fw_conf->{ipset}->{$param->{rename}}; - $fw_conf->{ipset}->{$param->{name}} = $data; - if (my $comment = delete $fw_conf->{ipset_comments}->{$param->{rename}}) { - $fw_conf->{ipset_comments}->{$param->{name}} = $comment; - } - $fw_conf->{ipset_comments}->{$param->{name}} = $param->{comment} if defined($param->{comment}); - } else { - foreach my $name (keys %{$fw_conf->{ipset}}) { - raise_param_exc({ name => "IPSet '$name' already exists" }) - if $name eq $param->{name}; - } + # prevent overwriting existing ipset + raise_param_exc({ name => "IPSet '$param->{name}' does already exist"}) + if $fw_conf->{ipset}->{$param->{name}} && + $param->{name} ne $param->{rename}; - $fw_conf->{ipset}->{$param->{name}} = []; - $fw_conf->{ipset_comments}->{$param->{name}} = $param->{comment} if defined($param->{comment}); - } + my $data = delete $fw_conf->{ipset}->{$param->{rename}}; + $fw_conf->{ipset}->{$param->{name}} = $data; + if (my $comment = delete $fw_conf->{ipset_comments}->{$param->{rename}}) { + $fw_conf->{ipset_comments}->{$param->{name}} = $comment; + } + $fw_conf->{ipset_comments}->{$param->{name}} = $param->{comment} if defined($param->{comment}); + } else { + foreach my $name (keys %{$fw_conf->{ipset}}) { + raise_param_exc({ name => "IPSet '$name' already exists" }) + if $name eq $param->{name}; + } + + $fw_conf->{ipset}->{$param->{name}} = []; + $fw_conf->{ipset_comments}->{$param->{name}} = $param->{comment} if defined($param->{comment}); + } - $class->save_config($param, $fw_conf); + $class->save_config($param, $fw_conf); + }); return undef; }});