Blob Blame History Raw
From 96695bb8e414be941e07d43652516a99cfd89a24 Mon Sep 17 00:00:00 2001
From: Petr Spacek <pspacek@redhat.com>
Date: Sun, 20 Dec 2015 18:36:48 +0100
Subject: [PATCH] DNSSEC: ipa-dnskeysyncd: Skip zones with old DNSSEC metadata
 in LDAP

This filtering is useful in cases where LDAP contains DNS zones which
have old metadata objects and DNSSEC disabled. Such zones must be
ignored to prevent errors while calling dnssec-keyfromlabel or rndc.

https://fedorahosted.org/freeipa/ticket/5348

Reviewed-By: Martin Basti <mbasti@redhat.com>
Reviewed-By: Martin Basti <mbasti@redhat.com>
---
 ipapython/dnssec/bindmgr.py   | 16 +++++++++++++---
 ipapython/dnssec/keysyncer.py | 24 ++++++++++++++++++------
 2 files changed, 31 insertions(+), 9 deletions(-)

diff --git a/ipapython/dnssec/bindmgr.py b/ipapython/dnssec/bindmgr.py
index 70caaf4ee74f594c652cd82bccb8964e172bc719..d81dad940df49e79f4534c2224c10ecf192794ba 100644
--- a/ipapython/dnssec/bindmgr.py
+++ b/ipapython/dnssec/bindmgr.py
@@ -191,10 +191,20 @@ class BINDMgr(object):
 
         self.notify_zone(zone)
 
-    def sync(self):
-        """Synchronize list of zones in LDAP with BIND."""
+    def sync(self, dnssec_zones):
+        """Synchronize list of zones in LDAP with BIND.
+
+        dnssec_zones lists zones which should be processed. All other zones
+        will be ignored even though they were modified using ldap_event().
+
+        This filter is useful in cases where LDAP contains DNS zones which
+        have old metadata objects and DNSSEC disabled. Such zones must be
+        ignored to prevent errors while calling dnssec-keyfromlabel or rndc.
+        """
         self.log.debug('Key metadata in LDAP: %s' % self.ldap_keys)
-        for zone in self.modified_zones:
+        self.log.debug('Zones modified but skipped during bindmgr.sync: %s',
+                       self.modified_zones - dnssec_zones)
+        for zone in self.modified_zones.intersection(dnssec_zones):
             self.sync_zone(zone)
 
         self.modified_zones = set()
diff --git a/ipapython/dnssec/keysyncer.py b/ipapython/dnssec/keysyncer.py
index de5b5aa5f670db4c58fb92b989e181d45d887b55..5ba9baaab30b07d2f4e4ae3a3507898d08a0d6c1 100644
--- a/ipapython/dnssec/keysyncer.py
+++ b/ipapython/dnssec/keysyncer.py
@@ -6,6 +6,8 @@ import logging
 import ldap.dn
 import os
 
+import dns.name
+
 from ipaplatform.paths import paths
 from ipapython import ipautil
 
@@ -33,6 +35,7 @@ class KeySyncer(SyncReplConsumer):
 
         self.bindmgr = BINDMgr(self.api)
         self.init_done = False
+        self.dnssec_zones = set()
         SyncReplConsumer.__init__(self, *args, **kwargs)
 
     def _get_objclass(self, attrs):
@@ -112,7 +115,7 @@ class KeySyncer(SyncReplConsumer):
         self.ods_sync()
         self.hsm_replica_sync()
         self.hsm_master_sync()
-        self.bindmgr.sync()
+        self.bindmgr.sync(self.dnssec_zones)
 
     # idnsSecKey wrapper
     # Assumption: metadata points to the same key blob all the time,
@@ -121,23 +124,29 @@ class KeySyncer(SyncReplConsumer):
     def key_meta_add(self, uuid, dn, newattrs):
         self.hsm_replica_sync()
         self.bindmgr.ldap_event('add', uuid, newattrs)
-        self.bindmgr_sync()
+        self.bindmgr_sync(self.dnssec_zones)
 
     def key_meta_del(self, uuid, dn, oldattrs):
         self.bindmgr.ldap_event('del', uuid, oldattrs)
-        self.bindmgr_sync()
+        self.bindmgr_sync(self.dnssec_zones)
         self.hsm_replica_sync()
 
     def key_metadata_sync(self, uuid, dn, oldattrs, newattrs):
         self.bindmgr.ldap_event('mod', uuid, newattrs)
-        self.bindmgr_sync()
+        self.bindmgr_sync(self.dnssec_zones)
 
-    def bindmgr_sync(self):
+    def bindmgr_sync(self, dnssec_zones):
         if self.init_done:
-            self.bindmgr.sync()
+            self.bindmgr.sync(dnssec_zones)
 
     # idnsZone wrapper
     def zone_add(self, uuid, dn, newattrs):
+        zone = dns.name.from_text(newattrs['idnsname'][0])
+        if self.__is_dnssec_enabled(newattrs):
+            self.dnssec_zones.add(zone)
+        else:
+            self.dnssec_zones.discard(zone)
+
         if not self.ismaster:
             return
 
@@ -146,6 +155,9 @@ class KeySyncer(SyncReplConsumer):
         self.ods_sync()
 
     def zone_del(self, uuid, dn, oldattrs):
+        zone = dns.name.from_text(oldattrs['idnsname'][0])
+        self.dnssec_zones.discard(zone)
+
         if not self.ismaster:
             return
 
-- 
2.4.3