>From 82c4bd6a946f2aed6a5b9d33435ff8d3c4d3f2ab Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata@redhat.com>
Date: Wed, 27 Apr 2016 04:58:12 +0200
Subject: [PATCH] Fixed duplicate executions of finalization scriptlet.

Previously the finalization scriptlet was always executed in each
pkispawn execution. In multi-step installations (e.g. external CA,
standalone, or installation/configuration-only mode) some of the
code in the scriptlet such as enabling systemd service, restarting
the service, and purging client database will be redundant.

Now the scriptlet has been modified to execute only in the final
step of the installation. The code that archives the deployment
and manifest files has been moved into pkispawn to ensure that it
is always executed in each pkispawn execution.

For clarity the method that displays the installation summary has
been broken up into separate methods for standalone step 1,
installation-only mode, and configuration-only/full installation.
---
 .../python/pki/server/deployment/pkimessages.py    |   3 +-
 .../server/deployment/scriptlets/finalization.py   |  43 ++----
 base/server/sbin/pkispawn                          | 149 +++++++++++++++------
 3 files changed, 126 insertions(+), 69 deletions(-)

diff --git a/base/server/python/pki/server/deployment/pkimessages.py b/base/server/python/pki/server/deployment/pkimessages.py
index b58915fe269c26bece62677974431caf783004c4..c8821bbb632ff5c8f329e7bd278db9e283d01542 100644
--- a/base/server/python/pki/server/deployment/pkimessages.py
+++ b/base/server/python/pki/server/deployment/pkimessages.py
@@ -98,7 +98,8 @@ PKI_SUBORDINATE_UNSUPPORTED_1 = \
 PKI_IOERROR_1 = "IOError:  %s!"
 PKI_KEYERROR_1 = "KeyError:  %s!"
 PKI_LARGEZIPFILE_ERROR_1 = "zipfile.LargeZipFile:  %s!"
-PKI_MANIFEST_MESSAGE_1 = "generating manifest file called '%s'"
+PKI_ARCHIVE_CONFIG_MESSAGE_1 = "archiving configuration into '%s'"
+PKI_ARCHIVE_MANIFEST_MESSAGE_1 = "archiving manifest into '%s'"
 PKI_OSERROR_1 = "OSError:  %s!"
 PKI_SHUTIL_ERROR_1 = "shutil.Error:  %s!"
 PKI_SUBPROCESS_ERROR_1 = "subprocess.CalledProcessError:  %s!"
diff --git a/base/server/python/pki/server/deployment/scriptlets/finalization.py b/base/server/python/pki/server/deployment/scriptlets/finalization.py
index 8f8cfe0ac6e91c5332f28ffd8ccbc2a0ad8b056a..5fd8d1a57137bc09e8c6ff4aa7137df8080dd506 100644
--- a/base/server/python/pki/server/deployment/scriptlets/finalization.py
+++ b/base/server/python/pki/server/deployment/scriptlets/finalization.py
@@ -19,10 +19,10 @@
 #
 
 from __future__ import absolute_import
+import os
 
 # PKI Deployment Imports
 from .. import pkiconfig as config
-from .. import pkimanifest as manifest
 from .. import pkimessages as log
 from .. import pkiscriptlet
 
@@ -32,30 +32,19 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet):
 
     def spawn(self, deployer):
 
-        # ALWAYS finalize execution of scriptlets
+        external = deployer.configuration_file.external
+        standalone = deployer.configuration_file.standalone
+        step_one = deployer.configuration_file.external_step_one
+        skip_configuration = deployer.configuration_file.skip_configuration
+
+        if (external or standalone) and step_one or skip_configuration:
+            config.pki_log.info(log.SKIP_FINALIZATION_SPAWN_1, __name__,
+                                extra=config.PKI_INDENTATION_LEVEL_1)
+            return
+
         config.pki_log.info(log.FINALIZATION_SPAWN_1, __name__,
                             extra=config.PKI_INDENTATION_LEVEL_1)
-        # For debugging/auditing purposes, save a timestamped copy of
-        # this configuration file in the subsystem archive
-        deployer.file.copy(
-            deployer.mdict['pki_user_deployment_cfg_replica'],
-            deployer.mdict['pki_user_deployment_cfg_spawn_archive'])
-        # Save a copy of the installation manifest file
-        config.pki_log.info(
-            log.PKI_MANIFEST_MESSAGE_1, deployer.mdict['pki_manifest'],
-            extra=config.PKI_INDENTATION_LEVEL_2)
-        # for record in manifest.database:
-        #     print tuple(record)
-        manifest_file = manifest.File(deployer.manifest_db)
-        manifest_file.register(deployer.mdict['pki_manifest'])
-        manifest_file.write()
-        deployer.file.modify(deployer.mdict['pki_manifest'], silent=True)
 
