>From d0c91b8a337ecd95512be91b22a23fe0e4514911 Mon Sep 17 00:00:00 2001
From: Ade Lee <alee@redhat.com>
Date: Fri, 1 Feb 2013 14:21:25 -0500
Subject: [PATCH 117/117] Change pkidestroy to get an install token and use
 admin interface to update security domain.

---
 base/deploy/src/pkidestroy                   |  20 ++
 base/deploy/src/scriptlets/initialization.py |   6 +-
 base/deploy/src/scriptlets/pkiconfig.py      |   2 +
 base/deploy/src/scriptlets/pkihelper.py      | 371 ++++++++++++++++-----------
 base/deploy/src/scriptlets/pkimessages.py    |   2 +
 5 files changed, 257 insertions(+), 144 deletions(-)

diff --git a/base/deploy/src/pkidestroy b/base/deploy/src/pkidestroy
index edb57e9ac3472ab34b650f7ec9cdf7662e946dc6..2bda9a6b1e7a3414e3583bdd4d855cadeafb76e7 100755
--- a/base/deploy/src/pkidestroy
+++ b/base/deploy/src/pkidestroy
@@ -100,12 +100,32 @@ def main(argv):
         nargs=1, required=True, metavar='<instance>',
         help='FORMAT:  ${pki_instance_name}')
 
+    parser.optional.add_argument('-u',
+        dest='pki_secdomain_user',
+        action='store',
+        nargs=1, metavar='<security domain user>',
+        help='security domain user')
+
+    parser.optional.add_argument('-w', 
+        dest='pki_secdomain_pass',
+        action='store',
+        nargs=1, metavar='<security domain password>',
+        help='security domain password')
+
     args = parser.process_command_line_arguments(argv)
 
     # -i <instance name>
     config.pki_deployed_instance_name =\
         str(args.pki_deployed_instance_name).strip('[\']')
 
+    #    '-u'
+    if args.pki_secdomain_user:
+        config.pki_secdomain_user = str(args.pki_secdomain_user).strip('[\']')
+
+    #    '-w'
+    if args.pki_secdomain_pass:
+        config.pki_secdomain_pass = str(args.pki_secdomain_pass).strip('[\']')
+
     # verify that previously deployed instance exists
     deployed_pki_instance_path = config.pki_root_prefix +\
                                  config.PKI_DEPLOYMENT_BASE_ROOT + "/" +\
diff --git a/base/deploy/src/scriptlets/initialization.py b/base/deploy/src/scriptlets/initialization.py
index 102fd42455ae0a61b44b955c829cc407bc8c658d..3494ebdc7a296e12553b5ddfb6d82f03240e01e4 100644
--- a/base/deploy/src/scriptlets/initialization.py
+++ b/base/deploy/src/scriptlets/initialization.py
@@ -105,6 +105,10 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet):
         # get ports to remove selinux context
         util.configuration_file.populate_non_default_ports()
 
+        # get deinstallation token
+        token = util.security_domain.get_installation_token(
+            config.pki_secdomain_user, config.pki_secdomain_pass)
+
         # remove kra connector from CA if this is a KRA
         util.kra_connector.deregister()
 
@@ -116,7 +120,7 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet):
         #            instance's security domain may be a part of a
         #            tightly-coupled shared instance.
         #
-        util.security_domain.deregister()
+        util.security_domain.deregister(token)
         # ALWAYS Stop this Apache/Tomcat PKI Process
         util.systemd.stop()
         return self.rv
diff --git a/base/deploy/src/scriptlets/pkiconfig.py b/base/deploy/src/scriptlets/pkiconfig.py
index 4a884617c7caab03159b68d4407b8897f151564c..2d0596fa20199f4379c684540be9f29bb65cda03 100644
--- a/base/deploy/src/scriptlets/pkiconfig.py
+++ b/base/deploy/src/scriptlets/pkiconfig.py
@@ -119,6 +119,8 @@ default_deployment_cfg = None
 user_deployment_cfg = None
 #     'pkidestroy' ONLY
 pki_deployed_instance_name = None
+pki_secdomain_user = None
+pki_secdomain_pass = None
 
 # PKI Deployment "Optional" Command-Line Variables
 #     'pkispawn' ONLY
diff --git a/base/deploy/src/scriptlets/pkihelper.py b/base/deploy/src/scriptlets/pkihelper.py
index c58fcf0e886fee711297d0591a2e9127ee801d2f..7eae9324d3e96521a914644bed94f5810fd5eeec 100644
--- a/base/deploy/src/scriptlets/pkihelper.py
+++ b/base/deploy/src/scriptlets/pkihelper.py
@@ -2415,156 +2415,187 @@ class kra_connector:
 
 # PKI Deployment Security Domain Class
 class security_domain:
