mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-01-11 08:41:55 -06:00
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>
This commit is contained in:
parent
09a65df684
commit
3d01ec14c6
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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()
|
||||
|
@ -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)
|
||||
|
@ -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()
|
||||
|
@ -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)
|
||||
|
@ -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()
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user