Hi,

this is the first batch of patches for <https://fedorahosted.org/freeipa/ticket/3641>. It contains port of ipa-server-certinstall to the admintool framework and fixes some bugs.


Note that there's still some work I have to do to make ipa-server-certinstall work properly for installs with CA, currently it works reliably only on CA-less installs.

This patchset also does not make it possible to change the CA certificate (as requested in the ticket). We discussed this with Rob and agreed that it should instead be done as part of <https://fedorahosted.org/freeipa/ticket/3737>. Unless there are any objections, that's what is going to happen.

Honza

--
Jan Cholasta
>From 285b2fc9bc9444c44ff0a33e07ea7f5eba125d7b Mon Sep 17 00:00:00 2001
From: Jan Cholasta <jchol...@redhat.com>
Date: Thu, 4 Jul 2013 14:41:07 +0000
Subject: [PATCH 1/5] Make PKCS#12 handling in ipa-server-certinstall closer to
 what other tools do.

In particular, PKCS#12 validation and server certificate selection is now done
the same way as in ipa-server-install and ipa-replica-prepare.

https://fedorahosted.org/freeipa/ticket/3641
---
 install/tools/ipa-server-certinstall | 52 +++++++++++++-----------------------
 1 file changed, 18 insertions(+), 34 deletions(-)

diff --git a/install/tools/ipa-server-certinstall b/install/tools/ipa-server-certinstall
index bc4dde2..493e685 100755
--- a/install/tools/ipa-server-certinstall
+++ b/install/tools/ipa-server-certinstall
@@ -31,10 +31,13 @@ from ipapython.ipautil import user_input
 
 from ipaserver.install import certs, dsinstance, httpinstance, installutils
 from ipalib import api
+from ipapython import admintool
 from ipapython.ipa_log_manager import *
 from ipapython.dn import DN
 from ipaserver.plugins.ldap2 import ldap2
 
+CACERT = "/etc/ipa/ca.crt"
+
 def get_realm_name():
     c = krbV.default_context()
     return c.default_realm
@@ -72,53 +75,34 @@ def set_ds_cert_name(cert_name, dm_password):
     conn.update_entry(DN(('cn', 'RSA'), ('cn', 'encryption'), ('cn', 'config')), mod)
     conn.disconnect()
 
-def choose_server_cert(server_certs):
-    print "Please select the certificate to use:"
-    num = 1
-    for cert in server_certs:
-        print "%d. %s" % (num, cert[0])
-        num += 1
-
-    while 1:
-        num = user_input("Certificate number", 1)
-        print ""
-        if num < 1 or num > len(server_certs):
-            print "number out of range"
-        else:
-            break
+def import_cert(dirname, pkcs12_fname, pkcs12_passwd, db_password):
+    [pw_fd, pw_name] = tempfile.mkstemp()
+    os.write(pw_fd, pkcs12_passwd)
+    os.close(pw_fd)
 
-    return server_certs[num - 1]
+    try:
+        server_cert = installutils.check_pkcs12(
+            pkcs12_info=(pkcs12_fname, pw_name),
+            ca_file=CACERT,
+            hostname=api.env.host)
+    except admintool.ScriptError, e:
+        print str(e)
+        sys.exit(1)
 
-def import_cert(dirname, pkcs12_fname, pkcs12_passwd, db_password):
     cdb = certs.CertDB(api.env.realm, nssdir=dirname)
     cdb.create_passwd_file(db_password)
     cdb.create_certdbs()
-    [pw_fd, pw_name] = tempfile.mkstemp()
-    os.write(pw_fd, pkcs12_passwd)
-    os.close(pw_fd)
 
     try:
         try:
+            cdb.nssdb.import_pem_cert('CA', 'CT,CT,', CACERT)
             cdb.import_pkcs12(pkcs12_fname, pw_name)
-            ca_names = cdb.find_root_cert_from_pkcs12(pkcs12_fname, pw_name)
         except RuntimeError, e:
             print str(e)
             sys.exit(1)
     finally:
         os.remove(pw_name)
 