-    def deregister(self, critical_failure=False):
-        try:
-            # process this PKI subsystem instance's 'CS.cfg'
-            cs_cfg = PKIConfigParser.read_simple_configuration_file(master['pki_target_cs_cfg'])
+    def deregister(self, install_token, critical_failure=False):
+        # process this PKI subsystem instance's 'CS.cfg'
+        cs_cfg = PKIConfigParser.read_simple_configuration_file(
+            master['pki_target_cs_cfg'])
 
-            # assign key name/value pairs
-            machinename = cs_cfg.get('service.machineName')
-            sport = cs_cfg.get('service.securityDomainPort')
-            ncsport = cs_cfg.get('service.non_clientauth_securePort', '')
-            sechost = cs_cfg.get('securitydomain.host')
-            httpport = cs_cfg.get('securitydomain.httpport')
-            seceeport = cs_cfg.get('securitydomain.httpseeport')
-            secagentport = cs_cfg.get('securitydomain.httpsagentport')
-            secadminport = cs_cfg.get('securitydomain.httpsadminport')
-            secname = cs_cfg.get('securitydomain.name', 'unknown')
-            secselect = cs_cfg.get('securitydomain.select')
-            adminsport = cs_cfg.get('pkicreate.admin_secure_port', '')
-            typeval = cs_cfg.get('cs.type', '')
-            agentsport = cs_cfg.get('pkicreate.agent_secure_port', '')
-            token_pwd = None
+        # assign key name/value pairs
+        machinename = cs_cfg.get('service.machineName')
+        sport = cs_cfg.get('service.securityDomainPort')
+        ncsport = cs_cfg.get('service.non_clientauth_securePort', '')
+        sechost = cs_cfg.get('securitydomain.host')
+        httpport = cs_cfg.get('securitydomain.httpport')
+        seceeport = cs_cfg.get('securitydomain.httpseeport')
+        secagentport = cs_cfg.get('securitydomain.httpsagentport')
+        secadminport = cs_cfg.get('securitydomain.httpsadminport')
+        secname = cs_cfg.get('securitydomain.name', 'unknown')
+        secselect = cs_cfg.get('securitydomain.select')
+        adminsport = cs_cfg.get('pkicreate.admin_secure_port', '')
+        typeval = cs_cfg.get('cs.type', '')
+        agentsport = cs_cfg.get('pkicreate.agent_secure_port', '')
 
-            # retrieve subsystem nickname
-            subsystemnick_param = typeval.lower() + ".cert.subsystem.nickname"
-            subsystemnick = cs_cfg.get(subsystemnick_param)
-            if subsystemnick is None:
-                config.pki_log.warning(
-                    log.PKIHELPER_SECURITY_DOMAIN_UPDATE_FAILURE_2,
-                    typeval,
-                    secname,
-                    extra=config.PKI_INDENTATION_LEVEL_2)
-                config.pki_log.error(
-                    log.PKIHELPER_UNDEFINED_SUBSYSTEM_NICKNAME,
-                    extra=config.PKI_INDENTATION_LEVEL_2)
-                if critical_failure == True:
-                    sys.exit(-1)
-                else:
-                    return
-
-            # retrieve name of token based upon type (hardware/software)
-            if ':' in subsystemnick:
-                token_name = subsystemnick.split(':')[0]
+        # NOTE:  Don't check for the existence of 'httpport', as this will
+        #        be undefined for a Security Domain that has been migrated!
+        if sechost is None or\
+           seceeport is None or\
+           secagentport is None or\
+           secadminport is None:
+            config.pki_log.warning(
+                log.PKIHELPER_SECURITY_DOMAIN_UPDATE_FAILURE_2,
+                typeval,
+                secname,
+                extra=config.PKI_INDENTATION_LEVEL_2)
+            config.pki_log.error(
+                log.PKIHELPER_SECURITY_DOMAIN_UNDEFINED,
+                extra=config.PKI_INDENTATION_LEVEL_2)
+            if critical_failure == True:
+                sys.exit(-1)
             else:
-                token_name = "internal"
+                return
 
