Hi,

the attached patches fix <https://fedorahosted.org/freeipa/ticket/3547>.

Honza

--
Jan Cholasta
>From e5a6141d932bd5f9685a83ad9b039ea334363a00 Mon Sep 17 00:00:00 2001
From: Jan Cholasta <jchol...@redhat.com>
Date: Fri, 12 Apr 2013 13:16:17 +0200
Subject: [PATCH 1/2] Use A/AAAA records instead of CNAME records in ipa-ca.

https://fedorahosted.org/freeipa/ticket/3547
---
 install/share/bind.zone.db.template |  2 +-
 install/tools/ipa-ca-install        |  2 +-
 install/tools/ipa-replica-manage    |  1 +
 install/tools/ipa-upgradeconfig     | 55 ++++++++++++-----------
 ipaserver/install/bindinstance.py   | 87 +++++++++++++++++++++++++++----------
 ipaserver/install/cainstance.py     |  6 +--
 6 files changed, 100 insertions(+), 53 deletions(-)

diff --git a/install/share/bind.zone.db.template b/install/share/bind.zone.db.template
index 5ee71d6..6795bb0 100644
--- a/install/share/bind.zone.db.template
+++ b/install/share/bind.zone.db.template
@@ -26,4 +26,4 @@ _kpasswd._udp		IN SRV 0 100 464	$HOST
 $OPTIONAL_NTP
 
 ; CNAME for IPA CA replicas (used for CRL, OCSP)
-$IPA_CA_CNAME		IN CNAME		$HOST
+$IPA_CA_RECORD
diff --git a/install/tools/ipa-ca-install b/install/tools/ipa-ca-install
index f8f7e1d..2ebce60 100755
--- a/install/tools/ipa-ca-install
+++ b/install/tools/ipa-ca-install
@@ -85,7 +85,7 @@ def install_dns_records(config, options):
     try:
         api.Backend.ldap2.connect(bind_dn=DN(('cn', 'Directory Manager')),
                                   bind_pw=config.dirman_password)
-        bind.add_ipa_ca_cname(config.host_name, config.domain_name)
+        bind.add_ipa_ca_dns_records(config.host_name, config.domain_name)
     finally:
         if api.Backend.ldap2.isconnected():
              api.Backend.ldap2.disconnect()
diff --git a/install/tools/ipa-replica-manage b/install/tools/ipa-replica-manage
index 636529c..5d5b5eb 100755
--- a/install/tools/ipa-replica-manage
+++ b/install/tools/ipa-replica-manage
@@ -718,6 +718,7 @@ def del_master(realm, hostname, options):
                 api.Backend.ldap2.connect(ccache=ccache)
             bind = bindinstance.BindInstance()
             bind.remove_master_dns_records(hostname, realm, realm.lower())
+            bind.remove_ipa_ca_dns_records(hostname, realm.lower())
     except Exception, e:
         print "Failed to cleanup %s DNS entries: %s" % (hostname, e)
         print "You may need to manually remove them from the tree"
diff --git a/install/tools/ipa-upgradeconfig b/install/tools/ipa-upgradeconfig
index c690544..95231af 100644
--- a/install/tools/ipa-upgradeconfig
+++ b/install/tools/ipa-upgradeconfig
@@ -727,31 +727,36 @@ def migrate_crl_publish_dir(ca):
                      'request pki-ca restart')
     return True
 
-def add_server_cname_records():
-    root_logger.info('[Add missing server CNAME records]')
+def add_ca_dns_records():
+    root_logger.info('[Add missing CA DNS records]')
 
