From bfaea1dd78bbf6de0248ef8e33784d57ead9d24a Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 8 Dec 2010 16:35:12 -0500 Subject: Move Selfsigned CA creation out of dsinstance This allows us to have the CA ready to serve out certs for any operation even before the dsinstance is created. The CA is independent of the dsinstance anyway. Also fixes: https://fedorahosted.org/freeipa/ticket/544 --- install/tools/ipa-replica-install | 2 +- install/tools/ipa-replica-prepare | 13 +++------ install/tools/ipa-server-certinstall | 2 +- install/tools/ipa-server-install | 13 ++++++--- ipaserver/install/cainstance.py | 10 +++---- ipaserver/install/certs.py | 10 ++++++- ipaserver/install/dsinstance.py | 9 +++--- ipaserver/install/httpinstance.py | 56 +++++++++++++++++------------------- ipaserver/install/krbinstance.py | 9 ++---- 9 files changed, 62 insertions(+), 62 deletions(-) diff --git a/install/tools/ipa-replica-install b/install/tools/ipa-replica-install index c539e7517..3d6f4743a 100755 --- a/install/tools/ipa-replica-install +++ b/install/tools/ipa-replica-install @@ -158,7 +158,7 @@ def install_ca(config): cs = cainstance.CADSInstance() cs.create_instance(config.ds_user, config.realm_name, config.host_name, config.domain_name, config.dirman_password) - ca = cainstance.CAInstance(config.realm_name) + ca = cainstance.CAInstance(config.realm_name, certs.NSS_DIR) ca.configure_instance("pkiuser", config.host_name, config.dirman_password, config.dirman_password, pkcs12_info=(cafile,), master_host=config.master_host_name, subject_base=config.subject_base) return ca diff --git a/install/tools/ipa-replica-prepare b/install/tools/ipa-replica-prepare index d70741f1a..b9e3425ea 100755 --- a/install/tools/ipa-replica-prepare +++ b/install/tools/ipa-replica-prepare @@ -27,7 +27,7 @@ import krbV from optparse import OptionParser from ipapython import ipautil -from ipaserver.install import bindinstance, dsinstance, installutils, certs, httpinstance +from ipaserver.install import bindinstance, dsinstance, installutils, certs from ipaserver.install.bindinstance import add_zone, add_reverze_zone, add_rr, add_ptr_rr from ipaserver.plugins.ldap2 import ldap2 from ipapython import version @@ -123,14 +123,9 @@ def export_certdb(realm_name, ds_dir, dir, passwd_fname, fname, hostname, subjec try: self_signed = certs.ipa_self_signed() - db = certs.CertDB(dir, realm_name, subject_base=subject_base) + db = certs.CertDB(realm_name, nssdir=dir, subject_base=subject_base) db.create_passwd_file() -# if self_signed: -# ca_db = certs.CertDB(dsinstance.config_dirname(dsinstance.realm_to_serverid(realm_name))) -# db.create_from_cacert(ca_db.cacert_fname) -# else: -# ca_db = certs.CertDB(httpinstance.NSS_DIR, host_name=api.env.host) - ca_db = certs.CertDB(httpinstance.NSS_DIR, realm_name, host_name=api.env.host, subject_base=subject_base) + ca_db = certs.CertDB(realm_name, host_name=api.env.host, subject_base=subject_base) if is_kdc: ca_db.create_kdc_cert("KDC-Cert", hostname, dir) else: @@ -177,7 +172,7 @@ def export_ra_pkcs12(dir, dm_password): try: try: - db = certs.CertDB(httpinstance.NSS_DIR, api.env.realm, host_name=api.env.host) + db = certs.CertDB(api.env.realm, host_name=api.env.host) if db.has_nickname("ipaCert"): pkcs12_fname = "%s/ra.p12" % dir diff --git a/install/tools/ipa-server-certinstall b/install/tools/ipa-server-certinstall index 4b460535d..5c6b25bc7 100755 --- a/install/tools/ipa-server-certinstall +++ b/install/tools/ipa-server-certinstall @@ -89,7 +89,7 @@ def choose_server_cert(server_certs): return server_certs[num - 1] def import_cert(dirname, pkcs12_fname, pkcs12_passwd, db_password): - cdb = certs.CertDB(dirname, api.env.realm) + cdb = certs.CertDB(api.env.realm, nssdir=dirname) cdb.create_passwd_file(db_password) cdb.create_certdbs() [pw_fd, pw_name] = tempfile.mkstemp() diff --git a/install/tools/ipa-server-install b/install/tools/ipa-server-install index 67c1a004e..7fa6c71df 100755 --- a/install/tools/ipa-server-install +++ b/install/tools/ipa-server-install @@ -420,8 +420,8 @@ def uninstall(): ntpinstance.NTPInstance(fstore).uninstall() if cainstance.CADSInstance().is_configured(): cainstance.CADSInstance().uninstall() - if cainstance.CAInstance(api.env.realm).is_configured(): - cainstance.CAInstance(api.env.realm).uninstall() + if cainstance.CAInstance(api.env.realm, certs.NSS_DIR).is_configured(): + cainstance.CAInstance(api.env.realm, certs.NSS_DIR).uninstall() bindinstance.BindInstance(fstore).uninstall() httpinstance.HTTPInstance(fstore).uninstall() krbinstance.KrbInstance(fstore).uninstall() @@ -693,7 +693,12 @@ def main(): ntp = ntpinstance.NTPInstance(fstore) ntp.create_instance() - if not options.selfsign: + if options.selfsign: + ca = certs.CertDB(realm_name, host_name=host_name, + subject_base=options.subject) + ca.create_self_signed() + ca.publish_ca_cert("/etc/ipa/ca.crt") + else: # Clean up any previous self-signed CA that may exist try: os.remove(certs.CA_SERIALNO) @@ -720,7 +725,7 @@ def main(): if options.external_cert_file is None: cs = cainstance.CADSInstance() cs.create_instance("pkisrv", realm_name, host_name, domain_name, dm_password) - ca = cainstance.CAInstance(realm_name) + ca = cainstance.CAInstance(realm_name, certs.NSS_DIR) if external == 0: ca.configure_instance("pkiuser", host_name, dm_password, dm_password, subject_base=options.subject) elif external == 1: diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py index 4a645bc84..e03adfb9b 100644 --- a/ipaserver/install/cainstance.py +++ b/ipaserver/install/cainstance.py @@ -341,8 +341,8 @@ class CADSInstance(service.Service): class CAInstance(service.Service): """ - In the self-signed case (all done in certs.py) the CA exists in the DS - database. When using a dogtag CA the DS database contains just the + In the self-signed case the CA exists in the NSS_DB database. + When using a dogtag CA the DS database contains just the server cert for DS. The mod_nss database will contain the RA agent cert that will be used to do authenticated requests against dogtag. @@ -357,7 +357,7 @@ class CAInstance(service.Service): 2 = have signed cert, continue installation """ - def __init__(self, realm): + def __init__(self, realm, ra_db): service.Service.__init__(self, "pki-cad") self.realm = realm self.pki_user = "pkiuser" @@ -378,7 +378,7 @@ class CAInstance(service.Service): self.canickname = get_ca_nickname(realm) self.basedn = "o=ipaca" self.ca_agent_db = tempfile.mkdtemp(prefix = "tmp-") - self.ra_agent_db = "/etc/httpd/alias" + self.ra_agent_db = ra_db self.ra_agent_pwd = self.ra_agent_db + "/pwdfile.txt" self.ds_port = DEFAULT_DSPORT self.domain_name = "IPA" @@ -1000,5 +1000,5 @@ if __name__ == "__main__": installutils.standard_logging_setup("install.log", False) cs = CADSInstance() cs.create_instance("dirsrv", "EXAMPLE.COM", "catest.example.com", "example.com", "password") - ca = CAInstance("EXAMPLE.COM") + ca = CAInstance("EXAMPLE.COM", "/etc/httpd/alias") ca.configure_instance("pkiuser", "catest.example.com", "password", "password") diff --git a/ipaserver/install/certs.py b/ipaserver/install/certs.py index bd5c7bf9c..0a40c667c 100644 --- a/ipaserver/install/certs.py +++ b/ipaserver/install/certs.py @@ -47,6 +47,10 @@ from ipalib import api from ipalib.compat import sha1 +# Apache needs access to this database so we need to create it +# where apache can reach +NSS_DIR = "/etc/httpd/alias" + CA_SERIALNO="/var/lib/ipa/ca_serialno" def ipa_self_signed(): @@ -163,7 +167,7 @@ def next_replica(serial_file=CA_SERIALNO): return str(serial) class CertDB(object): - def __init__(self, nssdir, realm, fstore=None, host_name=None, subject_base=None): + def __init__(self, realm, nssdir=NSS_DIR, fstore=None, host_name=None, subject_base=None): self.secdir = nssdir self.realm = realm @@ -1040,3 +1044,7 @@ class CertDB(object): self.fstore.backup_file(self.pin_fname) self.fstore.backup_file(self.certreq_fname) self.fstore.backup_file(self.certder_fname) + + def publish_ca_cert(self, location): + shutil.copy(self.cacert_fname, location) + os.chmod(location, 0444) diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py index 6fdc479ca..36bc51530 100644 --- a/ipaserver/install/dsinstance.py +++ b/ipaserver/install/dsinstance.py @@ -469,7 +469,7 @@ class DsInstance(service.Service): def __enable_ssl(self): dirname = config_dirname(self.serverid) - dsdb = certs.CertDB(dirname, self.realm_name, subject_base=self.subject_base) + dsdb = certs.CertDB(self.realm_name, nssdir=dirname, subject_base=self.subject_base) if self.pkcs12_info: dsdb.create_from_pkcs12(self.pkcs12_info[0], self.pkcs12_info[1]) server_certs = dsdb.find_server_certs() @@ -481,9 +481,8 @@ class DsInstance(service.Service): self.dercert = dsdb.get_cert_from_db(nickname) else: nickname = "Server-Cert" - cadb = certs.CertDB(httpinstance.NSS_DIR, self.realm_name, host_name=self.fqdn, subject_base=self.subject_base) + cadb = certs.CertDB(self.realm_name, host_name=self.fqdn, subject_base=self.subject_base) if self.self_signed_ca: - cadb.create_self_signed() dsdb.create_from_cacert(cadb.cacert_fname, passwd=None) self.dercert = dsdb.create_server_cert("Server-Cert", self.fqdn, cadb) dsdb.track_server_cert("Server-Cert", self.principal, dsdb.passwd_fname) @@ -601,7 +600,7 @@ class DsInstance(service.Service): # drop the trailing / off the config_dirname so the directory # will match what is in certmonger dirname = config_dirname(serverid)[:-1] - dsdb = certs.CertDB(dirname, self.realm_name) + dsdb = certs.CertDB(self.realm_name, nssdir=dirname) dsdb.untrack_server_cert("Server-Cert") erase_ds_instance_data(serverid) @@ -643,7 +642,7 @@ class DsInstance(service.Service): self.stop() dirname = config_dirname(realm_to_serverid(self.realm_name)) - certdb = certs.CertDB(dirname, self.realm_name, subject_base=self.subject_base) + certdb = certs.CertDB(self.realm_name, nssdir=dirname, subject_base=self.subject_base) if not cacert_name or len(cacert_name) == 0: cacert_name = "Imported CA" # we can't pass in the nickname, so we set the instance variable diff --git a/ipaserver/install/httpinstance.py b/ipaserver/install/httpinstance.py index 73930825f..411f2ae46 100644 --- a/ipaserver/install/httpinstance.py +++ b/ipaserver/install/httpinstance.py @@ -35,7 +35,6 @@ from ipalib import util, api HTTPD_DIR = "/etc/httpd" SSL_CONF = HTTPD_DIR + "/conf.d/ssl.conf" NSS_CONF = HTTPD_DIR + "/conf.d/nss.conf" -NSS_DIR = HTTPD_DIR + "/alias" selinux_warning = """WARNING: could not set selinux boolean httpd_can_network_connect to true. The web interface may not function correctly until this boolean is @@ -166,11 +165,13 @@ class HTTPInstance(service.Service): print "Adding Include conf.d/ipa-rewrite to %s failed." % NSS_CONF def __setup_ssl(self): - if self.self_signed_ca: - ca_db = certs.CertDB(NSS_DIR, self.realm, subject_base=self.subject_base) - else: - ca_db = certs.CertDB(NSS_DIR, self.realm, host_name=self.fqdn, subject_base=self.subject_base) - db = certs.CertDB(NSS_DIR, self.realm, subject_base=self.subject_base) + fqdn = None + if not self.self_signed_ca: + fqdn = self.fqdn + + ca_db = certs.CertDB(self.realm, host_name=fqdn, subject_base=self.subject_base) + + db = certs.CertDB(self.realm, subject_base=self.subject_base) if self.pkcs12_info: db.create_from_pkcs12(self.pkcs12_info[0], self.pkcs12_info[1], passwd="") server_certs = db.find_server_certs() @@ -186,31 +187,27 @@ class HTTPInstance(service.Service): else: if self.self_signed_ca: db.create_from_cacert(ca_db.cacert_fname) - db.create_password_conf() - self.dercert = db.create_server_cert("Server-Cert", self.fqdn, ca_db) - db.track_server_cert("Server-Cert", self.principal, db.passwd_fname) - db.create_signing_cert("Signing-Cert", "Object Signing Cert", ca_db) - else: - self.dercert = db.create_server_cert("Server-Cert", self.fqdn, ca_db) - db.track_server_cert("Server-Cert", self.principal, db.passwd_fname) - db.create_signing_cert("Signing-Cert", "Object Signing Cert", ca_db) - db.create_password_conf() + + db.create_password_conf() + self.dercert = db.create_server_cert("Server-Cert", self.fqdn, ca_db) + db.track_server_cert("Server-Cert", self.principal, db.passwd_fname) + db.create_signing_cert("Signing-Cert", "Object Signing Cert", ca_db) # Fix the database permissions - os.chmod(NSS_DIR + "/cert8.db", 0660) - os.chmod(NSS_DIR + "/key3.db", 0660) - os.chmod(NSS_DIR + "/secmod.db", 0660) - os.chmod(NSS_DIR + "/pwdfile.txt", 0660) + os.chmod(certs.NSS_DIR + "/cert8.db", 0660) + os.chmod(certs.NSS_DIR + "/key3.db", 0660) + os.chmod(certs.NSS_DIR + "/secmod.db", 0660) + os.chmod(certs.NSS_DIR + "/pwdfile.txt", 0660) pent = pwd.getpwnam("apache") - os.chown(NSS_DIR + "/cert8.db", 0, pent.pw_gid ) - os.chown(NSS_DIR + "/key3.db", 0, pent.pw_gid ) - os.chown(NSS_DIR + "/secmod.db", 0, pent.pw_gid ) - os.chown(NSS_DIR + "/pwdfile.txt", 0, pent.pw_gid ) + os.chown(certs.NSS_DIR + "/cert8.db", 0, pent.pw_gid ) + os.chown(certs.NSS_DIR + "/key3.db", 0, pent.pw_gid ) + os.chown(certs.NSS_DIR + "/secmod.db", 0, pent.pw_gid ) + os.chown(certs.NSS_DIR + "/pwdfile.txt", 0, pent.pw_gid ) # Fix SELinux permissions on the database - ipautil.run(["/sbin/restorecon", NSS_DIR + "/cert8.db"]) - ipautil.run(["/sbin/restorecon", NSS_DIR + "/key3.db"]) + ipautil.run(["/sbin/restorecon", certs.NSS_DIR + "/cert8.db"]) + ipautil.run(["/sbin/restorecon", certs.NSS_DIR + "/key3.db"]) # In case this got generated as part of the install, reset the # context @@ -226,7 +223,7 @@ class HTTPInstance(service.Service): prefs_fd.close() # The signing cert is generated in __setup_ssl - db = certs.CertDB(NSS_DIR, self.realm, subject_base=self.subject_base) + db = certs.CertDB(self.realm, subject_base=self.subject_base) pwdfile = open(db.passwd_fname) pwd = pwdfile.read() @@ -241,9 +238,8 @@ class HTTPInstance(service.Service): shutil.rmtree(tmpdir) def __publish_ca_cert(self): - ca_db = certs.CertDB(NSS_DIR, self.realm) - shutil.copy(ca_db.cacert_fname, "/usr/share/ipa/html/ca.crt") - os.chmod("/usr/share/ipa/html/ca.crt", 0444) + ca_db = certs.CertDB(self.realm) + ca_db.publish_ca_cert("/usr/share/ipa/html/ca.crt") def uninstall(self): if self.is_configured(): @@ -255,7 +251,7 @@ class HTTPInstance(service.Service): if not running is None: self.stop() - db = certs.CertDB(NSS_DIR, api.env.realm) + db = certs.CertDB(api.env.realm) db.untrack_server_cert("Server-Cert") if not enabled is None and not enabled: self.chkconfig_off() diff --git a/ipaserver/install/krbinstance.py b/ipaserver/install/krbinstance.py index 516c7eac5..247b39009 100644 --- a/ipaserver/install/krbinstance.py +++ b/ipaserver/install/krbinstance.py @@ -45,7 +45,6 @@ import pyasn1.codec.ber.decoder import struct import certs -import httpinstance from distutils import version KRBMKEY_DENY_ACI = '(targetattr = "krbMKey")(version 3.0; acl "No external access"; deny (read,write,search,compare) userdn != "ldap:///uid=kdc,cn=sysaccounts,cn=etc,$SUFFIX";)' @@ -544,11 +543,10 @@ class KrbInstance(service.Service): def __setup_pkinit(self): if self.self_signed_ca: - ca_db = certs.CertDB(httpinstance.NSS_DIR, self.realm, + ca_db = certs.CertDB(self.realm, subject_base=self.subject_base) else: - ca_db = certs.CertDB(httpinstance.NSS_DIR, self.realm, - host_name=self.fqdn, + ca_db = certs.CertDB(self.realm, host_name=self.fqdn, subject_base=self.subject_base) if self.pkcs12_info: @@ -564,8 +562,7 @@ class KrbInstance(service.Service): # Finally copy the cacert in the krb directory so we don't # have any selinux issues with the file context - shutil.copyfile("/usr/share/ipa/html/ca.crt", - "/var/kerberos/krb5kdc/cacert.pem") + shutil.copyfile("/etc/ipa/ca.crt", "/var/kerberos/krb5kdc/cacert.pem") def __add_anonymous_pkinit_principal(self): princ = "WELLKNOWN/ANONYMOUS" -- cgit