From 6b836e05eac5cf1718bf7a9cf37b5141225634bc Mon Sep 17 00:00:00 2001
From: Ade Lee <alee@redhat.com>
Date: Tue, 23 Feb 2016 14:06:23 -0500
Subject: [PATCH] Add precheck option for pkispawn.

--precheck can be used to run specific tests prior to ensure
that the installation parameters are sane, without actually
doing the installation.

There are also optional parameters to disable specific tests.
Trac Ticket #2042
---
 base/server/etc/default.cfg |   2 +
 base/server/sbin/pkispawn   | 177 +++++++++++++++++++++++++-------------------
 2 files changed, 103 insertions(+), 76 deletions(-)

diff --git a/base/server/etc/default.cfg b/base/server/etc/default.cfg
index 1c1ae92b323d67dc5fb810df79bbdbbb0b6c26e7..aefe0f45c771bc5e18775f87a46cd31d65d75979 100644
--- a/base/server/etc/default.cfg
+++ b/base/server/etc/default.cfg
@@ -112,7 +112,9 @@ pki_security_domain_user=caadmin
 pki_san_inject=False
 pki_san_for_server_cert=
 pki_skip_configuration=False
+pki_skip_ds_verify=False
 pki_skip_installation=False
+pki_skip_sd_verify=False
 pki_ssl_server_key_algorithm=SHA256withRSA
 pki_ssl_server_key_size=2048
 pki_ssl_server_key_type=rsa
diff --git a/base/server/sbin/pkispawn b/base/server/sbin/pkispawn
index 5892a671f3bf286553efeed3e63fd96b7a0265bd..e7b22ef1e66598c2a1a64b544ffdc171b88bbd4a 100755
--- a/base/server/sbin/pkispawn
+++ b/base/server/sbin/pkispawn
@@ -110,6 +110,11 @@ def main(argv):
         help='configuration filename '
         '(MUST specify complete path)')
 
+    parser.optional.add_argument(
+        '--precheck',
+        dest='precheck', action='store_true',
+        help='Execute pre-checks and exit')
+
     args = parser.process_command_line_arguments()
 
     config.default_deployment_cfg = \
@@ -149,6 +154,9 @@ def main(argv):
         parser.init_config()
 
         if config.user_deployment_cfg is None:
+            if args.precheck:
+                sys.exit(
+                    'precheck mode is only valid for non-interactive installs')
             interactive = True
             parser.indent = 2
 
@@ -488,6 +496,62 @@ def main(argv):
               config.pki_subsystem.lower())
         sys.exit(1)
 
+    start_logging()
+    create_master_dictionary(parser)
+
+    if not interactive and \
+            not config.str2bool(parser.mdict['pki_skip_configuration']):
+        check_ds(parser)
+        check_security_domain(parser)
+
+    if args.precheck:
+        print('pre-checks completed successfully.')
+        sys.exit(0)
+
+    print("Installing " + config.pki_subsystem + " into " +
+          parser.mdict['pki_instance_path'] + ".")
+
+    # Process the various "scriptlets" to create the specified PKI subsystem.
+    pki_subsystem_scriptlets = parser.mdict['spawn_scriplets'].split()
+    deployer = util.PKIDeployer(parser.mdict, parser.slots_dict)
+    rv = 0
+    for pki_scriptlet in pki_subsystem_scriptlets:
+        scriptlet = __import__("pki.server.deployment.scriptlets." +
+                               pki_scriptlet,
+                               fromlist=[pki_scriptlet])
+        instance = scriptlet.PkiScriptlet()
+        try:
+            rv = instance.spawn(deployer)
+        # pylint: disable=W0703
+        except Exception:
+            log_error_details()
+            print()
+            print("Installation failed.")
+            print()
+            sys.exit(1)
+        if rv != 0:
+            print("Nothing here!!!")
+            print("Installation failed.")
+            sys.exit(1)
+    config.pki_log.debug(log.PKI_DICTIONARY_MASTER,
+                         extra=config.PKI_INDENTATION_LEVEL_0)
+    config.pki_log.debug(pkilogging.log_format(parser.mdict),
+                         extra=config.PKI_INDENTATION_LEVEL_0)
+
+    external = deployer.configuration_file.external
+    step_one = deployer.configuration_file.external_step_one
+
+    if external and step_one:
+        external_csr_path = deployer.mdict['pki_external_csr_path']
+        if external_csr_path:
+            print_external_ca_step_one_information(parser.mdict)
+        else:
+            print_existing_ca_step_one_information(parser.mdict)
+    else:
+        print_install_information(parser.mdict)
+
+
+def start_logging():
     # Enable 'pkispawn' logging.
     config.pki_log_dir = config.pki_root_prefix + \
         config.PKI_DEPLOYMENT_LOG_ROOT
