[Freeipa-devel] [PATCH] 0053..0054 Configure lightweight CA key replication

Fraser Tweedale ftweedal at redhat.com
Thu Apr 21 03:30:04 UTC 2016


On Thu, Apr 14, 2016 at 04:39:37PM +1000, Fraser Tweedale wrote:
> Hi all,
> 
> The attached patches configure lightweight CA key replication on IPA
> CAs, on upgrade and installation.
> 
> Patches 0051..0052 from my other mail are also needed for the system
> to work, but this patchset does not depend on them and can be
> reviewed independently.
> 
> There is also no hard dependency on the (unreleased) Dogtag 10.3.0b1
> - it just puts the necessary principals/keys/configuration in place.
> 
> Cheers,
> Fraser
>
New patches attached;  0054-2 changes the service name from
'dogtag-ipa-custodia' to just 'dogtag', and adds an ACI to allow the
principal to search server Custodia keys.

Cheers,
Fraser
-------------- next part --------------
From b30e8d640a03ec81d5a1f962a81076993d9cea69 Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftweedal at redhat.com>
Date: Mon, 11 Apr 2016 12:42:35 +1000
Subject: [PATCH 53/54] Optionally add service name to Custodia key DNs

Lightweight CAs support introduces new service principals for
Dogtag, with Custodia keys.  The current Custodia key creation uses
a DN that contains only they key type and the hostname, so keys for
multiple services on the same host cannot be created.

Add the 'generate_keys' method to generate keys for a host or an
arbitrary service.  When a service name is given, include the
service name in the DN.

This change does not affect searching because all searching is done
using the ipaKeyUsage and memberPrincipal attributes.

Part of: https://fedorahosted.org/freeipa/ticket/4559
---
 ipapython/secrets/kem.py | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/ipapython/secrets/kem.py b/ipapython/secrets/kem.py
index 1025ed7980f055c82c602634e8845fa490cf0514..533121779241d30e19fef4c050bb69c55d29ec22 100644
--- a/ipapython/secrets/kem.py
+++ b/ipapython/secrets/kem.py
@@ -105,10 +105,11 @@ class KEMLdap(iSecLdap):
             encoding=serialization.Encoding.DER,
             format=serialization.PublicFormat.SubjectPublicKeyInfo)
 
-    def set_key(self, usage, host, principal, key):
+    def set_key(self, usage, servicename, host, principal, key):
         public_key = self._format_public_key(key)
         conn = self.connect()