-            # NOTE:  Don't check for the existence of 'httpport', as this will
-            #        be undefined for a Security Domain that has been migrated!
-            if sechost is None or\
-               seceeport is None or\
-               secagentport is None or\
-               secadminport is None:
-                config.pki_log.warning(
-                    log.PKIHELPER_SECURITY_DOMAIN_UPDATE_FAILURE_2,
-                    typeval,
-                    secname,
-                    extra=config.PKI_INDENTATION_LEVEL_2)
-                config.pki_log.error(
-                    log.PKIHELPER_SECURITY_DOMAIN_UNDEFINED,
-                    extra=config.PKI_INDENTATION_LEVEL_2)
-                if critical_failure == True:
-                    sys.exit(-1)
-                else:
-                    return
+        config.pki_log.info(log.PKIHELPER_SECURITY_DOMAIN_CONTACT_1,
+                            secname,
+                            extra=config.PKI_INDENTATION_LEVEL_2)
+        listval = typeval.lower() + "List"
+        urlheader = "https://{}:{}".format(sechost, seceeport)
+        urlagentheader = "https://{}:{}".format(sechost, secagentport)
+        urladminheader = "https://{}:{}".format(sechost, secadminport)
+        updateURL = "/ca/agent/ca/updateDomainXML"
 
-            if secselect != "new":
-                # This is not a domain master, so we need to update the master
-                config.pki_log.info(log.PKIHELPER_SECURITY_DOMAIN_CONTACT_1,
-                                    secname,
-                                    extra=config.PKI_INDENTATION_LEVEL_2)
-                listval = typeval.lower() + "List"
-                urlheader = "https://{}:{}".format(sechost, seceeport)
-                urlagentheader = "https://{}:{}".format(sechost, secagentport)
-                urladminheader = "https://{}:{}".format(sechost, secadminport)
-                updateURL = "/ca/agent/ca/updateDomainXML"
+        params = "name=" + "\"" + master['pki_instance_path'] + "\"" +\
+                 "&type=" + str(typeval) +\
+                 "&list=" + str(listval) +\
+                 "&host=" + str(machinename) +\
+                 "&sport=" + str(sport) +\
+                 "&ncsport=" + str(ncsport) +\
+                 "&adminsport=" + str(adminsport) +\
+                 "&agentsport=" + str(agentsport) +\
+                 "&operation=remove"
 