-    server_certs = cdb.find_server_certs()
-    if len(server_certs) == 0:
-        print "could not find a suitable server cert in import"
-        sys.exit(1)
-    elif len(server_certs) == 1:
-        server_cert = server_certs[0]
-    else:
-        server_cert = choose_server_cert(server_certs)
-
-    for ca in ca_names:
-        cdb.trust_root_cert(ca)
-
     return server_cert
 
 def main():
@@ -149,12 +133,12 @@ def main():
             fd.close()
 
             server_cert = import_cert(dirname, pkcs12_fname, options.dirsrv_pin, passwd)
-            set_ds_cert_name(server_cert[0], dm_password)
+            set_ds_cert_name(server_cert, dm_password)
 
         if options.http:
             dirname = certs.NSS_DIR
             server_cert = import_cert(dirname, pkcs12_fname, options.http_pin, "")
-            installutils.set_directive(httpinstance.NSS_CONF, 'NSSNickname', server_cert[0])
+            installutils.set_directive(httpinstance.NSS_CONF, 'NSSNickname', server_cert)
 
             # Fix the database permissions
             os.chmod(dirname + "/cert8.db", 0640)
-- 
1.8.3.1

>From c85eed733fb4da37d8e126697563d6a0f8340ddb Mon Sep 17 00:00:00 2001
From: Jan Cholasta <jchol...@redhat.com>
Date: Thu, 4 Jul 2013 15:45:42 +0000
Subject: [PATCH 2/5] Port ipa-server-certinstall to the admintool framework.

https://fedorahosted.org/freeipa/ticket/3641
---
 install/tools/ipa-server-certinstall        | 145 +-------------------------
 ipaserver/install/ipa_server_certinstall.py | 154 ++++++++++++++++++++++++++++
 2 files changed, 158 insertions(+), 141 deletions(-)
 create mode 100644 ipaserver/install/ipa_server_certinstall.py

diff --git a/install/tools/ipa-server-certinstall b/install/tools/ipa-server-certinstall
index 493e685..9bb0ef8 100755
--- a/install/tools/ipa-server-certinstall
+++ b/install/tools/ipa-server-certinstall
@@ -1,7 +1,7 @@
 #! /usr/bin/python -E
-# Authors: Karl MacMillan <kmacmil...@mentalrootkit.com>
+# Authors: Jan Cholasta <jchol...@redhat.com>
 #
-# Copyright (C) 2007  Red Hat
+# Copyright (C) 2013  Red Hat
 # see file 'COPYING' for use and warranty information
 #
 # This program is free software; you can redistribute it and/or modify
@@ -18,143 +18,6 @@
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 #
 
-import sys
-import os
-import pwd
-import tempfile
+from ipaserver.install.ipa_server_certinstall import ServerCertInstall
 
