From 63c91681ed5073e1e659860a1948ed852e061fee Mon Sep 17 00:00:00 2001 From: Dietmar Maurer Date: Wed, 2 Apr 2014 10:11:33 +0200 Subject: [PATCH] implement rules API for host.fw --- src/PVE/API2/Firewall/Host.pm | 45 +++--------------- src/PVE/API2/Firewall/Rules.pm | 87 +++++++++++++++++++--------------- src/PVE/Firewall.pm | 48 ++++++++++++++----- 3 files changed, 91 insertions(+), 89 deletions(-) diff --git a/src/PVE/API2/Firewall/Host.pm b/src/PVE/API2/Firewall/Host.pm index e82604e..0ebdcce 100644 --- a/src/PVE/API2/Firewall/Host.pm +++ b/src/PVE/API2/Firewall/Host.pm @@ -5,12 +5,17 @@ use warnings; use PVE::JSONSchema qw(get_standard_option); use PVE::Firewall; - +use PVE::API2::Firewall::Rules; use Data::Dumper; # fixme: remove use base qw(PVE::RESTHandler); +__PACKAGE__->register_method ({ + subclass => "PVE::API2::Firewall::HostRules", + path => 'rules', +}); + __PACKAGE__->register_method({ name => 'index', path => '', @@ -42,44 +47,6 @@ __PACKAGE__->register_method({ return $result; }}); -__PACKAGE__->register_method({ - name => 'get_rules', - path => 'rules', - method => 'GET', - description => "List host firewall rules.", - proxyto => 'node', - parameters => { - additionalProperties => 0, - properties => { - node => get_standard_option('pve-node'), - }, - }, - returns => { - type => 'array', - items => { - type => "object", - properties => {}, - }, - }, - code => sub { - my ($param) = @_; - - my $hostfw_conf = PVE::Firewall::load_hostfw_conf(); - - my $rules = $hostfw_conf->{rules} || []; - - my $digest = $hostfw_conf->{digest}; - - my $res = []; - - my $ind = 0; - foreach my $rule (@$rules) { - push @$res, PVE::Firewall::cleanup_fw_rule($rule, $digest, $ind++); - } - - return $res; - }}); - __PACKAGE__->register_method({ name => 'get_options', path => 'options', diff --git a/src/PVE/API2/Firewall/Rules.pm b/src/PVE/API2/Firewall/Rules.pm index f7ede73..16e22ba 100644 --- a/src/PVE/API2/Firewall/Rules.pm +++ b/src/PVE/API2/Firewall/Rules.pm @@ -9,11 +9,6 @@ use PVE::Firewall; use base qw(PVE::RESTHandler); my $api_properties = { - group => { - description => "Security group name.", - type => 'string', - maxLength => 20, # fixme: what length? - }, pos => { description => "Rule position.", type => 'integer', @@ -35,24 +30,26 @@ sub save_rules { die "implement this in subclass"; } -my $need_group_param_hash = {}; +my $additional_param_hash = {}; -sub need_group_param { +sub additional_parameters { my ($class, $new_value) = @_; - $need_group_param_hash->{$class} = $new_value if defined($new_value); + if (defined($new_value)) { + $additional_param_hash->{$class} = $new_value; + } - return $need_group_param_hash->{$class}; + # return a copy + my $copy = {}; + my $org = $additional_param_hash->{$class} || {}; + foreach my $p (keys %$org) { $copy->{$p} = $org->{$p}; } + return $copy; } sub register_get_rules { my ($class) = @_; - my $properties = {}; - - if ($class->need_group_param()) { - $properties->{group} = $api_properties->{group}; - } + my $properties = $class->additional_parameters(); $class->register_method({ name => 'get_rules', @@ -96,14 +93,10 @@ sub register_get_rules { sub register_get_rule { my ($class) = @_; - my $properties = {}; + my $properties = $class->additional_parameters(); $properties->{pos} = $api_properties->{pos}; - if ($class->need_group_param()) { - $properties->{group} = $api_properties->{group}; - } - $class->register_method({ name => 'get_rule', path => '{pos}', @@ -140,11 +133,7 @@ sub register_get_rule { sub register_create_rule { my ($class) = @_; - my $properties = {}; - - if ($class->need_group_param()) { - $properties->{group} = $api_properties->{group}; - } + my $properties = $class->additional_parameters(); my $create_rule_properties = PVE::Firewall::add_rule_properties($properties); @@ -181,14 +170,10 @@ sub register_create_rule { sub register_update_rule { my ($class) = @_; - my $properties = {}; + my $properties = $class->additional_parameters(); $properties->{pos} = $api_properties->{pos}; - if ($class->need_group_param()) { - $properties->{group} = $api_properties->{group}; - } - $properties->{moveto} = { description => "Move rule to new position . Other arguments are ignored.", type => 'integer', @@ -246,14 +231,10 @@ sub register_update_rule { sub register_delete_rule { my ($class) = @_; - my $properties = {}; + my $properties = $class->additional_parameters(); $properties->{pos} = $api_properties->{pos}; - if ($class->need_group_param()) { - $properties->{group} = $api_properties->{group}; - } - $class->register_method({ name => 'delete_rule', path => '{pos}', @@ -300,7 +281,11 @@ use warnings; use base qw(PVE::API2::Firewall::RulesBase); -__PACKAGE__->need_group_param(1); +__PACKAGE__->additional_parameters({ group => { + description => "Security group name.", + type => 'string', + maxLength => 20, # fixme: what length? +}}); sub load_config { my ($class, $param) = @_; @@ -319,7 +304,7 @@ sub save_rules { PVE::Firewall::save_clusterfw_conf($fw_conf); } -__PACKAGE__->register_handlers('groups'); +__PACKAGE__->register_handlers(); package PVE::API2::Firewall::ClusterRules; @@ -344,6 +329,34 @@ sub save_rules { PVE::Firewall::save_clusterfw_conf($fw_conf); } -__PACKAGE__->register_handlers('cluster'); +__PACKAGE__->register_handlers(); + +package PVE::API2::Firewall::HostRules; + +use strict; +use warnings; +use PVE::JSONSchema qw(get_standard_option); + +use base qw(PVE::API2::Firewall::RulesBase); + +__PACKAGE__->additional_parameters({ node => get_standard_option('pve-node')}); + +sub load_config { + my ($class, $param) = @_; + + my $fw_conf = PVE::Firewall::load_hostfw_conf(); + my $rules = $fw_conf->{rules}; + + return ($fw_conf, $rules); +} + +sub save_rules { + my ($class, $param, $fw_conf, $rules) = @_; + + $fw_conf->{rules} = $rules; + PVE::Firewall::save_hostfw_conf($fw_conf); +} + +__PACKAGE__->register_handlers(); 1; diff --git a/src/PVE/Firewall.pm b/src/PVE/Firewall.pm index 54235fb..6d1818c 100644 --- a/src/PVE/Firewall.pm +++ b/src/PVE/Firewall.pm @@ -16,6 +16,7 @@ use Net::IP; use PVE::Tools qw(run_command lock_file); use Encode; +my $hostfw_conf_filename = "/etc/pve/local/host.fw"; my $clusterfw_conf_filename = "/etc/pve/firewall/cluster.fw"; # dynamically include PVE::QemuServer and PVE::OpenVZ @@ -2060,7 +2061,7 @@ sub load_clusterfw_conf { return $cluster_conf; } -my $rules_to_conf = sub { +my $format_rules = sub { my ($rules, $need_iface) = @_; my $raw = ''; @@ -2087,33 +2088,37 @@ my $rules_to_conf = sub { return $raw; }; +my $format_options = sub { + my ($raw, $options) = @_; + + $raw .= "[OPTIONS]\n\n"; + foreach my $opt (keys %$options) { + $raw .= "$opt: $options->{$opt}\n"; + } + $raw .= "\n"; +}; + sub save_clusterfw_conf { my ($cluster_conf) = @_; my $raw = ''; my $options = $cluster_conf->{options}; - if (scalar(keys %$options)) { - $raw .= "[OPTIONS]\n\n"; - foreach my $opt (keys %$options) { - $raw .= "$opt: $options->{$opt}\n"; - } - $raw .= "\n"; - } + &$format_options($raw, $options) if scalar(keys %$options); # fixme: save ipset my $rules = $cluster_conf->{rules}; if (scalar(@$rules)) { $raw .= "[RULES]\n\n"; - $raw .= &$rules_to_conf($rules, 1); + $raw .= &$format_rules($rules, 1); $raw .= "\n"; } foreach my $group (sort keys %{$cluster_conf->{groups}}) { my $rules = $cluster_conf->{groups}->{$group}; $raw .= "[group $group]\n\n"; - $raw .= &$rules_to_conf($rules, 0); + $raw .= &$format_rules($rules, 0); $raw .= "\n"; } @@ -2123,13 +2128,30 @@ sub save_clusterfw_conf { sub load_hostfw_conf { my $hostfw_conf = {}; - my $filename = "/etc/pve/local/host.fw"; - if (my $fh = IO::File->new($filename, O_RDONLY)) { - $hostfw_conf = parse_host_fw_rules($filename, $fh); + if (my $fh = IO::File->new($hostfw_conf_filename, O_RDONLY)) { + $hostfw_conf = parse_host_fw_rules($hostfw_conf_filename, $fh); } return $hostfw_conf; } +sub save_hostfw_conf { + my ($hostfw_conf) = @_; + + my $raw = ''; + + my $options = $hostfw_conf->{options}; + &$format_options($raw, $options) if scalar(keys %$options); + + my $rules = $hostfw_conf->{rules}; + if (scalar(@$rules)) { + $raw .= "[RULES]\n\n"; + $raw .= &$format_rules($rules, 1); + $raw .= "\n"; + } + + PVE::Tools::file_set_contents($hostfw_conf_filename, $raw); +} + sub compile { my $vmdata = read_local_vm_config(); my $vmfw_configs = read_vm_firewall_configs($vmdata); -- 2.39.2