-                token_pwd = password.get_password(
-                                master['pki_shared_password_conf'],
-                                token_name,
-                                critical_failure)
-                if token_pwd is None or token_pwd == '':
-                    config.pki_log.warning(
-                        log.PKIHELPER_SECURITY_DOMAIN_UPDATE_FAILURE_2,
-                        typeval,
-                        secname,
-                        extra=config.PKI_INDENTATION_LEVEL_2)
-                    if critical_failure == True:
-                        sys.exit(-1)
-                    else:
-                        return
-
-                params = "name=" + "\"" + master['pki_instance_path'] + "\"" +\
-                         "&type=" + str(typeval) +\
-                         "&list=" + str(listval) +\
-                         "&host=" + str(machinename) +\
-                         "&sport=" + str(sport) +\
-                         "&ncsport=" + str(ncsport) +\
-                         "&adminsport=" + str(adminsport) +\
-                         "&agentsport=" + str(agentsport) +\
-                         "&operation=remove"
-
-                # Compose this "sslget" command
-                #
-                #     REMINDER:  NEVER log this command as it contains
-                #                an exposed password in plaintext!
-                #
-                command = "/usr/bin/sslget -n '{}' -p '{}' -d '{}' -e '{}' "\
+        if install_token:
+            try:
+                # first try install token-based servlet
+                params += "&sessionID=" + str(install_token)
+                adminUpdateURL = "/ca/admin/ca/updateDomainXML"
+                command = "/usr/bin/sslget -p 123456 -d '{}' -e '{}' "\
                           "-v -r '{}' {}:{} 2>&1".format(
-                              subsystemnick, token_pwd,
-                              master['pki_database_path'],
-                              params, updateURL,
-                              sechost, secagentport)
-                # update domainXML
-                # Execute this "sslget" command
+                             master['pki_database_path'],
+                             params, adminUpdateURL,
+                             sechost, secadminport)
                 output = subprocess.check_output(command,
-                                                 stderr=subprocess.STDOUT,
-                                                 shell=True)
-                config.pki_log.debug(log.PKIHELPER_SSLGET_OUTPUT_1,
-                                     output,
-                                     extra=config.PKI_INDENTATION_LEVEL_2)
-                # Search the output for Status
-                status = re.findall("\<Status\>(.*?)\<\/Status\>", output)
-                if not status:
-                    config.pki_log.warning(
-                        log.PKIHELPER_SECURITY_DOMAIN_UNREACHABLE_1,
-                        secname,
-                        extra=config.PKI_INDENTATION_LEVEL_2)
-                    if critical_failure == True:
-                        sys.exit(-1)
-                elif status[0] != "0":
-                    error = re.findall("\<Error\>(.*?)\<\/Error\>", output)
-                    if not error:
-                        error = ""
-                    config.pki_log.warning(
-                        log.PKIHELPER_SECURITY_DOMAIN_UNREGISTERED_2,
-                        typeval,
-                        secname,
-                        extra=config.PKI_INDENTATION_LEVEL_2)
-                    config.pki_log.error(
-                        log.PKIHELPER_SECURITY_DOMAIN_UPDATE_FAILURE_3,
-                        typeval,
-                        secname,
-                        error,
-                        extra=config.PKI_INDENTATION_LEVEL_2)
-                    if critical_failure == True:
-                         sys.exit(-1)
-                else:
-                    config.pki_log.info(
-                        log.PKIHELPER_SECURITY_DOMAIN_UPDATE_SUCCESS_2,
-                        typeval,
-                        secname,
-                        extra=config.PKI_INDENTATION_LEVEL_2)
+                                             stderr=subprocess.STDOUT,
+                                             shell=True)
+            except subprocess.CalledProcessError as exc:
+                config.pki_log.warning(
+                    log.PKIHELPER_SECURITY_DOMAIN_UNREACHABLE_1,
+                    secname,
+                    extra=config.PKI_INDENTATION_LEVEL_2)
+                output = self.update_domain_using_agent_port(typeval, 
+                    secname, params, updateURL, sechost, secagentport, 
+                    critical_failure)
+        else:
+            output = self.update_domain_using_agent_port(typeval, 
+                secname, params, updateURL, sechost, secagentport, 
+                critical_failure)
+
+        if not output: 
+            if critical_failure == True:
+                sys.exit(-1)
+            else:
+                return
+            
+        config.pki_log.debug(log.PKIHELPER_SSLGET_OUTPUT_1,
+                             output,
+                             extra=config.PKI_INDENTATION_LEVEL_2)
+        # Search the output for Status
+        status = re.findall("\<Status\>(.*?)\<\/Status\>", output)
+        if not status:
+            config.pki_log.warning(
+                log.PKIHELPER_SECURITY_DOMAIN_UNREACHABLE_1,
+                secname,
+                extra=config.PKI_INDENTATION_LEVEL_2)
+            if critical_failure == True:
+                sys.exit(-1)
+        elif status[0] != "0":
+            error = re.findall("\<Error\>(.*?)\<\/Error\>", output)
+            if not error:
+                error = ""
+            config.pki_log.warning(
+                log.PKIHELPER_SECURITY_DOMAIN_UNREGISTERED_2,
+                typeval,
+                secname,
+                extra=config.PKI_INDENTATION_LEVEL_2)
+            config.pki_log.error(
+                log.PKIHELPER_SECURITY_DOMAIN_UPDATE_FAILURE_3,
+                typeval,
+                secname,
+                error,
+                extra=config.PKI_INDENTATION_LEVEL_2)
+            if critical_failure == True:
+                sys.exit(-1)
+        else:
+            config.pki_log.info(
+                log.PKIHELPER_SECURITY_DOMAIN_UPDATE_SUCCESS_2,
+                typeval,
+                secname,
+                extra=config.PKI_INDENTATION_LEVEL_2)
+
+    def update_domain_using_agent_port(self, typeval, secname, params,
+        updateURL, sechost, secagentport, critical_failure= False):
+        token_pwd = None
+        cs_cfg = PKIConfigParser.read_simple_configuration_file(
+            master['pki_target_cs_cfg'])
+        # retrieve subsystem nickname
+        subsystemnick_param = typeval.lower() + ".cert.subsystem.nickname"
+        subsystemnick = cs_cfg.get(subsystemnick_param)
+        if subsystemnick is None:
+            config.pki_log.warning(
+                log.PKIHELPER_SECURITY_DOMAIN_UPDATE_FAILURE_2,
+                typeval,
+                secname,
+                extra=config.PKI_INDENTATION_LEVEL_2)
+            config.pki_log.error(
+                log.PKIHELPER_UNDEFINED_SUBSYSTEM_NICKNAME,
+                extra=config.PKI_INDENTATION_LEVEL_2)
+            if critical_failure == True:
+                sys.exit(-1)
+            else:
+                return
+
+        # retrieve name of token based upon type (hardware/software)
+        if ':' in subsystemnick:
+            token_name = subsystemnick.split(':')[0]
+        else:
+            token_name = "internal"
+
+        token_pwd = password.get_password(
+                        master['pki_shared_password_conf'],
+                        token_name,
+                        critical_failure)
+
+        if token_pwd is None or token_pwd == '':
+            config.pki_log.warning(
+                log.PKIHELPER_SECURITY_DOMAIN_UPDATE_FAILURE_2,
+                typeval,
+                secname,
+                extra=config.PKI_INDENTATION_LEVEL_2)
+            if critical_failure == True:
+                sys.exit(-1)
+            else:
+                return
+
+        command = "/usr/bin/sslget -n '{}' -p '{}' -d '{}' -e '{}' "\
+                  "-v -r '{}' {}:{} 2>&1".format(
+                      subsystemnick, token_pwd,
+                      master['pki_database_path'],
+                      params, updateURL,
+                      sechost, secagentport)
+        try:
+            output = subprocess.check_output(command,
+                                             stderr=subprocess.STDOUT,
+                                             shell=True)
+            return output
         except subprocess.CalledProcessError as exc:
             config.pki_log.warning(
                 log.PKIHELPER_SECURITY_DOMAIN_UPDATE_FAILURE_2,
@@ -2579,8 +2610,62 @@ class security_domain:
                                  extra=config.PKI_INDENTATION_LEVEL_2)
             if critical_failure == True:
                 sys.exit(-1)
