On Fri, Jul 15, 2016 at 03:04:48PM +1000, Fraser Tweedale wrote: > The attached patch is a work in progress for > https://fedorahosted.org/freeipa/ticket/2614 (BZ 828866). > > I am sharing now to make the approach clear and solicit feedback. > > It has been tested for server install, replica install (with and > without CA) and CA-replica install (all hosts running master+patch). > > Migration from earlier versions and server/replica/CA install on a > CA-less deployment are not yet tested; these will be tested over > coming days and patch will be tweaked as necessary. > > Commit message has a fair bit to say so I won't repeat here but let > me know your questions and comments. > > Thanks, > Fraser > It does help to attach the patch, of course ^_^
From 74102e13b041cd05396a579f12f26a9f80394ad1 Mon Sep 17 00:00:00 2001 From: Fraser Tweedale <ftwee...@redhat.com> Date: Mon, 11 Jul 2016 12:57:11 +1000 Subject: [PATCH] Allow full customisability of IPA CA subject DN
Currently only the "subject base" of the IPA CA subject DN can be customised via the installer's --subject option. The RDN "CN=Certificate Authority" is appended to form the subject DN, and this composition is widely assumed, hardcoded in many places. Some administrators need more control over the CA subject DN, especially to satisfy expectations of external CAs when the IPA CA is to be externally signed. This patch adds full customisability of the CA subject DN. The --subject argument can now be the full DN, and the subject base is derived from it. The full rules are as follows: - If --subject is not given, default to "CN=Certificate Authority, O=$REALM" (existing behaviour) - If --external-ca is used, subject is used as-is. - If and only if --external-ca is not used, to meet Dogtag's expectations, the "most specific" CN AVA encountered shall be the most specific RDN (it is moved if necessary); if the subject DN does not contain a CN AVA, then "CN=Certificate Authority" is appended. - The subject base is derived from the subject (after processing per preceding points) by extracting OU, O, L, ST, C and DC AVAs, preserving relative order. If the resulting DN is empty, it defaults to "O=$REALM". Fixes: https://fedorahosted.org/freeipa/ticket/2614 --- install/share/certmap.conf.template | 2 +- install/tools/ipa-ca-install | 14 +++++------- install/tools/man/ipa-server-install.1 | 2 +- ipapython/ipautil.py | 20 +++++++++++++++++ ipaserver/install/ca.py | 20 +++++++++-------- ipaserver/install/cainstance.py | 35 ++++++++++++++++++------------ ipaserver/install/certs.py | 9 ++++---- ipaserver/install/dsinstance.py | 29 +++++++++++++++---------- ipaserver/install/installutils.py | 35 +++++++++++++++++++++++++++--- ipaserver/install/ipa_cacert_manage.py | 9 ++++++-- ipaserver/install/krainstance.py | 9 +++++--- ipaserver/install/server/common.py | 4 ++-- ipaserver/install/server/install.py | 17 ++++++++++----- ipaserver/install/server/replicainstall.py | 27 ++++++++++++++++------- 14 files changed, 159 insertions(+), 73 deletions(-) diff --git a/install/share/certmap.conf.template b/install/share/certmap.conf.template index e76bf3c653a4f1d130ce8c264a28cac5dc63925c..d59b095faff804eae4cbd2ef984aa8ca3be52946 100644 --- a/install/share/certmap.conf.template +++ b/install/share/certmap.conf.template @@ -41,6 +41,6 @@ certmap default default #default:InitFn <Init function's name> default:DNComps default:FilterComps uid -certmap ipaca CN=Certificate Authority,$SUBJECT_BASE +certmap ipaca $ISSUER_DN ipaca:CmapLdapAttr seeAlso ipaca:verifycert on diff --git a/install/tools/ipa-ca-install b/install/tools/ipa-ca-install index ed685920cbadb9cd3fc80865afb1610ca42f8b13..8a8adb3984386bb88227d769a8c5132bb121b870 100755 --- a/install/tools/ipa-ca-install +++ b/install/tools/ipa-ca-install @@ -32,7 +32,7 @@ from ipaserver.install import bindinstance, dsinstance, ca from ipaserver.install import cainstance, custodiainstance, service from ipapython import version from ipalib import api -from ipalib.constants import DOMAIN_LEVEL_0 +from ipalib.constants import DOMAIN_LEVEL_0, IPA_CA_CN from ipapython.dn import DN from ipapython.config import IPAOptionParser from ipapython.ipa_log_manager import root_logger, standard_logging_setup @@ -160,9 +160,7 @@ def install_replica(safe_options, options, filename): conn.connect(bind_dn=DN(('cn', 'Directory Manager')), bind_pw=dirman_password) - if config.subject_base is None: - attrs = conn.get_ipa_config() - config.subject_base = attrs.get('ipacertificatesubjectbase')[0] + subject = api.Command.ca_show(IPA_CA_CN)['result']['ipacasubjectdn'][0] if config.master_host_name is None: config.ca_host_name = \ @@ -175,7 +173,7 @@ def install_replica(safe_options, options, filename): options.domain_name = config.domain_name options.dm_password = config.dirman_password options.host_name = config.host_name - options.subject = config.subject_base + options.subject = subject if os.path.exists(cafile): options.ca_cert_file = cafile else: @@ -193,7 +191,7 @@ def install_replica(safe_options, options, filename): host_name=config.host_name, dm_password=config.dirman_password) CA.configure_replica(config.ca_host_name, - subject_base=config.subject_base, + subject=subject, ca_cert_bundle=ca_data) # Install CA DNS records if bindinstance.dns_container_exists(api.env.host, api.env.basedn, @@ -220,13 +218,13 @@ def install_master(safe_options, options): bind_pw=dm_password) config = api.Command['config_show']()['result'] - subject_base = config['ipacertificatesubjectbase'][0] + subject = api.Command.ca_show(IPA_CA_CN)['result']['ipacasubjectdn'] options.realm_name = api.env.realm options.domain_name = api.env.domain options.dm_password = dm_password options.host_name = api.env.host - options.subject = subject_base + options.subject = subject ca.install_check(True, None, options) ca.install(True, None, options) diff --git a/install/tools/man/ipa-server-install.1 b/install/tools/man/ipa-server-install.1 index 55b49449e3c44aebfeefe5cb71d73e9abf07c5b2..775427de1a2a220fb01dc7b8892105dd40bf182d 100644 --- a/install/tools/man/ipa-server-install.1 +++ b/install/tools/man/ipa-server-install.1 @@ -130,7 +130,7 @@ Name of the Kerberos KDC SSL certificate to install File containing the CA certificate of the CA which issued the Directory Server, Apache Server and Kerberos KDC certificates. The file is accepted in PEM and DER certificate and PKCS#7 certificate chain formats. This option may be used multiple times. Use this option if the CA certificate is not present in the certificate files. .TP \fB\-\-subject\fR=\fISUBJECT\fR -The certificate subject base (default O=REALM.NAME) +The CA certificate subject DN (default CN=Certificate Authority,O=REALM.NAME) .TP \fB\-\-ca\-signing\-algorithm\fR=\fIALGORITHM\fR Signing algorithm of the IPA CA certificate. Possible values are SHA1withRSA, SHA256withRSA, SHA512withRSA. Default value is SHA256withRSA. Use this option with --external-ca if the external CA does not support the default signing algorithm. diff --git a/ipapython/ipautil.py b/ipapython/ipautil.py index 763a99c117e22a4ac49d8d34b38230f3da7c8435..b2c5a9adf57522bb28583c03eb60ce74c4d14868 100644 --- a/ipapython/ipautil.py +++ b/ipapython/ipautil.py @@ -1469,3 +1469,23 @@ def is_fips_enabled(): # Consider that the host is not fips-enabled if the file does not exist pass return False + + +def extract_ca_subject_base(dn, realm_name): + """ + Extract a base DN from the given CA subject DN. + + Components extracted are OU, O, L, ST, C, DC. Relative order + is retained. If none of those attributes are present, return + O=<realm_name>. + + """ + base_attrs = ['ou', 'o', 'l', 'st', 'c', 'dc'] + l = [] + for rdn in DN(dn): + for ava in rdn: + if ava.attr.lower() in base_attrs: + l.append(ava) + if len(l) == 0: + l = [('O', realm_name)] + return DN(*l) diff --git a/ipaserver/install/ca.py b/ipaserver/install/ca.py index bce804ac1c4e3eaf8dd08bed894ad45ea2d73ae1..e2d12e829ff24d2d317ed4d136363df35c40d07c 100644 --- a/ipaserver/install/ca.py +++ b/ipaserver/install/ca.py @@ -26,7 +26,8 @@ def install_check(standalone, replica_config, options): realm_name = options.realm_name host_name = options.host_name - subject_base = options.subject + subject_dn = options.subject + subject_base = ipautil.extract_ca_subject_base(subject_dn, realm_name) if replica_config is not None: if standalone and api.env.ra_plugin == 'selfsign': @@ -106,7 +107,7 @@ def install_check(standalone, replica_config, options): if not cert: continue subject = DN(str(x509.get_subject(cert))) - if subject in (DN('CN=Certificate Authority', subject_base), + if subject in (DN(subject_dn), DN('CN=IPA RA', subject_base), DN('CN=Object Signing Cert', subject_base)): print(("Certificate with subject %s is present in %s, " @@ -124,7 +125,6 @@ def install_step_0(standalone, replica_config, options): domain_name = options.domain_name dm_password = options.dm_password host_name = options.host_name - subject_base = options.subject if replica_config is not None: # Configure the CA if necessary @@ -136,8 +136,10 @@ def install_step_0(standalone, replica_config, options): if standalone: api.Backend.ldap2.disconnect() - cainstance.install_replica_ca(replica_config, postinstall, - ra_p12=getattr(options, 'ra_p12', None)) + cainstance.install_replica_ca( + replica_config, postinstall, + ra_p12=getattr(options, 'ra_p12', None), + subject=options.subject) if standalone and not api.Backend.ldap2.isconnected(): api.Backend.ldap2.connect(bind_dn=DN(('cn', 'Directory Manager')), @@ -157,19 +159,19 @@ def install_step_0(standalone, replica_config, options): ca.create_ra_agent_db = False if external == 0: ca.configure_instance(host_name, dm_password, - dm_password, subject_base=subject_base, + dm_password, subject=options.subject, ca_signing_algorithm=options.ca_signing_algorithm) elif external == 1: ca.configure_instance(host_name, dm_password, dm_password, csr_file=paths.ROOT_IPA_CSR, - subject_base=subject_base, + subject=options.subject, ca_signing_algorithm=options.ca_signing_algorithm, ca_type=options.external_ca_type) else: ca.configure_instance(host_name, dm_password, dm_password, cert_file=external_cert_file.name, cert_chain_file=external_ca_file.name, - subject_base=subject_base, + subject=options.subject, ca_signing_algorithm=options.ca_signing_algorithm) @@ -178,7 +180,7 @@ def install_step_1(standalone, replica_config, options): domain_name = options.domain_name dm_password = options.dm_password host_name = options.host_name - subject_base = options.subject + subject_base = ipautil.extract_ca_subject_base(options.subject, realm_name) basedn = ipautil.realm_to_suffix(realm_name) diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py index 070498fe8a394802ea55f848a268e2b6563ec472..afeb8007f47571f1de38f190e64cb6cae52b3d98 100644 --- a/ipaserver/install/cainstance.py +++ b/ipaserver/install/cainstance.py @@ -344,7 +344,7 @@ class CAInstance(DogtagInstance): pkcs12_info=None, master_host=None, csr_file=None, cert_file=None, cert_chain_file=None, master_replication_port=None, - subject_base=None, ca_signing_algorithm=None, + subject=None, ca_signing_algorithm=None, ca_type=None, ra_p12=None): """Create a CA instance. @@ -364,10 +364,14 @@ class CAInstance(DogtagInstance): self.clone = True self.master_host = master_host self.master_replication_port = master_replication_port - if subject_base is None: - self.subject_base = DN(('O', self.realm)) + + if subject is None: + self.subject = installutils.default_ca_subject_dn(self.realm) else: - self.subject_base = subject_base + self.subject = subject + self.subject_base = ipautil.extract_ca_subject_base( + self.subject, self.realm) + if ca_signing_algorithm is None: self.ca_signing_algorithm = 'SHA256withRSA' else: @@ -501,7 +505,7 @@ class CAInstance(DogtagInstance): config.set("CA", "pki_audit_signing_subject_dn", str(DN(('cn', 'CA Audit'), self.subject_base))) config.set("CA", "pki_ca_signing_subject_dn", - str(DN(('cn', 'Certificate Authority'), self.subject_base))) + str(self.subject)) # Certificate nicknames config.set("CA", "pki_subsystem_nickname", "subsystemCert cert-pki-ca") @@ -775,7 +779,7 @@ class CAInstance(DogtagInstance): userCertificate=[cert_data], description=['2;%s;%s;%s' % ( cert.serial_number, - DN(('CN', 'Certificate Authority'), self.subject_base), + DN(self.subject), DN(('CN', 'IPA RA'), self.subject_base))]) conn.add_entry(entry) @@ -854,7 +858,7 @@ class CAInstance(DogtagInstance): st = 1 en = 0 subid = 0 - ca_dn = DN(('CN','Certificate Authority'), self.subject_base) + ca_dn = DN(self.subject) while st > 0: st = certlist.find('-----BEGIN', en) en = certlist.find('-----END', en+1) @@ -1305,7 +1309,7 @@ class CAInstance(DogtagInstance): basedn = ipautil.realm_to_suffix(self.realm) self.ldap_enable('CA', self.fqdn, None, basedn) - def configure_replica(self, master_host, subject_base=None, + def configure_replica(self, master_host, subject=None, ca_cert_bundle=None, ca_signing_algorithm=None, ca_type=None): """Creates a replica CA, creating a local DS backend and using @@ -1314,10 +1318,14 @@ class CAInstance(DogtagInstance): """ self.master_host = master_host self.master_replication_port = 389 - if subject_base is None: - self.subject_base = DN(('O', self.realm)) + + if subject is None: + self.subject = installutils.default_ca_subject_dn(self.realm) else: - self.subject_base = subject_base + self.subject = subject + self.subject_base = ipautil.extract_ca_subject_base( + self.subject, self.realm) + if ca_signing_algorithm is None: self.ca_signing_algorithm = 'SHA256withRSA' else: @@ -1489,7 +1497,7 @@ def replica_ca_install_check(config): exit('IPA schema missing on master CA directory server') -def install_replica_ca(config, postinstall=False, ra_p12=None): +def install_replica_ca(config, postinstall=False, ra_p12=None, subject=None): """ Install a CA on a replica. @@ -1509,7 +1517,6 @@ def install_replica_ca(config, postinstall=False, ra_p12=None): ca = CAInstance(config.realm_name, certs.NSS_DIR) ca.dm_password = config.dirman_password - ca.subject_base = config.subject_base if not config.setup_ca: # We aren't configuring the CA in this step but we still need @@ -1528,7 +1535,7 @@ def install_replica_ca(config, postinstall=False, ra_p12=None): pkcs12_info=(cafile,), ra_p12=ra_p12, master_host=config.master_host_name, master_replication_port=config.ca_ds_port, - subject_base=config.subject_base) + subject=subject) # Restart httpd since we changed it's config and added ipa-pki-proxy.conf # Without the restart, CA service status check would fail due to missing diff --git a/ipaserver/install/certs.py b/ipaserver/install/certs.py index b3d273ff107f0493516845745c4f14242fc518ca..06248e2387c11ff69e26a61e4a0a584711afa7c9 100644 --- a/ipaserver/install/certs.py +++ b/ipaserver/install/certs.py @@ -93,15 +93,14 @@ class CertDB(object): self.certreq_fname = None self.certder_fname = None self.host_name = host_name - self.subject_base = subject_base + self.subject = subject_base or DN(('O', 'IPA')) + self.subject_base = ipautil.extract_ca_subject_base( + self.subject, realm) try: self.cwd = os.getcwd() except OSError as e: raise RuntimeError("Unable to determine the current directory: %s" % str(e)) - if not subject_base: - self.subject_base = DN(('O', 'IPA')) - self.cacert_name = get_ca_nickname(self.realm) self.valid_months = "120" self.keysize = "1024" @@ -253,7 +252,7 @@ class CertDB(object): certs = fd.read() fd.close() - ca_dn = DN(('CN','Certificate Authority'), self.subject_base) + ca_dn = self.subject st = 0 while True: try: diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py index c93b3b4ff58c4102a9de448247966ad3dd8e4e7c..12cc838a1e42f89d1f6c1107ffc82ef02bd48fe7 100644 --- a/ipaserver/install/dsinstance.py +++ b/ipaserver/install/dsinstance.py @@ -227,6 +227,7 @@ class DsInstance(service.Service): self.dercert = None self.idstart = None self.idmax = None + self.subject = None self.subject_base = None self.open_ports = [] self.run_init_memberof = True @@ -244,6 +245,7 @@ class DsInstance(service.Service): self.fstore = sysrestore.FileStore(paths.SYSRESTORE) + subject = ipautil.dn_attribute_property('_subject') subject_base = ipautil.dn_attribute_property('_subject_base') def __common_setup(self, enable_ssl=False): @@ -292,7 +294,7 @@ class DsInstance(service.Service): self.step("configuring directory to start on boot", self.__enable) def init_info(self, realm_name, fqdn, domain_name, dm_password, - subject_base, idstart, idmax, pkcs12_info, ca_file=None): + subject, idstart, idmax, pkcs12_info, ca_file=None): self.realm = realm_name.upper() self.serverid = installutils.realm_to_serverid(self.realm) self.suffix = ipautil.realm_to_suffix(self.realm) @@ -300,7 +302,9 @@ class DsInstance(service.Service): self.dm_password = dm_password self.domain = domain_name self.principal = "ldap/%s@%s" % (self.fqdn, self.realm) - self.subject_base = subject_base + self.subject = subject + self.subject_base = ipautil.extract_ca_subject_base( + self.subject, self.realm) self.idstart = idstart self.idmax = idmax self.pkcs12_info = pkcs12_info @@ -312,11 +316,11 @@ class DsInstance(service.Service): def create_instance(self, realm_name, fqdn, domain_name, dm_password, pkcs12_info=None, - idstart=1100, idmax=999999, subject_base=None, + idstart=1100, idmax=999999, subject=None, hbac_allow=True, ca_file=None): self.init_info( realm_name, fqdn, domain_name, dm_password, - subject_base, idstart, idmax, pkcs12_info, ca_file=ca_file) + subject, idstart, idmax, pkcs12_info, ca_file=ca_file) self.__common_setup() self.step("restarting directory server", self.__restart_instance) @@ -350,7 +354,7 @@ class DsInstance(service.Service): self.start_creation(runtime=10) def create_replica(self, realm_name, master_fqdn, fqdn, - domain_name, dm_password, subject_base, api, + domain_name, dm_password, subject, api, pkcs12_info=None, ca_file=None, ca_is_configured=None, promote=False): # idstart and idmax are configured so that the range is seen as @@ -365,7 +369,7 @@ class DsInstance(service.Service): fqdn=fqdn, domain_name=domain_name, dm_password=dm_password, - subject_base=subject_base, + subject=subject, idstart=idstart, idmax=idmax, pkcs12_info=pkcs12_info, @@ -865,7 +869,7 @@ class DsInstance(service.Service): shutil.copyfile(ipautil.SHARE_DIR + "certmap.conf.template", config_dirname(self.serverid) + "certmap.conf") installutils.update_file(config_dirname(self.serverid) + "certmap.conf", - '$SUBJECT_BASE', str(self.subject_base)) + '$ISSUER_DN', str(self.subject)) sysupgrade.set_upgrade_state( 'certmap.conf', 'subject_base', @@ -1190,9 +1194,12 @@ class DsInstance(service.Service): ) try: with open(os.path.join(certmap_dir, 'certmap.conf')) as f: + prefix = 'certmap ipaca' for line in f: - if line.startswith('certmap ipaca'): - subject_base = line.strip().split(',')[-1] + if line.startswith(prefix): + subject_dn = line[len(prefix):].strip() + subject_base = ipautil.extract_ca_subject_base( + subject_dn, api.env.realm) root_logger.debug( 'Found certificate subject base in certmap.conf: ' '%s', subject_base) @@ -1237,9 +1244,9 @@ class DsInstance(service.Service): os.chown(paths.DS_KEYTAB, pent.pw_uid, pent.pw_gid) def __get_ds_cert(self): - subject = DN(('O', self.realm)) nssdb_dir = config_dirname(self.serverid) - db = certs.CertDB(self.realm, nssdir=nssdb_dir, subject_base=subject) + db = certs.CertDB( + self.realm, nssdir=nssdb_dir, subject_base=self.subject_base) db.request_service_cert(self.nickname, self.principal, self.fqdn) db.create_pin_file() diff --git a/ipaserver/install/installutils.py b/ipaserver/install/installutils.py index 25f48aed1eeaa03353465bc40abf3484ec19bf3b..dd625868c0078359db81e4eaee80dd619778fbde 100644 --- a/ipaserver/install/installutils.py +++ b/ipaserver/install/installutils.py @@ -996,7 +996,7 @@ def check_entropy(): except ValueError as e: root_logger.debug("Invalid value in %s %s", paths.ENTROPY_AVAIL, e) -def load_external_cert(files, subject_base): +def load_external_cert(files, subject): """ Load and verify external CA certificate chain from multiple files. @@ -1004,7 +1004,7 @@ def load_external_cert(files, subject_base): chain formats. :param files: Names of files to import - :param subject_base: Subject name base for IPA certificates + :param subject: IPA CA subject DN :returns: Temporary file with the IPA CA certificate and temporary file with the external CA certificate chain """ @@ -1018,7 +1018,7 @@ def load_external_cert(files, subject_base): except RuntimeError as e: raise ScriptError(str(e)) - ca_subject = DN(('CN', 'Certificate Authority'), subject_base) + ca_subject = DN(subject) ca_nickname = None cache = {} for nickname, trust_flags in nssdb.list_certs(): @@ -1377,3 +1377,32 @@ def remove_ccache(ccache_path=None, run_as=None): except ipautil.CalledProcessError as e: root_logger.warning( "Failed to clear Kerberos credentials cache: {}".format(e)) + + +def default_ca_subject_dn(realm_name): + return DN(('CN', 'Certificate Authority'), ('O', realm_name)) + + +def normalize_dogtag_ca_subject_dn(dn): + """ + Prepare a CA subject DN to be compliant with Dogtag. + + Move the most specific CN AVA encountered to be the most + specific RDN, if it is not already so. + + If no CN AVA is encountered, add 'CN=Certificate Authority' as + the most specific RDN. + + """ + cn_ava = None + l = [] + for rdn in DN(dn): + for ava in rdn: + if cn_ava is None and ava.attr.lower() == 'cn': + cn_ava = ava + else: + l.append(ava) + if cn_ava is None: + cn_ava = ('cn', 'Certificate Authority') + l.insert(0, cn_ava) + return DN(*l) diff --git a/ipaserver/install/ipa_cacert_manage.py b/ipaserver/install/ipa_cacert_manage.py index de13ad39397ae5e9b924b0621521e5fc6016c8e6..f5e8a5f63396ad8ca887c1a41944c89c777e4311 100644 --- a/ipaserver/install/ipa_cacert_manage.py +++ b/ipaserver/install/ipa_cacert_manage.py @@ -24,6 +24,7 @@ from optparse import OptionGroup from nss import nss from nss.error import NSPRError import gssapi +import six from ipapython import admintool, certmonger, ipautil from ipapython.dn import DN @@ -31,6 +32,9 @@ from ipaplatform.paths import paths from ipalib import api, errors, x509, certstore from ipaserver.install import certs, cainstance, installutils +if six.PY3: + unicode = str + class CACertManage(admintool.AdminTool): command_name = 'ipa-cacert-manage' @@ -198,8 +202,6 @@ class CACertManage(admintool.AdminTool): options = self.options conn = api.Backend.ldap2 - cert_file, ca_file = installutils.load_external_cert( - options.external_cert_files, x509.subject_base()) nss_cert = None nss.nss_init(paths.PKI_TOMCAT_ALIAS_DIR) @@ -211,6 +213,9 @@ class CACertManage(admintool.AdminTool): pkinfo = nss_cert.subject_public_key_info.format() #pylint: enable=E1101 + cert_file, ca_file = installutils.load_external_cert( + options.external_cert_files, unicode(subject)) + nss_cert = x509.load_certificate_from_file(cert_file.name) cert = nss_cert.der_data if nss_cert.subject != subject: diff --git a/ipaserver/install/krainstance.py b/ipaserver/install/krainstance.py index dc44726887916c7216564679c6ea8e9902177b64..491c4e57f71a9aa89bb4736258b144681a93f061 100644 --- a/ipaserver/install/krainstance.py +++ b/ipaserver/install/krainstance.py @@ -93,9 +93,12 @@ class KRAInstance(DogtagInstance): self.clone = True self.master_host = master_host if subject_base is None: - self.subject_base = DN(('O', self.realm)) + self.subject = installutils.default_ca_subject_dn(realm_name) else: - self.subject_base = subject_base + self.subject = subject_base + self.subject_base = ipautil.extract_ca_subject_base( + self.subject, self.realm) + self.realm = realm_name self.suffix = ipautil.realm_to_suffix(realm_name) @@ -296,7 +299,7 @@ class KRAInstance(DogtagInstance): userCertificate=[cert_data], description=['2;%s;%s;%s' % ( cert.serial_number, - DN(('CN', 'Certificate Authority'), self.subject_base), + DN(self.subject), DN(('CN', 'IPA RA'), self.subject_base))]) conn.add_entry(entry) diff --git a/ipaserver/install/server/common.py b/ipaserver/install/server/common.py index 45fb2dc17976a08acab16783584524721411fb4e..e2780acc96db8f19598468e2b694e419eb80fd8b 100644 --- a/ipaserver/install/server/common.py +++ b/ipaserver/install/server/common.py @@ -19,7 +19,7 @@ from ipapython.dnsutil import check_zone_overlap if six.PY3: unicode = str -VALID_SUBJECT_ATTRS = ['st', 'o', 'ou', 'dnqualifier', 'c', +VALID_SUBJECT_ATTRS = ['cn', 'st', 'o', 'ou', 'dnqualifier', 'c', 'serialnumber', 'l', 'title', 'sn', 'givenname', 'initials', 'generationqualifier', 'dc', 'mail', 'uid', 'postaladdress', 'postalcode', 'postofficebox', @@ -130,7 +130,7 @@ class BaseServerCA(common.Installable, core.Group, core.Composite): subject = Knob( str, None, - description="The certificate subject base (default O=<realm-name>)", + description="The CA certificate subject DN (default CN=Certificate Authority,O=<realm-name>)", ) @subject.validator diff --git a/ipaserver/install/server/install.py b/ipaserver/install/server/install.py index c0c676b870b481696ae75742c7bf88074b0ecf9c..c3c4fce8f40ff52a6fb4f23a59feaa2bdeaa286b 100644 --- a/ipaserver/install/server/install.py +++ b/ipaserver/install/server/install.py @@ -238,7 +238,7 @@ def check_dirsrv(unattended): sys.exit(1) -def set_subject_in_config(realm_name, dm_password, suffix, subject_base): +def set_subject_base_in_config(realm_name, dm_password, suffix, subject_base): ldapuri = 'ldapi://%%2fvar%%2frun%%2fslapd-%s.socket' % ( installutils.realm_to_serverid(realm_name) ) @@ -479,7 +479,10 @@ def install_check(installer): realm_name = options.realm_name.upper() if not options.subject: - options.subject = DN(('O', realm_name)) + options.subject = installutils.default_ca_subject_dn(realm_name) + if not options.external_ca: + options.subject = installutils.normalize_dogtag_ca_subject_dn( + options.subject) if options.http_cert_files: if options.http_pin is None: @@ -733,7 +736,7 @@ def install(installer): ds.create_instance(realm_name, host_name, domain_name, dm_password, dirsrv_pkcs12_info, idstart=options.idstart, idmax=options.idmax, - subject_base=options.subject, + subject=options.subject, hbac_allow=not options.no_hbac_allow) else: ds = dsinstance.DsInstance(fstore=fstore, @@ -743,7 +746,7 @@ def install(installer): ds.create_instance(realm_name, host_name, domain_name, dm_password, idstart=options.idstart, idmax=options.idmax, - subject_base=options.subject, + subject=options.subject, hbac_allow=not options.no_hbac_allow) ntpinstance.ntp_ldap_enable(host_name, ds.suffix, realm_name) @@ -784,6 +787,7 @@ def install(installer): ds.enable_ssl() krb = krbinstance.KrbInstance(fstore) + subject_base = ipautil.extract_ca_subject_base(options.subject, realm_name) if options.pkinit_cert_files: krb.create_instance(realm_name, host_name, domain_name, dm_password, master_password, @@ -835,8 +839,9 @@ def install(installer): os.chmod(CACERT, 0o644) ca_db.publish_ca_cert(CACERT) - set_subject_in_config(realm_name, dm_password, - ipautil.realm_to_suffix(realm_name), options.subject) + set_subject_base_in_config( + realm_name, dm_password, + ipautil.realm_to_suffix(realm_name), subject_base) # Apply any LDAP updates. Needs to be done after the configuration file # is created diff --git a/ipaserver/install/server/replicainstall.py b/ipaserver/install/server/replicainstall.py index 9d05a0be5a2679d825b4ee6bc2ea55ed358e8ff9..84bfb9966f11e628a76de74a266245b79c5afe44 100644 --- a/ipaserver/install/server/replicainstall.py +++ b/ipaserver/install/server/replicainstall.py @@ -19,6 +19,7 @@ import tempfile import six from ipapython import ipaldap, ipautil, sysrestore +from ipapython.certdb import get_ca_nickname from ipapython.dn import DN from ipapython.install.common import step from ipapython.install.core import Knob @@ -71,7 +72,7 @@ def make_pkcs12_info(directory, cert_name, password_name): return None -def install_http_certs(config, fstore, remote_api): +def install_http_certs(config, fstore, remote_api, subject_base): # Obtain keytab for the HTTP service fstore.backup_file(paths.IPA_KEYTAB) @@ -89,8 +90,7 @@ def install_http_certs(config, fstore, remote_api): # Obtain certificate for the HTTP service nssdir = certs.NSS_DIR - subject = DN(('O', config.realm_name)) - db = certs.CertDB(config.realm_name, nssdir=nssdir, subject_base=subject) + db = certs.CertDB(config.realm_name, nssdir=nssdir, subject_base=subject_base) db.request_service_cert('Server-Cert', principal, config.host_name, True) # FIXME: need Signing-Cert too ? @@ -119,7 +119,7 @@ def install_replica_ds(config, options, ca_is_configured, remote_api, fqdn=config.host_name, domain_name=config.domain_name, dm_password=config.dirman_password, - subject_base=config.subject_base, + subject=options.subject, pkcs12_info=pkcs12_info, ca_is_configured=ca_is_configured, ca_file=ca_file, @@ -625,6 +625,12 @@ def install_check(installer): finally: shutil.rmtree(tmp_db_dir) + # TODO look up CA subject name (needed for DS certmap.conf) + #ipa_ca_nickname = get_ca_nickname(config.realm_name) + #db = certs.CertDB(config.realm_name, nssdir=paths.IPA_NSSDB_DIR) + #cert = db.get_cert_from_db(ipa_ca_nickname) + #options.subject = unicode(cert.subject) + ldapuri = 'ldaps://%s' % ipautil.format_netloc(config.master_host_name) remote_api = create_api(mode=None) remote_api.bootstrap(in_server=True, context='installer', @@ -717,7 +723,6 @@ def install_check(installer): if options.setup_ca: options.realm_name = config.realm_name options.host_name = config.host_name - options.subject = config.subject_base ca.install_check(False, config, options) if config.setup_kra: @@ -1256,6 +1261,12 @@ def promote_check(installer): if subject_base is not None: config.subject_base = DN(subject_base) + # look up CA subject name (needed for DS certmap.conf) + ipa_ca_nickname = get_ca_nickname(config.realm_name) + db = certs.CertDB(config.realm_name, nssdir=paths.IPA_NSSDB_DIR) + cert = db.get_cert_from_db(ipa_ca_nickname) + options.subject = unicode(x509.load_certificate(cert).subject) + # Find if any server has a CA ca_host = service.find_providing_server('CA', conn, api.env.server) if ca_host is not None: @@ -1289,7 +1300,7 @@ def promote_check(installer): options.realm_name = config.realm_name options.host_name = config.host_name - options.subject = config.subject_base + ca.install_check(False, None, options) if config.setup_kra: @@ -1419,7 +1430,7 @@ def promote(installer): # Must install http certs before changing ipa configuration file # or certmonger will fail to contact the peer master - install_http_certs(config, fstore, remote_api) + install_http_certs(config, fstore, remote_api, config.subject_base) ntpinstance.ntp_ldap_enable(config.host_name, ds.suffix, remote_api.env.realm) @@ -1507,7 +1518,7 @@ def promote(installer): host_name=config.host_name, dm_password=config.dirman_password) ca.configure_replica(config.ca_host_name, - subject_base=config.subject_base, + subject=options.subject, ca_cert_bundle=ca_data) if options.setup_kra: -- 2.5.5
-- Manage your subscription for the Freeipa-devel mailing list: https://www.redhat.com/mailman/listinfo/freeipa-devel Contribute to FreeIPA: http://www.freeipa.org/page/Contribute/Code