summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRob Crittenden <rcritten@redhat.com>2011-01-26 10:53:02 -0500
committerRob Crittenden <rcritten@redhat.com>2011-02-01 17:52:57 -0500
commitf3d04bfc405753b3c6a11a53ec6b2ccc99e8bf09 (patch)
tree8012c2dcdc84a9dec656fcb656ba145dcf488e13
parentc704ae605a5ee19642cc5dbf0189f416c8ff4588 (diff)
downloadfreeipa.git-f3d04bfc405753b3c6a11a53ec6b2ccc99e8bf09.tar.gz
freeipa.git-f3d04bfc405753b3c6a11a53ec6b2ccc99e8bf09.tar.xz
freeipa.git-f3d04bfc405753b3c6a11a53ec6b2ccc99e8bf09.zip
Fix installing with an external CA and wait for dogtag to come up
There wasn't an exception in the "is the server already installed" check for a two-stage CA installation. Made the installer slightly more robust. We create a cache file of answers so the next run won't ask all the questions again. This cache is removed when the installation is complete. Previously nothing would work if the installer was run more than once, this should be fixed now. The cache is encrypted using the DM password. The second problem is that the tomcat6 init script returns control before the web apps are up. Add a small loop in our restart method to wait for the 9180 port to be available. This also adds an additional restart to ensure that nonces are disabled. ticket 835 revise
-rwxr-xr-xinstall/tools/ipa-server-install50
-rw-r--r--ipaserver/install/cainstance.py23
2 files changed, 63 insertions, 10 deletions
diff --git a/install/tools/ipa-server-install b/install/tools/ipa-server-install
index 4a40c13a..64eccd87 100755
--- a/install/tools/ipa-server-install
+++ b/install/tools/ipa-server-install
@@ -39,6 +39,7 @@ import glob
import traceback
from ConfigParser import RawConfigParser
import random
+import tempfile
from ipaserver.install import dsinstance
from ipaserver.install import krbinstance
@@ -203,25 +204,33 @@ def signal_handler(signum, frame):
ANSWER_CACHE = "/root/.ipa_cache"
-def read_cache():
+def read_cache(dm_password):
"""
Returns a dict of cached answers or None if no cache file exists.
"""
if not ipautil.file_exists(ANSWER_CACHE):
return {}
+ top_dir = tempfile.mkdtemp("ipa")
+ try:
+ clearfile = "%s/cache" % top_dir
+ decrypt_file(ANSWER_CACHE, clearfile, dm_password, top_dir)
+ except Exception, e:
+ shutil.rmtree(top_dir)
+ raise RuntimeError("Problem decrypting answer cache in %s, check your password." % ANSWER_CACHE)
+
optdict={}
parser = RawConfigParser()
try:
- fp = open(ANSWER_CACHE, "r")
+ fp = open(clearfile, "r")
parser.readfp(fp)
optlist = parser.items('options')
fp.close()
- # this is one-use only
- os.remove(ANSWER_CACHE)
except IOError, e:
- raise RuntimeError("Unable to determine serial number: %s" % str(e))
+ raise RuntimeError("Error reading cache file %s: %s" % (ANSWER_CACHE, str(e)))
+ finally:
+ shutil.rmtree(top_dir)
for opt in optlist:
value = opt[1]
@@ -247,15 +256,19 @@ def write_cache(options):
# convert the options instance into a dict
optdict = eval(str(options))
parser = RawConfigParser()
+ top_dir = tempfile.mkdtemp("ipa")
try:
- fp = open(ANSWER_CACHE, "w")
+ fp = open("%s/cache" % top_dir, "w")
parser.add_section('options')
for opt in optdict:
parser.set('options', opt, optdict[opt])
parser.write(fp)
fp.close()
+ ipautil.encrypt_file("%s/cache" % top_dir, ANSWER_CACHE, options.dm_password, top_dir);
except IOError, e:
raise RuntimeError("Unable to cache command-line options %s" % str(e))
+ finally:
+ shutil.rmtree(top_dir)
def read_host_name(host_default,no_host_dns=False):
host_name = ""
@@ -464,7 +477,7 @@ def main():
else:
standard_logging_setup("/var/log/ipaserver-install.log", options.debug)
print "\nThe log file for this installation can be found in /var/log/ipaserver-install.log"
- if dsinstance.DsInstance().is_configured() or cainstance.CADSInstance().is_configured():
+ if (dsinstance.DsInstance().is_configured() or cainstance.CADSInstance().is_configured()) and not options.external_cert_file:
sys.exit("IPA server is already configured on this system.")
logging.debug('%s was invoked with options: %s' % (sys.argv[0], safe_options))
@@ -500,7 +513,9 @@ def main():
return uninstall()
# This will override any settings passed in on the cmdline
- options._update_loose(read_cache())
+ if ipautil.file_exists(ANSWER_CACHE):
+ dm_password = read_dm_password()
+ options._update_loose(read_cache(dm_password))
print "=============================================================================="
print "This program will set up the FreeIPA Server."
@@ -523,7 +538,9 @@ def main():
print "To accept the default shown in brackets, press the Enter key."
print ""
- if not options.external_ca:
+ if not options.external_ca and not options.external_cert_file:
+ # Let it past if there is an external_cert_file defined on the chance
+ # that we are coming in without a cache file.
check_dirsrv(options.unattended)
realm_name = ""
@@ -686,7 +703,8 @@ def main():
# Configure ntpd
if options.conf_ntp:
ntp = ntpinstance.NTPInstance(fstore)
- ntp.create_instance()
+ if not ntp.is_configured():
+ ntp.create_instance()
if options.selfsign:
ca = certs.CertDB(realm_name, host_name=host_name,
@@ -701,6 +719,10 @@ def main():
# Figure out what state we're in. See cainstance.py for more info on
# the 3 states.
+ if options.external_cert_file is not None and options.external_ca_file is not None:
+ # These options imply this and this is required to install the CA.
+ # This is needed otherwise the setup of dogtag will fail.
+ options.external_ca = True
external = 0
if options.external_ca:
external = 1
@@ -727,6 +749,8 @@ def main():
options.realm_name = realm_name
options.domain_name = domain_name
options.master_password = master_password
+ options.dm_password = dm_password
+ options.admin_password = admin_password
options.host_name = host_default
options.unattended = True
write_cache(options)
@@ -734,6 +758,10 @@ def main():
csr_file="/root/ipa.csr",
subject_base=options.subject)
else:
+ if not ca.is_installed():
+ # This can happen if someone passes external_ca_file without
+ # already having done the first stage of the CA install.
+ sys.exit('CA is not installed yet. To install with an external CA is a two-stage process.\nFirst run the installer with --external-ca.')
ca.configure_instance(host_name, dm_password, dm_password,
cert_file=options.external_cert_file,
cert_chain_file=options.external_ca_file,
@@ -910,6 +938,8 @@ def main():
print "This file is required to create replicas. The password for this"
print "file is the Directory Manager password"
+ if ipautil.file_exists(ANSWER_CACHE):
+ os.remove(ANSWER_CACHE)
return 0
try:
diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py
index 8aa1d447..7cdd28d9 100644
--- a/ipaserver/install/cainstance.py
+++ b/ipaserver/install/cainstance.py
@@ -35,6 +35,7 @@ import httplib
import urllib
import xml.dom.minidom
import stat
+import socket
from ipapython import dogtag
from ipapython.certdb import get_ca_nickname
from ipalib import pkcs10
@@ -391,6 +392,15 @@ class CAInstance(service.Service):
def __del__(self):
shutil.rmtree(self.ca_agent_db, ignore_errors=True)
+ def is_installed(self):
+ """
+ Installing with an external CA is a two-step process. This
+ is used to determine if the first step has been done.
+
+ Returns True/False
+ """
+ return os.path.exists(self.server_root + '/' + PKI_INSTANCE_NAME)
+
def configure_instance(self, host_name, dm_password,
admin_password, ds_port=DEFAULT_DSPORT,
pkcs12_info=None, master_host=None, csr_file=None,
@@ -442,6 +452,7 @@ class CAInstance(service.Service):
self.step("creating CA agent PKCS#12 file in /root", self.__create_ca_agent_pkcs12)
self.step("creating RA agent certificate database", self.__create_ra_agent_db)
self.step("importing CA chain to RA certificate database", self.__import_ca_chain)
+ self.step("restarting certificate server", self.__restart_instance)
if not self.clone:
self.step("requesting RA certificate from CA", self.__request_ra_certificate)
self.step("issuing RA agent certificate", self.__issue_ra_cert)
@@ -629,6 +640,18 @@ class CAInstance(service.Service):
def __restart_instance(self):
try:
self.restart()
+ # Wait until the dogtag webapp responds
+ while True:
+ try:
+ s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+ s.connect(('localhost', 9180))
+ s.close()
+ break
+ except socket.error, e:
+ if e.errno == 111: # Connection refused
+ time.sleep(1)
+ else:
+ raise e
except Exception:
# TODO: roll back here?
logging.critical("Failed to restart the certificate server. See the installation log for details.")