From 9dfb0f05b03176dd8478b56ce684c9a2f4f07b0e Mon Sep 17 00:00:00 2001 From: Rob Crittenden Date: Mar 10 2011 14:57:36 +0000 Subject: Use TLS for dogtag replication agreements. Configure the dogtag 389-ds instance with SSL so we can enable TLS for the dogtag replication agreements. The NSS database we use is a symbolic link to the IPA 389-ds instance. ticket 1060 --- diff --git a/install/tools/ipa-replica-install b/install/tools/ipa-replica-install index d9a9748..cfaeaa4 100755 --- a/install/tools/ipa-replica-install +++ b/install/tools/ipa-replica-install @@ -167,9 +167,22 @@ def install_ca(config): print "Please install dogtag and restart the setup program" sys.exit(1) + # We replicate to the master using TLS. In order for this to work we + # need an SSL server cert. To make things easier we'll re-use the + # IPA 389-ds instance certificate loaded directly into the + # dogtag 389-ds instance. Later we will replace the NSS databases with + # symbolic links. + pkcs12_info = None + if ipautil.file_exists(config.dir + "/dscert.p12"): + pkcs12_info = (config.dir + "/dscert.p12", + config.dir + "/dirsrv_pin.txt") cs = cainstance.CADSInstance() cs.create_instance(config.realm_name, config.host_name, - config.domain_name, config.dirman_password) + config.domain_name, config.dirman_password, + pkcs12_info) + cs.load_pkcs12() + cs.enable_ssl() + cs.restart_instance() ca = cainstance.CAInstance(config.realm_name, certs.NSS_DIR) ca.configure_instance(config.host_name, config.dirman_password, config.dirman_password, pkcs12_info=(cafile,), @@ -187,8 +200,8 @@ def install_ca(config): service_name = cs.service_name service.print_msg("Restarting the directory and certificate servers") cs.service_name = "dirsrv" - cs.stop("PKI-IPA") ca.stop() + cs.stop("PKI-IPA") cs.start("PKI-IPA") ca.start() cs.service_name = service_name @@ -487,6 +500,15 @@ def main(): CA.ldap_enable('CA', config.host_name, config.dirman_password, util.realm_to_suffix(config.realm_name)) + # Now we will replace the existing dogtag 389-ds instance NSS + # database with a symbolic link to the IPA 389-ds NSS database. + caconfigdir = dsinstance.config_dirname(dsinstance.realm_to_serverid('PKI-IPA')) + for filename in ['cert8.db', 'key3.db', 'secmod.db', 'pin.txt']: + os.unlink('%s%s' % (caconfigdir, filename)) + dsconfigdir = dsinstance.config_dirname(dsinstance.realm_to_serverid(config.realm_name)) + for filename in ['cert8.db', 'key3.db', 'secmod.db', 'pin.txt']: + os.symlink('%s%s' % (dsconfigdir, filename), '%s%s' % (caconfigdir, filename)) + install_krb(config, setup_pkinit=options.setup_pkinit) install_http(config) if CA: diff --git a/install/tools/ipa-server-install b/install/tools/ipa-server-install index 29c3f78..9c0947c 100755 --- a/install/tools/ipa-server-install +++ b/install/tools/ipa-server-install @@ -760,6 +760,7 @@ def main(): ca.configure_instance(host_name, dm_password, dm_password, subject_base=options.subject) elif external == 1: + # stage 2 of external CA installation options.realm_name = realm_name options.domain_name = domain_name options.master_password = master_password @@ -776,6 +777,7 @@ def main(): # 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.') + cs = cainstance.CADSInstance(dm_password=dm_password) ca.configure_instance(host_name, dm_password, dm_password, cert_file=options.external_cert_file, cert_chain_file=options.external_ca_file, @@ -810,11 +812,23 @@ def main(): subject_base=options.subject, hbac_allow=not options.hbac_allow) - # We ned to ldap_enable the CA now that DS is up and running + # We need to ldap_enable the CA now that DS is up and running if not options.selfsign: ca.ldap_enable('CA', host_name, dm_password, util.realm_to_suffix(realm_name)) + # Symlink the IPA LDAP server NSS database to this one. + caconfigdir = dsinstance.config_dirname(dsinstance.realm_to_serverid('PKI-IPA')) + for filename in ['cert8.db', 'key3.db', 'secmod.db']: + os.unlink('%s%s' % (caconfigdir, filename)) + dsconfigdir = dsinstance.config_dirname(dsinstance.realm_to_serverid(realm_name)) + for filename in ['cert8.db', 'key3.db', 'secmod.db', 'pin.txt']: + os.symlink('%s%s' % (dsconfigdir, filename), '%s%s' % (caconfigdir, filename)) + + # Turn on SSL in the dogtag LDAP instance. This will get restarted + # later, we don't need SSL now. + cs.enable_ssl() + # Create a kerberos instance if options.pkinit_pin: [pw_fd, pw_name] = tempfile.mkstemp() diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py index 74d78dc..cb54747 100644 --- a/ipaserver/install/cainstance.py +++ b/ipaserver/install/cainstance.py @@ -47,9 +47,11 @@ import nss.nss as nss from ipapython import ipautil from ipapython import nsslib +from ipaserver import ipaldap from ipaserver.install import service from ipaserver.install import installutils from ipaserver.install import dsinstance +from ipaserver.install import certs from ipalib import util DEFAULT_DSPORT=7389 @@ -226,6 +228,7 @@ class CADSInstance(service.Service): self.pkcs12_info = None self.ds_port = None self.master_host = None + self.nickname = 'Server-Cert' if realm_name: self.suffix = util.realm_to_suffix(self.realm_name) self.__setup_sub_dict() @@ -246,7 +249,7 @@ class CADSInstance(service.Service): self.step("creating directory server user", self.__create_ds_user) self.step("creating directory server instance", self.__create_instance) - self.step("restarting directory server", self.__restart_instance) + self.step("restarting directory server", self.restart_instance) self.start_creation("Configuring directory server for the CA", 30) @@ -302,7 +305,48 @@ class CADSInstance(service.Service): logging.critical("failed to restart ds instance %s" % e) inf_fd.close() - def __restart_instance(self): + def load_pkcs12(self): + dirname = dsinstance.config_dirname(self.serverid) + dsdb = certs.CertDB(self.realm_name, nssdir=dirname) + if self.pkcs12_info: + dsdb.create_from_pkcs12(self.pkcs12_info[0], self.pkcs12_info[1]) + server_certs = dsdb.find_server_certs() + if len(server_certs) == 0: + raise RuntimeError("Could not find a suitable server cert in import in %s" % self.pkcs12_info[0]) + + # We only handle one server cert + self.nickname = server_certs[0][0] + self.dercert = dsdb.get_cert_from_db(self.nickname) + + def enable_ssl(self): + conn = ipaldap.IPAdmin("127.0.0.1", port=DEFAULT_DSPORT) + conn.simple_bind_s("cn=directory manager", self.dm_password) + + mod = [(ldap.MOD_REPLACE, "nsSSLClientAuth", "allowed"), + (ldap.MOD_REPLACE, "nsSSL3Ciphers", + "-rsa_null_md5,+rsa_rc4_128_md5,+rsa_rc4_40_md5,+rsa_rc2_40_md5,\ ++rsa_des_sha,+rsa_fips_des_sha,+rsa_3des_sha,+rsa_fips_3des_sha,+fortezza,\ ++fortezza_rc4_128_sha,+fortezza_null,+tls_rsa_export1024_with_rc4_56_sha,\ ++tls_rsa_export1024_with_des_cbc_sha")] + conn.modify_s("cn=encryption,cn=config", mod) + + mod = [(ldap.MOD_ADD, "nsslapd-security", "on"), + (ldap.MOD_ADD, "nsslapd-secureport", str(DEFAULT_DSPORT+1))] + conn.modify_s("cn=config", mod) + + entry = ipaldap.Entry("cn=RSA,cn=encryption,cn=config") + + entry.setValues("objectclass", "top", "nsEncryptionModule") + entry.setValues("cn", "RSA") + entry.setValues("nsSSLPersonalitySSL", self.nickname) + entry.setValues("nsSSLToken", "internal (software)") + entry.setValues("nsSSLActivation", "on") + + conn.addEntry(entry) + + conn.unbind() + + def restart_instance(self): try: # Have to trick the base class to use the right service name sav_name = self.service_name @@ -454,8 +498,8 @@ 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("restarting certificate server", self.__restart_instance) self.step("requesting RA certificate from CA", self.__request_ra_certificate) self.step("issuing RA agent certificate", self.__issue_ra_cert) self.step("adding RA agent as a trusted user", self.__configure_ra) @@ -463,7 +507,9 @@ class CAInstance(service.Service): self.step("setting up signing cert profile", self.__setup_sign_profile) self.step("set up CRL publishing", self.__enable_crl_publish) self.step("configuring certificate server to start on boot", self.__enable) - self.step("restarting certificate server", self.__restart_instance) + if not self.clone: + # A clone will be restarted in ipa-replica-install + self.step("restarting certificate server", self.__restart_instance) self.start_creation("Configuring certificate server", 360) @@ -590,6 +636,8 @@ class CAInstance(service.Service): args.append("admin") args.append("-sd_admin_password") args.append("'%s'" % self.admin_password) + args.append("-clone_start_tls") + args.append("true") args.append("-clone_uri") args.append("https://%s:%d" % (self.master_host, EE_SECURE_PORT)) else: