Hi,

the attached patches fix <https://fedorahosted.org/freeipa/ticket/4480> and <https://fedorahosted.org/freeipa/ticket/4489>.

(Note that design page for this is TBD.)

Honza

--
Jan Cholasta
>From ad61849f6070db621d0ed98010bca5fc657e9ff1 Mon Sep 17 00:00:00 2001
From: Jan Cholasta <jchol...@redhat.com>
Date: Wed, 24 Sep 2014 16:22:32 +0200
Subject: [PATCH 1/4] Add NSSDatabase.import_files method for importing files
 in various formats

The files are accepted in PEM and DER certificate, PKCS#7 certificate chain,
PKCS#8 and raw private key and PKCS#12 formats.
---
 ipaserver/install/certs.py | 174 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 174 insertions(+)

diff --git a/ipaserver/install/certs.py b/ipaserver/install/certs.py
index 4d508cd..5221721 100644
--- a/ipaserver/install/certs.py
+++ b/ipaserver/install/certs.py
@@ -195,6 +195,180 @@ class NSSDatabase(object):
                 raise RuntimeError("unknown error import pkcs#12 file %s" %
                     pkcs12_filename)
 
+    def import_files(self, files, db_password_filename, load_keys=False,
+                     key_password=None, key_nickname=None):
+        key_file = None
+        extracted_key = None
+        extracted_certs = ''
+
+        for filename in files:
+            if load_keys:
+                # Try to import file as PKCS#12 file
+                try:
+                    self.import_pkcs12(
+                        filename, db_password_filename, key_password)
+                except RuntimeError:
+                    pass
+                else:
+                    if key_file:
+                        raise RuntimeError(
+                            "Can't load private key from both %s and %s" %
+                            (key_file, filename))
+                    key_file = filename
+
+                    server_certs = self.find_server_certs()
+                    if key_nickname:
+                        for nickname, trust_flags in server_certs:
+                            if nickname == key_nickname:
+                                break
+                        else:
+                            raise RuntimeError(
+                                "Private key \"%s\" not found in %s" %
+                                (key_nickname, filename))
+                    else:
+                        if len(server_certs) > 1:
+                            raise RuntimeError(
+                                "%s server certificates found in %s, "
+                                "expecting only one" %
+                                (len(server_certs), filename))
+
+                    continue
+
+            try:
+                with open(filename, 'rb') as f:
+                    data = f.read()
+            except IOError as e:
+                raise RuntimeError(
+                    "Failed to open %s: %s" % (filename, e.strerror))
+
+            # Try to load file as DER certificate
+            try:
+                x509.load_certificate(data, x509.DER)
+            except NSPRError:
+                pass
+            else:
+                data = x509.make_pem(base64.b64encode(data))
+                extracted_certs += data + '\n'
+                continue
+
+            # Try to parse PEM file
+            matches = re.finditer(
+                r'-----BEGIN (.+?)-----(.*?)-----END \1-----', data, re.DOTALL)
+            loaded = False
+            for match in matches:
+                body = match.group()
+                label = match.group(1)
+                line = len(data[:match.start() + 1].splitlines())
+
+                if label in ('CERTIFICATE', 'X509 CERTIFICATE',
+                             'X.509 CERTIFICATE'):
+                    try:
+                        x509.load_certificate(match.group(2))
+                    except NSPRError as e:
+                        if label != 'CERTIFICATE':
+                            root_logger.warning(
+                                "Skipping certificate in %s at line %s: %s",
+                                filename, line, e)
+                            continue
+                    else:
+                        extracted_certs += body + '\n'
+                        loaded = True
+                        continue
+
+                if label in ('PKCS7', 'PKCS #7 SIGNED DATA', 'CERTIFICATE'):
+                    args = [
+                        paths.OPENSSL, 'pkcs7',
+                        '-print_certs',
+                    ]
+                    try:
+                        stdout, stderr, rc = ipautil.run(args, stdin=body)
+                    except ipautil.CalledProcessError as e:
+                        if label == 'CERTIFICATE':
+                            root_logger.warning(
+                                "Skipping certificate in %s at line %s: %s",
+                                filename, line, e)
+                        else:
+                            root_logger.warning(
+                                "Skipping PKCS#7 in %s at line %s: %s",
+                                filename, line, e)
+                        continue
+                    else:
+                        extracted_certs += stdout + '\n'
+                        loaded = True
+                        continue
+
+                if label in ('PRIVATE KEY', 'ENCRYPTED PRIVATE KEY',
+                             'RSA PRIVATE KEY', 'DSA PRIVATE KEY',
+                             'EC PRIVATE KEY'):
+                    if not load_keys:
+                        continue
+
+                    if key_file:
+                        raise RuntimeError(
+                            "Can't load private key from both %s and %s" %
+                            (key_file, filename))
+
+                    args = [
+                        paths.OPENSSL, 'pkcs8',
+                        '-topk8',
+                        '-passout', 'file:' + db_password_filename,
+                    ]
+                    if ((label != 'PRIVATE KEY' and key_password) or
+                        label == 'ENCRYPTED PRIVATE KEY'):
+                        key_pwdfile = ipautil.write_tmp_file(key_password)
+                        args += [
+                            '-passin', 'file:' + key_pwdfile.name,
+                        ]
+                    try:
+                        stdout, stderr, rc = ipautil.run(args, stdin=body)
+                    except ipautil.CalledProcessError as e:
+                        root_logger.warning(
+                            "Skipping private key in %s at line %s: %s",
+                            filename, line, e)
+                        continue
+                    else:
+                        extracted_key = stdout
+                        key_file = filename
+                        loaded = True
+                        continue
+
+            if not loaded:
+                raise RuntimeError("Failed to load %s" % filename)
+
+        if load_keys and not key_file:
+            raise RuntimeError(
+                "No private key found in %s" % (', '.join(files)))
+
+        nss_certs = x509.load_certificate_list(extracted_certs)
+        nss_cert = None
+        for nss_cert in nss_certs:
+            nickname = str(nss_cert.subject)
+            self.add_cert(nss_cert.der_data, nickname, ',,')
+        del nss_certs, nss_cert
+
+        if extracted_key:
+            in_file = ipautil.write_tmp_file(extracted_certs + extracted_key)
+            out_file = tempfile.NamedTemporaryFile()
+            out_password = ipautil.ipa_generate_password()
+            out_pwdfile = ipautil.write_tmp_file(out_password)
+            args = [
+                paths.OPENSSL, 'pkcs12',
+                '-export',
+                '-in', in_file.name,
+                '-out', out_file.name,
+                '-passin', 'file:' + db_password_filename,
+                '-passout', 'file:' + out_pwdfile.name,
+            ]
+            try:
+                ipautil.run(args)
+            except ipautil.CalledProcessError as e:
+                raise RuntimeError(
+                    "No matching certificate found for private key from %s" %
+                    key_file)
+
+            self.import_pkcs12(out_file.name, db_password_filename,
+                               out_password)
+
     def trust_root_cert(self, root_nickname, trust_flags=None):
         if root_nickname[:7] == "Builtin":
             root_logger.debug(
-- 
1.9.3

>From 2aee09574ac9ccd087f5ce2db29a6303e7f811a1 Mon Sep 17 00:00:00 2001
From: Jan Cholasta <jchol...@redhat.com>
Date: Wed, 24 Sep 2014 16:31:39 +0200
Subject: [PATCH 2/4] External CA installer options usability fixes

The --external_cert_file and --external_ca_file options of ipa-server-install
and ipa-ca-install have been replaced by --external-cert-file option which
accepts multiple files. The files are accepted in PEM and DER certificate and
PKCS#7 certificate chain formats.

https://fedorahosted.org/freeipa/ticket/4480
---
 install/tools/ipa-ca-install                  | 33 +++++++-------
 install/tools/ipa-server-install              | 66 +++++++++++++--------------
 install/tools/man/ipa-ca-install.1            |  3 ++
 install/tools/man/ipa-cacert-manage.1         |  5 +-
 install/tools/man/ipa-server-install.1        | 11 +----
 ipaserver/install/cainstance.py               |  4 +-
 ipaserver/install/installutils.py             | 32 +++++++++++++
 ipaserver/install/ipa_cacert_manage.py        | 30 ++++++------
 ipatests/test_integration/test_external_ca.py |  4 +-
 9 files changed, 104 insertions(+), 84 deletions(-)

diff --git a/install/tools/ipa-ca-install b/install/tools/ipa-ca-install
index fc89412..85e0c97 100755
--- a/install/tools/ipa-ca-install
+++ b/install/tools/ipa-ca-install
@@ -30,7 +30,8 @@ from ipaserver.install import installutils, service
 from ipaserver.install import certs
 from ipaserver.install.installutils import (HostnameLocalhost, ReplicaConfig,
         expand_replica_info, read_replica_info, get_host_name, BadHostError,
-        private_ccache, read_replica_info_dogtag_port, validate_external_cert)
+        private_ccache, read_replica_info_dogtag_port, validate_external_cert,
+        make_external_cert)
 from ipaserver.install import dsinstance, cainstance, bindinstance
 from ipaserver.install.replication import replica_conn_check
 from ipapython import version
@@ -68,10 +69,9 @@ def parse_options():
                       default=False, help="unattended installation never prompts the user")
     parser.add_option("--external-ca", dest="external_ca", action="store_true",
                       default=False, help="Generate a CSR to be signed by an external CA")
-    parser.add_option("--external_cert_file", dest="external_cert_file",
-                      help="PEM file containing a certificate signed by the external CA")
-    parser.add_option("--external_ca_file", dest="external_ca_file",
-                      help="PEM file containing the external CA chain")
+    parser.add_option("--external-cert-file", dest="external_cert_files",
+                      action="append", metavar="FILE",
+                      help="File containing the IPA CA certificate and the external CA certificate chain")
 
     options, args = parser.parse_args()
     safe_options = parser.get_safe_opts(options)
@@ -86,12 +86,9 @@ def parse_options():
         filename = None
 
         if options.external_ca:
-            if options.external_cert_file:
-                parser.error("You cannot specify --external_cert_file "
+            if options.external_cert_files:
+                parser.error("You cannot specify --external-cert-file "
                              "together with --external-ca")
-            if options.external_ca_file:
-                parser.error("You cannot specify --external_ca_file together "
-                             "with --external-ca")
 
     return safe_options, options, filename
 
@@ -264,23 +261,25 @@ def install_master(safe_options, options):
     if options.external_ca:
         if cainstance.is_step_one_done():
             print ("CA is already installed.\nRun the installer with "
-                   "--external-cert-file and --external-ca-file.")
+                   "--external-cert-file.")
             sys.exit(1)
-    elif options.external_cert_file:
+    elif options.external_cert_files:
         if not cainstance.is_step_one_done():
             print ("CA is not installed yet. To install with an external CA "
                    "is a two-stage process.\nFirst run the installer with "
                    "--external-ca.")
             sys.exit(1)
 
+        external_cert_file, external_ca_file = make_external_cert(
+            options.external_cert_files, subject_base)
         try:
-            validate_external_cert(options.external_cert_file,
-                                   options.external_ca_file, subject_base)
+            validate_external_cert(external_cert_file.name,
+                                   external_ca_file.name, subject_base)
         except ValueError, e:
             print e
             sys.exit(1)
 
-    if options.external_cert_file:
+    if options.external_cert_files:
         external = 2
     elif options.external_ca:
         external = 1
@@ -329,8 +328,8 @@ def install_master(safe_options, options):
     else:
         ca.configure_instance(host_name, domain_name, dm_password,
                               dm_password,
-                              cert_file=options.external_cert_file,
-                              cert_chain_file=options.external_ca_file,
+                              cert_file=external_cert_file.name,
+                              cert_chain_file=external_ca_file.name,
                               subject_base=subject_base)
 
     ca.stop(ca.dogtag_constants.PKI_INSTANCE_NAME)
diff --git a/install/tools/ipa-server-install b/install/tools/ipa-server-install
index cb59311..223ac81 100755
--- a/install/tools/ipa-server-install
+++ b/install/tools/ipa-server-install
@@ -38,7 +38,7 @@ import nss.error
 import base64
 import pwd
 import textwrap
-from optparse import OptionGroup, OptionValueError
+from optparse import OptionGroup, OptionValueError, SUPPRESS_HELP
 
 try:
     from ipaserver.install import adtrustinstance
@@ -203,10 +203,15 @@ def parse_options():
     cert_group = OptionGroup(parser, "certificate system options")
     cert_group.add_option("", "--external-ca", dest="external_ca", action="store_true",
                       default=False, help="Generate a CSR for the IPA CA certificate to be signed by an external CA")
-    cert_group.add_option("", "--external_cert_file", dest="external_cert_file",
-                      help="File containing the IPA CA certificate signed by the external CA in PEM format")
-    cert_group.add_option("", "--external_ca_file", dest="external_ca_file",
-                      help="File containing the external CA certificate chain in PEM format")
+    cert_group.add_option("--external-cert-file", dest="external_cert_files",
+                      action="append", metavar="FILE",
+                      help="File containing the IPA CA certificate and the external CA certificate chain")
+    cert_group.add_option("--external_cert_file", dest="external_cert_files",
+                      action="append",
+                      help=SUPPRESS_HELP)
+    cert_group.add_option("--external_ca_file", dest="external_cert_files",
+                      action="append",
+                      help=SUPPRESS_HELP)
     cert_group.add_option("--no-pkinit", dest="setup_pkinit", action="store_false",
                       default=True, help="disables pkinit setup steps")
     cert_group.add_option("--dirsrv_pkcs12", dest="dirsrv_pkcs12",
@@ -315,25 +320,19 @@ def parse_options():
         if options.pkinit_pkcs12 and options.pkinit_pin is None:
             parser.error("You must specify --pkinit_pin with --pkinit_pkcs12")
 
-    if (options.external_cert_file or options.external_ca_file) and options.dirsrv_pkcs12:
-        parser.error(
-            "PKCS#12 options cannot be used with the external CA options.")
+    if options.external_cert_files and options.dirsrv_pkcs12:
+        parser.error("Service certificate file options cannot be used with "
+                     "the external CA options.")
 
     if options.external_ca:
-        if options.external_cert_file:
-            parser.error("You cannot specify --external_cert_file together with --external-ca")
-        if options.external_ca_file:
-            parser.error("You cannot specify --external_ca_file together with --external-ca")
+        if options.external_cert_files:
+            parser.error("You cannot specify --external-cert-file "
+                         "together with --external-ca")
         if options.dirsrv_pkcs12:
             parser.error("You cannot specify PKCS#12 options together with --external-ca")
 
-    if ((options.external_cert_file and not options.external_ca_file) or
-       (not options.external_cert_file and options.external_ca_file)):
-        parser.error("if either external CA option is used, both are required.")
-
-    if (options.external_ca_file and not os.path.isabs(options.external_ca_file)):
-        parser.error("--external-ca-file must use an absolute path")
-    if (options.external_cert_file and not os.path.isabs(options.external_cert_file)):
+    if (options.external_cert_files and
+        any(not os.path.isabs(path) for path in options.external_cert_files)):
         parser.error("--external-cert-file must use an absolute path")
 
     if options.idmax == 0:
@@ -387,11 +386,10 @@ def read_cache(dm_password):
         shutil.rmtree(top_dir)
 
     # These are the only ones that may be overridden
-    for opt in ('external_ca_file', 'external_cert_file'):
-        try:
-            del optdict[opt]
-        except KeyError:
-            pass
+    try:
+        del optdict['external_cert_files']
+    except KeyError:
+        pass
 
     return optdict
 
@@ -621,7 +619,7 @@ def main():
     else:
         standard_logging_setup(paths.IPASERVER_INSTALL_LOG, debug=options.debug)
         print "\nThe log file for this installation can be found in /var/log/ipaserver-install.log"
-        if not options.external_ca and not options.external_cert_file and is_ipa_configured():
+        if not options.external_ca and not options.external_cert_files and is_ipa_configured():
             installation_cleanup = False
             sys.exit("IPA server is already configured on this system.\n" +
                 "If you want to reinstall the IPA server, please uninstall " +
@@ -714,14 +712,14 @@ def main():
     if options.external_ca:
         if cainstance.is_step_one_done():
             print ("CA is already installed.\nRun the installer with "
-                   "--external_cert_file and --external_ca_file.")
+                   "--external-cert-file.")
             sys.exit(1)
         if ipautil.file_exists(paths.ROOT_IPA_CSR):
             print ("CA CSR file %s already exists.\nIn order to continue "
                    "remove the file and run the installer again." %
                    paths.ROOT_IPA_CSR)
             sys.exit(1)
-    elif options.external_cert_file:
+    elif options.external_cert_files:
         if not cainstance.is_step_one_done():
             # This can happen if someone passes external_ca_file without
             # already having done the first stage of the CA install.
@@ -743,10 +741,12 @@ def main():
         except Exception, e:
             sys.exit("Cannot process the cache file: %s" % str(e))
 
-    if options.external_cert_file:
+    if options.external_cert_files:
+        external_cert_file, external_ca_file = make_external_cert(
+            options.external_cert_files, options.subject)
         try:
-            validate_external_cert(options.external_cert_file,
-                                   options.external_ca_file, options.subject)
+            validate_external_cert(external_cert_file.name,
+                                   external_ca_file.name, options.subject)
         except ValueError, e:
             print e
             sys.exit(1)
@@ -759,7 +759,7 @@ def main():
 
     # Figure out what external CA step we're in. See cainstance.py for more
     # info on the 3 states.
-    if options.external_cert_file:
+    if options.external_cert_files:
         external = 2
     elif options.external_ca:
         external = 1
@@ -1103,8 +1103,8 @@ def main():
             # stage 2 of external CA installation
             ca.configure_instance(host_name, domain_name, dm_password,
                                   dm_password,
-                                  cert_file=options.external_cert_file,
-                                  cert_chain_file=options.external_ca_file,
+                                  cert_file=external_cert_file.name,
+                                  cert_chain_file=external_ca_file.name,
                                   subject_base=options.subject)
 
         # Now put the CA cert where other instances exepct it
diff --git a/install/tools/man/ipa-ca-install.1 b/install/tools/man/ipa-ca-install.1
index 2e0b079..186b0e5 100644
--- a/install/tools/man/ipa-ca-install.1
+++ b/install/tools/man/ipa-ca-install.1
@@ -37,6 +37,9 @@ Directory Manager (existing master) password
 \fB\-w\fR \fIADMIN_PASSWORD\fR, \fB\-\-admin\-password\fR=\fIADMIN_PASSWORD\fR
 Admin user Kerberos password used for connection check
 .TP
+\fB\-\-external\-cert\-file\fR=\fIFILE\fR
+File containing the IPA CA certificate and the external CA certificate chain.
+.TP
 \fB\-\-no\-host\-dns\fR
 Do not use DNS for hostname lookup during installation
 .TP
diff --git a/install/tools/man/ipa-cacert-manage.1 b/install/tools/man/ipa-cacert-manage.1
index 3006be7..a2c341b 100644
--- a/install/tools/man/ipa-cacert-manage.1
+++ b/install/tools/man/ipa-cacert-manage.1
@@ -56,10 +56,7 @@ Sign the renewed certificate by itself.
 Sign the renewed certificate by external CA.
 .TP
 \fB\-\-external\-cert\-file\fR=\fIFILE\fR
-PEM file containing a certificate signed by the external CA. Must be given with \-\-external\-ca\-file.
-.TP
-\fB\-\-external\-ca\-file\fR=\fIFILE\fR
-PEM file containing the external CA chain.
+File containing the IPA CA certificate and the external CA certificate chain.
 .TP
 \fB\-n\fR \fINICKNAME\fR, \fB\-\-nickname\fR=\fINICKNAME\fR
 Nickname for the certificate.
diff --git a/install/tools/man/ipa-server-install.1 b/install/tools/man/ipa-server-install.1
index 8cc2ffa..f23cd9f 100644
--- a/install/tools/man/ipa-server-install.1
+++ b/install/tools/man/ipa-server-install.1
@@ -87,15 +87,8 @@ An unattended installation that will never prompt for user input
 \fB\-\-external\-ca\fR
 Generate a CSR for the IPA CA certificate to be signed by an external CA.
 .TP
-\fB\-\-external_cert_file\fR=\fIFILE\fR
-File containing the IPA CA certificate signed by the external CA in PEM format. Must be given with \-\-external_ca_file.
-.TP
-\fB\-\-external_ca_file\fR=\fIFILE\fR
-File containing the external CA certificate chain in PEM format. Must be given with \-\-external_cert_file.
-
-If the CA certificate chain is in PKCS#7 format you can convert it to PEM using:
-
-    openssl pkcs7 -in PKCS7_FILE -print_certs -out PEM_FILE
+\fB\-\-external\-cert\-file\fR=\fIFILE\fR
+File containing the IPA CA certificate and the external CA certificate chain.
 .TP
 \fB\-\-no\-pkinit\fR
 Disables pkinit setup steps
diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py
index 52e76b7..48010aa 100644
--- a/ipaserver/install/cainstance.py
+++ b/ipaserver/install/cainstance.py
@@ -647,7 +647,7 @@ class CAInstance(service.Service):
 
         if self.external == 1:
             print "The next step is to get %s signed by your CA and re-run %s as:" % (self.csr_file, sys.argv[0])
-            print "%s --external_cert_file=/path/to/signed_certificate --external_ca_file=/path/to/external_ca_certificate" % sys.argv[0]
+            print "%s --external-cert-file=/path/to/signed_certificate --external-cert-file=/path/to/external_ca_certificate" % sys.argv[0]
             sys.exit(0)
         else:
             shutil.move(paths.CA_BACKUP_KEYS_P12, \
@@ -795,7 +795,7 @@ class CAInstance(service.Service):
 
         if self.external == 1:
             print "The next step is to get %s signed by your CA and re-run %s as:" % (self.csr_file, sys.argv[0])
-            print "%s --external_cert_file=/path/to/signed_certificate --external_ca_file=/path/to/external_ca_certificate" % sys.argv[0]
+            print "%s --external-cert-file=/path/to/signed_certificate --external-cert-file=/path/to/external_ca_certificate" % sys.argv[0]
             sys.exit(0)
 
         # pkisilent makes a copy of the CA PKCS#12 file for us but gives
diff --git a/ipaserver/install/installutils.py b/ipaserver/install/installutils.py
index 70cb5ff..c0beed9 100644
--- a/ipaserver/install/installutils.py
+++ b/ipaserver/install/installutils.py
@@ -875,6 +875,38 @@ def check_entropy():
         root_logger.debug("Invalid value in /proc/sys/kernel/random/entropy_avail %s" % \
             e)
 
+def make_external_cert(files, subject_base):
+    with certs.NSSDatabase() as nssdb:
+        db_password = ipautil.ipa_generate_password()
+        db_pwdfile = ipautil.write_tmp_file(db_password)
+        nssdb.create_db(db_pwdfile.name)
+
+        try:
+            nssdb.import_files(files, db_pwdfile.name)
+        except RuntimeError as e:
+            raise ScriptError(str(e))
+
+        cert_file = tempfile.NamedTemporaryFile()
+        ca_file = tempfile.NamedTemporaryFile()
+
+        ipa_subject = DN(('CN', 'Certificate Authority'), subject_base)
+        for nickname, trust_flags in nssdb.list_certs():
+            cert = nssdb.get_cert(nickname, pem=True)
+
+            nss_cert = x509.load_certificate(cert)
+            subject = DN(str(nss_cert.subject))
+            del nss_cert
+
+            if subject == ipa_subject:
+                cert_file.write(cert)
+            else:
+                ca_file.write(cert)
+
+        cert_file.flush()
+        ca_file.flush()
+
+    return cert_file, ca_file
+
 def validate_external_cert(cert_file, ca_file, subject_base):
     extcert = None
     try:
diff --git a/ipaserver/install/ipa_cacert_manage.py b/ipaserver/install/ipa_cacert_manage.py
index c681261..f0ea35b 100644
--- a/ipaserver/install/ipa_cacert_manage.py
+++ b/ipaserver/install/ipa_cacert_manage.py
@@ -60,11 +60,10 @@ class CACertManage(admintool.AdminTool):
             action='store_false',
             help="Sign the renewed certificate by external CA")
         renew_group.add_option(
-            "--external-cert-file", dest='external_cert_file',
-            help="PEM file containing a certificate signed by the external CA")
-        renew_group.add_option(
-            "--external-ca-file", dest='external_ca_file',
-            help="PEM file containing the external CA chain")
+            "--external-cert-file", dest="external_cert_files",
+            action="append", metavar="FILE",
+            help="File containing the IPA CA certificate and the external CA "
+                 "certificate chain")
         parser.add_option_group(renew_group)
 
         install_group = OptionGroup(parser, "Install options")
@@ -90,10 +89,7 @@ class CACertManage(admintool.AdminTool):
         options = self.options
 
         if command == 'renew':
-            if options.external_cert_file and not options.external_ca_file:
-                parser.error("--external-ca-file not specified")
-            elif not options.external_cert_file and options.external_ca_file:
-                parser.error("--external-cert-file not specified")
+            pass
         elif command == 'install':
             if len(self.args) < 2:
                 parser.error("certificate file name not provided")
@@ -107,7 +103,7 @@ class CACertManage(admintool.AdminTool):
         api.bootstrap(in_server=True)
         api.finalize()
 
-        if ((command == 'renew' and options.external_cert_file) or
+        if ((command == 'renew' and options.external_cert_files) or
             command == 'install'):
             self.conn = self.ldap_connect()
         else:
@@ -166,7 +162,7 @@ class CACertManage(admintool.AdminTool):
         cert = db.get_cert_from_db(self.cert_nickname, pem=False)
 
         options = self.options
-        if options.external_cert_file:
+        if options.external_cert_files:
             return self.renew_external_step_2(ca, cert)
 
         if options.self_signed is not None:
@@ -200,21 +196,21 @@ class CACertManage(admintool.AdminTool):
               "ipa-cacert-manage as:" % paths.IPA_CA_CSR)
         print("ipa-cacert-manage renew "
               "--external-cert-file=/path/to/signed_certificate "
-              "--external-ca-file=/path/to/external_ca_certificate")
+              "--external-cert-file=/path/to/external_ca_certificate")
 
     def renew_external_step_2(self, ca, old_cert):
         print "Importing the renewed CA certificate, please wait"
 
         options = self.options
-        cert_filename = options.external_cert_file
-        ca_filename = options.external_ca_file
+        cert_file, ca_file = installutils.make_external_cert(
+            options.external_cert_files, x509.subject_base())
 
         nss_cert = None
         nss.nss_init(ca.dogtag_constants.ALIAS_DIR)
         try:
             try:
                 installutils.validate_external_cert(
-                    cert_filename, ca_filename, x509.subject_base())
+                    cert_file.name, ca_file.name, x509.subject_base())
             except ValueError, e:
                 raise admintool.ScriptError(e)
 
@@ -224,7 +220,7 @@ class CACertManage(admintool.AdminTool):
             pkinfo = nss_cert.subject_public_key_info.format()
             #pylint: enable=E1101
 
-            nss_cert = x509.load_certificate_from_file(cert_filename)
+            nss_cert = x509.load_certificate_from_file(cert_file.name)
             if not nss_cert.is_ca_cert():
                 raise admintool.ScriptError("Not a CA certificate")
             if nss_cert.subject != subject:
@@ -249,7 +245,7 @@ class CACertManage(admintool.AdminTool):
                 raise admintool.ScriptError(
                     "Not compatible with the current CA certificate: %s", e)
 
-            ca_certs = x509.load_certificate_list_from_file(ca_filename)
+            ca_certs = x509.load_certificate_list_from_file(ca_file.name)
             for ca_cert in ca_certs:
                 tmpdb.add_cert(ca_cert.der_data, str(ca_cert.subject), 'C,,')
             del ca_certs
diff --git a/ipatests/test_integration/test_external_ca.py b/ipatests/test_integration/test_external_ca.py
index 747990c..fbffdf1 100644
--- a/ipatests/test_integration/test_external_ca.py
+++ b/ipatests/test_integration/test_external_ca.py
@@ -97,8 +97,8 @@ class TestExternalCA(IntegrationTest):
             'ipa-server-install',
             '-a', self.master.config.admin_password,
             '-p', self.master.config.dirman_password,
-            '--external_cert_file', external_cert_file,
-            '--external_ca_file', external_ca_file
+            '--external-cert-file', external_cert_file,
+            '--external-cert-file', external_ca_file
         ])
 
         # Make sure IPA server is working properly
-- 
1.9.3

>From 871a043fc48ef6f22393ee2b93a61be9ea5d86b0 Mon Sep 17 00:00:00 2001
From: Jan Cholasta <jchol...@redhat.com>
Date: Wed, 24 Sep 2014 16:41:47 +0200
Subject: [PATCH 3/4] CA-less installer options usability fixes

The --*_pkcs12 options of ipa-server-install and ipa-replica-prepare have
been replaced by --*-cert-file options which accept multiple files.
ipa-server-certinstall now accepts multiple files as well. The files are
accepted in PEM and DER certificate, PKCS#7 certificate chain, PKCS#8 and
raw private key and PKCS#12 formats.

The --root-ca-file option of ipa-server-install has been replaced by
--ca-cert-file option which accepts multiple files. The files are
accepted in PEM and DER certificate and PKCS#7 certificate chain formats.

The --*_pin options of ipa-server-install and ipa-replica-prepare have been
renamed to --*-pin.
---
 install/tools/ipa-server-install            | 146 ++++++++++++++++++----------
 install/tools/man/ipa-replica-prepare.1     |  24 ++---
 install/tools/man/ipa-server-certinstall.1  |   4 +-
 install/tools/man/ipa-server-install.1      |  28 +++---
 ipaserver/install/installutils.py           |  40 ++++++++
 ipaserver/install/ipa_replica_prepare.py    | 137 +++++++++++++++-----------
 ipaserver/install/ipa_server_certinstall.py |  23 ++---
 ipatests/test_integration/test_caless.py    |  33 ++++---
 8 files changed, 269 insertions(+), 166 deletions(-)

diff --git a/install/tools/ipa-server-install b/install/tools/ipa-server-install
index 223ac81..d02a8af 100755
--- a/install/tools/ipa-server-install
+++ b/install/tools/ipa-server-install
@@ -214,20 +214,45 @@ def parse_options():
                       help=SUPPRESS_HELP)
     cert_group.add_option("--no-pkinit", dest="setup_pkinit", action="store_false",
                       default=True, help="disables pkinit setup steps")
-    cert_group.add_option("--dirsrv_pkcs12", dest="dirsrv_pkcs12",
-                      help="PKCS#12 file containing the Directory Server SSL certificate")
-    cert_group.add_option("--http_pkcs12", dest="http_pkcs12",
-                      help="PKCS#12 file containing the Apache Server SSL certificate")
-    cert_group.add_option("--pkinit_pkcs12", dest="pkinit_pkcs12",
-                      help="PKCS#12 file containing the Kerberos KDC SSL certificate")
+    cert_group.add_option("--dirsrv-cert-file", dest="dirsrv_cert_files",
+                      action="append", metavar="FILE",
+                      help="File containing the Directory Server SSL certificate and private key")
+    cert_group.add_option("--dirsrv_pkcs12", dest="dirsrv_cert_files",
+                      action="append",
+                      help=SUPPRESS_HELP)
+    cert_group.add_option("--http-cert-file", dest="http_cert_files",
+                      action="append", metavar="FILE",
+                      help="File containing the Apache Server SSL certificate and private key")
+    cert_group.add_option("--http_pkcs12", dest="http_cert_files",
+                      action="append",
+                      help=SUPPRESS_HELP)
+    cert_group.add_option("--pkinit-cert-file", dest="pkinit_cert_files",
+                      action="append", metavar="FILE",
+                      help="File containing the Kerberos KDC SSL certificate and private key")
+    cert_group.add_option("--pkinit_pkcs12", dest="pkinit_cert_files",
+                      action="append",
+                      help=SUPPRESS_HELP)
+    cert_group.add_option("--dirsrv-pin", dest="dirsrv_pin", sensitive=True,
+                      metavar="PIN",
+                      help="The password to unlock the Directory Server private key")
     cert_group.add_option("--dirsrv_pin", dest="dirsrv_pin", sensitive=True,
-                      help="The password of the Directory Server PKCS#12 file")
+                      help=SUPPRESS_HELP)
+    cert_group.add_option("--http-pin", dest="http_pin", sensitive=True,
+                      metavar="PIN",
+                      help="The password to unlock the Apache Server private key")
     cert_group.add_option("--http_pin", dest="http_pin", sensitive=True,
-                      help="The password of the Apache Server PKCS#12 file")
+                      help=SUPPRESS_HELP)
+    cert_group.add_option("--pkinit-pin", dest="pkinit_pin",
+                      metavar="PIN",
+                      help="The password to unlock the Kerberos KDC private key")
     cert_group.add_option("--pkinit_pin", dest="pkinit_pin",
-                      help="The password of the Kerberos KDC PKCS#12 file")
-    cert_group.add_option("--root-ca-file", dest="root_ca_file",
-                      help="PEM file containing the CA certificate for the PKCS#12 files")
+                      help=SUPPRESS_HELP)
+    cert_group.add_option("--ca-cert-file", dest="ca_cert_files",
+                      action="append", metavar="FILE",
+                      help="File containing CA certificates for the service certificate files")
+    cert_group.add_option("--root-ca-file", dest="ca_cert_files",
+                      action="append",
+                      help=SUPPRESS_HELP)
     cert_group.add_option("--subject", action="callback", callback=subject_callback,
                       type="string",
                       help="The certificate subject base (default O=<realm-name>)")
@@ -305,22 +330,25 @@ def parse_options():
             if not options.forwarders and not options.no_forwarders:
                 parser.error("You must specify at least one --forwarder option or --no-forwarders option")
 
-    # If any of the PKCS#12 options are selected, all are required.
-    pkcs12_req = (options.dirsrv_pkcs12, options.http_pkcs12)
-    pkcs12_opt = (options.pkinit_pkcs12,)
-    if any(pkcs12_req + pkcs12_opt) and not all(pkcs12_req):
-        parser.error("--dirsrv_pkcs12 and --http_pkcs12 are required if any "
-                     "PKCS#12 options are used.")
+    # If any of the key file options are selected, all are required.
+    cert_file_req = (options.dirsrv_cert_files, options.http_cert_files)
+    cert_file_opt = (options.pkinit_cert_files,)
+    if any(cert_file_req + cert_file_opt) and not all(cert_file_req):
+        parser.error("--dirsrv-cert-file and --http-cert-file are required if "
+                     "any key file options are used.")
 
     if options.unattended:
-        if options.dirsrv_pkcs12 and options.dirsrv_pin is None:
-            parser.error("You must specify --dirsrv_pin with --dirsrv_pkcs12")
-        if options.http_pkcs12 and options.http_pin is None:
-            parser.error("You must specify --http_pin with --http_pkcs12")
-        if options.pkinit_pkcs12 and options.pkinit_pin is None:
-            parser.error("You must specify --pkinit_pin with --pkinit_pkcs12")
-
-    if options.external_cert_files and options.dirsrv_pkcs12:
+        if options.dirsrv_cert_files and options.dirsrv_pin is None:
+            parser.error(
+                "You must specify --dirsrv-pin with --dirsrv-cert-file")
+        if options.http_cert_files and options.http_pin is None:
+            parser.error(
+                "You must specify --http-pin with --http-cert-file")
+        if options.pkinit_cert_files and options.pkinit_pin is None:
+            parser.error(
+                "You must specify --pkinit-pin with --pkinit-cert-file")
+
+    if options.external_cert_files and options.dirsrv_cert_files:
         parser.error("Service certificate file options cannot be used with "
                      "the external CA options.")
 
@@ -328,8 +356,9 @@ def parse_options():
         if options.external_cert_files:
             parser.error("You cannot specify --external-cert-file "
                          "together with --external-ca")
-        if options.dirsrv_pkcs12:
-            parser.error("You cannot specify PKCS#12 options together with --external-ca")
+        if options.dirsrv_cert_files:
+            parser.error("You cannot specify service certificate file options "
+                         "together with --external-ca")
 
     if (options.external_cert_files and
         any(not os.path.isabs(path) for path in options.external_cert_files)):
@@ -752,7 +781,7 @@ def main():
             sys.exit(1)
 
     # We only set up the CA if the PKCS#12 options are not given.
-    if options.dirsrv_pkcs12:
+    if options.dirsrv_cert_files:
         setup_ca = False
     else:
         setup_ca = True
@@ -890,43 +919,53 @@ def main():
     if not options.subject:
         options.subject = DN(('O', realm_name))
 
-    ca_file = options.root_ca_file
-
-    if options.http_pkcs12:
+    if options.http_cert_files:
         if options.http_pin is None:
             options.http_pin = installutils.read_password(
-                "Enter %s unlock" % options.http_pkcs12,
+                "Enter Apache Server private key unlock",
                 confirm=False, validate=False)
             if options.http_pin is None:
-                sys.exit("%s unlock password required" % options.http_pkcs12)
-        http_pkcs12_info = (options.http_pkcs12, options.http_pin)
+                sys.exit(
+                    "Apache Server private key unlock password required")
+        http_pkcs12_file, http_pin = installutils.make_pkcs12(
+            options.http_cert_files, options.http_pin,
+            None, options.ca_cert_files)
+        http_pkcs12_info = (http_pkcs12_file.name, http_pin)
         http_ca_cert = installutils.check_pkcs12(
-            http_pkcs12_info, ca_file, host_name)
+            http_pkcs12_info, None, host_name)
 
-    if options.dirsrv_pkcs12:
+    if options.dirsrv_cert_files:
         if options.dirsrv_pin is None:
             options.dirsrv_pin = installutils.read_password(
-                "Enter %s unlock" % options.dirsrv_pkcs12,
+                "Enter Directory Server private key unlock",
                 confirm=False, validate=False)
             if options.dirsrv_pin is None:
-                sys.exit("%s unlock password required" % options.dirsrv_pkcs12)
-        dirsrv_pkcs12_info = (options.dirsrv_pkcs12, options.dirsrv_pin)
+                sys.exit(
+                    "Directory Server private key unlock password required")
+        dirsrv_pkcs12_file, dirsrv_pin = installutils.make_pkcs12(
+            options.dirsrv_cert_files, options.dirsrv_pin,
+            None, options.ca_cert_files)
+        dirsrv_pkcs12_info = (dirsrv_pkcs12_file.name, dirsrv_pin)
         dirsrv_ca_cert = installutils.check_pkcs12(
-            dirsrv_pkcs12_info, ca_file, host_name)
+            dirsrv_pkcs12_info, None, host_name)
 
-    if options.pkinit_pkcs12:
+    if options.pkinit_cert_files:
         if options.pkinit_pin is None:
             options.pkinit_pin = installutils.read_password(
-                "Enter %s unlock" % options.pkinit_pkcs12,
+                "Enter Kerberos KDC private key unlock",
                 confirm=False, validate=False)
             if options.pkinit_pin is None:
-                sys.exit("%s unlock password required" % options.pkinit_pkcs12)
-        pkinit_pkcs12_info = (options.pkinit_pkcs12, options.pkinit_pin)
-
-    if (options.http_pkcs12 and options.dirsrv_pkcs12 and
+                sys.exit(
+                    "Kerberos KDC private key unlock password required")
+        pkinit_pkcs12_file, pkinit_pin = installutils.make_pkcs12(
+            options.pkinit_cert_files, options.pkinit_pin,
+            None, options.ca_cert_files)
+        pkinit_pkcs12_info = (pkinit_pkcs12_file.name, pkinit_pin)
+
+    if (options.http_cert_files and options.dirsrv_cert_files and
         http_ca_cert != dirsrv_ca_cert):
-        sys.exit("%s and %s are not signed by the same CA certificate" %
-                 (options.http_pkcs12, options.dirsrv_pkcs12))
+        sys.exit("Apache Server SSL certificate and Directory Server SSL "
+                 "certificate are not signed by the same CA certificate")
 
     if not options.dm_password:
         dm_password = read_dm_password()
@@ -1056,14 +1095,13 @@ def main():
             if not ntp.is_configured():
                 ntp.create_instance()
 
-        if options.dirsrv_pkcs12:
+        if options.dirsrv_cert_files:
             ds = dsinstance.DsInstance(fstore=fstore)
             ds.create_instance(realm_name, host_name, domain_name,
                             dm_password, dirsrv_pkcs12_info,
                             idstart=options.idstart, idmax=options.idmax,
                             subject_base=options.subject,
-                            hbac_allow=not options.hbac_allow,
-                            ca_file=ca_file)
+                            hbac_allow=not options.hbac_allow)
         else:
             ds = dsinstance.DsInstance(fstore=fstore)
             ds.create_instance(realm_name, host_name, domain_name,
@@ -1126,7 +1164,7 @@ def main():
         ca.enable_client_auth_to_db()
 
     krb = krbinstance.KrbInstance(fstore)
-    if options.pkinit_pkcs12:
+    if options.pkinit_cert_files:
         krb.create_instance(realm_name, host_name, domain_name,
                             dm_password, master_password,
                             setup_pkinit=options.setup_pkinit,
@@ -1152,11 +1190,11 @@ def main():
 
     # Create a HTTP instance
     http = httpinstance.HTTPInstance(fstore)
-    if options.http_pkcs12:
+    if options.http_cert_files:
         http.create_instance(
             realm_name, host_name, domain_name, dm_password,
             pkcs12_info=http_pkcs12_info, subject_base=options.subject,
-            auto_redirect=options.ui_redirect, ca_file=ca_file)
+            auto_redirect=options.ui_redirect)
     else:
         http.create_instance(
             realm_name, host_name, domain_name, dm_password,
diff --git a/install/tools/man/ipa-replica-prepare.1 b/install/tools/man/ipa-replica-prepare.1
index 8e1e60a..75ee725 100644
--- a/install/tools/man/ipa-replica-prepare.1
+++ b/install/tools/man/ipa-replica-prepare.1
@@ -35,23 +35,23 @@ Once the file has been created it will be named replica\-hostname. This file can
 A replica should only be installed on the same or higher version of IPA on the remote system.
 .SH "OPTIONS"
 .TP
-\fB\-\-dirsrv_pkcs12\fR=\fIFILE\fR
-PKCS#12 file containing the Directory Server SSL Certificate and Private Key
+\fB\-\-dirsrv\-cert\-file\fR=\fIFILE\fR
+File containing the Directory Server SSL certificate and private key
 .TP
-\fB\-\-http_pkcs12\fR=\fIFILE\fR
-PKCS#12 file containing the Apache Server SSL Certificate and Private Key
+\fB\-\-http\-cert\-file\fR=\fIFILE\fR
+File containing the Apache Server SSL certificate and private key
 .TP
-\fB\-\-pkinit_pkcs12\fR=\fIFILE\fR
-PKCS#12 file containing the Kerberos KDC Certificate and Private Key
+\fB\-\-pkinit\-cert\-file\fR=\fIFILE\fR
+File containing the Kerberos KDC SSL certificate and private key
 .TP
-\fB\-\-dirsrv_pin\fR=\fIDIRSRV_PIN\fR
-The password of the Directory Server PKCS#12 file
+\fB\-\-dirsrv\-pin\fR=\fIPIN\fR
+The password to unlock the Directory Server private key
 .TP
-\fB\-\-http_pin\fR=\fIHTTP_PIN\fR
-The password of the Apache Server PKCS#12 file
+\fB\-\-http\-pin\fR=\fIPIN\fR
+The password to unlock the Apache Server private key
 .TP
-\fB\-\-pkinit_pin\fR=\fIPKINIT_PIN\fR
-The password of the Kerberos KDC PKCS#12 file
+\fB\-\-pkinit\-pin\fR=\fIPIN\fR
+The password to unlock the Kerberos KDC private key
 .TP
 \fB\-p\fR \fIDM_PASSWORD\fR, \fB\-\-password\fR=\fIDM_PASSWORD\fR
 Directory Manager (existing master) password
diff --git a/install/tools/man/ipa-server-certinstall.1 b/install/tools/man/ipa-server-certinstall.1
index f428402..301441d 100644
--- a/install/tools/man/ipa-server-certinstall.1
+++ b/install/tools/man/ipa-server-certinstall.1
@@ -20,7 +20,7 @@
 .SH "NAME"
 ipa\-server\-certinstall \- Install new SSL server certificates
 .SH "SYNOPSIS"
-ipa\-server\-certinstall [\fIOPTION\fR]... PKCS12_FILE
+ipa\-server\-certinstall [\fIOPTION\fR]... FILE...
 .SH "DESCRIPTION"
 Replace the current SSL Directory and/or Apache server certificate(s) with the certificate in the PKCS#12 file.
 
@@ -38,7 +38,7 @@ Install the certificate on the Directory Server
 Install the certificate in the Apache Web Server
 .TP
 \fB\-\-pin\fR=\fIPIN\fR
-The password of the PKCS#12 file
+The password to unlock the private key
 .TP
 \fB\-\-dirman\-password\fR=\fIDIRMAN_PASSWORD\fR
 Directory Manager password
diff --git a/install/tools/man/ipa-server-install.1 b/install/tools/man/ipa-server-install.1
index f23cd9f..2a5d1c1 100644
--- a/install/tools/man/ipa-server-install.1
+++ b/install/tools/man/ipa-server-install.1
@@ -93,26 +93,26 @@ File containing the IPA CA certificate and the external CA certificate chain.
 \fB\-\-no\-pkinit\fR
 Disables pkinit setup steps
 .TP
-\fB\-\-dirsrv_pkcs12\fR=\fIFILE\fR
-PKCS#12 file containing the Directory Server SSL Certificate
+\fB\-\-dirsrv\-cert\-file\fR=\fIFILE\fR
+File containing the Directory Server SSL certificate and private key
 .TP
-\fB\-\-http_pkcs12\fR=\fIFILE\fR
-PKCS#12 file containing the Apache Server SSL Certificate
+\fB\-\-http\-cert\-file\fR=\fIFILE\fR
+File containing the Apache Server SSL certificate and private key
 .TP
-\fB\-\-pkinit_pkcs12\fR=\fIFILE\fR
-PKCS#12 file containing the Kerberos KDC SSL certificate
+\fB\-\-pkinit\-cert\-file\fR=\fIFILE\fR
+File containing the Kerberos KDC SSL certificate and private key
 .TP
-\fB\-\-dirsrv_pin\fR=\fIDIRSRV_PIN\fR
-The password of the Directory Server PKCS#12 file
+\fB\-\-dirsrv\-pin\fR=\fIPIN\fR
+The password to unlock the Directory Server private key
 .TP
-\fB\-\-http_pin\fR=\fIHTTP_PIN\fR
-The password of the Apache Server PKCS#12 file
+\fB\-\-http\-pin\fR=\fIPIN\fR
+The password to unlock the Apache Server private key
 .TP
-\fB\-\-pkinit_pin\fR=\fIPKINIT_PIN\fR
-The password of the Kerberos KDC PKCS#12 file
+\fB\-\-pkinit\-pin\fR=\fIPIN\fR
+The password to unlock the Kerberos KDC private key
 .TP
-\fB\-\-root\-ca\-file\fR=\fIFILE\fR
-PEM file containing the CA certificate of the CA which issued the Directory Server, Apache Server and Kerberos KDC SSL certificates. Use this option if the CA certificate is not present in the PKCS#12 files.
+\fB\-\-ca\-cert\-file\fR=\fIFILE\fR
+File containing the CA certificate of the CA which issued the Directory Server, Apache Server and Kerberos KDC certificates. Use this option if the CA certificate is not present in the certificate files.
 .TP
 \fB\-\-subject\fR=\fISUBJECT\fR
 The certificate subject base (default O=REALM.NAME)
diff --git a/ipaserver/install/installutils.py b/ipaserver/install/installutils.py
index c0beed9..f90aa6f 100644
--- a/ipaserver/install/installutils.py
+++ b/ipaserver/install/installutils.py
@@ -733,6 +733,46 @@ def handle_error(error, log_file_name=None):
     message += '\n%s: %s' % (type(error).__name__, error)
     return message, 1
 
+def make_pkcs12(cert_files, key_password, key_nickname, ca_files):
+    with certs.NSSDatabase() as nssdb:
+        db_password = ipautil.ipa_generate_password()
+        db_pwdfile = ipautil.write_tmp_file(db_password)
+        nssdb.create_db(db_pwdfile.name)
+
+        try:
+            nssdb.import_files(cert_files, db_pwdfile.name,
+                               True, key_password, key_nickname)
+        except RuntimeError as e:
+            raise ScriptError(str(e))
+
+        if ca_files:
+            try:
+                nssdb.import_files(ca_files, db_pwdfile.name)
+            except RuntimeError as e:
+                raise ScriptError(str(e))
+
+        server_certs = nssdb.find_server_certs()
+        if len(server_certs) > 1:
+            for nickname, trust_flags in server_certs:
+                if nickname != key_nickname:
+                    nssdb.delete_cert(nickname)
+        else:
+            key_nickname = server_certs[0][0]
+
+        out_file = tempfile.NamedTemporaryFile()
+        out_password = ipautil.ipa_generate_password()
+        out_pwdfile = ipautil.write_tmp_file(out_password)
+        args = [
+            paths.PK12UTIL,
+            '-o', out_file.name,
+            '-n', key_nickname,
+            '-d', nssdb.secdir,
+            '-k', db_pwdfile.name,
+            '-w', out_pwdfile.name,
+        ]
+        ipautil.run(args)
+
+    return out_file, out_password
 
 def check_pkcs12(pkcs12_info, ca_file, hostname):
     """Check the given PKCS#12 with server cert and return the cert nickname
diff --git a/ipaserver/install/ipa_replica_prepare.py b/ipaserver/install/ipa_replica_prepare.py
index 7762614..a5459f8 100644
--- a/ipaserver/install/ipa_replica_prepare.py
+++ b/ipaserver/install/ipa_replica_prepare.py
@@ -21,7 +21,7 @@
 import os
 import shutil
 import tempfile
-from optparse import OptionGroup
+from optparse import OptionGroup, SUPPRESS_HELP
 from ConfigParser import SafeConfigParser
 
 from ipaserver.install import certs, installutils, bindinstance, dsinstance
@@ -67,21 +67,39 @@ class ReplicaPrepare(admintool.AdminTool):
 
         group = OptionGroup(parser, "SSL certificate options",
             "Only used if the server was installed using custom SSL certificates")
-        group.add_option("--dirsrv_pkcs12", dest="dirsrv_pkcs12",
-            metavar="FILE",
-            help="install certificate for the directory server")
-        group.add_option("--http_pkcs12", dest="http_pkcs12",
-            metavar="FILE",
-            help="install certificate for the http server")
-        group.add_option("--pkinit_pkcs12", dest="pkinit_pkcs12",
-            metavar="FILE",
-            help="install certificate for the KDC")
-        group.add_option("--dirsrv_pin", dest="dirsrv_pin", metavar="PIN",
-            help="PIN for the Directory Server PKCS#12 file")
-        group.add_option("--http_pin", dest="http_pin", metavar="PIN",
-            help="PIN for the Apache Server PKCS#12 file")
-        group.add_option("--pkinit_pin", dest="pkinit_pin", metavar="PIN",
-            help="PIN for the KDC pkinit PKCS#12 file")
+        group.add_option("--dirsrv-cert-file", dest="dirsrv_cert_files",
+            action="append", metavar="FILE",
+            help="File containing the Directory Server SSL certificate and private key")
+        group.add_option("--dirsrv_pkcs12", dest="dirsrv_cert_files",
+            action="append",
+            help=SUPPRESS_HELP)
+        group.add_option("--http-cert-file", dest="http_cert_files",
+            action="append", metavar="FILE",
+            help="File containing the Apache Server SSL certificate and private key")
+        group.add_option("--http_pkcs12", dest="http_cert_files",
+            action="append",
+            help=SUPPRESS_HELP)
+        group.add_option("--pkinit-cert-file", dest="pkinit_cert_files",
+            action="append", metavar="FILE",
+            help="File containing the Kerberos KDC SSL certificate and private key")
+        group.add_option("--pkinit_pkcs12", dest="pkinit_cert_files",
+            action="append",
+            help=SUPPRESS_HELP)
+        group.add_option("--dirsrv-pin", dest="dirsrv_pin", sensitive=True,
+            metavar="PIN",
+            help="The password to unlock the Directory Server private key")
+        group.add_option("--dirsrv_pin", dest="dirsrv_pin", sensitive=True,
+            help=SUPPRESS_HELP)
+        group.add_option("--http-pin", dest="http_pin", sensitive=True,
+            metavar="PIN",
+            help="The password to unlock the Apache Server private key")
+        group.add_option("--http_pin", dest="http_pin", sensitive=True,
+            help=SUPPRESS_HELP)
+        group.add_option("--pkinit-pin", dest="pkinit_pin",
+            metavar="PIN",
+            help="The password to unlock the Kerberos KDC private key")
+        group.add_option("--pkinit_pin", dest="pkinit_pin",
+            help=SUPPRESS_HELP)
         parser.add_option_group(group)
 
     def validate_options(self):
@@ -104,11 +122,11 @@ class ReplicaPrepare(admintool.AdminTool):
         options.setup_pkinit = False
 
         # If any of the PKCS#12 options are selected, all are required.
-        pkcs12_req = (options.dirsrv_pkcs12, options.http_pkcs12)
-        pkcs12_opt = (options.pkinit_pkcs12,)
-        if any(pkcs12_req + pkcs12_opt) and not all(pkcs12_req):
+        cert_file_req = (options.dirsrv_cert_files, options.http_cert_files)
+        cert_file_opt = (options.pkinit_cert_files,)
+        if any(cert_file_req + cert_file_opt) and not all(cert_file_req):
             self.option_parser.error(
-                "--dirsrv_pkcs12 and --http_pkcs12 are required if any "
+                "--dirsrv-cert-file and --http-cert-file are required if any "
                 "PKCS#12 options are used.")
 
         if len(self.args) < 1:
@@ -126,11 +144,11 @@ class ReplicaPrepare(admintool.AdminTool):
         if api.env.host == self.replica_fqdn:
             raise admintool.ScriptError("You can't create a replica on itself")
 
-        if not api.env.enable_ra and not options.http_pkcs12:
+        if not api.env.enable_ra and not options.http_cert_files:
             raise admintool.ScriptError(
                 "Cannot issue certificates: a CA is not installed. Use the "
-                "--http_pkcs12, --dirsrv_pkcs12 options to provide custom "
-                "certificates.")
+                "--http-cert-file, --dirsrv-cert-file options to provide "
+                "custom certificates.")
 
         config_dir = dsinstance.config_dirname(
             dsinstance.realm_to_serverid(api.env.realm))
@@ -141,7 +159,7 @@ class ReplicaPrepare(admintool.AdminTool):
     def check_pkcs12(self, pkcs12_file, pkcs12_pin):
         return installutils.check_pkcs12(
             pkcs12_info=(pkcs12_file, pkcs12_pin),
-            ca_file=CACERT,
+            ca_file=None,
             hostname=self.replica_fqdn)
 
     def ask_for_options(self):
@@ -213,42 +231,51 @@ class ReplicaPrepare(admintool.AdminTool):
                     options.reverse_zone, options.ip_address):
                 raise admintool.ScriptError("Invalid reverse zone")
 
-        if options.http_pkcs12:
+        if options.http_cert_files:
             if options.http_pin is None:
                 options.http_pin = installutils.read_password(
-                    "Enter %s unlock" % options.http_pkcs12,
+                    "Enter Apache Server private key unlock",
                     confirm=False, validate=False)
                 if options.http_pin is None:
                     raise admintool.ScriptError(
-                        "%s unlock password required" % options.http_pkcs12)
+                        "Apache Server private key unlock password required")
+            self.http_pkcs12_file, self.http_pin = installutils.make_pkcs12(
+                options.http_cert_files, options.http_pin,
+                None, [CACERT])
             http_ca_cert = self.check_pkcs12(
-                options.http_pkcs12, options.http_pin)
+                self.http_pkcs12_file.name, self.http_pin)
 
-        if options.dirsrv_pkcs12:
+        if options.dirsrv_cert_files:
             if options.dirsrv_pin is None:
                 options.dirsrv_pin = installutils.read_password(
-                    "Enter %s unlock" % options.dirsrv_pkcs12,
+                    "Enter Directory Server private key unlock",
                     confirm=False, validate=False)
                 if options.dirsrv_pin is None:
                     raise admintool.ScriptError(
-                        "%s unlock password required" % options.dirsrv_pkcs12)
+                        "Directory Server private key unlock password required")
+            self.dirsrv_pkcs12_file, self.dirsrv_pin = installutils.make_pkcs12(
+                options.dirsrv_cert_files, options.dirsrv_pin,
+                None, [CACERT])
             dirsrv_ca_cert = self.check_pkcs12(
-                options.dirsrv_pkcs12, options.dirsrv_pin)
+                self.dirsrv_pkcs12_file.name, self.dirsrv_pin)
 
-        if options.pkinit_pkcs12:
+        if options.pkinit_cert_files:
             if options.pkinit_pin is None:
                 options.pkinit_pin = installutils.read_password(
-                    "Enter %s unlock" % options.pkinit_pkcs12,
+                    "Enter Kerberos KDC private key unlock",
                     confirm=False, validate=False)
                 if options.pkinit_pin is None:
                     raise admintool.ScriptError(
-                        "%s unlock password required" % options.pkinit_pkcs12)
+                        "Kerberos KDC private key unlock password required")
+            self.pkinit_pkcs12_file, self.pkinit_pin = installutils.make_pkcs12(
+                options.pkinit_cert_files, options.pkinit_pin,
+                None, [CACERT])
 
-        if (options.http_pkcs12 and options.dirsrv_pkcs12 and
+        if (options.http_cert_files and options.dirsrv_cert_files and
             http_ca_cert != dirsrv_ca_cert):
             raise admintool.ScriptError(
-                "%s and %s are not signed by the same CA certificate" %
-                (options.http_pkcs12, options.dirsrv_pkcs12))
+                "Apache Server SSL certificate and Directory Server SSL "
+                 "certificate are not signed by the same CA certificate")
 
         if (not ipautil.file_exists(
                     dogtag.configured_constants().CS_CFG_PATH) and
@@ -263,6 +290,8 @@ class ReplicaPrepare(admintool.AdminTool):
         options = self.options
         super(ReplicaPrepare, self).run()
 
+        self.http_pin = self.dirsrv_pin = self.pkinit_pin = None
+
         self.log.info("Preparing replica for %s from %s",
             self.replica_fqdn, api.env.host)
         enable_replication_version_checking(api.env.host, api.env.realm,
@@ -295,13 +324,11 @@ class ReplicaPrepare(admintool.AdminTool):
 
         passwd_fname = os.path.join(self.dir, "dirsrv_pin.txt")
         with open(passwd_fname, "w") as fd:
-            fd.write("%s\n" % (options.dirsrv_pin or ''))
+            fd.write("%s\n" % (self.dirsrv_pin or ''))
 
-        if options.dirsrv_pkcs12:
-            self.log.info(
-                "Copying SSL certificate for the Directory Server from %s",
-                options.dirsrv_pkcs12)
-            self.copy_info_file(options.dirsrv_pkcs12, "dscert.p12")
+        if options.dirsrv_cert_files:
+            self.log.info("Copying SSL certificate for the Directory Server")
+            self.copy_info_file(self.dirsrv_pkcs12_file.name, "dscert.p12")
         else:
             if ipautil.file_exists(options.ca_file):
                 # Since it is possible that the Directory Manager password
@@ -318,7 +345,7 @@ class ReplicaPrepare(admintool.AdminTool):
                 "Creating SSL certificate for the Directory Server")
             self.export_certdb("dscert", passwd_fname)
 
-        if not options.dirsrv_pkcs12:
+        if not options.dirsrv_cert_files:
             self.log.info(
                 "Creating SSL certificate for the dogtag Directory Server")
             self.export_certdb("dogtagcert", passwd_fname)
@@ -333,13 +360,11 @@ class ReplicaPrepare(admintool.AdminTool):
 
         passwd_fname = os.path.join(self.dir, "http_pin.txt")
         with open(passwd_fname, "w") as fd:
-            fd.write("%s\n" % (options.http_pin or ''))
+            fd.write("%s\n" % (self.http_pin or ''))
 
-        if options.http_pkcs12:
-            self.log.info(
-                "Copying SSL certificate for the Web Server from %s",
-                options.http_pkcs12)
-            self.copy_info_file(options.http_pkcs12, "httpcert.p12")
+        if options.http_cert_files:
+            self.log.info("Copying SSL certificate for the Web Server")
+            self.copy_info_file(self.http_pkcs12_file.name, "httpcert.p12")
         else:
             self.log.info("Creating SSL certificate for the Web Server")
             self.export_certdb("httpcert", passwd_fname)
@@ -352,13 +377,11 @@ class ReplicaPrepare(admintool.AdminTool):
 
         passwd_fname = os.path.join(self.dir, "pkinit_pin.txt")
         with open(passwd_fname, "w") as fd:
-            fd.write("%s\n" % (options.pkinit_pin or ''))
+            fd.write("%s\n" % (self.pkinit_pin or ''))
 
-        if options.pkinit_pkcs12:
-            self.log.info(
-                "Copying SSL certificate for the KDC from %s",
-                options.pkinit_pkcs12)
-            self.copy_info_file(options.pkinit_pkcs12, "pkinitcert.p12")
+        if options.pkinit_cert_files:
+            self.log.info("Copying SSL certificate for the KDC")
+            self.copy_info_file(self.pkinit_pkcs12_file.name, "pkinitcert.p12")
         else:
             self.log.info("Creating SSL certificate for the KDC")
             self.export_certdb("pkinitcert", passwd_fname, is_kdc=True)
diff --git a/ipaserver/install/ipa_server_certinstall.py b/ipaserver/install/ipa_server_certinstall.py
index 6300a14..f22033b 100644
--- a/ipaserver/install/ipa_server_certinstall.py
+++ b/ipaserver/install/ipa_server_certinstall.py
@@ -36,7 +36,7 @@ from ipaserver.plugins.ldap2 import ldap2
 class ServerCertInstall(admintool.AdminTool):
     command_name = 'ipa-server-certinstall'
 
-    usage = "%prog <-d|-w> [options] <PKCS#12 file>"
+    usage = "%prog <-d|-w> [options] <file> ..."
 
     description = "Install new SSL server certificates."
 
@@ -54,7 +54,7 @@ class ServerCertInstall(admintool.AdminTool):
             help="install certificate for the http server")
         parser.add_option(
             "--pin",
-            dest="pin",
+            dest="pin", metavar="PIN",
             help="The password of the PKCS#12 file")
         parser.add_option(
             "--dirsrv_pin", "--http_pin",
@@ -73,8 +73,8 @@ class ServerCertInstall(admintool.AdminTool):
         if not self.options.dirsrv and not self.options.http:
             self.option_parser.error("you must specify dirsrv and/or http")
 
-        if len(self.args) != 1:
-            self.option_parser.error("you must provide a pkcs12 filename")
+        if not self.args:
+            self.option_parser.error("you must provide certificate filename")
 
     def ask_for_options(self):
         super(ServerCertInstall, self).ask_for_options()
@@ -88,17 +88,15 @@ class ServerCertInstall(admintool.AdminTool):
 
         if self.options.pin is None:
             self.options.pin = installutils.read_password(
-                "Enter %s unlock" % self.args[0], confirm=False, validate=False)
+                "Enter private key unlock", confirm=False, validate=False)
             if self.options.pin is None:
                 raise admintool.ScriptError(
-                    "%s unlock password required" % self.args[0])
+                    "Private key unlock 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()
 
@@ -154,9 +152,12 @@ class ServerCertInstall(admintool.AdminTool):
         os.chown(os.path.join(dirname, 'secmod.db'), 0, pent.pw_gid)
 
     def import_cert(self, dirname, pkcs12_passwd, old_cert, principal, command):
+        pkcs12_file, pin = installutils.make_pkcs12(
+            self.args, pkcs12_passwd, None, [CACERT])
+
         installutils.check_pkcs12(
-            pkcs12_info=(self.pkcs12_fname, pkcs12_passwd),
-            ca_file=CACERT,
+            pkcs12_info=(pkcs12_file.name, pin),
+            ca_file=None,
             hostname=api.env.host)
 
         cdb = certs.CertDB(api.env.realm, nssdir=dirname)
@@ -165,7 +166,7 @@ class ServerCertInstall(admintool.AdminTool):
                 cdb.untrack_server_cert(old_cert)
 
             cdb.delete_cert(old_cert)
-            cdb.import_pkcs12(self.pkcs12_fname, pkcs12_passwd)
+            cdb.import_pkcs12(pkcs12_file.name, pin)
             server_cert = cdb.find_server_certs()[0][0]
 
             if api.env.enable_ra:
diff --git a/ipatests/test_integration/test_caless.py b/ipatests/test_integration/test_caless.py
index 28bfae5..1bd8202 100644
--- a/ipatests/test_integration/test_caless.py
+++ b/ipatests/test_integration/test_caless.py
@@ -154,9 +154,9 @@ class CALessBase(IntegrationTest):
 
         args = [
             'ipa-server-install',
-            '--http_pkcs12', http_pkcs12,
-            '--dirsrv_pkcs12', dirsrv_pkcs12,
-            '--root-ca-file', root_ca_file,
+            '--http-cert-file', http_pkcs12,
+            '--dirsrv-cert-file', dirsrv_pkcs12,
+            '--ca-cert-file', root_ca_file,
             '--ip-address', host.ip,
             '-r', host.domain.name,
             '-p', host.config.dirman_password,
@@ -166,9 +166,9 @@ class CALessBase(IntegrationTest):
         ]
 
         if http_pin is not None:
-            args.extend(['--http_pin', http_pin])
+            args.extend(['--http-pin', http_pin])
         if dirsrv_pin is not None:
-            args.extend(['--dirsrv_pin', dirsrv_pin])
+            args.extend(['--dirsrv-pin', dirsrv_pin])
         if unattended:
             args.extend(['-U'])
 
@@ -230,13 +230,13 @@ class CALessBase(IntegrationTest):
         ]
 
         if http_pkcs12:
-            args.extend(['--http_pkcs12', http_pkcs12])
+            args.extend(['--http-cert-file', http_pkcs12])
         if dirsrv_pkcs12:
-            args.extend(['--dirsrv_pkcs12', dirsrv_pkcs12])
+            args.extend(['--dirsrv-cert-file', dirsrv_pkcs12])
         if http_pin is not None:
-            args.extend(['--http_pin', http_pin])
+            args.extend(['--http-pin', http_pin])
         if dirsrv_pin is not None:
-            args.extend(['--dirsrv_pin', dirsrv_pin])
+            args.extend(['--dirsrv-pin', dirsrv_pin])
 
         args.extend([replica.hostname])
 
@@ -428,8 +428,8 @@ class TestServerInstall(CALessBase):
 
         result = self.install_server(http_pin=None)
         assert_error(result,
-                     'ipa-server-install: error: You must specify --http_pin '
-                     'with --http_pkcs12')
+                     'ipa-server-install: error: You must specify --http-pin '
+                     'with --http-cert-file')
 
     def test_missing_ds_password(self):
         "IPA server install with missing DS PKCS#12 password (unattended)"
@@ -441,7 +441,7 @@ class TestServerInstall(CALessBase):
         result = self.install_server(dirsrv_pin=None)
         assert_error(result,
                      'ipa-server-install: error: You must specify '
-                     '--dirsrv_pin with --dirsrv_pkcs12')
+                     '--dirsrv-pin with --dirsrv-cert-file')
 
     def test_incorect_http_pin(self):
         "IPA server install with incorrect HTTP PKCS#12 password"
@@ -784,8 +784,9 @@ class TestReplicaInstall(CALessBase):
                                          raiseonerr=False)
         assert result.returncode > 0
         assert ('Cannot issue certificates: a CA is not installed. Use the '
-                '--http_pkcs12, --dirsrv_pkcs12 options to provide custom '
-                'certificates.' in result.stderr_text), result.stderr_text
+                '--http-cert-file, --dirsrv-cert-file options to provide '
+                'custom certificates.' in result.stderr_text), \
+               result.stderr_text
 
     def test_nonexistent_http_pkcs12_file(self):
         "IPA replica install with non-existent HTTP PKCS#12 file"
@@ -1479,7 +1480,7 @@ class TestCertinstall(CALessBase):
 
         args = ['ipa-server-certinstall',
                 '-w', 'server.p12',
-                '--http_pin', self.cert_password]
+                '--http-pin', self.cert_password]
 
         result = self.certinstall('w', 'ca1/server', args=args)
         assert result.returncode == 0
@@ -1490,7 +1491,7 @@ class TestCertinstall(CALessBase):
 
         args = ['ipa-server-certinstall',
                 '-d', 'server.p12',
-                '--dirsrv_pin', self.cert_password]
+                '--dirsrv-pin', self.cert_password]
         stdin_text = self.master.config.dirman_password + '\n'
 
         result = self.certinstall('d', 'ca1/server',
-- 
1.9.3

>From 74c1c2ff0c0747fa6d5e20d2a7cc4a8169d013e8 Mon Sep 17 00:00:00 2001
From: Jan Cholasta <jchol...@redhat.com>
Date: Wed, 24 Sep 2014 16:48:15 +0200
Subject: [PATCH 4/4] Allow choosing CA-less server certificates by name

Added new --*-cert-name options to ipa-server-install and ipa-replica-prepare
and --cert-name option to ipa-server-certinstall. The options allows choosing
a particular certificate and private key from PKCS#12 files by its friendly
name.

https://fedorahosted.org/freeipa/ticket/4489
---
 install/tools/ipa-server-install            | 15 ++++++++++++---
 install/tools/man/ipa-replica-prepare.1     |  9 +++++++++
 install/tools/man/ipa-server-certinstall.1  |  3 +++
 install/tools/man/ipa-server-install.1      |  9 +++++++++
 ipaserver/install/ipa_replica_prepare.py    | 15 ++++++++++++---
 ipaserver/install/ipa_server_certinstall.py |  6 +++++-
 6 files changed, 50 insertions(+), 7 deletions(-)

diff --git a/install/tools/ipa-server-install b/install/tools/ipa-server-install
index d02a8af..26374e9 100755
--- a/install/tools/ipa-server-install
+++ b/install/tools/ipa-server-install
@@ -247,6 +247,15 @@ def parse_options():
                       help="The password to unlock the Kerberos KDC private key")
     cert_group.add_option("--pkinit_pin", dest="pkinit_pin",
                       help=SUPPRESS_HELP)
+    cert_group.add_option("--dirsrv-cert-name", dest="dirsrv_cert_name",
+                      metavar="NAME",
+                      help="Name of the Directory Server SSL certificate to install")
+    cert_group.add_option("--http-cert-name", dest="http_cert_name",
+                      metavar="NAME",
+                      help="Name of the Apache Server SSL certificate to install")
+    cert_group.add_option("--pkinit-cert-name", dest="pkinit_cert_name",
+                      metavar="NAME",
+                      help="Name of the Kerberos KDC SSL certificate to install")
     cert_group.add_option("--ca-cert-file", dest="ca_cert_files",
                       action="append", metavar="FILE",
                       help="File containing CA certificates for the service certificate files")
@@ -929,7 +938,7 @@ def main():
                     "Apache Server private key unlock password required")
         http_pkcs12_file, http_pin = installutils.make_pkcs12(
             options.http_cert_files, options.http_pin,
-            None, options.ca_cert_files)
+            options.http_cert_name, options.ca_cert_files)
         http_pkcs12_info = (http_pkcs12_file.name, http_pin)
         http_ca_cert = installutils.check_pkcs12(
             http_pkcs12_info, None, host_name)
@@ -944,7 +953,7 @@ def main():
                     "Directory Server private key unlock password required")
         dirsrv_pkcs12_file, dirsrv_pin = installutils.make_pkcs12(
             options.dirsrv_cert_files, options.dirsrv_pin,
-            None, options.ca_cert_files)
+            options.dirsrv_cert_name, options.ca_cert_files)
         dirsrv_pkcs12_info = (dirsrv_pkcs12_file.name, dirsrv_pin)
         dirsrv_ca_cert = installutils.check_pkcs12(
             dirsrv_pkcs12_info, None, host_name)
@@ -959,7 +968,7 @@ def main():
                     "Kerberos KDC private key unlock password required")
         pkinit_pkcs12_file, pkinit_pin = installutils.make_pkcs12(
             options.pkinit_cert_files, options.pkinit_pin,
-            None, options.ca_cert_files)
+            options.pkinit_cert_name, options.ca_cert_files)
         pkinit_pkcs12_info = (pkinit_pkcs12_file.name, pkinit_pin)
 
     if (options.http_cert_files and options.dirsrv_cert_files and
diff --git a/install/tools/man/ipa-replica-prepare.1 b/install/tools/man/ipa-replica-prepare.1
index 75ee725..7fa439c 100644
--- a/install/tools/man/ipa-replica-prepare.1
+++ b/install/tools/man/ipa-replica-prepare.1
@@ -53,6 +53,15 @@ The password to unlock the Apache Server private key
 \fB\-\-pkinit\-pin\fR=\fIPIN\fR
 The password to unlock the Kerberos KDC private key
 .TP
+\fB\-\-dirsrv\-cert\-name\fR=\fINAME\fR
+Name of the Directory Server SSL certificate to install
+.TP
+\fB\-\-http\-cert\-name\fR=\fINAME\fR
+Name of the Apache Server SSL certificate to install
+.TP
+\fB\-\-pkinit\-cert\-name\fR=\fINAME\fR
+Name of the Kerberos KDC SSL certificate to install
+.TP
 \fB\-p\fR \fIDM_PASSWORD\fR, \fB\-\-password\fR=\fIDM_PASSWORD\fR
 Directory Manager (existing master) password
 .TP
diff --git a/install/tools/man/ipa-server-certinstall.1 b/install/tools/man/ipa-server-certinstall.1
index 301441d..73436e1 100644
--- a/install/tools/man/ipa-server-certinstall.1
+++ b/install/tools/man/ipa-server-certinstall.1
@@ -40,6 +40,9 @@ Install the certificate in the Apache Web Server
 \fB\-\-pin\fR=\fIPIN\fR
 The password to unlock the private key
 .TP
+\fB\-\-cert\-name\fR=\fINAME\fR
+Name of the certificate to install
+.TP
 \fB\-\-dirman\-password\fR=\fIDIRMAN_PASSWORD\fR
 Directory Manager password
 .SH "EXIT STATUS"
diff --git a/install/tools/man/ipa-server-install.1 b/install/tools/man/ipa-server-install.1
index 2a5d1c1..1c7ca4a 100644
--- a/install/tools/man/ipa-server-install.1
+++ b/install/tools/man/ipa-server-install.1
@@ -111,6 +111,15 @@ The password to unlock the Apache Server private key
 \fB\-\-pkinit\-pin\fR=\fIPIN\fR
 The password to unlock the Kerberos KDC private key
 .TP
+\fB\-\-dirsrv\-cert\-name\fR=\fINAME\fR
+Name of the Directory Server SSL certificate to install
+.TP
+\fB\-\-http\-cert\-name\fR=\fINAME\fR
+Name of the Apache Server SSL certificate to install
+.TP
+\fB\-\-pkinit\-cert\-name\fR=\fINAME\fR
+Name of the Kerberos KDC SSL certificate to install
+.TP
 \fB\-\-ca\-cert\-file\fR=\fIFILE\fR
 File containing the CA certificate of the CA which issued the Directory Server, Apache Server and Kerberos KDC certificates. Use this option if the CA certificate is not present in the certificate files.
 .TP
diff --git a/ipaserver/install/ipa_replica_prepare.py b/ipaserver/install/ipa_replica_prepare.py
index a5459f8..91f9363 100644
--- a/ipaserver/install/ipa_replica_prepare.py
+++ b/ipaserver/install/ipa_replica_prepare.py
@@ -100,6 +100,15 @@ class ReplicaPrepare(admintool.AdminTool):
             help="The password to unlock the Kerberos KDC private key")
         group.add_option("--pkinit_pin", dest="pkinit_pin",
             help=SUPPRESS_HELP)
+        group.add_option("--dirsrv-cert-name", dest="dirsrv_cert_name",
+            metavar="NAME",
+            help="Name of the Directory Server SSL certificate to install")
+        group.add_option("--http-cert-name", dest="http_cert_name",
+            metavar="NAME",
+            help="Name of the Apache Server SSL certificate to install")
+        group.add_option("--pkinit-cert-name", dest="pkinit_cert_name",
+            metavar="NAME",
+            help="Name of the Kerberos KDC SSL certificate to install")
         parser.add_option_group(group)
 
     def validate_options(self):
@@ -241,7 +250,7 @@ class ReplicaPrepare(admintool.AdminTool):
                         "Apache Server private key unlock password required")
             self.http_pkcs12_file, self.http_pin = installutils.make_pkcs12(
                 options.http_cert_files, options.http_pin,
-                None, [CACERT])
+                options.http_cert_name, [CACERT])
             http_ca_cert = self.check_pkcs12(
                 self.http_pkcs12_file.name, self.http_pin)
 
@@ -255,7 +264,7 @@ class ReplicaPrepare(admintool.AdminTool):
                         "Directory Server private key unlock password required")
             self.dirsrv_pkcs12_file, self.dirsrv_pin = installutils.make_pkcs12(
                 options.dirsrv_cert_files, options.dirsrv_pin,
-                None, [CACERT])
+                options.dirsrv_cert_name, [CACERT])
             dirsrv_ca_cert = self.check_pkcs12(
                 self.dirsrv_pkcs12_file.name, self.dirsrv_pin)
 
@@ -269,7 +278,7 @@ class ReplicaPrepare(admintool.AdminTool):
                         "Kerberos KDC private key unlock password required")
             self.pkinit_pkcs12_file, self.pkinit_pin = installutils.make_pkcs12(
                 options.pkinit_cert_files, options.pkinit_pin,
-                None, [CACERT])
+                options.pkinit_cert_name, [CACERT])
 
         if (options.http_cert_files and options.dirsrv_cert_files and
             http_ca_cert != dirsrv_ca_cert):
diff --git a/ipaserver/install/ipa_server_certinstall.py b/ipaserver/install/ipa_server_certinstall.py
index f22033b..c80b830 100644
--- a/ipaserver/install/ipa_server_certinstall.py
+++ b/ipaserver/install/ipa_server_certinstall.py
@@ -61,6 +61,10 @@ class ServerCertInstall(admintool.AdminTool):
             dest="pin",
             help=optparse.SUPPRESS_HELP)
         parser.add_option(
+            "--cert-name",
+            dest="cert_name", metavar="NAME",
+            help="Name of the certificate to install")
+        parser.add_option(
             "-p", "--dirman-password",
             dest="dirman_password",
             help="Directory Manager password")
@@ -153,7 +157,7 @@ class ServerCertInstall(admintool.AdminTool):
 
     def import_cert(self, dirname, pkcs12_passwd, old_cert, principal, command):
         pkcs12_file, pin = installutils.make_pkcs12(
-            self.args, pkcs12_passwd, None, [CACERT])
+            self.args, pkcs12_passwd, self.options.cert_name, [CACERT])
 
         installutils.check_pkcs12(
             pkcs12_info=(pkcs12_file.name, pin),
-- 
1.9.3

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

Reply via email to