-        # Also, for debugging/auditing purposes, save a timestamped copy of
-        # this installation manifest file
-        deployer.file.copy(
-            deployer.mdict['pki_manifest'],
-            deployer.mdict['pki_manifest_spawn_archive'])
         # Optionally, programmatically 'enable' the configured PKI instance
         # to be started upon system boot (default is True)
         if not config.str2bool(deployer.mdict['pki_enable_on_system_boot']):
@@ -66,13 +55,9 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet):
             # Modify contents of 'serverCertNick.conf' (if necessary)
             deployer.servercertnick_conf.modify()
 
-        external = config.str2bool(deployer.mdict['pki_external'])
-        step_one = not config.str2bool(deployer.mdict['pki_external_step_two'])
-
-        if not (external and step_one):
-            # Optionally, programmatically 'restart' the configured PKI instance
-            if config.str2bool(deployer.mdict['pki_restart_configured_instance']):
-                deployer.systemd.restart()
+        # Optionally, programmatically 'restart' the configured PKI instance
+        if config.str2bool(deployer.mdict['pki_restart_configured_instance']):
+            deployer.systemd.restart()
 
         # Optionally, 'purge' the entire temporary client infrastructure
         # including the client NSS security databases and password files
diff --git a/base/server/sbin/pkispawn b/base/server/sbin/pkispawn
index b019d8869e4247cc8c0c635775c37b96575df152..f75fa43aec5f1f147d898b051a04a8186b3ef232 100755
--- a/base/server/sbin/pkispawn
+++ b/base/server/sbin/pkispawn
@@ -40,6 +40,7 @@ try:
     import traceback
     from time import strftime as date
     from pki.server.deployment import pkiconfig as config
+    from pki.server.deployment import pkimanifest as manifest
     from pki.server.deployment.pkiparser import PKIConfigParser
     from pki.server.deployment import pkilogging
     from pki.server.deployment import pkimessages as log
@@ -534,18 +535,60 @@ def main(argv):
         print()
         sys.exit(1)
 
+    # ALWAYS archive configuration file and manifest file
+
+    config.pki_log.info(
+        log.PKI_ARCHIVE_CONFIG_MESSAGE_1,
+        deployer.mdict['pki_user_deployment_cfg_spawn_archive'],
+        extra=config.PKI_INDENTATION_LEVEL_1)
+
+    # For debugging/auditing purposes, save a timestamped copy of
+    # this configuration file in the subsystem archive
+    deployer.file.copy(
+        deployer.mdict['pki_user_deployment_cfg_replica'],
+        deployer.mdict['pki_user_deployment_cfg_spawn_archive'])
+
+    config.pki_log.info(
+        log.PKI_ARCHIVE_MANIFEST_MESSAGE_1,
+        deployer.mdict['pki_manifest_spawn_archive'],
+        extra=config.PKI_INDENTATION_LEVEL_1)
+
+    # for record in manifest.database:
+    #     print tuple(record)
+
+    manifest_file = manifest.File(deployer.manifest_db)
+    manifest_file.register(deployer.mdict['pki_manifest'])
+    manifest_file.write()
+
+    deployer.file.modify(deployer.mdict['pki_manifest'], silent=True)
+
+    # Also, for debugging/auditing purposes, save a timestamped copy of
+    # this installation manifest file
+    deployer.file.copy(
+        deployer.mdict['pki_manifest'],
+        deployer.mdict['pki_manifest_spawn_archive'])
+
     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
+    standalone = deployer.configuration_file.standalone
     step_one = deployer.configuration_file.external_step_one
+    skip_configuration = deployer.configuration_file.skip_configuration
 
     if external and step_one:
         print_external_ca_step_one_information(parser.mdict)
+
+    elif standalone and step_one:
+        print_standalone_step_one_information(parser.mdict)
+
+    elif skip_configuration:
+        print_skip_configuration_information(parser.mdict)
+
     else:
-        print_install_information(parser.mdict)
+        print_final_install_information(parser.mdict)
 
 
 def start_logging():
@@ -672,48 +715,76 @@ def print_external_ca_step_one_information(mdict):
     print(log.PKI_SPAWN_INFORMATION_FOOTER)
 
 
-def print_install_information(mdict):
+def print_standalone_step_one_information(mdict):
 
-    skip_configuration = config.str2bool(mdict['pki_skip_configuration'])
     print(log.PKI_SPAWN_INFORMATION_HEADER)
