diff options
author | Martin Kosek <mkosek@redhat.com> | 2011-06-01 14:51:06 +0200 |
---|---|---|
committer | Martin Kosek <mkosek@redhat.com> | 2011-06-15 09:02:09 +0200 |
commit | f21508978511d40a60fbdaaa786bcc96f99578d5 (patch) | |
tree | 61f1fcc141b48cb5b944535abcf3728e575f4585 | |
parent | 058e3d03068f84d4fd62e1ae77156329ceda2537 (diff) | |
download | freeipa-f21508978511d40a60fbdaaa786bcc96f99578d5.tar.gz freeipa-f21508978511d40a60fbdaaa786bcc96f99578d5.tar.xz freeipa-f21508978511d40a60fbdaaa786bcc96f99578d5.zip |
Improve DNS zone creation
When a new DNS zone is being created a local hostname is set as a
nameserver of the new zone. However, when the zone is created
during ipa-replica-prepare, the the current master/replica doesn't
have to be an IPA server with DNS support. This would lead to DNS
zones with incorrect NS records as they wouldn't point to a valid
name server.
Now, a list of all master servers with DNS support is retrieved
during DNS zone creation and added as NS records for a new DNS
zone.
https://fedorahosted.org/freeipa/ticket/1261
-rwxr-xr-x | install/tools/ipa-replica-prepare | 8 | ||||
-rw-r--r-- | ipalib/plugins/dns.py | 20 | ||||
-rw-r--r-- | ipaserver/install/bindinstance.py | 67 |
3 files changed, 74 insertions, 21 deletions
diff --git a/install/tools/ipa-replica-prepare b/install/tools/ipa-replica-prepare index cd13f5d93..8117bfcdd 100755 --- a/install/tools/ipa-replica-prepare +++ b/install/tools/ipa-replica-prepare @@ -425,8 +425,6 @@ def main(): ip_address = str(ip) ip_prefixlen = ip.prefixlen - ns_ip_address = resolve_host(api.env.host) - if ip.defaultnet: revzone = ip.reverse_dns if ip.version == 4: @@ -445,10 +443,10 @@ def main(): if prefix > 0: ip_prefixlen = prefix else: - add_reverse_zone(ip_address, ip_prefixlen, ns_ip_address) + add_reverse_zone(ip_address, ip_prefixlen) - zone = add_zone(domain, nsaddr=ns_ip_address) - add_fwd_rr(zone, name, ip_address) + add_zone(domain) + add_fwd_rr(domain, name, ip_address) add_ptr_rr(ip_address, ip_prefixlen, replica_fqdn) try: diff --git a/ipalib/plugins/dns.py b/ipalib/plugins/dns.py index 42ca498c9..cc2e6e548 100644 --- a/ipalib/plugins/dns.py +++ b/ipalib/plugins/dns.py @@ -105,6 +105,7 @@ from ipalib import Flag, Int, List, Str, StrEnum from ipalib.plugins.baseldap import * from ipalib import _, ngettext from ipapython import dnsclient +from ldap import explode_dn # supported resource record types _record_types = ( @@ -559,6 +560,25 @@ class dnsrecord(LDAPObject): cliname = attr return cliname + def get_dns_masters(self): + ldap = self.api.Backend.ldap2 + base_dn = 'cn=masters,cn=ipa,cn=etc,%s' % self.api.env.basedn + ldap_filter = '(&(objectClass=ipaConfigObject)(cn=DNS))' + dns_masters = [] + + try: + entries = ldap.find_entries(filter=ldap_filter, base_dn=base_dn)[0] + + for entry in entries: + master_dn = entry[0] + if master_dn.startswith('cn='): + master = explode_dn(master_dn)[1].replace('cn=','') + dns_masters.append(master) + except errors.NotFound: + return [] + + return dns_masters + api.register(dnsrecord) diff --git a/ipaserver/install/bindinstance.py b/ipaserver/install/bindinstance.py index fc6519d96..2f897b423 100644 --- a/ipaserver/install/bindinstance.py +++ b/ipaserver/install/bindinstance.py @@ -28,6 +28,7 @@ import ldap import service from ipaserver import ipaldap from ipaserver.install.dsinstance import realm_to_serverid +from ipaserver.install.installutils import resolve_host from ipapython import sysrestore from ipapython import ipautil @@ -125,39 +126,69 @@ def dns_zone_exists(name): else: return True -def add_zone(name, zonemgr=None, dns_backup=None, nsaddr=None, update_policy=None): - if not update_policy: +def add_zone(name, zonemgr=None, dns_backup=None, ns_hostname=None, ns_ip_address=None, + update_policy=None): + if update_policy is None: update_policy = "grant %(realm)s krb5-self * A; grant %(realm)s krb5-self * AAAA;" % dict(realm=api.env.realm) + if ns_hostname is None: + # automatically retrieve list of DNS masters + dns_masters = api.Object.dnsrecord.get_dns_masters() + if not dns_masters: + raise errors.NotFound("No IPA server with DNS support found!") + ns_main = dns_masters.pop(0) + ns_replicas = dns_masters + ns_ip_address = resolve_host(ns_main) + else: + ns_main = ns_hostname + ns_replicas = [] + try: api.Command.dnszone_add(unicode(name), - idnssoamname=unicode(api.env.host+"."), + idnssoamname=unicode(ns_main+'.'), idnssoarname=unicode(zonemgr), - ip_address=unicode(nsaddr), + ip_address=unicode(ns_ip_address), idnsallowdynupdate=True, idnsupdatepolicy=unicode(update_policy)) except (errors.DuplicateEntry, errors.EmptyModlist): pass - add_rr(name, "@", "NS", api.env.host+'.', dns_backup, force=True) - return name + nameservers = ns_replicas + [ns_main] + for hostname in nameservers: + add_ns_rr(name, hostname, dns_backup=None, force=True) + -def add_reverse_zone(ip_address, ip_prefixlen, ns_ip_address, update_policy=None, dns_backup=None): +def add_reverse_zone(ip_address, ip_prefixlen, ns_hostname=None, ns_ip_address=None, + ns_replicas=[], update_policy=None, dns_backup=None): zone, name = get_reverse_zone(ip_address, ip_prefixlen) - if not update_policy: + if update_policy is None: update_policy = "grant %s krb5-subdomain %s. PTR;" % (api.env.realm, zone) + + if ns_hostname is None: + # automatically retrieve list of DNS masters + dns_masters = api.Object.dnsrecord.get_dns_masters() + if not dns_masters: + raise errors.NotFound("No IPA server with DNS support found!") + ns_main = dns_masters.pop(0) + ns_replicas = dns_masters + ns_ip_address = resolve_host(ns_main) + else: + ns_main = ns_hostname + ns_replicas = [] + try: api.Command.dnszone_add(unicode(zone), - idnssoamname=unicode(api.env.host+"."), + idnssoamname=unicode(ns_main+'.'), idnsallowdynupdate=True, ip_address=unicode(ns_ip_address), idnsupdatepolicy=unicode(update_policy)) except (errors.DuplicateEntry, errors.EmptyModlist): pass - add_rr(zone, "@", "NS", api.env.host+".", dns_backup, force=True) + nameservers = ns_replicas + [ns_main] + for hostname in nameservers: + add_ns_rr(zone, hostname, dns_backup=None, force=True) - return zone def add_rr(zone, name, type, rdata, dns_backup=None, **kwargs): addkw = { '%srecord' % str(type.lower()) : unicode(rdata) } @@ -180,6 +211,10 @@ def add_ptr_rr(ip_address, ip_prefixlen, fqdn, dns_backup=None): zone, name = get_reverse_zone(ip_address, ip_prefixlen) add_rr(zone, name, "PTR", fqdn+".", dns_backup) +def add_ns_rr(zone, hostname, dns_backup=None, force=True): + add_rr(zone, "@", "NS", hostname+'.', dns_backup=dns_backup, + force=force) + def del_rr(zone, name, type, rdata): delkw = { '%srecord' % str(type.lower()) : unicode(rdata) } try: @@ -367,11 +402,11 @@ class BindInstance(service.Service): self._ldap_mod("dns.ldif", self.sub_dict) def __setup_zone(self): - zone = add_zone(self.domain, self.zonemgr, - self.dns_backup, self.ip_address) + add_zone(self.domain, self.zonemgr, dns_backup=self.dns_backup, + ns_hostname=api.env.host, ns_ip_address=self.ip_address) def __add_self_ns(self): - add_rr(self.domain, "@", "NS", api.env.host+'.', self.dns_backup, force=True) + add_ns_rr(self.domain, api.env.host, self.dns_backup, force=True) def __add_self(self): zone = self.domain @@ -400,8 +435,8 @@ class BindInstance(service.Service): add_ptr_rr(self.ip_address, self.ip_prefixlen, self.fqdn) def __setup_reverse_zone(self): - add_reverse_zone(self.ip_address, self.ip_prefixlen, self.ip_address, - dns_backup=self.dns_backup) + add_reverse_zone(self.ip_address, self.ip_prefixlen, ns_hostname=api.env.host, + ns_ip_address=self.ip_address, dns_backup=self.dns_backup) def __setup_principal(self): dns_principal = "DNS/" + self.fqdn + "@" + self.realm |