[Freeipa-devel] [PATCH] 0056 Add custodia store for lightweight CA key replication

Fraser Tweedale ftweedal at redhat.com
Thu May 5 07:05:30 UTC 2016


G'day team,

This patch implements a new Custodia store type to be used for LWCA
keys.  Simo gave a preliminary review a couple weeks ago (I was
holding off because required Dogtag bits were not yet merged... they
are now, so here's the patch ^_^)

Cheers,
Fraser
-------------- next part --------------
From 42ad22dddf4ea05792a64dbab8ff810fa4a075f2 Mon Sep 17 00:00:00 2001
From: Fraser Tweedale <ftweedal at redhat.com>
Date: Tue, 19 Apr 2016 11:47:29 +1000
Subject: [PATCH] Add custodia store for lightweight CA key replication

Due to limitations in Dogtag's use of NSSDB, importing private keys
must be done by the Dogtag Java process itself.  This requires a
PKIArchiveOptions format (signing key wrapped with host CA key) -
PKCS #12 cannot be used because that would require decrypting the
key in Dogtag's memory, albeit temporarily.

Add a new custodia store that executes a 'pki' command to acquire
the wrapped key.

Part of: https://fedorahosted.org/freeipa/ticket/4559
---
 ipaplatform/base/paths.py  |  1 +
 ipapython/secrets/store.py | 53 ++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 54 insertions(+)

diff --git a/ipaplatform/base/paths.py b/ipaplatform/base/paths.py
index ca7eb6cf47b4442fa538a47c74846e13c25e02e8..bbd95a327971c2c1d75102bdef125dc81327ddff 100644
--- a/ipaplatform/base/paths.py
+++ b/ipaplatform/base/paths.py
@@ -214,6 +214,7 @@ class BasePathNamespace(object):
     NTPD = "/usr/sbin/ntpd"
     PKIDESTROY = "/usr/sbin/pkidestroy"
     PKISPAWN = "/usr/sbin/pkispawn"
+    PKI = "/usr/bin/pki"
     REMOVE_DS_PL = "/usr/sbin/remove-ds.pl"
     RESTORECON = "/usr/sbin/restorecon"
     SELINUXENABLED = "/usr/sbin/selinuxenabled"
diff --git a/ipapython/secrets/store.py b/ipapython/secrets/store.py
index 26dcc468863dd758154c820cc4365418abe3eca8..94edd2dd9105e20e3dcd1069fd166d7863c65e44 100644
--- a/ipapython/secrets/store.py
+++ b/ipapython/secrets/store.py
@@ -51,6 +51,53 @@ def HTTPD_password_callback():
     return password
 
 
+class NSSWrappedCertDB(DBMAPHandler):
+    '''
+    Store that extracts private keys from an NSSDB, wrapped with the
+    private key of the primary CA.
+    '''
+
+    def __init__(self, config, dbmap, nickname):
+        if 'path' not in dbmap:
+            raise ValueError('Configuration does not provide NSSDB path')
+        if 'pwcallback' not in dbmap:
+            raise ValueError('Configuration does not provide Password Calback')
+        if 'wrap_nick' not in dbmap:
+            raise ValueError('Configuration does not provide nickname of wrapping key')
+        self.nssdb_path = dbmap['path']
+        self.nssdb_password = dbmap['pwcallback']()
+        self.wrap_nick = dbmap['wrap_nick']
+        self.target_nick = nickname
+
+    def export_key(self):
+        tdir = tempfile.mkdtemp(dir=paths.TMP)
+        try:
+            nsspwfile = os.path.join(tdir, 'nsspwfile')
+            with open(nsspwfile, 'w+') as f:
+                f.write(self.nssdb_password)
+            wrapped_key_file = os.path.join(tdir, 'wrapped_key')
+            certificate_file = os.path.join(tdir, 'certificate')
+            ipautil.run([
+                paths.PKI, '-d', self.nssdb_path, '-C', nsspwfile,
+                'ca-authority-key-export',
+                '--wrap-nickname', self.wrap_nick,
+                '--target-nickname', self.target_nick,
+                '-o', wrapped_key_file])
+            ipautil.run([
+                paths.CERTUTIL, '-d', self.nssdb_path,
+                '-L', '-n', self.target_nick,
+                '-a', '-o', certificate_file])
+            with open(wrapped_key_file, 'r') as f:
+                wrapped_key = f.read()
+            with open(certificate_file, 'r') as f:
+                certificate = f.read()
+        finally:
+            shutil.rmtree(tdir)
+        return json_encode({
+            'wrapped_key': b64encode(wrapped_key),
+            'certificate': certificate})
+
+
 class NSSCertDB(DBMAPHandler):
 
     def __init__(self, config, dbmap, nickname):
@@ -148,6 +195,12 @@ NAME_DB_MAP = {
         'handler': NSSCertDB,
         'pwcallback': PKI_TOMCAT_password_callback,
     },
+    'ca_wrapped': {
+        'handler': NSSWrappedCertDB,
+        'path': paths.PKI_TOMCAT_ALIAS_DIR,
+        'pwcallback': PKI_TOMCAT_password_callback,
+        'wrap_nick': 'caSigningCert cert-pki-ca',
+    },
     'ra': {
         'type': 'NSSDB',
         'path': paths.HTTPD_ALIAS_DIR,
-- 
2.5.5



More information about the Freeipa-devel mailing list