-import traceback
-
-import krbV
-
-from ipapython.ipautil import user_input
-
-from ipaserver.install import certs, dsinstance, httpinstance, installutils
-from ipalib import api
-from ipapython import admintool
-from ipapython.ipa_log_manager import *
-from ipapython.dn import DN
-from ipaserver.plugins.ldap2 import ldap2
-
-CACERT = "/etc/ipa/ca.crt"
-
-def get_realm_name():
-    c = krbV.default_context()
-    return c.default_realm
-
-def parse_options():
-    from optparse import OptionParser
-    parser = OptionParser()
-
-    parser.add_option("-d", "--dirsrv", dest="dirsrv", action="store_true",
-                      default=False, help="install certificate for the directory server")
-    parser.add_option("-w", "--http", dest="http", action="store_true",
-                      default=False, help="install certificate for the http server")
-    parser.add_option("--dirsrv_pin", dest="dirsrv_pin",
-                      help="The password of the Directory Server PKCS#12 file")
-    parser.add_option("--http_pin", dest="http_pin",
-                      help="The password of the Apache Server PKCS#12 file")
-
-    options, args = parser.parse_args()
-
-    if not options.dirsrv and not options.http:
-        parser.error("you must specify dirsrv and/or http")
-    if ((options.dirsrv and not options.dirsrv_pin) or
-            (options.http and not options.http_pin)):
-        parser.error("you must provide the password for the PKCS#12 file")
-
-    if len(args) != 1:
-        parser.error("you must provide a pkcs12 filename")
-
-    return options, args[0]
-
-def set_ds_cert_name(cert_name, dm_password):
-    conn = ldap2(shared_instance=False, base_dn='')
-    conn.connect(bind_dn=DN(('cn', 'directory manager')), bind_pw=dm_password)
-    mod = {'nssslpersonalityssl': cert_name}
-    conn.update_entry(DN(('cn', 'RSA'), ('cn', 'encryption'), ('cn', 'config')), mod)
-    conn.disconnect()
-
-def import_cert(dirname, pkcs12_fname, pkcs12_passwd, db_password):
-    [pw_fd, pw_name] = tempfile.mkstemp()
-    os.write(pw_fd, pkcs12_passwd)
-    os.close(pw_fd)
-
-    try:
-        server_cert = installutils.check_pkcs12(
-            pkcs12_info=(pkcs12_fname, pw_name),
-            ca_file=CACERT,
-            hostname=api.env.host)
-    except admintool.ScriptError, e:
-        print str(e)
-        sys.exit(1)
-
-    cdb = certs.CertDB(api.env.realm, nssdir=dirname)
-    cdb.create_passwd_file(db_password)
-    cdb.create_certdbs()
-
-    try:
-        try:
-            cdb.nssdb.import_pem_cert('CA', 'CT,CT,', CACERT)
-            cdb.import_pkcs12(pkcs12_fname, pw_name)
-        except RuntimeError, e:
-            print str(e)
-            sys.exit(1)
-    finally:
-        os.remove(pw_name)
-
-    return server_cert
-
-def main():
-    if os.geteuid() != 0:
-        sys.exit("\nYou must be root to run this script.\n")
-
-    installutils.check_server_configuration()
-
-    options, pkcs12_fname = parse_options()
-
-    cfg = dict(in_server=True,)
-
-    standard_logging_setup("/var/log/ipa/default.log")
-
-    api.bootstrap(**cfg)
-    api.finalize()
-
-    try:
-        if options.dirsrv:
-            dm_password = installutils.read_password("Directory Manager",
-                confirm=False, validate=False, retry=False)
-            if dm_password is None:
-                sys.exit("\nDirectory Manager password required")
-            realm = get_realm_name()
-            dirname = dsinstance.config_dirname(dsinstance.realm_to_serverid(realm))
-            fd = open(dirname + "/pwdfile.txt")
-            passwd = fd.read()
-            fd.close()
-
-            server_cert = import_cert(dirname, pkcs12_fname, options.dirsrv_pin, passwd)
-            set_ds_cert_name(server_cert, dm_password)
-
-        if options.http:
-            dirname = certs.NSS_DIR
-            server_cert = import_cert(dirname, pkcs12_fname, options.http_pin, "")
-            installutils.set_directive(httpinstance.NSS_CONF, 'NSSNickname', server_cert)
-
-            # Fix the database permissions
-            os.chmod(dirname + "/cert8.db", 0640)
-            os.chmod(dirname + "/key3.db", 0640)
-            os.chmod(dirname + "/secmod.db", 0640)
-
-            pent = pwd.getpwnam("apache")
-            os.chown(dirname + "/cert8.db", 0, pent.pw_gid )
-            os.chown(dirname + "/key3.db", 0, pent.pw_gid )
-            os.chown(dirname + "/secmod.db", 0, pent.pw_gid )
-
-    except Exception, e:
-        traceback.print_exc(file=sys.stderr)
-        sys.exit("an unexpected error occurred: %s" % str(e))
-
-    return 0
-
-if __name__ == '__main__':
-    installutils.run_script(main, operation_name='ipa-server-certinstall')
+ServerCertInstall.run_cli()
diff --git a/ipaserver/install/ipa_server_certinstall.py b/ipaserver/install/ipa_server_certinstall.py
new file mode 100644
index 0000000..8eff3ee
--- /dev/null
+++ b/ipaserver/install/ipa_server_certinstall.py
@@ -0,0 +1,154 @@
+#! /usr/bin/python
+# Authors: Karl MacMillan <kmacmil...@mentalrootkit.com>
+#          Jan Cholasta <jchol...@redhat.com>
+#
+# Copyright (C) 2007-2013  Red Hat
+# see file 'COPYING' for use and warranty information
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+#
+
+import sys
+import os
+import os.path
+import pwd
+
+from ipapython import admintool
+from ipapython.dn import DN
+from ipapython.ipautil import user_input, write_tmp_file
+from ipalib import api
+from ipaserver.install import certs, dsinstance, httpinstance, installutils
+from ipaserver.plugins.ldap2 import ldap2
+
+CACERT = "/etc/ipa/ca.crt"
+
+class ServerCertInstall(admintool.AdminTool):
+    command_name = 'ipa-server-certinstall'
+
+    usage = "%prog [options]"
+
+    description = "Install new SSL server certificates."
+
+    @classmethod
+    def add_options(cls, parser):
+        super(ServerCertInstall, cls).add_options(parser)
+
+        parser.add_option(
+            "-d", "--dirsrv",
+            dest="dirsrv", action="store_true", default=False,
+            help="install certificate for the directory server")
+        parser.add_option(
+            "-w", "--http",
+            dest="http", action="store_true", default=False,
+            help="install certificate for the http server")
+        parser.add_option(
+            "--dirsrv_pin",
+            dest="dirsrv_pin",
+            help="The password of the Directory Server PKCS#12 file")
+        parser.add_option(
+            "--http_pin",
+            dest="http_pin",
+            help="The password of the Apache Server PKCS#12 file")
+
+    def validate_options(self):
+        super(ServerCertInstall, self).validate_options(needs_root=True)
+
+        installutils.check_server_configuration()
+
+        if not self.options.dirsrv and not self.options.http:
+            self.option_parser.error("you must specify dirsrv and/or http")
+        if ((self.options.dirsrv and not self.options.dirsrv_pin) or
+                (self.options.http and not self.options.http_pin)):
+            self.option_parser.error("you must provide the password for the "
+                                     "PKCS#12 file")
+
+        if len(self.args) != 1:
+            self.option_parser.error("you must provide a pkcs12 filename")
+
+    def ask_for_options(self):
+        super(ServerCertInstall, self).ask_for_options()
+
+        if self.options.dirsrv:
+            self.dm_password = installutils.read_password(
+                "Directory Manager", confirm=False, validate=False, retry=False)
+            if self.dm_password is None:
+                raise admintool.ScriptError(
+                    "Directory Manager password required")
+
+    def run(self):
+        api.bootstrap(in_server=True)
+        api.finalize()
+
+        self.pkcs12_fname = self.args[0]
+
+        if self.options.dirsrv:
+            self.install_dirsrv_cert()
+
+        if self.options.http:
+            self.install_http_cert()
+
+    def install_dirsrv_cert(self):
+        serverid = dsinstance.realm_to_serverid(api.env.realm)
+        dirname = dsinstance.config_dirname(serverid)
+
+        pwdfile = os.path.join(dirname, 'pwdfile.txt')
+        with open(pwdfile) as fd:
+            passwd = fd.read()
+
+        server_cert = self.import_cert(dirname, self.options.dirsrv_pin, passwd)
+
+        conn = ldap2(shared_instance=False, base_dn='')
+        conn.connect(bind_dn=DN(('cn', 'directory manager')),
+                     bind_pw=self.dm_password)
+
+        entry = conn.make_entry(DN(('cn', 'RSA'), ('cn', 'encryption'),
+                                   ('cn', 'config')),
+                                nssslpersonalityssl=[server_cert])
+        conn.update_entry(entry)
+
+        conn.disconnect()
+
+    def install_http_cert(self):
+        dirname = certs.NSS_DIR
+
+        server_cert = self.import_cert(dirname, self.options.http_pin, "")
+
+        installutils.set_directive(httpinstance.NSS_CONF,
+                                   'NSSNickname', server_cert)
+
+        # Fix the database permissions
+        os.chmod(os.path.join(dirname, 'cert8.db'), 0640)
+        os.chmod(os.path.join(dirname, 'key3.db'), 0640)
+        os.chmod(os.path.join(dirname, 'secmod.db'), 0640)
+
+        pent = pwd.getpwnam("apache")
+        os.chown(os.path.join(dirname, 'cert8.db'), 0, pent.pw_gid)
+        os.chown(os.path.join(dirname, 'key3.db'), 0, pent.pw_gid)
+        os.chown(os.path.join(dirname, 'secmod.db'), 0, pent.pw_gid)
+
+    def import_cert(self, dirname, pkcs12_passwd, db_password):
+        pw = write_tmp_file(pkcs12_passwd)
+        server_cert = installutils.check_pkcs12(
+            pkcs12_info=(self.pkcs12_fname, pw.name),
+            ca_file=CACERT,
+            hostname=api.env.host)
+
+        cdb = certs.CertDB(api.env.realm, nssdir=dirname)
+        try:
+            cdb.create_from_pkcs12(self.pkcs12_fname, pw.name,
+                                   db_password, CACERT)
+        except RuntimeError, e:
+            raise admintool.ScriptError(str(e))
+
+        return server_cert
-- 
1.8.3.1