-    if not sysupgrade.get_upgrade_state('dns', 'ipa_ca_cname'):
-        try:
-            api.Backend.ldap2.connect(autobind=True)
-        except ipalib.errors.PublicError, e:
-            root_logger.error("Cannot connect to LDAP to add DNS records: %s", e)
-        else:
-            ret = api.Command['dns_is_enabled']()
-            if not ret['result']:
-                root_logger.info('DNS is not configured')
-                sysupgrade.set_upgrade_state('dns', 'ipa_ca_cname', True)
-                return
-
-            bind = bindinstance.BindInstance()
-            # DNS is enabled, so let bindinstance find out if CA is enabled
-            # and let it add the CNAME in that case
-            bind.add_ipa_ca_cname(api.env.host, api.env.domain, ca_configured=None)
-            sysupgrade.set_upgrade_state('dns', 'ipa_ca_cname', True)
-        finally:
-            if api.Backend.ldap2.isconnected():
-                 api.Backend.ldap2.disconnect()
-    else:
-        root_logger.info('IPA CA CNAME already processed')
+    if sysupgrade.get_upgrade_state('dns', 'ipa_ca_records'):
+        root_logger.info('IPA CA DNS records already processed')
+        return
+
+    try:
+        api.Backend.ldap2.connect(autobind=True)
+    except ipalib.errors.PublicError, e:
+        root_logger.error("Cannot connect to LDAP to add DNS records: %s", e)
+        return
+
+    ret = api.Command['dns_is_enabled']()
+    if not ret['result']:
+        root_logger.info('DNS is not configured')
+        sysupgrade.set_upgrade_state('dns', 'ipa_ca_records', True)
+        return
+
+    bind = bindinstance.BindInstance()
+
+    root_logger.info('Converting IPA CA CNAME records to A/AAAA records')
+    bind.convert_ipa_ca_cnames(api.env.domain)
+
+    # DNS is enabled, so let bindinstance find out if CA is enabled
+    # and let it add the CNAME in that case
+    bind.add_ipa_ca_dns_records(api.env.host, api.env.domain,
+                                ca_configured=None)
+
+    sysupgrade.set_upgrade_state('dns', 'ipa_ca_records', True)
 
 def main():
     """
@@ -845,7 +850,7 @@ def main():
 
     cleanup_kdc(fstore)
     setup_firefox_extension(fstore)
-    add_server_cname_records()
+    add_ca_dns_records()
     changed_psearch = named_enable_psearch()
     changed_autoincrement = named_enable_serial_autoincrement()
     changed_gssapi_conf = named_update_gssapi_configuration()
diff --git a/ipaserver/install/bindinstance.py b/ipaserver/install/bindinstance.py
index 20d3349..cb35c80 100644
--- a/ipaserver/install/bindinstance.py
+++ b/ipaserver/install/bindinstance.py
@@ -29,7 +29,7 @@ import installutils
 import service
 from ipaserver.plugins import ldap2
 from ipaserver.install.dsinstance import realm_to_serverid
-from ipaserver.install.cainstance import IPA_CA_CNAME
+from ipaserver.install.cainstance import IPA_CA_RECORD
 from ipapython import sysrestore, ipautil, ipaldap
 from ipapython.ipa_log_manager import *
 from ipapython.dn import DN
@@ -357,6 +357,13 @@ def del_rr(zone, name, type, rdata):
     except (errors.NotFound, errors.AttrValueNotFound, errors.EmptyModlist):
         pass
 
+def del_fwd_rr(zone, host, ip_address):
+    addr = netaddr.IPAddress(ip_address)
+    if addr.version == 4:
+        del_rr(zone, host, "A", ip_address)
+    elif addr.version == 6:
+        del_rr(zone, host, "AAAA", ip_address)
+
 def get_rr(zone, name, type):
     rectype = '%srecord' % unicode(type.lower())
     ret = api.Command.dnsrecord_find(unicode(zone), unicode(name))
@@ -367,6 +374,9 @@ def get_rr(zone, name, type):
 
     return []
 
+def get_fwd_rr(zone, host):
+    return [x for t in ("A", "AAAA") for x in get_rr(zone, host, t)]
+
 def zonemgr_callback(option, opt_str, value, parser):
     """
     Properly validate and convert --zonemgr Option to IA5String
@@ -523,7 +533,7 @@ class BindInstance(service.Service):
         if self.reverse_zone is not None:
             self.step("setting up reverse zone", self.__setup_reverse_zone)
         self.step("setting up our own record", self.__add_self)
-        self.step("setting up CA CNAME record", self.__add_ipa_ca_cname)
+        self.step("setting up CA record", self.__add_ipa_ca_record)
 
         self.step("setting up kerberos principal", self.__setup_principal)
         self.step("setting up named.conf", self.__setup_named_conf)
@@ -568,6 +578,15 @@ class BindInstance(service.Service):
         else:
             optional_ntp = ""
 
+        addr = netaddr.IPAddress(self.ip_address)
+        if addr.version in (4, 6):
+            ipa_ca = "%s\t\t\tIN %s\t\t\t%s\n" % (
+                IPA_CA_RECORD,
+                "A" if addr.version == 4 else "AAAA",
+                self.ip_address)
+        else:
+            ipa_ca = ""
+
         boolean_var = {}
         for var in ('persistent_search', 'serial_autoincrement'):
             boolean_var[var] = "yes" if getattr(self, var, False) else "no"
@@ -583,7 +602,7 @@ class BindInstance(service.Service):
                              OPTIONAL_NTP=optional_ntp,
                              ZONEMGR=self.zonemgr,
                              ZONE_REFRESH=self.zone_refresh,
