use PMG::API2::Domains;
use PMG::API2::Transport;
use PMG::API2::ClusterConfig;
+use PMG::API2::MyNetworks;
use base qw(PVE::RESTHandler);
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',
}
push @$res, { section => 'ldap' };
+ push @$res, { section => 'mynetworks' };
push @$res, { section => 'domains' };
push @$res, { section => 'cluster' };
push @$res, { section => 'ruledb' };
--- /dev/null
+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;
\&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 {
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$/) {
# 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);