>From eced39d6b16433b2bbc0c0edf79117bb8207b80c Mon Sep 17 00:00:00 2001
From: Jan Cholasta <jchol...@redhat.com>
Date: Thu, 4 Jul 2013 15:46:05 +0000
Subject: [PATCH 3/5] Remove unused NSSDatabase and CertDB method
 find_root_cert_from_pkcs12.

https://fedorahosted.org/freeipa/ticket/3641
---
 ipaserver/install/certs.py | 42 ------------------------------------------
 1 file changed, 42 deletions(-)

diff --git a/ipaserver/install/certs.py b/ipaserver/install/certs.py
index 06925d5..531ea76 100644
--- a/ipaserver/install/certs.py
+++ b/ipaserver/install/certs.py
@@ -192,44 +192,6 @@ class NSSDatabase(object):
                 raise RuntimeError("unknown error import pkcs#12 file %s" %
                     pkcs12_filename)
 
-    def find_root_cert_from_pkcs12(self, pkcs12_fname, passwd_fname=None):
-        """Given a PKCS#12 file, try to find any certificates that do
-           not have a key. The assumption is that these are the root CAs.
-        """
-        args = ["/usr/bin/pk12util", "-d", self.secdir,
-                "-l", pkcs12_fname,
-                "-k", passwd_fname]
-        if passwd_fname:
-            args = args + ["-w", passwd_fname]
-        try:
-            (stdout, stderr, returncode) = ipautil.run(args)
-        except ipautil.CalledProcessError, e:
-            if e.returncode == 17:
-                raise RuntimeError("incorrect password for pkcs#12 file")
-            else:
-                raise RuntimeError("unknown error using pkcs#12 file")
-
-        lines = stdout.split('\n')
-
-        # A simple state machine.
-        # 1 = looking for a line starting with 'Certificate'
-        # 2 = looking for the Friendly name (nickname)
-        nicknames = []
-        state = 1
-        for line in lines:
-            if state == 2:
-                m = re.match("\W+Friendly Name: (.*)", line)
-                if m:
-                    nicknames.append( m.groups(0)[0])
-                    state = 1
-            if line == "Certificate:":
-                state = 2
-            elif line and not line.startswith(' '):
-                # Top-level item that is not a certificate
-                state = 1
-
-        return nicknames
-
     def trust_root_cert(self, root_nickname):
         if root_nickname[:7] == "Builtin":
             root_logger.debug(
@@ -782,10 +744,6 @@ class CertDB(object):
 
         return root_nicknames
 
-    def find_root_cert_from_pkcs12(self, pkcs12_fname, passwd_fname=None):
-        return self.nssdb.find_root_cert_from_pkcs12(pkcs12_fname,
-                                                     passwd_fname=passwd_fname)
-
     def trust_root_cert(self, root_nickname):
         if root_nickname is None:
             root_logger.debug("Unable to identify root certificate to trust. Continuing but things are likely to fail.")
-- 
1.8.3.1

>From b5137825340e548f2fccf08e98e5300ffed923dd Mon Sep 17 00:00:00 2001
From: Jan Cholasta <jchol...@redhat.com>
Date: Thu, 4 Jul 2013 18:42:29 +0200
Subject: [PATCH 4/5] Use correct password for httpd NSS DB in
 ipa-server-certinstall.

https://fedorahosted.org/freeipa/ticket/3641
---
 ipaserver/install/ipa_server_certinstall.py | 15 +++++++++------
 1 file changed, 9 insertions(+), 6 deletions(-)

diff --git a/ipaserver/install/ipa_server_certinstall.py b/ipaserver/install/ipa_server_certinstall.py
index 8eff3ee..eb7325d 100644
--- a/ipaserver/install/ipa_server_certinstall.py
+++ b/ipaserver/install/ipa_server_certinstall.py
@@ -101,12 +101,10 @@ class ServerCertInstall(admintool.AdminTool):
     def install_dirsrv_cert(self):
         serverid = dsinstance.realm_to_serverid(api.env.realm)
         dirname = dsinstance.config_dirname(serverid)
-
         pwdfile = os.path.join(dirname, 'pwdfile.txt')
-        with open(pwdfile) as fd:
-            passwd = fd.read()
 
-        server_cert = self.import_cert(dirname, self.options.dirsrv_pin, passwd)
+        server_cert = self.import_cert(dirname, self.options.dirsrv_pin,
+                                       pwdfile)
 
         conn = ldap2(shared_instance=False, base_dn='')
         conn.connect(bind_dn=DN(('cn', 'directory manager')),
@@ -121,8 +119,10 @@ class ServerCertInstall(admintool.AdminTool):
 
     def install_http_cert(self):
         dirname = certs.NSS_DIR
+        pwdfile = os.path.join(dirname, 'pwdfile.txt')
 
-        server_cert = self.import_cert(dirname, self.options.http_pin, "")
+        server_cert = self.import_cert(dirname, self.options.http_pin,
+                                       pwdfile)
 
         installutils.set_directive(httpinstance.NSS_CONF,
                                    'NSSNickname', server_cert)
@@ -137,13 +137,16 @@ class ServerCertInstall(admintool.AdminTool):
         os.chown(os.path.join(dirname, 'key3.db'), 0, pent.pw_gid)
         os.chown(os.path.join(dirname, 'secmod.db'), 0, pent.pw_gid)
 
-    def import_cert(self, dirname, pkcs12_passwd, db_password):
+    def import_cert(self, dirname, pkcs12_passwd, db_pwdfile):
         pw = write_tmp_file(pkcs12_passwd)
         server_cert = installutils.check_pkcs12(
             pkcs12_info=(self.pkcs12_fname, pw.name),
             ca_file=CACERT,
             hostname=api.env.host)
 
+        with open(db_pwdfile) as fd:
+            db_password = fd.read()
+
         cdb = certs.CertDB(api.env.realm, nssdir=dirname)
         try:
             cdb.create_from_pkcs12(self.pkcs12_fname, pw.name,
-- 
1.8.3.1

>From 4fe3075a4baba0e48e159e54a7464bbf481954a1 Mon Sep 17 00:00:00 2001
From: Jan Cholasta <jchol...@redhat.com>
Date: Thu, 4 Jul 2013 18:43:08 +0200
Subject: [PATCH 5/5] Ignore empty mod error when updating DS SSL config in
 ipa-server-certinstall.

https://fedorahosted.org/freeipa/ticket/3641
---
 ipaserver/install/ipa_server_certinstall.py | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/ipaserver/install/ipa_server_certinstall.py b/ipaserver/install/ipa_server_certinstall.py
index eb7325d..c2cd4df 100644
--- a/ipaserver/install/ipa_server_certinstall.py
+++ b/ipaserver/install/ipa_server_certinstall.py
@@ -27,7 +27,7 @@ import pwd
 from ipapython import admintool
 from ipapython.dn import DN
 from ipapython.ipautil import user_input, write_tmp_file
-from ipalib import api
+from ipalib import api, errors
 from ipaserver.install import certs, dsinstance, httpinstance, installutils
 from ipaserver.plugins.ldap2 import ldap2
 
@@ -113,7 +113,10 @@ class ServerCertInstall(admintool.AdminTool):
         entry = conn.make_entry(DN(('cn', 'RSA'), ('cn', 'encryption'),
                                    ('cn', 'config')),
                                 nssslpersonalityssl=[server_cert])
-        conn.update_entry(entry)
+        try:
+            conn.update_entry(entry)
+        except errors.EmptyModlist:
+            pass
 
         conn.disconnect()
 
-- 
1.8.3.1

_______________________________________________
Freeipa-devel mailing list
Freeipa-devel@redhat.com
https://www.redhat.com/mailman/listinfo/freeipa-devel

Reply via email to