Allow replicas of an IPA server using an internal dogtag server as the CA

This involves creating a new CA instance on the replica and using pkisilent
to create a clone of the master CA.

Also generally fixes IPA to work with the latest dogtag SVN tip. A lot of
changes to ports and configuration have been done recently.
This commit is contained in:
Rob Crittenden
2009-07-10 16:18:16 -04:00
parent 904e555404
commit 8d164569d0
9 changed files with 299 additions and 116 deletions

View File

@@ -101,6 +101,25 @@ def set_owner(config, dir):
pw = pwd.getpwnam(config.ds_user)
os.chown(dir, pw.pw_uid, pw.pw_gid)
def install_ca(config):
cafile = config.dir + "/ca.p12"
if not ipautil.file_exists(cafile):
return None
try:
from ipaserver.install import cainstance
except ImportError:
print >> sys.stderr, "Import failed: %s" % sys.exc_value
sys.exit(1)
cs = cainstance.CADSInstance()
cs.create_instance(config.ds_user, config.realm_name, config.host_name, config.domain_name, config.dirman_password)
ca = cainstance.CAInstance()
ca.configure_instance("pkiuser", config.host_name, config.dirman_password, config.dirman_password, pkcs12_info=(cafile,), master_host=config.master_host_name)
return ca
def install_ds(config):
dsinstance.check_existing_installation()
dsinstance.check_ports()
@@ -237,17 +256,20 @@ def main():
except ldap.INVALID_CREDENTIALS, e :
sys.exit("\nThe password provided is incorrect for LDAP server %s" % config.master_host_name)
# Install CA cert so that we can do SSL connections with ldap
install_ca_cert(config)
# Configure ntpd
if options.conf_ntp:
ntp = ntpinstance.NTPInstance()
ntp.create_instance()
# Configure the CA if necessary
CA = install_ca(config)
# Configure dirsrv
ds = install_ds(config)
# Install CA cert so that we can do SSL connections with ldap
install_ca_cert(config)
try:
repl = replication.ReplicationManager(config.host_name, config.dirman_password)
ret = repl.setup_replication(config.master_host_name, config.realm_name)
@@ -259,6 +281,10 @@ def main():
install_krb(config)
install_http(config)
if CA:
CA.import_ra_cert(dir + "/ra.p12")
CA.fix_ra_perms()
service.restart("httpd")
# Create the config file
fd = open("/etc/ipa/ipa.conf", "w")
@@ -275,8 +301,7 @@ def main():
fd.write("realm=" + config.realm_name + "\n")
fd.write("domain=" + config.domain_name + "\n")
fd.write("xmlrpc_uri=https://%s/ipa/xml\n" % config.host_name)
# FIXME: detect when we are installing a cloned CA
if False:
if ipautil.file_exists(config.dir + "/ca.p12"):
fd.write("enable_ra=True\n")
fd.close()

View File