-        return
 
+        return None
+
+
+    def get_installation_token(self, secuser, secpass, critical_failure=True):
+        token = None
+
+        if not secuser or not secpass:
+            return None
+
+        # process this PKI subsystem instance's 'CS.cfg'
+        cs_cfg = PKIConfigParser.read_simple_configuration_file(
+            master['pki_target_cs_cfg'])
+
+        # assign key name/value pairs
+        machinename = cs_cfg.get('service.machineName')
+        cstype = cs_cfg.get('cs.type', '')
+        sechost = cs_cfg.get('securitydomain.host')
+        secadminport = cs_cfg.get('securitydomain.httpsadminport')
+        secselect = cs_cfg.get('securitydomain.select')
+
+        command = "/bin/pki -p '{}' -h '{}' -P https -u '{}' -w '{}' "\
+                  "securitydomain-get-install-token --hostname {} "\
+                  "--subsystem {}".format(
+                      secadminport, sechost, secuser, secpass,
+                      machinename, cstype)
+        try:
+            output = subprocess.check_output(command,
+                                         stderr=subprocess.STDOUT,
+                                         shell=True)
+
+            token_list = re.findall("Install token: \"(.*)\"", output)
+            if not token_list:
+                config.pki_log.error(
+                    log.PKIHELPER_SECURITY_DOMAIN_GET_TOKEN_FAILURE_2,
+                    str(sechost),
+                    str(secadminport),
+                    extra=config.PKI_INDENTATION_LEVEL_2)
+                config.pki_log.error(log.PKI_SUBPROCESS_ERROR_1, output,
+                    extra=config.PKI_INDENTATION_LEVEL_2)
+                if critical_failure == True:
+                    sys.exit(-1)
+            else:
+                token = token_list[0]
+                return token
+        except subprocess.CalledProcessError as exc:
+            config.pki_log.error(
+                log.PKIHELPER_SECURITY_DOMAIN_GET_TOKEN_FAILURE_2,
+                str(sechost),
+                str(secadminport),
+                extra=config.PKI_INDENTATION_LEVEL_2)
+            config.pki_log.error(log.PKI_SUBPROCESS_ERROR_1, exc,
+                                 extra=config.PKI_INDENTATION_LEVEL_2)
+            if critical_failure == True:
+                sys.exit(-1)
+        return None
 
 # PKI Deployment 'systemd' Execution Management Class
 class systemd:
diff --git a/base/deploy/src/scriptlets/pkimessages.py b/base/deploy/src/scriptlets/pkimessages.py
index 3a6bec1e389f6f282cd4f6a2f95386fdeb26753b..c16d3ce46618acb968f91314048331d2269bd6ec 100644
--- a/base/deploy/src/scriptlets/pkimessages.py
+++ b/base/deploy/src/scriptlets/pkimessages.py
@@ -232,6 +232,8 @@ PKIHELPER_RM_RF_1 = "rm -rf %s"
 PKIHELPER_RMDIR_1 = "rmdir %s"
 PKIHELPER_SECURITY_DOMAIN_CONTACT_1 =\
     "contacting the security domain master to update security domain '%s'"
+PKIHELPER_SECURITY_DOMAIN_GET_TOKEN_FAILURE_2 =\
+    "Failed to get installation token from security domain '%s:%s'"
 PKIHELPER_SECURITY_DOMAIN_UNDEFINED =\
     "No security domain defined.\n"\
     "If this is an unconfigured instance, then that is OK.\n"\
-- 
1.7.11.7

