mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
Honor netmask in DNS reverse zone setup.
ticket 910
This commit is contained in:
committed by
Martin Kosek
parent
80b4b3d44b
commit
db78f36235
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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):
|
||||
|
||||
Reference in New Issue
Block a user