@@ -496,7 +560,6 @@ def main(argv):
                           "-" + "spawn" + "." + \
                           config.pki_timestamp + "." + "log"
     print('Log file: %s/%s' % (config.pki_log_dir, config.pki_log_name))
-
     rv = pkilogging.enable_pki_logger(config.pki_log_dir,
                                       config.pki_log_name,
                                       config.pki_log_level,
@@ -508,6 +571,8 @@ def main(argv):
         print(log.PKI_UNABLE_TO_CREATE_LOG_DIRECTORY_1 % config.pki_log_dir)
         sys.exit(1)
 
+
+def create_master_dictionary(parser):
     # Read the specified PKI configuration file.
     rv = parser.read_pki_configuration_file()
     if rv != 0:
@@ -521,10 +586,8 @@ def main(argv):
                          extra=config.PKI_INDENTATION_LEVEL_0)
     config.pki_log.debug(pkilogging.log_format(parser.slots_dict),
                          extra=config.PKI_INDENTATION_LEVEL_0)
-
     # Combine the various sectional dictionaries into a PKI master dictionary
     parser.compose_pki_master_dictionary()
-
     parser.mdict['pki_spawn_log'] = \
         config.pki_log_dir + "/" + config.pki_log_name
     config.pki_log.debug(log.PKI_DICTIONARY_MASTER,
@@ -532,43 +595,21 @@ def main(argv):
     config.pki_log.debug(pkilogging.log_format(parser.mdict),
                          extra=config.PKI_INDENTATION_LEVEL_0)
 
-    if not interactive and \
-            not config.str2bool(parser.mdict['pki_skip_configuration']):
+
+def check_security_domain(parser):
+    if parser.mdict['pki_security_domain_type'] != "new":
         try:
-            # Verify existence of Directory Server Password
-            if 'pki_ds_password' not in parser.mdict or\
-               not len(parser.mdict['pki_ds_password']):
+            # Verify existence of Security Domain Password
+            if 'pki_security_domain_password' not in parser.mdict or \
+                    not len(parser.mdict['pki_security_domain_password']):
                 config.pki_log.error(
                     log.PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2,
-                    "pki_ds_password",
+                    "pki_security_domain_password",
                     parser.mdict['pki_user_deployment_cfg'],
                     extra=config.PKI_INDENTATION_LEVEL_0)
                 sys.exit(1)
 
-            parser.ds_verify_configuration()
-
-            if parser.ds_base_dn_exists() and\
-                    not config.str2bool(parser.mdict['pki_ds_remove_data']):
-                print('ERROR:  Base DN already exists.')
-                sys.exit(1)
-
-        except ldap.LDAPError as e:
-            print('ERROR:  Unable to access directory server: ' +
-                  e.args[0]['desc'])
-            sys.exit(1)
-
-        if parser.mdict['pki_security_domain_type'] != "new":
-            try:
-                # Verify existence of Security Domain Password
-                if 'pki_security_domain_password' not in parser.mdict or\
-                   not len(parser.mdict['pki_security_domain_password']):
-                    config.pki_log.error(
-                        log.PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2,
-                        "pki_security_domain_password",
-                        parser.mdict['pki_user_deployment_cfg'],
-                        extra=config.PKI_INDENTATION_LEVEL_0)
-                    sys.exit(1)
-
+            if not config.str2bool(parser.mdict['pki_skip_sd_verify']):
                 parser.sd_connect()
                 info = parser.sd_get_info()
                 parser.set_property(config.pki_subsystem,
@@ -576,55 +617,39 @@ def main(argv):
                                     info.name)
                 parser.sd_authenticate()
 
-            except requests.exceptions.ConnectionError as e:
-                print(('ERROR:  Unable to access security domain: ' + str(e)))
-                sys.exit(1)
+        except requests.exceptions.ConnectionError as e:
+            print(('ERROR:  Unable to access security domain: ' + str(e)))
+            sys.exit(1)
 
-            except requests.exceptions.HTTPError as e:
-                print(('ERROR:  Unable to access security domain: ' + str(e)))
-                sys.exit(1)
+        except requests.exceptions.HTTPError as e:
+            print(('ERROR:  Unable to access security domain: ' + str(e)))
+            sys.exit(1)
 
-    print("Installing " + config.pki_subsystem + " into " +
-          parser.mdict['pki_instance_path'] + ".")
 
-    # Process the various "scriptlets" to create the specified PKI subsystem.
-    pki_subsystem_scriptlets = parser.mdict['spawn_scriplets'].split()
-    deployer = util.PKIDeployer(parser.mdict, parser.slots_dict)
-    rv = 0
-    for pki_scriptlet in pki_subsystem_scriptlets:
-        scriptlet = __import__("pki.server.deployment.scriptlets." +
-                               pki_scriptlet,
-                               fromlist=[pki_scriptlet])
-        instance = scriptlet.PkiScriptlet()
-        try:
-            rv = instance.spawn(deployer)
-        # pylint: disable=W0703
-        except Exception:
-            log_error_details()
-            print()
-            print("Installation failed.")
-            print()
+def check_ds(parser):
+    try:
+        # Verify existence of Directory Server Password
+        if 'pki_ds_password' not in parser.mdict or \
+                not len(parser.mdict['pki_ds_password']):
+            config.pki_log.error(
+                log.PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2,
+                "pki_ds_password",
+                parser.mdict['pki_user_deployment_cfg'],
+                extra=config.PKI_INDENTATION_LEVEL_0)
             sys.exit(1)
-        if rv != 0:
-            print("Nothing here!!!")
-            print("Installation failed.")
-            sys.exit(1)
-    config.pki_log.debug(log.PKI_DICTIONARY_MASTER,
-                         extra=config.PKI_INDENTATION_LEVEL_0)
-    config.pki_log.debug(pkilogging.log_format(parser.mdict),
-                         extra=config.PKI_INDENTATION_LEVEL_0)
 
-    external = deployer.configuration_file.external
-    step_one = deployer.configuration_file.external_step_one
+        if not config.str2bool(parser.mdict['pki_skip_ds_verify']):
+            parser.ds_verify_configuration()
+
+            if parser.ds_base_dn_exists() and not \
+                    config.str2bool(parser.mdict['pki_ds_remove_data']):
+                print('ERROR:  Base DN already exists.')
+                sys.exit(1)
 
-    if external and step_one:
-        external_csr_path = deployer.mdict['pki_external_csr_path']
-        if external_csr_path:
-            print_external_ca_step_one_information(parser.mdict)
-        else:
-            print_existing_ca_step_one_information(parser.mdict)
-    else:
-        print_install_information(parser.mdict)
+    except ldap.LDAPError as e:
+        print('ERROR:  Unable to access directory server: ' +
+              e.args[0]['desc'])
+        sys.exit(1)
 
 
 def set_port(parser, tag, prompt, existing_data):
-- 
2.4.3

