mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
IPv6 enhancements
* Make host-add, host-del and reverse zone creation IPv6 aware * Make Bind listen on IPv6 interfaces, too https://fedorahosted.org/freeipa/ticket/398
This commit is contained in:
parent
2518612b0d
commit
bb56285f6b
@ -1,4 +1,7 @@
|
|||||||
options {
|
options {
|
||||||
|
// turns on IPv6 for port 53, IPv4 is on by default for all ifaces
|
||||||
|
listen-on-v6 {any;};
|
||||||
|
|
||||||
// Put files that named is allowed to write in the data/ directory:
|
// Put files that named is allowed to write in the data/ directory:
|
||||||
directory "/var/named"; // the default
|
directory "/var/named"; // the default
|
||||||
dump-file "data/cache_dump.db";
|
dump-file "data/cache_dump.db";
|
||||||
|
@ -85,6 +85,7 @@ from ipalib.plugins.service import set_certificate_attrs
|
|||||||
from ipalib.plugins.service import make_pem, check_writable_file
|
from ipalib.plugins.service import make_pem, check_writable_file
|
||||||
from ipalib.plugins.service import write_certificate
|
from ipalib.plugins.service import write_certificate
|
||||||
from ipalib.plugins.dns import dns_container_exists, _record_types
|
from ipalib.plugins.dns import dns_container_exists, _record_types
|
||||||
|
from ipalib.plugins.dns import add_forward_record
|
||||||
from ipalib import _, ngettext
|
from ipalib import _, ngettext
|
||||||
from ipalib import x509
|
from ipalib import x509
|
||||||
from ipapython.ipautil import ipa_generate_password
|
from ipapython.ipautil import ipa_generate_password
|
||||||
@ -103,6 +104,32 @@ def validate_host(ugettext, fqdn):
|
|||||||
return _('Fully-qualified hostname required')
|
return _('Fully-qualified hostname required')
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def is_forward_record(zone, str_address):
|
||||||
|
addr = netaddr.IPAddress(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)
|
||||||
|
else:
|
||||||
|
raise ValueError('Invalid address family')
|
||||||
|
|
||||||
|
return result['count'] > 0
|
||||||
|
|
||||||
|
def remove_fwd_ptr(ipaddr, host, domain, recordtype):
|
||||||
|
api.log.debug('deleting ipaddr %s' % ipaddr)
|
||||||
|
revzone, revname = get_reverse_zone(ipaddr)
|
||||||
|
try:
|
||||||
|
delkw = { 'ptrrecord' : "%s.%s." % (host, domain) }
|
||||||
|
api.Command['dnsrecord_del'](revzone, revname, **delkw)
|
||||||
|
except errors.NotFound:
|
||||||
|
pass
|
||||||
|
|
||||||
|
try:
|
||||||
|
delkw = { recordtype : ipaddr }
|
||||||
|
api.Command['dnsrecord_del'](domain, host, **delkw)
|
||||||
|
except errors.NotFound:
|
||||||
|
pass
|
||||||
|
|
||||||
host_output_params = (
|
host_output_params = (
|
||||||
Flag('has_keytab',
|
Flag('has_keytab',
|
||||||
label=_('Keytab'),
|
label=_('Keytab'),
|
||||||
@ -309,8 +336,7 @@ class host_add(LDAPCreate):
|
|||||||
except errors.NotFound:
|
except errors.NotFound:
|
||||||
pass
|
pass
|
||||||
else:
|
else:
|
||||||
result = api.Command['dnsrecord_find'](domain, arecord=options['ip_address'])
|
if is_forward_record(domain, options['ip_address']):
|
||||||
if result['count'] > 0:
|
|
||||||
raise errors.DuplicateEntry(message=u'This IP address is already assigned.')
|
raise errors.DuplicateEntry(message=u'This IP address is already assigned.')
|
||||||
if not options.get('force', False) and not 'ip_address' in options:
|
if not options.get('force', False) and not 'ip_address' in options:
|
||||||
util.validate_host_dns(self.log, keys[-1])
|
util.validate_host_dns(self.log, keys[-1])
|
||||||
@ -347,15 +373,8 @@ class host_add(LDAPCreate):
|
|||||||
if 'ip_address' in options and dns_container_exists(ldap):
|
if 'ip_address' in options and dns_container_exists(ldap):
|
||||||
parts = keys[-1].split('.')
|
parts = keys[-1].split('.')
|
||||||
domain = unicode('.'.join(parts[1:]))
|
domain = unicode('.'.join(parts[1:]))
|
||||||
if ':' in options['ip_address']:
|
|
||||||
addkw = { 'aaaarecord' : options['ip_address'] }
|
add_forward_record(domain, parts[0], options['ip_address'])
|
||||||
else:
|
|
||||||
addkw = { 'arecord' : options['ip_address'] }
|
|
||||||
try:
|
|
||||||
api.Command['dnsrecord_add'](domain, parts[0], **addkw)
|
|
||||||
except errors.EmptyModlist:
|
|
||||||
# the entry already exists and matches
|
|
||||||
pass
|
|
||||||
|
|
||||||
if not options.get('no_reverse', False):
|
if not options.get('no_reverse', False):
|
||||||
revzone, revname = get_reverse_zone(options['ip_address'])
|
revzone, revname = get_reverse_zone(options['ip_address'])
|
||||||
@ -444,24 +463,16 @@ class host_del(LDAPDelete):
|
|||||||
records = api.Command['dnsrecord_find'](domain, idnsname=parts[0])['result']
|
records = api.Command['dnsrecord_find'](domain, idnsname=parts[0])['result']
|
||||||
for record in records:
|
for record in records:
|
||||||
if 'arecord' in record:
|
if 'arecord' in record:
|
||||||
ipaddr = record['arecord'][0]
|
remove_fwd_ptr(record['arecord'][0], parts[0],
|
||||||
self.debug('deleting ipaddr %s' % ipaddr)
|
domain, 'arecord')
|
||||||
revzone, revname = get_reverse_zone(ipaddr)
|
if 'aaaarecord' in record:
|
||||||
try:
|
remove_fwd_ptr(record['aaaarecord'][0], parts[0],
|
||||||
delkw = { 'ptrrecord' : fqdn+'.' }
|
domain, 'aaaarecord')
|
||||||
api.Command['dnsrecord_del'](revzone, revname, **delkw)
|
|
||||||
except errors.NotFound:
|
|
||||||
pass
|
|
||||||
try:
|
|
||||||
delkw = { 'arecord' : ipaddr }
|
|
||||||
api.Command['dnsrecord_del'](domain, parts[0], **delkw)
|
|
||||||
except errors.NotFound:
|
|
||||||
pass
|
|
||||||
else:
|
else:
|
||||||
# Try to delete all other record types too
|
# Try to delete all other record types too
|
||||||
_attribute_types = [str('%srecord' % t.lower()) for t in _record_types]
|
_attribute_types = [str('%srecord' % t.lower()) for t in _record_types]
|
||||||
for attr in _attribute_types:
|
for attr in _attribute_types:
|
||||||
if attr != 'arecord' and attr in record:
|
if attr not in ['arecord', 'aaaarecord'] and attr in record:
|
||||||
for i in xrange(len(record[attr])):
|
for i in xrange(len(record[attr])):
|
||||||
if (record[attr][i].endswith(parts[0]) or
|
if (record[attr][i].endswith(parts[0]) or
|
||||||
record[attr][i].endswith(fqdn+'.')):
|
record[attr][i].endswith(fqdn+'.')):
|
||||||
|
@ -21,6 +21,7 @@ import tempfile
|
|||||||
import os
|
import os
|
||||||
import pwd
|
import pwd
|
||||||
import logging
|
import logging
|
||||||
|
import netaddr
|
||||||
|
|
||||||
import installutils
|
import installutils
|
||||||
import ldap
|
import ldap
|
||||||
@ -97,11 +98,15 @@ def dns_container_exists(fqdn, suffix):
|
|||||||
|
|
||||||
return ret
|
return ret
|
||||||
|
|
||||||
def get_reverse_zone(ip_address):
|
def get_reverse_zone(ip_address_str):
|
||||||
tmp = ip_address.split(".")
|
ip = netaddr.IPAddress(ip_address_str)
|
||||||
tmp.reverse()
|
if ip.version == 4:
|
||||||
name = tmp.pop(0)
|
name, dot, zone = ip.reverse_dns.partition('.')
|
||||||
zone = ".".join(tmp) + ".in-addr.arpa"
|
elif ip.version == 6:
|
||||||
|
name = '.'.join(ip.reverse_dns.split('.')[:8])
|
||||||
|
zone = '.'.join(ip.reverse_dns.split('.')[8:])
|
||||||
|
else:
|
||||||
|
raise ValueError('Bad address format?')
|
||||||
|
|
||||||
return zone, name
|
return zone, name
|
||||||
|
|
||||||
@ -118,7 +123,7 @@ def dns_zone_exists(name):
|
|||||||
|
|
||||||
def add_zone(name, zonemgr=None, dns_backup=None, nsaddr=None, update_policy=None):
|
def add_zone(name, zonemgr=None, dns_backup=None, nsaddr=None, update_policy=None):
|
||||||
if not update_policy:
|
if not update_policy:
|
||||||
update_policy = "grant %s krb5-self * A;" % api.env.realm
|
update_policy = "grant %(realm)s krb5-self * A; grant %(realm)s krb5-self * AAAA;" % dict(realm=api.env.realm)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
api.Command.dnszone_add(unicode(name),
|
api.Command.dnszone_add(unicode(name),
|
||||||
@ -160,6 +165,13 @@ def add_rr(zone, name, type, rdata, dns_backup=None, **kwargs):
|
|||||||
if dns_backup:
|
if dns_backup:
|
||||||
dns_backup.add(zone, type, name, rdata)
|
dns_backup.add(zone, type, name, rdata)
|
||||||
|
|
||||||
|
def add_fwd_rr(zone, host, ip_address):
|
||||||
|
addr = netaddr.IPAddress(ip_address)
|
||||||
|
if addr.version == 4:
|
||||||
|
add_rr(zone, host, "A", ip_address)
|
||||||
|
elif addr.version == 6:
|
||||||
|
add_rr(zone, host, "AAAA", ip_address)
|
||||||
|
|
||||||
def add_ptr_rr(ip_address, fqdn, dns_backup=None):
|
def add_ptr_rr(ip_address, fqdn, dns_backup=None):
|
||||||
zone, name = get_reverse_zone(ip_address)
|
zone, name = get_reverse_zone(ip_address)
|
||||||
add_rr(zone, name, "PTR", fqdn+".", dns_backup)
|
add_rr(zone, name, "PTR", fqdn+".", dns_backup)
|
||||||
@ -264,11 +276,7 @@ class BindInstance(service.Service):
|
|||||||
else:
|
else:
|
||||||
self.zonemgr = 'root.%s.%s' % (self.host, self.domain)
|
self.zonemgr = 'root.%s.%s' % (self.host, self.domain)
|
||||||
|
|
||||||
tmp = ip_address.split(".")
|
self.reverse_subnet, self.reverse_host = get_reverse_zone(ip_address)
|
||||||
tmp.reverse()
|
|
||||||
|
|
||||||
self.reverse_host = tmp.pop(0)
|
|
||||||
self.reverse_subnet = ".".join(tmp)
|
|
||||||
|
|
||||||
self.__setup_sub_dict()
|
self.__setup_sub_dict()
|
||||||
|
|
||||||
@ -357,7 +365,6 @@ class BindInstance(service.Service):
|
|||||||
def __add_self(self):
|
def __add_self(self):
|
||||||
zone = self.domain
|
zone = self.domain
|
||||||
resource_records = (
|
resource_records = (
|
||||||
(self.host, "A", self.ip_address),
|
|
||||||
("_ldap._tcp", "SRV", "0 100 389 %s" % self.host),
|
("_ldap._tcp", "SRV", "0 100 389 %s" % self.host),
|
||||||
("_kerberos", "TXT", self.realm),
|
("_kerberos", "TXT", self.realm),
|
||||||
("_kerberos._tcp", "SRV", "0 100 88 %s" % self.host),
|
("_kerberos._tcp", "SRV", "0 100 88 %s" % self.host),
|
||||||
@ -376,6 +383,8 @@ class BindInstance(service.Service):
|
|||||||
if self.ntp:
|
if self.ntp:
|
||||||
add_rr(zone, "_ntp._udp", "SRV", "0 100 123 %s" % self.host)
|
add_rr(zone, "_ntp._udp", "SRV", "0 100 123 %s" % self.host)
|
||||||
|
|
||||||
|
# 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]):
|
if dns_zone_exists(get_reverse_zone(self.ip_address)[0]):
|
||||||
add_ptr_rr(self.ip_address, self.fqdn)
|
add_ptr_rr(self.ip_address, self.fqdn)
|
||||||
|
|
||||||
|
@ -133,12 +133,12 @@ def verify_fqdn(host_name,no_host_dns=False):
|
|||||||
|
|
||||||
# Verify that it is a DNS A or AAAA record
|
# Verify that it is a DNS A or AAAA record
|
||||||
rs = dnsclient.query(host_name+".", dnsclient.DNS_C_IN, dnsclient.DNS_T_A)
|
rs = dnsclient.query(host_name+".", dnsclient.DNS_C_IN, dnsclient.DNS_T_A)
|
||||||
if len(rs) > 0:
|
if len([ rec for rec in rs if rec.dns_type is not dnsclient.DNS_T_SOA ]) > 0:
|
||||||
verify_dns_records(host_name, rs, resaddr, 'ipv4')
|
verify_dns_records(host_name, rs, resaddr, 'ipv4')
|
||||||
return
|
return
|
||||||
|
|
||||||
rs = dnsclient.query(host_name+".", dnsclient.DNS_C_IN, dnsclient.DNS_T_AAAA)
|
rs = dnsclient.query(host_name+".", dnsclient.DNS_C_IN, dnsclient.DNS_T_AAAA)
|
||||||
if len(rs) > 0:
|
if len([ rec for rec in rs if rec.dns_type is not dnsclient.DNS_T_SOA ]) > 0:
|
||||||
verify_dns_records(host_name, rs, resaddr, 'ipv6')
|
verify_dns_records(host_name, rs, resaddr, 'ipv6')
|
||||||
return
|
return
|
||||||
else:
|
else:
|
||||||
|
Loading…
Reference in New Issue
Block a user