@@ -28,7 +28,7 @@ from optparse import OptionParser
import ipapython.config
from ipapython import ipautil
from ipaserver.install import dsinstance, installutils, certs
from ipaserver.install import dsinstance, installutils, certs, httpinstance
from ipaserver import ipaldap
from ipapython import version
import ldap
@@ -98,28 +98,37 @@ def check_ipa_configuration(realm_name):
logging.error("could not find directory instance: %s" % config_dir)
sys.exit(1)
def export_certdb(realm_name, ds_dir, dir, passwd_fname, fname, subject):
def export_certdb(realm_name, ds_dir, dir, passwd_fname, fname, hostname):
"""realm is the kerberos realm for the IPA server.
ds_dir is the location of the master DS we are creating a replica for.
dir is the location of the files for the replica we are creating.
passwd_fname is the file containing the PKCS#12 password
fname is the filename of the PKCS#12 file for this cert (minus the .p12).
subject is the subject of the certificate we are creating
hostname is the FQDN of the server we're creating a cert for.
The subject is handled by certs.CertDB:create_server_cert()
"""
try:
ds_ca = certs.CertDB(dsinstance.config_dirname(dsinstance.realm_to_serverid(realm_name)))
ca = certs.CertDB(dir)
ca.create_from_cacert(ds_ca.cacert_fname)
ca.create_server_cert("Server-Cert", subject, ds_ca)
self_signed = certs.ipa_self_signed()
db = certs.CertDB(dir)
db.create_passwd_file()
db.create_certdbs()
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=get_host_name())
db.create_server_cert("Server-Cert", hostname, ca_db)
except Exception, e:
raise e
pkcs12_fname = dir + "/" + fname + ".p12"
try:
ca.export_pkcs12(pkcs12_fname, passwd_fname, "Server-Cert")
db.export_pkcs12(pkcs12_fname, passwd_fname, "Server-Cert")
except ipautil.CalledProcessError, e:
print "error exporting CA certificate: " + str(e)
print "error exporting Server certificate: " + str(e)
remove_file(pkcs12_fname)
remove_file(passwd_fname)
@@ -130,6 +139,32 @@ def export_certdb(realm_name, ds_dir, dir, passwd_fname, fname, subject):
if ipautil.file_exists(passwd_fname + ".orig"):
remove_file(passwd_fname + ".orig")
def export_ra_pkcs12(dir, dm_password):
"""
dir is the location of the files for the replica we are creating.
dm_password is the Directory Manager password
If this install is using dogtag/RHCS then export the RA certificate.
"""
if certs.ipa_self_signed():
return
(agent_fd, agent_name) = tempfile.mkstemp()
os.write(agent_fd, dm_password)
os.close(agent_fd)
try:
try:
db = certs.CertDB(httpinstance.NSS_DIR, host_name=get_host_name())
if db.has_nickname("ipaCert"):
pkcs12_fname = "%s/ra.p12" % dir
db.export_pkcs12(pkcs12_fname, agent_name, "ipaCert")
except Exception, e:
raise e
finally:
os.remove(agent_name)
def get_ds_user(ds_dir):
uid = os.stat(ds_dir).st_uid
user = pwd.getpwuid(uid)[0]
@@ -176,7 +211,8 @@ def main():
replica_fqdn = args[0]
if not ipautil.file_exists(certs.CA_SERIALNO) and not options.dirsrv_pin:
# FIXME: need more robust way to determine if dogtag is configured
if not certs.ipa_self_signed() and not ipautil.file_exists("/var/lib/pki-ca") and not options.dirsrv_pin:
sys.exit("The replica must be created on the primary IPA server.\nIf you installed IPA with your own certificates using PKCS#12 files you must provide PKCS#12 files for any replicas you create as well.")
print "Determining current realm name"
@@ -244,8 +280,18 @@ def main():
print "Copy failed %s" % e
sys.exit(1)
else:
try:
if not certs.ipa_self_signed():
# FIXME, need option for location of CA backup
if ipautil.file_exists("/root/tmp-ca.p12"):
shutil.copy("/root/tmp-ca.p12", dir + "/ca.p12")
else:
raise RuntimeError("Root CA PKCS#12 not found in /root/tmp-ca.p12")
except IOError, e:
print "Copy failed %s" % e
sys.exit(1)
print "Creating SSL certificate for the Directory Server"
export_certdb(realm_name, ds_dir, dir, passwd_fname, "dscert", "cn=%s,ou=Fedora Directory Server" % replica_fqdn)
export_certdb(realm_name, ds_dir, dir, passwd_fname, "dscert", replica_fqdn)
if options.http_pin:
passwd = options.http_pin
@@ -266,7 +312,9 @@ def main():
sys.exit(1)
else:
print "Creating SSL certificate for the Web Server"
export_certdb(realm_name, ds_dir, dir, passwd_fname, "httpcert", "cn=%s,ou=Apache Web Server" % replica_fqdn)
export_certdb(realm_name, ds_dir, dir, passwd_fname, "httpcert", replica_fqdn)
print "Exporting RA certificate"
export_ra_pkcs12(dir, dirman_password)
print "Copying additional files"
copy_files(realm_name, dir)
print "Finalizing configuration"

