summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFraser Tweedale <ftweedal@redhat.com>2016-11-16 20:49:36 +1000
committerJan Cholasta <jcholast@redhat.com>2017-01-11 15:26:20 +0100
commit3d01ec14c6e36fa962d0c54b2e08df0ecd401bd6 (patch)
tree7aa59616dbb3b5a420d8e4509bb108ae314794c5
parent09a65df6842411d42966111e50924df3de0b7031 (diff)
downloadfreeipa-3d01ec14c6e36fa962d0c54b2e08df0ecd401bd6.tar.gz
freeipa-3d01ec14c6e36fa962d0c54b2e08df0ecd401bd6.tar.xz
freeipa-3d01ec14c6e36fa962d0c54b2e08df0ecd401bd6.zip
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-base option. The RDN "CN=Certificate Authority" is appended to form the subject DN, and this composition is widely assumed. 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. Specifically: - Add the --ca-subject option for specifying the full IPA CA subject DN. Defaults to "CN=Certificate Authority, O=$SUBJECT_BASE". - ipa-ca-install, when installing a CA in a previous CA-less topology, updates DS certmap.conf with the new new CA subject DN. - DsInstance.find_subject_base no longer looks in certmap.conf, because the CA subject DN can be unrelated to the subject base. Fixes: https://fedorahosted.org/freeipa/ticket/2614 Reviewed-By: Jan Cholasta <jcholast@redhat.com>
-rwxr-xr-xinstall/tools/ipa-ca-install18
-rw-r--r--install/tools/man/ipa-ca-install.16
-rw-r--r--install/tools/man/ipa-server-install.13
-rw-r--r--ipaserver/install/ca.py123
-rw-r--r--ipaserver/install/cainstance.py14
-rw-r--r--ipaserver/install/certs.py20
-rw-r--r--ipaserver/install/dsinstance.py67
-rw-r--r--ipaserver/install/installutils.py4
-rw-r--r--ipaserver/install/ipa_cacert_manage.py4
-rw-r--r--ipaserver/install/krainstance.py7
-rw-r--r--ipaserver/install/server/__init__.py3
-rw-r--r--ipaserver/install/server/install.py8
-rw-r--r--ipaserver/install/server/replicainstall.py19
13 files changed, 198 insertions, 98 deletions
diff --git a/install/tools/ipa-ca-install b/install/tools/ipa-ca-install
index 3451a8e0a..29952a420 100755
--- a/install/tools/ipa-ca-install
+++ b/install/tools/ipa-ca-install
@@ -81,6 +81,11 @@ def parse_options():
help=(
"The certificate subject base "
"(default O=<realm-name>)"))
+ parser.add_option("--ca-subject", dest="ca_subject",
+ default=None,
+ help=(
+ "The CA certificate subject DN "
+ "(default CN=Certificate Authority,O=<realm-name>)"))
options, args = parser.parse_args()
safe_options = parser.get_safe_opts(options)
@@ -177,7 +182,6 @@ 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_base = config.subject_base
if os.path.exists(cafile):
options.ca_cert_file = cafile
else:
@@ -206,6 +210,18 @@ def install_master(safe_options, options):
if not options.subject_base:
options.subject_base = installutils.default_subject_base(api.env.realm)
+ if not options.ca_subject:
+ options.ca_subject = installutils.default_ca_subject_dn(
+ options.subject_base)
+
+ try:
+ ca.subject_validator(ca.VALID_SUBJECT_BASE_ATTRS, options.subject_base)
+ except ValueError as e:
+ sys.exit("Subject base: {}".format(e.message))
+ try:
+ ca.subject_validator(ca.VALID_SUBJECT_ATTRS, options.ca_subject)
+ except ValueError as e:
+ sys.exit("CA subject: {}".format(e.message))
ca.install_check(True, None, options)
ca.install(True, None, options)
diff --git a/install/tools/man/ipa-ca-install.1 b/install/tools/man/ipa-ca-install.1
index aa186987a..16e5431b6 100644
--- a/install/tools/man/ipa-ca-install.1
+++ b/install/tools/man/ipa-ca-install.1
@@ -46,6 +46,12 @@ Type of the external CA. Possible values are "generic", "ms-cs". Default value i
\fB\-\-external\-cert\-file\fR=\fIFILE\fR
File containing the IPA CA certificate and the external CA certificate chain. The file is accepted in PEM and DER certificate and PKCS#7 certificate chain formats. This option may be used multiple times.
.TP
+\fB\-\-ca\-subject\fR=\fISUBJECT\fR
+The CA certificate subject DN (default CN=Certificate Authority,O=REALM.NAME)
+.TP
+\fB\-\-subject\-base\fR=\fISUBJECT\fR
+The subject base for certificates issued by IPA (default 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.
.TP
diff --git a/install/tools/man/ipa-server-install.1 b/install/tools/man/ipa-server-install.1
index 07f772ad4..9568888ff 100644
--- a/install/tools/man/ipa-server-install.1
+++ b/install/tools/man/ipa-server-install.1
@@ -122,6 +122,9 @@ Name of the Kerberos KDC SSL certificate to install
\fB\-\-ca\-cert\-file\fR=\fIFILE\fR
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\-\-ca\-subject\fR=\fISUBJECT\fR
+The CA certificate subject DN (default CN=Certificate Authority,O=REALM.NAME)
+.TP
\fB\-\-subject\-base\fR=\fISUBJECT\fR
The subject base for certificates issued by IPA (default O=REALM.NAME)
.TP
diff --git a/ipaserver/install/ca.py b/ipaserver/install/ca.py
index 7b67110e2..cc52b9053 100644
--- a/ipaserver/install/ca.py
+++ b/ipaserver/install/ca.py
@@ -13,6 +13,7 @@ import os.path
import six
+from ipalib.constants import IPA_CA_CN
from ipalib.install import certstore
from ipalib.install.service import enroll_only, master_install_only, replica_install_only
from ipaserver.install import sysupgrade
@@ -28,7 +29,7 @@ from ipaplatform import services
from ipaplatform.paths import paths
from ipaserver.install import installutils, certs
from ipaserver.install.replication import replica_conn_check
-from ipalib import api, x509
+from ipalib import api, errors, x509
from ipapython.dn import DN
from ipapython.ipa_log_manager import root_logger
@@ -37,18 +38,53 @@ from . import conncheck, dogtag
if six.PY3:
unicode = str
-VALID_SUBJECT_ATTRS = ['st', 'o', 'ou', 'dnqualifier', 'c',
- 'serialnumber', 'l', 'title', 'sn', 'givenname',
- 'initials', 'generationqualifier', 'dc', 'mail',
- 'uid', 'postaladdress', 'postalcode', 'postofficebox',
- 'houseidentifier', 'e', 'street', 'pseudonym',
- 'incorporationlocality', 'incorporationstate',
- 'incorporationcountry', 'businesscategory']
+VALID_SUBJECT_BASE_ATTRS = {
+ 'st', 'o', 'ou', 'dnqualifier', 'c', 'serialnumber', 'l', 'title', 'sn',
+ 'givenname', 'initials', 'generationqualifier', 'dc', 'mail', 'uid',
+ 'postaladdress', 'postalcode', 'postofficebox', 'houseidentifier', 'e',
+ 'street', 'pseudonym', 'incorporationlocality', 'incorporationstate',
+ 'incorporationcountry', 'businesscategory',
+}
+VALID_SUBJECT_ATTRS = {'cn'} | VALID_SUBJECT_BASE_ATTRS
external_cert_file = None
external_ca_file = None
+def subject_validator(valid_attrs, value):
+ v = unicode(value, 'utf-8')
+ if any(ord(c) < 0x20 for c in v):
+ raise ValueError("must not contain control characters")
+ if '&' in v:
+ raise ValueError("must not contain an ampersand (\"&\")")
+ try:
+ dn = DN(v)
+ for rdn in dn:
+ if rdn.attr.lower() not in valid_attrs:
+ raise ValueError("invalid attribute: \"%s\"" % rdn.attr)
+ except ValueError as e:
+ raise ValueError("invalid DN: %s" % e)
+
+
+def lookup_ca_subject(api, subject_base):
+ dn = DN(('cn', IPA_CA_CN), api.env.container_ca, api.env.basedn)
+ try:
+ # we do not use api.Command.ca_show because it attempts to
+ # talk to the CA (to read certificate / chain), but the RA
+ # backend may be unavailable (ipa-replica-install) or unusable
+ # due to RA Agent cert not yet created (ipa-ca-install).
+ ca_subject = api.Backend.ldap2.get_entry(dn)['ipacasubjectdn'][0]
+ except errors.NotFound:
+ # if the entry doesn't exist, we are dealing with a pre-v4.4
+ # installation, where the default CA subject was always based
+ # on the subject_base.
+ #
+ # installutils.default_ca_subject_dn is NOT used here in
+ # case the default changes in the future.
+ ca_subject = DN(('CN', 'Certificate Authority'), subject_base)
+ return six.text_type(ca_subject)
+
+
def set_subject_base_in_config(subject_base):
entry_attrs = api.Backend.ldap2.get_ipa_config()
entry_attrs['ipacertificatesubjectbase'] = [str(subject_base)]
@@ -62,12 +98,23 @@ def install_check(standalone, replica_config, options):
global external_cert_file
global external_ca_file
- if replica_config is not None and not replica_config.setup_ca:
- return
-
realm_name = options.realm_name
host_name = options.host_name
- subject_base = options.subject_base
+
+ if replica_config is None:
+ options._subject_base = options.subject_base
+ options._ca_subject = options.ca_subject
+ else:
+ # during replica install, this gets invoked before local DS is
+ # available, so use the remote api.
+ _api = api if standalone else options._remote_api
+
+ # for replica-install the knobs cannot be written, hence leading '_'
+ options._subject_base = six.text_type(replica_config.subject_base)
+ options._ca_subject = lookup_ca_subject(_api, options._subject_base)
+
+ if replica_config is not None and not replica_config.setup_ca:
+ return
if replica_config is not None:
if standalone and api.env.ra_plugin == 'selfsign':
@@ -110,9 +157,7 @@ def install_check(standalone, replica_config, options):
"--external-ca.")
external_cert_file, external_ca_file = installutils.load_external_cert(
- options.external_cert_files,
- DN(('CN', 'Certificate Authority'), options.subject_base)
- )
+ options.external_cert_files, options._ca_subject)
elif options.external_ca:
if cainstance.is_step_one_done():
raise ScriptError(
@@ -132,8 +177,9 @@ def install_check(standalone, replica_config, options):
if standalone:
dirname = dsinstance.config_dirname(
installutils.realm_to_serverid(realm_name))
- cadb = certs.CertDB(realm_name, subject_base=subject_base)
- dsdb = certs.CertDB(realm_name, nssdir=dirname, subject_base=subject_base)
+ cadb = certs.CertDB(realm_name, subject_base=options._subject_base)
+ dsdb = certs.CertDB(
+ realm_name, nssdir=dirname, subject_base=options._subject_base)
for db in (cadb, dsdb):
for nickname, _trust_flags in db.list_certs():
@@ -147,8 +193,8 @@ def install_check(standalone, replica_config, options):
if not cert:
continue
subject = DN(x509.load_certificate(cert).subject)
- if subject in (DN('CN=Certificate Authority', subject_base),
- DN('CN=IPA RA', subject_base)):
+ if subject in (DN(options._ca_subject),
+ DN('CN=IPA RA', options._subject_base)):
raise ScriptError(
"Certificate with subject %s is present in %s, "
"cannot continue." % (subject, db.secdir))
@@ -163,10 +209,10 @@ def install_step_0(standalone, replica_config, options):
realm_name = options.realm_name
dm_password = options.dm_password
host_name = options.host_name
+ ca_subject = options._ca_subject
+ subject_base = options._subject_base
if replica_config is None:
- subject_base = options.subject_base
-
ca_signing_algorithm = options.ca_signing_algorithm
if options.external_ca:
ca_type = options.external_ca_type
@@ -198,8 +244,6 @@ def install_step_0(standalone, replica_config, options):
cafile,
replica_config.dirman_password)
- subject_base = replica_config.subject_base
-
ca_signing_algorithm = None
ca_type = None
csr_file = None
@@ -214,16 +258,18 @@ def install_step_0(standalone, replica_config, options):
promote = options.promote
# if upgrading from CA-less to CA-ful, need to rewrite
- # subject_base configuration
+ # certmap.conf and subject_base configuration
#
set_subject_base_in_config(subject_base)
sysupgrade.set_upgrade_state(
'certmap.conf', 'subject_base', str(subject_base))
+ dsinstance.write_certmap_conf(realm_name, ca_subject)
ca = cainstance.CAInstance(realm_name, certs.NSS_DIR,
host_name=host_name)
ca.configure_instance(host_name, dm_password, dm_password,
subject_base=subject_base,
+ ca_subject=ca_subject,
ca_signing_algorithm=ca_signing_algorithm,
ca_type=ca_type,
csr_file=csr_file,
@@ -244,8 +290,7 @@ def install_step_1(standalone, replica_config, options):
realm_name = options.realm_name
host_name = options.host_name
- subject_base = options.subject_base
-
+ subject_base = options._subject_base
basedn = ipautil.realm_to_suffix(realm_name)
ca = cainstance.CAInstance(realm_name, certs.NSS_DIR, host_name=host_name)
@@ -396,18 +441,20 @@ class CAInstallInterface(dogtag.DogtagInstallInterface,
@subject_base.validator
def subject_base(self, value):
- v = unicode(value, 'utf-8')
- if any(ord(c) < 0x20 for c in v):
- raise ValueError("must not contain control characters")
- if '&' in v:
- raise ValueError("must not contain an ampersand (\"&\")")
- try:
- dn = DN(v)
- for rdn in dn:
- if rdn.attr.lower() not in VALID_SUBJECT_ATTRS:
- raise ValueError("invalid attribute: \"%s\"" % rdn.attr)
- except ValueError as e:
- raise ValueError("invalid subject base format: %s" % e)
+ subject_validator(VALID_SUBJECT_BASE_ATTRS, value)
+
+ ca_subject = knob(
+ str, None,
+ description=(
+ "The CA certificate subject DN "
+ "(default CN=Certificate Authority,O=<realm-name>)"
+ ),
+ )
+ ca_subject = master_install_only(ca_subject)
+
+ @ca_subject.validator
+ def ca_subject(self, value):
+ subject_validator(VALID_SUBJECT_ATTRS, value)
ca_signing_algorithm = knob(
CASigningAlgorithm, None,
diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py
index 4f01f83e4..f933479df 100644
--- a/ipaserver/install/cainstance.py
+++ b/ipaserver/install/cainstance.py
@@ -330,7 +330,8 @@ 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_base=None, ca_subject=None,
+ ca_signing_algorithm=None,
ca_type=None, ra_p12=None, ra_only=False,
promote=False, use_ldaps=False):
"""Create a CA instance.
@@ -355,6 +356,8 @@ class CAInstance(DogtagInstance):
self.subject_base = \
subject_base or installutils.default_subject_base(self.realm)
+ self.ca_subject = \
+ ca_subject or installutils.default_ca_subject_dn(self.subject_base)
if ca_signing_algorithm is None:
self.ca_signing_algorithm = 'SHA256withRSA'
@@ -514,8 +517,9 @@ class CAInstance(DogtagInstance):
str(DN(('cn', self.fqdn), self.subject_base)))
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)))
+ config.set(
+ "CA", "pki_ca_signing_subject_dn",
+ str(self.ca_subject))
# Certificate nicknames
config.set("CA", "pki_subsystem_nickname", "subsystemCert cert-pki-ca")
@@ -701,7 +705,7 @@ class CAInstance(DogtagInstance):
userCertificate=[cert_data],
description=['2;%s;%s;%s' % (
cert.serial,
- DN(('CN', 'Certificate Authority'), self.subject_base),
+ DN(self.ca_subject),
DN(('CN', 'IPA RA'), self.subject_base))])
conn.add_entry(entry)
@@ -754,7 +758,7 @@ class CAInstance(DogtagInstance):
# Ok, now we have all the certificates in certs, walk through it
# and pull out each certificate and add it to our database
- ca_dn = DN(('CN','Certificate Authority'), self.subject_base)
+ ca_dn = DN(self.ca_subject)
for cert in certlist:
try:
chain_fd, chain_name = tempfile.mkstemp()
diff --git a/ipaserver/install/certs.py b/ipaserver/install/certs.py
index 85c2d06c0..80918d431 100644
--- a/ipaserver/install/certs.py
+++ b/ipaserver/install/certs.py
@@ -70,9 +70,19 @@ class CertDB(object):
This class knows IPA-specific details such as nssdir location, or the
CA cert name.
+
+ ``subject_base``
+ Realm subject base DN. This argument is required when creating
+ server or object signing certs.
+ ``ca_subject``
+ IPA CA subject DN. This argument is required when importing
+ CA certificates into the certificate database.
+
"""
# TODO: Remove all selfsign code
- def __init__(self, realm, nssdir=NSS_DIR, fstore=None, host_name=None, subject_base=None):
+ def __init__(
+ self, realm, nssdir=NSS_DIR, fstore=None, host_name=None,
+ subject_base=None, ca_subject=None):
self.nssdb = NSSDatabase(nssdir)
self.secdir = nssdir
@@ -91,15 +101,13 @@ class CertDB(object):
self.certreq_fname = None
self.certder_fname = None
self.host_name = host_name
+ self.ca_subject = ca_subject
self.subject_base = subject_base
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"
@@ -118,6 +126,7 @@ class CertDB(object):
else:
self.fstore = sysrestore.FileStore(paths.SYSRESTORE)
+ ca_subject = ipautil.dn_attribute_property('_ca_subject')
subject_base = ipautil.dn_attribute_property('_subject_base')
def __del__(self):
@@ -248,13 +257,12 @@ class CertDB(object):
certs = fd.read()
fd.close()
- ca_dn = DN(('CN','Certificate Authority'), self.subject_base)
st = 0
while True:
try:
(cert, st) = find_cert_from_txt(certs, st)
_rdn, subject_dn = get_cert_nickname(cert)
- if subject_dn == ca_dn:
+ if subject_dn == self.ca_subject:
nick = get_ca_nickname(self.realm)
else:
nick = str(subject_dn)
diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py
index d23a2aa6f..6e7019a08 100644
--- a/ipaserver/install/dsinstance.py
+++ b/ipaserver/install/dsinstance.py
@@ -241,6 +241,7 @@ class DsInstance(service.Service):
self.dercert = None
self.idstart = None
self.idmax = None
+ self.ca_subject = None
self.subject_base = None
self.open_ports = []
self.run_init_memberof = True
@@ -301,7 +302,8 @@ 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_base, ca_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)
@@ -309,6 +311,7 @@ class DsInstance(service.Service):
self.dm_password = dm_password
self.domain = domain_name
self.subject_base = subject_base
+ self.ca_subject = ca_subject
self.idstart = idstart
self.idmax = idmax
self.pkcs12_info = pkcs12_info
@@ -320,11 +323,13 @@ 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_base=None, ca_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_base, ca_subject,
+ idstart, idmax, pkcs12_info, ca_file=ca_file)
self.__common_setup()
self.step("restarting directory server", self.__restart_instance)
@@ -358,8 +363,9 @@ 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,
- pkcs12_info=None, ca_file=None,
+ domain_name, dm_password,
+ subject_base, ca_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
# depleted by the DNA plugin and the replica will go and get a
@@ -374,6 +380,7 @@ class DsInstance(service.Service):
domain_name=domain_name,
dm_password=dm_password,
subject_base=subject_base,
+ ca_subject=ca_subject,
idstart=idstart,
idmax=idmax,
pkcs12_info=pkcs12_info,
@@ -777,7 +784,12 @@ class DsInstance(service.Service):
def __enable_ssl(self):
dirname = config_dirname(self.serverid)
- dsdb = certs.CertDB(self.realm, nssdir=dirname, subject_base=self.subject_base)
+ dsdb = certs.CertDB(
+ self.realm,
+ nssdir=dirname,
+ subject_base=self.subject_base,
+ ca_subject=self.ca_subject,
+ )
if self.pkcs12_info:
if self.ca_is_configured:
trust_flags = 'CT,C,C'
@@ -920,8 +932,7 @@ class DsInstance(service.Service):
self._ldap_mod("indices.ldif")
def __certmap_conf(self):
- ca_subject = 'CN=Certificate Authority,' + str(self.subject_base)
- write_certmap_conf(self.realm, ca_subject)
+ write_certmap_conf(self.realm, self.ca_subject)
sysupgrade.set_upgrade_state(
'certmap.conf',
'subject_base',
@@ -1064,7 +1075,12 @@ class DsInstance(service.Service):
self.stop()
dirname = config_dirname(installutils.realm_to_serverid(self.realm))
- certdb = certs.CertDB(self.realm, nssdir=dirname, subject_base=self.subject_base)
+ certdb = certs.CertDB(
+ self.realm,
+ nssdir=dirname,
+ subject_base=self.subject_base,
+ ca_subject=self.ca_subject,
+ )
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
@@ -1163,8 +1179,7 @@ class DsInstance(service.Service):
Try to find the current value of certificate subject base.
1) Look in sysupgrade first
2) If no value is found there, look in DS (start DS if necessary)
- 3) Last resort, look in the certmap.conf itself
- 4) If all fails, log loudly and return None
+ 3) If all fails, log loudly and return None
Note that this method can only be executed AFTER the ipa server
is configured, the api is initialized elsewhere and
@@ -1206,27 +1221,6 @@ class DsInstance(service.Service):
root_logger.error('Cannot connect to DS to find certificate '
'subject base: %s', e)
- if not subject_base:
- root_logger.debug('Unable to find certificate subject base in DS')
- root_logger.debug('Trying to find certificate subject base in '
- 'certmap.conf')
-
- certmap_dir = config_dirname(
- installutils.realm_to_serverid(api.env.realm)
- )
- try:
- with open(os.path.join(certmap_dir, 'certmap.conf')) as f:
- for line in f:
- if line.startswith('certmap ipaca'):
- subject_base = line.strip().split(',')[-1]
- root_logger.debug(
- 'Found certificate subject base in certmap.conf: '
- '%s', subject_base)
-
- except IOError as e:
- root_logger.error('Cannot open certmap.conf to find certificate '
- 'subject base: %s', e.strerror)
-
if subject_base:
return subject_base
@@ -1248,10 +1242,13 @@ class DsInstance(service.Service):
replacevars=vardict)
def __get_ds_cert(self):
- subject = self.subject_base \
- or installutils.default_subject_base(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,
+ ca_subject=self.ca_subject,
+ )
db.create_from_cacert(paths.IPA_CA_CRT)
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 ca7a5d6ac..0d8a574ae 100644
--- a/ipaserver/install/installutils.py
+++ b/ipaserver/install/installutils.py
@@ -1480,3 +1480,7 @@ def restart_dirsrv(instance_name="", capture_output=True):
def default_subject_base(realm_name):
return DN(('O', realm_name))
+
+
+def default_ca_subject_dn(subject_base):
+ return DN(('CN', 'Certificate Authority'), subject_base)
diff --git a/ipaserver/install/ipa_cacert_manage.py b/ipaserver/install/ipa_cacert_manage.py
index 4082dfa4e..1d1ae2f21 100644
--- a/ipaserver/install/ipa_cacert_manage.py
+++ b/ipaserver/install/ipa_cacert_manage.py
@@ -201,9 +201,7 @@ class CACertManage(admintool.AdminTool):
)
cert_file, ca_file = installutils.load_external_cert(
- options.external_cert_files,
- DN(('CN', 'Certificate Authority'), x509.subject_base())
- )
+ options.external_cert_files, DN(old_cert_obj.subject))
with open(cert_file.name) as f:
new_cert_data = f.read()
diff --git a/ipaserver/install/krainstance.py b/ipaserver/install/krainstance.py
index 1d9c2b773..1f38c8636 100644
--- a/ipaserver/install/krainstance.py
+++ b/ipaserver/install/krainstance.py
@@ -77,7 +77,8 @@ class KRAInstance(DogtagInstance):
def configure_instance(self, realm_name, host_name, dm_password,
admin_password, pkcs12_info=None, master_host=None,
- subject_base=None, ra_only=False, promote=False):
+ subject_base=None, subject=None,
+ ra_only=False, promote=False):
"""Create a KRA instance.
To create a clone, pass in pkcs12_info.
@@ -93,6 +94,8 @@ class KRAInstance(DogtagInstance):
self.subject_base = \
subject_base or installutils.default_subject_base(realm_name)
+ self.subject = \
+ subject or installutils.default_ca_subject_dn(self.subject_base)
self.realm = realm_name
self.suffix = ipautil.realm_to_suffix(realm_name)
@@ -307,7 +310,7 @@ class KRAInstance(DogtagInstance):
userCertificate=[cert_data],
description=['2;%s;%s;%s' % (
cert.serial,
- 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/__init__.py b/ipaserver/install/server/__init__.py
index 28cdd066a..86cb4a9ef 100644
--- a/ipaserver/install/server/__init__.py
+++ b/ipaserver/install/server/__init__.py
@@ -573,7 +573,8 @@ class ServerReplicaInstall(ServerReplicaInstallInterface):
Server replica installer
"""
- subject = None
+ subject_base = None
+ ca_subject = None
admin_password = knob(
bases=ServerReplicaInstallInterface.admin_password,
diff --git a/ipaserver/install/server/install.py b/ipaserver/install/server/install.py
index aae8d367a..db765d60b 100644
--- a/ipaserver/install/server/install.py
+++ b/ipaserver/install/server/install.py
@@ -467,6 +467,10 @@ def install_check(installer):
if not options.subject_base:
options.subject_base = installutils.default_subject_base(realm_name)
+ if not options.ca_subject:
+ options.ca_subject = \
+ installutils.default_ca_subject_dn(options.subject_base)
+
if options.http_cert_files:
if options.http_pin is None:
options.http_pin = installutils.read_password(
@@ -726,6 +730,7 @@ def install(installer):
dm_password, dirsrv_pkcs12_info,
idstart=options.idstart, idmax=options.idmax,
subject_base=options.subject_base,
+ ca_subject=options.ca_subject,
hbac_allow=not options.no_hbac_allow)
else:
ds = dsinstance.DsInstance(fstore=fstore,
@@ -736,6 +741,7 @@ def install(installer):
dm_password,
idstart=options.idstart, idmax=options.idmax,
subject_base=options.subject_base,
+ ca_subject=options.ca_subject,
hbac_allow=not options.no_hbac_allow)
ntpinstance.ntp_ldap_enable(host_name, ds.suffix, realm_name)
@@ -747,7 +753,7 @@ def install(installer):
installer._ds = ds
ds.init_info(
realm_name, host_name, domain_name, dm_password,
- options.subject_base, 1101, 1100, None)
+ options.subject_base, options.ca_subject, 1101, 1100, None)
if setup_ca:
if not options.external_cert_files and options.external_ca:
diff --git a/ipaserver/install/server/replicainstall.py b/ipaserver/install/server/replicainstall.py
index 16352a5c8..18222c80e 100644
--- a/ipaserver/install/server/replicainstall.py
+++ b/ipaserver/install/server/replicainstall.py
@@ -78,8 +78,7 @@ def install_http_certs(host_name, realm_name, subject_base):
principal = 'HTTP/%s@%s' % (host_name, realm_name)
# Obtain certificate for the HTTP service
nssdir = certs.NSS_DIR
- subject = subject_base or installutils.default_subject_base(realm_name)
- db = certs.CertDB(realm_name, nssdir=nssdir, subject_base=subject)
+ db = certs.CertDB(realm_name, nssdir=nssdir, subject_base=subject_base)
db.request_service_cert('Server-Cert', principal, host_name, True)
@@ -94,6 +93,11 @@ def install_replica_ds(config, options, ca_is_configured, remote_api,
pkcs12_info = make_pkcs12_info(config.dir, "dscert.p12",
"dirsrv_pin.txt")
+ if ca_is_configured:
+ ca_subject = ca.lookup_ca_subject(remote_api, config.subject_base)
+ else:
+ ca_subject = installutils.default_ca_subject_dn(config.subject_base)
+
ds = dsinstance.DsInstance(
config_ldif=options.dirsrv_config_file)
ds.create_replica(
@@ -103,6 +107,7 @@ def install_replica_ds(config, options, ca_is_configured, remote_api,
domain_name=config.domain_name,
dm_password=config.dirman_password,
subject_base=config.subject_base,
+ ca_subject=ca_subject,
pkcs12_info=pkcs12_info,
ca_is_configured=ca_is_configured,
ca_file=ca_file,
@@ -703,6 +708,10 @@ def install_check(installer):
raise RuntimeError("CA cert file is not available. Please run "
"ipa-replica-prepare to create a new replica file.")
+ # look up CA subject name (needed for DS certmap.conf)
+ options.ca_subject = unicode(
+ DN(x509.load_certificate_from_file(cafile).subject))
+
for pkcs12_name, pin_name in (('dscert.p12', 'dirsrv_pin.txt'),
('httpcert.p12', 'http_pin.txt')):
pkcs12_info = make_pkcs12_info(config.dir, pkcs12_name, pin_name)
@@ -737,6 +746,7 @@ def install_check(installer):
confdir=paths.ETC_IPA,
ldap_uri=ldapuri)
remote_api.finalize()
+ installer._remote_api = remote_api
conn = remote_api.Backend.ldap2
replman = None
try:
@@ -796,7 +806,6 @@ def install_check(installer):
if ca_enabled:
options.realm_name = config.realm_name
options.host_name = config.host_name
- options.subject_base = config.subject_base
ca.install_check(False, config, options)
if kra_enabled:
@@ -855,7 +864,6 @@ def install_check(installer):
installer._ca_enabled = ca_enabled
installer._kra_enabled = kra_enabled
installer._ca_file = cafile
- installer._remote_api = remote_api
installer._fstore = fstore
installer._sstore = sstore
@@ -1067,6 +1075,7 @@ def promote_check(installer):
ldap_uri=ldapuri,
xmlrpc_uri=xmlrpc_uri)
remote_api.finalize()
+ installer._remote_api = remote_api
check_remote_version(remote_api)
@@ -1203,7 +1212,6 @@ def promote_check(installer):
if ca_enabled:
options.realm_name = config.realm_name
options.host_name = config.host_name
- options.subject_base = config.subject_base
ca.install_check(False, config, options)
if kra_enabled:
@@ -1263,7 +1271,6 @@ def promote_check(installer):
installer._fstore = fstore
installer._sstore = sstore
installer._config = config
- installer._remote_api = remote_api
installer._add_to_ipaservers = add_to_ipaservers
installer._dirsrv_pkcs12_file = dirsrv_pkcs12_file
installer._dirsrv_pkcs12_info = dirsrv_pkcs12_info