2007-09-20 14:10:21 -05:00
|
|
|
# Authors: Simo Sorce <ssorce@redhat.com>
|
|
|
|
#
|
|
|
|
# Copyright (C) 2007 Red Hat
|
|
|
|
# see file 'COPYING' for use and warranty information
|
|
|
|
#
|
2010-12-09 06:59:11 -06:00
|
|
|
# This program is free software; you can redistribute it and/or modify
|
|
|
|
# it under the terms of the GNU General Public License as published by
|
|
|
|
# the Free Software Foundation, either version 3 of the License, or
|
|
|
|
# (at your option) any later version.
|
2007-09-20 14:10:21 -05:00
|
|
|
#
|
|
|
|
# This program is distributed in the hope that it will be useful,
|
|
|
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
# GNU General Public License for more details.
|
|
|
|
#
|
|
|
|
# You should have received a copy of the GNU General Public License
|
2010-12-09 06:59:11 -06:00
|
|
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
2007-09-20 14:10:21 -05:00
|
|
|
#
|
|
|
|
|
|
|
|
import tempfile
|
|
|
|
import os
|
2009-06-04 14:33:49 -05:00
|
|
|
import pwd
|
2008-03-27 18:01:38 -05:00
|
|
|
import logging
|
2011-01-31 08:30:43 -06:00
|
|
|
import netaddr
|
2007-09-20 14:10:21 -05:00
|
|
|
|
2009-06-04 14:33:49 -05:00
|
|
|
import installutils
|
|
|
|
import ldap
|
2007-12-13 03:31:28 -06:00
|
|
|
import service
|
2009-06-04 14:33:49 -05:00
|
|
|
from ipaserver import ipaldap
|
2009-11-24 18:00:26 -06:00
|
|
|
from ipaserver.install.dsinstance import realm_to_serverid
|
2011-06-01 07:51:06 -05:00
|
|
|
from ipaserver.install.installutils import resolve_host
|
2009-02-05 14:03:08 -06:00
|
|
|
from ipapython import sysrestore
|
|
|
|
from ipapython import ipautil
|
2011-08-31 07:42:57 -05:00
|
|
|
from ipalib.constants import DNS_ZONE_REFRESH
|
2009-11-10 06:21:09 -06:00
|
|
|
|
|
|
|
import ipalib
|
|
|
|
from ipalib import api, util, errors
|
2007-12-13 03:31:28 -06:00
|
|
|
|
2009-11-13 09:57:51 -06:00
|
|
|
def check_inst(unattended):
|
2010-09-10 16:14:16 -05:00
|
|
|
has_bind = True
|
2008-05-28 21:46:08 -05:00
|
|
|
# So far this file is always present in both RHEL5 and Fedora if all the necessary
|
|
|
|
# bind packages are installed (RHEL5 requires also the pkg: caching-nameserver)
|
|
|
|
if not os.path.exists('/etc/named.rfc1912.zones'):
|
2009-11-13 09:57:51 -06:00
|
|
|
print "BIND was not found on this system"
|
2010-09-10 16:14:16 -05:00
|
|
|
print "Please install the 'bind' package and start the installation again"
|
|
|
|
has_bind = False
|
2009-05-12 08:20:24 -05:00
|
|
|
|
|
|
|
# Also check for the LDAP BIND plug-in
|
|
|
|
if not os.path.exists('/usr/lib/bind/ldap.so') and \
|
|
|
|
not os.path.exists('/usr/lib64/bind/ldap.so'):
|
2009-11-13 09:57:51 -06:00
|
|
|
print "The BIND LDAP plug-in was not found on this system"
|
2010-09-10 16:14:16 -05:00
|
|
|
print "Please install the 'bind-dyndb-ldap' package and start the installation again"
|
|
|
|
has_bind = False
|
|
|
|
|
|
|
|
if not has_bind:
|
2009-05-12 08:20:24 -05:00
|
|
|
return False
|
2008-05-28 21:46:08 -05:00
|
|
|
|
2009-11-13 09:57:51 -06:00
|
|
|
if not unattended and os.path.exists('/etc/named.conf'):
|
|
|
|
msg = "Existing BIND configuration detected, overwrite?"
|
|
|
|
return ipautil.user_input(msg, False)
|
|
|
|
|
2008-05-28 21:46:08 -05:00
|
|
|
return True
|
|
|
|
|
2011-07-11 03:14:53 -05:00
|
|
|
def normalize_zone(zone):
|
|
|
|
if zone[-1] != '.':
|
|
|
|
return zone + '.'
|
|
|
|
else:
|
|
|
|
return zone
|
|
|
|
|
2011-01-04 07:55:47 -06:00
|
|
|
def create_reverse():
|
|
|
|
return ipautil.user_input("Do you want to configure the reverse zone?", True)
|
2010-11-11 12:27:27 -06:00
|
|
|
|
2011-01-03 07:48:29 -06:00
|
|
|
def named_conf_exists():
|
|
|
|
named_fd = open('/etc/named.conf', 'r')
|
|
|
|
lines = named_fd.readlines()
|
|
|
|
named_fd.close()
|
|
|
|
for line in lines:
|
|
|
|
if line.startswith('dynamic-db "ipa"'):
|
|
|
|
return True
|
|
|
|
return False
|
|
|
|
|
|
|
|
def dns_container_exists(fqdn, suffix):
|
2010-02-08 07:21:46 -06:00
|
|
|
"""
|
|
|
|
Test whether the dns container exists.
|
|
|
|
"""
|
|
|
|
|
|
|
|
def object_exists(dn):
|
|
|
|
"""
|
|
|
|
Test whether the given object exists in LDAP.
|
|
|
|
"""
|
|
|
|
try:
|
|
|
|
server.search_ext_s(dn, ldap.SCOPE_BASE)
|
|
|
|
except ldap.NO_SUCH_OBJECT:
|
|
|
|
return False
|
|
|
|
else:
|
|
|
|
return True
|
|
|
|
|
2010-09-29 13:51:35 -05:00
|
|
|
try:
|
2011-09-30 03:09:55 -05:00
|
|
|
server = ldap.initialize("ldap://" + ipautil.format_netloc(fqdn))
|
2010-09-29 13:51:35 -05:00
|
|
|
server.simple_bind_s()
|
|
|
|
except ldap.SERVER_DOWN:
|
|
|
|
raise RuntimeError('LDAP server on %s is not responding. Is IPA installed?' % fqdn)
|
2010-02-08 07:21:46 -06:00
|
|
|
|
|
|
|
ret = object_exists("cn=dns,%s" % suffix)
|
|
|
|
server.unbind_s()
|
|
|
|
|
|
|
|
return ret
|
|
|
|
|
2011-01-03 07:48:29 -06:00
|
|
|
def dns_zone_exists(name):
|
|
|
|
try:
|
2011-01-12 14:02:05 -06:00
|
|
|
zone = api.Command.dnszone_show(unicode(name))
|
|
|
|
except ipalib.errors.NotFound:
|
2011-01-03 07:48:29 -06:00
|
|
|
return False
|
|
|
|
|
|
|
|
if len(zone) == 0:
|
|
|
|
return False
|
|
|
|
else:
|
|
|
|
return True
|
|
|
|
|
2011-07-11 03:14:53 -05:00
|
|
|
def get_reverse_record_name(zone, ip_address):
|
|
|
|
ip = netaddr.IPAddress(ip_address)
|
|
|
|
rev = '.' + normalize_zone(zone)
|
|
|
|
fullrev = '.' + normalize_zone(ip.reverse_dns)
|
|
|
|
|
|
|
|
if not fullrev.endswith(rev):
|
|
|
|
raise ValueError("IP address does not match reverse zone")
|
|
|
|
|
|
|
|
return fullrev[1:-len(rev)]
|
|
|
|
|
|
|
|
def verify_reverse_zone(zone, ip_address):
|
|
|
|
try:
|
|
|
|
get_reverse_record_name(zone, ip_address)
|
|
|
|
except ValueError:
|
|
|
|
print "Invalid reverse zone %s" % zone
|
|
|
|
return False
|
|
|
|
|
|
|
|
return True
|
|
|
|
|
|
|
|
def get_reverse_zone_default(ip_address):
|
|
|
|
ip = netaddr.IPAddress(ip_address)
|
|
|
|
items = ip.reverse_dns.split('.')
|
|
|
|
|
|
|
|
if ip.version == 4:
|
|
|
|
items = items[1:] # /24 for IPv4
|
|
|
|
elif ip.version == 6:
|
|
|
|
items = items[16:] # /64 for IPv6
|
|
|
|
|
|
|
|
return normalize_zone('.'.join(items))
|
|
|
|
|
|
|
|
def find_reverse_zone(ip_address):
|
|
|
|
ip = netaddr.IPAddress(ip_address)
|
|
|
|
zone = normalize_zone(ip.reverse_dns)
|
|
|
|
|
|
|
|
while len(zone) > 0:
|
|
|
|
if dns_zone_exists(zone):
|
|
|
|
return zone
|
|
|
|
foo, bar, zone = zone.partition('.')
|
|
|
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
def get_reverse_zone(ip_address):
|
|
|
|
return find_reverse_zone(ip_address) or get_reverse_zone_default(ip_address)
|
|
|
|
|
|
|
|
def read_reverse_zone(default, ip_address):
|
|
|
|
while True:
|
|
|
|
zone = ipautil.user_input("Please specify the reverse zone name", default=default)
|
|
|
|
if not zone:
|
|
|
|
return None
|
|
|
|
if verify_reverse_zone(zone, ip_address):
|
|
|
|
break
|
|
|
|
|
|
|
|
return normalize_zone(zone)
|
|
|
|
|
2011-06-01 07:51:06 -05:00
|
|
|
def add_zone(name, zonemgr=None, dns_backup=None, ns_hostname=None, ns_ip_address=None,
|
|
|
|
update_policy=None):
|
|
|
|
if update_policy is None:
|
2011-01-31 08:30:43 -06:00
|
|
|
update_policy = "grant %(realm)s krb5-self * A; grant %(realm)s krb5-self * AAAA;" % dict(realm=api.env.realm)
|
2009-11-10 06:21:09 -06:00
|
|
|
|
2011-06-01 07:51:06 -05:00
|
|
|
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 = []
|
|
|
|
|
2009-11-10 06:21:09 -06:00
|
|
|
try:
|
2011-01-12 14:02:05 -06:00
|
|
|
api.Command.dnszone_add(unicode(name),
|
2011-06-01 07:51:06 -05:00
|
|
|
idnssoamname=unicode(ns_main+'.'),
|
2011-01-12 14:02:05 -06:00
|
|
|
idnssoarname=unicode(zonemgr),
|
2011-06-01 07:51:06 -05:00
|
|
|
ip_address=unicode(ns_ip_address),
|
2011-01-12 14:02:05 -06:00
|
|
|
idnsallowdynupdate=True,
|
|
|
|
idnsupdatepolicy=unicode(update_policy))
|
2009-11-10 06:21:09 -06:00
|
|
|
except (errors.DuplicateEntry, errors.EmptyModlist):
|
|
|
|
pass
|
|
|
|
|
2011-06-01 07:51:06 -05:00
|
|
|
nameservers = ns_replicas + [ns_main]
|
|
|
|
for hostname in nameservers:
|
|
|
|
add_ns_rr(name, hostname, dns_backup=None, force=True)
|
|
|
|
|
2009-11-10 06:21:09 -06:00
|
|
|
|
2011-07-11 03:14:53 -05:00
|
|
|
def add_reverse_zone(zone, ns_hostname=None, ns_ip_address=None,
|
2011-06-01 07:51:06 -05:00
|
|
|
ns_replicas=[], update_policy=None, dns_backup=None):
|
2011-08-09 03:30:18 -05:00
|
|
|
zone = normalize_zone(zone)
|
2011-06-01 07:51:06 -05:00
|
|
|
if update_policy is None:
|
2011-08-09 03:30:18 -05:00
|
|
|
update_policy = "grant %s krb5-subdomain %s PTR;" % (api.env.realm, zone)
|
2011-06-01 07:51:06 -05:00
|
|
|
|
|
|
|
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 = []
|
|
|
|
|
2009-11-10 06:21:09 -06:00
|
|
|
try:
|
2011-01-12 14:02:05 -06:00
|
|
|
api.Command.dnszone_add(unicode(zone),
|
2011-06-01 07:51:06 -05:00
|
|
|
idnssoamname=unicode(ns_main+'.'),
|
2011-01-12 14:02:05 -06:00
|
|
|
idnsallowdynupdate=True,
|
2011-05-27 10:05:45 -05:00
|
|
|
ip_address=unicode(ns_ip_address),
|
2011-01-12 14:02:05 -06:00
|
|
|
idnsupdatepolicy=unicode(update_policy))
|
2009-11-10 06:21:09 -06:00
|
|
|
except (errors.DuplicateEntry, errors.EmptyModlist):
|
|
|
|
pass
|
|
|
|
|
2011-06-01 07:51:06 -05:00
|
|
|
nameservers = ns_replicas + [ns_main]
|
|
|
|
for hostname in nameservers:
|
|
|
|
add_ns_rr(zone, hostname, dns_backup=None, force=True)
|
2009-11-10 06:21:09 -06:00
|
|
|
|
|
|
|
|
2011-01-31 11:05:07 -06:00
|
|
|
def add_rr(zone, name, type, rdata, dns_backup=None, **kwargs):
|
2011-02-07 11:52:07 -06:00
|
|
|
addkw = { '%srecord' % str(type.lower()) : unicode(rdata) }
|
2011-01-31 11:05:07 -06:00
|
|
|
addkw.update(kwargs)
|
2009-11-10 06:21:09 -06:00
|
|
|
try:
|
2011-01-12 14:02:05 -06:00
|
|
|
api.Command.dnsrecord_add(unicode(zone), unicode(name), **addkw)
|
2009-11-10 06:21:09 -06:00
|
|
|
except (errors.DuplicateEntry, errors.EmptyModlist):
|
|
|
|
pass
|
2009-11-24 17:49:40 -06:00
|
|
|
if dns_backup:
|
|
|
|
dns_backup.add(zone, type, name, rdata)
|
2009-11-10 06:21:09 -06:00
|
|
|
|
2011-01-31 08:30:43 -06:00
|
|
|
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)
|
|
|
|
|
2011-07-11 03:14:53 -05:00
|
|
|
def add_ptr_rr(zone, ip_address, fqdn, dns_backup=None):
|
|
|
|
name = get_reverse_record_name(zone, ip_address)
|
2009-11-24 17:49:40 -06:00
|
|
|
add_rr(zone, name, "PTR", fqdn+".", dns_backup)
|
|
|
|
|
2011-06-01 07:51:06 -05:00
|
|
|
def add_ns_rr(zone, hostname, dns_backup=None, force=True):
|
|
|
|
add_rr(zone, "@", "NS", hostname+'.', dns_backup=dns_backup,
|
|
|
|
force=force)
|
|
|
|
|
2011-01-21 13:46:58 -06:00
|
|
|
def del_rr(zone, name, type, rdata):
|
2011-02-07 11:52:07 -06:00
|
|
|
delkw = { '%srecord' % str(type.lower()) : unicode(rdata) }
|
2011-01-21 13:46:58 -06:00
|
|
|
try:
|
|
|
|
api.Command.dnsrecord_del(unicode(zone), unicode(name), **delkw)
|
|
|
|
except (errors.NotFound, errors.EmptyModlist):
|
|
|
|
pass
|
|
|
|
|
|
|
|
def get_rr(zone, name, type):
|
|
|
|
rectype = '%srecord' % unicode(type.lower())
|
|
|
|
ret = api.Command.dnsrecord_find(unicode(zone), unicode(name))
|
|
|
|
if ret['count'] > 0:
|
|
|
|
for r in ret['result']:
|
|
|
|
if rectype in r:
|
|
|
|
return r[rectype]
|
|
|
|
|
|
|
|
return []
|
|
|
|
|
2009-11-24 17:49:40 -06:00
|
|
|
|
|
|
|
class DnsBackup(object):
|
|
|
|
def __init__(self, service):
|
|
|
|
self.service = service
|
|
|
|
self.zones = {}
|
|
|
|
|
|
|
|
def add(self, zone, record_type, host, rdata):
|
|
|
|
"""
|
|
|
|
Backup a DNS record in the file store so it can later be removed.
|
|
|
|
"""
|
|
|
|
if zone not in self.zones:
|
|
|
|
zone_id = len(self.zones)
|
|
|
|
self.zones[zone] = (zone_id, 0)
|
|
|
|
self.service.backup_state("dns_zone_%s" % zone_id, zone)
|
|
|
|
|
|
|
|
(zone_id, record_id) = self.zones[zone]
|
|
|
|
self.service.backup_state("dns_record_%s_%s" % (zone_id, record_id),
|
|
|
|
"%s %s %s" % (record_type, host, rdata))
|
|
|
|
self.zones[zone] = (zone_id, record_id + 1)
|
|
|
|
|
|
|
|
def clear_records(self, have_ldap):
|
|
|
|
"""
|
|
|
|
Remove all records from the file store. If we are connected to
|
|
|
|
ldap, we will also remove them there.
|
|
|
|
"""
|
|
|
|
i = 0
|
|
|
|
while True:
|
|
|
|
zone = self.service.restore_state("dns_zone_%s" % i)
|
|
|
|
if not zone:
|
|
|
|
return
|
|
|
|
|
|
|
|
j = 0
|
|
|
|
while True:
|
|
|
|
dns_record = self.service.restore_state("dns_record_%s_%s" % (i, j))
|
|
|
|
if not dns_record:
|
|
|
|
break
|
|
|
|
if have_ldap:
|
|
|
|
type, host, rdata = dns_record.split(" ", 2)
|
|
|
|
try:
|
2011-02-07 11:52:07 -06:00
|
|
|
delkw = { '%srecord' % str(type.lower()) : unicode(rdata) }
|
2011-01-12 14:02:05 -06:00
|
|
|
api.Command.dnsrecord_del(unicode(zone), unicode(host), **delkw)
|
2009-11-24 17:49:40 -06:00
|
|
|
except:
|
|
|
|
pass
|
|
|
|
j += 1
|
|
|
|
|
|
|
|
i += 1
|
|
|
|
|
2009-11-10 06:21:09 -06:00
|
|
|
|
2007-12-13 03:31:28 -06:00
|
|
|
class BindInstance(service.Service):
|
2009-05-12 08:20:24 -05:00
|
|
|
def __init__(self, fstore=None, dm_password=None):
|
|
|
|
service.Service.__init__(self, "named", dm_password=dm_password)
|
2009-11-24 17:49:40 -06:00
|
|
|
self.dns_backup = DnsBackup(self)
|
2009-06-04 14:33:49 -05:00
|
|
|
self.named_user = None
|
2009-05-12 08:20:24 -05:00
|
|
|
self.domain = None
|
2007-09-20 14:10:21 -05:00
|
|
|
self.host = None
|
|
|
|
self.ip_address = None
|
|
|
|
self.realm = None
|
2009-09-01 16:28:52 -05:00
|
|
|
self.forwarders = None
|
2007-09-20 14:10:21 -05:00
|
|
|
self.sub_dict = None
|
2011-07-11 03:14:53 -05:00
|
|
|
self.reverse_zone = None
|
2007-09-20 14:10:21 -05:00
|
|
|
|
2008-03-27 18:01:38 -05:00
|
|
|
if fstore:
|
|
|
|
self.fstore = fstore
|
|
|
|
else:
|
|
|
|
self.fstore = sysrestore.FileStore('/var/lib/ipa/sysrestore')
|
|
|
|
|
2011-08-31 07:42:57 -05:00
|
|
|
def setup(self, fqdn, ip_address, realm_name, domain_name, forwarders, ntp,
|
|
|
|
reverse_zone, named_user="named", zonemgr=None,
|
|
|
|
zone_refresh=DNS_ZONE_REFRESH, zone_notif=False):
|
2009-06-04 14:33:49 -05:00
|
|
|
self.named_user = named_user
|
2007-09-20 14:10:21 -05:00
|
|
|
self.fqdn = fqdn
|
|
|
|
self.ip_address = ip_address
|
|
|
|
self.realm = realm_name
|
2008-02-15 19:47:29 -06:00
|
|
|
self.domain = domain_name
|
2009-09-01 16:28:52 -05:00
|
|
|
self.forwarders = forwarders
|
2008-05-15 10:33:07 -05:00
|
|
|
self.host = fqdn.split(".")[0]
|
2011-06-09 05:33:09 -05:00
|
|
|
self.host_domain = '.'.join(fqdn.split(".")[1:])
|
2009-05-12 08:20:24 -05:00
|
|
|
self.suffix = util.realm_to_suffix(self.realm)
|
2009-11-10 08:16:38 -06:00
|
|
|
self.ntp = ntp
|
2011-07-11 03:14:53 -05:00
|
|
|
self.reverse_zone = reverse_zone
|
2011-08-31 07:42:57 -05:00
|
|
|
self.zone_refresh = zone_refresh
|
|
|
|
self.zone_notif = zone_notif
|
2007-09-20 14:10:21 -05:00
|
|
|
|
2010-09-20 14:41:20 -05:00
|
|
|
if zonemgr:
|
|
|
|
self.zonemgr = zonemgr.replace('@','.')
|
|
|
|
else:
|
|
|
|
self.zonemgr = 'root.%s.%s' % (self.host, self.domain)
|
|
|
|
|
2007-09-20 14:10:21 -05:00
|
|
|
self.__setup_sub_dict()
|
|
|
|
|
|
|
|
def create_sample_bind_zone(self):
|
2007-12-13 03:31:28 -06:00
|
|
|
bind_txt = ipautil.template_file(ipautil.SHARE_DIR + "bind.zone.db.template", self.sub_dict)
|
2007-09-20 14:10:21 -05:00
|
|
|
[bind_fd, bind_name] = tempfile.mkstemp(".db","sample.zone.")
|
|
|
|
os.write(bind_fd, bind_txt)
|
|
|
|
os.close(bind_fd)
|
|
|
|
print "Sample zone file for bind has been created in "+bind_name
|
|
|
|
|
|
|
|
def create_instance(self):
|
|
|
|
|
|
|
|
try:
|
|
|
|
self.stop()
|
|
|
|
except:
|
|
|
|
pass
|
|
|
|
|
2011-01-05 06:46:30 -06:00
|
|
|
# get a connection to the DS
|
|
|
|
self.ldap_connect()
|
|
|
|
|
2011-02-10 14:47:45 -06:00
|
|
|
if not installutils.record_in_hosts(self.ip_address, self.fqdn):
|
|
|
|
installutils.add_record_to_hosts(self.ip_address, self.fqdn)
|
|
|
|
|
2010-02-08 07:21:46 -06:00
|
|
|
if not dns_container_exists(self.fqdn, self.suffix):
|
|
|
|
self.step("adding DNS container", self.__setup_dns_container)
|
2011-05-03 04:31:16 -05:00
|
|
|
if dns_zone_exists(self.domain):
|
|
|
|
self.step("adding NS record to the zone", self.__add_self_ns)
|
|
|
|
else:
|
2011-01-03 07:48:29 -06:00
|
|
|
self.step("setting up our zone", self.__setup_zone)
|
2011-07-11 03:14:53 -05:00
|
|
|
if self.reverse_zone is not None:
|
2010-11-11 12:27:27 -06:00
|
|
|
self.step("setting up reverse zone", self.__setup_reverse_zone)
|
2011-01-03 07:48:29 -06:00
|
|
|
self.step("setting up our own record", self.__add_self)
|
2009-06-04 14:33:49 -05:00
|
|
|
|
2009-06-27 00:53:45 -05:00
|
|
|
self.step("setting up kerberos principal", self.__setup_principal)
|
|
|
|
self.step("setting up named.conf", self.__setup_named_conf)
|
2008-03-27 18:01:38 -05:00
|
|
|
|
|
|
|
self.step("restarting named", self.__start)
|
|
|
|
self.step("configuring named to start on boot", self.__enable)
|
|
|
|
|
2009-06-27 00:53:45 -05:00
|
|
|
self.step("changing resolv.conf to point to ourselves", self.__setup_resolv_conf)
|
|
|
|
self.start_creation("Configuring named:")
|
2007-09-20 14:10:21 -05:00
|
|
|
|
2008-03-27 18:01:38 -05:00
|
|
|
def __start(self):
|
2007-10-03 16:37:13 -05:00
|
|
|
try:
|
2008-01-14 11:43:26 -06:00
|
|
|
self.backup_state("running", self.is_running())
|
2008-03-27 18:01:38 -05:00
|
|
|
self.restart()
|
2007-10-03 16:37:13 -05:00
|
|
|
except:
|
|
|
|
print "named service failed to start"
|
2007-09-20 14:10:21 -05:00
|
|
|
|
2008-03-27 18:01:38 -05:00
|
|
|
def __enable(self):
|
|
|
|
self.backup_state("enabled", self.is_running())
|
2010-12-04 14:42:14 -06:00
|
|
|
# We do not let the system start IPA components on its own,
|
|
|
|
# Instead we reply on the IPA init script to start only enabled
|
|
|
|
# components as found in our LDAP configuration tree
|
|
|
|
self.ldap_enable('DNS', self.fqdn, self.dm_password, self.suffix)
|
2008-03-27 18:01:38 -05:00
|
|
|
|
2007-09-20 14:10:21 -05:00
|
|
|
def __setup_sub_dict(self):
|
2009-09-01 16:28:52 -05:00
|
|
|
if self.forwarders:
|
|
|
|
fwds = "\n"
|
|
|
|
for forwarder in self.forwarders:
|
|
|
|
fwds += "\t\t%s;\n" % forwarder
|
|
|
|
fwds += "\t"
|
|
|
|
else:
|
|
|
|
fwds = " "
|
|
|
|
|
2009-11-10 08:16:38 -06:00
|
|
|
if self.ntp:
|
|
|
|
optional_ntp = "\n;ntp server\n"
|
|
|
|
optional_ntp += "_ntp._udp\t\tIN SRV 0 100 123\t%s""" % self.host
|
|
|
|
else:
|
|
|
|
optional_ntp = ""
|
|
|
|
|
2007-09-20 14:10:21 -05:00
|
|
|
self.sub_dict = dict(FQDN=self.fqdn,
|
|
|
|
IP=self.ip_address,
|
|
|
|
DOMAIN=self.domain,
|
|
|
|
HOST=self.host,
|
2009-05-12 08:20:24 -05:00
|
|
|
REALM=self.realm,
|
2009-11-24 18:00:26 -06:00
|
|
|
SERVER_ID=realm_to_serverid(self.realm),
|
2009-09-01 16:28:52 -05:00
|
|
|
FORWARDERS=fwds,
|
2009-11-10 08:16:38 -06:00
|
|
|
SUFFIX=self.suffix,
|
2010-09-20 14:41:20 -05:00
|
|
|
OPTIONAL_NTP=optional_ntp,
|
2011-08-31 07:42:57 -05:00
|
|
|
ZONEMGR=self.zonemgr,
|
|
|
|
ZONE_REFRESH=self.zone_refresh,
|
|
|
|
PERSISTENT_SEARCH=self.zone_notif and "yes" or "no")
|
2007-09-20 14:10:21 -05:00
|
|
|
|
2009-11-10 06:21:09 -06:00
|
|
|
def __setup_dns_container(self):
|
2009-05-12 08:20:24 -05:00
|
|
|
self._ldap_mod("dns.ldif", self.sub_dict)
|
2009-06-27 00:53:45 -05:00
|
|
|
|
2009-11-10 06:21:09 -06:00
|
|
|
def __setup_zone(self):
|
2011-06-09 05:33:09 -05:00
|
|
|
if self.host_domain != self.domain:
|
|
|
|
# add DNS domain for host first
|
|
|
|
logging.debug("Host domain (%s) is different from DNS domain (%s)!" \
|
|
|
|
% (self.host_domain, self.domain))
|
|
|
|
logging.debug("Add DNS zone for host first.")
|
|
|
|
|
|
|
|
add_zone(self.host_domain, self.zonemgr, dns_backup=self.dns_backup,
|
|
|
|
ns_hostname=api.env.host, ns_ip_address=self.ip_address)
|
2011-06-01 07:51:06 -05:00
|
|
|
add_zone(self.domain, self.zonemgr, dns_backup=self.dns_backup,
|
|
|
|
ns_hostname=api.env.host, ns_ip_address=self.ip_address)
|
2011-01-31 11:05:07 -06:00
|
|
|
|
2011-05-03 04:31:16 -05:00
|
|
|
def __add_self_ns(self):
|
2011-06-01 07:51:06 -05:00
|
|
|
add_ns_rr(self.domain, api.env.host, self.dns_backup, force=True)
|
2011-01-03 07:48:29 -06:00
|
|
|
|
|
|
|
def __add_self(self):
|
|
|
|
zone = self.domain
|
2009-11-10 06:21:09 -06:00
|
|
|
resource_records = (
|
|
|
|
("_ldap._tcp", "SRV", "0 100 389 %s" % self.host),
|
|
|
|
("_kerberos", "TXT", self.realm),
|
|
|
|
("_kerberos._tcp", "SRV", "0 100 88 %s" % self.host),
|
|
|
|
("_kerberos._udp", "SRV", "0 100 88 %s" % self.host),
|
|
|
|
("_kerberos-master._tcp", "SRV", "0 100 88 %s" % self.host),
|
|
|
|
("_kerberos-master._udp", "SRV", "0 100 88 %s" % self.host),
|
|
|
|
("_kpasswd._tcp", "SRV", "0 100 464 %s" % self.host),
|
|
|
|
("_kpasswd._udp", "SRV", "0 100 464 %s" % self.host),
|
|
|
|
)
|
|
|
|
|
|
|
|
for (host, type, rdata) in resource_records:
|
2009-11-24 17:49:40 -06:00
|
|
|
if type == "SRV":
|
|
|
|
add_rr(zone, host, type, rdata, self.dns_backup)
|
|
|
|
else:
|
|
|
|
add_rr(zone, host, type, rdata)
|
2009-11-10 08:16:38 -06:00
|
|
|
if self.ntp:
|
2009-11-24 17:49:40 -06:00
|
|
|
add_rr(zone, "_ntp._udp", "SRV", "0 100 123 %s" % self.host)
|
2009-09-02 09:22:50 -05:00
|
|
|
|
2011-01-31 08:30:43 -06:00
|
|
|
# Add forward and reverse records to self
|
|
|
|
add_fwd_rr(zone, self.host, self.ip_address)
|
2011-07-11 03:14:53 -05:00
|
|
|
if self.reverse_zone is not None and dns_zone_exists(self.reverse_zone):
|
|
|
|
add_ptr_rr(self.reverse_zone, self.ip_address, self.fqdn)
|
2011-01-03 07:48:29 -06:00
|
|
|
|
2009-11-10 06:21:09 -06:00
|
|
|
def __setup_reverse_zone(self):
|
2011-07-11 03:14:53 -05:00
|
|
|
add_reverse_zone(self.reverse_zone, ns_hostname=api.env.host,
|
2011-06-01 07:51:06 -05:00
|
|
|
ns_ip_address=self.ip_address, dns_backup=self.dns_backup)
|
2009-09-02 09:22:50 -05:00
|
|
|
|
2009-06-04 14:33:49 -05:00
|
|
|
def __setup_principal(self):
|
|
|
|
dns_principal = "DNS/" + self.fqdn + "@" + self.realm
|
|
|
|
installutils.kadmin_addprinc(dns_principal)
|
|
|
|
|
|
|
|
# Store the keytab on disk
|
|
|
|
self.fstore.backup_file("/etc/named.keytab")
|
|
|
|
installutils.create_keytab("/etc/named.keytab", dns_principal)
|
2010-04-14 11:52:12 -05:00
|
|
|
p = self.move_service(dns_principal)
|
|
|
|
if p is None:
|
|
|
|
# the service has already been moved, perhaps we're doing a DNS reinstall
|
|
|
|
dns_principal = "krbprincipalname=%s,cn=services,cn=accounts,%s" % (dns_principal, self.suffix)
|
|
|
|
else:
|
|
|
|
dns_principal = p
|
2009-06-04 14:33:49 -05:00
|
|
|
|
|
|
|
# Make sure access is strictly reserved to the named user
|
|
|
|
pent = pwd.getpwnam(self.named_user)
|
|
|
|
os.chown("/etc/named.keytab", pent.pw_uid, pent.pw_gid)
|
|
|
|
os.chmod("/etc/named.keytab", 0400)
|
|
|
|
|
|
|
|
# modify the principal so that it is marked as an ipa service so that
|
|
|
|
# it can host the memberof attribute, then also add it to the
|
|
|
|
# dnsserver role group, this way the DNS is allowed to perform
|
|
|
|
# DNS Updates
|
2011-01-31 16:43:29 -06:00
|
|
|
dns_group = "cn=DNS Servers,cn=privileges,cn=pbac,%s" % self.suffix
|
2010-04-14 11:52:12 -05:00
|
|
|
if isinstance(dns_principal, unicode):
|
|
|
|
dns_principal = dns_principal.encode('utf-8')
|
2009-12-07 22:17:00 -06:00
|
|
|
mod = [(ldap.MOD_ADD, 'member', dns_principal)]
|
2009-06-04 14:33:49 -05:00
|
|
|
|
|
|
|
try:
|
2011-01-05 06:46:30 -06:00
|
|
|
self.admin_conn.modify_s(dns_group, mod)
|
2010-04-14 11:52:12 -05:00
|
|
|
except ldap.TYPE_OR_VALUE_EXISTS:
|
|
|
|
pass
|
2009-06-04 14:33:49 -05:00
|
|
|
except Exception, e:
|
|
|
|
logging.critical("Could not modify principal's %s entry" % dns_principal)
|
|
|
|
raise e
|
|
|
|
|
2007-09-20 14:10:21 -05:00
|
|
|
def __setup_named_conf(self):
|
2008-03-27 18:01:38 -05:00
|
|
|
self.fstore.backup_file('/etc/named.conf')
|
2007-12-13 03:31:28 -06:00
|
|
|
named_txt = ipautil.template_file(ipautil.SHARE_DIR + "bind.named.conf.template", self.sub_dict)
|
2007-09-20 14:10:21 -05:00
|
|
|
named_fd = open('/etc/named.conf', 'w')
|
|
|
|
named_fd.seek(0)
|
|
|
|
named_fd.truncate(0)
|
|
|
|
named_fd.write(named_txt)
|
|
|
|
named_fd.close()
|
|
|
|
|
2008-05-13 12:35:20 -05:00
|
|
|
def __setup_resolv_conf(self):
|
|
|
|
self.fstore.backup_file('/etc/resolv.conf')
|
|
|
|
resolv_txt = "search "+self.domain+"\nnameserver "+self.ip_address+"\n"
|
|
|
|
resolv_fd = open('/etc/resolv.conf', 'w')
|
|
|
|
resolv_fd.seek(0)
|
|
|
|
resolv_fd.truncate(0)
|
|
|
|
resolv_fd.write(resolv_txt)
|
|
|
|
resolv_fd.close()
|
2007-09-20 14:10:21 -05:00
|
|
|
|
2011-07-11 03:14:53 -05:00
|
|
|
def add_master_dns_records(self, fqdn, ip_address, realm_name, domain_name,
|
|
|
|
reverse_zone, ntp=False):
|
2011-01-21 13:46:58 -06:00
|
|
|
self.fqdn = fqdn
|
|
|
|
self.ip_address = ip_address
|
|
|
|
self.realm = realm_name
|
|
|
|
self.domain = domain_name
|
|
|
|
self.host = fqdn.split(".")[0]
|
|
|
|
self.suffix = util.realm_to_suffix(self.realm)
|
|
|
|
self.ntp = ntp
|
2011-07-11 03:14:53 -05:00
|
|
|
self.reverse_zone = reverse_zone
|
2011-01-21 13:46:58 -06:00
|
|
|
|
|
|
|
self.__add_self()
|
|
|
|
|
|
|
|
def remove_master_dns_records(self, fqdn, realm_name, domain_name):
|
|
|
|
host = fqdn.split(".")[0]
|
|
|
|
suffix = util.realm_to_suffix(realm_name)
|
|
|
|
|
|
|
|
zone = domain_name
|
|
|
|
resource_records = (
|
|
|
|
("_ldap._tcp", "SRV", "0 100 389 %s" % host),
|
|
|
|
("_kerberos._tcp", "SRV", "0 100 88 %s" % host),
|
|
|
|
("_kerberos._udp", "SRV", "0 100 88 %s" % host),
|
|
|
|
("_kerberos-master._tcp", "SRV", "0 100 88 %s" % host),
|
|
|
|
("_kerberos-master._udp", "SRV", "0 100 88 %s" % host),
|
|
|
|
("_kpasswd._tcp", "SRV", "0 100 464 %s" % host),
|
|
|
|
("_kpasswd._udp", "SRV", "0 100 464 %s" % host),
|
|
|
|
("_ntp._udp", "SRV", "0 100 123 %s" % host),
|
2011-05-03 04:31:16 -05:00
|
|
|
("@", "NS", fqdn+"."),
|
2011-01-21 13:46:58 -06:00
|
|
|
)
|
|
|
|
|
|
|
|
for (record, type, rdata) in resource_records:
|
|
|
|
del_rr(zone, record, type, rdata)
|
|
|
|
|
2011-05-27 13:29:33 -05:00
|
|
|
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)
|
|
|
|
|
2011-07-11 03:14:53 -05:00
|
|
|
rzone = find_reverse_zone(rdata)
|
|
|
|
if rzone is not None:
|
|
|
|
record = get_reverse_record_name(rzone, rdata)
|
|
|
|
del_rr(rzone, record, "PTR", fqdn+".")
|
|
|
|
# remove also master NS record from the reverse zone
|
|
|
|
del_rr(rzone, "@", "NS", fqdn+".")
|
2011-01-21 13:46:58 -06:00
|
|
|
|
|
|
|
|
2008-01-11 05:57:36 -06:00
|
|
|
def uninstall(self):
|
2010-05-03 14:21:51 -05:00
|
|
|
if self.is_configured():
|
|
|
|
self.print_msg("Unconfiguring %s" % self.service_name)
|
|
|
|
|
2008-01-11 05:57:36 -06:00
|
|
|
running = self.restore_state("running")
|
2008-03-27 18:01:38 -05:00
|
|
|
enabled = self.restore_state("enabled")
|
2008-01-11 05:57:36 -06:00
|
|
|
|
2009-11-24 17:49:40 -06:00
|
|
|
self.dns_backup.clear_records(api.Backend.ldap2.isconnected())
|
|
|
|
|
2008-01-11 05:57:36 -06:00
|
|
|
if not running is None:
|
|
|
|
self.stop()
|
|
|
|
|
2008-05-13 12:35:20 -05:00
|
|
|
for f in ["/etc/named.conf", "/etc/resolv.conf"]:
|
2008-03-27 18:01:38 -05:00
|
|
|
try:
|
|
|
|
self.fstore.restore_file(f)
|
|
|
|
except ValueError, error:
|
|
|
|
logging.debug(error)
|
|
|
|
pass
|
|
|
|
|
|
|
|
if not enabled is None and not enabled:
|
2011-09-13 02:47:13 -05:00
|
|
|
self.disable()
|
2008-01-11 05:57:36 -06:00
|
|
|
|
|
|
|
if not running is None and running:
|
|
|
|
self.start()
|