X-Git-Url: https://git.proxmox.com/?p=pve-firewall.git;a=blobdiff_plain;f=src%2FPVE%2FAPI2%2FFirewall%2FCluster.pm;h=c9c3e67a16c5212b1a4984c2081e4adf7fc07198;hp=028600cf4174b62e737df8655c6e9c92115aa9ce;hb=HEAD;hpb=ebd54ae918365a722c1091109e74ec21ca7f4be6 diff --git a/src/PVE/API2/Firewall/Cluster.pm b/src/PVE/API2/Firewall/Cluster.pm index 028600c..48ad90d 100644 --- a/src/PVE/API2/Firewall/Cluster.pm +++ b/src/PVE/API2/Firewall/Cluster.pm @@ -6,25 +6,37 @@ use PVE::Exception qw(raise raise_param_exc raise_perm_exc); use PVE::JSONSchema qw(get_standard_option); use PVE::Firewall; +use PVE::API2::Firewall::Aliases; use PVE::API2::Firewall::Rules; use PVE::API2::Firewall::Groups; +use PVE::API2::Firewall::IPSet; #fixme: locking? -use Data::Dumper; # fixme: remove use base qw(PVE::RESTHandler); __PACKAGE__->register_method ({ - subclass => "PVE::API2::Firewall::Groups", + subclass => "PVE::API2::Firewall::Groups", path => 'groups', }); __PACKAGE__->register_method ({ - subclass => "PVE::API2::Firewall::ClusterRules", + subclass => "PVE::API2::Firewall::ClusterRules", path => 'rules', }); +__PACKAGE__->register_method ({ + subclass => "PVE::API2::Firewall::ClusterIPSetList", + path => 'ipset', +}); + +__PACKAGE__->register_method ({ + subclass => "PVE::API2::Firewall::ClusterAliases", + path => 'aliases', +}); + + __PACKAGE__->register_method({ name => 'index', path => '', @@ -46,60 +58,55 @@ __PACKAGE__->register_method({ my ($param) = @_; my $result = [ + { name => 'aliases' }, { name => 'rules' }, { name => 'options' }, { name => 'groups' }, - { name => 'netgroups' }, + { name => 'ipset' }, { name => 'macros' }, + { name => 'refs' }, ]; return $result; }}); +my $option_properties = $PVE::Firewall::cluster_option_properties; + +my $add_option_properties = sub { + my ($properties) = @_; + + foreach my $k (keys %$option_properties) { + $properties->{$k} = $option_properties->{$k}; + } + + return $properties; +}; + + __PACKAGE__->register_method({ name => 'get_options', path => 'options', method => 'GET', description => "Get Firewall options.", + permissions => { + check => ['perm', '/', [ 'Sys.Audit' ]], + }, parameters => { additionalProperties => 0, }, returns => { type => "object", #additionalProperties => 1, - properties => { - enable => { - type => 'boolean', - optional => 1, - }, - }, + properties => $option_properties, }, code => sub { my ($param) = @_; my $cluster_conf = PVE::Firewall::load_clusterfw_conf(); - my $options = $cluster_conf->{options}; - - return $options; + return PVE::Firewall::copy_opject_with_digest($cluster_conf->{options}); }}); -my $option_properties = { - enable => { - type => 'boolean', - optional => 1, - }, -}; - -my $add_option_properties = sub { - my ($properties) = @_; - - foreach my $k (keys %$option_properties) { - $properties->{$k} = $option_properties->{$k}; - } - - return $properties; -}; __PACKAGE__->register_method({ name => 'set_options', @@ -107,6 +114,9 @@ __PACKAGE__->register_method({ method => 'PUT', description => "Set Firewall options.", protected => 1, + permissions => { + check => ['perm', '/', [ 'Sys.Modify' ]], + }, parameters => { additionalProperties => 0, properties => &$add_option_properties({ @@ -115,27 +125,44 @@ __PACKAGE__->register_method({ description => "A list of settings you want to delete.", optional => 1, }, + digest => get_standard_option('pve-config-digest'), }), }, returns => { type => "null" }, code => sub { my ($param) = @_; - my $cluster_conf = PVE::Firewall::load_clusterfw_conf(); + PVE::Firewall::lock_clusterfw_conf(10, sub { + my $cluster_conf = PVE::Firewall::load_clusterfw_conf(); + + my (undef, $digest) = PVE::Firewall::copy_opject_with_digest($cluster_conf->{options}); + PVE::Tools::assert_if_modified($digest, $param->{digest}); - if ($param->{delete}) { - foreach my $opt (PVE::Tools::split_list($param->{delete})) { - raise_param_exc({ delete => "no such option '$opt'" }) - if !$option_properties->{$opt}; - delete $cluster_conf->{options}->{$opt}; + if ($param->{delete}) { + foreach my $opt (PVE::Tools::split_list($param->{delete})) { + raise_param_exc({ delete => "no such option '$opt'" }) + if !$option_properties->{$opt}; + delete $cluster_conf->{options}->{$opt}; + } } - } - if (defined($param->{enable})) { - $cluster_conf->{options}->{enable} = $param->{enable} ? 1 : 0; - } + if (defined($param->{enable}) && ($param->{enable} > 1)) { + $param->{enable} = time(); + } + + foreach my $k (keys %$option_properties) { + next if !defined($param->{$k}); + $cluster_conf->{options}->{$k} = $param->{$k}; + } + + PVE::Firewall::save_clusterfw_conf($cluster_conf); + }); - PVE::Firewall::save_clusterfw_conf($cluster_conf); + # instant firewall update when using double (anti-lockout) API call + # -> not waiting for a firewall update at the first (timestamp enable) set + if (defined($param->{enable}) && ($param->{enable} > 1)) { + PVE::Firewall::update(); + } return undef; }}); @@ -145,6 +172,7 @@ __PACKAGE__->register_method({ path => 'macros', method => 'GET', description => "List available macros", + permissions => { user => 'all' }, parameters => { additionalProperties => 0, }, @@ -178,4 +206,56 @@ __PACKAGE__->register_method({ return $res; }}); +__PACKAGE__->register_method({ + name => 'refs', + path => 'refs', + method => 'GET', + description => "Lists possible IPSet/Alias reference which are allowed in source/dest properties.", + permissions => { + check => ['perm', '/', [ 'Sys.Audit' ]], + }, + parameters => { + additionalProperties => 0, + properties => { + type => { + description => "Only list references of specified type.", + type => 'string', + enum => ['alias', 'ipset'], + optional => 1, + }, + }, + }, + returns => { + type => 'array', + items => { + type => "object", + properties => { + type => { + type => 'string', + enum => ['alias', 'ipset'], + }, + name => { + type => 'string', + }, + ref => { + type => 'string', + }, + scope => { + type => 'string', + }, + comment => { + type => 'string', + optional => 1, + }, + }, + }, + }, + code => sub { + my ($param) = @_; + + my $conf = PVE::Firewall::load_clusterfw_conf(); + + return PVE::Firewall::Helpers::collect_refs($conf, $param->{type}, "dc"); + }}); + 1;