From 78c59858cddec7f5fec176eacaf318e2d77d2045 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Tue, 25 Aug 2015 15:42:25 -0400 Subject: Allow to install the KRA on a promoted server Signed-off-by: Simo Sorce --- install/tools/ipa-ca-install | 5 +- ipaserver/install/cainstance.py | 106 +---------------------------- ipaserver/install/custodiainstance.py | 29 ++++++-- ipaserver/install/dogtaginstance.py | 91 +++++++++++++++++++++++-- ipaserver/install/ipa_kra_install.py | 55 +++++++++++---- ipaserver/install/kra.py | 31 ++++++++- ipaserver/install/krainstance.py | 70 ++++++++++++++++--- ipaserver/install/server/replicainstall.py | 29 +++++--- ipaserver/install/service.py | 30 +++++++- 9 files changed, 299 insertions(+), 147 deletions(-) mode change 100644 => 100755 ipaserver/install/ipa_kra_install.py diff --git a/install/tools/ipa-ca-install b/install/tools/ipa-ca-install index 46fb36aa2..82896867c 100755 --- a/install/tools/ipa-ca-install +++ b/install/tools/ipa-ca-install @@ -29,7 +29,7 @@ from ipaserver.install import certs from ipaserver.install.installutils import create_replica_config from ipaserver.install.installutils import check_creds, ReplicaConfig from ipaserver.install import dsinstance, ca -from ipaserver.install import cainstance, custodiainstance +from ipaserver.install import cainstance, custodiainstance, service from ipapython import dogtag from ipapython import version from ipalib import api @@ -175,7 +175,8 @@ def install_replica(safe_options, options, filename): config.subject_base = attrs.get('ipacertificatesubjectbase')[0] if config.master_host_name is None: - config.ca_host_name = cainstance.find_ca_server(api.env.ca_host, conn) + config.ca_host_name = \ + service.find_providing_server('CA', conn, api.env.ca_host) config.master_host_name = config.ca_host_name else: config.ca_host_name = config.master_host_name diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py index ff906cea5..da0a6893a 100644 --- a/ipaserver/install/cainstance.py +++ b/ipaserver/install/cainstance.py @@ -262,30 +262,6 @@ def is_step_one_done(): return False -def find_ca_server(host_name, conn, api=api): - """ - :param host_name: the preferred server - :param conn: a connection to the LDAP server - :return: the selected host name - - Find a server that is a CA. - """ - base_dn = DN(('cn', 'masters'), ('cn', 'ipa'), ('cn', 'etc'), - api.env.basedn) - query_filter = conn.make_filter({'objectClass': 'ipaConfigObject', - 'ipaConfigString': 'enabledService', - 'cn': 'CA'}, rules='&') - entries, trunc = conn.find_entries(filter=query_filter, base_dn=base_dn) - if len(entries): - if host_name is not None: - for entry in entries: - if entry.dn[1].value == host_name: - return host_name - # if the preferred is not found, return the first in the list - return entries[0].dn[1].value - return None - - def is_ca_installed_locally(): """Check if CA is installed locally by checking for existence of CS.cfg :return:True/False @@ -1527,83 +1503,6 @@ class CAInstance(DogtagInstance): # Activate Topology for o=ipaca segments self.__update_topology() - def __add_admin_to_group(self, group): - dn = DN(('cn', group), ('ou', 'groups'), ('o', 'ipaca')) - entry = self.admin_conn.get_entry(dn) - members = entry.get('uniqueMember', []) - members.append(self.admin_dn) - mod = [(ldap.MOD_REPLACE, 'uniqueMember', members)] - try: - self.admin_conn.modify_s(dn, mod) - except ldap.TYPE_OR_VALUE_EXISTS: - # already there - pass - - def __setup_admin(self): - self.admin_user = "admin-%s" % self.fqdn - self.admin_password = binascii.hexlify(os.urandom(16)) - - if not self.admin_conn: - self.ldap_connect() - - self.admin_dn = DN(('uid', self.admin_user), - ('ou', 'people'), ('o', 'ipaca')) - - # remove user if left-over exists - try: - entry = self.admin_conn.delete_entry(self.admin_dn) - except errors.NotFound: - pass - - # add user - entry = self.admin_conn.make_entry( - self.admin_dn, - objectclass=["top", "person", "organizationalPerson", - "inetOrgPerson", "cmsuser"], - uid=[self.admin_user], - cn=[self.admin_user], - sn=[self.admin_user], - usertype=['adminType'], - mail=['root@localhost'], - userPassword=[self.admin_password], - userstate=['1'] - ) - self.admin_conn.add_entry(entry) - - for group in ADMIN_GROUPS: - self.__add_admin_to_group(group) - - # Now wait until the other server gets replicated this data - master_conn = ipaldap.IPAdmin(self.master_host, - port=replication.DEFAULT_PORT, - protocol='ldap') - master_conn.do_sasl_gssapi_bind() - replication.wait_for_entry(master_conn, entry) - del master_conn - - def __remove_admin_from_group(self, group): - dn = DN(('cn', group), ('ou', 'groups'), ('o', 'ipaca')) - entry = self.admin_conn.get_entry(dn) - mod = [(ldap.MOD_DELETE, 'uniqueMember', self.admin_dn)] - try: - self.admin_conn.modify_s(dn, mod) - except ldap.NO_SUCH_ATTRIBUTE: - # already removed - pass - - def __teardown_admin(self): - - if not self.admin_conn: - self.ldap_connect() - - for group in ADMIN_GROUPS: - self.__remove_admin_from_group(group) - self.admin_conn.delete_entry(self.admin_dn) - - def __restart_ds_instance(self): - self.ldap_disconnect() - services.knownservices.dirsrv.restart() - def __client_auth_to_db(self): self.enable_client_auth_to_db(self.dogtag_constants.CS_CFG_PATH) @@ -1638,6 +1537,7 @@ class CAInstance(DogtagInstance): else: self.ca_type = 'generic' + self.admin_groups = ADMIN_GROUPS self.pkcs12_info = ca_cert_bundle self.no_db_setup = True self.clone = True @@ -1651,7 +1551,7 @@ class CAInstance(DogtagInstance): self.step("creating certificate server db", self.__create_ds_db) self.step("setting up initial replication", self.__setup_replication) - self.step("creating installation admin user", self.__setup_admin) + self.step("creating installation admin user", self.setup_admin) # Setup instance self.step("setting up certificate server", self.__spawn_instance) @@ -1662,7 +1562,7 @@ class CAInstance(DogtagInstance): self.step("enable PKIX certificate path discovery and validation", self.enable_pkix) self.step("set up client auth to db", self.__client_auth_to_db) - self.step("destroying installation admin user", self.__teardown_admin) + self.step("destroying installation admin user", self.teardown_admin) self.step("starting instance", self.start_instance) self.step("importing CA chain to RA certificate database", diff --git a/ipaserver/install/custodiainstance.py b/ipaserver/install/custodiainstance.py index 6f4afb3a9..eb9512bf1 100644 --- a/ipaserver/install/custodiainstance.py +++ b/ipaserver/install/custodiainstance.py @@ -78,13 +78,12 @@ class CustodiaInstance(SimpleServiceInstance): cli = CustodiaClient(self.fqdn, master_host_name, self.realm) cli.fetch_key('dm/DMHash') - def get_ca_keys(self, ca_host, cacerts_file, cacerts_pwd): + def __get_keys(self, ca_host, cacerts_file, cacerts_pwd, data): # Fecth all needed certs one by one, then combine them in a single # p12 file - certlist = ['caSigningCert cert-pki-ca', - 'ocspSigningCert cert-pki-ca', - 'auditSigningCert cert-pki-ca', - 'subsystemCert cert-pki-ca'] + + prefix = data['prefix'] + certlist = data['list'] cli = CustodiaClient(self.fqdn, ca_host, self.realm) @@ -104,7 +103,7 @@ class CustodiaInstance(SimpleServiceInstance): f.flush() for nickname in certlist: - value = cli.fetch_key(os.path.join('ca', nickname), False) + value = cli.fetch_key(os.path.join(prefix, nickname), False) v = json_decode(value) pk12pwfile = os.path.join(tmpnssdir, 'pk12pwfile') with open(pk12pwfile, 'w+') as f: @@ -129,6 +128,24 @@ class CustodiaInstance(SimpleServiceInstance): finally: shutil.rmtree(tmpnssdir) + def get_ca_keys(self, ca_host, cacerts_file, cacerts_pwd): + certlist = ['caSigningCert cert-pki-ca', + 'ocspSigningCert cert-pki-ca', + 'auditSigningCert cert-pki-ca', + 'subsystemCert cert-pki-ca'] + data = {'prefix': 'ca', + 'list': certlist} + self.__get_keys(ca_host, cacerts_file, cacerts_pwd, data) + + def get_kra_keys(self, ca_host, cacerts_file, cacerts_pwd): + certlist = ['auditSigningCert cert-pki-kra', + 'storageCert cert-pki-kra', + 'subsystemCert cert-pki-ca', + 'transportCert cert-pki-kra'] + data = {'prefix': 'ca', + 'list': certlist} + self.__get_keys(ca_host, cacerts_file, cacerts_pwd, data) + def __start(self): super(CustodiaInstance, self).__start() diff --git a/ipaserver/install/dogtaginstance.py b/ipaserver/install/dogtaginstance.py index 3a269f973..34308107b 100644 --- a/ipaserver/install/dogtaginstance.py +++ b/ipaserver/install/dogtaginstance.py @@ -18,6 +18,8 @@ # import base64 +import binascii +import ldap import os import shutil import tempfile @@ -27,6 +29,8 @@ import dbus from pki.client import PKIConnection import pki.system +from ipalib import errors + from ipaplatform import services from ipaplatform.paths import paths from ipapython import certmonger @@ -36,6 +40,7 @@ from ipapython import ipautil from ipapython.dn import DN from ipaserver.install import service from ipaserver.install import installutils +from ipaserver.install import replication from ipaserver.install.installutils import stopped_service from ipapython.ipa_log_manager import log_mgr @@ -122,7 +127,10 @@ class DogtagInstance(service.Service): self.clone = False self.basedn = DN(('o', 'ipa%s' % subsystem.lower())) - self.admin_user = DN(('uid', 'admin'), ('ou', 'people'), ('o', 'ipaca')) + self.admin_user = "admin" + self.admin_dn = DN(('uid', self.admin_user), + ('ou', 'people'), ('o', 'ipaca')) + self.admin_groups = None self.agent_db = tempfile.mkdtemp(prefix="tmp-") self.ds_port = DEFAULT_DSPORT self.server_root = dogtag_constants.SERVER_ROOT @@ -413,12 +421,10 @@ class DogtagInstance(service.Service): conn = None try: - conn = ipaldap.IPAdmin(self.fqdn, self.ds_port) - conn.do_simple_bind( - DN(('cn', 'Directory Manager')), - self.dm_password) + conn = ipaldap.IPAdmin(self.fqdn, ldapi=True, realm=self.realm) + conn.do_external_bind('root') - entry_attrs = conn.get_entry(self.admin_user, ['usercertificate']) + entry_attrs = conn.get_entry(self.admin_dn, ['usercertificate']) admin_cert = entry_attrs.get('usercertificate')[0] # TODO(edewata) Add check to warn if there is more than one cert. @@ -440,3 +446,76 @@ class DogtagInstance(service.Service): self.log.critical(" %s" % log) raise RuntimeError("%s configuration failed." % self.subsystem) + + def __add_admin_to_group(self, group): + dn = DN(('cn', group), ('ou', 'groups'), ('o', 'ipaca')) + entry = self.admin_conn.get_entry(dn) + members = entry.get('uniqueMember', []) + members.append(self.admin_dn) + mod = [(ldap.MOD_REPLACE, 'uniqueMember', members)] + try: + self.admin_conn.modify_s(dn, mod) + except ldap.TYPE_OR_VALUE_EXISTS: + # already there + pass + + def setup_admin(self): + self.admin_user = "admin-%s" % self.fqdn + self.admin_password = binascii.hexlify(os.urandom(16)) + + if not self.admin_conn: + self.ldap_connect() + + self.admin_dn = DN(('uid', self.admin_user), + ('ou', 'people'), ('o', 'ipaca')) + + # remove user if left-over exists + try: + entry = self.admin_conn.delete_entry(self.admin_dn) + except errors.NotFound: + pass + + # add user + entry = self.admin_conn.make_entry( + self.admin_dn, + objectclass=["top", "person", "organizationalPerson", + "inetOrgPerson", "cmsuser"], + uid=[self.admin_user], + cn=[self.admin_user], + sn=[self.admin_user], + usertype=['adminType'], + mail=['root@localhost'], + userPassword=[self.admin_password], + userstate=['1'] + ) + self.admin_conn.add_entry(entry) + + for group in self.admin_groups: + self.__add_admin_to_group(group) + + # Now wait until the other server gets replicated this data + master_conn = ipaldap.IPAdmin(self.master_host, + port=DEFAULT_DSPORT, + protocol='ldap') + master_conn.do_sasl_gssapi_bind() + replication.wait_for_entry(master_conn, entry) + del master_conn + + def __remove_admin_from_group(self, group): + dn = DN(('cn', group), ('ou', 'groups'), ('o', 'ipaca')) + entry = self.admin_conn.get_entry(dn) + mod = [(ldap.MOD_DELETE, 'uniqueMember', self.admin_dn)] + try: + self.admin_conn.modify_s(dn, mod) + except ldap.NO_SUCH_ATTRIBUTE: + # already removed + pass + + def teardown_admin(self): + + if not self.admin_conn: + self.ldap_connect() + + for group in self.admin_groups: + self.__remove_admin_from_group(group) + self.admin_conn.delete_entry(self.admin_dn) diff --git a/ipaserver/install/ipa_kra_install.py b/ipaserver/install/ipa_kra_install.py old mode 100644 new mode 100755 index ef2b2f985..7e7f60ef2 --- a/ipaserver/install/ipa_kra_install.py +++ b/ipaserver/install/ipa_kra_install.py @@ -20,6 +20,8 @@ from __future__ import print_function +import tempfile + from textwrap import dedent from ipalib import api from ipaplatform import services @@ -28,11 +30,14 @@ from ipapython import admintool from ipapython import dogtag from ipapython import ipautil from ipapython.dn import DN +from ipaserver.install import service from ipaserver.install import krainstance +from ipaserver.install import dsinstance from ipaserver.install import installutils from ipaserver.install.installutils import create_replica_config from ipaserver.install import dogtaginstance from ipaserver.install import kra +from ipaserver.install.installutils import ReplicaConfig class KRAInstall(admintool.AdminTool): @@ -129,8 +134,14 @@ class KRAInstaller(KRAInstall): ) self.installing_replica = dogtaginstance.is_installing_replica("KRA") + self.options.promote = False if self.installing_replica: + domain_level = dsinstance.get_domain_level(api) + if domain_level > 0: + self.options.promote = True + return + if not self.args: self.option_parser.error("A replica file is required.") if len(self.args) > 1: @@ -161,28 +172,48 @@ class KRAInstaller(KRAInstall): print(dedent(self.INSTALLER_START_MESSAGE)) if not self.installing_replica: - replica_config = None + config = None else: - replica_config = create_replica_config( - self.options.password, - self.replica_file, - self.options) + if self.options.promote: + config = ReplicaConfig() + config.master_host_name = None + config.realm_name = api.env.realm + config.host_name = api.env.host + config.domain_name = api.env.domain + config.dirman_password = self.options.password + config.ca_ds_port = dogtag.install_constants.DS_PORT + config.top_dir = tempfile.mkdtemp("ipa") + config.dir = config.top_dir + else: + config = create_replica_config( + self.options.password, + self.replica_file, + self.options) self.options.dm_password = self.options.password self.options.setup_ca = False - api.Backend.ldap2.connect(bind_dn=DN('cn=Directory Manager'), - bind_pw=self.options.dm_password) + conn = api.Backend.ldap2 + conn.connect(bind_dn=DN(('cn', 'Directory Manager')), + bind_pw=self.options.password) + + if config.subject_base is None: + attrs = conn.get_ipa_config() + config.subject_base = attrs.get('ipacertificatesubjectbase')[0] + + if config.master_host_name is None: + config.kra_host_name = \ + service.find_providing_server('KRA', conn, api.env.ca_host) + config.master_host_name = config.kra_host_name + else: + config.kra_host_name = config.master_host_name try: - kra.install_check(api, replica_config, self.options) + kra.install_check(api, config, self.options) except RuntimeError as e: raise admintool.ScriptError(str(e)) - kra.install(api, replica_config, self.options) - - # Restart apache for new proxy config file - services.knownservices.httpd.restart(capture_output=True) + kra.install(api, config, self.options) def run(self): try: diff --git a/ipaserver/install/kra.py b/ipaserver/install/kra.py index f3a0fe5c6..40c283e6d 100644 --- a/ipaserver/install/kra.py +++ b/ipaserver/install/kra.py @@ -2,11 +2,15 @@ # Copyright (C) 2015 FreeIPA Contributors see COPYING for license # +import os + from ipalib import api, errors +from ipaplatform import services from ipapython import certdb from ipapython import dogtag from ipapython import ipautil from ipapython.dn import DN +from ipaserver.install import custodiainstance from ipaserver.install import cainstance from ipaserver.install import krainstance from ipaserver.install import dsinstance @@ -36,6 +40,9 @@ def install_check(api, replica_config, options): if not api.Command.kra_is_enabled()['result']: raise RuntimeError("KRA is not installed on the master system") + if options.promote: + return + with certdb.NSSDatabase() as tmpdb: pw = ipautil.write_tmp_file(ipautil.ipa_generate_password()) tmpdb.create_db(pw.name) @@ -62,7 +69,26 @@ def install(api, replica_config, options): api.env.realm, api.env.host, options.dm_password, options.dm_password, subject_base=subject) else: - kra = krainstance.install_replica_kra(replica_config) + if options.promote: + ca_data = (os.path.join(replica_config.dir, 'kracert.p12'), + replica_config.dirman_password) + + custodia = custodiainstance.CustodiaInstance( + replica_config.host_name, replica_config.realm_name) + custodia.get_kra_keys(replica_config.kra_host_name, + ca_data[0], ca_data[1]) + + kra = krainstance.KRAInstance( + replica_config.realm_name, + dogtag_constants=dogtag.install_constants) + kra.configure_replica(replica_config.host_name, + replica_config.kra_host_name, + replica_config.dirman_password, + kra_cert_bundle=ca_data) + return + + else: + kra = krainstance.install_replica_kra(replica_config) service.print_msg("Restarting the directory server") ds = dsinstance.DsInstance() @@ -72,6 +98,9 @@ def install(api, replica_config, options): kra.enable_client_auth_to_db(kra.dogtag_constants.KRA_CS_CFG_PATH) + # Restart apache for new proxy config file + services.knownservices.httpd.restart(capture_output=True) + def uninstall(standalone): dogtag_constants = dogtag.configured_constants(api) diff --git a/ipaserver/install/krainstance.py b/ipaserver/install/krainstance.py index ba6606ba4..e3cc17990 100644 --- a/ipaserver/install/krainstance.py +++ b/ipaserver/install/krainstance.py @@ -46,6 +46,11 @@ from ipapython.ipa_log_manager import log_mgr # replicas with KRA configured IPA_KRA_RECORD = "ipa-kra" +ADMIN_GROUPS = [ + 'Enterprise CA Administrators', + 'Enterprise KRA Administrators', + 'Security Domain Administrators' +] class KRAInstance(DogtagInstance): """ @@ -146,7 +151,7 @@ class KRAInstance(DogtagInstance): # Security Domain Authentication config.set("KRA", "pki_security_domain_https_port", "443") config.set("KRA", "pki_security_domain_password", self.admin_password) - config.set("KRA", "pki_security_domain_user", "admin") + config.set("KRA", "pki_security_domain_user", self.admin_user) # issuing ca config.set("KRA", "pki_issuing_ca_uri", "https://%s" % @@ -165,8 +170,8 @@ class KRAInstance(DogtagInstance): config.set("KRA", "pki_client_pkcs12_password", self.admin_password) # Administrator - config.set("KRA", "pki_admin_name", "admin") - config.set("KRA", "pki_admin_uid", "admin") + config.set("KRA", "pki_admin_name", self.admin_user) + config.set("KRA", "pki_admin_uid", self.admin_user) config.set("KRA", "pki_admin_email", "root@localhost") config.set("KRA", "pki_admin_password", self.admin_password) config.set("KRA", "pki_admin_nickname", "ipa-ca-agent") @@ -226,15 +231,16 @@ class KRAInstance(DogtagInstance): pent = pwd.getpwnam(PKI_USER) os.chown(p12_tmpfile_name, pent.pw_uid, pent.pw_gid) - # create admin cert file if it does not exist - cert = DogtagInstance.get_admin_cert(self) - with open(paths.ADMIN_CERT_PATH, "w") as admin_path: - admin_path.write(cert) + # FIXME + # # create admin cert file if it does not exist + # cert = DogtagInstance.get_admin_cert(self) + # with open(paths.ADMIN_CERT_PATH, "w") as admin_path: + # admin_path.write(cert) # Security domain registration config.set("KRA", "pki_security_domain_hostname", self.master_host) config.set("KRA", "pki_security_domain_https_port", "443") - config.set("KRA", "pki_security_domain_user", "admin") + config.set("KRA", "pki_security_domain_user", self.admin_user) config.set("KRA", "pki_security_domain_password", self.admin_password) @@ -349,6 +355,54 @@ class KRAInstance(DogtagInstance): dogtag.configured_constants().KRA_CS_CFG_PATH, dogtag_constants) + def __enable_instance(self): + self.ldap_enable('KRA', self.fqdn, None, self.suffix) + + def configure_replica(self, host_name, master_host, dm_password, + kra_cert_bundle=None, subject_base=None): + """Create a KRA instance. + + To create a clone, pass in pkcs12_info. + """ + self.fqdn = host_name + self.dm_password = dm_password + self.ds_port = DEFAULT_DSPORT + self.master_host = master_host + if subject_base is None: + self.subject_base = DN(('O', self.realm)) + else: + self.subject_base = subject_base + self.suffix = ipautil.realm_to_suffix(self.realm) + + self.pkcs12_info = kra_cert_bundle + self.clone = True + self.admin_groups = ADMIN_GROUPS + + # Confirm that a KRA does not already exist + if self.is_installed(): + raise RuntimeError( + "KRA already installed.") + # Confirm that a Dogtag 10 CA instance already exists + ca = cainstance.CAInstance(self.realm, certs.NSS_DIR, + dogtag_constants=dogtag.Dogtag10Constants) + if not ca.is_installed(): + raise RuntimeError( + "KRA configuration failed. " + "A Dogtag CA must be installed first") + + self.step("creating installation admin user", self.setup_admin) + self.step("configuring KRA instance", self.__spawn_instance) + self.step("destroying installation admin user", self.teardown_admin) + self.step("restarting KRA", self.restart_instance) + self.step("configure certmonger for renewals", + self.configure_certmonger_renewal) + self.step("configure certificate renewals", self.configure_renewal) + self.step("add vault container", self.__add_vault_container) + + self.step("enabling KRA instance", self.__enable_instance) + + self.start_creation(runtime=126) + def install_replica_kra(config, postinstall=False): """ diff --git a/ipaserver/install/server/replicainstall.py b/ipaserver/install/server/replicainstall.py index 8b2bfd3e1..225c896e4 100644 --- a/ipaserver/install/server/replicainstall.py +++ b/ipaserver/install/server/replicainstall.py @@ -28,8 +28,8 @@ import ipaclient.ipachangeconf import ipaclient.ntpconf from ipaserver.install import ( bindinstance, ca, cainstance, certs, dns, dsinstance, httpinstance, - installutils, kra, krbinstance, memcacheinstance, ntpinstance, - otpdinstance, custodiainstance, service) + installutils, kra, krainstance, krbinstance, memcacheinstance, + ntpinstance, otpdinstance, custodiainstance, service) from ipaserver.install.installutils import create_replica_config from ipaserver.install.installutils import ReplicaConfig from ipaserver.install.replication import ( @@ -771,10 +771,6 @@ def promote_check(installer): installer._top_dir = tempfile.mkdtemp("ipa") - # FIXME: to implement yet - if options.setup_kra: - raise NotImplementedError - tasks.check_selinux_status() client_fstore = sysrestore.FileStore(paths.IPA_CLIENT_SYSRESTORE) @@ -921,7 +917,7 @@ def promote_check(installer): config.subject_base = DN(subject_base) # Find if any server has a CA - ca_host = cainstance.find_ca_server(api.env.server, conn) + ca_host = service.find_providing_server('CA', conn, api.env.server) if ca_host is not None: config.ca_host_name = ca_host ca_enabled = True @@ -931,6 +927,13 @@ def promote_check(installer): "installed, can't proceed without certs") sys.exit(3) + config.kra_host_name = service.find_providing_server('KRA', conn, + api.env.server) + if options.setup_kra and config.kra_host_name is None: + root_logger.error("There is no KRA server in the domain, can't " + "setup a KRA clone") + sys.exit(3) + if options.setup_ca: if not ca_enabled: root_logger.error("The remote master does not have a CA " @@ -1082,7 +1085,17 @@ def promote(installer): ca_cert_bundle=ca_data) if options.setup_kra: - kra.install(api, config, options) + ca_data = (os.path.join(config.dir, 'kracert.p12'), + config.dirman_password) + custodia.get_kra_keys(config.kra_host_name, ca_data[0], ca_data[1]) + + constants = dogtag.install_constants + kra = krainstance.KRAInstance(config.realm_name, + dogtag_constants=constants) + kra.configure_replica(config.host_name, config.kra_host_name, + config.dirman_password, + kra_cert_bundle=ca_data) + ds.replica_populate() diff --git a/ipaserver/install/service.py b/ipaserver/install/service.py index b2d111cdf..7b7b68c15 100644 --- a/ipaserver/install/service.py +++ b/ipaserver/install/service.py @@ -27,7 +27,7 @@ import traceback from ipapython import sysrestore, ipautil, dogtag, ipaldap from ipapython.dn import DN from ipapython.ipa_log_manager import * -from ipalib import errors, certstore +from ipalib import api, errors, certstore from ipaplatform import services from ipaplatform.paths import paths @@ -100,6 +100,34 @@ def add_principals_to_group(admin_conn, group, member_attr, principals): # If there are no changes just pass pass + +def find_providing_server(svcname, conn, host_name=None, api=api): + """ + :param svcname: The service to find + :param conn: a connection to the LDAP server + :param host_name: the preferred server + :return: the selected host name + + Find a server that is a CA. + """ + dn = DN(('cn', 'masters'), ('cn', 'ipa'), ('cn', 'etc'), api.env.basedn) + query_filter = conn.make_filter({'objectClass': 'ipaConfigObject', + 'ipaConfigString': 'enabledService', + 'cn': svcname}, rules='&') + try: + entries, trunc = conn.find_entries(filter=query_filter, base_dn=dn) + except errors.NotFound: + return None + if len(entries): + if host_name is not None: + for entry in entries: + if entry.dn[1].value == host_name: + return host_name + # if the preferred is not found, return the first in the list + return entries[0].dn[1].value + return None + + class Service(object): def __init__(self, service_name, service_desc=None, sstore=None, dm_password=None, ldapi=True, autobind=ipaldap.AUTOBIND_AUTO, -- cgit