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
This commit is contained in:
Simo Sorce 2010-12-08 16:35:12 -05:00
parent 2efc08a6fc
commit bfaea1dd78
9 changed files with 62 additions and 62 deletions

View File

@ -158,7 +158,7 @@ def install_ca(config):
cs = cainstance.CADSInstance() cs = cainstance.CADSInstance()
cs.create_instance(config.ds_user, config.realm_name, config.host_name, config.domain_name, config.dirman_password) 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) 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 return ca

View File

@ -27,7 +27,7 @@ import krbV
from optparse import OptionParser from optparse import OptionParser
from ipapython import ipautil 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.install.bindinstance import add_zone, add_reverze_zone, add_rr, add_ptr_rr
from ipaserver.plugins.ldap2 import ldap2 from ipaserver.plugins.ldap2 import ldap2
from ipapython import version from ipapython import version
@ -123,14 +123,9 @@ def export_certdb(realm_name, ds_dir, dir, passwd_fname, fname, hostname, subjec
try: try:
self_signed = certs.ipa_self_signed() 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() db.create_passwd_file()
# if self_signed: ca_db = certs.CertDB(realm_name, host_name=api.env.host, subject_base=subject_base)
# 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)
if is_kdc: if is_kdc:
ca_db.create_kdc_cert("KDC-Cert", hostname, dir) ca_db.create_kdc_cert("KDC-Cert", hostname, dir)
else: else:
@ -177,7 +172,7 @@ def export_ra_pkcs12(dir, dm_password):
try: try:
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"): if db.has_nickname("ipaCert"):
pkcs12_fname = "%s/ra.p12" % dir pkcs12_fname = "%s/ra.p12" % dir

View File

@ -89,7 +89,7 @@ def choose_server_cert(server_certs):
return server_certs[num - 1] return server_certs[num - 1]
def import_cert(dirname, pkcs12_fname, pkcs12_passwd, db_password): 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_passwd_file(db_password)
cdb.create_certdbs() cdb.create_certdbs()
[pw_fd, pw_name] = tempfile.mkstemp() [pw_fd, pw_name] = tempfile.mkstemp()

View File

@ -420,8 +420,8 @@ def uninstall():
ntpinstance.NTPInstance(fstore).uninstall() ntpinstance.NTPInstance(fstore).uninstall()
if cainstance.CADSInstance().is_configured(): if cainstance.CADSInstance().is_configured():
cainstance.CADSInstance().uninstall() cainstance.CADSInstance().uninstall()
if cainstance.CAInstance(api.env.realm).is_configured(): if cainstance.CAInstance(api.env.realm, certs.NSS_DIR).is_configured():
cainstance.CAInstance(api.env.realm).uninstall() cainstance.CAInstance(api.env.realm, certs.NSS_DIR).uninstall()
bindinstance.BindInstance(fstore).uninstall() bindinstance.BindInstance(fstore).uninstall()
httpinstance.HTTPInstance(fstore).uninstall() httpinstance.HTTPInstance(fstore).uninstall()
krbinstance.KrbInstance(fstore).uninstall() krbinstance.KrbInstance(fstore).uninstall()
@ -693,7 +693,12 @@ def main():
ntp = ntpinstance.NTPInstance(fstore) ntp = ntpinstance.NTPInstance(fstore)
ntp.create_instance() 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 # Clean up any previous self-signed CA that may exist
try: try:
os.remove(certs.CA_SERIALNO) os.remove(certs.CA_SERIALNO)
@ -720,7 +725,7 @@ def main():
if options.external_cert_file is None: if options.external_cert_file is None:
cs = cainstance.CADSInstance() cs = cainstance.CADSInstance()
cs.create_instance("pkisrv", realm_name, host_name, domain_name, dm_password) 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: if external == 0:
ca.configure_instance("pkiuser", host_name, dm_password, dm_password, subject_base=options.subject) ca.configure_instance("pkiuser", host_name, dm_password, dm_password, subject_base=options.subject)
elif external == 1: elif external == 1:

View File

@ -341,8 +341,8 @@ class CADSInstance(service.Service):
class CAInstance(service.Service): class CAInstance(service.Service):
""" """
In the self-signed case (all done in certs.py) the CA exists in the DS In the self-signed case the CA exists in the NSS_DB database.
database. When using a dogtag CA the DS database contains just the When using a dogtag CA the DS database contains just the
server cert for DS. The mod_nss database will contain the RA agent server cert for DS. The mod_nss database will contain the RA agent
cert that will be used to do authenticated requests against dogtag. 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 2 = have signed cert, continue installation
""" """
def __init__(self, realm): def __init__(self, realm, ra_db):
service.Service.__init__(self, "pki-cad") service.Service.__init__(self, "pki-cad")
self.realm = realm self.realm = realm
self.pki_user = "pkiuser" self.pki_user = "pkiuser"
@ -378,7 +378,7 @@ class CAInstance(service.Service):
self.canickname = get_ca_nickname(realm) self.canickname = get_ca_nickname(realm)
self.basedn = "o=ipaca" self.basedn = "o=ipaca"
self.ca_agent_db = tempfile.mkdtemp(prefix = "tmp-") 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.ra_agent_pwd = self.ra_agent_db + "/pwdfile.txt"
self.ds_port = DEFAULT_DSPORT self.ds_port = DEFAULT_DSPORT
self.domain_name = "IPA" self.domain_name = "IPA"
@ -1000,5 +1000,5 @@ if __name__ == "__main__":
installutils.standard_logging_setup("install.log", False) installutils.standard_logging_setup("install.log", False)
cs = CADSInstance() cs = CADSInstance()
cs.create_instance("dirsrv", "EXAMPLE.COM", "catest.example.com", "example.com", "password") 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") ca.configure_instance("pkiuser", "catest.example.com", "password", "password")

View File

@ -47,6 +47,10 @@ from ipalib import api
from ipalib.compat import sha1 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" CA_SERIALNO="/var/lib/ipa/ca_serialno"
def ipa_self_signed(): def ipa_self_signed():
@ -163,7 +167,7 @@ def next_replica(serial_file=CA_SERIALNO):
return str(serial) return str(serial)
class CertDB(object): 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.secdir = nssdir
self.realm = realm self.realm = realm
@ -1040,3 +1044,7 @@ class CertDB(object):
self.fstore.backup_file(self.pin_fname) self.fstore.backup_file(self.pin_fname)
self.fstore.backup_file(self.certreq_fname) self.fstore.backup_file(self.certreq_fname)
self.fstore.backup_file(self.certder_fname) self.fstore.backup_file(self.certder_fname)
def publish_ca_cert(self, location):
shutil.copy(self.cacert_fname, location)
os.chmod(location, 0444)

View File

@ -469,7 +469,7 @@ class DsInstance(service.Service):
def __enable_ssl(self): def __enable_ssl(self):
dirname = config_dirname(self.serverid) 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: if self.pkcs12_info:
dsdb.create_from_pkcs12(self.pkcs12_info[0], self.pkcs12_info[1]) dsdb.create_from_pkcs12(self.pkcs12_info[0], self.pkcs12_info[1])
server_certs = dsdb.find_server_certs() server_certs = dsdb.find_server_certs()
@ -481,9 +481,8 @@ class DsInstance(service.Service):
self.dercert = dsdb.get_cert_from_db(nickname) self.dercert = dsdb.get_cert_from_db(nickname)
else: else:
nickname = "Server-Cert" 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: if self.self_signed_ca:
cadb.create_self_signed()
dsdb.create_from_cacert(cadb.cacert_fname, passwd=None) dsdb.create_from_cacert(cadb.cacert_fname, passwd=None)
self.dercert = dsdb.create_server_cert("Server-Cert", self.fqdn, cadb) self.dercert = dsdb.create_server_cert("Server-Cert", self.fqdn, cadb)
dsdb.track_server_cert("Server-Cert", self.principal, dsdb.passwd_fname) 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 # drop the trailing / off the config_dirname so the directory
# will match what is in certmonger # will match what is in certmonger
dirname = config_dirname(serverid)[:-1] 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") dsdb.untrack_server_cert("Server-Cert")
erase_ds_instance_data(serverid) erase_ds_instance_data(serverid)
@ -643,7 +642,7 @@ class DsInstance(service.Service):
self.stop() self.stop()
dirname = config_dirname(realm_to_serverid(self.realm_name)) 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: if not cacert_name or len(cacert_name) == 0:
cacert_name = "Imported CA" cacert_name = "Imported CA"
# we can't pass in the nickname, so we set the instance variable # we can't pass in the nickname, so we set the instance variable

View File

@ -35,7 +35,6 @@ from ipalib import util, api
HTTPD_DIR = "/etc/httpd" HTTPD_DIR = "/etc/httpd"
SSL_CONF = HTTPD_DIR + "/conf.d/ssl.conf" SSL_CONF = HTTPD_DIR + "/conf.d/ssl.conf"
NSS_CONF = HTTPD_DIR + "/conf.d/nss.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. 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 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 print "Adding Include conf.d/ipa-rewrite to %s failed." % NSS_CONF
def __setup_ssl(self): def __setup_ssl(self):
if self.self_signed_ca: fqdn = None
ca_db = certs.CertDB(NSS_DIR, self.realm, subject_base=self.subject_base) if not self.self_signed_ca:
else: fqdn = self.fqdn
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) 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: if self.pkcs12_info:
db.create_from_pkcs12(self.pkcs12_info[0], self.pkcs12_info[1], passwd="") db.create_from_pkcs12(self.pkcs12_info[0], self.pkcs12_info[1], passwd="")
server_certs = db.find_server_certs() server_certs = db.find_server_certs()
@ -186,31 +187,27 @@ class HTTPInstance(service.Service):
else: else:
if self.self_signed_ca: if self.self_signed_ca:
db.create_from_cacert(ca_db.cacert_fname) 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.create_password_conf()
db.track_server_cert("Server-Cert", self.principal, db.passwd_fname) self.dercert = db.create_server_cert("Server-Cert", self.fqdn, ca_db)
db.create_signing_cert("Signing-Cert", "Object Signing Cert", ca_db) db.track_server_cert("Server-Cert", self.principal, db.passwd_fname)
else: db.create_signing_cert("Signing-Cert", "Object Signing Cert", ca_db)
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()
# Fix the database permissions # Fix the database permissions
os.chmod(NSS_DIR + "/cert8.db", 0660) os.chmod(certs.NSS_DIR + "/cert8.db", 0660)
os.chmod(NSS_DIR + "/key3.db", 0660) os.chmod(certs.NSS_DIR + "/key3.db", 0660)
os.chmod(NSS_DIR + "/secmod.db", 0660) os.chmod(certs.NSS_DIR + "/secmod.db", 0660)
os.chmod(NSS_DIR + "/pwdfile.txt", 0660) os.chmod(certs.NSS_DIR + "/pwdfile.txt", 0660)
pent = pwd.getpwnam("apache") pent = pwd.getpwnam("apache")
os.chown(NSS_DIR + "/cert8.db", 0, pent.pw_gid ) os.chown(certs.NSS_DIR + "/cert8.db", 0, pent.pw_gid )
os.chown(NSS_DIR + "/key3.db", 0, pent.pw_gid ) os.chown(certs.NSS_DIR + "/key3.db", 0, pent.pw_gid )
os.chown(NSS_DIR + "/secmod.db", 0, pent.pw_gid ) os.chown(certs.NSS_DIR + "/secmod.db", 0, pent.pw_gid )
os.chown(NSS_DIR + "/pwdfile.txt", 0, pent.pw_gid ) os.chown(certs.NSS_DIR + "/pwdfile.txt", 0, pent.pw_gid )
# Fix SELinux permissions on the database # Fix SELinux permissions on the database
ipautil.run(["/sbin/restorecon", NSS_DIR + "/cert8.db"]) ipautil.run(["/sbin/restorecon", certs.NSS_DIR + "/cert8.db"])
ipautil.run(["/sbin/restorecon", NSS_DIR + "/key3.db"]) ipautil.run(["/sbin/restorecon", certs.NSS_DIR + "/key3.db"])
# In case this got generated as part of the install, reset the # In case this got generated as part of the install, reset the
# context # context
@ -226,7 +223,7 @@ class HTTPInstance(service.Service):
prefs_fd.close() prefs_fd.close()
# The signing cert is generated in __setup_ssl # 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) pwdfile = open(db.passwd_fname)
pwd = pwdfile.read() pwd = pwdfile.read()
@ -241,9 +238,8 @@ class HTTPInstance(service.Service):
shutil.rmtree(tmpdir) shutil.rmtree(tmpdir)
def __publish_ca_cert(self): def __publish_ca_cert(self):
ca_db = certs.CertDB(NSS_DIR, self.realm) ca_db = certs.CertDB(self.realm)
shutil.copy(ca_db.cacert_fname, "/usr/share/ipa/html/ca.crt") ca_db.publish_ca_cert("/usr/share/ipa/html/ca.crt")
os.chmod("/usr/share/ipa/html/ca.crt", 0444)
def uninstall(self): def uninstall(self):
if self.is_configured(): if self.is_configured():
@ -255,7 +251,7 @@ class HTTPInstance(service.Service):
if not running is None: if not running is None:
self.stop() self.stop()
db = certs.CertDB(NSS_DIR, api.env.realm) db = certs.CertDB(api.env.realm)
db.untrack_server_cert("Server-Cert") db.untrack_server_cert("Server-Cert")
if not enabled is None and not enabled: if not enabled is None and not enabled:
self.chkconfig_off() self.chkconfig_off()

