|
|
7bbb43 |
From d3c09a6de06d8ae19d05c0b96cb9c2a5b789b472 Mon Sep 17 00:00:00 2001
|
|
|
7bbb43 |
From: Christian Heimes <cheimes@redhat.com>
|
|
|
7bbb43 |
Date: Thu, 7 Jun 2018 18:17:20 +0200
|
|
|
7bbb43 |
Subject: [PATCH] Use one Custodia peer to retrieve all secrets
|
|
|
7bbb43 |
|
|
|
7bbb43 |
Fix 994f71ac8a1bb7ba6bc9caf0f6e4f59af44ad9c4 was incomplete. Under some
|
|
|
7bbb43 |
circumstancs the DM hash and CA keys were still retrieved from two different
|
|
|
7bbb43 |
machines.
|
|
|
7bbb43 |
|
|
|
7bbb43 |
Custodia client now uses a single remote to upload keys and download all
|
|
|
7bbb43 |
secrets.
|
|
|
7bbb43 |
|
|
|
7bbb43 |
Fixes: https://pagure.io/freeipa/issue/7518
|
|
|
7bbb43 |
Signed-off-by: Christian Heimes <cheimes@redhat.com>
|
|
|
7bbb43 |
Reviewed-By: Simo Sorce <ssorce@redhat.com>
|
|
|
7bbb43 |
---
|
|
|
7bbb43 |
ipaserver/install/ca.py | 1 -
|
|
|
7bbb43 |
ipaserver/install/cainstance.py | 2 +-
|
|
|
7bbb43 |
ipaserver/install/custodiainstance.py | 74 +++++++++++++++++-------------
|
|
|
7bbb43 |
ipaserver/install/kra.py | 1 -
|
|
|
7bbb43 |
ipaserver/install/server/install.py | 4 +-
|
|
|
7bbb43 |
ipaserver/install/server/replicainstall.py | 2 +-
|
|
|
7bbb43 |
6 files changed, 46 insertions(+), 38 deletions(-)
|
|
|
7bbb43 |
|
|
|
7bbb43 |
diff --git a/ipaserver/install/ca.py b/ipaserver/install/ca.py
|
|
|
7bbb43 |
index 2ac4382..1c7d375 100644
|
|
|
7bbb43 |
--- a/ipaserver/install/ca.py
|
|
|
7bbb43 |
+++ b/ipaserver/install/ca.py
|
|
|
7bbb43 |
@@ -235,7 +235,6 @@ def install_step_0(standalone, replica_config, options, custodia):
|
|
|
7bbb43 |
cafile = os.path.join(replica_config.dir, 'cacert.p12')
|
|
|
7bbb43 |
if options.promote:
|
|
|
7bbb43 |
custodia.get_ca_keys(
|
|
|
7bbb43 |
- replica_config.ca_host_name,
|
|
|
7bbb43 |
cafile,
|
|
|
7bbb43 |
replica_config.dirman_password)
|
|
|
7bbb43 |
|
|
|
7bbb43 |
diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py
|
|
|
7bbb43 |
index eefc30b..cc0dbf3 100644
|
|
|
7bbb43 |
--- a/ipaserver/install/cainstance.py
|
|
|
7bbb43 |
+++ b/ipaserver/install/cainstance.py
|
|
|
7bbb43 |
@@ -712,7 +712,7 @@ class CAInstance(DogtagInstance):
|
|
|
7bbb43 |
self.configure_agent_renewal()
|
|
|
7bbb43 |
|
|
|
7bbb43 |
def __import_ra_key(self):
|
|
|
7bbb43 |
- self._custodia.import_ra_key(self.master_host)
|
|
|
7bbb43 |
+ self._custodia.import_ra_key()
|
|
|
7bbb43 |
self.__set_ra_cert_perms()
|
|
|
7bbb43 |
|
|
|
7bbb43 |
self.configure_agent_renewal()
|
|
|
7bbb43 |
diff --git a/ipaserver/install/custodiainstance.py b/ipaserver/install/custodiainstance.py
|
|
|
7bbb43 |
index 262ae58..ada8d03 100644
|
|
|
7bbb43 |
--- a/ipaserver/install/custodiainstance.py
|
|
|
7bbb43 |
+++ b/ipaserver/install/custodiainstance.py
|
|
|
7bbb43 |
@@ -71,41 +71,45 @@ def get_custodia_instance(config, mode):
|
|
|
7bbb43 |
if mode == CustodiaModes.CA_PEER:
|
|
|
7bbb43 |
# In case we install replica with CA, prefer CA host as source for
|
|
|
7bbb43 |
# all Custodia secret material.
|
|
|
7bbb43 |
- custodia_master = config.ca_host_name
|
|
|
7bbb43 |
+ custodia_peer = config.ca_host_name
|
|
|
7bbb43 |
elif mode == CustodiaModes.KRA_PEER:
|
|
|
7bbb43 |
- custodia_master = config.kra_host_name
|
|
|
7bbb43 |
+ custodia_peer = config.kra_host_name
|
|
|
7bbb43 |
elif mode == CustodiaModes.MASTER_PEER:
|
|
|
7bbb43 |
- custodia_master = config.master_host_name
|
|
|
7bbb43 |
+ custodia_peer = config.master_host_name
|
|
|
7bbb43 |
elif mode == CustodiaModes.STANDALONE:
|
|
|
7bbb43 |
- custodia_master = None
|
|
|
7bbb43 |
+ custodia_peer = None
|
|
|
7bbb43 |
else:
|
|
|
7bbb43 |
- custodia_master = None
|
|
|
7bbb43 |
+ custodia_peer = None
|
|
|
7bbb43 |
|
|
|
7bbb43 |
- if custodia_master is None:
|
|
|
7bbb43 |
+ if custodia_peer is None:
|
|
|
7bbb43 |
# use ldapi with local dirsrv instance
|
|
|
7bbb43 |
root_logger.info("Custodia uses LDAPI.")
|
|
|
7bbb43 |
- ldap_uri = None
|
|
|
7bbb43 |
else:
|
|
|
7bbb43 |
- root_logger.info("Custodia uses '%s' as master peer.",
|
|
|
7bbb43 |
- custodia_master)
|
|
|
7bbb43 |
- ldap_uri = 'ldap://{}'.format(custodia_master)
|
|
|
7bbb43 |
+ root_logger.info("Custodia uses '%s' as master peer.", custodia_peer)
|
|
|
7bbb43 |
|
|
|
7bbb43 |
return CustodiaInstance(
|
|
|
7bbb43 |
host_name=config.host_name,
|
|
|
7bbb43 |
realm=config.realm_name,
|
|
|
7bbb43 |
- ldap_uri=ldap_uri
|
|
|
7bbb43 |
+ custodia_peer=custodia_peer
|
|
|
7bbb43 |
)
|
|
|
7bbb43 |
|
|
|
7bbb43 |
|
|
|
7bbb43 |
class CustodiaInstance(SimpleServiceInstance):
|
|
|
7bbb43 |
- def __init__(self, host_name=None, realm=None, ldap_uri=None):
|
|
|
7bbb43 |
+ def __init__(self, host_name=None, realm=None, custodia_peer=None):
|
|
|
7bbb43 |
super(CustodiaInstance, self).__init__("ipa-custodia")
|
|
|
7bbb43 |
self.config_file = paths.IPA_CUSTODIA_CONF
|
|
|
7bbb43 |
self.server_keys = paths.IPA_CUSTODIA_KEYS
|
|
|
7bbb43 |
- self.ldap_uri = ldap_uri
|
|
|
7bbb43 |
+ self.custodia_peer = custodia_peer
|
|
|
7bbb43 |
self.fqdn = host_name
|
|
|
7bbb43 |
self.realm = realm
|
|
|
7bbb43 |
|
|
|
7bbb43 |
+ @property
|
|
|
7bbb43 |
+ def ldap_uri(self):
|
|
|
7bbb43 |
+ if self.custodia_peer is None:
|
|
|
7bbb43 |
+ return installutils.realm_to_ldapi_uri(self.realm)
|
|
|
7bbb43 |
+ else:
|
|
|
7bbb43 |
+ return "ldap://{}".format(self.custodia_peer)
|
|
|
7bbb43 |
+
|
|
|
7bbb43 |
def __config_file(self):
|
|
|
7bbb43 |
template_file = os.path.basename(self.config_file) + '.template'
|
|
|
7bbb43 |
template = os.path.join(paths.USR_SHARE_IPA_DIR, template_file)
|
|
|
7bbb43 |
@@ -125,7 +129,7 @@ class CustodiaInstance(SimpleServiceInstance):
|
|
|
7bbb43 |
ipautil.flush_sync(f)
|
|
|
7bbb43 |
|
|
|
7bbb43 |
def create_instance(self):
|
|
|
7bbb43 |
- if self.ldap_uri is None or self.ldap_uri.startswith('ldapi://'):
|
|
|
7bbb43 |
+ if self.ldap_uri.startswith('ldapi://'):
|
|
|
7bbb43 |
# local case, ensure container exists
|
|
|
7bbb43 |
self.step("Making sure custodia container exists",
|
|
|
7bbb43 |
self.__create_container)
|
|
|
7bbb43 |
@@ -174,25 +178,24 @@ class CustodiaInstance(SimpleServiceInstance):
|
|
|
7bbb43 |
updater = ldapupdate.LDAPUpdate(sub_dict=sub_dict)
|
|
|
7bbb43 |
updater.update([os.path.join(paths.UPDATES_DIR, '73-custodia.update')])
|
|
|
7bbb43 |
|
|
|
7bbb43 |
- def import_ra_key(self, master_host_name):
|
|
|
7bbb43 |
- cli = self._get_custodia_client(server=master_host_name)
|
|
|
7bbb43 |
+ def import_ra_key(self):
|
|
|
7bbb43 |
+ cli = self._get_custodia_client()
|
|
|
7bbb43 |
# please note that ipaCert part has to stay here for historical
|
|
|
7bbb43 |
# reasons (old servers expect you to ask for ra/ipaCert during
|
|
|
7bbb43 |
# replication as they store the RA agent cert in an NSS database
|
|
|
7bbb43 |
# with this nickname)
|
|
|
7bbb43 |
cli.fetch_key('ra/ipaCert')
|
|
|
7bbb43 |
|
|
|
7bbb43 |
- def import_dm_password(self, master_host_name):
|
|
|
7bbb43 |
- cli = self._get_custodia_client(server=master_host_name)
|
|
|
7bbb43 |
+ def import_dm_password(self):
|
|
|
7bbb43 |
+ cli = self._get_custodia_client()
|
|
|
7bbb43 |
cli.fetch_key('dm/DMHash')
|
|
|
7bbb43 |
|
|
|
7bbb43 |
- def _wait_keys(self, host, timeout=300):
|
|
|
7bbb43 |
- ldap_uri = 'ldap://%s' % host
|
|
|
7bbb43 |
+ def _wait_keys(self, timeout=300):
|
|
|
7bbb43 |
deadline = int(time.time()) + timeout
|
|
|
7bbb43 |
root_logger.info("Waiting up to %s seconds to see our keys "
|
|
|
7bbb43 |
- "appear on host: %s", timeout, host)
|
|
|
7bbb43 |
+ "appear on host %s", timeout, self.ldap_uri)
|
|
|
7bbb43 |
|
|
|
7bbb43 |
- konn = KEMLdap(ldap_uri)
|
|
|
7bbb43 |
+ konn = KEMLdap(self.ldap_uri)
|
|
|
7bbb43 |
saved_e = None
|
|
|
7bbb43 |
while True:
|
|
|
7bbb43 |
try:
|
|
|
7bbb43 |
@@ -202,8 +205,11 @@ class CustodiaInstance(SimpleServiceInstance):
|
|
|
7bbb43 |
if saved_e is None:
|
|
|
7bbb43 |
# FIXME: Change once there's better way to show this
|
|
|
7bbb43 |
# message in installer output,
|
|
|
7bbb43 |
- print(" Waiting for keys to appear on host: {}, please "
|
|
|
7bbb43 |
- "wait until this has completed.".format(host))
|
|
|
7bbb43 |
+ print(
|
|
|
7bbb43 |
+ " Waiting for keys to appear on host: {}, please "
|
|
|
7bbb43 |
+ "wait until this has completed.".format(
|
|
|
7bbb43 |
+ self.ldap_uri)
|
|
|
7bbb43 |
+ )
|
|
|
7bbb43 |
# log only once for the same error
|
|
|
7bbb43 |
if not isinstance(e, type(saved_e)):
|
|
|
7bbb43 |
root_logger.debug(
|
|
|
7bbb43 |
@@ -213,23 +219,25 @@ class CustodiaInstance(SimpleServiceInstance):
|
|
|
7bbb43 |
raise RuntimeError("Timed out trying to obtain keys.")
|
|
|
7bbb43 |
time.sleep(1)
|
|
|
7bbb43 |
|
|
|
7bbb43 |
- def _get_custodia_client(self, server):
|
|
|
7bbb43 |
+ def _get_custodia_client(self):
|
|
|
7bbb43 |
+ if self.custodia_peer is None:
|
|
|
7bbb43 |
+ raise ValueError("Can't replicate secrets without Custodia peer")
|
|
|
7bbb43 |
# Before we attempt to fetch keys from this host, make sure our public
|
|
|
7bbb43 |
# keys have been replicated there.
|
|
|
7bbb43 |
- self._wait_keys(server)
|
|
|
7bbb43 |
+ self._wait_keys()
|
|
|
7bbb43 |
|
|
|
7bbb43 |
return CustodiaClient(
|
|
|
7bbb43 |
client_service='host@{}'.format(self.fqdn),
|
|
|
7bbb43 |
keyfile=self.server_keys, keytab=paths.KRB5_KEYTAB,
|
|
|
7bbb43 |
- server=server, realm=self.realm
|
|
|
7bbb43 |
+ server=self.custodia_peer, realm=self.realm
|
|
|
7bbb43 |
)
|
|
|
7bbb43 |
|
|
|
7bbb43 |
- def _get_keys(self, ca_host, cacerts_file, cacerts_pwd, data):
|
|
|
7bbb43 |
+ def _get_keys(self, cacerts_file, cacerts_pwd, data):
|
|
|
7bbb43 |
# Fetch all needed certs one by one, then combine them in a single
|
|
|
7bbb43 |
# PKCS12 file
|
|
|
7bbb43 |
prefix = data['prefix']
|
|
|
7bbb43 |
certlist = data['list']
|
|
|
7bbb43 |
- cli = self._get_custodia_client(server=ca_host)
|
|
|
7bbb43 |
+ cli = self._get_custodia_client()
|
|
|
7bbb43 |
|
|
|
7bbb43 |
# Temporary nssdb
|
|
|
7bbb43 |
tmpnssdir = tempfile.mkdtemp(dir=paths.TMP)
|
|
|
7bbb43 |
@@ -272,23 +280,23 @@ class CustodiaInstance(SimpleServiceInstance):
|
|
|
7bbb43 |
finally:
|
|
|
7bbb43 |
shutil.rmtree(tmpnssdir)
|
|
|
7bbb43 |
|
|
|
7bbb43 |
- def get_ca_keys(self, ca_host, cacerts_file, cacerts_pwd):
|
|
|
7bbb43 |
+ def get_ca_keys(self, cacerts_file, cacerts_pwd):
|
|
|
7bbb43 |
certlist = ['caSigningCert cert-pki-ca',
|
|
|
7bbb43 |
'ocspSigningCert cert-pki-ca',
|
|
|
7bbb43 |
'auditSigningCert cert-pki-ca',
|
|
|
7bbb43 |
'subsystemCert cert-pki-ca']
|
|
|
7bbb43 |
data = {'prefix': 'ca',
|
|
|
7bbb43 |
'list': certlist}
|
|
|
7bbb43 |
- self._get_keys(ca_host, cacerts_file, cacerts_pwd, data)
|
|
|
7bbb43 |
+ self._get_keys(cacerts_file, cacerts_pwd, data)
|
|
|
7bbb43 |
|
|
|
7bbb43 |
- def get_kra_keys(self, ca_host, cacerts_file, cacerts_pwd):
|
|
|
7bbb43 |
+ def get_kra_keys(self, cacerts_file, cacerts_pwd):
|
|
|
7bbb43 |
certlist = ['auditSigningCert cert-pki-kra',
|
|
|
7bbb43 |
'storageCert cert-pki-kra',
|
|
|
7bbb43 |
'subsystemCert cert-pki-ca',
|
|
|
7bbb43 |
'transportCert cert-pki-kra']
|
|
|
7bbb43 |
data = {'prefix': 'ca',
|
|
|
7bbb43 |
'list': certlist}
|
|
|
7bbb43 |
- self._get_keys(ca_host, cacerts_file, cacerts_pwd, data)
|
|
|
7bbb43 |
+ self._get_keys(cacerts_file, cacerts_pwd, data)
|
|
|
7bbb43 |
|
|
|
7bbb43 |
def __start(self):
|
|
|
7bbb43 |
super(CustodiaInstance, self).__start()
|
|
|
7bbb43 |
diff --git a/ipaserver/install/kra.py b/ipaserver/install/kra.py
|
|
|
7bbb43 |
index 3333970..d8773b9 100644
|
|
|
7bbb43 |
--- a/ipaserver/install/kra.py
|
|
|
7bbb43 |
+++ b/ipaserver/install/kra.py
|
|
|
7bbb43 |
@@ -91,7 +91,6 @@ def install(api, replica_config, options, custodia):
|
|
|
7bbb43 |
paths.KRB5_KEYTAB,
|
|
|
7bbb43 |
ccache)
|
|
|
7bbb43 |
custodia.get_kra_keys(
|
|
|
7bbb43 |
- replica_config.kra_host_name,
|
|
|
7bbb43 |
krafile,
|
|
|
7bbb43 |
replica_config.dirman_password)
|
|
|
7bbb43 |
else:
|
|
|
7bbb43 |
diff --git a/ipaserver/install/server/install.py b/ipaserver/install/server/install.py
|
|
|
7bbb43 |
index f4338ed..3651cde 100644
|
|
|
7bbb43 |
--- a/ipaserver/install/server/install.py
|
|
|
7bbb43 |
+++ b/ipaserver/install/server/install.py
|
|
|
7bbb43 |
@@ -1085,7 +1085,9 @@ def uninstall(installer):
|
|
|
7bbb43 |
dsinstance.DsInstance(fstore=fstore).uninstall()
|
|
|
7bbb43 |
if _server_trust_ad_installed:
|
|
|
7bbb43 |
adtrustinstance.ADTRUSTInstance(fstore).uninstall()
|
|
|
7bbb43 |
- custodiainstance.CustodiaInstance().uninstall()
|
|
|
7bbb43 |
+ # realm isn't used, but IPAKEMKeys parses /etc/ipa/default.conf
|
|
|
7bbb43 |
+ # otherwise, see https://pagure.io/freeipa/issue/7474 .
|
|
|
7bbb43 |
+ custodiainstance.CustodiaInstance(realm='REALM.INVALID').uninstall()
|
|
|
7bbb43 |
otpdinstance.OtpdInstance().uninstall()
|
|
|
7bbb43 |
tasks.restore_hostname(fstore, sstore)
|
|
|
7bbb43 |
fstore.restore_all_files()
|
|
|
7bbb43 |
diff --git a/ipaserver/install/server/replicainstall.py b/ipaserver/install/server/replicainstall.py
|
|
|
7bbb43 |
index ef61590..b9cd518 100644
|
|
|
7bbb43 |
--- a/ipaserver/install/server/replicainstall.py
|
|
|
7bbb43 |
+++ b/ipaserver/install/server/replicainstall.py
|
|
|
7bbb43 |
@@ -1512,7 +1512,7 @@ def install(installer):
|
|
|
7bbb43 |
krb.restart()
|
|
|
7bbb43 |
|
|
|
7bbb43 |
if promote:
|
|
|
7bbb43 |
- custodia.import_dm_password(config.master_host_name)
|
|
|
7bbb43 |
+ custodia.import_dm_password()
|
|
|
7bbb43 |
promote_sssd(config.host_name)
|
|
|
7bbb43 |
promote_openldap_conf(config.host_name, config.master_host_name)
|
|
|
7bbb43 |
|
|
|
7bbb43 |
--
|
|
|
7bbb43 |
2.9.3
|
|
|
7bbb43 |
|