From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.proxmox.com (Postfix) with ESMTPS id 1BAAE65F23 for ; Tue, 5 Jan 2021 10:35:42 +0100 (CET) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 18E102553B for ; Tue, 5 Jan 2021 10:35:42 +0100 (CET) Received: from kvmformation1.odiso.net (globalOdiso.M6Lille.odiso.net [89.248.211.242]) by firstgate.proxmox.com (Proxmox) with ESMTP id 90426254C9 for ; Tue, 5 Jan 2021 10:35:37 +0100 (CET) Received: by kvmformation1.odiso.net (Postfix, from userid 0) id 6526C168B87; Tue, 5 Jan 2021 10:35:37 +0100 (CET) From: Alexandre Derumier To: pve-devel@lists.proxmox.com Date: Tue, 5 Jan 2021 10:35:27 +0100 Message-Id: <20210105093536.1727641-7-aderumier@odiso.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20210105093536.1727641-1-aderumier@odiso.com> References: <20210105093536.1727641-1-aderumier@odiso.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 1 AWL -0.140 Adjusted score from AWL reputation of From: address HEADER_FROM_DIFFERENT_DOMAINS 0.248 From and EnvelopeFrom 2nd level mail domains are different KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment KAM_LAZY_DOMAIN_SECURITY 1 Sending domain does not have any anti-forgery methods KHOP_HELO_FCRDNS 0.287 Relay HELO differs from its IP's reverse DNS NO_DNS_FOR_FROM 0.379 Envelope sender has no MX or A DNS records SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_NONE 0.001 SPF: sender does not publish an SPF Record URIBL_BLOCKED 0.001 ADMINISTRATOR NOTICE: The query to URIBL was blocked. See http://wiki.apache.org/spamassassin/DnsBlocklists#dnsbl-block for more information. [vnets.pm, powerdnsplugin.pm, plugin.pm, subnets.pm] Subject: [pve-devel] [PATCH pve-network 06/15] dns: add update record && fix powerdns X-BeenThere: pve-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox VE development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 05 Jan 2021 09:35:42 -0000 Signed-off-by: Alexandre Derumier --- PVE/Network/SDN/Dns/Plugin.pm | 32 +++++++++- PVE/Network/SDN/Dns/PowerdnsPlugin.pm | 87 +++++++++++++++++++++++++-- PVE/Network/SDN/Subnets.pm | 7 ++- PVE/Network/SDN/Vnets.pm | 4 +- 4 files changed, 119 insertions(+), 11 deletions(-) diff --git a/PVE/Network/SDN/Dns/Plugin.pm b/PVE/Network/SDN/Dns/Plugin.pm index ef866b7..199c170 100644 --- a/PVE/Network/SDN/Dns/Plugin.pm +++ b/PVE/Network/SDN/Dns/Plugin.pm @@ -67,11 +67,39 @@ sub parse_section_header { sub add_a_record { - my ($class, $plugin_config, $type, $zone, $reversezone, $hostname, $ip) = @_; + my ($class, $plugin_config, $zone, $hostname, $ip) = @_; + + die "please implement inside plugin"; +} + +sub add_ptr_record { + my ($class, $plugin_config, $zone, $hostname, $ip) = @_; + + die "please implement inside plugin"; +} + +sub del_ptr_record { + my ($class, $plugin_config, $zone, $ip) = @_; + + die "please implement inside plugin"; } sub del_a_record { - my ($class, $plugin_config, $hostname, $ip) = @_; + my ($class, $plugin_config, $zone, $hostname, $ip) = @_; + + die "please implement inside plugin"; +} + +sub verify_zone { + my ($class, $plugin_config, $zone) = @_; + + die "please implement inside plugin"; +} + +sub get_reversedns_zone { + my ($class, $plugin_config, $subnetid, $subnet, $ip) = @_; + + die "please implement inside plugin"; } sub on_update_hook { diff --git a/PVE/Network/SDN/Dns/PowerdnsPlugin.pm b/PVE/Network/SDN/Dns/PowerdnsPlugin.pm index 4c00a26..d93fb06 100644 --- a/PVE/Network/SDN/Dns/PowerdnsPlugin.pm +++ b/PVE/Network/SDN/Dns/PowerdnsPlugin.pm @@ -52,6 +52,19 @@ sub add_a_record { my $type = Net::IP::ip_is_ipv6($ip) ? "AAAA" : "A"; my $fqdn = $hostname.".".$zone."."; + my $zonecontent = get_zone_content($plugin_config, $zone); + my $existing_rrset = get_zone_rrset($zonecontent, $fqdn); + + my $final_records = []; + my $foundrecord = undef; + foreach my $record (@{$existing_rrset->{records}}) { + if($record->{content} eq $ip) { + $foundrecord = 1; + next; + } + push @$final_records, $record; + } + return if $foundrecord; my $record = { content => $ip, disabled => JSON::false, @@ -59,11 +72,13 @@ sub add_a_record { type => $type, priority => 0 }; + push @$final_records, $record; + my $rrset = { name => $fqdn, type => $type, ttl => $ttl, changetype => "REPLACE", - records => [ $record ] }; + records => $final_records }; my $params = { rrsets => [ $rrset ] }; @@ -123,10 +138,37 @@ sub del_a_record { my $fqdn = $hostname.".".$zone."."; my $type = Net::IP::ip_is_ipv6($ip) ? "AAAA" : "A"; - my $rrset = { name => $fqdn, - type => $type, - changetype => "DELETE", - records => [] }; + my $zonecontent = get_zone_content($plugin_config, $zone); + my $existing_rrset = get_zone_rrset($zonecontent, $fqdn); + + my $final_records = []; + my $foundrecord = undef; + foreach my $record (@{$existing_rrset->{records}}) { + if ($record->{content} eq $ip) { + $foundrecord = 1; + next; + } + push @$final_records, $record; + } + return if !$foundrecord; + + my $rrset = {}; + + if (scalar (@{$final_records}) > 0) { + #if we still have other records, we rewrite them without removed ip + $rrset = { name => $fqdn, + type => $type, + ttl => $existing_rrset->{ttl}, + changetype => "REPLACE", + records => $final_records }; + + } else { + + $rrset = { name => $fqdn, + type => $type, + changetype => "DELETE", + records => [] }; + } my $params = { rrsets => [ $rrset ] }; @@ -176,7 +218,7 @@ sub verify_zone { my $headers = ['Content-Type' => 'application/json; charset=UTF-8', 'X-API-Key' => $key]; eval { - PVE::Network::SDN::api_request("GET", "$url/zones/$zone", $headers); + PVE::Network::SDN::api_request("GET", "$url/zones/$zone?rrsets=false", $headers); }; if ($@) { @@ -249,6 +291,39 @@ sub on_update_hook { } } + +sub get_zone_content { + my ($plugin_config, $zone) = @_; + + #verify that api is working + + my $url = $plugin_config->{url}; + my $key = $plugin_config->{key}; + my $headers = ['Content-Type' => 'application/json; charset=UTF-8', 'X-API-Key' => $key]; + + my $result = undef; + eval { + $result = PVE::Network::SDN::api_request("GET", "$url/zones/$zone", $headers); + }; + + if ($@) { + die "can't read zone $zone: $@"; + } + return $result; +} + +sub get_zone_rrset { + my ($zonecontent, $name) = @_; + + my $rrsetresult = undef; + foreach my $rrset (@{$zonecontent->{rrsets}}) { + next if $rrset->{name} ne $name; + $rrsetresult = $rrset; + last; + } + return $rrsetresult; +} + 1; diff --git a/PVE/Network/SDN/Subnets.pm b/PVE/Network/SDN/Subnets.pm index 5446044..25261ac 100644 --- a/PVE/Network/SDN/Subnets.pm +++ b/PVE/Network/SDN/Subnets.pm @@ -257,7 +257,7 @@ sub add_ip { } sub update_ip { - my ($zone, $subnetid, $subnet, $ip, $hostname, $mac, $description) = @_; + my ($zone, $subnetid, $subnet, $ip, $hostname, $oldhostname, $mac, $description) = @_; return if !$subnet || !$ip; @@ -287,10 +287,15 @@ sub update_ip { die $@ if $@; } + return if $hostname eq $oldhostname; + eval { #add dns + + &$del_dns_record($dnszone, $dns, $oldhostname, $ip); &$add_dns_record($dnszone, $dns, $hostname, $ip); #add reverse dns + &$del_dns_ptr_record($reversednszone, $reversedns, $ip); &$add_dns_ptr_record($reversednszone, $dnszone, $reversedns, $hostname, $ip); }; } diff --git a/PVE/Network/SDN/Vnets.pm b/PVE/Network/SDN/Vnets.pm index 7421adf..ff39eef 100644 --- a/PVE/Network/SDN/Vnets.pm +++ b/PVE/Network/SDN/Vnets.pm @@ -134,10 +134,10 @@ sub add_cidr { } sub update_cidr { - my ($vnetid, $cidr, $hostname, $mac, $description) = @_; + my ($vnetid, $cidr, $hostname, $oldhostname, $mac, $description) = @_; my ($zone, $subnetid, $subnet, $ip) = PVE::Network::SDN::Vnets::get_subnet_from_vnet_cidr($vnetid, $cidr); - PVE::Network::SDN::Subnets::update_ip($zone, $subnetid, $subnet, $ip, $hostname, $mac, $description); + PVE::Network::SDN::Subnets::update_ip($zone, $subnetid, $subnet, $ip, $hostname, $oldhostname, $mac, $description); } sub del_cidr { -- 2.20.1