From 1cceecafb8050ec362a9c9568d36d52d3fe4117e Mon Sep 17 00:00:00 2001 From: Ade Lee Date: Thu, 20 Dec 2012 17:38:13 -0500 Subject: Resolved Trac Ticket 367 - pkidestroy does not remove connector * Added RESTful servlet to add/remove a KRA connector from the CA. * Modified ACL to allow KRA subsystem user to remove connector. * Modified connector code to allow the connector to be replaced without a server restart. * Added functionality to pki CLI to add/remove connector * Added code to pkidestroy to remove the connector (using both pki CLI and sslget) When the issues with pki connection are resolved, we will use that method instead. * Modified sslget to accept HTTP return codes != 200. In this case, we were returning 204 - which is perfectly legitimate. --- base/deploy/src/scriptlets/initialization.py | 4 + base/deploy/src/scriptlets/pkihelper.py | 178 +++++++++++++++++++++++---- base/deploy/src/scriptlets/pkimessages.py | 6 + 3 files changed, 167 insertions(+), 21 deletions(-) (limited to 'base/deploy/src/scriptlets') diff --git a/base/deploy/src/scriptlets/initialization.py b/base/deploy/src/scriptlets/initialization.py index 034179ef1..102fd4245 100644 --- a/base/deploy/src/scriptlets/initialization.py +++ b/base/deploy/src/scriptlets/initialization.py @@ -104,6 +104,10 @@ class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet): util.identity.set_gid(master['pki_group']) # get ports to remove selinux context util.configuration_file.populate_non_default_ports() + + # remove kra connector from CA if this is a KRA + util.kra_connector.deregister() + # de-register instance from its Security Domain # # NOTE: Since the security domain of an instance must be up diff --git a/base/deploy/src/scriptlets/pkihelper.py b/base/deploy/src/scriptlets/pkihelper.py index 48c5f84f0..c58fcf0e8 100644 --- a/base/deploy/src/scriptlets/pkihelper.py +++ b/base/deploy/src/scriptlets/pkihelper.py @@ -1983,6 +1983,28 @@ class password: sys.exit(1) return + def get_password(self, path, token_name, critical_failure=True): + if os.path.exists(path) and os.path.isfile(path) and\ + os.access(path, os.R_OK): + tokens = PKIConfigParser.read_simple_configuration_file(path) + hardware_token = "hardware-" + token_name + if tokens.has_key(hardware_token): + token_name = hardware_token + token_pwd = tokens[hardware_token] + elif tokens.has_key(token_name): + token_pwd = tokens[token_name] + + if token_pwd is None or token_pwd == '': + # TODO prompt for this password + config.pki_log.error(log.PKIHELPER_PASSWORD_NOT_FOUND_1, + token_name, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + sys.exit(-1) + else: + return + return token_pwd + # PKI Deployment NSS 'certutil' Class class certutil: @@ -2260,6 +2282,136 @@ class certutil: sys.exit(1) return +# KRA Connector Class +class kra_connector: + def deregister(self, critical_failure=False): + try: + # this is applicable to KRAs only + if master['pki_subsystem_type'] != "kra": + return + + config.pki_log.info( + log.PKIHELPER_KRACONNECTOR_UPDATE_CONTACT, + extra=config.PKI_INDENTATION_LEVEL_2) + + cs_cfg = PKIConfigParser.read_simple_configuration_file( + master['pki_target_cs_cfg']) + krahost = cs_cfg.get('service.machineName') + kraport = cs_cfg.get('pkicreate.secure_port') + cahost = cs_cfg.get('cloning.ca.hostname') + caport = cs_cfg.get('cloning.ca.httpsport') + if cahost is None or\ + caport is None: + config.pki_log.warning( + log.PKIHELPER_KRACONNECTOR_UPDATE_FAILURE, + extra=config.PKI_INDENTATION_LEVEL_2) + config.pki_log.error( + log.PKIHELPER_UNDEFINED_CA_HOST_PORT, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + sys.exit(-1) + else: + return + + # retrieve subsystem nickname + subsystemnick = cs_cfg.get('kra.cert.subsystem.nickname') + if subsystemnick is None: + config.pki_log.warning( + log.PKIHELPER_KRACONNECTOR_UPDATE_FAILURE, + 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_KRACONNECTOR_UPDATE_FAILURE, + extra=config.PKI_INDENTATION_LEVEL_2) + config.pki_log.error( + log.PKIHELPER_UNDEFINED_TOKEN_PASSWD_1, + token_name, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + sys.exit(-1) + else: + return + + self.execute_using_sslget(caport, cahost, subsystemnick, + token_pwd, krahost, kraport) + + except subprocess.CalledProcessError as exc: + config.pki_log.warning( + log.PKIHELPER_KRACONNECTOR_UPDATE_FAILURE_2, + str(krahost), + str(kraport), + 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 + + def execute_using_pki(self, caport, cahost, subsystemnick, + token_pwd, krahost, kraport, critical_failure=False): + command = "/bin/pki -p '{}' -h '{}' -n '{}' -P https -d '{}' -w '{}' "\ + "kraconnector-del {} {}".format( + caport, cahost, subsystemnick, + master['pki_database_path'], + token_pwd, krahost, kraport) + + output = subprocess.check_output(command, + stderr=subprocess.STDOUT, + shell=True) + + error = re.findall("ClientResponseFailure:(.*?)", output) + if error: + config.pki_log.warning( + log.PKIHELPER_KRACONNECTOR_UPDATE_FAILURE_2, + str(krahost), + str(kraport), + 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) + + def execute_using_sslget(self, caport, cahost, subsystemnick, + token_pwd, krahost, kraport): + urlheader = "https://{}:{}".format(cahost, caport) + updateURL = "/ca/rest/admin/kraconnector/remove" + + params = "host=" + str(krahost) +\ + "&port=" + str(kraport) + + command = "/usr/bin/sslget -n '{}' -p '{}' -d '{}' -e '{}' "\ + "-v -r '{}' {}:{} 2>&1".format( + subsystemnick, token_pwd, + master['pki_database_path'], + params, updateURL, + cahost, caport) + + # update KRA connector + # Execute this "sslget" command + # Note that sslget will return non-zero value for HTTP code != 200 + # and this will raise an exception + output = subprocess.check_output(command, + stderr=subprocess.STDOUT, + shell=True) # PKI Deployment Security Domain Class class security_domain: @@ -2337,33 +2489,16 @@ class security_domain: urladminheader = "https://{}:{}".format(sechost, secadminport) updateURL = "/ca/agent/ca/updateDomainXML" - # process this PKI subsystem instance's 'password.conf' - # - # REMINDER: NEVER log this 'sensitive' information! - # - if os.path.exists(master['pki_shared_password_conf']) and\ - os.path.isfile(master['pki_shared_password_conf']) and\ - os.access(master['pki_shared_password_conf'], os.R_OK): - tokens = PKIConfigParser.read_simple_configuration_file( - master['pki_shared_password_conf']) - hardware_token = "hardware-" + token_name - if tokens.has_key(hardware_token): - token_name = hardware_token - token_pwd = tokens[hardware_token] - elif tokens.has_key(token_name): - token_pwd = tokens[token_name] - + token_pwd = password.get_password( + master['pki_shared_password_conf'], + token_name, + critical_failure) if token_pwd is None or token_pwd == '': - # 'pkiremove' prompts with - # "What is the password for this token?" 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_PASSWORD_NOT_FOUND_1, - token_name, - extra=config.PKI_INDENTATION_LEVEL_2) if critical_failure == True: sys.exit(-1) else: @@ -2608,5 +2743,6 @@ war = war() password = password() certutil = certutil() security_domain = security_domain() +kra_connector = kra_connector() systemd = systemd() jython = jython() diff --git a/base/deploy/src/scriptlets/pkimessages.py b/base/deploy/src/scriptlets/pkimessages.py index ade19422e..3a6bec1e3 100644 --- a/base/deploy/src/scriptlets/pkimessages.py +++ b/base/deploy/src/scriptlets/pkimessages.py @@ -194,6 +194,10 @@ PKIHELPER_IS_A_DIRECTORY_1 = "'%s' is a directory" PKIHELPER_IS_A_FILE_1 = "'%s' is a file" PKIHELPER_IS_A_SYMLINK_1 = "'%s' is a symlink" PKIHELPER_JAR_XF_C_2 = "jar -xf %s -C %s" +PKIHELPER_KRACONNECTOR_UPDATE_CONTACT =\ + "contacting the CA to update the KRA connector" +PKIHELPER_KRACONNECTOR_UPDATE_FAILURE = "Failed to update KRA connector on CA" +PKIHELPER_KRACONNECTOR_UPDATE_FAILURE_2 = "Failed to update KRA connector for %s:%s" PKIHELPER_LINK_S_2 = "ln -s %s %s" PKIHELPER_MKDIR_1 = "mkdir -p %s" PKIHELPER_MODIFY_DIR_1 = "modifying '%s'" @@ -259,12 +263,14 @@ PKIHELPER_TOMCAT_INSTANCES_2 = "PKI Tomcat registry '%s' contains '%d' "\ "Tomcat PKI instances" PKIHELPER_TOUCH_1 = "touch %s" PKIHELPER_UID_2 = "UID of '%s' is %s" +PKIHELPER_UNDEFINED_CA_HOST_PORT = "CA Host or Port is undefined" PKIHELPER_UNDEFINED_CLIENT_DATABASE_PASSWORD_2 =\ "Either a value for '%s' MUST be defined in '%s', or "\ "the randomly generated client pin MUST be used" PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2 =\ "A value for '%s' MUST be defined in '%s'" PKIHELPER_UNDEFINED_SUBSYSTEM_NICKNAME = "subsystem nickname not defined" +PKIHELPER_UNDEFINED_TOKEN_PASSWD_1 = "Password for token '%s' not defined" PKIHELPER_USER_1 = "retrieving UID for '%s' . . ." PKIHELPER_USER_ADD_2 = "adding UID '%s' for user '%s' . . ." PKIHELPER_USER_ADD_DEFAULT_2 = "adding default UID '%s' for user '%s' . . ." -- cgit