-    if skip_configuration:
-        print("      The %s subsystem of the '%s' instance\n"
-              "      must still be configured!" %
+    print("      The %s subsystem of the '%s' instance is still incomplete." %
+          (config.pki_subsystem, mdict['pki_instance_name']))
+    print()
+    print("      The CSRs for the %s certificates have been generated in:\n"
+          "            %s"
+          % (config.pki_subsystem, mdict['pki_instance_configuration_path']))
+    print(log.PKI_CHECK_STATUS_MESSAGE % mdict['pki_instance_name'])
+    print(log.PKI_INSTANCE_RESTART_MESSAGE % mdict['pki_instance_name'])
+    print(log.PKI_CONFIGURATION_STANDALONE_1 % config.pki_subsystem)
+    print(log.PKI_SPAWN_INFORMATION_FOOTER)
+
+
+def print_skip_configuration_information(mdict):
+
+    print(log.PKI_SPAWN_INFORMATION_HEADER)
+    print("      The %s subsystem of the '%s' instance\n"
+          "      must still be configured!" %
+          (config.pki_subsystem, mdict['pki_instance_name']))
+    print(log.PKI_CHECK_STATUS_MESSAGE % mdict['pki_instance_name'])
+    print(log.PKI_INSTANCE_RESTART_MESSAGE % mdict['pki_instance_name'])
+
+    print(log.PKI_ACCESS_URL % (mdict['pki_hostname'],
+                                mdict['pki_https_port'],
+                                config.pki_subsystem.lower()))
+    if not config.str2bool(mdict['pki_enable_on_system_boot']):
+        print(log.PKI_SYSTEM_BOOT_STATUS_MESSAGE % "disabled")
+    else:
+        print(log.PKI_SYSTEM_BOOT_STATUS_MESSAGE % "enabled")
+    print(log.PKI_SPAWN_INFORMATION_FOOTER)
+
+
+def print_final_install_information(mdict):
+
+    print(log.PKI_SPAWN_INFORMATION_HEADER)
+    print("      Administrator's username:             %s" %
+          mdict['pki_admin_uid'])
+
+    if os.path.isfile(mdict['pki_client_admin_cert_p12']):
+        print("      Administrator's PKCS #12 file:\n            %s" %
+              mdict['pki_client_admin_cert_p12'])
+
+    if not config.str2bool(mdict['pki_client_database_purge']):
+        print()
+        print("      Administrator's certificate nickname:\n            %s"
+              % mdict['pki_admin_nickname'])
+
+    if not config.str2bool(mdict['pki_clone']):
+        print("      Administrator's certificate database:\n            %s"
+              % mdict['pki_client_database_dir'])
+
+    else:
+        print()
+        print("      This %s subsystem of the '%s' instance\n"
+              "      is a clone." %
               (config.pki_subsystem, mdict['pki_instance_name']))
+
+    print(log.PKI_CHECK_STATUS_MESSAGE % mdict['pki_instance_name'])
+    print(log.PKI_INSTANCE_RESTART_MESSAGE % mdict['pki_instance_name'])
+
+    print(log.PKI_ACCESS_URL % (mdict['pki_hostname'],
+                                mdict['pki_https_port'],
+                                config.pki_subsystem.lower()))
+    if not config.str2bool(mdict['pki_enable_on_system_boot']):
+        print(log.PKI_SYSTEM_BOOT_STATUS_MESSAGE % "disabled")
     else:
-        print("      Administrator's username:             %s" %
-              mdict['pki_admin_uid'])
-        if os.path.isfile(mdict['pki_client_admin_cert_p12']):
-            print("      Administrator's PKCS #12 file:\n            %s" %
-                  mdict['pki_client_admin_cert_p12'])
-        if not config.str2bool(mdict['pki_client_database_purge']):
-            print()
-            print("      Administrator's certificate nickname:\n            %s"
-                  % mdict['pki_admin_nickname'])
-        if not config.str2bool(mdict['pki_clone']):
-            print("      Administrator's certificate database:\n            %s"
-                  % mdict['pki_client_database_dir'])
-        else:
-            print()
-            print("      This %s subsystem of the '%s' instance\n"
-                  "      is a clone." %
-                  (config.pki_subsystem, mdict['pki_instance_name']))
-        print(log.PKI_CHECK_STATUS_MESSAGE % mdict['pki_instance_name'])
-        print(log.PKI_INSTANCE_RESTART_MESSAGE % mdict['pki_instance_name'])
-        if (((config.pki_subsystem == "KRA" or
-              config.pki_subsystem == "OCSP") and
-             config.str2bool(mdict['pki_standalone'])) and
-                not config.str2bool(mdict['pki_external_step_two'])):
-            # Stand-alone PKI KRA/OCSP (External CA Step 1)
-            print(log.PKI_CONFIGURATION_STANDALONE_1 % config.pki_subsystem)
-        else:
-            print(log.PKI_ACCESS_URL % (mdict['pki_hostname'],
-                                        mdict['pki_https_port'],
-                                        config.pki_subsystem.lower()))
-            if not config.str2bool(mdict['pki_enable_on_system_boot']):
-                print(log.PKI_SYSTEM_BOOT_STATUS_MESSAGE % "disabled")
-            else:
-                print(log.PKI_SYSTEM_BOOT_STATUS_MESSAGE % "enabled")
+        print(log.PKI_SYSTEM_BOOT_STATUS_MESSAGE % "enabled")
+
     print(log.PKI_SPAWN_INFORMATION_FOOTER)
 
 
-- 
2.5.5

