summaryrefslogtreecommitdiffstats
path: root/ipaserver
diff options
context:
space:
mode:
authorRob Crittenden <rcritten@redhat.com>2011-06-17 16:47:39 -0400
committerRob Crittenden <rcritten@redhat.com>2011-06-23 19:04:33 -0400
commit8a32bb3746802a29b2655e4ad2cbbba8481e1eaf (patch)
tree14c7e77b744d31e303d78313cf9866502dad1ef9 /ipaserver
parentcbffe1d65df222acf6eb26cdaa121932a01f9ba7 (diff)
downloadfreeipa-8a32bb3746802a29b2655e4ad2cbbba8481e1eaf.zip
freeipa-8a32bb3746802a29b2655e4ad2cbbba8481e1eaf.tar.gz
freeipa-8a32bb3746802a29b2655e4ad2cbbba8481e1eaf.tar.xz
Make dogtag an optional (and default un-) installed component in a replica.
A dogtag replica file is created as usual. When the replica is installed dogtag is optional and not installed by default. Adding the --setup-ca option will configure it when the replica is installed. A new tool ipa-ca-install will configure dogtag if it wasn't configured when the replica was initially installed. This moves a fair bit of code out of ipa-replica-install into installutils and cainstance to avoid duplication. https://fedorahosted.org/freeipa/ticket/1251
Diffstat (limited to 'ipaserver')
-rw-r--r--ipaserver/install/cainstance.py78
-rw-r--r--ipaserver/install/certs.py4
-rw-r--r--ipaserver/install/installutils.py57
-rw-r--r--ipaserver/install/replication.py33
4 files changed, 170 insertions, 2 deletions
diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py
index 928d01e..4ace26d 100644
--- a/ipaserver/install/cainstance.py
+++ b/ipaserver/install/cainstance.py
@@ -52,6 +52,7 @@ from ipaserver.install import service
from ipaserver.install import installutils
from ipaserver.install import dsinstance
from ipaserver.install import certs
+from ipaserver.install.installutils import ReplicaConfig
from ipalib import util
DEFAULT_DSPORT=7389
@@ -446,6 +447,7 @@ class CAInstance(service.Service):
self.csr_file = None
self.cert_file = None
self.cert_chain_file = None
+ self.create_ra_agent_db = True
# The same database is used for mod_nss because the NSS context
# will already have been initialized by Apache by the time
@@ -521,7 +523,8 @@ class CAInstance(service.Service):
if self.external != 1:
if not self.clone:
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)
+ if self.create_ra_agent_db:
+ 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)
if not self.clone:
self.step("restarting certificate server", self.__restart_instance)
@@ -1091,6 +1094,79 @@ class CAInstance(service.Service):
fd.close()
os.chmod(location, 0444)
+def install_replica_ca(config, postinstall=False):
+ """
+ Install a CA on a replica.
+
+ There are two modes of doing this controlled:
+ - While the replica is being installed
+ - Post-replica installation
+
+ config is a ReplicaConfig object
+
+ Returns a tuple of the CA and CADS instances
+ """
+ cafile = config.dir + "/cacert.p12"
+
+ if not ipautil.file_exists(cafile):
+ # not a dogtag CA replica
+ sys.exit('Not a dogtag CA installation')
+
+ if not config.setup_ca:
+ # We aren't configuring the CA in this step but we still need
+ # a minimum amount of information on the CA for this IPA install.
+ ca = CAInstance(config.realm_name, certs.NSS_DIR)
+ ca.dm_password = config.dirman_password
+ ca.subject_base = config.subject_base
+ return (ca, None)
+
+ ca = CAInstance(config.realm_name, certs.NSS_DIR)
+ ca.dm_password = config.dirman_password
+ ca.subject_base = config.subject_base
+ if ca.is_installed():
+ sys.exit("A CA is already configured on this system.")
+
+ pkcs12_info = None
+ if ipautil.file_exists(config.dir + "/dogtagcert.p12"):
+ pkcs12_info = (config.dir + "/dogtagcert.p12",
+ config.dir + "/dirsrv_pin.txt")
+ cs = CADSInstance()
+ cs.create_instance(config.realm_name, config.host_name,
+ config.domain_name, config.dirman_password,
+ pkcs12_info)
+ cs.load_pkcs12()
+ cs.enable_ssl()
+ cs.restart_instance()
+ ca = CAInstance(config.realm_name, certs.NSS_DIR)
+ if postinstall:
+ # If installing this afterward the Apache NSS database already
+ # exists, don't remove it.
+ ca.create_ra_agent_db = False
+ ca.configure_instance(config.host_name, config.dirman_password,
+ config.dirman_password, pkcs12_info=(cafile,),
+ master_host=config.master_host_name,
+ subject_base=config.subject_base)
+
+ # The dogtag DS instance needs to be restarted after installation.
+ # The procedure for this is: stop dogtag, stop DS, start DS, start
+ # dogtag
+ #
+ #
+ # The service_name trickery is due to the service naming we do
+ # internally. In the case of the dogtag DS the name doesn't match the
+ # unix service.
+
+ service_name = cs.service_name
+ service.print_msg("Restarting the directory and certificate servers")
+ cs.service_name = "dirsrv"
+ ca.stop()
+ cs.stop("PKI-IPA")
+ cs.start("PKI-IPA")
+ ca.start()
+ cs.service_name = service_name
+
+ return (ca, cs)
+
if __name__ == "__main__":
installutils.standard_logging_setup("install.log", False)
cs = CADSInstance()
diff --git a/ipaserver/install/certs.py b/ipaserver/install/certs.py
index 07dda2c..ebe654d 100644
--- a/ipaserver/install/certs.py
+++ b/ipaserver/install/certs.py
@@ -446,6 +446,7 @@ class CertDB(object):
return cert
else:
(cert, start) = find_cert_from_txt(cert, start=0)
+ cert = x509.strip_header(cert)
dercert = base64.b64decode(cert)
return dercert
except ipautil.CalledProcessError:
@@ -475,7 +476,8 @@ class CertDB(object):
service.stop("certmonger")
cert = self.get_cert_from_db(nickname)
- subject = str(x509.get_subject(cert))
+ nsscert = x509.load_certificate(cert, dbdir=self.secdir)
+ subject = str(nsscert.subject)
m = re.match('New tracking request "(\d+)" added', stdout)
if not m:
logging.error('Didn\'t get new certmonger request, got %s' % stdout)
diff --git a/ipaserver/install/installutils.py b/ipaserver/install/installutils.py
index f5a8625..68fce7e 100644
--- a/ipaserver/install/installutils.py
+++ b/ipaserver/install/installutils.py
@@ -29,6 +29,8 @@ import struct
import fcntl
import netaddr
import time
+import tempfile
+from ConfigParser import SafeConfigParser
from ipapython import ipautil
from ipapython import dnsclient
@@ -36,6 +38,17 @@ from ipapython import dnsclient
class HostnameLocalhost(Exception):
pass
+class ReplicaConfig:
+ def __init__(self):
+ self.realm_name = ""
+ self.domain_name = ""
+ self.master_host_name = ""
+ self.dirman_password = ""
+ self.host_name = ""
+ self.dir = ""
+ self.subject_base = ""
+ self.setup_ca = False
+
def get_fqdn():
fqdn = ""
try:
@@ -442,3 +455,47 @@ def resolve_host(host_name):
return addrinfos[0][4][0]
except:
return None
+
+def get_host_name(no_host_dns):
+ """
+ Get the current FQDN from the socket and verify that it is valid.
+
+ no_host_dns is a boolean that determines whether we enforce that the
+ hostname is resolvable.
+
+ Will raise a RuntimeError on error, returns hostname on success
+ """
+ hostname = get_fqdn()
+ verify_fqdn(hostname, no_host_dns)
+ return hostname
+
+def expand_replica_info(filename, password):
+ """
+ Decrypt and expand a replica installation file into a temporary
+ location. The caller is responsible to remove this directory.
+ """
+ top_dir = tempfile.mkdtemp("ipa")
+ tarfile = top_dir+"/files.tar"
+ dir = top_dir + "/realm_info"
+ ipautil.decrypt_file(filename, tarfile, password, top_dir)
+ ipautil.run(["tar", "xf", tarfile, "-C", top_dir])
+ os.remove(tarfile)
+
+ return top_dir, dir
+
+def read_replica_info(dir, rconfig):
+ """
+ Read the contents of a replica installation file.
+
+ rconfig is a ReplicaConfig object
+ """
+ filename = dir + "/realm_info"
+ fd = open(filename)
+ config = SafeConfigParser()
+ config.readfp(fd)
+
+ rconfig.realm_name = config.get("realm", "realm_name")
+ rconfig.master_host_name = config.get("realm", "master_host_name")
+ rconfig.domain_name = config.get("realm", "domain_name")
+ rconfig.host_name = config.get("realm", "destination_host")
+ rconfig.subject_base = config.get("realm", "subject_base")
diff --git a/ipaserver/install/replication.py b/ipaserver/install/replication.py
index e640873..fddb737 100644
--- a/ipaserver/install/replication.py
+++ b/ipaserver/install/replication.py
@@ -20,6 +20,7 @@
import time, logging
import os
+import sys
import ldap
from ipaserver import ipaldap
from ipaserver.install.service import restart
@@ -27,6 +28,7 @@ import installutils
from ldap import modlist
from ipalib import util
from ipalib import errors
+from ipapython import ipautil
DIRMAN_CN = "cn=directory manager"
CACERT = "/etc/ipa/ca.crt"
@@ -40,6 +42,37 @@ TIMEOUT = 120
IPA_REPLICA = 1
WINSYNC = 2
+def replica_conn_check(master_host, host_name, realm, check_ca,
+ admin_password=None):
+ """
+ Check the ports used by the replica both locally and remotely to be sure
+ that replication will work.
+
+ Does not return a value, will sys.exit() on failure.
+ """
+ print "Run connection check to master"
+ args = ["/usr/sbin/ipa-replica-conncheck", "--master", master_host,
+ "--auto-master-check", "--realm", realm,
+ "--principal", "admin",
+ "--hostname", host_name]
+
+ if admin_password:
+ args.extend(["--password", admin_password])
+
+ if check_ca:
+ args.append('--check-ca')
+ logging.debug("Running ipa-replica-conncheck with following arguments: %s" %
+ " ".join(args))
+ (stdin, stderr, returncode) = ipautil.run(args,raiseonerr=False, capture_output=False)
+
+ if returncode != 0:
+ sys.exit("Connection check failed!" +
+ "\nPlease fix your network settings according to error messages above." +
+ "\nIf the check results are not valid it can be skipped with --skip-conncheck parameter.")
+ else:
+ print "Connection check OK"
+
+
def check_replication_plugin():
"""
Confirm that the 389-ds replication is installed.