#! /usr/bin/python -E
# Authors: Karl MacMillan <kmacmillan@mentalrootkit.com>
2010-12-06 16:16:49 -05:00
# Simo Sorce <ssorce@redhat.com>
# Rob Crittenden <rcritten@redhat.com>
#
2010-12-06 16:16:49 -05:00
# Copyright (C) 2007-2010 Red Hat
# see file 'COPYING' for use and warranty information
#
2010-12-09 13:59:11 +01: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.
#
# 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 13:59:11 +01:00
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
# requires the following packages:
# fedora-ds-base
# openldap-clients
# nss-tools
import sys
2007-10-02 16:56:51 -04:00
import os
2007-10-15 13:27:05 -04:00
import errno
2011-01-28 15:45:19 -05:00
import grp
2007-10-03 17:37:13 -04:00
import subprocess
2007-10-02 16:56:51 -04:00
import signal
import shutil
import glob
import traceback
2011-11-03 11:08:26 +01:00
import pickle
2009-08-27 14:12:55 -04:00
import random
2011-01-26 10:53:02 -05:00
import tempfile
2011-08-17 10:19:37 +02:00
import nss.error
2011-09-26 08:27:01 +02:00
from optparse import OptionGroup , OptionValueError
2009-02-02 13:50:53 -05:00
from ipaserver.install import dsinstance
from ipaserver.install import krbinstance
from ipaserver.install import bindinstance
from ipaserver.install import httpinstance
from ipaserver.install import ntpinstance
2009-04-13 13:39:15 -04:00
from ipaserver.install import certs
2010-02-24 11:38:09 -05:00
from ipaserver.install import cainstance
2009-02-02 13:50:53 -05:00
from ipaserver.install import service
2009-02-05 15:03:08 -05:00
from ipapython import version
2009-02-02 13:50:53 -05:00
from ipaserver.install.installutils import *
2010-03-24 15:51:31 +01:00
from ipaserver.plugins.ldap2 import ldap2
2009-02-05 15:03:08 -05:00
from ipapython import sysrestore
from ipapython.ipautil import *
2010-03-24 15:51:31 +01:00
from ipalib import api , errors , util
2010-10-29 20:24:31 +02:00
from ipapython.config import IPAOptionParser
2011-07-07 11:55:20 -04:00
from ipalib.dn import DN
2011-08-17 10:19:37 +02:00
from ipalib.x509 import load_certificate_from_file , load_certificate_chain_from_file
2011-08-31 14:42:57 +02:00
from ipalib.constants import DNS_ZONE_REFRESH
2011-09-13 00:11:54 +03:00
from ipapython import services as ipaservices
2011-11-15 14:39:31 -05:00
from ipapython.ipa_log_manager import *
2008-07-11 11:34:29 -04:00
pw_name = None
2010-04-27 17:51:13 -04:00
uninstalling = False
2011-11-29 09:10:31 +01:00
installation_cleanup = True
2008-07-11 11:34:29 -04:00
2011-07-07 11:55:20 -04:00
VALID_SUBJECT_ATTRS = [ 'cn' , 'st' , 'o' , 'ou' , 'dnqualifier' , 'c' ,
'serialnumber' , 'l' , 'title' , 'sn' , 'givenname' ,
'initials' , 'generationqualifier' , 'dc' , 'mail' ,
'uid' , 'postaladdress' , 'postalcode' , 'postofficebox' ,
'houseidentifier' , 'e' , 'street' , 'pseudonym' ,
'incorporationlocality' , 'incorporationstate' ,
'incorporationcountry' , 'businesscategory' ]
def subject_callback ( option , opt_str , value , parser ):
"""
Make sure the certificate subject base is a valid DN
"""
name = opt_str . replace ( '--' , '' )
v = unicode ( value , 'utf-8' )
2011-09-26 08:27:01 +02:00
if any ( ord ( c ) < 0x20 for c in v ):
raise OptionValueError ( "Subject base must not contain control characters" )
if '&' in v :
raise OptionValueError ( "Subject base must not contain an ampersand ( \" & \" )" )
2011-07-07 11:55:20 -04:00
try :
dn = DN ( v )
2011-07-28 14:32:26 -04:00
for rdn in dn :
if rdn . attr . lower () not in VALID_SUBJECT_ATTRS :
2011-09-26 08:27:01 +02:00
raise OptionValueError ( 'invalid attribute: %s ' % rdn . attr )
2011-07-07 11:55:20 -04:00
except ValueError , e :
2011-09-26 08:27:01 +02:00
raise OptionValueError ( 'Invalid subject base format: %s ' % str ( e ))
2011-07-11 17:39:30 -04:00
parser . values . subject = str ( dn ) # may as well normalize it
2011-07-07 11:55:20 -04:00
2011-09-26 08:27:01 +02:00
def validate_dm_password ( password ):
if len ( password ) < 8 :
raise ValueError ( "Password must be at least 8 characters long" )
if any ( ord ( c ) < 0x20 for c in password ):
raise ValueError ( "Password must not contain control characters" )
if ' ' in password :
raise ValueError ( "Password must not contain a space ( \" \" )" )
if '&' in password :
raise ValueError ( "Password must not contain an ampersand ( \" & \" )" )
if ' \\ ' in password :
raise ValueError ( "Password must not contain a backslash ( \"\\\" )" )
def parse_options ():
2010-12-06 16:16:49 -05:00
# Guaranteed to give a random 200k range below the 2G mark (uint32_t limit)
namespace = random . randint ( 1 , 10000 ) * 200000
2010-10-29 20:24:31 +02:00
parser = IPAOptionParser ( version = version . VERSION )
2011-09-05 11:04:17 +02:00
basic_group = OptionGroup ( parser , "basic options" )
basic_group . add_option ( "-r" , "--realm" , dest = "realm_name" ,
help = "realm name" )
2011-09-05 11:04:17 +02:00
basic_group . add_option ( "-n" , "--domain" , dest = "domain_name" ,
2008-02-15 20:47:29 -05:00
help = "domain name" )
2011-09-05 11:04:17 +02:00
basic_group . add_option ( "-p" , "--ds-password" , dest = "dm_password" ,
2010-10-29 20:24:31 +02:00
sensitive = True , help = "admin password" )
2011-09-05 11:04:17 +02:00
basic_group . add_option ( "-P" , "--master-password" ,
2010-10-29 20:24:31 +02:00
dest = "master_password" , sensitive = True ,
2008-02-25 17:18:18 -05:00
help = "kerberos master password (normally autogenerated)" )
2011-09-05 11:04:17 +02:00
basic_group . add_option ( "-a" , "--admin-password" ,
2010-10-29 20:24:31 +02:00
sensitive = True , dest = "admin_password" ,
2007-08-31 18:40:01 -04:00
help = "admin user kerberos password" )
2011-09-05 11:04:17 +02:00
basic_group . add_option ( "--hostname" , dest = "host_name" , help = "fully qualified name of server" )
basic_group . add_option ( "--ip-address" , dest = "ip_address" ,
type = "ip" , ip_local = True ,
help = "Master Server IP Address" )
basic_group . add_option ( "-N" , "--no-ntp" , dest = "conf_ntp" , action = "store_false" ,
help = "do not configure ntp" , default = True )
basic_group . add_option ( "--idstart" , dest = "idstart" , default = namespace , type = int ,
help = "The starting value for the IDs range (default random)" )
basic_group . add_option ( "--idmax" , dest = "idmax" , default = 0 , type = int ,
help = "The max value value for the IDs range (default: idstart+199999)" )
basic_group . add_option ( "--no_hbac_allow" , dest = "hbac_allow" , default = False ,
action = "store_true" ,
help = "Don't install allow_all HBAC rule" )
basic_group . add_option ( "--no-ui-redirect" , dest = "ui_redirect" , action = "store_false" ,
default = True , help = "Do not automatically redirect to the Web UI" )
basic_group . add_option ( "-d" , "--debug" , dest = "debug" , action = "store_true" ,
2007-09-20 15:10:21 -04:00
default = False , help = "print debugging information" )
2011-09-05 11:04:17 +02:00
basic_group . add_option ( "-U" , "--unattended" , dest = "unattended" , action = "store_true" ,
default = False , help = "unattended (un)installation never prompts the user" )
parser . add_option_group ( basic_group )
cert_group = OptionGroup ( parser , "certificate system options" )
cert_group . add_option ( "" , "--external-ca" , dest = "external_ca" , action = "store_true" ,
2009-09-10 16:15:14 -04:00
default = False , help = "Generate a CSR to be signed by an external CA" )
2011-09-05 11:04:17 +02:00
cert_group . add_option ( "" , "--external_cert_file" , dest = "external_cert_file" ,
2009-09-10 16:15:14 -04:00
help = "File containing PKCS#10 certificate" )
2011-09-05 11:04:17 +02:00
cert_group . add_option ( "" , "--external_ca_file" , dest = "external_ca_file" ,
2009-09-10 16:15:14 -04:00
help = "File containing PKCS#10 of the external CA chain" )
2011-09-05 11:04:17 +02:00
cert_group . add_option ( "--no-pkinit" , dest = "setup_pkinit" , action = "store_false" ,
default = True , help = "disables pkinit setup steps" )
cert_group . add_option ( "--dirsrv_pkcs12" , dest = "dirsrv_pkcs12" ,
help = "PKCS#12 file containing the Directory Server SSL certificate" )
cert_group . add_option ( "--http_pkcs12" , dest = "http_pkcs12" ,
help = "PKCS#12 file containing the Apache Server SSL certificate" )
cert_group . add_option ( "--pkinit_pkcs12" , dest = "pkinit_pkcs12" ,
help = "PKCS#12 file containing the Kerberos KDC SSL certificate" )
cert_group . add_option ( "--dirsrv_pin" , dest = "dirsrv_pin" , sensitive = True ,
help = "The password of the Directory Server PKCS#12 file" )
cert_group . add_option ( "--http_pin" , dest = "http_pin" , sensitive = True ,
help = "The password of the Apache Server PKCS#12 file" )
cert_group . add_option ( "--pkinit_pin" , dest = "pkinit_pin" ,
help = "The password of the Kerberos KDC PKCS#12 file" )
cert_group . add_option ( "--subject" , action = "callback" , callback = subject_callback ,
type = "string" ,
help = "The certificate subject base (default O=<realm-name>)" )
2011-10-03 12:30:34 +02:00
cert_group . add_option ( "" , "--selfsign" , dest = "selfsign" , action = "store_true" ,
default = False , help = "Configure a self-signed CA instance rather than a dogtag CA. " \
"WARNING: Certificate management capabilities will be limited" )
2011-09-05 11:04:17 +02:00
parser . add_option_group ( cert_group )
dns_group = OptionGroup ( parser , "DNS options" )
dns_group . add_option ( "--setup-dns" , dest = "setup_dns" , action = "store_true" ,
2009-06-25 14:42:08 +02:00
default = False , help = "configure bind with our zone" )
2011-09-05 11:04:17 +02:00
dns_group . add_option ( "--forwarder" , dest = "forwarders" , action = "append" ,
2011-06-16 10:47:11 +02:00
type = "ip" , help = "Add a DNS forwarder" )
2011-09-05 11:04:17 +02:00
dns_group . add_option ( "--no-forwarders" , dest = "no_forwarders" , action = "store_true" ,
2009-09-01 23:28:52 +02:00
default = False , help = "Do not add any DNS forwarders, use root servers instead" )
2011-09-05 11:04:17 +02:00
dns_group . add_option ( "--reverse-zone" , dest = "reverse_zone" , help = "The reverse DNS zone to use" )
dns_group . add_option ( "--no-reverse" , dest = "no_reverse" , action = "store_true" ,
2011-01-04 08:55:47 -05:00
default = False , help = "Do not create reverse DNS zone" )
2011-10-24 18:35:48 +02:00
dns_group . add_option ( "--zonemgr" , action = "callback" , callback = bindinstance . zonemgr_callback ,
2011-04-22 17:18:57 -04:00
type = "string" ,
2010-09-20 15:41:20 -04:00
help = "DNS zone manager e-mail address. Defaults to root" )
2011-09-05 11:04:17 +02:00
dns_group . add_option ( "--zone-notif" , dest = "zone_notif" ,
2011-08-31 14:42:57 +02:00
action = "store_true" , default = False ,
help = "Let name server receive notification when a new zone is added." \
"Zone refresh is turned off when zone notification is enabled" )
2011-09-05 11:04:17 +02:00
dns_group . add_option ( "--zone-refresh" , dest = "zone_refresh" ,
2011-08-31 14:42:57 +02:00
default = DNS_ZONE_REFRESH , type = "int" ,
help = "A delay between checks for new DNS zones. Defaults to %d " \
% DNS_ZONE_REFRESH )
2011-09-05 11:04:17 +02:00
dns_group . add_option ( "--no-host-dns" , dest = "no_host_dns" , action = "store_true" ,
2008-09-16 20:18:11 -06:00
default = False ,
help = "Do not use DNS for hostname lookup during installation" )
2011-09-05 11:04:17 +02:00
parser . add_option_group ( dns_group )
uninstall_group = OptionGroup ( parser , "uninstall options" )
uninstall_group . add_option ( "" , "--uninstall" , dest = "uninstall" , action = "store_true" ,
default = False , help = "uninstall an existing installation. The uninstall can " \
"be run with --unattended option" )
parser . add_option_group ( uninstall_group )
options , args = parser . parse_args ()
2010-10-29 20:24:31 +02:00
safe_options = parser . get_safe_opts ( options )
2011-09-26 08:27:01 +02:00
if options . dm_password is not None :
try :
validate_dm_password ( options . dm_password )
except ValueError , e :
parser . error ( "DS admin password: " + str ( e ))
2011-08-15 09:02:39 +02:00
if options . admin_password is not None and len ( options . admin_password ) < 8 :
parser . error ( "Admin user password must be at least 8 characters long" )
2009-09-01 23:28:52 +02:00
if not options . setup_dns :
if options . forwarders :
parser . error ( "You cannot specify a --forwarder option without the --setup-dns option" )
if options . no_forwarders :
parser . error ( "You cannot specify a --no-forwarders option without the --setup-dns option" )
2011-07-11 10:14:53 +02:00
if options . reverse_zone :
parser . error ( "You cannot specify a --reverse-zone option without the --setup-dns option" )
2011-01-04 08:55:47 -05:00
if options . no_reverse :
parser . error ( "You cannot specify a --no-reverse option without the --setup-dns option" )
2009-09-01 23:28:52 +02:00
elif options . forwarders and options . no_forwarders :
parser . error ( "You cannot specify a --forwarder option together with --no-forwarders" )
2011-07-11 10:14:53 +02:00
elif options . reverse_zone and options . no_reverse :
parser . error ( "You cannot specify a --reverse-zone option together with --no-reverse" )
2009-09-01 23:28:52 +02:00
2008-01-11 11:57:36 +00:00
if options . uninstall :
2011-01-28 15:45:19 -05:00
if ( options . realm_name or
2010-04-15 11:08:48 +02:00
options . admin_password or options . master_password ):
2011-01-28 15:45:19 -05:00
parser . error ( "In uninstall mode, -a, -r and -P options are not allowed" )
2008-01-11 11:57:36 +00:00
elif options . unattended :
2011-01-24 14:58:11 -05:00
if ( not options . realm_name or
2008-02-25 17:18:18 -05:00
not options . dm_password or not options . admin_password ):
2011-01-24 14:58:11 -05:00
parser . error ( "In unattended mode you need to provide at least -r, -p and -a options" )
2009-09-01 23:28:52 +02:00
if options . setup_dns :
if not options . forwarders and not options . no_forwarders :
parser . error ( "You must specify at least one --forwarder option or --no-forwarders option" )
2008-07-11 11:34:29 -04:00
# If any of the PKCS#12 options are selected, all are required. Create a
# list of the options and count it to enforce that all are required without
# having a huge set of it blocks.
pkcs12 = [ options . dirsrv_pkcs12 , options . http_pkcs12 , options . dirsrv_pin , options . http_pin ]
cnt = pkcs12 . count ( None )
if cnt > 0 and cnt < 4 :
2009-11-23 08:42:30 +01:00
parser . error ( "All PKCS#12 options are required if any are used." )
2008-07-11 11:34:29 -04:00
2010-02-24 11:38:09 -05:00
if ( options . external_cert_file or options . external_ca_file ) and options . selfsign :
parser . error ( "--selfsign cannot be used with the external CA options." )
2009-09-10 16:15:14 -04:00
2011-07-26 13:21:36 +02:00
if options . external_ca :
if options . external_cert_file :
parser . error ( "You cannot specify --external_cert_file together with --external-ca" )
if options . external_ca_file :
parser . error ( "You cannot specify --external_ca_file together with --external-ca" )
2009-09-10 16:15:14 -04:00
if (( options . external_cert_file and not options . external_ca_file ) or
( not options . external_cert_file and options . external_ca_file )):
2011-07-26 13:21:36 +02:00
parser . error ( "if either external CA option is used, both are required." )
2009-09-10 16:15:14 -04:00
2010-04-01 17:20:38 -04:00
if ( options . external_ca_file and not os . path . isabs ( options . external_ca_file )):
parser . error ( "--external-ca-file must use an absolute path" )
if ( options . external_cert_file and not os . path . isabs ( options . external_cert_file )):
parser . error ( "--external-cert-file must use an absolute path" )
2010-11-11 18:15:28 -05:00
if options . idmax == 0 :
2010-12-06 16:16:49 -05:00
options . idmax = int ( options . idstart ) + 200000 - 1
2010-11-11 18:15:28 -05:00
if options . idmax < options . idstart :
2011-04-07 17:26:15 +02:00
parser . error ( "idmax ( %u ) cannot be smaller than idstart ( %u )" %
2010-11-11 18:15:28 -05:00
( options . idmax , options . idstart ))
2010-11-19 11:22:10 -05:00
#Automatically disable pkinit w/ dogtag until that is supported
if not options . pkinit_pkcs12 and not options . selfsign :
options . setup_pkinit = False
2011-08-31 14:42:57 +02:00
if options . zone_refresh < 0 :
parser . error ( "negative numbers not allowed for --zone-refresh" )
if options . zone_notif : # these 2 features are mutually exclusive
options . zone_refresh = 0
2010-10-29 20:24:31 +02:00
return safe_options , options
2007-10-02 16:56:51 -04:00
def signal_handler ( signum , frame ):
global ds
print " \n Cleaning up..."
if ds :
print "Removing configuration for %s instance" % ds . serverid
ds . stop ()
if ds . serverid :
2009-02-02 13:50:53 -05:00
dsinstance . erase_ds_instance_data ( ds . serverid )
2007-10-02 16:56:51 -04:00
sys . exit ( 1 )
2009-11-18 14:28:33 -05:00
ANSWER_CACHE = "/root/.ipa_cache"
2011-01-26 10:53:02 -05:00
def read_cache ( dm_password ):
2009-11-18 14:28:33 -05:00
"""
2011-11-03 11:08:26 +01:00
Returns a dict of cached answers or empty dict if no cache file exists.
2009-11-18 14:28:33 -05:00
"""
if not ipautil . file_exists ( ANSWER_CACHE ):
return {}
2011-01-26 10:53:02 -05:00
top_dir = tempfile . mkdtemp ( "ipa" )
2011-11-03 11:08:26 +01:00
fname = " %s /cache" % top_dir
2011-01-26 10:53:02 -05:00
try :
2011-11-03 11:08:26 +01:00
decrypt_file ( ANSWER_CACHE , fname , dm_password , top_dir )
2011-01-26 10:53:02 -05:00
except Exception , e :
shutil . rmtree ( top_dir )
2011-11-03 11:08:26 +01:00
raise Exception ( "Decryption of answer cache in %s failed, please check your password." % ANSWER_CACHE )
2011-01-26 10:53:02 -05:00
2009-11-18 14:28:33 -05:00
try :
2011-11-03 11:08:26 +01:00
with open ( fname , 'rb' ) as f :
try :
optdict = pickle . load ( f )
except Exception , e :
raise Exception ( "Parse error in %s : %s " % ( ANSWER_CACHE , str ( e )))
2009-11-18 14:28:33 -05:00
except IOError , e :
2011-11-03 11:08:26 +01:00
raise Exception ( "Read error in %s : %s " % ( ANSWER_CACHE , str ( e )))
2011-01-26 10:53:02 -05:00
finally :
shutil . rmtree ( top_dir )
2009-11-18 14:28:33 -05:00
# These are the only ones that may be overridden
2011-11-03 11:08:26 +01:00
for opt in ( 'external_ca_file' , 'external_cert_file' ):
try :
del optdict [ opt ]
except KeyError :
pass
2009-11-18 14:28:33 -05:00
return optdict
def write_cache ( options ):
"""
Takes a dict as input and writes a cached file of answers
"""
2011-01-26 10:53:02 -05:00
top_dir = tempfile . mkdtemp ( "ipa" )
2011-11-03 11:08:26 +01:00
fname = " %s /cache" % top_dir
2009-11-18 14:28:33 -05:00
try :
2011-11-03 11:08:26 +01:00
with open ( fname , 'wb' ) as f :
pickle . dump ( options , f )
ipautil . encrypt_file ( fname , ANSWER_CACHE , options [ 'dm_password' ], top_dir )
2009-11-18 14:28:33 -05:00
except IOError , e :
2011-11-03 11:08:26 +01:00
raise Exception ( "Unable to cache command-line options %s " % str ( e ))
2011-01-26 10:53:02 -05:00
finally :
shutil . rmtree ( top_dir )
2009-11-18 14:28:33 -05:00
2008-09-16 20:18:11 -06:00
def read_host_name ( host_default , no_host_dns = False ):
host_name = ""
print "Enter the fully qualified domain name of the computer"
print "on which you're setting up server software. Using the form"
print "<hostname>.<domainname>"
print "Example: master.example.com."
print ""
print ""
if host_default == "" :
host_default = "master.example.com"
2011-10-06 11:26:03 +02:00
host_name = user_input ( "Server host name" , host_default , allow_empty = False )
print ""
verify_fqdn ( host_name , no_host_dns )
return host_name
2008-02-25 17:16:18 -05:00
def read_domain_name ( domain_name , unattended ):
2008-02-15 20:47:29 -05:00
print "The domain name has been calculated based on the host name."
print ""
2008-02-25 17:16:18 -05:00
if not unattended :
2008-07-21 12:25:37 +02:00
domain_name = user_input ( "Please confirm the domain name" , domain_name )
2008-02-25 17:16:18 -05:00
print ""
2008-02-15 20:47:29 -05:00
return domain_name
2008-02-25 17:16:18 -05:00
def read_realm_name ( domain_name , unattended ):
print "The kerberos protocol requires a Realm name to be defined."
print "This is typically the domain name converted to uppercase."
print ""
2009-05-12 15:20:24 +02:00
2008-02-25 17:16:18 -05:00
if unattended :
2008-07-21 12:25:37 +02:00
return domain_name . upper ()
realm_name = user_input ( "Please provide a realm name" , domain_name . upper ())
2011-04-07 16:53:52 +02:00
upper_dom = realm_name . upper () #pylint: disable=E1103
2008-07-21 12:25:37 +02:00
if upper_dom != realm_name :
print "An upper-case realm name is required."
if not user_input ( "Do you want to use " + upper_dom + " as realm name?" , True ):
2008-02-25 17:16:18 -05:00
print ""
2008-07-21 12:25:37 +02:00
print "An upper-case realm name is required. Unable to continue."
sys . exit ( 1 )
else :
realm_name = upper_dom
print ""
return realm_name
2008-07-21 12:25:37 +02:00
def read_dm_password ():
print "Certain directory server operations require an administrative user."
print "This user is referred to as the Directory Manager and has full access"
2008-01-29 11:33:44 -05:00
print "to the Directory for system management tasks and will be added to the"
2008-01-25 17:08:36 -05:00
print "instance of directory server created for IPA."
print "The password must be at least 8 characters long."
print ""
#TODO: provide the option of generating a random password
2011-09-26 08:27:01 +02:00
dm_password = read_password ( "Directory Manager" , validator = validate_dm_password )
return dm_password
def read_admin_password ():
print "The IPA server requires an administrative user, named 'admin'."
print "This user is a regular system account used for IPA server administration."
print ""
#TODO: provide the option of generating a random password
admin_password = read_password ( "IPA admin" )
return admin_password
2008-05-30 15:31:13 -04:00
def check_dirsrv ( unattended ):
2009-02-02 13:50:53 -05:00
( ds_unsecure , ds_secure ) = dsinstance . check_ports ()
2008-01-22 08:03:06 +00:00
if not ds_unsecure or not ds_secure :
print "IPA requires ports 389 and 636 for the Directory Server."
print "These are currently in use:"
if not ds_unsecure :
print " \t 389"
if not ds_secure :
print " \t 636"
sys . exit ( 1 )
2010-10-06 10:16:54 -04:00
def uninstall ():
2010-04-15 11:08:48 +02:00
2011-08-29 11:16:52 -04:00
rv = 0
2010-11-08 11:05:37 -05:00
print "Shutting down all IPA services"
try :
( stdout , stderr , rc ) = run ([ "/usr/sbin/ipactl" , "stop" ], raiseonerr = False )
except Exception , e :
pass
print "Removing IPA client configuration"
2008-03-31 17:35:45 -04:00
try :
2010-08-31 17:21:25 -04:00
( stdout , stderr , rc ) = run ([ "/usr/sbin/ipa-client-install" , "--on-master" , "--unattended" , "--uninstall" ], raiseonerr = False )
2010-09-23 12:07:29 -04:00
if rc not in [ 0 , 2 ]:
2011-11-15 14:39:31 -05:00
root_logger . debug ( "ipa-client-install returned %d " % rc )
2010-08-31 17:21:25 -04:00
raise RuntimeError ( stdout )
2008-03-31 17:35:45 -04:00
except Exception , e :
2011-08-29 11:16:52 -04:00
rv = 1
2008-03-31 17:35:45 -04:00
print "Uninstall of client side components failed!"
print "ipa-client-install returned: " + str ( e )
2009-02-02 13:50:53 -05:00
ntpinstance . NTPInstance ( fstore ) . uninstall ()
2010-05-03 15:21:51 -04:00
if cainstance . CADSInstance () . is_configured ():
2009-04-01 22:39:44 -04:00
cainstance . CADSInstance () . uninstall ()
2010-12-08 16:35:12 -05:00
if cainstance . CAInstance ( api . env . realm , certs . NSS_DIR ) . is_configured ():
cainstance . CAInstance ( api . env . realm , certs . NSS_DIR ) . uninstall ()
2009-02-02 13:50:53 -05:00
bindinstance . BindInstance ( fstore ) . uninstall ()
httpinstance . HTTPInstance ( fstore ) . uninstall ()
krbinstance . KrbInstance ( fstore ) . uninstall ()
2011-03-01 14:17:03 +01:00
dsinstance . DsInstance ( fstore = fstore ) . uninstall ()
2008-03-27 19:01:38 -04:00
fstore . restore_all_files ()
2009-11-18 14:28:33 -05:00
try :
os . remove ( ANSWER_CACHE )
except Exception :
pass
2011-09-09 17:07:09 -04:00
2010-01-28 14:22:50 -05:00
# ipa-client-install removes /etc/ipa/default.conf
2011-01-28 15:45:19 -05:00
2011-02-07 13:31:51 -05:00
sstore . _load ()
2011-01-28 15:45:19 -05:00
group_exists = sstore . restore_state ( "install" , "group_exists" )
if group_exists == False :
try :
grp . getgrnam ( dsinstance . DS_GROUP )
try :
ipautil . run ([ "/usr/sbin/groupdel" , dsinstance . DS_GROUP ])
except ipautil . CalledProcessError , e :
2011-11-15 14:39:31 -05:00
root_logger . critical ( "failed to delete group %s " % e )
2011-08-29 11:16:52 -04:00
rv = 1
2011-01-28 15:45:19 -05:00
except KeyError :
2011-11-15 14:39:31 -05:00
root_logger . info ( "Group %s already removed" , dsinstance . DS_GROUP )
2011-01-28 15:45:19 -05:00
2011-09-13 00:11:54 +03:00
ipaservices . knownservices . ipa . disable ()
2011-03-07 16:29:08 -05:00
2011-10-13 12:16:15 +02:00
old_hostname = sstore . restore_state ( 'network' , 'hostname' )
system_hostname = get_fqdn ()
if old_hostname is not None and old_hostname != system_hostname :
try :
ipautil . run ([ '/bin/hostname' , old_hostname ])
except CalledProcessError , e :
print >> sys . stderr , "Failed to set this machine hostname back to %s ( %s )." % ( old_hostname , str ( e ))
2011-08-29 11:16:52 -04:00
if fstore . has_files ():
2011-11-15 14:39:31 -05:00
root_logger . error ( 'Some files have not been restored, see /var/lib/ipa/sysrestore/sysrestore.index' )
2011-08-29 11:16:52 -04:00
has_state = False
for module in IPA_MODULES : # from installutils
if sstore . has_state ( module ):
2011-11-15 14:39:31 -05:00
root_logger . error ( 'Some installation state for %s has not been restored, see /var/lib/ipa/sysrestore/sysrestore.state' % module )
2011-08-29 11:16:52 -04:00
has_state = True
rv = 1
if has_state :
2011-11-15 14:39:31 -05:00
root_logger . warning ( 'Some installation state has not been restored. \n This will cause re-installation to fail. \n It should be safe to remove /var/lib/ipa/sysrestore.state but it may \n mean your system hasn \' t be restored to its pre-installation state.' )
2011-08-29 11:16:52 -04:00
return rv
2008-01-11 11:57:36 +00:00
2009-11-02 14:16:27 -07:00
2011-02-15 14:11:27 -05:00
def set_subject_in_config ( realm_name , dm_password , suffix , subject_base ):
ldapuri = 'ldapi:// %% 2fvar %% 2frun %% 2fslapd- %s .socket' % (
dsinstance . realm_to_serverid ( realm_name )
)
2010-01-20 11:26:20 -05:00
try :
2010-03-24 15:51:31 +01:00
conn = ldap2 ( shared_instance = False , ldap_uri = ldapuri , base_dn = suffix )
conn . connect ( bind_dn = 'cn=directory manager' , bind_pw = dm_password )
except errors . ExecutionError , e :
2011-11-15 14:39:31 -05:00
root_logger . critical ( "Could not connect to the Directory Server on %s " % realm_name )
2010-01-20 11:26:20 -05:00
raise e
2010-03-24 15:51:31 +01:00
( dn , entry_attrs ) = conn . get_ipa_config ()
if 'ipacertificatesubjectbase' not in entry_attrs :
mod = { 'ipacertificatesubjectbase' : subject_base }
conn . update_entry ( dn , mod )
conn . disconnect ()
2009-11-02 14:16:27 -07:00
def main ():
2007-10-02 16:56:51 -04:00
global ds
2008-07-11 11:34:29 -04:00
global pw_name
2010-04-27 17:51:13 -04:00
global uninstalling
2011-11-29 09:10:31 +01:00
global installation_cleanup
2007-10-02 16:56:51 -04:00
ds = None
2010-10-29 20:24:31 +02:00
safe_options , options = parse_options ()
2007-10-02 16:56:51 -04:00
if os . getegid () != 0 :
2010-11-08 23:13:48 +01:00
sys . exit ( "Must be root to set up server" )
2008-02-20 10:16:19 -05:00
2007-10-02 16:56:51 -04:00
signal . signal ( signal . SIGTERM , signal_handler )
signal . signal ( signal . SIGINT , signal_handler )
2008-03-24 12:22:34 -04:00
if options . uninstall :
2010-04-27 17:51:13 -04:00
uninstalling = True
2011-11-15 14:39:31 -05:00
standard_logging_setup ( "/var/log/ipaserver-uninstall.log" , debug = options . debug )
2011-11-29 09:10:31 +01:00
installation_cleanup = False
2008-03-24 12:22:34 -04:00
else :
2011-11-15 14:39:31 -05:00
standard_logging_setup ( "/var/log/ipaserver-install.log" , debug = options . debug )
2008-03-24 12:22:34 -04:00
print " \n The log file for this installation can be found in /var/log/ipaserver-install.log"
2011-08-29 11:16:52 -04:00
if not options . external_ca and not options . external_cert_file and is_ipa_configured ():
2011-11-29 09:10:31 +01:00
installation_cleanup = False
2011-04-27 16:09:43 +02:00
sys . exit ( "IPA server is already configured on this system. \n "
+ "If you want to reinstall the IPA server please uninstall it first." )
2011-02-24 13:02:27 +01:00
client_fstore = sysrestore . FileStore ( '/var/lib/ipa-client/sysrestore' )
if client_fstore . has_files ():
2011-11-29 09:10:31 +01:00
installation_cleanup = False
2011-02-24 13:02:27 +01:00
sys . exit ( "IPA client is already configured on this system. \n "
+ "Please uninstall it first before configuring the IPA server." )
2011-11-15 14:39:31 -05:00
root_logger . debug ( ' %s was invoked with options: %s ' % ( sys . argv [ 0 ], safe_options ))
root_logger . debug ( "missing options might be asked for interactively later \n " )
2010-10-29 20:24:31 +02:00
2008-03-27 19:01:38 -04:00
global fstore
fstore = sysrestore . FileStore ( '/var/lib/ipa/sysrestore' )
2011-01-28 15:45:19 -05:00
global sstore
sstore = sysrestore . StateFile ( '/var/lib/ipa/sysrestore' )
2008-03-27 19:01:38 -04:00
2009-12-03 16:32:56 +01:00
# Configuration for ipalib, we will bootstrap and finalize later, after
# we are sure we have the configuration file ready.
2009-11-02 14:16:27 -07:00
cfg = dict (
2010-03-17 10:01:24 -04:00
context = 'installer' ,
2009-11-02 14:16:27 -07:00
in_server = True ,
2009-11-19 10:33:50 -05:00
debug = options . debug
2009-11-02 14:16:27 -07:00
)
2009-09-28 23:34:15 -04:00
2008-01-11 11:57:36 +00:00
if options . uninstall :
2010-04-15 11:08:48 +02:00
# We will need at least api.env, finalize api now. This system is
# already installed, so the configuration file is there.
api . bootstrap ( ** cfg )
api . finalize ()
2008-03-31 17:35:45 -04:00
if not options . unattended :
print " \n This is a NON REVERSIBLE operation and will delete all data and configuration! \n "
2008-08-06 11:27:04 -04:00
if not user_input ( "Are you sure you want to continue with the uninstall procedure?" , False ):
2008-03-31 17:35:45 -04:00
print ""
print "Aborting uninstall operation."
sys . exit ( 1 )
2010-10-06 10:16:54 -04:00
return uninstall ()
2008-01-11 11:57:36 +00:00
2011-07-26 13:21:36 +02:00
if options . external_ca :
if cainstance . CADSInstance () . is_configured ():
print "CA is already installed. \n Run the installer with --external_cert_file and --external_ca_file."
sys . exit ( 1 )
elif options . external_cert_file :
if not cainstance . CADSInstance () . is_configured ():
# This can happen if someone passes external_ca_file without
# already having done the first stage of the CA install.
print "CA is not installed yet. To install with an external CA is a two-stage process. \n First run the installer with --external-ca."
sys . exit ( 1 )
2009-11-18 14:28:33 -05:00
# This will override any settings passed in on the cmdline
2011-01-26 10:53:02 -05:00
if ipautil . file_exists ( ANSWER_CACHE ):
2011-07-26 13:21:36 +02:00
dm_password = read_password ( "Directory Manager" , confirm = False )
2011-10-06 08:22:08 +02:00
if dm_password is None :
sys . exit ( " \n Directory Manager password required" )
2011-11-03 11:08:26 +01:00
try :
options . _update_loose ( read_cache ( dm_password ))
except Exception , e :
sys . exit ( "Cannot process the cache file: %s " % str ( e ))
2009-11-18 14:28:33 -05:00
2011-08-17 10:19:37 +02:00
if options . external_cert_file :
try :
extcert = load_certificate_from_file ( options . external_cert_file )
except IOError , e :
print "Can't load the PKCS#10 certificate: %s ." % str ( e )
sys . exit ( 1 )
except nss . error . NSPRError :
print "' %s ' is not a valid PEM-encoded certificate." % options . external_cert_file
sys . exit ( 1 )
certsubject = unicode ( extcert . subject )
wantsubject = unicode ( DN (( 'CN' , 'Certificate Authority' ), options . subject ))
if certsubject . lower () != wantsubject . lower ():
print "Subject of the PKCS#10 certificate is not correct (got %s , expected %s )." % ( certsubject , wantsubject )
sys . exit ( 1 )
try :
extchain = load_certificate_chain_from_file ( options . external_ca_file )
except IOError , e :
print "Can't load the external CA chain: %s ." % str ( e )
sys . exit ( 1 )
except nss . error . NSPRError :
print "' %s ' is not a valid PEM-encoded certificate chain." % options . external_ca_file
sys . exit ( 1 )
certdict = dict (( unicode ( cert . subject ) . lower (), cert ) for cert in extchain )
certissuer = unicode ( extcert . issuer )
if certissuer . lower () not in certdict :
print "The PKCS#10 certificate is not signed by the external CA (unknown issuer %s )." % certissuer
sys . exit ( 1 )
cert = extcert
while cert . issuer != cert . subject :
certissuer = unicode ( cert . issuer )
if certissuer . lower () not in certdict :
print "The external CA chain is incomplete ( %s is missing from the chain)." % certissuer
sys . exit ( 1 )
cert = certdict [ certissuer . lower ()]
print "=============================================================================="
2010-02-03 14:56:17 -05:00
print "This program will set up the FreeIPA Server."
print ""
2008-01-25 17:08:36 -05:00
print "This includes:"
2011-10-03 12:30:34 +02:00
if options . selfsign :
print " * Configure NSS to handle a self-signed CA"
print " WARNING: certificate management capabilities will be limited"
else :
print " * Configure a stand-alone CA (dogtag) for certificate management"
2008-06-06 15:25:36 -04:00
if options . conf_ntp :
print " * Configure the Network Time Daemon (ntpd)"
2008-01-25 17:08:36 -05:00
print " * Create and configure an instance of Directory Server"
2008-03-04 14:47:47 -05:00
print " * Create and configure a Kerberos Key Distribution Center (KDC)"
2008-01-25 17:08:36 -05:00
print " * Configure Apache (httpd)"
2009-06-25 14:42:08 +02:00
if options . setup_dns :
2008-06-06 15:25:36 -04:00
print " * Configure DNS (bind)"
2010-10-29 16:23:21 -04:00
if options . setup_pkinit :
print " * Configure the KDC to enable PKINIT"
2008-06-06 15:25:36 -04:00
if not options . conf_ntp :
print ""
print "Excluded by options:"
print " * Configure the Network Time Daemon (ntpd)"
2008-01-25 17:08:36 -05:00
print ""
print "To accept the default shown in brackets, press the Enter key."
print ""
2011-10-21 15:25:21 -04:00
# Make sure the 389-ds ports are available
check_dirsrv ( options . unattended )
2007-08-20 18:40:32 -04:00
realm_name = ""
host_name = ""
2007-09-20 15:10:21 -04:00
domain_name = ""
ip_address = ""
2007-08-20 18:40:32 -04:00
master_password = ""
2007-08-31 18:40:01 -04:00
dm_password = ""
admin_password = ""
2011-07-11 10:14:53 +02:00
reverse_zone = None
2007-08-20 18:40:32 -04:00
2007-09-20 15:10:21 -04:00
# check bind packages are installed
2009-06-25 14:42:08 +02:00
if options . setup_dns :
2009-11-13 16:57:51 +01:00
if not bindinstance . check_inst ( options . unattended ):
2010-11-08 23:13:48 +01:00
sys . exit ( "Aborting installation" )
2007-09-20 15:10:21 -04:00
2011-03-03 16:03:44 -05:00
# Don't require an external DNS to say who we are if we are
# setting up a local DNS server.
options . no_host_dns = True
# check the hostname is correctly configured, it must be as the kldap
2010-12-01 17:22:56 +01:00
# utilities just use the hostname as returned by getaddrinfo to set
# up some of the standard entries
host_default = ""
if options . host_name :
host_default = options . host_name
else :
host_default = get_fqdn ()
2008-02-20 10:16:19 -05:00
2011-06-24 16:56:25 +02:00
try :
if options . unattended :
2008-09-16 20:18:11 -06:00
verify_fqdn ( host_default , options . no_host_dns )
2011-06-24 16:56:25 +02:00
host_name = host_default
else :
host_name = read_host_name ( host_default , options . no_host_dns )
2011-10-06 11:26:03 +02:00
except BadHostError , e :
2011-06-24 16:56:25 +02:00
sys . exit ( str ( e ) + " \n " )
2008-02-15 20:47:29 -05:00
2008-05-20 10:17:20 -04:00
host_name = host_name . lower ()
2011-11-15 14:39:31 -05:00
root_logger . debug ( "will use host_name: %s \n " % host_name )
2008-05-20 10:17:20 -04:00
2011-10-13 12:16:15 +02:00
system_hostname = get_fqdn ()
if host_name != system_hostname :
print >> sys . stderr
print >> sys . stderr , "Warning: hostname %s does not match system hostname %s ." \
% ( host_name , system_hostname )
print >> sys . stderr , "System hostname will be updated during the installation process"
print >> sys . stderr , "to prevent service failures."
print >> sys . stderr
2008-02-15 20:47:29 -05:00
if not options . domain_name :
2008-02-25 17:16:18 -05:00
domain_name = read_domain_name ( host_name [ host_name . find ( "." ) + 1 :], options . unattended )
2011-11-15 14:39:31 -05:00
root_logger . debug ( "read domain_name: %s \n " % domain_name )
2008-02-15 20:47:29 -05:00
else :
2008-02-25 17:16:18 -05:00
domain_name = options . domain_name
2007-09-20 15:10:21 -04:00
2008-05-20 10:17:20 -04:00
domain_name = domain_name . lower ()
2007-09-20 15:10:21 -04:00
# Check we have a public IP that is associated with the hostname
2011-11-29 09:10:31 +01:00
try :
hostaddr = resolve_host ( host_name )
except HostnameLocalhost :
print >> sys . stderr , "The hostname resolves to the localhost address (127.0.0.1/::1)"
print >> sys . stderr , "Please change your /etc/hosts file so that the hostname"
print >> sys . stderr , "resolves to the ip address of your network interface."
print >> sys . stderr , "The KDC service does not listen on localhost"
print >> sys . stderr , ""
print >> sys . stderr , "Please fix your /etc/hosts file and restart the setup program"
sys . exit ( 1 )
2011-11-07 18:35:23 +01:00
ip_add_to_hosts = False
2011-05-27 20:17:22 +02:00
if hostaddr is not None :
2011-06-13 16:37:40 -04:00
ip = CheckedIPAddress ( hostaddr , match_local = True )
2011-05-27 20:17:22 +02:00
else :
2011-11-07 18:35:23 +01:00
# hostname is not resolvable
2011-05-27 20:17:22 +02:00
ip = options . ip_address
2011-11-07 18:35:23 +01:00
ip_add_to_hosts = True
2011-07-18 13:36:47 +02:00
if ip is None :
print "Unable to resolve IP address for host name"
if options . unattended :
sys . exit ( 1 )
2007-09-20 15:10:21 -04:00
2011-05-27 20:17:22 +02:00
if options . ip_address :
if options . ip_address != ip and not options . setup_dns :
2010-11-08 23:13:48 +01:00
print >> sys . stderr , "Error: the hostname resolves to an IP address that is different"
print >> sys . stderr , "from the one provided on the command line. Please fix your DNS"
print >> sys . stderr , "or /etc/hosts file and restart the installation."
2008-05-22 16:36:11 -04:00
return 1
2008-02-20 10:16:19 -05:00
2011-05-27 20:17:22 +02:00
ip = options . ip_address
2007-09-20 15:10:21 -04:00
2011-05-27 20:17:22 +02:00
if ip is None :
2009-11-23 09:15:35 +01:00
ip = read_ip_address ( host_name , fstore )
2011-11-15 14:39:31 -05:00
root_logger . debug ( "read ip_address: %s \n " % str ( ip ))
2011-10-13 12:15:41 +02:00
2011-05-27 20:17:22 +02:00
ip_address = str ( ip )
2011-07-11 10:14:53 +02:00
2011-10-13 12:15:41 +02:00
# check /etc/hosts sanity, add a record when needed
hosts_record = record_in_hosts ( ip_address )
if hosts_record is None :
if ip_add_to_hosts :
print "Adding [" + ip_address + " " + host_name + "] to your /etc/hosts file"
fstore . backup_file ( "/etc/hosts" )
add_record_to_hosts ( ip_address , host_name )
else :
primary_host = hosts_record [ 1 ][ 0 ]
if primary_host != host_name :
print >> sys . stderr , "Error: there is already a record in /etc/hosts for IP address %s :" \
% ip_address
print >> sys . stderr , hosts_record [ 0 ], " " . join ( hosts_record [ 1 ])
print >> sys . stderr , "Chosen hostname %s does not match configured canonical hostname %s " \
% ( host_name , primary_host )
print >> sys . stderr , "Please fix your /etc/hosts file and restart the installation."
return 1
2011-07-11 10:14:53 +02:00
if options . reverse_zone and not bindinstance . verify_reverse_zone ( options . reverse_zone , ip ):
sys . exit ( 1 )
2007-09-20 15:10:21 -04:00
print "The IPA Master Server will be configured with"
print "Hostname: " + host_name
print "IP address: " + ip_address
print "Domain name: " + domain_name
2007-08-20 18:40:32 -04:00
print ""
if not options . realm_name :
2008-02-25 17:16:18 -05:00
realm_name = read_realm_name ( domain_name , options . unattended )
2011-11-15 14:39:31 -05:00
root_logger . debug ( "read realm_name: %s \n " % realm_name )
2007-08-20 18:40:32 -04:00
else :
2008-06-03 11:28:27 -04:00
realm_name = options . realm_name . upper ()
2007-08-20 18:40:32 -04:00
2010-11-01 13:51:14 -04:00
if not options . subject :
options . subject = "O= %s " % realm_name
2007-08-31 18:40:01 -04:00
if not options . dm_password :
dm_password = read_dm_password ()
2011-10-06 08:22:08 +02:00
if dm_password is None :
sys . exit ( " \n Directory Manager password required" )
2007-08-20 18:40:32 -04:00
else :
2007-08-31 18:40:01 -04:00
dm_password = options . dm_password
2007-08-20 18:40:32 -04:00
if not options . master_password :
master_password = ipa_generate_password ()
2007-08-20 18:40:32 -04:00
else :
master_password = options . master_password
2007-08-31 18:40:01 -04:00
if not options . admin_password :
admin_password = read_admin_password ()
2011-10-06 08:22:08 +02:00
if admin_password is None :
sys . exit ( " \n IPA admin password required" )
2007-08-31 18:40:01 -04:00
else :
admin_password = options . admin_password
2009-09-01 23:28:52 +02:00
if options . setup_dns :
if options . no_forwarders :
dns_forwarders = ()
elif options . forwarders :
dns_forwarders = options . forwarders
else :
dns_forwarders = read_dns_forwarders ()
2011-07-26 14:53:19 +02:00
if options . reverse_zone :
reverse_zone = bindinstance . normalize_zone ( options . reverse_zone )
elif not options . no_reverse :
reverse_zone = bindinstance . get_reverse_zone_default ( ip )
if not options . unattended and bindinstance . create_reverse ():
reverse_zone = bindinstance . read_reverse_zone ( reverse_zone , ip )
if reverse_zone is not None :
print "Using reverse zone %s " % reverse_zone
2009-09-08 01:03:55 -06:00
else :
dns_forwarders = ()
2011-11-15 14:39:31 -05:00
root_logger . debug ( "will use dns_forwarders: %s \n " % str ( dns_forwarders ))
2009-09-01 23:28:52 +02:00
2011-11-29 09:10:31 +01:00
# Installation has started. No IPA sysrestore items are restored in case of
# failure to enable root cause investigation
installation_cleanup = False
2009-12-03 16:32:56 +01:00
# Create the management framework config file and finalize api
2011-08-30 16:32:40 +02:00
target_fname = '/etc/ipa/default.conf'
fd = open ( target_fname , "w" )
fd . write ( "[global] \n " )
fd . write ( "host=" + host_name + " \n " )
fd . write ( "basedn=" + util . realm_to_suffix ( realm_name ) + " \n " )
fd . write ( "realm=" + realm_name + " \n " )
fd . write ( "domain=" + domain_name + " \n " )
2011-09-30 10:09:55 +02:00
fd . write ( "xmlrpc_uri=https:// %s /ipa/xml \n " % format_netloc ( host_name ))
2011-08-30 16:32:40 +02:00
fd . write ( "ldap_uri=ldapi:// %% 2fvar %% 2frun %% 2fslapd- %s .socket \n " % dsinstance . realm_to_serverid ( realm_name ))
fd . write ( "enable_ra=True \n " )
if not options . selfsign :
fd . write ( "ra_plugin=dogtag \n " )
fd . write ( "mode=production \n " )
fd . close ()
# Must be readable for everyone
os . chmod ( target_fname , 0644 )
2009-12-03 16:32:56 +01:00
api . bootstrap ( ** cfg )
api . finalize ()
2007-09-20 15:10:21 -04:00
if not options . unattended :
print ""
print "The following operations may take some minutes to complete."
print "Please wait until the prompt is returned."
2009-09-10 16:15:14 -04:00
print ""
2008-02-20 11:03:46 -05:00
2011-10-13 12:16:15 +02:00
if host_name != system_hostname :
2011-11-15 14:39:31 -05:00
root_logger . debug ( "Chosen hostname ( %s ) differs from system hostname ( %s ) - change it" \
2011-10-13 12:16:15 +02:00
% ( host_name , system_hostname ))
# configure /etc/sysconfig/network to contain the custom hostname
ipaservices . backup_and_replace_hostname ( fstore , sstore , host_name )
2011-01-28 15:45:19 -05:00
# Create DS group if it doesn't exist yet
try :
grp . getgrnam ( dsinstance . DS_GROUP )
2011-11-15 14:39:31 -05:00
root_logger . debug ( "ds group %s exists" % dsinstance . DS_GROUP )
2011-01-28 15:45:19 -05:00
group_exists = True
except KeyError :
group_exists = False
args = [ "/usr/sbin/groupadd" , "-r" , dsinstance . DS_GROUP ]
try :
ipautil . run ( args )
2011-11-15 14:39:31 -05:00
root_logger . debug ( "done adding DS group" )
2011-01-28 15:45:19 -05:00
except ipautil . CalledProcessError , e :
2011-11-15 14:39:31 -05:00
root_logger . critical ( "failed to add DS group: %s " % e )
2011-01-28 15:45:19 -05:00
sstore . backup_state ( "install" , "group_exists" , group_exists )
2010-12-08 10:25:49 -05:00
# Configure ntpd
if options . conf_ntp :
ntp = ntpinstance . NTPInstance ( fstore )
2011-01-26 10:53:02 -05:00
if not ntp . is_configured ():
ntp . create_instance ()
2008-07-11 11:34:29 -04:00
2010-12-08 16:35:12 -05:00
if options . selfsign :
ca = certs . CertDB ( realm_name , host_name = host_name ,
subject_base = options . subject )
ca . create_self_signed ()
else :
2009-04-13 13:39:15 -04:00
# Clean up any previous self-signed CA that may exist
try :
os . remove ( certs . CA_SERIALNO )
except :
pass
2009-09-10 16:15:14 -04:00
# Figure out what state we're in. See cainstance.py for more info on
# the 3 states.
2011-07-26 13:21:36 +02:00
if options . external_cert_file :
2009-09-10 16:15:14 -04:00
external = 2
2011-07-26 13:21:36 +02:00
elif options . external_ca :
external = 1
else :
external = 0
2009-09-10 16:15:14 -04:00
2011-06-10 15:28:46 -04:00
cs = cainstance . CADSInstance ( host_name , realm_name , domain_name , dm_password )
if not cs . is_configured ():
2011-03-14 16:27:19 -04:00
cs . create_instance ( realm_name , host_name , domain_name , dm_password , subject_base = options . subject )
2010-12-08 16:35:12 -05:00
ca = cainstance . CAInstance ( realm_name , certs . NSS_DIR )
2009-09-10 16:15:14 -04:00
if external == 0 :
2011-01-28 15:45:19 -05:00
ca . configure_instance ( host_name , dm_password , dm_password ,
subject_base = options . subject )
2009-09-10 16:15:14 -04:00
elif external == 1 :
2011-06-10 15:28:46 -04:00
# stage 1 of external CA installation
2010-04-01 17:20:38 -04:00
options . realm_name = realm_name
options . domain_name = domain_name
options . master_password = master_password
2011-01-26 10:53:02 -05:00
options . dm_password = dm_password
options . admin_password = admin_password
2011-07-26 13:21:36 +02:00
options . host_name = host_name
2010-04-01 17:20:38 -04:00
options . unattended = True
2011-07-26 13:21:36 +02:00
options . forwarders = dns_forwarders
options . reverse_zone = reverse_zone
2011-11-03 11:08:26 +01:00
write_cache ( vars ( options ))
2011-01-28 15:45:19 -05:00
ca . configure_instance ( host_name , dm_password , dm_password ,
csr_file = "/root/ipa.csr" ,
subject_base = options . subject )
2009-09-10 16:15:14 -04:00
else :
2011-06-10 15:28:46 -04:00
# stage 2 of external CA installation
2011-01-28 15:45:19 -05:00
ca . configure_instance ( host_name , dm_password , dm_password ,
cert_file = options . external_cert_file ,
cert_chain_file = options . external_ca_file ,
subject_base = options . subject )
2009-09-10 16:15:14 -04:00
2010-12-10 14:53:06 -05:00
# Now put the CA cert where other instances exepct it
ca . publish_ca_cert ( "/etc/ipa/ca.crt" )
# Create a directory server instance
2011-03-01 14:17:03 +01:00
ds = dsinstance . DsInstance ( fstore = fstore )
2010-12-08 10:25:49 -05:00
if options . dirsrv_pin :
[ pw_fd , pw_name ] = tempfile . mkstemp ()
os . write ( pw_fd , options . dirsrv_pin )
os . close ( pw_fd )
2008-07-11 11:34:29 -04:00
if options . dirsrv_pkcs12 :
pkcs12_info = ( options . dirsrv_pkcs12 , pw_name )
2009-04-01 22:39:44 -04:00
try :
2011-01-28 15:45:19 -05:00
ds . create_instance ( realm_name , host_name , domain_name ,
dm_password , pkcs12_info ,
subject_base = options . subject ,
hbac_allow = not options . hbac_allow )
2009-04-01 22:39:44 -04:00
finally :
os . remove ( pw_name )
2008-07-11 11:34:29 -04:00
else :
2011-01-28 15:45:19 -05:00
ds . create_instance ( realm_name , host_name , domain_name ,
2010-11-11 18:15:28 -05:00
dm_password , self_signed_ca = options . selfsign ,
idstart = options . idstart , idmax = options . idmax ,
subject_base = options . subject ,
hbac_allow = not options . hbac_allow )
2011-03-10 00:06:15 -05:00
# We need to ldap_enable the CA now that DS is up and running
2010-12-10 14:53:06 -05:00
if not options . selfsign :
ca . ldap_enable ( 'CA' , host_name , dm_password ,
util . realm_to_suffix ( realm_name ))
2011-03-10 00:06:15 -05:00
# Turn on SSL in the dogtag LDAP instance. This will get restarted
# later, we don't need SSL now.
2011-03-14 16:27:19 -04:00
cs . create_certdb ()
2011-03-10 00:06:15 -05:00
cs . enable_ssl ()
2011-03-14 16:27:19 -04:00
# Add the IPA service for storing the PKI-IPA server certificate.
2011-06-08 15:56:29 -04:00
cs . add_simple_service ( cs . principal )
2011-03-14 16:27:19 -04:00
cs . add_cert_to_service ()
2011-03-10 00:06:15 -05:00
2010-12-10 14:53:06 -05:00
# Create a kerberos instance
2010-10-29 16:23:21 -04:00
if options . pkinit_pin :
[ pw_fd , pw_name ] = tempfile . mkstemp ()
os . write ( pw_fd , options . dirsrv_pin )
os . close ( pw_fd )
2009-02-02 13:50:53 -05:00
krb = krbinstance . KrbInstance ( fstore )
2010-10-29 16:23:21 -04:00
if options . pkinit_pkcs12 :
pkcs12_info = ( options . pkinit_pkcs12 , pw_name )
2011-01-28 15:45:19 -05:00
krb . create_instance ( realm_name , host_name , domain_name ,
2010-10-29 16:23:21 -04:00
dm_password , master_password ,
setup_pkinit = options . setup_pkinit ,
pkcs12_info = pkcs12_info ,
subject_base = options . subject )
else :
2011-01-28 15:45:19 -05:00
krb . create_instance ( realm_name , host_name , domain_name ,
2010-10-29 16:23:21 -04:00
dm_password , master_password ,
setup_pkinit = options . setup_pkinit ,
self_signed_ca = options . selfsign ,
subject_base = options . subject )
if options . pkinit_pin :
os . remove ( pw_name )
2009-12-07 23:17:00 -05:00
# The DS instance is created before the keytab, add the SSL cert we
# generated
ds . add_cert_to_service ()
2007-10-15 15:42:12 -04:00
# Create a HTTP instance
2008-07-11 11:34:29 -04:00
if options . http_pin :
[ pw_fd , pw_name ] = tempfile . mkstemp ()
os . write ( pw_fd , options . http_pin )
os . close ( pw_fd )
2009-02-02 13:50:53 -05:00
http = httpinstance . HTTPInstance ( fstore )
2008-07-11 11:34:29 -04:00
if options . http_pkcs12 :
pkcs12_info = ( options . http_pkcs12 , pw_name )
2011-08-16 19:34:04 +02:00
http . create_instance ( realm_name , host_name , domain_name , dm_password , autoconfig = False , pkcs12_info = pkcs12_info , subject_base = options . subject , auto_redirect = options . ui_redirect )
2008-07-11 11:34:29 -04:00
os . remove ( pw_name )
else :
2011-08-16 19:34:04 +02:00
http . create_instance ( realm_name , host_name , domain_name , dm_password , autoconfig = True , self_signed_ca = options . selfsign , subject_base = options . subject , auto_redirect = options . ui_redirect )
2011-09-13 00:11:54 +03:00
ipaservices . restore_context ( "/var/cache/ipa/sessions" )
2011-02-15 14:11:27 -05:00
set_subject_in_config ( realm_name , dm_password , util . realm_to_suffix ( realm_name ), options . subject )
2010-01-20 11:26:20 -05:00
2008-09-15 18:15:12 -04:00
# Apply any LDAP updates. Needs to be done after the configuration file
# is created
service . print_msg ( "Applying LDAP updates" )
ds . apply_updates ()
2007-09-20 15:10:21 -04:00
# Restart ds and krb after configurations have been changed
2011-02-02 16:24:30 +01:00
service . print_msg ( "Restarting the directory server" )
2007-06-28 19:09:54 -04:00
ds . restart ()
2008-02-20 10:16:19 -05:00
2011-02-02 16:24:30 +01:00
service . print_msg ( "Restarting the KDC" )
2007-09-20 15:10:21 -04:00
krb . restart ()
2007-06-28 19:09:54 -04:00
2009-11-24 16:07:44 -05:00
# Restart httpd to pick up the new IPA configuration
2011-02-02 16:24:30 +01:00
service . print_msg ( "Restarting the web server" )
2009-11-24 16:07:44 -05:00
http . restart ()
2009-09-02 12:24:17 +02:00
# Create a BIND instance
bind = bindinstance . BindInstance ( fstore , dm_password )
2011-08-31 14:42:57 +02:00
bind . setup ( host_name , ip_address , realm_name , domain_name , dns_forwarders ,
options . conf_ntp , reverse_zone , zonemgr = options . zonemgr ,
zone_refresh = options . zone_refresh ,
zone_notif = options . zone_notif )
2009-09-02 12:24:17 +02:00
if options . setup_dns :
2009-09-02 16:22:50 +02:00
api . Backend . ldap2 . connect ( bind_dn = "cn=Directory Manager" , bind_pw = dm_password )
2009-09-02 12:24:17 +02:00
bind . create_instance ()
else :
bind . create_sample_bind_zone ()
2007-08-31 18:40:01 -04:00
# Set the admin user kerberos password
ds . change_admin_password ( admin_password )
2008-02-20 10:16:19 -05:00
# Call client install script
try :
2011-06-23 02:06:49 -04:00
run ([ "/usr/sbin/ipa-client-install" , "--on-master" , "--unattended" , "--domain" , domain_name , "--server" , host_name , "--realm" , realm_name , "--hostname" , host_name ])
2008-02-20 10:16:19 -05:00
except Exception , e :
2010-11-08 23:13:48 +01:00
sys . exit ( "Configuration of client side components failed! \n ipa-client-install returned: " + str ( e ))
2008-02-20 10:16:19 -05:00
2010-12-04 15:42:14 -05:00
#Everything installed properly, activate ipa service.
2011-09-13 00:11:54 +03:00
ipaservices . knownservices . ipa . enable ()
2010-12-04 15:42:14 -05:00
print "=============================================================================="
print "Setup complete"
print ""
print "Next steps:"
2008-06-06 15:25:36 -04:00
print " \t 1. You must make sure these network ports are open:"
print " \t\t TCP Ports:"
2008-01-25 17:08:36 -05:00
print " \t\t * 80, 443: HTTP/HTTPS"
print " \t\t * 389, 636: LDAP/LDAPS"
print " \t\t * 88, 464: kerberos"
2009-06-25 14:42:08 +02:00
if options . setup_dns :
2008-06-06 15:25:36 -04:00
print " \t\t * 53: bind"
print " \t\t UDP Ports:"
print " \t\t * 88, 464: kerberos"
2009-06-25 14:42:08 +02:00
if options . setup_dns :
2008-06-06 15:25:36 -04:00
print " \t\t * 53: bind"
if options . conf_ntp :
print " \t\t * 123: ntp"
print ""
2008-02-05 12:23:53 -05:00
print " \t 2. You can now obtain a kerberos ticket using the command: 'kinit admin'"
2010-02-03 14:47:51 -05:00
print " \t This ticket will allow you to use the IPA tools (e.g., ipa user-add)"
print " \t and the web user interface."
2011-09-13 00:11:54 +03:00
if not ipaservices . knownservices . ntpd . is_running ():
print " \t 3. Kerberos requires time synchronization between clients"
print " \t and servers for correct operation. You should consider enabling ntpd."
2008-02-05 12:23:53 -05:00
print ""
2010-03-10 11:55:48 -05:00
if options . http_pkcs12 :
2008-07-11 11:34:29 -04:00
print "In order for Firefox autoconfiguration to work you will need to"
print "use a SSL signing certificate. See the IPA documentation for more details."
2010-03-10 11:55:48 -05:00
print "You also need to install a PEM copy of the CA certificate into"
2008-07-11 11:34:29 -04:00
print "/usr/share/ipa/html/ca.crt"
2010-03-10 11:55:48 -05:00
else :
if options . selfsign :
print "Be sure to back up the CA certificate stored in /etc/httpd/alias/cacert.p12"
print "The password for this file is in /etc/httpd/alias/pwdfile.txt"
else :
print "Be sure to back up the CA certificate stored in /root/cacert.p12"
print "This file is required to create replicas. The password for this"
print "file is the Directory Manager password"
2011-01-26 10:53:02 -05:00
if ipautil . file_exists ( ANSWER_CACHE ):
os . remove ( ANSWER_CACHE )
return 0
try :
2011-11-29 09:10:31 +01:00
success = True
2008-07-11 11:34:29 -04:00
try :
2011-11-29 09:10:31 +01:00
rval = main ()
if rval != 0 :
success = False
sys . exit ( rval )
2008-07-11 11:34:29 -04:00
except SystemExit , e :
2011-11-29 09:10:31 +01:00
if e . code is not None or e . code != 0 :
success = False
2008-07-11 11:34:29 -04:00
sys . exit ( e )
except Exception , e :
2011-11-29 09:10:31 +01:00
success = False
2010-04-27 17:51:13 -04:00
if uninstalling :
2010-04-27 16:35:07 +02:00
message = "Unexpected error - see ipaserver-uninstall.log for details: \n %s " % str ( e )
2010-04-27 17:51:13 -04:00
else :
2010-04-27 16:35:07 +02:00
message = "Unexpected error - see ipaserver-install.log for details: \n %s " % str ( e )
2008-07-11 11:34:29 -04:00
print message
message = str ( e )
for str in traceback . format_tb ( sys . exc_info ()[ 2 ]):
message = message + " \n " + str
2011-11-15 14:39:31 -05:00
root_logger . debug ( message )
2008-07-11 11:34:29 -04:00
sys . exit ( 1 )
finally :
if pw_name and ipautil . file_exists ( pw_name ):
os . remove ( pw_name )
2011-11-29 09:10:31 +01:00
if not success and installation_cleanup :
# Do a cautious clean up as we don't know what failed and what is
# the state of the environment
try :
fstore . restore_file ( '/etc/hosts' )
except :
pass