X-Git-Url: https://git.proxmox.com/?p=pve-firewall.git;a=blobdiff_plain;f=src%2FPVE%2FAPI2%2FFirewall%2FRules.pm;h=83190b4f3886e59d2564b4d65f2dfca275a98ae4;hp=46fdd56cf80404ab81934098d5e0fa5cc0739d14;hb=eadbc1ded37cf77ae49141d8064ad2b42af0d72e;hpb=0d22acb3445afea9d33a9ed80addb912ad116f7e diff --git a/src/PVE/API2/Firewall/Rules.pm b/src/PVE/API2/Firewall/Rules.pm index 46fdd56..83190b4 100644 --- a/src/PVE/API2/Firewall/Rules.pm +++ b/src/PVE/API2/Firewall/Rules.pm @@ -22,7 +22,7 @@ sub load_config { die "implement this in subclass"; - #return ($fw_conf, $rules); + #return ($cluster_conf, $fw_conf, $rules); } sub save_rules { @@ -33,8 +33,10 @@ sub save_rules { my $additional_param_hash = {}; -sub allow_groups { - return 1; +sub rule_env { + my ($class, $param) = @_; + + die "implement this in subclass"; } sub additional_parameters { @@ -65,6 +67,7 @@ sub register_get_rules { additionalProperties => 0, properties => $properties, }, + proxyto => $class->rule_env() eq 'host' ? 'node' : undef, returns => { type => 'array', items => { @@ -80,18 +83,16 @@ sub register_get_rules { code => sub { my ($param) = @_; - my ($fw_conf, $rules) = $class->load_config($param); + my ($cluster_conf, $fw_conf, $rules) = $class->load_config($param); - my $digest = $fw_conf->{digest}; - - my $res = []; + my ($list, $digest) = PVE::Firewall::copy_list_with_digest($rules); my $ind = 0; - foreach my $rule (@$rules) { - push @$res, PVE::Firewall::cleanup_fw_rule($rule, $digest, $ind++); + foreach my $rule (@$list) { + $rule->{pos} = $ind++; } - return $res; + return $list; }}); } @@ -111,6 +112,7 @@ sub register_get_rule { additionalProperties => 0, properties => $properties, }, + proxyto => $class->rule_env() eq 'host' ? 'node' : undef, returns => { type => "object", properties => { @@ -122,16 +124,16 @@ sub register_get_rule { code => sub { my ($param) = @_; - my ($fw_conf, $rules) = $class->load_config($param); + my ($cluster_conf, $fw_conf, $rules) = $class->load_config($param); - my $digest = $fw_conf->{digest}; - # fixme: check digest + my ($list, $digest) = PVE::Firewall::copy_list_with_digest($rules); - die "no rule at position $param->{pos}\n" if $param->{pos} >= scalar(@$rules); + die "no rule at position $param->{pos}\n" if $param->{pos} >= scalar(@$list); - my $rule = $rules->[$param->{pos}]; - - return PVE::Firewall::cleanup_fw_rule($rule, $digest, $param->{pos}); + my $rule = $list->[$param->{pos}]; + $rule->{pos} = $param->{pos}; + + return $rule; }}); } @@ -154,18 +156,17 @@ sub register_create_rule { additionalProperties => 0, properties => $create_rule_properties, }, + proxyto => $class->rule_env() eq 'host' ? 'node' : undef, returns => { type => "null" }, code => sub { my ($param) = @_; - my ($fw_conf, $rules) = $class->load_config($param); - - my $digest = $fw_conf->{digest}; + my ($cluster_conf, $fw_conf, $rules) = $class->load_config($param); my $rule = {}; PVE::Firewall::copy_rule_data($rule, $param); - PVE::Firewall::verify_rule($rule, $class->allow_groups()); + PVE::Firewall::verify_rule($rule, $cluster_conf, $fw_conf, $class->rule_env()); $rule->{enable} = 0 if !defined($param->{enable}); @@ -209,15 +210,16 @@ sub register_update_rule { additionalProperties => 0, properties => $update_rule_properties, }, + proxyto => $class->rule_env() eq 'host' ? 'node' : undef, returns => { type => "null" }, code => sub { my ($param) = @_; - my ($fw_conf, $rules) = $class->load_config($param); + my ($cluster_conf, $fw_conf, $rules) = $class->load_config($param); + + my (undef, $digest) = PVE::Firewall::copy_list_with_digest($rules); + PVE::Tools::assert_if_modified($digest, $param->{digest}); - my $digest = $fw_conf->{digest}; - # fixme: check digest - die "no rule at position $param->{pos}\n" if $param->{pos} >= scalar(@$rules); my $rule = $rules->[$param->{pos}]; @@ -235,16 +237,11 @@ sub register_update_rule { push @$newrules, $rule if $moveto >= scalar(@$rules); $rules = $newrules; } else { - raise_param_exc({ type => "property is missing"}) - if !defined($param->{type}); - raise_param_exc({ action => "property is missing"}) - if !defined($param->{action}); - PVE::Firewall::copy_rule_data($rule, $param); PVE::Firewall::delete_rule_properties($rule, $param->{'delete'}) if $param->{'delete'}; - PVE::Firewall::verify_rule($rule, $class->allow_groups()); + PVE::Firewall::verify_rule($rule, $cluster_conf, $fw_conf, $class->rule_env()); } $class->save_rules($param, $fw_conf, $rules); @@ -259,6 +256,8 @@ sub register_delete_rule { my $properties = $class->additional_parameters(); $properties->{pos} = $api_properties->{pos}; + + $properties->{digest} = get_standard_option('pve-config-digest'); $class->register_method({ name => 'delete_rule', @@ -270,14 +269,15 @@ sub register_delete_rule { additionalProperties => 0, properties => $properties, }, + proxyto => $class->rule_env() eq 'host' ? 'node' : undef, returns => { type => "null" }, code => sub { my ($param) = @_; - my ($fw_conf, $rules) = $class->load_config($param); + my ($cluster_conf, $fw_conf, $rules) = $class->load_config($param); - my $digest = $fw_conf->{digest}; - # fixme: check digest + my (undef, $digest) = PVE::Firewall::copy_list_with_digest($rules); + PVE::Tools::assert_if_modified($digest, $param->{digest}); die "no rule at position $param->{pos}\n" if $param->{pos} >= scalar(@$rules); @@ -309,8 +309,11 @@ use base qw(PVE::API2::Firewall::RulesBase); __PACKAGE__->additional_parameters({ group => get_standard_option('pve-security-group-name') }); -sub allow_groups { - return 0; + +sub rule_env { + my ($class, $param) = @_; + + return 'group'; } sub load_config { @@ -320,16 +323,47 @@ sub load_config { my $rules = $fw_conf->{groups}->{$param->{group}}; die "no such security group '$param->{group}'\n" if !defined($rules); - return ($fw_conf, $rules); + return (undef, $fw_conf, $rules); } sub save_rules { my ($class, $param, $fw_conf, $rules) = @_; - $fw_conf->{groups}->{$param->{group}} = $rules; + if (!defined($rules)) { + delete $fw_conf->{groups}->{$param->{group}}; + } else { + $fw_conf->{groups}->{$param->{group}} = $rules; + } + PVE::Firewall::save_clusterfw_conf($fw_conf); } +__PACKAGE__->register_method({ + name => 'delete_security_group', + path => '', + method => 'DELETE', + description => "Delete security group.", + protected => 1, + parameters => { + additionalProperties => 0, + properties => { + group => get_standard_option('pve-security-group-name'), + }, + }, + returns => { type => 'null' }, + code => sub { + my ($param) = @_; + + my (undef, $cluster_conf, $rules) = __PACKAGE__->load_config($param); + + die "Security group '$param->{group}' is not empty\n" + if scalar(@$rules); + + __PACKAGE__->save_rules($param, $cluster_conf, undef); + + return undef; + }}); + __PACKAGE__->register_handlers(); package PVE::API2::Firewall::ClusterRules; @@ -339,13 +373,19 @@ use warnings; use base qw(PVE::API2::Firewall::RulesBase); +sub rule_env { + my ($class, $param) = @_; + + return 'cluster'; +} + sub load_config { my ($class, $param) = @_; my $fw_conf = PVE::Firewall::load_clusterfw_conf(); my $rules = $fw_conf->{rules}; - return ($fw_conf, $rules); + return (undef, $fw_conf, $rules); } sub save_rules { @@ -367,13 +407,20 @@ use base qw(PVE::API2::Firewall::RulesBase); __PACKAGE__->additional_parameters({ node => get_standard_option('pve-node')}); +sub rule_env { + my ($class, $param) = @_; + + return 'host'; +} + sub load_config { my ($class, $param) = @_; - my $fw_conf = PVE::Firewall::load_hostfw_conf(); + my $cluster_conf = PVE::Firewall::load_clusterfw_conf(); + my $fw_conf = PVE::Firewall::load_hostfw_conf($cluster_conf); my $rules = $fw_conf->{rules}; - return ($fw_conf, $rules); + return ($cluster_conf, $fw_conf, $rules); } sub save_rules { @@ -398,13 +445,58 @@ __PACKAGE__->additional_parameters({ vmid => get_standard_option('pve-vmid'), }); +sub rule_env { + my ($class, $param) = @_; + + return 'vm'; +} + +sub load_config { + my ($class, $param) = @_; + + my $cluster_conf = PVE::Firewall::load_clusterfw_conf(); + my $fw_conf = PVE::Firewall::load_vmfw_conf($cluster_conf, 'vm', $param->{vmid}); + my $rules = $fw_conf->{rules}; + + return ($cluster_conf, $fw_conf, $rules); +} + +sub save_rules { + my ($class, $param, $fw_conf, $rules) = @_; + + $fw_conf->{rules} = $rules; + PVE::Firewall::save_vmfw_conf($param->{vmid}, $fw_conf); +} + +__PACKAGE__->register_handlers(); + +package PVE::API2::Firewall::CTRules; + +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'), + vmid => get_standard_option('pve-vmid'), +}); + +sub rule_env { + my ($class, $param) = @_; + + return 'ct'; +} + sub load_config { my ($class, $param) = @_; - my $fw_conf = PVE::Firewall::load_vmfw_conf($param->{vmid}); + my $cluster_conf = PVE::Firewall::load_clusterfw_conf(); + my $fw_conf = PVE::Firewall::load_vmfw_conf($cluster_conf, 'ct', $param->{vmid}); my $rules = $fw_conf->{rules}; - return ($fw_conf, $rules); + return ($cluster_conf, $fw_conf, $rules); } sub save_rules {