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 => '',
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',
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',
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',
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}',
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);
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 <moveto>. Other arguments are ignored.",
type => 'integer',
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}',
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) = @_;
PVE::Firewall::save_clusterfw_conf($fw_conf);
}
-__PACKAGE__->register_handlers('groups');
+__PACKAGE__->register_handlers();
package PVE::API2::Firewall::ClusterRules;
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;
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
return $cluster_conf;
}
-my $rules_to_conf = sub {
+my $format_rules = sub {
my ($rules, $need_iface) = @_;
my $raw = '';
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";
}
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);