diff options
-rwxr-xr-x | install/tools/ipa-dns-install | 3 | ||||
-rwxr-xr-x | install/tools/ipa-replica-install | 6 | ||||
-rwxr-xr-x | install/tools/ipa-replica-prepare | 34 | ||||
-rwxr-xr-x | install/tools/ipa-server-install | 3 | ||||
-rw-r--r-- | ipalib/plugins/host.py | 45 | ||||
-rw-r--r-- | ipaserver/install/bindinstance.py | 52 |
6 files changed, 98 insertions, 45 deletions
diff --git a/install/tools/ipa-dns-install b/install/tools/ipa-dns-install index e8379191a..91edcca8a 100755 --- a/install/tools/ipa-dns-install +++ b/install/tools/ipa-dns-install @@ -113,6 +113,7 @@ def main(): sys.exit("Unable to resolve IP address for host name") else: ip_address = read_ip_address(api.env.host, fstore) + ip_prefixlen = ip_address.prefixlen ip_address = str(ip_address) logging.debug("will use ip_address: %s\n", ip_address) @@ -158,7 +159,7 @@ def main(): create_reverse = not options.no_reverse elif not options.no_reverse: create_reverse = bindinstance.create_reverse() - bind.setup(api.env.host, ip_address, api.env.realm, api.env.domain, dns_forwarders, conf_ntp, create_reverse, zonemgr=options.zonemgr) + bind.setup(api.env.host, ip_address, ip_prefixlen, api.env.realm, api.env.domain, dns_forwarders, conf_ntp, create_reverse, zonemgr=options.zonemgr) if bind.dm_password: api.Backend.ldap2.connect(bind_dn="cn=Directory Manager", bind_pw=bind.dm_password) diff --git a/install/tools/ipa-replica-install b/install/tools/ipa-replica-install index 6df512312..2848366dd 100755 --- a/install/tools/ipa-replica-install +++ b/install/tools/ipa-replica-install @@ -272,6 +272,7 @@ def install_bind(config, options): sys.exit("Unable to resolve IP address for host name") ip = installutils.parse_ip_address(ip_address) ip_address = str(ip) + ip_prefixlen = ip.prefixlen create_reverse = True if options.unattended: @@ -285,7 +286,7 @@ def install_bind(config, options): # specified, ask the user create_reverse = bindinstance.create_reverse() - bind.setup(config.host_name, ip_address, config.realm_name, + bind.setup(config.host_name, ip_address, ip_prefixlen, config.realm_name, config.domain_name, forwarders, options.conf_ntp, create_reverse) bind.create_instance() @@ -309,8 +310,9 @@ def install_dns_records(config, options): sys.exit("Unable to resolve IP address for host name") ip = installutils.parse_ip_address(ip_address) ip_address = str(ip) + ip_prefixlen = ip.prefixlen - bind.add_master_dns_records(config.host_name, ip_address, + bind.add_master_dns_records(config.host_name, ip_address, ip_prefixlen, config.realm_name, config.domain_name, options.conf_ntp) diff --git a/install/tools/ipa-replica-prepare b/install/tools/ipa-replica-prepare index 21f30f072..2765e4a0e 100755 --- a/install/tools/ipa-replica-prepare +++ b/install/tools/ipa-replica-prepare @@ -27,7 +27,7 @@ import krbV from ipapython import ipautil from ipaserver.install import bindinstance, dsinstance, installutils, certs -from ipaserver.install.bindinstance import add_zone, add_reverse_zone, add_rr, add_ptr_rr +from ipaserver.install.bindinstance import add_zone, add_reverse_zone, add_fwd_rr, add_ptr_rr, dns_zone_exists from ipaserver.install.replication import check_replication_plugin, enable_replication_version_checking from ipaserver.install.installutils import resolve_host from ipaserver.plugins.ldap2 import ldap2 @@ -426,12 +426,34 @@ def main(): name = domain.pop(0) domain = ".".join(domain) - ip_address = str(options.ip_address) + ip = options.ip_address + ip_address = str(ip) + ip_prefixlen = ip.prefixlen + + if ip.defaultnet: + revzone = ip.reverse_dns + if ip.version == 4: + prefix = 32 + dec = 8 + elif ip.version == 6: + prefix = 128 + dec = 4 + + while prefix > 0: + dummy, dot, revzone = revzone.partition('.') + prefix = prefix - dec + if dns_zone_exists(revzone): + break + + if prefix > 0: + ip_prefixlen = prefix + else: + ns_ip_address = resolve_host(api.env.host) + add_reverse_zone(ip_address, ip_prefixlen, ns_ip_address) + zone = add_zone(domain, nsaddr=ip_address) - add_rr(zone, name, "A", ip_address) - ns_ip_address = resolve_host(api.env.host) - add_reverse_zone(ip_address, ns_ip_address) - add_ptr_rr(ip_address, replica_fqdn) + add_fwd_rr(zone, name, ip_address) + add_ptr_rr(ip_address, ip_prefixlen, replica_fqdn) try: if not os.geteuid()==0: diff --git a/install/tools/ipa-server-install b/install/tools/ipa-server-install index e36d5af48..23e495e63 100755 --- a/install/tools/ipa-server-install +++ b/install/tools/ipa-server-install @@ -622,6 +622,7 @@ def main(): ip = read_ip_address(host_name, fstore) logging.debug("read ip_address: %s\n" % str(ip)) ip_address = str(ip) + ip_prefixlen = ip.prefixlen print "The IPA Master Server will be configured with" print "Hostname: " + host_name @@ -892,7 +893,7 @@ def main(): # specified, ask the user create_reverse = bindinstance.create_reverse() - bind.setup(host_name, ip_address, realm_name, domain_name, dns_forwarders, options.conf_ntp, create_reverse, zonemgr=options.zonemgr) + bind.setup(host_name, ip_address, ip_prefixlen, realm_name, domain_name, dns_forwarders, options.conf_ntp, create_reverse, zonemgr=options.zonemgr) if options.setup_dns: api.Backend.ldap2.connect(bind_dn="cn=Directory Manager", bind_pw=dm_password) diff --git a/ipalib/plugins/host.py b/ipalib/plugins/host.py index 52830de1b..4947986f6 100644 --- a/ipalib/plugins/host.py +++ b/ipalib/plugins/host.py @@ -91,8 +91,6 @@ from ipalib import _, ngettext from ipalib import x509 from ipapython.ipautil import ipa_generate_password from ipalib.request import context -if api.env.context in ['lite', 'server']: - from ipaserver.install.bindinstance import get_reverse_zone import base64 import nss.nss as nss import netaddr @@ -111,16 +109,37 @@ def is_forward_record(zone, str_address): if addr.version == 4: result = api.Command['dnsrecord_find'](zone, arecord=str_address) elif addr.version == 6: - result = api.Command['dnsrecord_find'](zone, aaarecord=str_address) + result = api.Command['dnsrecord_find'](zone, aaaarecord=str_address) else: raise ValueError('Invalid address family') return result['count'] > 0 +def get_reverse_zone(ipaddr): + ip = netaddr.IPAddress(ipaddr) + revdns = unicode(ip.reverse_dns) + + revzone = u'' + + result = api.Command['dnszone_find']()['result'] + for zone in result: + zonename = zone['idnsname'][0] + if revdns.endswith(zonename) and len(zonename) > len(revzone): + revzone = zonename + + if len(revzone) == 0: + raise errors.NotFound( + reason=_('DNS reverse zone for IP address %(addr)s not found') % dict(addr=ipaddr) + ) + + revname = revdns[:-len(revzone)-1] + + return revzone, revname + def remove_fwd_ptr(ipaddr, host, domain, recordtype): api.log.debug('deleting ipaddr %s' % ipaddr) - revzone, revname = get_reverse_zone(ipaddr) try: + revzone, revname = get_reverse_zone(ipaddr) delkw = { 'ptrrecord' : "%s.%s." % (host, domain) } api.Command['dnsrecord_del'](revzone, revname, **delkw) except errors.NotFound: @@ -321,19 +340,9 @@ class host_add(LDAPCreate): reason=_('DNS zone %(zone)s not found') % dict(zone=domain) ) if not options.get('no_reverse', False): - # we prefer lookup of the IP through the reverse zone - revzone, revname = get_reverse_zone(options['ip_address']) - # Verify that our reverse zone exists - match = False - for zone in result: - if revzone == zone['idnsname'][0]: - match = True - break - if not match: - raise errors.NotFound( - reason=_('Reverse DNS zone %(zone)s not found') % dict(zone=revzone) - ) try: + # we prefer lookup of the IP through the reverse zone + revzone, revname = get_reverse_zone(options['ip_address']) reverse = api.Command['dnsrecord_find'](revzone, idnsname=revname) if reverse['count'] > 0: raise errors.DuplicateEntry(message=u'This IP address is already assigned.') @@ -381,10 +390,12 @@ class host_add(LDAPCreate): add_forward_record(domain, parts[0], options['ip_address']) if not options.get('no_reverse', False): - revzone, revname = get_reverse_zone(options['ip_address']) try: + revzone, revname = get_reverse_zone(options['ip_address']) addkw = { 'ptrrecord' : keys[-1]+'.' } api.Command['dnsrecord_add'](revzone, revname, **addkw) + except errors.NotFound: + pass except errors.EmptyModlist: # the entry already exists and matches pass diff --git a/ipaserver/install/bindinstance.py b/ipaserver/install/bindinstance.py index fa2745170..fc6519d96 100644 --- a/ipaserver/install/bindinstance.py +++ b/ipaserver/install/bindinstance.py @@ -98,16 +98,20 @@ def dns_container_exists(fqdn, suffix): return ret -def get_reverse_zone(ip_address_str): +def get_reverse_zone(ip_address_str, ip_prefixlen): ip = netaddr.IPAddress(ip_address_str) + items = ip.reverse_dns.split('.') + if ip.version == 4: - name, dot, zone = ip.reverse_dns.partition('.') + pos = 4 - ip_prefixlen / 8 elif ip.version == 6: - name = '.'.join(ip.reverse_dns.split('.')[:8]) - zone = '.'.join(ip.reverse_dns.split('.')[8:]) + pos = 32 - ip_prefixlen / 4 else: raise ValueError('Bad address format?') + name = '.'.join(items[:pos]) + zone = '.'.join(items[pos:]) + return unicode(zone), unicode(name) def dns_zone_exists(name): @@ -138,8 +142,8 @@ def add_zone(name, zonemgr=None, dns_backup=None, nsaddr=None, update_policy=Non add_rr(name, "@", "NS", api.env.host+'.', dns_backup, force=True) return name -def add_reverse_zone(ip_address, ns_ip_address, update_policy=None, dns_backup=None): - zone, name = get_reverse_zone(ip_address) +def add_reverse_zone(ip_address, ip_prefixlen, ns_ip_address, update_policy=None, dns_backup=None): + zone, name = get_reverse_zone(ip_address, ip_prefixlen) if not update_policy: update_policy = "grant %s krb5-subdomain %s. PTR;" % (api.env.realm, zone) try: @@ -172,8 +176,8 @@ def add_fwd_rr(zone, host, ip_address): elif addr.version == 6: add_rr(zone, host, "AAAA", ip_address) -def add_ptr_rr(ip_address, fqdn, dns_backup=None): - zone, name = get_reverse_zone(ip_address) +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 del_rr(zone, name, type, rdata): @@ -249,6 +253,7 @@ class BindInstance(service.Service): self.domain = None self.host = None self.ip_address = None + self.ip_prefixlen = None self.realm = None self.forwarders = None self.sub_dict = None @@ -259,10 +264,11 @@ class BindInstance(service.Service): else: self.fstore = sysrestore.FileStore('/var/lib/ipa/sysrestore') - def setup(self, fqdn, ip_address, realm_name, domain_name, forwarders, ntp, create_reverse, named_user="named", zonemgr=None): + def setup(self, fqdn, ip_address, ip_prefixlen, realm_name, domain_name, forwarders, ntp, create_reverse, named_user="named", zonemgr=None): self.named_user = named_user self.fqdn = fqdn self.ip_address = ip_address + self.ip_prefixlen = ip_prefixlen self.realm = realm_name self.domain = domain_name self.forwarders = forwarders @@ -390,11 +396,11 @@ class BindInstance(service.Service): # Add forward and reverse records to self add_fwd_rr(zone, self.host, self.ip_address) - if dns_zone_exists(get_reverse_zone(self.ip_address)[0]): - add_ptr_rr(self.ip_address, self.fqdn) + if dns_zone_exists(get_reverse_zone(self.ip_address, self.ip_prefixlen)[0]): + add_ptr_rr(self.ip_address, self.ip_prefixlen, self.fqdn) def __setup_reverse_zone(self): - add_reverse_zone(self.ip_address, self.ip_address, + add_reverse_zone(self.ip_address, self.ip_prefixlen, self.ip_address, dns_backup=self.dns_backup) def __setup_principal(self): @@ -451,10 +457,11 @@ class BindInstance(service.Service): resolv_fd.write(resolv_txt) resolv_fd.close() - def add_master_dns_records(self, fqdn, ip_address, + def add_master_dns_records(self, fqdn, ip_address, ip_prefixlen, realm_name, domain_name, ntp=False): self.fqdn = fqdn self.ip_address = ip_address + self.ip_prefixlen = ip_prefixlen self.realm = realm_name self.domain = domain_name self.host = fqdn.split(".")[0] @@ -483,16 +490,25 @@ class BindInstance(service.Service): for (record, type, rdata) in resource_records: del_rr(zone, record, type, rdata) - areclist = get_rr(zone, host, "A") - if len(areclist) != 0: - for rdata in areclist: - del_rr(zone, host, "A", 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) + + ip = netaddr.IPAddress(rdata) + rzone = ip.reverse_dns + record = '' + + while True: + part, dot, rzone = rzone.partition('.') + if len(rzone) == 0: + break + record = (record + '.' + part).lstrip('.') - rzone, record = get_reverse_zone(rdata) if dns_zone_exists(rzone): del_rr(rzone, record, "PTR", fqdn+".") # remove also master NS record from the reverse zone del_rr(rzone, "@", "NS", fqdn+".") + break def uninstall(self): |