mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2024-12-25 08:21:05 -06:00
620036d26e
Profiles and the default CA ACL were not being added during replica install from pre-4.2 servers. Update ipa-replica-install to add these if they are missing. Also update the caacl plugin to prevent deletion of the default CA ACL and instruct the administrator to disable it instead. To ensure that the cainstance installation can add profiles, supply the RA certificate as part of the instance configuration. Certmonger renewal setup is avoided at this point because the NSSDB gets reinitialised later in installation procedure. Also move the addition of the default CA ACL from dsinstance installation to cainstance installation. Fixes: https://fedorahosted.org/freeipa/ticket/5459 Reviewed-By: Jan Cholasta <jcholast@redhat.com>
281 lines
11 KiB
Python
281 lines
11 KiB
Python
#
|
|
# Copyright (C) 2015 FreeIPA Contributors see COPYING for license
|
|
#
|
|
|
|
from __future__ import print_function
|
|
|
|
import sys
|
|
import os.path
|
|
|
|
from six.moves.configparser import RawConfigParser
|
|
|
|
from ipaserver.install import cainstance, dsinstance, bindinstance
|
|
from ipapython import dogtag, ipautil, certdb
|
|
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, certstore, x509
|
|
from ipapython.dn import DN
|
|
from ipapython.ipa_log_manager import root_logger
|
|
|
|
|
|
def install_check(standalone, replica_config, options):
|
|
global external_cert_file
|
|
global external_ca_file
|
|
|
|
realm_name = options.realm_name
|
|
host_name = options.host_name
|
|
subject_base = options.subject
|
|
|
|
if replica_config is not None:
|
|
if standalone and api.env.ra_plugin == 'selfsign':
|
|
sys.exit('A selfsign CA can not be added')
|
|
|
|
if ((not options.promote
|
|
and not ipautil.file_exists(replica_config.dir + "/cacert.p12"))):
|
|
print('CA cannot be installed in CA-less setup.')
|
|
sys.exit(1)
|
|
|
|
if standalone and not options.skip_conncheck:
|
|
principal = options.principal
|
|
replica_conn_check(
|
|
replica_config.master_host_name, host_name, realm_name, True,
|
|
replica_config.ca_ds_port, options.admin_password,
|
|
principal=principal)
|
|
|
|
if options.skip_schema_check or options.promote:
|
|
root_logger.info("Skipping CA DS schema check")
|
|
else:
|
|
cainstance.replica_ca_install_check(replica_config)
|
|
|
|
return
|
|
|
|
if standalone:
|
|
if api.Command.ca_is_enabled()['result']:
|
|
sys.exit(
|
|
"One or more CA masters are already present in IPA realm "
|
|
"'%s'.\nIf you wish to replicate CA to this host, please "
|
|
"re-run 'ipa-ca-install'\nwith a replica file generated on "
|
|
"an existing CA master as argument." % realm_name
|
|
)
|
|
|
|
if options.external_cert_files:
|
|
if not cainstance.is_step_one_done():
|
|
# This can happen if someone passes external_ca_file without
|
|
# already having done the first stage of the CA install.
|
|
print("CA is not installed yet. To install with an external CA "
|
|
"is a two-stage process.\nFirst run the installer with "
|
|
"--external-ca.")
|
|
sys.exit(1)
|
|
|
|
external_cert_file, external_ca_file = installutils.load_external_cert(
|
|
options.external_cert_files, options.subject)
|
|
elif options.external_ca:
|
|
if cainstance.is_step_one_done():
|
|
print("CA is already installed.\nRun the installer with "
|
|
"--external-cert-file.")
|
|
sys.exit(1)
|
|
if ipautil.file_exists(paths.ROOT_IPA_CSR):
|
|
print(("CA CSR file %s already exists.\nIn order to continue "
|
|
"remove the file and run the installer again." %
|
|
paths.ROOT_IPA_CSR))
|
|
sys.exit(1)
|
|
|
|
if not options.external_cert_files:
|
|
if not cainstance.check_port():
|
|
print("IPA requires port 8443 for PKI but it is currently in use.")
|
|
sys.exit("Aborting installation")
|
|
|
|
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)
|
|
|
|
for db in (cadb, dsdb):
|
|
for nickname, trust_flags in db.list_certs():
|
|
if nickname in (certdb.get_ca_nickname(realm_name),
|
|
'ipaCert',
|
|
'Signing-Cert'):
|
|
print(("Certificate with nickname %s is present in %s, "
|
|
"cannot continue." % (nickname, db.secdir)))
|
|
sys.exit(1)
|
|
|
|
cert = db.get_cert_from_db(nickname)
|
|
if not cert:
|
|
continue
|
|
subject = DN(str(x509.get_subject(cert)))
|
|
if subject in (DN('CN=Certificate Authority', subject_base),
|
|
DN('CN=IPA RA', subject_base),
|
|
DN('CN=Object Signing Cert', subject_base)):
|
|
print(("Certificate with subject %s is present in %s, "
|
|
"cannot continue." % (subject, db.secdir)))
|
|
sys.exit(1)
|
|
|
|
|
|
def install(standalone, replica_config, options):
|
|
install_step_0(standalone, replica_config, options)
|
|
install_step_1(standalone, replica_config, options)
|
|
|
|
|
|
def install_step_0(standalone, replica_config, options):
|
|
realm_name = options.realm_name
|
|
domain_name = options.domain_name
|
|
dm_password = options.dm_password
|
|
host_name = options.host_name
|
|
subject_base = options.subject
|
|
|
|
dogtag_constants = dogtag.install_constants
|
|
|
|
if replica_config is not None:
|
|
# Configure the CA if necessary
|
|
if standalone:
|
|
postinstall = True
|
|
else:
|
|
postinstall = False
|
|
|
|
if standalone:
|
|
api.Backend.ldap2.disconnect()
|
|
|
|
cainstance.install_replica_ca(replica_config, postinstall,
|
|
ra_p12=getattr(options, 'ra_p12', None))
|
|
|
|
if standalone and not api.Backend.ldap2.isconnected():
|
|
api.Backend.ldap2.connect(bind_dn=DN(('cn', 'Directory Manager')),
|
|
bind_pw=dm_password)
|
|
|
|
return
|
|
|
|
if options.external_cert_files:
|
|
external = 2
|
|
elif options.external_ca:
|
|
external = 1
|
|
else:
|
|
external = 0
|
|
|
|
ca = cainstance.CAInstance(realm_name, certs.NSS_DIR,
|
|
dogtag_constants=dogtag_constants)
|
|
if standalone:
|
|
ca.create_ra_agent_db = False
|
|
if external == 0:
|
|
ca.configure_instance(host_name, dm_password,
|
|
dm_password, subject_base=subject_base,
|
|
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,
|
|
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,
|
|
ca_signing_algorithm=options.ca_signing_algorithm)
|
|
|
|
|
|
def install_step_1(standalone, replica_config, options):
|
|
realm_name = options.realm_name
|
|
domain_name = options.domain_name
|
|
dm_password = options.dm_password
|
|
host_name = options.host_name
|
|
subject_base = options.subject
|
|
|
|
basedn = ipautil.realm_to_suffix(realm_name)
|
|
|
|
dogtag_constants = dogtag.install_constants
|
|
|
|
ca = cainstance.CAInstance(realm_name, certs.NSS_DIR,
|
|
dogtag_constants=dogtag_constants)
|
|
|
|
if standalone:
|
|
ca.stop(ca.dogtag_constants.PKI_INSTANCE_NAME)
|
|
|
|
# We need to ldap_enable the CA now that DS is up and running
|
|
ca.ldap_enable('CA', host_name, dm_password, basedn, ['caRenewalMaster'])
|
|
|
|
# This is done within stopped_service context, which restarts CA
|
|
ca.enable_client_auth_to_db(dogtag_constants.CS_CFG_PATH)
|
|
|
|
if standalone and replica_config is None:
|
|
serverid = installutils.realm_to_serverid(realm_name)
|
|
dirname = dsinstance.config_dirname(serverid)
|
|
|
|
# Store the new IPA CA cert chain in DS NSS database and LDAP
|
|
cadb = certs.CertDB(realm_name, subject_base=subject_base)
|
|
dsdb = certs.CertDB(realm_name, nssdir=dirname, subject_base=subject_base)
|
|
trust_flags = dict(reversed(cadb.list_certs()))
|
|
trust_chain = cadb.find_root_cert('ipaCert')[:-1]
|
|
for nickname in trust_chain[:-1]:
|
|
cert = cadb.get_cert_from_db(nickname, pem=False)
|
|
dsdb.add_cert(cert, nickname, trust_flags[nickname])
|
|
certstore.put_ca_cert_nss(api.Backend.ldap2, api.env.basedn,
|
|
cert, nickname, trust_flags[nickname])
|
|
|
|
nickname = trust_chain[-1]
|
|
cert = cadb.get_cert_from_db(nickname, pem=False)
|
|
dsdb.add_cert(cert, nickname, trust_flags[nickname])
|
|
certstore.put_ca_cert_nss(api.Backend.ldap2, api.env.basedn,
|
|
cert, nickname, trust_flags[nickname],
|
|
config_ipa=True, config_compat=True)
|
|
|
|
|
|
api.Backend.ldap2.disconnect()
|
|
|
|
# Restart DS
|
|
services.knownservices.dirsrv.restart(serverid)
|
|
|
|
api.Backend.ldap2.connect(bind_dn=DN(('cn', 'Directory Manager')),
|
|
bind_pw=dm_password)
|
|
|
|
# Store DS CA cert in Dogtag NSS database
|
|
dogtagdb = certs.CertDB(realm_name, nssdir=dogtag_constants.ALIAS_DIR)
|
|
trust_flags = dict(reversed(dsdb.list_certs()))
|
|
server_certs = dsdb.find_server_certs()
|
|
trust_chain = dsdb.find_root_cert(server_certs[0][0])[:-1]
|
|
nickname = trust_chain[-1]
|
|
cert = dsdb.get_cert_from_db(nickname)
|
|
dogtagdb.add_cert(cert, nickname, trust_flags[nickname])
|
|
|
|
if standalone:
|
|
ca.start(ca.dogtag_constants.PKI_INSTANCE_NAME)
|
|
|
|
# Update config file
|
|
try:
|
|
parser = RawConfigParser()
|
|
parser.read(paths.IPA_DEFAULT_CONF)
|
|
parser.set('global', 'enable_ra', 'True')
|
|
parser.set('global', 'ra_plugin', 'dogtag')
|
|
parser.set('global', 'dogtag_version',
|
|
str(dogtag_constants.DOGTAG_VERSION))
|
|
with open(paths.IPA_DEFAULT_CONF, 'w') as f:
|
|
parser.write(f)
|
|
except IOError as e:
|
|
print("Failed to update /etc/ipa/default.conf")
|
|
root_logger.error(str(e))
|
|
sys.exit(1)
|
|
|
|
# We need to restart apache as we drop a new config file in there
|
|
services.knownservices.httpd.restart(capture_output=True)
|
|
|
|
# Install CA DNS records
|
|
if bindinstance.dns_container_exists(host_name, basedn, dm_password):
|
|
bind = bindinstance.BindInstance(dm_password=dm_password)
|
|
bind.add_ipa_ca_dns_records(host_name, domain_name)
|
|
|
|
|
|
def uninstall(dogtag_constants):
|
|
if not dogtag_constants.SHARED_DB:
|
|
cads_instance = cainstance.CADSInstance(
|
|
dogtag_constants=dogtag_constants)
|
|
if cads_instance.is_configured():
|
|
cads_instance.uninstall()
|
|
|
|
ca_instance = cainstance.CAInstance(
|
|
api.env.realm, certs.NSS_DIR, dogtag_constants=dogtag_constants)
|
|
ca_instance.stop_tracking_certificates()
|
|
if ca_instance.is_configured():
|
|
ca_instance.uninstall()
|