[Freeipa-devel] PATCH: setup bind as part of server configuration
Pete Rowley
prowley at redhat.com
Thu Sep 20 20:17:05 UTC 2007
Simo Sorce wrote:
> This patch will help QA, you have to explicitly pass --setup-bind and no
> question about it is asked if you don't.
>
Ack
> ------------------------------------------------------------------------
>
> # HG changeset patch
> # User Simo Sorce <ssorce at redhat.com>
> # Date 1190315421 14400
> # Node ID 9353b33672ee1bf8afabee1615d2cd4aebcce019
> # Parent 578d26927d915e3c85bded0c2206cf9679a58977
> Initial support for confiuguring a DNS Server during installation.
> It's not perfect yet but good enough to include it.
>
> diff -r 578d26927d91 -r 9353b33672ee ipa-client/ipa-install/ipa-client-install
> --- a/ipa-client/ipa-install/ipa-client-install Thu Sep 13 12:10:55 2007 -0400
> +++ b/ipa-client/ipa-install/ipa-client-install Thu Sep 20 15:10:21 2007 -0400
> @@ -31,7 +31,6 @@ import ipaclient.ipadiscovery
> import ipaclient.ipadiscovery
> import ipaclient.ipachangeconf
> from ipa.ipautil import run
> -import shutil
>
> def parse_options():
> parser = OptionParser(version=VERSION)
> diff -r 578d26927d91 -r 9353b33672ee ipa-server/ipa-install/ipa-server-install
> --- a/ipa-server/ipa-install/ipa-server-install Thu Sep 13 12:10:55 2007 -0400
> +++ b/ipa-server/ipa-install/ipa-server-install Thu Sep 20 15:10:21 2007 -0400
> @@ -36,6 +36,7 @@ from optparse import OptionParser
> from optparse import OptionParser
> import ipaserver.dsinstance
> import ipaserver.krbinstance
> +import ipaserver.bindinstance
> from ipa.ipautil import run
>
> def parse_options():
> @@ -51,10 +52,13 @@ def parse_options():
> parser.add_option("-a", "--admin-password", dest="admin_password",
> help="admin user kerberos password")
> parser.add_option("-d", "--debug", dest="debug", action="store_true",
> - dest="debug", default=False, help="print debugging information")
> + default=False, help="print debugging information")
> parser.add_option("--hostname", dest="host_name", help="fully qualified name of server")
> - parser.add_option("-U", "--unattended", dest="unattended",
> - help="unattended installation never prompts the user")
> + parser.add_option("--ip-address", dest="ip_address", help="Master Server IP Address")
> + parser.add_option("--setup-bind", dest="setup_bind", action="store_true",
> + default=False, help="configure bind with our zone file")
> + parser.add_option("-U", "--unattended", dest="unattended", action="store_true",
> + default=False, help="unattended installation never prompts the user")
>
> options, args = parser.parse_args()
>
> @@ -63,7 +67,7 @@ def parse_options():
> not options.dm_password or
> not options.admin_password or
> not options.master_password):
> - parser.error("error: In unattended mode you need to provide -u, -r, -p and -P options")
> + parser.error("error: In unattended mode you need to provide iat least -u, -r, -p and -P options")
>
> return options
>
> @@ -93,34 +97,140 @@ def main():
> ds_user = ""
> realm_name = ""
> host_name = ""
> + domain_name = ""
> + ip_address = ""
> master_password = ""
> dm_password = ""
> admin_password = ""
>
> + # check bind packages are installed
> + bind = ipaserver.bindinstance.BindInstance()
> + if options.setup_bind:
> + if not bind.check_inst():
> + print "--setup-bind was specified but bind is not installed on the system"
> + print "Please install bind (you also need the package 'caching-nameserver') and restart the setup program"
> + return "-Fatal Error-"
> +
> # check the hostname is correctly configured, it must be as the kldap
> # utilities just use the hostname as returned by gethostbyname to set
> # up some of the standard entries
>
> + host_name = ""
> if options.host_name:
> host_name = options.host_name
> else:
> - host_name = socket.gethostname()
> - if len(host_name.split(".")) < 2:
> - print "Invalid hostname <"+host_name+">"
> - print "Check the /etc/hosts file and make sure to have a valid FQDN"
> - return "-Fatal Error-"
> -
> - ip = socket.gethostbyname(host_name)
> - if ip == "127.0.0.1":
> - print "The hostname resolves to the localhost address (127.0.0.1)"
> - print "Please change your /etc/hosts file or your DNS so that the"
> - print "hostname resolves to the ip address of your network interface."
> - print "The KDC service does not listen on 127.0.0.1"
> - print ""
> - print "Please fix your /etc/hosts file and restart the setup program"
> - return "-Fatal Error-"
> -
> - print "The Final KDC Host Name will be: " + host_name + ". With IP address: " + ip
> + try:
> + host_name = socket.gethostname()
> + except:
> + pass
> + if options.unattended:
> + if len(host_name.split(".")) < 2 or host_name == "localhost.localdomain":
> + print "Invalid hostname: "+host_name
> + print "This host name can't be used as a hostname for an IPA Server"
> + return "-Fatal Error-"
> + else:
> + host_ok = False
> + while not host_ok:
> + if host_name == "":
> + print ""
> + host_name = raw_input("Please provide a Fully Qualified name to use for your system [master.example.com]: ")
> + if host_name != "":
> + host_name = "master.example.com"
> +
> + if len(host_name.split(".")) < 2 or host_name == "localhost.localdomain":
> + print "Invalid hostname: "+host_name
> + print "This host name can't be used as a hostname for an IPA Server"
> + host_name = ""
> + continue
> + else:
> + host_ok = True
> +
> + yesno = raw_input("Please confirm this ["+host_name+"] is the server hostname you want to use [Y/n]: ")
> + if yesno != "" and yesno.lower() != 'y':
> + host_name = ""
> + host_ok = False
> +
> + domain_name = host_name[host_name.find(".")+1:]
> +
> + # Check we have a public IP that is associated with the hostname
> + ip = ""
> + askip = False
> + try:
> + ip = socket.gethostbyname(host_name)
> +
> + if ip == "127.0.0.1" or ip == "::1":
> + print "The hostname resolves to the localhost address (127.0.0.1/::1)"
> + print "Please change your /etc/hosts file so that the hostname"
> + print "resolves to the ip address of your network interface."
> + print "The KDC service does not listen on localhost"
> + print ""
> + print "Please fix your /etc/hosts file and restart the setup program"
> + return "-Fatal Error-"
> +
> + except:
> + print "The provided hostname can't actually be use to resolve the IP address"
> + if options.ip_address:
> + ip = options.ip_address
> + else:
> + askip = True
> +
> + if ip != "":
> + try:
> + socket.inet_pton(socket.AF_INET, ip)
> + except:
> + try:
> + socket.inet_pton(socket.AF_INET6, ip)
> + except:
> + print "Invalid IP format"
> + if options.unattended:
> + return "-Fatal Error-"
> + else:
> + ip = ""
> + askip = True
> +
> + if options.ip_address and options.ip_address != ip:
> + if options.setup_bind:
> + ip = options.ip_address
> + else:
> + print "Error: the hostname resolves to an IP that is different from the one provided on the command line"
> + print "Please fix your DNS or /etc/hosts file to provide consistent information and restart the setup program"
> + return "-Fatal Error-"
> +
> + if options.unattended:
> + if askip or ip == "":
> + print "Unable to resolve IP address"
> + return "-Fatal Error-"
> +
> + while askip:
> + ip = raw_input("Please provide the IP address to be used for this host name: ")
> +
> + if ip == "":
> + print "An empty IP is not acceptable"
> + continue
> + if ip == "127.0.0.1" or ip == "::1":
> + print "The IPA Server can't use localhost as a valid IP"
> + continue
> +
> + try:
> + socket.inet_pton(socket.AF_INET, ip)
> + except:
> + try:
> + socket.inet_pton(socket.AF_INET6, ip)
> + except:
> + print "Invalid IP format"
> + continue
> +
> + print "Adding ["+ip+" "+host_name+"] to your /etc/hosts file"
> + hosts_fd = open('/etc/hosts', 'r+')
> + hosts_fd.seek(0, 2)
> + hosts_fd.write(ip+'\t'+host_name+' '+host_name[:host_name.find('.')]+'\n')
> + hosts_fd.close()
> + askip = False
> +
> + ip_address = ip
> +
> + print "The IPA Master Server Name will be: " + host_name + ". With IP address: " + ip_address
> + print "The IPA Domain Name will be: " + domain_name
> print ""
>
> if not options.ds_user:
> @@ -152,7 +262,7 @@ def main():
> print "The kerberos protocol requires a Realm name to be defined."
> print "Usually the domain name all in uppercase is used as realm name."
> print ""
> - upper_dom = (host_name[host_name.find(".")+1:]).upper()
> + upper_dom = domain_name.upper()
> realm_name = raw_input("Please provide a realm name ["+upper_dom+"]: ")
> print ""
> if realm_name == "":
> @@ -227,6 +337,11 @@ def main():
> else:
> admin_password = options.admin_password
>
> + if not options.unattended:
> + print ""
> + print "The following operations may take some minutes to complete."
> + print "Please wait until the prompt is returned."
> +
> # Create a directory server instance
> ds = ipaserver.dsinstance.DsInstance()
> ds.create_instance(ds_user, realm_name, host_name, dm_password)
> @@ -235,8 +350,24 @@ def main():
> krb = ipaserver.krbinstance.KrbInstance()
> krb.create_instance(ds_user, realm_name, host_name, dm_password, master_password)
>
> - # Restart ds after the krb instance has changed ds configurations
> + bind.setup(host_name, ip_address, realm_name)
> + if options.setup_bind:
> + skipbind = False
> + if not options.unattended:
> + print "This program is about to replace the DNS Server configuration,"
> + print "with an automatically generated one, based on the data gathered so far."
> + print "This will REPLACE any existing configuration."
> + yesno = raw_input("Are you sure you want to configure the DNS Server ? [y/N]: ")
> + if yesno.lower() != 'y':
> + skipbind = True
> + if not skipbind:
> + bind.create_instance()
> + else:
> + bind.create_sample_bind_zone()
> +
> + # Restart ds and krb after configurations have been changed
> ds.restart()
> + krb.restart()
>
> # Restart apache
> run(["/sbin/service", "httpd", "restart"])
> diff -r 578d26927d91 -r 9353b33672ee ipa-server/ipa-install/share/bind.named.conf.template
> --- /dev/null Thu Jan 01 00:00:00 1970 +0000
> +++ b/ipa-server/ipa-install/share/bind.named.conf.template Thu Sep 20 15:10:21 2007 -0400
> @@ -0,0 +1,41 @@
> +options {
> + /* make named use port 53 for the source of all queries, to allow
> + * firewalls to block all ports except 53:
> + */
> + query-source port 53;
> + query-source-v6 port 53;
> +
> + // Put files that named is allowed to write in the data/ directory:
> + directory "/var/named"; // the default
> + dump-file "data/cache_dump.db";
> + statistics-file "data/named_stats.txt";
> + memstatistics-file "data/named_mem_stats.txt";
> +
> + /* Not used yet, support only on very recent bind versions */
> +# tkey-gssapi-credential "DNS/$FQDN";
> +# tkey-domain "$REALM";
> +};
> +
> +logging {
> +/* If you want to enable debugging, eg. using the 'rndc trace' command,
> + * By default, SELinux policy does not allow named to modify the /var/named directory,
> + * so put the default debug log file in data/ :
> + */
> + channel default_debug {
> + file "data/named.run";
> + severity dynamic;
> + };
> +};
> +
> +zone "." IN {
> + type hint;
> + file "named.ca";
> +};
> +
> +include "/etc/named.rfc1912.zones";
> +
> +zone "$DOMAIN" {
> + type master;
> + file "$DOMAIN.zone.db";
> +};
> +
> diff -r 578d26927d91 -r 9353b33672ee ipa-server/ipaserver/bindinstance.py
> --- /dev/null Thu Jan 01 00:00:00 1970 +0000
> +++ b/ipa-server/ipaserver/bindinstance.py Thu Sep 20 15:10:21 2007 -0400
> @@ -0,0 +1,113 @@
> +#! /usr/bin/python -E
> +# Authors: Simo Sorce <ssorce at redhat.com>
> +#
> +# Copyright (C) 2007 Red Hat
> +# see file 'COPYING' for use and warranty information
> +#
> +# 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; version 2 or later
> +#
> +# 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
> +# along with this program; if not, write to the Free Software
> +# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
> +#
> +
> +import string
> +import tempfile
> +import shutil
> +import os
> +import socket
> +from ipa.ipautil import *
> +
> +class BindInstance:
> + def __init__(self):
> + self.fqdn = None
> + self.domain = None
> + self.host = None
> + self.ip_address = None
> + self.realm = None
> + self.sub_dict = None
> +
> + def setup(self, fqdn, ip_address, realm_name):
> + self.fqdn = fqdn
> + self.ip_address = ip_address
> + self.realm = realm_name
> + self.domain = fqdn[fqdn.find(".")+1:]
> + self.host = fqdn[:fqdn.find(".")]
> +
> + self.__setup_sub_dict()
> +
> + def check_inst(self):
> + # 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'):
> + return False
> +
> + return True
> +
> + def create_sample_bind_zone(self):
> + bind_txt = template_file(SHARE_DIR + "bind.zone.db.template", self.sub_dict)
> + [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
> +
> + self.__setup_zone()
> + self.__setup_named_conf()
> +
> + self.start()
> +
> + def stop(self):
> + run(["/sbin/service", "named", "stop"])
> +
> + def start(self):
> + run(["/sbin/service", "named", "start"])
> +
> + def restart(self):
> + run(["/sbin/service", "named", "restart"])
> +
> + def __setup_sub_dict(self):
> + self.sub_dict = dict(FQDN=self.fqdn,
> + IP=self.ip_address,
> + DOMAIN=self.domain,
> + HOST=self.host,
> + REALM=self.realm)
> +
> + def __setup_zone(self):
> + zone_txt = template_file(SHARE_DIR + "bind.zone.db.template", self.sub_dict)
> + zone_fd = open('/var/named/'+self.domain+'.zone.db', 'w')
> + zone_fd.write(zone_txt)
> + zone_fd.close()
> +
> + def __setup_named_conf(self):
> + if os.path.exists('/etc/named.conf'):
> + shutil.copy2('/etc/named.conf', '/etc/named.conf.ipabkp')
> + named_txt = template_file(SHARE_DIR + "bind.named.conf.template", self.sub_dict)
> + named_fd = open('/etc/named.conf', 'w')
> + named_fd.seek(0)
> + named_fd.truncate(0)
> + named_fd.write(named_txt)
> + named_fd.close()
> +
> + if os.path.exists('/etc/resolve.conf'):
> + shutil.copy2('/etc/resolve.conf', '/etc/resolv.conf.ipabkp')
> + resolve_txt = "search "+self.domain+"\nnameserver "+self.ip_address+"\n"
> + resolve_fd = open('/etc/resolve.conf', 'w')
> + resolve_fd.seek(0)
> + resolve_fd.truncate(0)
> + resolve_fd.write(resolve_txt)
> + resolve_fd.close()
> +
> diff -r 578d26927d91 -r 9353b33672ee ipa-server/ipaserver/krbinstance.py
> --- a/ipa-server/ipaserver/krbinstance.py Thu Sep 13 12:10:55 2007 -0400
> +++ b/ipa-server/ipaserver/krbinstance.py Thu Sep 20 15:10:21 2007 -0400
> @@ -73,6 +73,9 @@ class KrbInstance:
>
> self.suffix = realm_to_suffix(self.realm)
> self.kdc_password = generate_kdc_password()
> +
> + self.stop()
> +
> self.__configure_kdc_account_password()
>
> self.__setup_sub_dict()
> @@ -88,8 +91,6 @@ class KrbInstance:
> self.__create_http_keytab()
>
> self.__export_kadmin_changepw_keytab()
> -
> - self.__create_sample_bind_zone()
>
> self.__add_pwd_extop_module()
>
> @@ -161,13 +162,6 @@ class KrbInstance:
> args = ["/usr/bin/setfacl", "-m", "u:"+self.ds_user+":r", "/var/kerberos/krb5kdc/.k5."+self.realm]
> run(args)
>
> - def __create_sample_bind_zone(self):
> - bind_txt = template_file(SHARE_DIR + "bind.zone.db.template", self.sub_dict)
> - [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_ds_keytab(self):
> (kwrite, kread, kerr) = os.popen3("/usr/kerberos/sbin/kadmin.local")
> kwrite.write("addprinc -randkey ldap/"+self.fqdn+"@"+self.realm+"\n")
>
> ------------------------------------------------------------------------
>
> _______________________________________________
> Freeipa-devel mailing list
> Freeipa-devel at redhat.com
> https://www.redhat.com/mailman/listinfo/freeipa-devel
--
Pete
-------------- next part --------------
A non-text attachment was scrubbed...
Name: smime.p7s
Type: application/x-pkcs7-signature
Size: 3241 bytes
Desc: S/MIME Cryptographic Signature
URL: <http://listman.redhat.com/archives/freeipa-devel/attachments/20070920/5e82d13f/attachment.bin>
More information about the Freeipa-devel
mailing list