View File

@ -45,7 +45,6 @@ import pyasn1.codec.ber.decoder
import struct import struct
import certs import certs
import httpinstance
from distutils import version 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";)' 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): def __setup_pkinit(self):
if self.self_signed_ca: 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) subject_base=self.subject_base)
else: else:
ca_db = certs.CertDB(httpinstance.NSS_DIR, self.realm, ca_db = certs.CertDB(self.realm, host_name=self.fqdn,
host_name=self.fqdn,
subject_base=self.subject_base) subject_base=self.subject_base)
if self.pkcs12_info: if self.pkcs12_info:
@ -564,8 +562,7 @@ class KrbInstance(service.Service):
# Finally copy the cacert in the krb directory so we don't # Finally copy the cacert in the krb directory so we don't
# have any selinux issues with the file context # have any selinux issues with the file context
shutil.copyfile("/usr/share/ipa/html/ca.crt", shutil.copyfile("/etc/ipa/ca.crt", "/var/kerberos/krb5kdc/cacert.pem")
"/var/kerberos/krb5kdc/cacert.pem")
def __add_anonymous_pkinit_principal(self): def __add_anonymous_pkinit_principal(self):
princ = "WELLKNOWN/ANONYMOUS" princ = "WELLKNOWN/ANONYMOUS"