-        name = '%s/%s' % (KEY_USAGE_MAP[usage], host)
+        service_segment = '~' + servicename if servicename else ''
+        name = '%s%s/%s' % (KEY_USAGE_MAP[usage], service_segment, host)
         dn = 'cn=%s,%s' % (name, self.keysbase)
         try:
             mods = [('objectClass', ['nsContainer',
@@ -170,15 +171,18 @@ class IPAKEMKeys(KEMKeysStore):
         return conn.get_key(usage, kid)
 
     def generate_server_keys(self):
-        principal = 'host/%s@%s' % (self.host, self.realm)
+        self.generate_keys()
+
+    def generate_keys(self, servicename=None):
+        principal = '%s/%s@%s' % (servicename or 'host', self.host, self.realm)
         # Neutralize the key with read if any
         self._server_keys = None
         # Generate private key and store it
         pubkeys = newServerKeys(self.config['server_keys'], principal)
         # Store public key in LDAP
         ldapconn = KEMLdap(self.ldap_uri)
-        ldapconn.set_key(KEY_USAGE_SIG, self.host, principal, pubkeys[0])
-        ldapconn.set_key(KEY_USAGE_ENC, self.host, principal, pubkeys[1])
+        ldapconn.set_key(KEY_USAGE_SIG, servicename, self.host, principal, pubkeys[0])
+        ldapconn.set_key(KEY_USAGE_ENC, servicename, self.host, principal, pubkeys[1])
 
     @property
     def server_keys(self):
-- 
2.5.5

-------------- next part --------------
From 8fa16b34e9c866d2f2470d70cb4b265e28013a16 Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftweedal at redhat.com>
Date: Mon, 11 Apr 2016 16:47:33 +1000
Subject: [PATCH 54/54] Setup lightweight CA key retrieval on install/upgrade

To configure Dogtag lightweight CA key replication on installation
and upgrade:

- add the 'dogtag/$HOSTNAME' service principal
- create the pricipal's Custodia keys
- add ACI to allow the principal to read server Custodia keys
- retrieve keytab
- configure the IPACustodiaKeyRetriever in CS.cfg

Part of: https://fedorahosted.org/freeipa/ticket/4559
---
 install/tools/ipa-ca-install        |  4 ++++
 install/updates/20-aci.update       |  3 +++
 ipaplatform/base/constants.py       |  1 +
 ipaserver/install/cainstance.py     | 43 +++++++++++++++++++++++++++++++++++++
 ipaserver/install/server/install.py |  8 ++++++-
 ipaserver/install/server/upgrade.py |  6 +++++-
 6 files changed, 63 insertions(+), 2 deletions(-)

diff --git a/install/tools/ipa-ca-install b/install/tools/ipa-ca-install
index 1bc5def03bf687a1e4f9fb38a54363b5429c8fc4..0af5b39116b4649423ed2a51579e2adc767d802b 100755
--- a/install/tools/ipa-ca-install
+++ b/install/tools/ipa-ca-install
@@ -226,6 +226,10 @@ def install_master(safe_options, options):
     ca.install_check(True, None, options)
     ca.install(True, None, options)
 
+    CA = cainstance.CAInstance(
+            api.env.realm, certs.NSS_DIR, host_name=api.env.host)
+    CA.setup_lightweight_ca_key_retrieval()
+
 
 def install(safe_options, options, filename):
     options.promote = False
diff --git a/install/updates/20-aci.update b/install/updates/20-aci.update
index 4802ae0458e8b870bf3127764ebabac1a48f7cf2..2e9a36da442c392c9161861615b1744eeb6b799c 100644
--- a/install/updates/20-aci.update
+++ b/install/updates/20-aci.update
@@ -136,3 +136,6 @@ add:aci: (target = "ldap:///cn=replication,cn=etc,$SUFFIX")(targetattr = "nsDS5R
 dn: cn=ipa,cn=etc,$SUFFIX
 add:aci: (target = "ldap:///cn=*/($$dn),cn=custodia,cn=ipa,cn=etc,$SUFFIX")(version 3.0; acl "IPA server hosts can create own Custodia secrets"; allow(add) groupdn = "ldap:///cn=ipaservers,cn=hostgroups,cn=accounts,$SUFFIX" and userdn = "ldap:///fqdn=($$dn),cn=computers,cn=accounts,$SUFFIX";)
 add:aci: (target = "ldap:///cn=*/($$dn),cn=custodia,cn=ipa,cn=etc,$SUFFIX")(targetattr = "ipaPublicKey")(version 3.0; acl "IPA server hosts can manage own Custodia secrets"; allow(write) groupdn = "ldap:///cn=ipaservers,cn=hostgroups,cn=accounts,$SUFFIX" and userdn = "ldap:///fqdn=($$dn),cn=computers,cn=accounts,$SUFFIX";)
+
+# Dogtag service principals can search Custodia keys
+add:aci: (target = "ldap:///cn=*,cn=custodia,cn=ipa,cn=etc,$SUFFIX")(targetattr = "ipaPublicKey || ipaKeyUsage || memberPrincipal")(version 3.0; acl "Dogtag service principals can search Custodia keys"; allow(read, search, compare) userdn = "ldap:///krbprincipalname=dogtag/*@$REALM,cn=services,cn=accounts,$SUFFIX";)
diff --git a/ipaplatform/base/constants.py b/ipaplatform/base/constants.py
index 3e1c4c6f761444bf1e8d527691aa53282e46f17e..26a9799838a2b3fb2d5ebab9e5e3cf7c4ba041ef 100644
--- a/ipaplatform/base/constants.py
+++ b/ipaplatform/base/constants.py
@@ -17,6 +17,7 @@ class BaseConstantsNamespace(object):
     NAMED_GROUP = "named"
     PKI_USER = 'pkiuser'
     PKI_GROUP = 'pkiuser'
+    PKI_GSSAPI_SERVICE_NAME = 'dogtag'
     # ntpd init variable used for daemon options
     NTPD_OPTS_VAR = "OPTIONS"
     # quote used for daemon options
diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py
index a21f7d2671461dfb99797d39fc7ee5706317241f..7e1aaf5d7ae5744d043787d1b5d3ab6bf6fc7333 100644
--- a/ipaserver/install/cainstance.py
+++ b/ipaserver/install/cainstance.py
@@ -59,6 +59,7 @@ from ipapython.certdb import get_ca_nickname
 from ipapython.dn import DN
 from ipapython.ipa_log_manager import log_mgr,\
     standard_logging_setup, root_logger
+from ipapython.secrets.kem import IPAKEMKeys
 
 from ipaserver.install import certs
 from ipaserver.install import dsinstance
@@ -66,6 +67,7 @@ from ipaserver.install import installutils
 from ipaserver.install import ldapupdate
 from ipaserver.install import replication
 from ipaserver.install import service
+from ipaserver.install import sysupgrade
 from ipaserver.install.dogtaginstance import (export_kra_agent_pem,
                                               DogtagInstance)
 from ipaserver.plugins import ldap2
@@ -1356,11 +1358,52 @@ class CAInstance(DogtagInstance):
         self.step("updating IPA configuration", update_ipa_conf)
         self.step("Restart HTTP server to pick up changes",
                   self.__restart_http_instance)
+        self.step("Configure lightweight CA key retrieval",
+                  self.setup_lightweight_ca_key_retrieval)
 
         self.step("enabling CA instance", self.__enable_instance)
 
         self.start_creation(runtime=210)
 
+    def setup_lightweight_ca_key_retrieval(self):
+        if sysupgrade.get_upgrade_state('dogtag', 'setup_lwca_key_retrieval'):
+            return
+
+        root_logger.info('[Set up lightweight CA key retrieval]')
+
+        service = constants.PKI_GSSAPI_SERVICE_NAME
+        principal = '{}/{}@{}'.format(service, api.env.host, self.realm)
+        pent = pwd.getpwnam(constants.PKI_USER)
+
+        root_logger.info('Creating principal')
+        installutils.kadmin_addprinc(principal)
+        self.suffix = ipautil.realm_to_suffix(self.realm)
+        if not self.admin_conn:
+            self.ldap_connect()
+        self.move_service(principal)
+
+        root_logger.info('Retrieving keytab')
+        keytab = os.path.join(paths.PKI_TOMCAT, service + '.keytab')
+        installutils.create_keytab(keytab, principal)
+        os.chmod(keytab, 0o600)
+        os.chown(keytab, pent.pw_uid, pent.pw_gid)
+
+        root_logger.info('Creating Custodia keys')
+        keyfile = os.path.join(paths.PKI_TOMCAT, service + '.keys')
+        keystore = IPAKEMKeys({'server_keys': keyfile})
+        keystore.generate_keys(service)
+        os.chmod(keyfile, 0o600)
+        os.chown(keyfile, pent.pw_uid, pent.pw_gid)
+
+        root_logger.info('Configuring key retriever')
+        installutils.set_directive(
+            paths.CA_CS_CFG_PATH,
+            'features.authority.keyRetrieverClass',
+            'com.netscape.ca.IPACustodiaKeyRetriever',
+            quotes=False, separator='=')
+
+        sysupgrade.set_upgrade_state('dogtag', 'setup_lwca_key_retieval', True)
+
 
 def replica_ca_install_check(config):
     if not config.setup_ca:
diff --git a/ipaserver/install/server/install.py b/ipaserver/install/server/install.py
index f01022c4c3a056513db47f70727aa48157a8c6f2..d9fcd7e6098c1bdd7647c300695f583f43bde9e5 100644
--- a/ipaserver/install/server/install.py
+++ b/ipaserver/install/server/install.py
@@ -892,7 +892,8 @@ def install(installer):
         ca.install_step_0(False, None, options)
 
         # Now put the CA cert where other instances exepct it
-        ca_instance = cainstance.CAInstance(realm_name, certs.NSS_DIR)
+        ca_instance = cainstance.CAInstance(
+            realm_name, certs.NSS_DIR, host_name=host_name)
         ca_instance.publish_ca_cert(CACERT)
     else:
         # Put the CA cert where other instances expect it
@@ -922,6 +923,11 @@ def install(installer):
     # generated
     ds.add_cert_to_service()
 
+    if setup_ca:
+        # CA was configured before Kerberos;
+        # add Custodia client princ and keys now
+        ca_instance.setup_lightweight_ca_key_retrieval()
+
     memcache = memcacheinstance.MemcacheInstance()
     memcache.create_instance('MEMCACHE', host_name, dm_password,
                              ipautil.realm_to_suffix(realm_name))
diff --git a/ipaserver/install/server/upgrade.py b/ipaserver/install/server/upgrade.py
index 3e60cfd3630c359268cf16219527088b5c63ba86..cc003c7146d547b5778f4d5d8d1c4f7eedc69ec7 100644
--- a/ipaserver/install/server/upgrade.py
+++ b/ipaserver/install/server/upgrade.py
@@ -1463,7 +1463,8 @@ def upgrade_configuration():
     if subject_base:
         sub_dict['SUBJECT_BASE'] = subject_base
 
-    ca = cainstance.CAInstance(api.env.realm, certs.NSS_DIR)
+    ca = cainstance.CAInstance(
+            api.env.realm, certs.NSS_DIR, host_name=api.env.host)
 
     with installutils.stopped_service('pki-tomcatd', 'pki-tomcat'):
         # Dogtag must be stopped to be able to backup CS.cfg config
@@ -1658,6 +1659,9 @@ def upgrade_configuration():
     ca_import_included_profiles(ca)
     add_default_caacl(ca)
 
+    if ca.is_configured():
+        ca.setup_lightweight_ca_key_retrieval()
+
     set_sssd_domain_option('ipa_server_mode', 'True')
 
     if ds_running and not ds.is_running():
-- 
2.5.5



More information about the Freeipa-devel mailing list