]> git.proxmox.com Git - pmg-api.git/commitdiff
implement parser/writer and API for /etc/pmg/mynetworks
authorDietmar Maurer <dietmar@proxmox.com>
Mon, 27 Feb 2017 06:28:38 +0000 (07:28 +0100)
committerDietmar Maurer <dietmar@proxmox.com>
Mon, 27 Feb 2017 07:15:15 +0000 (08:15 +0100)
Makefile
NEWS
PMG/API2/Config.pm
PMG/API2/MyNetworks.pm [new file with mode: 0644]
PMG/Config.pm

index f3340662f39a2fa3d8bd5e71521b1b67dd66223b..97dba63d8cd02741611f1f59963116d8fb9bbe6f 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -103,6 +103,7 @@ LIBSOURCES =                                \
        PMG/API2/LDAP.pm                \
        PMG/API2/Domains.pm             \
        PMG/API2/Transport.pm           \
+       PMG/API2/MyNetworks.pm          \
        PMG/API2/Config.pm              \
        PMG/API2/ClusterConfig.pm       \
        PMG/API2/Nodes.pm               \
diff --git a/NEWS b/NEWS
index 155b5fef9c13d69f3bde45371f33dc4d72f7bdb9..38b4f16314dd79ddf01a00927e0d5468e1edb12d 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -13,6 +13,7 @@ Proxmox Mail Gateway 5.0 News
 
 - templates moved to /var/lib/pmg/templates/
 
+- use extra file to store mail/networks /etc/pmg/mynetworks 
 
 Incompatible changes:
 ---------------------
index 2be8d3424395ba37cd2bdb3636334a84c7e1473b..b6eeda8446ee567d4eaa2f828fe7d9aaae407697 100644 (file)
@@ -17,6 +17,7 @@ use PMG::API2::LDAP;
 use PMG::API2::Domains;
 use PMG::API2::Transport;
 use PMG::API2::ClusterConfig;
+use PMG::API2::MyNetworks;
 
 use base qw(PVE::RESTHandler);
 
@@ -42,6 +43,14 @@ __PACKAGE__->register_method ({
     path => 'transport',
 });
 
