From e4470f8165242fba6c5ce477a2eeca0141891701 Mon Sep 17 00:00:00 2001 From: Rob Crittenden Date: Wed, 20 Jan 2010 11:26:20 -0500 Subject: User-defined certificate subjects Let the user, upon installation, set the certificate subject base for the dogtag CA. Certificate requests will automatically be given this subject base, regardless of what is in the CSR. The selfsign plugin does not currently support this dynamic name re-assignment and will reject any incoming requests that don't conform to the subject base. The certificate subject base is stored in cn=ipaconfig but it does NOT dynamically update the configuration, for dogtag at least. The file /var/lib/pki-ca/profiles/ca/caIPAserviceCert.cfg would need to be updated and pki-cad restarted. --- install/tools/ipa-replica-install | 8 ++++++-- install/tools/ipa-replica-prepare | 31 ++++++++++++++++++++++++------- install/tools/ipa-server-install | 39 +++++++++++++++++++++++++++++++-------- 3 files changed, 61 insertions(+), 17 deletions(-) (limited to 'install/tools') diff --git a/install/tools/ipa-replica-install b/install/tools/ipa-replica-install index 76695786..7131d6b7 100755 --- a/install/tools/ipa-replica-install +++ b/install/tools/ipa-replica-install @@ -48,6 +48,7 @@ class ReplicaConfig: self.host_name = "" self.repl_password = "" self.dir = "" + self.subject_base = "O=IPA" def parse_options(): from optparse import OptionParser @@ -106,6 +107,7 @@ def read_info(dir, rconfig): rconfig.ds_user = config.get("realm", "ds_user") rconfig.domain_name = config.get("realm", "domain_name") rconfig.host_name = config.get("realm", "destination_host") + rconfig.subject_base = config.get("realm", "subject_base") def get_host_name(): hostname = installutils.get_fqdn() @@ -150,9 +152,8 @@ 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() - ca.configure_instance("pkiuser", config.host_name, config.dirman_password, config.dirman_password, pkcs12_info=(cafile,), master_host=config.master_host_name) + 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 @@ -346,6 +347,8 @@ def main(): CA.import_ra_cert(dir + "/ra.p12") CA.fix_ra_perms() service.restart("httpd") + service.print_msg("Setting the certificate subject base") + CA.set_subject_in_config(util.realm_to_suffix(config.realm_name)) # The DS instance is created before the keytab, add the SSL cert we # generated @@ -370,6 +373,7 @@ def main(): service.restart("dirsrv") service.restart("krb5kdc") + service.restart("httpd") if options.setup_dns: api.Backend.ldap2.connect(bind_dn="cn=Directory Manager", diff --git a/install/tools/ipa-replica-prepare b/install/tools/ipa-replica-prepare index bc86a41a..f9977ecb 100755 --- a/install/tools/ipa-replica-prepare +++ b/install/tools/ipa-replica-prepare @@ -33,6 +33,7 @@ from ipaserver import ipaldap from ipapython import version from ipalib.constants import DEFAULT_CONFIG from ipalib import api +from ipalib import util import ldap def parse_options(): @@ -94,13 +95,23 @@ def get_domain_name(): return domain_name +def get_subject_base(host_name, dm_password, suffix): + try: + conn = ipaldap.IPAdmin(host_name) + conn.do_simple_bind(bindpw=dm_password) + except Exception, e: + logging.critical("Could not connect to the Directory Server on %s" % host_name) + raise e + entry = conn.getEntry("cn=ipaConfig, cn=etc, %s" % suffix, ldap.SCOPE_SUBTREE) + return entry.getValue('ipacertificatesubjectbase') + def check_ipa_configuration(realm_name): config_dir = dsinstance.config_dirname(dsinstance.realm_to_serverid(realm_name)) if not ipautil.dir_exists(config_dir): logging.error("could not find directory instance: %s" % config_dir) sys.exit(1) -def export_certdb(realm_name, ds_dir, dir, passwd_fname, fname, hostname): +def export_certdb(realm_name, ds_dir, dir, passwd_fname, fname, hostname, subject_base=None): """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. @@ -113,14 +124,14 @@ def export_certdb(realm_name, ds_dir, dir, passwd_fname, fname, hostname): try: self_signed = certs.ipa_self_signed() - db = certs.CertDB(dir) + db = certs.CertDB(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=get_host_name()) - ca_db = certs.CertDB(httpinstance.NSS_DIR, host_name=get_host_name()) + ca_db = certs.CertDB(httpinstance.NSS_DIR, host_name=get_host_name(), subject_base=subject_base) db.create_from_cacert(ca_db.cacert_fname) db.create_server_cert("Server-Cert", hostname, ca_db) except Exception, e: @@ -174,7 +185,8 @@ def get_ds_user(ds_dir): return user -def save_config(dir, realm_name, host_name, ds_user, domain_name, dest_host): +def save_config(dir, realm_name, host_name, ds_user, domain_name, dest_host, + subject_base): config = SafeConfigParser() config.add_section("realm") config.set("realm", "realm_name", realm_name) @@ -182,6 +194,7 @@ def save_config(dir, realm_name, host_name, ds_user, domain_name, dest_host): config.set("realm", "ds_user", ds_user) config.set("realm", "domain_name", domain_name) config.set("realm", "destination_host", dest_host) + config.set("realm", "subject_base", subject_base) fd = open(dir + "/realm_info", "w") config.write(fd) @@ -265,6 +278,8 @@ def main(): print "Preparing replica for %s from %s" % (replica_fqdn, host_name) + subject_base = get_subject_base(host_name, dirman_password, util.realm_to_suffix(realm_name)) + top_dir = tempfile.mkdtemp("ipa") dir = top_dir + "/realm_info" os.mkdir(dir, 0700) @@ -298,7 +313,7 @@ def main(): 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", replica_fqdn) + export_certdb(realm_name, ds_dir, dir, passwd_fname, "dscert", replica_fqdn, subject_base) if options.http_pin: passwd = options.http_pin @@ -319,13 +334,15 @@ def main(): sys.exit(1) else: print "Creating SSL certificate for the Web Server" - export_certdb(realm_name, ds_dir, dir, passwd_fname, "httpcert", replica_fqdn) + export_certdb(realm_name, ds_dir, dir, passwd_fname, "httpcert", replica_fqdn, subject_base) print "Exporting RA certificate" export_ra_pkcs12(dir, dirman_password) + print "Copying additional files" copy_files(realm_name, dir) + print "Finalizing configuration" - save_config(dir, realm_name, host_name, ds_user, domain_name, replica_fqdn) + save_config(dir, realm_name, host_name, ds_user, domain_name, replica_fqdn, subject_base) replicafile = "/var/lib/ipa/replica-info-" + replica_fqdn encfile = replicafile+".gpg" diff --git a/install/tools/ipa-server-install b/install/tools/ipa-server-install index c92989a4..06bed03b 100755 --- a/install/tools/ipa-server-install +++ b/install/tools/ipa-server-install @@ -35,6 +35,7 @@ import signal import shutil import glob import traceback +import ldap from optparse import OptionParser from ConfigParser import RawConfigParser import random @@ -49,6 +50,7 @@ from ipaserver.install import certs from ipaserver.install import service from ipapython import version from ipaserver.install.installutils import * +from ipaserver import ipaldap from ipapython import sysrestore from ipapython.ipautil import * @@ -117,6 +119,8 @@ def parse_options(): help="The starting uid value (default random)") parser.add_option("--gidstart", dest="gidstart", default=namespace, type=int, help="The starting gid value (default random)") + parser.add_option("--subject", dest="subject", default="O=IPA", + help="The certificate subject base (default O=IPA)") options, args = parser.parse_args() if not options.setup_dns: @@ -456,6 +460,20 @@ def render_assets(): ui = ipawebui.create_wsgi_app(api) ui.render_assets() +def set_subject_in_config(host_name, dm_password, suffix, subject_base): + try: + conn = ipaldap.IPAdmin(host_name) + conn.do_simple_bind(bindpw=dm_password) + except Exception, e: + logging.critical("Could not connect to the Directory Server on %s" % host_name) + raise e + entry = conn.getEntry("cn=ipaConfig, cn=etc, %s" % suffix, ldap.SCOPE_SUBTREE) + if entry.getValue('ipaCertificateSubjectBase') is None: + newentry = entry.toDict() + newentry['ipaCertificateSubjectBase'] = subject_base + conn.updateEntry(entry.dn, entry.toDict(), newentry) + + conn.unbind() def main(): global ds @@ -502,7 +520,7 @@ def main(): print "Aborting uninstall operation." sys.exit(1) - return uninstall(not certs.ipa_self_signed()) + return uninstall(not certs.ipa_self_signed() or options.ca) # This will override any settings passed in on the cmdline options._update_loose(read_cache()) @@ -702,12 +720,12 @@ def main(): cs.create_instance(ds_user, realm_name, host_name, domain_name, dm_password) ca = cainstance.CAInstance() if external == 0: - ca.configure_instance("pkiuser", host_name, dm_password, dm_password) + ca.configure_instance("pkiuser", host_name, dm_password, dm_password, subject_base=options.subject) elif external == 1: write_cache(options) - ca.configure_instance("pkiuser", host_name, dm_password, dm_password, csr_file="/root/ipa.csr") + ca.configure_instance("pkiuser", host_name, dm_password, dm_password, csr_file="/root/ipa.csr", subject_base=options.subject) else: - ca.configure_instance("pkiuser", host_name, dm_password, dm_password, cert_file=options.external_cert_file, cert_chain_file=options.external_ca_file) + ca.configure_instance("pkiuser", host_name, dm_password, dm_password, cert_file=options.external_cert_file, cert_chain_file=options.external_ca_file, subject_base=options.subject) # Configure ntpd if options.conf_ntp: @@ -719,11 +737,11 @@ def main(): if options.dirsrv_pkcs12: pkcs12_info = (options.dirsrv_pkcs12, pw_name) try: - ds.create_instance(ds_user, realm_name, host_name, domain_name, dm_password, pkcs12_info) + ds.create_instance(ds_user, realm_name, host_name, domain_name, dm_password, pkcs12_info, subject_base=options.subject) finally: os.remove(pw_name) else: - ds.create_instance(ds_user, realm_name, host_name, domain_name, dm_password, self_signed_ca=not options.ca, uidstart=options.uidstart, gidstart=options.gidstart) + ds.create_instance(ds_user, realm_name, host_name, domain_name, dm_password, self_signed_ca=not options.ca, uidstart=options.uidstart, gidstart=options.gidstart, subject_base=options.subject) # Create a kerberos instance krb = krbinstance.KrbInstance(fstore) @@ -747,10 +765,10 @@ def main(): http = httpinstance.HTTPInstance(fstore) if options.http_pkcs12: pkcs12_info = (options.http_pkcs12, pw_name) - http.create_instance(realm_name, host_name, domain_name, dm_password, autoconfig=False, pkcs12_info=pkcs12_info) + http.create_instance(realm_name, host_name, domain_name, dm_password, autoconfig=False, pkcs12_info=pkcs12_info, subject_base=options.subject) os.remove(pw_name) else: - http.create_instance(realm_name, host_name, domain_name, dm_password, autoconfig=True, self_signed_ca=not options.ca) + http.create_instance(realm_name, host_name, domain_name, dm_password, autoconfig=True, self_signed_ca=not options.ca, subject_base=options.subject) ipautil.run(["/sbin/restorecon", "/var/cache/ipa/sessions"]) # Create the management framework config file @@ -768,6 +786,11 @@ def main(): fd.write('webui_assets_dir=' + ASSETS_DIR + '\n') fd.close() + set_subject_in_config(host_name, dm_password, util.realm_to_suffix(realm_name), options.subject) + if options.ca: + service.print_msg("Setting the certificate subject base") + ca.set_subject_in_config(util.realm_to_suffix(realm_name)) + # Apply any LDAP updates. Needs to be done after the configuration file # is created service.print_msg("Applying LDAP updates") -- cgit