Move CA installation code into single module.

https://fedorahosted.org/freeipa/ticket/4468

Reviewed-By: Jan Cholasta <jcholast@redhat.com>
This commit is contained in:
David Kupka
2015-06-08 05:23:56 +00:00
committed by Jan Cholasta
parent a57998f51e
commit 2acedb2d5d
5 changed files with 330 additions and 345 deletions

View File

@@ -21,26 +21,18 @@
import sys
import os
import shutil
from ConfigParser import RawConfigParser
from ipapython import ipautil
from ipaserver.install import installutils
from ipaserver.install import certs
from ipaserver.install.installutils import (HostnameLocalhost, ReplicaConfig,
expand_replica_info, read_replica_info, get_host_name, BadHostError,
private_ccache, read_replica_info_dogtag_port, load_external_cert,
create_replica_config)
from ipaserver.install import dsinstance, cainstance, bindinstance
from ipaserver.install.replication import replica_conn_check
from ipaserver.install.installutils import (private_ccache,
create_replica_config)
from ipaserver.install import dsinstance, ca
from ipapython import version
from ipalib import api, certstore, x509
from ipalib import api
from ipapython.dn import DN
from ipapython.config import IPAOptionParser
from ipapython import sysrestore
from ipapython import dogtag
from ipapython import certdb
from ipapython.ipa_log_manager import *
from ipaplatform import services
from ipaplatform.paths import paths
log_file_name = paths.IPAREPLICA_CA_INSTALL_LOG
@@ -86,6 +78,9 @@ def parse_options():
if len(args) != 1:
parser.error("you must provide a file generated by "
"ipa-replica-prepare")
options.external_ca = None
options.external_cert_files = None
else:
filename = None
@@ -106,31 +101,6 @@ def get_dirman_password():
"Directory Manager (existing master)", confirm=False, validate=False)
def check_ca():
if not cainstance.check_port():
print "IPA requires port 8443 for PKI but it is currently in use."
sys.exit(1)
def install_dns_records(config, options):
if not bindinstance.dns_container_exists(config.master_host_name,
ipautil.realm_to_suffix(config.realm_name),
dm_password=config.dirman_password):
return
bind = bindinstance.BindInstance(dm_password=config.dirman_password)
disconnect = False
try:
if not api.Backend.ldap2.isconnected():
api.Backend.ldap2.connect(bind_dn=DN(('cn', 'Directory Manager')),
bind_pw=config.dirman_password)
disconnect = True
bind.add_ipa_ca_dns_records(config.host_name, config.domain_name)
finally:
if api.Backend.ldap2.isconnected() and disconnect:
api.Backend.ldap2.disconnect()
def install_replica(safe_options, options, filename):
standard_logging_setup(log_file_name, debug=options.debug)
@@ -141,18 +111,12 @@ def install_replica(safe_options, options, filename):
if not ipautil.file_exists(filename):
sys.exit("Replica file %s does not exist" % filename)
global sstore
sstore = sysrestore.StateFile(paths.SYSRESTORE)
if not dsinstance.DsInstance().is_configured():
sys.exit("IPA server is not configured on this system.\n")
api.bootstrap(in_server=True)
api.finalize()
if api.env.ra_plugin == 'selfsign':
sys.exit('A selfsign CA can not be added')
# get the directory manager password
dirman_password = options.password
if not dirman_password:
@@ -174,48 +138,17 @@ def install_replica(safe_options, options, filename):
REPLICA_INFO_TOP_DIR = config.top_dir
config.setup_ca = True
if not ipautil.file_exists(config.dir + "/cacert.p12"):
print 'CA cannot be installed in CA-less setup.'
sys.exit(1)
api.Backend.ldap2.connect(bind_dn=DN(('cn', 'Directory Manager')),
bind_pw=dirman_password)
if not options.skip_conncheck:
replica_conn_check(
config.master_host_name, config.host_name, config.realm_name, True,
config.ca_ds_port, options.admin_password)
options.realm_name = config.realm_name
options.domain_name = config.domain_name
options.dm_password = config.dirman_password
options.host_name = config.host_name
options.subject = config.subject_base
if options.skip_schema_check:
root_logger.info("Skipping CA DS schema check")
else:
cainstance.replica_ca_install_check(config)
check_ca()
# Configure the CA if necessary
CA = cainstance.install_replica_ca(config, postinstall=True)
# We need to ldap_enable the CA now that DS is up and running
CA.ldap_enable('CA', config.host_name, config.dirman_password,
ipautil.realm_to_suffix(config.realm_name))
# This is done within stopped_service context, which restarts CA
CA.enable_client_auth_to_db(CA.dogtag_constants.CS_CFG_PATH)
# Install CA DNS records
install_dns_records(config, options)
# We need to restart apache as we drop a new config file in there
services.knownservices.httpd.restart(capture_output=True)
#update dogtag version in config file
try:
fd = open(paths.IPA_DEFAULT_CONF, "a")
fd.write(
"dogtag_version=%s\n" % dogtag.install_constants.DOGTAG_VERSION)
fd.close()
except IOError, e:
print "Failed to update /etc/ipa/default.conf"
root_logger.error(str(e))
sys.exit(1)
ca.install_check(True, config, options)
ca.install(True, config, options)
def install_master(safe_options, options):
@@ -225,9 +158,6 @@ def install_master(safe_options, options):
"%s was invoked with options: %s", sys.argv[0], safe_options)
root_logger.debug("IPA version %s", version.VENDOR_VERSION)
global sstore
sstore = sysrestore.StateFile(paths.SYSRESTORE)
if not dsinstance.DsInstance().is_configured():
sys.exit("IPA server is not configured on this system.\n")
@@ -248,150 +178,17 @@ def install_master(safe_options, options):
api.Backend.ldap2.connect(bind_dn=DN(('cn', 'Directory Manager')),
bind_pw=dm_password)
if api.Command.ca_is_enabled()['result']:
sys.exit("CA is already installed.\n")
config = api.Command['config_show']()['result']
subject_base = config['ipacertificatesubjectbase'][0]
if options.external_ca:
if cainstance.is_step_one_done():
print ("CA is already installed.\nRun the installer with "
"--external-cert-file.")
sys.exit(1)
elif options.external_cert_files:
if not cainstance.is_step_one_done():
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)
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
external_cert_file, external_ca_file = load_external_cert(
options.external_cert_files, subject_base)
if options.external_cert_files:
external = 2
elif options.external_ca:
external = 1
else:
external = 0
realm_name = api.env.realm
domain_name = api.env.domain
host_name = api.env.host
if external != 2:
check_ca()
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)
ca = cainstance.CAInstance(
realm_name, certs.NSS_DIR,
dogtag_constants=dogtag.install_constants)
ca.create_ra_agent_db = False
if external == 0:
ca.configure_instance(host_name, domain_name, dm_password,
dm_password, subject_base=subject_base,
ca_signing_algorithm=options.ca_signing_algorithm)
elif external == 1:
ca.configure_instance(host_name, domain_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, domain_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)
ca.stop(ca.dogtag_constants.PKI_INSTANCE_NAME)
ca.ldap_enable('CA', host_name, dm_password,
ipautil.realm_to_suffix(realm_name), ['caRenewalMaster'])
ca.enable_client_auth_to_db(ca.dogtag_constants.CS_CFG_PATH)
# Install CA DNS records
config = ReplicaConfig()
config.realm_name = realm_name
config.domain_name = domain_name
config.host_name = config.master_host_name = host_name
config.dirman_password = dm_password
install_dns_records(config, options)
# We need to restart apache as we drop a new config file in there
services.knownservices.httpd.restart(capture_output=True)
# Update config file
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(ca.dogtag_constants.DOGTAG_VERSION))
with open(paths.IPA_DEFAULT_CONF, 'w') as f:
parser.write(f)
# 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)
# Restart DS
ds = dsinstance.DsInstance()
ds.init_info(realm_name, host_name, domain_name, dm_password, subject_base,
1101, 1100, None)
ds.restart(ds.serverid)
# Store DS CA cert in Dogtag NSS database
dogtagdb = certs.CertDB(realm_name, nssdir=ca.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])
ca.start(ca.dogtag_constants.PKI_INSTANCE_NAME)
ca.install_check(True, None, options)
ca.install(True, None, options)
def main():

View File

@@ -128,6 +128,9 @@ def parse_options():
elif options.reverse_zones and options.no_reverse:
parser.error("You cannot specify a --reverse-zone option together with --no-reverse")
options.external_ca = None
options.external_cert_files = None
options.zonemgr = None
options.dnssec_master = False