View File

@@ -521,7 +521,7 @@ def main():
pass
cs = cainstance.CADSInstance()
cs.create_instance("dirsrv", realm_name, host_name, domain_name, dm_password)
cs.create_instance(ds_user, realm_name, host_name, domain_name, dm_password)
ca = cainstance.CAInstance()
ca.configure_instance("pkiuser", host_name, dm_password, dm_password)

View File

@@ -114,7 +114,7 @@ DEFAULT_CONFIG = (
# CA plugin:
('ca_host', object), # Set in Env._finalize_core()
('ca_port', 9180),
('ca_ssl_port', 9444),
('ca_ssl_port', 9443),
# Special CLI:
('prompt_all', False),

View File

@@ -21,12 +21,14 @@ from ipalib import api, errors
import httplib
import xml.dom.minidom
def get_ca_certchain():
def get_ca_certchain(ca_host=None):
"""
Retrieve the CA Certificate chain from the configured Dogtag server.
"""
if ca_host is None:
ca_host = api.env.ca_host
chain = None
conn = httplib.HTTPConnection(api.env.ca_host, 9180)
conn = httplib.HTTPConnection(ca_host, 9180)
conn.request("GET", "/ca/ee/ca/getCertChain")
res = conn.getresponse()
if res.status == 200:
@@ -42,8 +44,8 @@ def get_ca_certchain():
item_node = doc.getElementsByTagName("Error")
reason = item_node[0].childNodes[0].data
raise errors.RemoteRetrieveError(reason=reason)
except:
raise errors.RemoteRetrieveError(reason="Retrieving CA cert chain failed")
except Exception, e:
raise errors.RemoteRetrieveError(reason="Retrieving CA cert chain failed: %s" % str(e))
finally:
doc.unlink()

View File

@@ -51,6 +51,14 @@ from ipalib import util
DEFAULT_DSPORT=7389
# These values come from /usr/share/pki/ca/setup/postinstall
PKI_INSTANCE_NAME="pki-ca"
AGENT_SECURE_PORT=9443
EE_SECURE_PORT=9444
ADMIN_SECURE_PORT=9445
UNSECURE_PORT=9180
TOMCAT_SERVER_PORT=9701
# We need to reset the template because the CA uses the regular boot
# information
INF_TEMPLATE = """
@@ -88,13 +96,12 @@ def get_preop_pin(instance_root, instance_name):
return preop_pin
def export_pkcs12(output_file, output_passwd, nickname, cert_database,
def import_pkcs12(input_file, input_passwd, cert_database,
cert_passwd):
ipautil.run(["/usr/bin/pk12util", "-d", cert_database,
"-o", output_file,
"-n", nickname,
"-i", input_file,
"-k", cert_passwd,
"-w", output_passwd])
"-w", input_passwd])
def client_auth_data_callback(ca_names, chosen_nickname, password, certdb):
cert = None
@@ -147,7 +154,7 @@ def get_defList(data):
"""
Return a dictionary of defList name/value pairs.
A certificate signing request is specfied as a series of these.
A certificate signing request is specified as a series of these.
"""
varname = None
value = None
@@ -215,6 +222,7 @@ class CADSInstance(service.Service):
self.pkcs12_info = None
self.ds_user = None
self.ds_port = None
self.master_host = None
if realm_name:
self.suffix = util.realm_to_suffix(self.realm_name)
self.__setup_sub_dict()
@@ -351,10 +359,13 @@ class CAInstance(service.Service):
def __init__(self):
service.Service.__init__(self, "pki-ca")
self.pki_user = None
self.pki_user = "pkiuser"
self.dm_password = None
self.admin_password = None
self.host_name = None
self.pkcs12_info = None
self.clone = False
self.external = False
# The same database is used for mod_nss because the NSS context
# will already have been initialized by Apache by the time
@@ -367,31 +378,36 @@ class CAInstance(service.Service):
self.ds_port = DEFAULT_DSPORT
self.domain_name = "IPA"
self.server_root = "/var/lib"
self.secure_port = 9444
self.ra_cert = None
self.requestId = None
def __del__(self):
shutil.rmtree(self.ca_agent_db, ignore_errors=True)
def configure_instance(self, pki_user, host_name, dm_password, admin_password, ds_port=DEFAULT_DSPORT):
def configure_instance(self, pki_user, host_name, dm_password, admin_password, ds_port=DEFAULT_DSPORT, pkcs12_info=None, master_host=None):
self.pki_user = pki_user
self.host_name = host_name
self.dm_password = dm_password
self.admin_password = admin_password
self.ds_port = ds_port
self.pkcs12_info = pkcs12_info
if self.pkcs12_info is not None:
self.clone = True
self.master_host = master_host
if not ipautil.dir_exists("/var/lib/pki-ca"):
self.step("creating pki-ca instance", self.create_instance)
self.step("creating certificate server user", self.__create_ca_user)
self.step("configuring certificate server instance", self.__configure_instance)
self.step("creating CA agent PKCS#12 file in /root", self.__create_ca_agent_pkcs12)
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)
self.step("importing CA chain to RA certificate database", self.__import_ca_chain)
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)
self.step("fixing RA database permissions", self.__fix_ra_perms)
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)
self.step("adding RA agent as a trusted user", self.__configure_ra)
self.step("fixing RA database permissions", self.fix_ra_perms)
self.step("setting up signing cert profile", self.__setup_sign_profile)
self.step("configuring certificate server to start on boot", self.__enable)
self.step("restarting certificate server", self.__restart_instance)
@@ -401,30 +417,35 @@ class CAInstance(service.Service):
def create_instance(self):
"""
If for some reason the instance doesn't exist, create a new one."
These values come from /usr/share/pki/ca/setup/postinstall
"""
PKI_INSTANCE_NAME="pki-ca"
AGENT_SECURE_PORT="9443"
EE_SECURE_PORT="9444"
ADMIN_SECURE_PORT="9445"
UNSECURE_PORT="9180"
TOMCAT_SERVER_PORT="9701"
args = ['/usr/bin/pkicreate',
'-pki_instance_root', '/var/lib',
'-pki_instance_name', PKI_INSTANCE_NAME,
'-subsystem_type', 'ca',
'-agent_secure_port', AGENT_SECURE_PORT,
'-ee_secure_port', EE_SECURE_PORT,
'-admin_secure_port', ADMIN_SECURE_PORT,
'-unsecure_port', UNSECURE_PORT,
'-tomcat_server_port', TOMCAT_SERVER_PORT,
'-agent_secure_port', str(AGENT_SECURE_PORT),
'-ee_secure_port', str(EE_SECURE_PORT),
'-admin_secure_port', str(ADMIN_SECURE_PORT),
'-unsecure_port', str(UNSECURE_PORT),
'-tomcat_server_port', str(TOMCAT_SERVER_PORT),
'-redirect', 'conf=/etc/pki-ca',
'-redirect', 'logs=/var/log/pki-ca',
]
ipautil.run(args)
# Turn off Nonces
if installutils.update_file('/var/lib/pki-ca/conf/CS.cfg', 'ca.enableNonces=true', 'ca.enableNonces=false') != 0:
raise RuntimeError("Disabling nonces failed")
pent = pwd.getpwnam(self.pki_user)
os.chown('/var/lib/pki-ca/conf/CS.cfg', pent.pw_uid, pent.pw_gid )
logging.debug("restarting ca instance")
try:
self.restart()
logging.debug("done restarting ca instance")
except ipautil.CalledProcessError, e:
print "failed to restart ca instance", e
def __enable(self):
self.backup_state("enabled", self.is_enabled())
self.chkconfig_on()
@@ -455,7 +476,7 @@ class CAInstance(service.Service):
try:
args = ["/usr/bin/perl", "/usr/bin/pkisilent", "ConfigureCA",
"-cs_hostname", self.host_name,
"-cs_port", str(self.secure_port),
"-cs_port", str(ADMIN_SECURE_PORT),
"-client_certdb_dir", self.ca_agent_db,
"-client_certdb_pwd", self.admin_password,
"-preop_pin" , preop_pin,
@@ -484,10 +505,9 @@ class CAInstance(service.Service):
"-ca_server_cert_subject_name", "CN=" + self.host_name + ",O=" + self.domain_name,
"-ca_audit_signing_cert_subject_name", "\"CN=CA Audit Signing Certificate,O=" + self.domain_name + "\"",
"-ca_sign_cert_subject_name", "\"CN=Certificate Authority,O=" + self.domain_name + "\"" ]
# if (options.external):
# pass
# args.append("-external")
# args.append("true")
if (self.external):
args.append("-external")
args.append("true")
# args.append("-ext_csr_file")
# args.append(ext_csr_file)
# if (options.cacertfile):
@@ -496,39 +516,51 @@ class CAInstance(service.Service):
# if (options.cacertchainfile):
# args.append("-ext_ca_cert_chain_file")
# args.append(options.cacertchainfile)
# else:
# args.append("-external")
# args.append("false")
# if (options.clone):
# pass
# args.append("-clone")
# args.append("true")
# args.append("-clone_p12_file")
# args.append(options.clonefile)
# args.append("-clone_p12_password")
# args.append(options.clonepasswd)
# args.append("-clone_uri")
# args.append(options.cloneURI)
# args.append("-sd_hostname")
# args.append(options.sd_hostname)
# args.append("-sd_ssl_port")
# args.append(options.sd_ssl_port)
# args.append("-sd_admin_name")
# args.append(options.sd_admin_name)
# args.append("-sd_admin_password")
# args.append(options.sd_admin_password)
# else:
# args.append("-clone")
# args.append("false")
# FIXME
args.append("-external")
args.append("false")
args.append("-clone")
args.append("false")
else:
args.append("-external")
args.append("false")
if (self.clone):
"""sd = security domain --> all CS systems get registered to
a security domain. This is set to the hostname and port of
the master CA.
"""
# The install wizard expects the file to be here.
cafile = self.pkcs12_info[0]
shutil.copy(cafile, "/var/lib/pki-ca/alias/ca.p12")
pent = pwd.getpwnam(self.pki_user)
os.chown("/var/lib/pki-ca/alias/ca.p12", pent.pw_uid, pent.pw_gid )
args.append("-clone")
args.append("true")
args.append("-clone_p12_file")
args.append("ca.p12")
args.append("-clone_p12_password")
args.append(self.dm_password)
args.append("-sd_hostname")
args.append(self.master_host)
args.append("-sd_admin_port")
args.append(str(ADMIN_SECURE_PORT))
args.append("-sd_admin_name")
args.append("admin")
args.append("-sd_admin_password")
args.append(self.admin_password)
else:
args.append("-clone")
args.append("false")
logging.debug(args)
ipautil.run(args)
# pkisilent doesn't return 1 on error so look at the output of
# /sbin/service pki-ca status. It will tell us if the instance
# still needs to be configured.
(stdout, stderr) = ipautil.run(["/sbin/service", "pki-ca", "status"])
try:
stdout.index("CONFIGURED!")
raise RuntimeError("pkisilent failed to configure instance.")
except ValueError:
# This is raised because the string doesn't exist, we're done
pass
logging.debug("completed creating ca instance")
except ipautil.CalledProcessError, e:
logging.critical("failed to restart ca instance %s" % e)
@@ -581,7 +613,7 @@ class CAInstance(service.Service):
'-p', self.admin_password,
'-d', self.ca_agent_db,
'-r', '/ca/agent/ca/profileReview?requestId=%s' % self.requestId,
'%s:%d' % (self.host_name, 9443),
'%s:%d' % (self.host_name, AGENT_SECURE_PORT),
]
logging.debug("running sslget %s" % args)
(stdout, stderr) = ipautil.run(args)
@@ -604,7 +636,7 @@ class CAInstance(service.Service):
'-d', self.ca_agent_db,
'-e', params,
'-r', '/ca/agent/ca/profileProcess',
'%s:%d' % (self.host_name, 9443),
'%s:%d' % (self.host_name, AGENT_SECURE_PORT),
]
logging.debug("running sslget %s" % args)
(stdout, stderr) = ipautil.run(args)
@@ -629,6 +661,22 @@ class CAInstance(service.Service):
finally:
os.remove(agent_name)
def import_ra_cert(self, rafile):
"""
Cloned RAs will use the same RA agent cert as the master so we
need to import from a PKCS#12 file.
Used when setting up replication
"""
# Add the new RA cert to the database in /etc/httpd/alias
(agent_fd, agent_name) = tempfile.mkstemp()
os.write(agent_fd, self.dm_password)
os.close(agent_fd)
try:
import_pkcs12(rafile, agent_name, self.ra_agent_db, self.ra_agent_pwd)
finally:
os.remove(agent_name)
def __configure_ra(self):
# Create an RA user in the CA LDAP server and add that user to
# the appropriate groups so it can issue certificates without
@@ -692,9 +740,9 @@ class CAInstance(service.Service):
def __get_ca_chain(self):
try:
return dogtag.get_ca_certchain()
except:
raise RuntimeError("Unable to retrieve CA chain")
return dogtag.get_ca_certchain(ca_host=self.host_name)
except Exception, e:
raise RuntimeError("Unable to retrieve CA chain: %s" % str(e))
def __create_ca_agent_pkcs12(self):
(pwd_fd, pwd_name) = tempfile.mkstemp()
@@ -766,7 +814,7 @@ class CAInstance(service.Service):
conn.close()
raise RuntimeError("Unable to submit RA cert request")
def __fix_ra_perms(self):
def fix_ra_perms(self):
os.chmod(self.ra_agent_db + "/cert8.db", 0640)
os.chmod(self.ra_agent_db + "/key3.db", 0640)
os.chmod(self.ra_agent_db + "/secmod.db", 0640)
@@ -775,23 +823,13 @@ class CAInstance(service.Service):
os.chown(self.ra_agent_db + "/cert8.db", 0, pent.pw_gid )
os.chown(self.ra_agent_db + "/key3.db", 0, pent.pw_gid )
os.chown(self.ra_agent_db + "/secmod.db", 0, pent.pw_gid )
os.chown(self.ra_agent_pwd, 0, pent.pw_gid)
os.chown(self.ra_agent_pwd, pent.pw_uid, pent.pw_gid)
def __setup_sign_profile(self):
caconfig = "/var/lib/pki-ca/conf/CS.cfg"
if not ipautil.file_exists('/var/lib/pki-ca/profiles/ca/caJarSigningCert.cfg'):
profile = ipautil.template_file(ipautil.SHARE_DIR + "caJarSigningCert.cfg.template", {})
fd = open("/var/lib/pki-ca/profiles/ca/caJarSigningCert.cfg", "w")
fd.write(profile)
fd.close()
profilelist = installutils.get_directive(caconfig, "profile.list", separator="=")
if profilelist.find('caJarSigningCert') < 0:
profilelist = profilelist + ',caJarSigningCert'
installutils.set_directive(caconfig, 'profile.list', profilelist, quotes=False, separator='=')
installutils.set_directive(caconfig, 'profile.caJarSigningCert.class_id', 'caEnrollImpl', quotes=False, separator='=')
installutils.set_directive(caconfig, 'profile.caJarSigningCert.config', '/var/lib/pki-ca/profiles/ca/caJarSigningCert.cfg', quotes=False, separator='=')
# Tell the profile to automatically issue certs for RAs
installutils.set_directive('/var/lib/pki-ca/profiles/ca/caJarSigningCert.cfg', 'auth.instance_id', 'raCertAuth', quotes=False, separator='=')
def uninstall(self):
try:
@@ -803,6 +841,6 @@ class CAInstance(service.Service):
if __name__ == "__main__":
installutils.standard_logging_setup("install.log", False)
cs = CADSInstance()
cs.create_instance("dirsrv", "GREYOAK.COM", "catest.greyoak.com", "greyoak.com", "password")
cs.create_instance("dirsrv", "EXAMPLE.COM", "catest.example.com", "example.com", "password")
ca = CAInstance()
ca.configure_instance("pkiuser", "catest.greyoak.com", "password", "password")
ca.configure_instance("pkiuser", "catest.example.com", "password", "password")

View File

@@ -37,6 +37,20 @@ import nss.nss as nss
CA_SERIALNO="/var/lib/ipa/ca_serialno"
def ipa_self_signed():
"""
Determine if the current IPA CA is self-signed or using another CA
Note that this doesn't distinguish between dogtag and being provided
PKCS#12 files from another CA.
A server is self-signed if /var/lib/ipa/ca_serialno exists
"""
if ipautil.file_exists(CA_SERIALNO):
return True
else:
return False
def client_auth_data_callback(ca_names, chosen_nickname, password, certdb):
cert = None
if chosen_nickname:
@@ -79,10 +93,12 @@ class CertDB(object):
self.certder_fname = self.reqdir + "/tmpcert.der"
self.host_name = host_name
if ipautil.file_exists(CA_SERIALNO):
self.self_signed_ca = True
self.self_signed_ca = ipa_self_signed()
if self.self_signed_ca:
self.subject_format = "CN=%s,ou=test-ipa,O=IPA"
else:
self.self_signed_ca = False
self.subject_format = "CN=%s,OU=pki-ipa,O=IPA"
# Making this a starting value that will generate
# unique values for the current DB is the
@@ -222,6 +238,42 @@ class CertDB(object):
"-f", self.passwd_fname])
self.set_perms(self.passwd_fname, write=True)
def list_certs(self):
"""
Return a tuple of tuples containing (nickname, trust)
"""
p = subprocess.Popen(["/usr/bin/certutil", "-d", self.secdir,
"-L"], stdout=subprocess.PIPE)
certs = p.stdout.read()
certs = certs.split("\n")
# FIXME, this relies on NSS never changing the formatting of certutil
certlist = []
for cert in certs:
nickname = cert[0:61]
trust = cert[61:]
if re.match(r'\w+,\w+,\w+', trust):
certlist.append((nickname.strip(), trust))
return tuple(certlist)
def has_nickname(self, nickname):
"""
Returns True if nickname exists in the certdb, False otherwise.
This could also be done directly with:
certutil -L -d -n <nickname> ...
"""
certs = self.list_certs()
for cert in certs:
if nickname == cert[0]:
return True
return False
def create_ca_cert(self):
# Generate the encryption key
self.run_certutil(["-G", "-z", self.noise_fname, "-f", self.passwd_fname])
@@ -279,7 +331,7 @@ class CertDB(object):
raise RuntimeError("Unable to find serial number")
def create_server_cert(self, nickname, subject, other_certdb=None):
def create_server_cert(self, nickname, hostname, other_certdb=None, subject=None):
"""
other_certdb can mean one of two things, depending on the context.
@@ -288,20 +340,26 @@ class CertDB(object):
If we are using a dogtag CA then it contains the RA agent key
that will issue our cert.
You can override the certificate Subject by specifying a subject.
"""
cdb = other_certdb
if not cdb:
cdb = self
if subject is None:
subject=self.subject_format % hostname
(out, err) = self.request_cert(subject)
cdb.issue_server_cert(self.certreq_fname, self.certder_fname)
self.add_cert(self.certder_fname, nickname)
os.unlink(self.certreq_fname)
os.unlink(self.certder_fname)
def create_signing_cert(self, nickname, subject, other_certdb=None):
def create_signing_cert(self, nickname, hostname, other_certdb=None, subject=None):
cdb = other_certdb
if not cdb:
cdb = self
if subject is None:
subject=self.subject_format % hostname
self.request_cert(subject)
cdb.issue_signing_cert(self.certreq_fname, self.certder_fname)
self.add_cert(self.certder_fname, nickname)
@@ -625,6 +683,9 @@ class CertDB(object):
pkcs12_pwd_fname: the file containing the pin for the PKCS#12 file
nickname: the nickname/friendly-name of the cert we are loading
passwd: The password to use for the new NSS database we are creating
The global CA may be added as well in case it wasn't included in the
PKCS#12 file. Extra certs won't hurt in any case.
"""
self.create_noise_file()
self.create_passwd_file(passwd)
@@ -638,6 +699,15 @@ class CertDB(object):
nickname = server_certs[0][0]
self.cacert_name = self.find_root_cert(nickname)
# The point here is to list the cert chain to determine which CA
# to trust. If we get the same nickname back as our server cert
# go ahead and try to pull in the CA in case it either wasn't in the
# PKCS#12 file we loaded or isn't showing in the chain from
# certutil -O (bug #509132)
if self.cacert_name == nickname:
self.cacert_name="CA certificate"
self.load_cacert("/usr/share/ipa/html/ca.crt")
self.trust_root_cert(nickname)
self.create_pin_file()
self.export_ca_cert(self.cacert_name, False)

View File

@@ -327,12 +327,12 @@ class DsInstance(service.Service):
nickname = "Server-Cert"
if self.self_signed_ca:
dsdb.create_self_signed()
dsdb.create_server_cert("Server-Cert", "cn=%s,ou=Fedora Directory Server" % self.host_name)
dsdb.create_server_cert("Server-Cert", self.host_name)
else:
cadb = certs.CertDB("/etc/httpd/alias", host_name=self.host_name)
cadb.export_ca_cert(cadb.cacert_name, False)
dsdb.create_from_cacert(cadb.cacert_fname, passwd=None)
dsdb.create_server_cert("Server-Cert", "CN=%s,OU=pki-ipa,O=IPA" % self.host_name, cadb)
dsdb.create_server_cert("Server-Cert", self.host_name, cadb)
dsdb.create_pin_file()
conn = ipaldap.IPAdmin("127.0.0.1")

View File

@@ -179,11 +179,11 @@ class HTTPInstance(service.Service):
else:
if self.self_signed_ca:
db.create_from_cacert(ca_db.cacert_fname)
db.create_server_cert("Server-Cert", "cn=%s,ou=Apache Web Server" % self.fqdn, ca_db)
db.create_signing_cert("Signing-Cert", "cn=%s,ou=Signing Certificate,o=Identity Policy Audit" % self.fqdn, ca_db)
db.create_server_cert("Server-Cert", self.fqdn, ca_db)
db.create_signing_cert("Signing-Cert", "Object Signing Cert", ca_db)
else:
db.create_server_cert("Server-Cert", "CN=%s,OU=ipa-pki,O=IPA" % self.fqdn, ca_db)
db.create_signing_cert("Signing-Cert", "CN=Object Signing Cert,OU=ipa-pki,O=IPA", ca_db)
db.create_server_cert("Server-Cert", self.fqdn, ca_db)
db.create_signing_cert("Signing-Cert", "Object Signing Cert", ca_db)
db.create_password_conf()
# Fix the database permissions