URL: https://github.com/freeipa/freeipa/pull/1819
Author: tiran
 Title: #1819: CA replica PKCS12 workaround for SQL NSSDB
Action: opened

PR body:
"""
CA replica installation fails, because 'caSigningCert cert-pki-ca' is
imported a second time under a different name. The issue is caused
by the fact, that SQL NSS DB handles duplicated certificates differently
than DBM format.

Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1561730
Signed-off-by: Christian Heimes <chei...@redhat.com>
"""

To pull the PR as Git branch:
git remote add ghfreeipa https://github.com/freeipa/freeipa
git fetch ghfreeipa pull/1819/head:pr1819
git checkout pr1819
From 7fd47c5d5c841d81fde45bbe6080a758cb137f5c Mon Sep 17 00:00:00 2001
From: Christian Heimes <chei...@redhat.com>
Date: Tue, 17 Apr 2018 07:10:48 +0200
Subject: [PATCH] CA replica PKCS12 workaround for SQL NSSDB

CA replica installation fails, because 'caSigningCert cert-pki-ca' is
imported a second time under a different name. The issue is caused
by the fact, that SQL NSS DB handles duplicated certificates differently
than DBM format.

Fixes: https://bugzilla.redhat.com/show_bug.cgi?id=1561730
Signed-off-by: Christian Heimes <chei...@redhat.com>
---
 freeipa.spec.in                       |  2 +-
 ipaserver/install/custodiainstance.py | 69 ++++++++++++++++++-----------------
 2 files changed, 36 insertions(+), 35 deletions(-)

diff --git a/freeipa.spec.in b/freeipa.spec.in
index 41cd59ea86..873a054ec4 100644
--- a/freeipa.spec.in
+++ b/freeipa.spec.in
@@ -84,7 +84,7 @@
 %endif
 
 # Require Dogtag PKI 10.6.0 with Python 3 and SQL NSSDB fixes
-%global pki_version 10.6.0-0.2
+%global pki_version 10.6.0-1
 
 %define krb5_base_version %(LC_ALL=C rpm -q --qf '%%{VERSION}' krb5-devel | grep -Eo '^[^.]+\.[^.]+')
 
diff --git a/ipaserver/install/custodiainstance.py b/ipaserver/install/custodiainstance.py
index 159976f552..8b0c5e0010 100644
--- a/ipaserver/install/custodiainstance.py
+++ b/ipaserver/install/custodiainstance.py
@@ -4,22 +4,22 @@
 
 import logging
 
+from ipalib import api
+from ipalib.install.certstore import get_ca_certs_nss
 from ipaserver.secrets.kem import IPAKEMKeys, KEMLdap
 from ipaserver.secrets.client import CustodiaClient
 from ipaplatform.paths import paths
 from ipaplatform.constants import constants
 from ipaserver.install.service import SimpleServiceInstance
 from ipapython import ipautil
-from ipapython.certdb import NSSDatabase
+from ipapython.certdb import NSSDatabase, get_ca_nickname
 from ipaserver.install import installutils
 from ipaserver.install import ldapupdate
 from ipaserver.install import sysupgrade
 from base64 import b64decode
 from jwcrypto.common import json_decode
-import shutil
 import os
 import stat
-import tempfile
 import time
 import pwd
 
@@ -178,54 +178,55 @@ def __CustodiaClient(self, server):
                               paths.KRB5_KEYTAB, server, realm=self.realm)
 
     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
-
+        # Fetch all needed certs one by one, then combine them in a single
+        # PKCS12 file
         prefix = data['prefix']
         certlist = data['list']
-
         cli = self.__CustodiaClient(server=ca_host)
 
-        # Temporary nssdb
-        tmpnssdir = tempfile.mkdtemp(dir=paths.TMP)
-        tmpdb = NSSDatabase(tmpnssdir)
-        tmpdb.create_db()
-        try:
+        with NSSDatabase(None, dbtype='sql') as tmpdb:
+            tmpdb.create_db()
             # Cert file password
-            crtpwfile = os.path.join(tmpnssdir, 'crtpwfile')
+            crtpwfile = os.path.join(tmpdb.secdir, 'crtpwfile')
             with open(crtpwfile, 'w+') as f:
                 f.write(cacerts_pwd)
-                f.flush()
 
             for nickname in certlist:
                 value = cli.fetch_key(os.path.join(prefix, nickname), False)
                 v = json_decode(value)
-                pk12pwfile = os.path.join(tmpnssdir, 'pk12pwfile')
+                pk12pwfile = os.path.join(tmpdb.secdir, 'pk12pwfile')
                 with open(pk12pwfile, 'w+') as f:
                     f.write(v['export password'])
-                pk12file = os.path.join(tmpnssdir, 'pk12file')
+                pk12file = os.path.join(tmpdb.secdir, 'pk12file')
                 with open(pk12file, 'wb') as f:
                     f.write(b64decode(v['pkcs12 data']))
-                ipautil.run([paths.PK12UTIL,
-                             '-d', tmpdb.secdir,
-                             '-k', tmpdb.pwd_file,
-                             '-n', nickname,
-                             '-i', pk12file,
-                             '-w', pk12pwfile])
-
-            # Add CA certificates
-            self.suffix = ipautil.realm_to_suffix(self.realm)
-            self.export_ca_certs_nssdb(tmpdb, True)
+                tmpdb.run_pk12util([
+                    '-k', tmpdb.pwd_file,
+                    '-n', nickname,
+                    '-i', pk12file,
+                    '-w', pk12pwfile
+                ])
+
+            # Add CA certificates, but don't import the main CA cert. It's
+            # already present as 'caSigningCert cert-pki-ca'. With SQL db
+            # format, a second import would rename the certificate. See
+            # https://pagure.io/freeipa/issue/7498 for more details.
+            conn = api.Backend.ldap2
+            suffix = ipautil.realm_to_suffix(self.realm)
+            ca_certs = get_ca_certs_nss(conn, suffix, self.realm, True)
+            for cert, nickname, trust_flags in ca_certs:
+                if nickname == get_ca_nickname(self.realm):
+                    continue
+                tmpdb.add_cert(cert, nickname, trust_flags)
 
             # Now that we gathered all certs, re-export
-            ipautil.run([paths.PKCS12EXPORT,
-                         '-d', tmpdb.secdir,
-                         '-p', tmpdb.pwd_file,
-                         '-w', crtpwfile,
-                         '-o', cacerts_file])
-
-        finally:
-            shutil.rmtree(tmpnssdir)
+            ipautil.run([
+                paths.PKCS12EXPORT,
+                '-d', tmpdb.secdir,
+                '-p', tmpdb.pwd_file,
+                '-w', crtpwfile,
+                '-o', cacerts_file
+            ])
 
     def get_ca_keys(self, ca_host, cacerts_file, cacerts_pwd):
         certlist = ['caSigningCert cert-pki-ca',
_______________________________________________
FreeIPA-devel mailing list -- freeipa-devel@lists.fedorahosted.org
To unsubscribe send an email to freeipa-devel-le...@lists.fedorahosted.org

Reply via email to