+__PACKAGE__->register_method ({
+    subclass => "PMG::API2::MyNetworks",
+    # set fragment delimiter (no subdirs) - we need that, because CIDRs
+    # contain a slash '/'
+    fragmentDelimiter => '',
+    path => 'mynetworks',
+});
+
 __PACKAGE__->register_method ({
     subclass => "PMG::API2::ClusterConfig",
     path => 'cluster',
@@ -73,6 +82,7 @@ __PACKAGE__->register_method ({
        }
 
        push @$res, { section => 'ldap' };
+       push @$res, { section => 'mynetworks' };
        push @$res, { section => 'domains' };
        push @$res, { section => 'cluster' };
        push @$res, { section => 'ruledb' };
diff --git a/PMG/API2/MyNetworks.pm b/PMG/API2/MyNetworks.pm
new file mode 100644 (file)
index 0000000..8c87e41
--- /dev/null
@@ -0,0 +1,213 @@
+package PMG::API2::MyNetworks;
+
+use strict;
+use warnings;
+use Data::Dumper;
+
+use PVE::SafeSyslog;
+use PVE::Tools qw(extract_param);
+use HTTP::Status qw(:constants);
+use PVE::JSONSchema qw(get_standard_option);
+use PVE::RESTHandler;
+use PVE::INotify;
+
+use PMG::Config;
+
+use base qw(PVE::RESTHandler);
+
+__PACKAGE__->register_method ({
+    name => 'index',
+    path => '',
+    method => 'GET',
+    description => "List of trusted networks from where SMTP clients are allowed to relay mail through Proxmox Mail Gateway.",
+    proxyto => 'master',
+    parameters => {
+       additionalProperties => 0,
+       properties => {},
+    },
+    returns => {
+       type => 'array',
+       items => {
+           type => "object",
+           properties => {
+               cidr => { type => 'string'},
+           },
+       },
+       links => [ { rel => 'child', href => "{cide}" } ],
+    },
+    code => sub {
+       my ($param) = @_;
+
+       my $mynetworks = PVE::INotify::read_file('mynetworks');
+
+       my $res = [];
+
+       foreach my $cidr (sort keys %$mynetworks) {
+           push @$res, $mynetworks->{$cidr};
+       }
+
+       return $res;
+    }});
+
+__PACKAGE__->register_method ({
+    name => 'create',
+    path => '',
+    method => 'POST',
+    proxyto => 'master',
+    protected => 1,
+    description => "Add a trusted network.",
+    parameters => {
+       additionalProperties => 0,
+       properties => {
+           cidr => {
+               description => "IPv4 or IPv6 network in CIDR notation.",
+               type => 'string', format => 'CIDR',
+           },
+           comment => {
+               description => "Comment.",
+               type => 'string',
+               optional => 1,
+           },
+       },
+    },
+    returns => { type => 'null' },
+    code => sub {
+       my ($param) = @_;
+
+       my $code = sub {
+
+           my $mynetworks = PVE::INotify::read_file('mynetworks');
+
+           die "trusted network '$param->{cidr}' already exists\n"
+               if $mynetworks->{$param->{cidr}};
+
+           $mynetworks->{$param->{cidr}} = {
+               comment => $param->{comment} // '',
+           };
+
+           PVE::INotify::write_file('mynetworks', $mynetworks);
+
+           PMG::Config::postmap_pmg_mynetworks();
+       };
+
+       PMG::Config::lock_config($code, "add trusted network failed");
+
+       return undef;
+    }});
+
+__PACKAGE__->register_method ({
+    name => 'read',
+    path => '{cidr}',
+    method => 'GET',
+    description => "Read trusted network data (comment).",
+    proxyto => 'master',
+    parameters => {
+       additionalProperties => 0,
+       properties => {
+           cidr => {
+               description => "IPv4 or IPv6 network in CIDR notation.",
+               type => 'string', format => 'CIDR',
+           },
+       },
+    },
+    returns => {
+       type => "object",
+       properties => {
+           cidr => { type => 'string'},
+           comment => { type => 'string'},
+       },
+    },
+    code => sub {
+       my ($param) = @_;
+
+       my $mynetworks = PVE::INotify::read_file('mynetworks');
+
+       die "trusted network '$param->{cidr}' does not exist\n"
+           if !$mynetworks->{$param->{cidr}};
+
+       return $mynetworks->{$param->{cidr}}
+    }});
+
+__PACKAGE__->register_method ({
+    name => 'write',
+    path => '{cidr}',
+    method => 'PUT',
+    description => "Update trusted data (comment).",
+    protected => 1,
+    proxyto => 'master',
+    parameters => {
+       additionalProperties => 0,
+       properties => {
+           cidr => {
+               description => "IPv4 or IPv6 network in CIDR notation.",
+               type => 'string', #format => 'CIDR',
+           },
+           comment => {
+               description => "Comment.",
+               type => 'string',
+           },
+       },
+    },
+    returns => { type => 'null' },
+    code => sub {
+       my ($param) = @_;
+
+       my $code = sub {
+
+           my $mynetworks = PVE::INotify::read_file('mynetworks');
+
+           die "trusted network '$param->{cidr}' does not exist\n"
+               if !$mynetworks->{$param->{cidr}};
+
+           $mynetworks->{$param->{cidr}}->{comment} = $param->{comment};
+
+           PVE::INotify::write_file('mynetworks', $mynetworks);
+
+           PMG::Config::postmap_pmg_mynetworks();
+       };
+
+       PMG::Config::lock_config($code, "update trusted network failed");
+
+       return undef;
+    }});
+
+__PACKAGE__->register_method ({
+    name => 'delete',
+    path => '{cidr}',
+    method => 'DELETE',
+    description => "Delete a truster network",
+    protected => 1,
+    proxyto => 'master',
+    parameters => {
+       additionalProperties => 0,
+       properties => {
+           cidr => {
+               description => "IPv4 or IPv6 network in CIDR notation.",
+               type => 'string', format => 'CIDR',
+           },
+       }
+    },
+    returns => { type => 'null' },
+    code => sub {
+       my ($param) = @_;
+
+       my $code = sub {
+
+           my $mynetworks = PVE::INotify::read_file('mynetworks');
+
+           die "trusted network '$param->{cidr}' does not exist\n"
+               if !$mynetworks->{$param->{cidr}};
+
+           delete $mynetworks->{$param->{cidr}};
+
+           PVE::INotify::write_file('mynetworks', $mynetworks);
+
+           PMG::Config::postmap_pmg_mynetworks();
+       };
+
+       PMG::Config::lock_config($code, "delete trusted network failed");
+
+       return undef;
+    }});
+
+1;
index d6d6570d78690e6091fc021d17e8dd047b88a6b6..9c6d59b26b13a3412b83df2e54130aebf096ab0b 100755 (executable)
@@ -713,6 +713,55 @@ PVE::INotify::register_file('domains', $domainsfilename,
                            \&write_pmg_domains,
                            undef, always_call_parser => 1);
 
+my $mynetworks_filename = "/etc/pmg/mynetworks";
+
+sub postmap_pmg_mynetworks {
+    PMG::Utils::run_postmap($mynetworks_filename);
+}
+
+sub read_pmg_mynetworks {
+    my ($filename, $fh) = @_;
+
+    my $mynetworks = {};
+
+    my $comment = '';
+    if (defined($fh)) {
+       while (defined(my $line = <$fh>)) {
+           chomp $line;
+           next if $line =~ m/^\s*$/;
+           if ($line =~ m!^((?:$IPV4RE|$IPV6RE))/(\d+)\s*(?:#(.*)\s*)?$!) {
+               my ($network, $prefix_size, $comment) = ($1, $2, $3);
+               my $cidr = "$network/${prefix_size}";
+               $mynetworks->{$cidr} = {
+                   cidr => $cidr,
+                   network_address => $network,
+                   prefix_size => $prefix_size,
+                   comment => $comment // '',
+               };
+           } else {
+               warn "parse error in '$filename': $line\n";
+           }
+       }
+    }
+
+    return $mynetworks;
+}
+
+sub write_pmg_mynetworks {
+    my ($filename, $fh, $mynetworks) = @_;
+
+    foreach my $cidr (sort keys %$mynetworks) {
+       my $data = $mynetworks->{$cidr};
+       my $comment = $data->{comment} // '*';
+       PVE::Tools::safe_print($filename, $fh, "$cidr #$comment\n");
+    }
+}
+
+PVE::INotify::register_file('mynetworks', $mynetworks_filename,
+                           \&read_pmg_mynetworks,
+                           \&write_pmg_mynetworks,
+                           undef, always_call_parser => 1);
+
 my $transport_map_filename = "/etc/pmg/transport";
 
 sub postmap_pmg_transport {
@@ -840,7 +889,9 @@ sub get_template_vars {
     my $mynetworks = [ '127.0.0.0/8', '[::1]/128' ];
     push @$mynetworks, @$transportnets;
     push @$mynetworks, $int_net_cidr;
+    push @$mynetworks, 'hash:/etc/pmg/mynetworks';
 
+    my $netlist = PVE::INotify::read_file('mynetworks');
     # add default relay to mynetworks
     if (my $relay = $self->get('mail', 'relay')) {
        if ($relay =~ m/^$IPV4RE$/) {
@@ -1039,6 +1090,7 @@ sub rewrite_config_postfix {
     # make sure we have required files (else postfix start fails)
     postmap_pmg_domains();
     postmap_pmg_transport();
+    postmap_pmg_mynetworks();
 
     IO::File->new($transport_map_filename, 'a', 0644);