-                             IPA_CA_CNAME=IPA_CA_CNAME,
+                             IPA_CA_RECORD=ipa_ca,
                              PERSISTENT_SEARCH=boolean_var['persistent_search'],
                              SERIAL_AUTOINCREMENT=boolean_var['serial_autoincrement'],)
 
@@ -610,27 +629,31 @@ class BindInstance(service.Service):
     def __add_self_ns(self):
         add_ns_rr(self.domain, api.env.host, self.dns_backup, force=True)
 
-    def __add_ipa_ca_cname(self):
-        if self.ca_configured is False:
-            root_logger.debug("CA is not configured, skip this step")
+    def _add_ipa_ca_dns_records(self, domain_name, fqdn, addrs, ca_configured):
+        if ca_configured is False:
+            root_logger.debug("CA is not configured")
             return
-        elif self.ca_configured is None:
+        elif ca_configured is None:
             # we do not know if CA is configured for this host and we can
-            # add the CA CNAME record. So we need to find out
+            # add the CA record. So we need to find out
             root_logger.debug("Check if CA is enabled for this host")
-            base_dn = DN(('cn', api.env.host), ('cn', 'masters'), ('cn', 'ipa'),
+            base_dn = DN(('cn', fqdn), ('cn', 'masters'), ('cn', 'ipa'),
                          ('cn', 'etc'), api.env.basedn)
             ldap_filter = '(&(objectClass=ipaConfigObject)(cn=CA))'
             try:
                 api.Backend.ldap2.find_entries(filter=ldap_filter, base_dn=base_dn)
             except ipalib.errors.NotFound:
-                # CA is not configured
                 root_logger.debug("CA is not configured")
                 return
             else:
-                root_logger.debug("CA is configured for this host, continue")
+                root_logger.debug("CA is configured for this host")
+
+        for addr in addrs:
+            add_fwd_rr(domain_name, IPA_CA_RECORD, addr)
 
-        add_rr(self.domain, IPA_CA_CNAME, "CNAME", self.host_in_rr)
+    def __add_ipa_ca_record(self):
+        self._add_ipa_ca_dns_records(self.domain, self.fqdn, [self.ip_address],
+                                     self.ca_configured)
 
     def __add_self(self):
         zone = self.domain
@@ -743,14 +766,23 @@ class BindInstance(service.Service):
         self.ca_configured = ca_configured
 
         self.__add_self()
-        self.__add_ipa_ca_cname()
+        self.__add_ipa_ca_record()
 
-    def add_ipa_ca_cname(self, fqdn, domain_name, ca_configured=True):
-        self.host = fqdn.split(".")[0]
-        self.fqdn = fqdn
-        self.domain = domain_name
-        self.ca_configured = ca_configured
-        self.__add_ipa_ca_cname()
+    def add_ipa_ca_dns_records(self, fqdn, domain_name, ca_configured=True):
+        host, zone = fqdn.split(".", 1)
+        if dns_zone_exists(zone):
+            addrs = get_fwd_rr(zone, host)
+        else:
+            addrs = installutils.resolve_host(fqdn)
+
+        self._add_ipa_ca_dns_records(domain_name, fqdn, addrs, ca_configured)
+
+    def convert_ipa_ca_cnames(self, domain_name):
+        cnames = get_rr(domain_name, IPA_CA_RECORD, "CNAME")
+        for cname in cnames:
+            del_rr(domain_name, IPA_CA_RECORD, "CNAME", cname)
+        for cname in cnames:
+            self.add_ipa_ca_dns_records(cname[:-1], domain_name, None)
 
     def remove_master_dns_records(self, fqdn, realm_name, domain_name):
         host = fqdn.split(".")[0]
@@ -769,16 +801,15 @@ class BindInstance(service.Service):
             ("_kpasswd._tcp", "SRV", "0 100 464 %s" % self.host_in_rr),
             ("_kpasswd._udp", "SRV", "0 100 464 %s" % self.host_in_rr),
             ("_ntp._udp", "SRV", "0 100 123 %s" % self.host_in_rr),
-            (IPA_CA_CNAME, "CNAME", self.host_in_rr),
             ("@", "NS", fqdn+"."),
         )
 
         for (record, type, rdata) in resource_records:
             del_rr(zone, record, type, rdata)
 
-        areclist = [("A", x) for x in get_rr(zone, host, "A")] + [("AAAA", x) for x in get_rr(zone, host, "AAAA")]
-        for (type, rdata) in areclist:
-            del_rr(zone, host, type, rdata)
+        areclist = get_fwd_rr(zone, host)
+        for rdata in areclist:
+            del_fwd_rr(zone, host, rdata)
 
             rzone = find_reverse_zone(rdata)
             if rzone is not None:
@@ -787,6 +818,16 @@ class BindInstance(service.Service):
                 # remove also master NS record from the reverse zone
                 del_rr(rzone, "@", "NS", fqdn+".")
 
+    def remove_ipa_ca_dns_records(self, fqdn, domain_name):
+        host, zone = fqdn.split(".", 1)
+        if dns_zone_exists(zone):
+            addrs = get_fwd_rr(zone, host)
+        else:
+            addrs = installutils.resolve_host(fqdn)
+
+        for addr in addrs:
+            del_fwd_rr(domain_name, IPA_CA_RECORD, addr)
+
     def check_global_configuration(self):
         """
         Check global DNS configuration in LDAP server and inform user when it
diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py
index 3476b2c..8c89947 100644
--- a/ipaserver/install/cainstance.py
+++ b/ipaserver/install/cainstance.py
@@ -64,7 +64,7 @@ PKI_DS_USER = dogtag.install_constants.DS_USER
 
 # When IPA is installed with DNS support, this CNAME should hold all IPA
 # replicas with CA configured
-IPA_CA_CNAME = "ipa-ca"
+IPA_CA_RECORD = "ipa-ca"
 
 # We need to reset the template because the CA uses the regular boot
 # information
@@ -1271,7 +1271,7 @@ class CAInstance(service.Service):
         changed = False
 
         # OCSP extension
-        ocsp_url = 'http://%s.%s/ca/ocsp' % (IPA_CA_CNAME, ipautil.format_netloc(domain))
+        ocsp_url = 'http://%s.%s/ca/ocsp' % (IPA_CA_RECORD, ipautil.format_netloc(domain))
 
         ocsp_location_0 = installutils.get_directive(
             self.dogtag_constants.IPA_SERVICE_PROFILE,
@@ -1298,7 +1298,7 @@ class CAInstance(service.Service):
 
 
         # CRL extension
-        crl_url = 'http://%s.%s/ipa/crl/MasterCRL.bin'% (IPA_CA_CNAME, ipautil.format_netloc(domain))
+        crl_url = 'http://%s.%s/ipa/crl/MasterCRL.bin'% (IPA_CA_RECORD, ipautil.format_netloc(domain))
 
         crl_point_0 = installutils.get_directive(
             self.dogtag_constants.IPA_SERVICE_PROFILE,
-- 
1.8.1.4

>From 64358771a48307dd8b19a333fb02615699e3f46d Mon Sep 17 00:00:00 2001
From: Jan Cholasta <jchol...@redhat.com>
Date: Fri, 12 Apr 2013 13:17:49 +0200
Subject: [PATCH 2/2] Delete DNS records in ipa-ca on ipa-csreplica-manage del.

https://fedorahosted.org/freeipa/ticket/3547
---
 install/tools/ipa-csreplica-manage | 14 +++++++++++++-
 1 file changed, 13 insertions(+), 1 deletion(-)

diff --git a/install/tools/ipa-csreplica-manage b/install/tools/ipa-csreplica-manage
index cd2fd01..a5a984a 100755
--- a/install/tools/ipa-csreplica-manage
+++ b/install/tools/ipa-csreplica-manage
@@ -25,7 +25,7 @@ import os
 import krbV
 from ipapython.ipa_log_manager import *
 
-from ipaserver.install import replication, installutils
+from ipaserver.install import replication, installutils, bindinstance
 from ipalib import api, errors, util
 from ipapython import ipautil, ipaldap, version, dogtag
 from ipapython.dn import DN
@@ -370,6 +370,18 @@ def del_master(realm, hostname, options):
         except Exception, e:
             sys.exit("There were issues removing a connection: %s" % e)
 
+    # 6. And clean up the removed replica DNS entries if any.
+    try:
+        if bindinstance.dns_container_exists(options.host, api.env.basedn,
+                                             dm_password=options.dirman_passwd):
+            api.Backend.ldap2.connect(bind_dn=DN(('cn', 'Directory Manager')),
+                                      bind_pw=options.dirman_passwd)
+            bind = bindinstance.BindInstance()
+            bind.remove_ipa_ca_dns_records(hostname, realm.lower())
+    except Exception, e:
+        print "Failed to cleanup %s DNS entries: %s" % (hostname, e)
+        print "You may need to manually remove them from the tree"
+
 def add_link(realm, replica1, replica2, dirman_passwd, options):
     repl2 = get_cs_replication_manager(realm, replica2, dirman_passwd)
     try:
-- 
1.8.1.4

_______________________________________________
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel

Reply via email to