From 6f76531f4a1b81c07f2db5183f5b10c9f4a531c3 Mon Sep 17 00:00:00 2001 From: "Endi S. Dewata" Date: Tue, 16 Jul 2013 17:47:18 -0400 Subject: Reorganized deployment tools. The pkispawn and pkidestroy scripts have been moved into sbin folder. The Python deployment library and the scriptlets were moved into pki.server.deployment and pki.server.deployment.scriptlets packages, respectively. --- .../python/pki/server/deployment/__init__.py | 0 .../python/pki/server/deployment/pkiconfig.py | 177 + .../python/pki/server/deployment/pkihelper.py | 3516 ++++++++++++++++++++ .../python/pki/server/deployment/pkilogging.py | 76 + .../python/pki/server/deployment/pkimanifest.py | 104 + .../python/pki/server/deployment/pkimessages.py | 359 ++ .../python/pki/server/deployment/pkiparser.py | 1080 ++++++ .../python/pki/server/deployment/pkiscriptlet.py | 41 + .../pki/server/deployment/scriptlets/__init__.py | 0 .../server/deployment/scriptlets/configuration.py | 140 + .../server/deployment/scriptlets/finalization.py | 106 + .../deployment/scriptlets/infrastructure_layout.py | 114 + .../server/deployment/scriptlets/initialization.py | 113 + .../deployment/scriptlets/instance_layout.py | 184 + .../deployment/scriptlets/security_databases.py | 114 + .../server/deployment/scriptlets/selinux_setup.py | 204 ++ .../deployment/scriptlets/slot_substitution.py | 96 + .../deployment/scriptlets/subsystem_layout.py | 121 + .../deployment/scriptlets/webapp_deployment.py | 165 + 19 files changed, 6710 insertions(+) create mode 100644 base/server/python/pki/server/deployment/__init__.py create mode 100644 base/server/python/pki/server/deployment/pkiconfig.py create mode 100644 base/server/python/pki/server/deployment/pkihelper.py create mode 100644 base/server/python/pki/server/deployment/pkilogging.py create mode 100644 base/server/python/pki/server/deployment/pkimanifest.py create mode 100644 base/server/python/pki/server/deployment/pkimessages.py create mode 100644 base/server/python/pki/server/deployment/pkiparser.py create mode 100644 base/server/python/pki/server/deployment/pkiscriptlet.py create mode 100644 base/server/python/pki/server/deployment/scriptlets/__init__.py create mode 100644 base/server/python/pki/server/deployment/scriptlets/configuration.py create mode 100644 base/server/python/pki/server/deployment/scriptlets/finalization.py create mode 100644 base/server/python/pki/server/deployment/scriptlets/infrastructure_layout.py create mode 100644 base/server/python/pki/server/deployment/scriptlets/initialization.py create mode 100644 base/server/python/pki/server/deployment/scriptlets/instance_layout.py create mode 100644 base/server/python/pki/server/deployment/scriptlets/security_databases.py create mode 100644 base/server/python/pki/server/deployment/scriptlets/selinux_setup.py create mode 100644 base/server/python/pki/server/deployment/scriptlets/slot_substitution.py create mode 100644 base/server/python/pki/server/deployment/scriptlets/subsystem_layout.py create mode 100644 base/server/python/pki/server/deployment/scriptlets/webapp_deployment.py (limited to 'base/server/python/pki') diff --git a/base/server/python/pki/server/deployment/__init__.py b/base/server/python/pki/server/deployment/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/base/server/python/pki/server/deployment/pkiconfig.py b/base/server/python/pki/server/deployment/pkiconfig.py new file mode 100644 index 000000000..2e9463b9d --- /dev/null +++ b/base/server/python/pki/server/deployment/pkiconfig.py @@ -0,0 +1,177 @@ +#!/usr/bin/python -t +# Authors: +# Matthew Harmsen +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Copyright (C) 2012 Red Hat, Inc. +# All rights reserved. +# + +# PKI Deployment Constants +PKI_DEPLOYMENT_DEFAULT_CLIENT_DIR_PERMISSIONS = 00755 +PKI_DEPLOYMENT_DEFAULT_DIR_PERMISSIONS = 00770 +PKI_DEPLOYMENT_DEFAULT_EXE_PERMISSIONS = 00770 +PKI_DEPLOYMENT_DEFAULT_FILE_PERMISSIONS = 00660 +PKI_DEPLOYMENT_DEFAULT_SECURITY_DATABASE_PERMISSIONS = 00600 +PKI_DEPLOYMENT_DEFAULT_SGID_DIR_PERMISSIONS = 02770 +PKI_DEPLOYMENT_DEFAULT_SYMLINK_PERMISSIONS = 00777 +PKI_DEPLOYMENT_DEFAULT_UMASK = 00002 + +PKI_DEPLOYMENT_DEFAULT_COMMENT = "'Certificate System'" +PKI_DEPLOYMENT_DEFAULT_GID = 17 +PKI_DEPLOYMENT_DEFAULT_GROUP = "pkiuser" +PKI_DEPLOYMENT_DEFAULT_SHELL = "/sbin/nologin" +PKI_DEPLOYMENT_DEFAULT_UID = 17 +PKI_DEPLOYMENT_DEFAULT_USER = "pkiuser" + +PKI_SUBSYSTEMS = ["CA", "KRA", "OCSP", "RA", "TKS", "TPS"] +PKI_SIGNED_AUDIT_SUBSYSTEMS = ["CA", "KRA", "OCSP", "TKS", "TPS"] +PKI_APACHE_SUBSYSTEMS = ["RA"] +PKI_TOMCAT_SUBSYSTEMS = ["CA", "KRA", "OCSP", "TKS", "TPS"] +PKI_BASE_RESERVED_NAMES = ["alias", "bin", "ca", "common", "conf", "kra", + "lib", "logs", "ocsp", "temp", "tks", "tps", "webapps", + "work"] +PKI_CONFIGURATION_RESERVED_NAMES = ["CA", "java", "nssdb", "rpm-gpg", + "rsyslog", "tls"] +PKI_APACHE_REGISTRY_RESERVED_NAMES = ["ra"] +PKI_TOMCAT_REGISTRY_RESERVED_NAMES = ["ca", "kra", "ocsp", "tks", "tps"] + +PKI_INDENTATION_LEVEL_0 = {'indent' : ''} +PKI_INDENTATION_LEVEL_1 = {'indent' : '... '} +PKI_INDENTATION_LEVEL_2 = {'indent' : '....... '} +PKI_INDENTATION_LEVEL_3 = {'indent' : '........... '} +PKI_INDENTATION_LEVEL_4 = {'indent' : '............... '} + +PKI_DEPLOYMENT_INTERRUPT_BANNER = "-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+"\ + "-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-" + +PKI_DEPLOYMENT_SOURCE_ROOT = "/usr/share/pki" +PKI_DEPLOYMENT_BASE_ROOT = "/var/lib/pki" +# NOTE: Top-level "/etc/pki" is owned by the "filesystem" package! +PKI_DEPLOYMENT_CONFIGURATION_ROOT = "/etc/pki" +PKI_DEPLOYMENT_LOG_ROOT = "/var/log/pki" +# NOTE: Well-known 'registry root', default 'instance', and default +# 'configuration file' names MUST be created in order to potentially +# obtain an instance-specific configuration file +# (presuming one has not been specified during command-line parsing) +# because command-line parsing happens prior to reading any +# configuration files. Although the 'registry root' MUST remain fixed, +# the default 'instance' name may be overridden by the value specified +# in the configuration file (the value in the default configuration file +# should always match the 'default' instance name specified below). +PKI_DEPLOYMENT_DEFAULT_APACHE_INSTANCE_NAME = "pki-apache" +PKI_DEPLOYMENT_DEFAULT_TOMCAT_INSTANCE_NAME = "pki-tomcat" + +DEFAULT_DEPLOYMENT_CONFIGURATION = "default.cfg" +USER_DEPLOYMENT_CONFIGURATION = "deployment.cfg" + +PKI_DEPLOYMENT_DEFAULT_CONFIGURATION_FILE = \ + PKI_DEPLOYMENT_CONFIGURATION_ROOT + "/" + DEFAULT_DEPLOYMENT_CONFIGURATION +PKI_DEPLOYMENT_SLOTS_CONFIGURATION_FILE = \ + PKI_DEPLOYMENT_SOURCE_ROOT + "/deployment/config/pkislots.cfg" + +# subtypes of PKI subsystems +PKI_DEPLOYMENT_CLONED_PKI_SUBSYSTEM = "Cloned" +PKI_DEPLOYMENT_EXTERNAL_CA = "External" +PKI_DEPLOYMENT_SUBORDINATE_CA = "Subordinate" + +# default ports (for defined selinux policy) +PKI_DEPLOYMENT_DEFAULT_TOMCAT_HTTP_PORT = 8080 +PKI_DEPLOYMENT_DEFAULT_TOMCAT_HTTPS_PORT = 8443 +PKI_DEPLOYMENT_DEFAULT_TOMCAT_SERVER_PORT = 8005 +PKI_DEPLOYMENT_DEFAULT_TOMCAT_AJP_PORT = 8009 + +# PKI Deployment Global Variables +pki_install_time = None +pki_timestamp = None +pki_architecture = None +pki_hostname = None +pki_dns_domainname = None +pki_certificate_timestamp = None + + +# PKI Deployment Command-Line Variables +pki_deployment_executable = None + +# PKI Deployment "Mandatory" Command-Line Variables +pki_subsystem = None +# 'pkispawn' ONLY +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 "Test" Command-Line Variables +pki_root_prefix = None + + +# PKI Deployment Helper Functions +def str2bool(string): + return string.lower() in ("yes", "true", "t", "1") + +# NOTE: To utilize the 'preparations_for_an_external_java_debugger(master)' +# and 'wait_to_attach_an_external_java_debugger(master)' functions, +# change 'pki_enable_java_debugger=False' to +# 'pki_enable_java_debugger=True' in the appropriate +# deployment configuration file. +def prepare_for_an_external_java_debugger(instance): + print + print PKI_DEPLOYMENT_INTERRUPT_BANNER + print + print "The following 'JAVA_OPTS' MUST be enabled (uncommented) in" + print "'%s':" % instance + print + print " JAVA_OPTS=\"-Xdebug -Xrunjdwp:transport=dt_socket,\"" + print " \"address=8000,server=y,suspend\"" + print + raw_input("Enable external java debugger 'JAVA_OPTS' "\ + "and press return to continue . . . ") + print + print PKI_DEPLOYMENT_INTERRUPT_BANNER + print + return + +def wait_to_attach_an_external_java_debugger(): + print + print PKI_DEPLOYMENT_INTERRUPT_BANNER + print + print "Attach the java debugger to this process on the port specified by" + print "the 'address' selected by 'JAVA_OPTS' (e. g. - port 8000) and" + print "set any desired breakpoints" + print + raw_input("Please attach an external java debugger "\ + "and press return to continue . . . ") + print + print PKI_DEPLOYMENT_INTERRUPT_BANNER + print + return + + +# PKI Deployment Logger Variables +pki_log = None +pki_log_dir = None +pki_log_name = None +pki_log_level = None +pki_console_log_level = None + +# PKI Selinux Constants and parameters +PKI_INSTANCE_SELINUX_CONTEXT = "pki_tomcat_var_lib_t" +PKI_LOG_SELINUX_CONTEXT = "pki_tomcat_log_t" +PKI_CFG_SELINUX_CONTEXT = "pki_tomcat_etc_rw_t" +PKI_CERTDB_SELINUX_CONTEXT = "pki_tomcat_cert_t" +PKI_PORT_SELINUX_CONTEXT = "http_port_t" +pki_selinux_config_ports = [] diff --git a/base/server/python/pki/server/deployment/pkihelper.py b/base/server/python/pki/server/deployment/pkihelper.py new file mode 100644 index 000000000..6d47a902b --- /dev/null +++ b/base/server/python/pki/server/deployment/pkihelper.py @@ -0,0 +1,3516 @@ +#!/usr/bin/python -t + +# Authors: +# Matthew Harmsen +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Copyright (C) 2012 Red Hat, Inc. +# All rights reserved. +# + +# System Imports +import errno +import sys +import os +import fileinput +import random +import re +import requests +import shutil +from shutil import Error, WindowsError +import string +import subprocess +import time +import types +from datetime import datetime +from grp import getgrgid +from grp import getgrnam +from pwd import getpwnam +from pwd import getpwuid +import xml.etree.ElementTree as ET +import zipfile +import selinux +if selinux.is_selinux_enabled(): + import seobject + + +# PKI Deployment Imports +from . import pkiconfig as config +from .pkiconfig import pki_selinux_config_ports as ports +from . import pkimanifest as manifest +from . import pkimessages as log +from .pkiparser import PKIConfigParser +import pki.account +import pki.client +import pki.system + +# PKI Deployment Helper Functions +def pki_copytree(src, dst, symlinks=False, ignore=None): + """Recursively copy a directory tree using copy2(). + + PATCH: This code was copied from 'shutil.py' and patched to + allow 'The destination directory to already exist.' + + If exception(s) occur, an Error is raised with a list of reasons. + + If the optional symlinks flag is true, symbolic links in the + source tree result in symbolic links in the destination tree; if + it is false, the contents of the files pointed to by symbolic + links are copied. + + The optional ignore argument is a callable. If given, it + is called with the `src` parameter, which is the directory + being visited by pki_copytree(), and `names` which is the list of + `src` contents, as returned by os.listdir(): + + callable(src, names) -> ignored_names + + Since pki_copytree() is called recursively, the callable will be + called once for each directory that is copied. It returns a + list of names relative to the `src` directory that should + not be copied. + + *** Consider this example code rather than the ultimate tool. + + """ + names = os.listdir(src) + if ignore is not None: + ignored_names = ignore(src, names) + else: + ignored_names = set() + + # PATCH: ONLY execute 'os.makedirs(dst)' if the top-level + # destination directory does NOT exist! + if not os.path.exists(dst): + os.makedirs(dst) + errors = [] + for name in names: + if name in ignored_names: + continue + srcname = os.path.join(src, name) + dstname = os.path.join(dst, name) + try: + if symlinks and os.path.islink(srcname): + linkto = os.readlink(srcname) + os.symlink(linkto, dstname) + elif os.path.isdir(srcname): + pki_copytree(srcname, dstname, symlinks, ignore) + else: + # Will raise a SpecialFileError for unsupported file types + shutil.copy2(srcname, dstname) + # catch the Error from the recursive pki_copytree so that we can + # continue with other files + except Error, err: + errors.extend(err.args[0]) + except EnvironmentError, why: + errors.append((srcname, dstname, str(why))) + try: + shutil.copystat(src, dst) + except OSError, why: + if WindowsError is not None and isinstance(why, WindowsError): + # Copying file access times may fail on Windows + pass + else: + errors.extend((src, dst, str(why))) + if errors: + raise Error, errors + +class Identity: + """PKI Deployment Identity Class""" + + def __init__(self, deployer): + self.master_dict = deployer.master_dict + + def __add_gid(self, pki_group): + pki_gid = None + try: + # Does the specified 'pki_group' exist? + pki_gid = getgrnam(pki_group)[2] + # Yes, group 'pki_group' exists! + config.pki_log.info(log.PKIHELPER_GROUP_ADD_2, pki_group, pki_gid, + extra=config.PKI_INDENTATION_LEVEL_2) + except KeyError as exc: + # No, group 'pki_group' does not exist! + config.pki_log.debug(log.PKIHELPER_GROUP_ADD_KEYERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + try: + # Is the default well-known GID already defined? + group = getgrgid(config.PKI_DEPLOYMENT_DEFAULT_GID)[0] + # Yes, the default well-known GID exists! + config.pki_log.info(log.PKIHELPER_GROUP_ADD_DEFAULT_2, + group, config.PKI_DEPLOYMENT_DEFAULT_GID, + extra=config.PKI_INDENTATION_LEVEL_2) + # Attempt to create 'pki_group' using a random GID. + command = "/usr/sbin/groupadd" + " " + \ + pki_group + " " + \ + "> /dev/null 2>&1" + except KeyError as exc: + # No, the default well-known GID does not exist! + config.pki_log.debug(log.PKIHELPER_GROUP_ADD_GID_KEYERROR_1, + exc, extra=config.PKI_INDENTATION_LEVEL_2) + # Is the specified 'pki_group' the default well-known group? + if pki_group == config.PKI_DEPLOYMENT_DEFAULT_GROUP: + # Yes, attempt to create the default well-known group + # using the default well-known GID. + command = "/usr/sbin/groupadd" + " " + \ + "-g" + " " + \ + str(config.PKI_DEPLOYMENT_DEFAULT_GID) + " " + \ + "-r" + " " + \ + pki_group + " " + \ + "> /dev/null 2>&1" + else: + # No, attempt to create 'pki_group' using a random GID. + command = "/usr/sbin/groupadd" + " " + \ + pki_group + " " + \ + "> /dev/null 2>&1" + # Execute this "groupadd" command. + subprocess.call(command, shell=True) + except subprocess.CalledProcessError as exc: + config.pki_log.error(log.PKI_SUBPROCESS_ERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + raise + return + + def __add_uid(self, pki_user, pki_group): + pki_uid = None + try: + # Does the specified 'pki_user' exist? + pki_uid = getpwnam(pki_user)[2] + # Yes, user 'pki_user' exists! + config.pki_log.info(log.PKIHELPER_USER_ADD_2, pki_user, pki_uid, + extra=config.PKI_INDENTATION_LEVEL_2) + # NOTE: For now, never check validity of specified 'pki_group'! + except KeyError as exc: + # No, user 'pki_user' does not exist! + config.pki_log.debug(log.PKIHELPER_USER_ADD_KEYERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + try: + # Is the default well-known UID already defined? + user = getpwuid(config.PKI_DEPLOYMENT_DEFAULT_UID)[0] + # Yes, the default well-known UID exists! + config.pki_log.info(log.PKIHELPER_USER_ADD_DEFAULT_2, + user, config.PKI_DEPLOYMENT_DEFAULT_UID, + extra=config.PKI_INDENTATION_LEVEL_2) + # Attempt to create 'pki_user' using a random UID. + command = "/usr/sbin/useradd" + " " + \ + "-g" + " " + \ + pki_group + " " + \ + "-d" + " " + \ + config.PKI_DEPLOYMENT_SOURCE_ROOT + " " + \ + "-s" + " " + \ + config.PKI_DEPLOYMENT_DEFAULT_SHELL + " " + \ + "-c" + " " + \ + config.PKI_DEPLOYMENT_DEFAULT_COMMENT + " " + \ + pki_user + " " + \ + "> /dev/null 2>&1" + except KeyError as exc: + # No, the default well-known UID does not exist! + config.pki_log.debug(log.PKIHELPER_USER_ADD_UID_KEYERROR_1, + exc, extra=config.PKI_INDENTATION_LEVEL_2) + # Is the specified 'pki_user' the default well-known user? + if pki_user == config.PKI_DEPLOYMENT_DEFAULT_USER: + # Yes, attempt to create the default well-known user + # using the default well-known UID. + command = "/usr/sbin/useradd" + " " + \ + "-g" + " " + \ + pki_group + " " + \ + "-d" + " " + \ + config.PKI_DEPLOYMENT_SOURCE_ROOT + " " + \ + "-s" + " " + \ + config.PKI_DEPLOYMENT_DEFAULT_SHELL + " " + \ + "-c" + " " + \ + config.PKI_DEPLOYMENT_DEFAULT_COMMENT + " " + \ + "-u" + " " + \ + str(config.PKI_DEPLOYMENT_DEFAULT_UID) + " " + \ + "-r" + " " + \ + pki_user + " " + \ + "> /dev/null 2>&1" + else: + # No, attempt to create 'pki_user' using a random UID. + command = "/usr/sbin/useradd" + " " + \ + "-g" + " " + \ + pki_group + " " + \ + "-d" + " " + \ + config.PKI_DEPLOYMENT_SOURCE_ROOT + " " + \ + "-s" + " " + \ + config.PKI_DEPLOYMENT_DEFAULT_SHELL + " " + \ + "-c" + " " + \ + config.PKI_DEPLOYMENT_DEFAULT_COMMENT + " " + \ + pki_user + " " + \ + "> /dev/null 2>&1" + # Execute this "useradd" command. + subprocess.call(command, shell=True) + except subprocess.CalledProcessError as exc: + config.pki_log.error(log.PKI_SUBPROCESS_ERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + raise + return + + def add_uid_and_gid(self, pki_user, pki_group): + self.__add_gid(pki_group) + self.__add_uid(pki_user, pki_group) + return + + def get_uid(self, critical_failure=True): + try: + pki_uid = self.master_dict['pki_uid'] + except KeyError as exc: + config.pki_log.error(log.PKI_KEYERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise + return pki_uid + + def get_gid(self, critical_failure=True): + try: + pki_gid = self.master_dict['pki_gid'] + except KeyError as exc: + config.pki_log.error(log.PKI_KEYERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise + return pki_gid + + def set_uid(self, name, critical_failure=True): + try: + config.pki_log.debug(log.PKIHELPER_USER_1, name, + extra=config.PKI_INDENTATION_LEVEL_2) + # id -u + pki_uid = getpwnam(name)[2] + self.master_dict['pki_uid'] = pki_uid + config.pki_log.debug(log.PKIHELPER_UID_2, name, pki_uid, + extra=config.PKI_INDENTATION_LEVEL_3) + except KeyError as exc: + config.pki_log.error(log.PKI_KEYERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise + return pki_uid + + def set_gid(self, name, critical_failure=True): + try: + config.pki_log.debug(log.PKIHELPER_GROUP_1, name, + extra=config.PKI_INDENTATION_LEVEL_2) + # id -g + pki_gid = getgrnam(name)[2] + self.master_dict['pki_gid'] = pki_gid + config.pki_log.debug(log.PKIHELPER_GID_2, name, pki_gid, + extra=config.PKI_INDENTATION_LEVEL_3) + except KeyError as exc: + config.pki_log.error(log.PKI_KEYERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise + return pki_gid + +class Namespace: + """PKI Deployment Namespace Class""" + + # Silently verify that the selected 'pki_instance_name' will + # NOT produce any namespace collisions + def __init__(self, deployer): + self.master_dict = deployer.master_dict + + def collision_detection(self): + # Run simple checks for pre-existing namespace collisions + if os.path.exists(self.master_dict['pki_instance_path']): + if os.path.exists(self.master_dict['pki_subsystem_path']): + # Top-Level PKI base path collision + config.pki_log.error( + log.PKIHELPER_NAMESPACE_COLLISION_2, + self.master_dict['pki_instance_name'], + self.master_dict['pki_instance_path'], + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_NAMESPACE_COLLISION_2 % (self.master_dict['pki_instance_name'], + self.master_dict['pki_instance_path'])) + else: + if os.path.exists(self.master_dict['pki_target_tomcat_conf_instance_id']): + # Top-Level "/etc/sysconfig" path collision + config.pki_log.error( + log.PKIHELPER_NAMESPACE_COLLISION_2, + self.master_dict['pki_instance_name'], + self.master_dict['pki_target_tomcat_conf_instance_id'], + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_NAMESPACE_COLLISION_2 % (self.master_dict['pki_instance_name'], + self.master_dict['pki_target_tomcat_conf_instance_id'])) + if os.path.exists(self.master_dict['pki_cgroup_systemd_service']): + # Systemd cgroup path collision + config.pki_log.error( + log.PKIHELPER_NAMESPACE_COLLISION_2, + self.master_dict['pki_instance_name'], + self.master_dict['pki_cgroup_systemd_service_path'], + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_NAMESPACE_COLLISION_2 % (self.master_dict['pki_instance_name'], + self.master_dict['pki_cgroup_systemd_service_path'])) + if os.path.exists(self.master_dict['pki_cgroup_cpu_systemd_service']): + # Systemd cgroup CPU path collision + config.pki_log.error( + log.PKIHELPER_NAMESPACE_COLLISION_2, + self.master_dict['pki_instance_name'], + self.master_dict['pki_cgroup_cpu_systemd_service_path'], + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_NAMESPACE_COLLISION_2 % (self.master_dict['pki_instance_name'], + self.master_dict['pki_cgroup_cpu_systemd_service_path'])) + if os.path.exists(self.master_dict['pki_instance_log_path']) and\ + os.path.exists(self.master_dict['pki_subsystem_log_path']): + # Top-Level PKI log path collision + config.pki_log.error( + log.PKIHELPER_NAMESPACE_COLLISION_2, + self.master_dict['pki_instance_name'], + self.master_dict['pki_instance_log_path'], + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_NAMESPACE_COLLISION_2 % (self.master_dict['pki_instance_name'], + self.master_dict['pki_instance_log_path'])) + if os.path.exists(self.master_dict['pki_instance_configuration_path']) and\ + os.path.exists(self.master_dict['pki_subsystem_configuration_path']): + # Top-Level PKI configuration path collision + config.pki_log.error( + log.PKIHELPER_NAMESPACE_COLLISION_2, + self.master_dict['pki_instance_name'], + self.master_dict['pki_instance_configuration_path'], + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_NAMESPACE_COLLISION_2 % (self.master_dict['pki_instance_name'], + self.master_dict['pki_instance_configuration_path'])) + if os.path.exists(self.master_dict['pki_instance_registry_path']) and\ + os.path.exists(self.master_dict['pki_subsystem_registry_path']): + # Top-Level PKI registry path collision + config.pki_log.error( + log.PKIHELPER_NAMESPACE_COLLISION_2, + self.master_dict['pki_instance_name'], + self.master_dict['pki_instance_registry_path'], + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_NAMESPACE_COLLISION_2 % (self.master_dict['pki_instance_name'], + self.master_dict['pki_instance_registry_path'])) + # Run simple checks for reserved name namespace collisions + if self.master_dict['pki_instance_name'] in config.PKI_BASE_RESERVED_NAMES: + # Top-Level PKI base path reserved name collision + config.pki_log.error( + log.PKIHELPER_NAMESPACE_RESERVED_NAME_2, + self.master_dict['pki_instance_name'], + self.master_dict['pki_instance_path'], + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_NAMESPACE_RESERVED_NAME_2 % (self.master_dict['pki_instance_name'], + self.master_dict['pki_instance_path'])) + # No need to check for reserved name under Top-Level PKI log path + if self.master_dict['pki_instance_name'] in config.PKI_CONFIGURATION_RESERVED_NAMES: + # Top-Level PKI configuration path reserved name collision + config.pki_log.error( + log.PKIHELPER_NAMESPACE_RESERVED_NAME_2, + self.master_dict['pki_instance_name'], + self.master_dict['pki_instance_configuration_path'], + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_NAMESPACE_RESERVED_NAME_2 % (self.master_dict['pki_instance_name'], + self.master_dict['pki_instance_configuration_path'])) + if self.master_dict['pki_subsystem'] in config.PKI_APACHE_SUBSYSTEMS: + # Top-Level Apache PKI registry path reserved name collision + if self.master_dict['pki_instance_name'] in\ + config.PKI_APACHE_REGISTRY_RESERVED_NAMES: + config.pki_log.error( + log.PKIHELPER_NAMESPACE_RESERVED_NAME_2, + self.master_dict['pki_instance_name'], + self.master_dict['pki_instance_registry_path'], + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_NAMESPACE_RESERVED_NAME_2 % (self.master_dict['pki_instance_name'], + self.master_dict['pki_instance_registry_path'])) + elif self.master_dict['pki_subsystem'] in config.PKI_TOMCAT_SUBSYSTEMS: + # Top-Level Tomcat PKI registry path reserved name collision + if self.master_dict['pki_instance_name'] in\ + config.PKI_TOMCAT_REGISTRY_RESERVED_NAMES: + config.pki_log.error( + log.PKIHELPER_NAMESPACE_RESERVED_NAME_2, + self.master_dict['pki_instance_name'], + self.master_dict['pki_instance_registry_path'], + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_NAMESPACE_RESERVED_NAME_2 % (self.master_dict['pki_instance_name'], + self.master_dict['pki_instance_registry_path'])) + + +class ConfigurationFile: + """PKI Deployment Configuration File Class""" + + def __init__(self, deployer): + self.master_dict = deployer.master_dict + + def log_configuration_url(self): + # NOTE: This is the one and only parameter containing a sensitive + # parameter that may be stored in a log file. + config.pki_log.info(log.PKI_CONFIGURATION_WIZARD_URL_1, + self.master_dict['pki_configuration_url'], + extra=config.PKI_INDENTATION_LEVEL_2) + config.pki_log.info(log.PKI_CONFIGURATION_WIZARD_RESTART_1, + self.master_dict['pki_registry_initscript_command'], + extra=config.PKI_INDENTATION_LEVEL_2) + + def display_configuration_url(self): + # NOTE: This is the one and only parameter containing a sensitive + # parameter that may be displayed to the screen. + print log.PKI_CONFIGURATION_URL_1 % self.master_dict['pki_configuration_url'] + print + print log.PKI_CONFIGURATION_RESTART_1 % \ + self.master_dict['pki_registry_initscript_command'] + print + + def verify_sensitive_data(self): + # Silently verify the existence of 'sensitive' data + if self.master_dict['pki_subsystem'] in config.PKI_TOMCAT_SUBSYSTEMS: + # Verify existence of Directory Server Password (ALWAYS) + if not self.master_dict.has_key('pki_ds_password') or\ + not len(self.master_dict['pki_ds_password']): + config.pki_log.error( + log.PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2, + "pki_ds_password", + self.master_dict['pki_user_deployment_cfg'], + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2 % ("pki_ds_password", + self.master_dict['pki_user_deployment_cfg'])) + # Verify existence of Admin Password (except for Clones) + if not config.str2bool(self.master_dict['pki_clone']): + if not self.master_dict.has_key('pki_admin_password') or\ + not len(self.master_dict['pki_admin_password']): + config.pki_log.error( + log.PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2, + "pki_admin_password", + self.master_dict['pki_user_deployment_cfg'], + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2 % ("pki_admin_password", + self.master_dict['pki_user_deployment_cfg'])) + # If required, verify existence of Backup Password + if config.str2bool(self.master_dict['pki_backup_keys']): + if not self.master_dict.has_key('pki_backup_password') or\ + not len(self.master_dict['pki_backup_password']): + config.pki_log.error( + log.PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2, + "pki_backup_password", + self.master_dict['pki_user_deployment_cfg'], + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2 % ("pki_backup_password", + self.master_dict['pki_user_deployment_cfg'])) + # Verify existence of Client Pin for NSS client security databases + if not self.master_dict.has_key('pki_client_database_password') or\ + not len(self.master_dict['pki_client_database_password']): + config.pki_log.error( + log.PKIHELPER_UNDEFINED_CLIENT_DATABASE_PASSWORD_2, + "pki_client_database_password", + self.master_dict['pki_user_deployment_cfg'], + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_UNDEFINED_CLIENT_DATABASE_PASSWORD_2 % ("pki_client_database_password", + self.master_dict['pki_user_deployment_cfg'])) + # Verify existence of Client PKCS #12 Password for Admin Cert + if not self.master_dict.has_key('pki_client_pkcs12_password') or\ + not len(self.master_dict['pki_client_pkcs12_password']): + config.pki_log.error( + log.PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2, + "pki_client_pkcs12_password", + self.master_dict['pki_user_deployment_cfg'], + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2 % ("pki_client_pkcs12_password", + self.master_dict['pki_user_deployment_cfg'])) + # Verify existence of PKCS #12 Password (ONLY for Clones) + if config.str2bool(self.master_dict['pki_clone']): + if not self.master_dict.has_key('pki_clone_pkcs12_password') or\ + not len(self.master_dict['pki_clone_pkcs12_password']): + config.pki_log.error( + log.PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2, + "pki_clone_pkcs12_password", + self.master_dict['pki_user_deployment_cfg'], + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2 % ("pki_clone_pkcs12_password", + self.master_dict['pki_user_deployment_cfg'])) + # Verify existence of Security Domain Password File + # (ONLY for Clones, KRA, OCSP, TKS, TPS, or Subordinate CA) + if config.str2bool(self.master_dict['pki_clone']) or\ + not self.master_dict['pki_subsystem'] == "CA" or\ + config.str2bool(self.master_dict['pki_subordinate']): + if not self.master_dict.has_key('pki_security_domain_password') or\ + not len(self.master_dict['pki_security_domain_password']): + config.pki_log.error( + log.PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2, + "pki_security_domain_password", + self.master_dict['pki_user_deployment_cfg'], + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2 % ("pki_security_domain_password", + self.master_dict['pki_user_deployment_cfg'])) + # If required, verify existence of Token Password + if not self.master_dict['pki_token_name'] == "internal": + if not self.master_dict.has_key('pki_token_password') or\ + not len(self.master_dict['pki_token_password']): + config.pki_log.error( + log.PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2, + "pki_token_password", + self.master_dict['pki_user_deployment_cfg'], + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2 % ("pki_token_password", + self.master_dict['pki_user_deployment_cfg'])) + return + + def verify_mutually_exclusive_data(self): + # Silently verify the existence of 'mutually exclusive' data + if self.master_dict['pki_subsystem'] in config.PKI_TOMCAT_SUBSYSTEMS: + if self.master_dict['pki_subsystem'] == "CA": + if config.str2bool(self.master_dict['pki_clone']) and\ + config.str2bool(self.master_dict['pki_external']) and\ + config.str2bool(self.master_dict['pki_subordinate']): + config.pki_log.error( + log.PKIHELPER_MUTUALLY_EXCLUSIVE_CLONE_EXTERNAL_SUB_CA, + self.master_dict['pki_user_deployment_cfg'], + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_MUTUALLY_EXCLUSIVE_CLONE_EXTERNAL_SUB_CA % self.master_dict['pki_user_deployment_cfg']) + elif config.str2bool(self.master_dict['pki_clone']) and\ + config.str2bool(self.master_dict['pki_external']): + config.pki_log.error( + log.PKIHELPER_MUTUALLY_EXCLUSIVE_CLONE_EXTERNAL_CA, + self.master_dict['pki_user_deployment_cfg'], + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_MUTUALLY_EXCLUSIVE_CLONE_EXTERNAL_CA % self.master_dict['pki_user_deployment_cfg']) + elif config.str2bool(self.master_dict['pki_clone']) and\ + config.str2bool(self.master_dict['pki_subordinate']): + config.pki_log.error( + log.PKIHELPER_MUTUALLY_EXCLUSIVE_CLONE_SUB_CA, + self.master_dict['pki_user_deployment_cfg'], + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_MUTUALLY_EXCLUSIVE_CLONE_SUB_CA % self.master_dict['pki_user_deployment_cfg']) + elif config.str2bool(self.master_dict['pki_external']) and\ + config.str2bool(self.master_dict['pki_subordinate']): + config.pki_log.error( + log.PKIHELPER_MUTUALLY_EXCLUSIVE_EXTERNAL_SUB_CA, + self.master_dict['pki_user_deployment_cfg'], + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_MUTUALLY_EXCLUSIVE_EXTERNAL_SUB_CA % self.master_dict['pki_user_deployment_cfg']) + + def verify_predefined_configuration_file_data(self): + # Silently verify the existence of any required 'predefined' data + # + # FUTURE: As much as is possible, alter this routine to verify + # ALL name/value pairs for the requested configuration + # scenario. This should include checking for the + # "existence" of ALL required "name" parameters, as well as + # the "existence", "type" (e. g. - string, boolean, number, + # etc.), and "correctness" (e. g. - file, directory, boolean + # 'True' or 'False', etc.) of ALL required "value" parameters. + # + if self.master_dict['pki_subsystem'] in config.PKI_TOMCAT_SUBSYSTEMS: + if config.str2bool(self.master_dict['pki_clone']): + # Verify existence of clone parameters + if not self.master_dict.has_key('pki_ds_base_dn') or\ + not len(self.master_dict['pki_ds_base_dn']): + config.pki_log.error( + log.PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2, + "pki_ds_base_dn", + self.master_dict['pki_user_deployment_cfg'], + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2 % ("pki_ds_base_dn", + self.master_dict['pki_user_deployment_cfg'])) + if not self.master_dict.has_key('pki_ds_ldap_port') or\ + not len(self.master_dict['pki_ds_ldap_port']): + # FUTURE: Check for unused port value + # (e. g. - must be different from master if the + # master is located on the same host) + config.pki_log.error( + log.PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2, + "pki_ds_ldap_port", + self.master_dict['pki_user_deployment_cfg'], + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2 % ("pki_ds_ldap_port", + self.master_dict['pki_user_deployment_cfg'])) + if not self.master_dict.has_key('pki_ds_ldaps_port') or\ + not len(self.master_dict['pki_ds_ldaps_port']): + # FUTURE: Check for unused port value + # (e. g. - must be different from master if the + # master is located on the same host) + config.pki_log.error( + log.PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2, + "pki_ds_ldaps_port", + self.master_dict['pki_user_deployment_cfg'], + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2 % ("pki_ds_ldaps_port", + self.master_dict['pki_user_deployment_cfg'])) + # NOTE: Although this will be checked prior to getting to + # this method, this clone's 'pki_instance_name' MUST + # be different from the master's 'pki_instance_name' + # IF AND ONLY IF the master and clone are located on + # the same host! + if not self.master_dict.has_key('pki_ajp_port') or\ + not len(self.master_dict['pki_ajp_port']): + # FUTURE: Check for unused port value + # (e. g. - must be different from master if the + # master is located on the same host) + config.pki_log.error( + log.PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2, + "pki_ajp_port", + self.master_dict['pki_user_deployment_cfg'], + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2 % ("pki_ajp_port", + self.master_dict['pki_user_deployment_cfg'])) + if not self.master_dict.has_key('pki_http_port') or\ + not len(self.master_dict['pki_http_port']): + # FUTURE: Check for unused port value + # (e. g. - must be different from master if the + # master is located on the same host) + config.pki_log.error( + log.PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2, + "pki_http_port", + self.master_dict['pki_user_deployment_cfg'], + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2 % ("pki_http_port", + self.master_dict['pki_user_deployment_cfg'])) + if not self.master_dict.has_key('pki_https_port') or\ + not len(self.master_dict['pki_https_port']): + # FUTURE: Check for unused port value + # (e. g. - must be different from master if the + # master is located on the same host) + config.pki_log.error( + log.PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2, + "pki_https_port", + self.master_dict['pki_user_deployment_cfg'], + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2 % ("pki_https_port", + self.master_dict['pki_user_deployment_cfg'])) + if not self.master_dict.has_key('pki_tomcat_server_port') or\ + not len(self.master_dict['pki_tomcat_server_port']): + # FUTURE: Check for unused port value + # (e. g. - must be different from master if the + # master is located on the same host) + config.pki_log.error( + log.PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2, + "pki_tomcat_server_port", + self.master_dict['pki_user_deployment_cfg'], + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2 % ("pki_tomcat_server_port", + self.master_dict['pki_user_deployment_cfg'])) + if not self.master_dict.has_key('pki_clone_pkcs12_path') or\ + not len(self.master_dict['pki_clone_pkcs12_path']): + config.pki_log.error( + log.PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2, + "pki_clone_pkcs12_path", + self.master_dict['pki_user_deployment_cfg'], + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2 % ("pki_clone_pkcs12_path", + self.master_dict['pki_user_deployment_cfg'])) + elif not os.path.isfile(self.master_dict['pki_clone_pkcs12_path']): + config.pki_log.error( + log.PKI_FILE_ALREADY_EXISTS_NOT_A_FILE_1, + self.master_dict['pki_clone_pkcs12_path'], + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKI_FILE_ALREADY_EXISTS_NOT_A_FILE_1 % "pki_clone_pkcs12_path") + if not self.master_dict.has_key('pki_clone_replication_security') or\ + not len(self.master_dict['pki_clone_replication_security']): + config.pki_log.error( + log.PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2, + "pki_clone_replication_security", + self.master_dict['pki_user_deployment_cfg'], + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2 % ("pki_clone_replication_security", + self.master_dict['pki_user_deployment_cfg'])) + if not self.master_dict.has_key('pki_clone_uri') or\ + not len(self.master_dict['pki_clone_uri']): + config.pki_log.error( + log.PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2, + "pki_clone_uri", + self.master_dict['pki_user_deployment_cfg'], + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2 % ("pki_clone_uri", + self.master_dict['pki_user_deployment_cfg'])) + elif self.master_dict['pki_subsystem'] == "CA" and\ + config.str2bool(self.master_dict['pki_external']): + if not self.master_dict.has_key('pki_external_step_two') or\ + not len(self.master_dict['pki_external_step_two']): + config.pki_log.error( + log.PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2, + "pki_external_step_two", + self.master_dict['pki_user_deployment_cfg'], + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2 % ("pki_extrenal_step_two", + self.master_dict['pki_user_deployment_cfg'])) + if not config.str2bool(self.master_dict['pki_external_step_two']): + # External CA (Step 1) + if not self.master_dict.has_key('pki_external_csr_path') or\ + not len(self.master_dict['pki_external_csr_path']): + config.pki_log.error( + log.PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2, + "pki_external_csr_path", + self.master_dict['pki_user_deployment_cfg'], + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2 % ("pki_extrenal_csr_path", + self.master_dict['pki_user_deployment_cfg'])) + elif os.path.exists(self.master_dict['pki_external_csr_path']) and\ + not os.path.isfile(self.master_dict['pki_external_csr_path']): + config.pki_log.error( + log.PKI_FILE_ALREADY_EXISTS_NOT_A_FILE_1, + self.master_dict['pki_external_csr_path'], + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2 % "pki_extrenal_csr_path") + else: + # External CA (Step 2) + if not self.master_dict.has_key('pki_external_ca_cert_chain_path') or\ + not len(self.master_dict['pki_external_ca_cert_chain_path']): + config.pki_log.error( + log.PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2, + "pki_external_ca_cert_chain_path", + self.master_dict['pki_user_deployment_cfg'], + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2 % ("pki_extrenal_ca_cert_chain_path", + self.master_dict['pki_user_deployment_cfg'])) + elif os.path.exists( + self.master_dict['pki_external_ca_cert_chain_path']) and\ + not os.path.isfile( + self.master_dict['pki_external_ca_cert_chain_path']): + config.pki_log.error( + log.PKI_FILE_ALREADY_EXISTS_NOT_A_FILE_1, + self.master_dict['pki_external_ca_cert_chain_path'], + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2 % "pki_extrenal_ca_cert_chain_path") + if not self.master_dict.has_key('pki_external_ca_cert_path') or\ + not len(self.master_dict['pki_external_ca_cert_path']): + config.pki_log.error( + log.PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2, + "pki_external_ca_cert_path", + self.master_dict['pki_user_deployment_cfg'], + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2 % ("pki_extrenal_ca_cert_path", + self.master_dict['pki_user_deployment_cfg'])) + elif os.path.exists(self.master_dict['pki_external_ca_cert_path']) and\ + not os.path.isfile( + self.master_dict['pki_external_ca_cert_path']): + config.pki_log.error( + log.PKI_FILE_ALREADY_EXISTS_NOT_A_FILE_1, + self.master_dict['pki_external_ca_cert_path'], + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2 % "pki_extrenal_ca_cert_path") + return + + def populate_non_default_ports(self): + if (self.master_dict['pki_http_port'] != + str(config.PKI_DEPLOYMENT_DEFAULT_TOMCAT_HTTP_PORT)): + ports.append(self.master_dict['pki_http_port']) + if (self.master_dict['pki_https_port'] != + str(config.PKI_DEPLOYMENT_DEFAULT_TOMCAT_HTTPS_PORT)): + ports.append(self.master_dict['pki_https_port']) + if (self.master_dict['pki_tomcat_server_port'] != + str(config.PKI_DEPLOYMENT_DEFAULT_TOMCAT_SERVER_PORT)): + ports.append(self.master_dict['pki_tomcat_server_port']) + if (self.master_dict['pki_ajp_port'] != + str(config.PKI_DEPLOYMENT_DEFAULT_TOMCAT_AJP_PORT)): + ports.append(self.master_dict['pki_ajp_port']) + return + + def verify_selinux_ports(self): + # Determine which ports still need to be labelled, and if any are + # incorrectly labelled + if len(ports) == 0: + return + + if not bool(selinux.is_selinux_enabled()): + config.pki_log.error( + log.PKIHELPER_SELINUX_DISABLED, + extra=config.PKI_INDENTATION_LEVEL_2) + return + + portrecs = seobject.portRecords().get_all() + portlist = ports[:] + for port in portlist: + context = "" + for i in portrecs: + if (portrecs[i][0] == "unreserved_port_t" or + portrecs[i][0] == "reserved_port_t" or + i[2] != "tcp"): + continue + if i[0] <= int(port) and int(port) <= i[1]: + context = portrecs[i][0] + break + if context == "": + # port has no current context + # leave it in list of ports to set + continue + elif context == config.PKI_PORT_SELINUX_CONTEXT: + # port is already set correctly + # remove from list of ports to set + ports.remove(port) + else: + config.pki_log.error( + log.PKIHELPER_INVALID_SELINUX_CONTEXT_FOR_PORT, + port, context, + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_INVALID_SELINUX_CONTEXT_FOR_PORT % (port, context)) + return + + def verify_command_matches_configuration_file(self): + # Silently verify that the command-line parameters match the values + # that are present in the corresponding configuration file + if self.master_dict['pki_deployment_executable'] == 'pkidestroy': + if self.master_dict['pki_deployed_instance_name'] != \ + self.master_dict['pki_instance_name']: + config.pki_log.error( + log.PKIHELPER_COMMAND_LINE_PARAMETER_MISMATCH_2, + self.master_dict['pki_deployed_instance_name'], + self.master_dict['pki_instance_name'], + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_UNDEFINED_CONFIGURATION_FILE_ENTRY_2 % (self.master_dict['pki_deployed_instance_name'], + self.master_dict['pki_instance_name'])) + return + +# PKI Deployment XML File Class +# class xml_file: +# def remove_filter_section_from_web_xml(self, +# web_xml_source, +# web_xml_target): +# config.pki_log.info(log.PKIHELPER_REMOVE_FILTER_SECTION_1, +# self.master_dict['pki_target_subsystem_web_xml'], +# extra=config.PKI_INDENTATION_LEVEL_2) +# begin_filters_section = False +# begin_servlet_section = False +# FILE = open(web_xml_target, "w") +# for line in fileinput.FileInput(web_xml_source): +# if not begin_filters_section: +# # Read and write lines until first "" tag +# if line.count("") >= 1: +# # Mark filters section +# begin_filters_section = True +# else: +# FILE.write(line) +# elif not begin_servlet_section: +# # Skip lines until first "" tag +# if line.count("") >= 1: +# # Mark servlets section and write out the opening tag +# begin_servlet_section = True +# FILE.write(line) +# else: +# continue +# else: +# # Read and write lines all lines after "" tag +# FILE.write(line) +# FILE.close() + +class Instance: + """PKI Deployment Instance Class""" + + def __init__(self, deployer): + self.master_dict = deployer.master_dict + + def apache_instance_subsystems(self): + rv = 0 + try: + # count number of PKI subsystems present + # within the specified Apache instance + for subsystem in config.PKI_APACHE_SUBSYSTEMS: + path = self.master_dict['pki_instance_path'] + "/" + subsystem.lower() + if os.path.exists(path) and os.path.isdir(path): + rv = rv + 1 + config.pki_log.debug(log.PKIHELPER_APACHE_INSTANCE_SUBSYSTEMS_2, + self.master_dict['pki_instance_path'], + rv, extra=config.PKI_INDENTATION_LEVEL_2) + except OSError as exc: + config.pki_log.error(log.PKI_OSERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + raise + return rv + + def apache_instances(self): + rv = 0 + try: + # Since ALL directories under the top-level PKI 'apache' registry + # directory SHOULD represent PKI Apache instances, and there + # shouldn't be any stray files or symbolic links at this level, + # simply count the number of PKI 'apache' instances (directories) + # present within the PKI 'apache' registry directory + for instance in\ + os.listdir(self.master_dict['pki_instance_type_registry_path']): + if os.path.isdir( + os.path.join(self.master_dict['pki_instance_type_registry_path'], + instance)) and not\ + os.path.islink( + os.path.join(self.master_dict['pki_instance_type_registry_path'], + instance)): + rv = rv + 1 + config.pki_log.debug(log.PKIHELPER_APACHE_INSTANCES_2, + self.master_dict['pki_instance_type_registry_path'], + rv, + extra=config.PKI_INDENTATION_LEVEL_2) + except OSError as exc: + config.pki_log.error(log.PKI_OSERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + raise + return rv + + def pki_instance_subsystems(self): + rv = 0 + try: + # Since ALL directories within the top-level PKI infrastructure + # SHOULD represent PKI instances, look for all possible + # PKI instances within the top-level PKI infrastructure + for instance in os.listdir(self.master_dict['pki_path']): + if os.path.isdir(os.path.join(self.master_dict['pki_path'], instance))\ + and not\ + os.path.islink(os.path.join(self.master_dict['pki_path'], instance)): + instance_dir = os.path.join(self.master_dict['pki_path'], instance) + # Since ANY directory within this PKI instance COULD + # be a PKI subsystem, look for all possible + # PKI subsystems within this PKI instance + for name in os.listdir(instance_dir): + if os.path.isdir(os.path.join(instance_dir, name)) and\ + not os.path.islink(os.path.join(instance_dir, name)): + if name.upper() in config.PKI_SUBSYSTEMS: + rv = rv + 1 + config.pki_log.debug(log.PKIHELPER_PKI_INSTANCE_SUBSYSTEMS_2, + self.master_dict['pki_instance_path'], rv, + extra=config.PKI_INDENTATION_LEVEL_2) + except OSError as exc: + config.pki_log.error(log.PKI_OSERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + raise + return rv + + def tomcat_instance_subsystems(self): + # Return list of PKI subsystems in the specified tomcat instance + rv = [] + try: + for subsystem in config.PKI_TOMCAT_SUBSYSTEMS: + path = self.master_dict['pki_instance_path'] + "/" + subsystem.lower() + if os.path.exists(path) and os.path.isdir(path): + rv.append(subsystem) + except OSError as exc: + config.pki_log.error(log.PKI_OSERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + raise + return rv + + def tomcat_instances(self): + rv = 0 + try: + # Since ALL directories under the top-level PKI 'tomcat' registry + # directory SHOULD represent PKI Tomcat instances, and there + # shouldn't be any stray files or symbolic links at this level, + # simply count the number of PKI 'tomcat' instances (directories) + # present within the PKI 'tomcat' registry directory + for instance in\ + os.listdir(self.master_dict['pki_instance_type_registry_path']): + if os.path.isdir( + os.path.join(self.master_dict['pki_instance_type_registry_path'], + instance)) and not\ + os.path.islink( + os.path.join(self.master_dict['pki_instance_type_registry_path'], + instance)): + rv = rv + 1 + config.pki_log.debug(log.PKIHELPER_TOMCAT_INSTANCES_2, + self.master_dict['pki_instance_type_registry_path'], + rv, + extra=config.PKI_INDENTATION_LEVEL_2) + except OSError as exc: + config.pki_log.error(log.PKI_OSERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + raise + return rv + + def verify_subsystem_exists(self): + try: + if not os.path.exists(self.master_dict['pki_subsystem_path']): + config.pki_log.error(log.PKI_SUBSYSTEM_DOES_NOT_EXIST_2, + self.master_dict['pki_subsystem'], + self.master_dict['pki_instance_name'], + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKI_SUBSYSTEM_DOES_NOT_EXIST_2 % (self.master_dict['pki_subsystem'], + self.master_dict['pki_instance_name'])) + except OSError as exc: + config.pki_log.error(log.PKI_OSERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + raise + + def verify_subsystem_does_not_exist(self): + try: + if os.path.exists(self.master_dict['pki_subsystem_path']): + config.pki_log.error(log.PKI_SUBSYSTEM_ALREADY_EXISTS_2, + self.master_dict['pki_subsystem'], + self.master_dict['pki_instance_name'], + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKI_SUBSYSTEM_DOES_NOT_EXIST_2 % (self.master_dict['pki_subsystem'], + self.master_dict['pki_instance_name'])) + except OSError as exc: + config.pki_log.error(log.PKI_OSERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + raise + + def get_instance_status(self): + connection = pki.client.PKIConnection( + protocol='https', + hostname=self.master_dict['pki_hostname'], + port=self.master_dict['pki_https_port'], + subsystem=self.master_dict['pki_subsystem_type'], + accept='application/xml') + + try: + client = pki.system.SystemStatusClient(connection) + response = client.getStatus() + config.pki_log.debug(response, + extra=config.PKI_INDENTATION_LEVEL_3) + + root = ET.fromstring(response) + status = root.findtext("Status") + return status + except requests.exceptions.ConnectionError: + config.pki_log.debug("No connection", + extra=config.PKI_INDENTATION_LEVEL_3) + return None + + def wait_for_startup(self, timeout): + start_time = datetime.today() + status = None + while status != "running": + status = self.get_instance_status() + time.sleep(1) + stop_time = datetime.today() + if (stop_time - start_time).total_seconds() >= timeout: + break + return status + +class Directory: + """PKI Deployment Directory Class""" + + def __init__(self, deployer): + self.master_dict = deployer.master_dict + self.identity = deployer.identity + self.manifest_db = deployer.manifest_db + + def create(self, name, uid=None, gid=None, + perms=config.PKI_DEPLOYMENT_DEFAULT_DIR_PERMISSIONS, + acls=None, critical_failure=True): + try: + if not os.path.exists(name): + # mkdir -p + config.pki_log.info(log.PKIHELPER_MKDIR_1, name, + extra=config.PKI_INDENTATION_LEVEL_2) + os.makedirs(name) + # chmod + config.pki_log.debug(log.PKIHELPER_CHMOD_2, perms, name, + extra=config.PKI_INDENTATION_LEVEL_3) + os.chmod(name, perms) + # chown : + if uid == None: + uid = self.identity.get_uid() + if gid == None: + gid = self.identity.get_gid() + config.pki_log.debug(log.PKIHELPER_CHOWN_3, + uid, gid, name, + extra=config.PKI_INDENTATION_LEVEL_3) + os.chown(name, uid, gid) + # Store record in installation manifest + record = manifest.Record() + record.name = name + record.type = manifest.RECORD_TYPE_DIRECTORY + record.user = self.master_dict['pki_user'] + record.group = self.master_dict['pki_group'] + record.uid = uid + record.gid = gid + record.permissions = perms + record.acls = acls + self.manifest_db.append(record) + elif not os.path.isdir(name): + config.pki_log.error( + log.PKI_DIRECTORY_ALREADY_EXISTS_NOT_A_DIRECTORY_1, name, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise Exception(log.PKI_DIRECTORY_ALREADY_EXISTS_NOT_A_DIRECTORY_1 % name) + except OSError as exc: + if exc.errno == errno.EEXIST: + pass + else: + config.pki_log.error(log.PKI_OSERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise + return + + def modify(self, name, uid=None, gid=None, + perms=config.PKI_DEPLOYMENT_DEFAULT_DIR_PERMISSIONS, + acls=None, silent=False, critical_failure=True): + try: + if os.path.exists(name): + if not os.path.isdir(name): + config.pki_log.error( + log.PKI_DIRECTORY_ALREADY_EXISTS_NOT_A_DIRECTORY_1, + name, extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise Exception(log.PKI_DIRECTORY_ALREADY_EXISTS_NOT_A_DIRECTORY_1 % name) + # Always re-process each directory whether it needs it or not + if not silent: + config.pki_log.info(log.PKIHELPER_MODIFY_DIR_1, name, + extra=config.PKI_INDENTATION_LEVEL_2) + # chmod + if not silent: + config.pki_log.debug(log.PKIHELPER_CHMOD_2, perms, name, + extra=config.PKI_INDENTATION_LEVEL_3) + os.chmod(name, perms) + # chown : + if uid == None: + uid = self.identity.get_uid() + if gid == None: + gid = self.identity.get_gid() + if not silent: + config.pki_log.debug(log.PKIHELPER_CHOWN_3, + uid, gid, name, + extra=config.PKI_INDENTATION_LEVEL_3) + os.chown(name, uid, gid) + # Store record in installation manifest + if not silent: + record = manifest.Record() + record.name = name + record.type = manifest.RECORD_TYPE_DIRECTORY + record.user = self.master_dict['pki_user'] + record.group = self.master_dict['pki_group'] + record.uid = uid + record.gid = gid + record.permissions = perms + record.acls = acls + self.manifest_db.append(record) + else: + config.pki_log.error( + log.PKI_DIRECTORY_MISSING_OR_NOT_A_DIRECTORY_1, name, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise Exception(log.PKI_DIRECTORY_MISSING_OR_NOT_A_DIRECTORY_1 % name) + except OSError as exc: + config.pki_log.error(log.PKI_OSERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise + return + + def delete(self, name, recursive_flag=True, critical_failure=True): + try: + if not os.path.exists(name) or not os.path.isdir(name): + # Simply issue a warning and continue + config.pki_log.warning( + log.PKI_DIRECTORY_MISSING_OR_NOT_A_DIRECTORY_1, name, + extra=config.PKI_INDENTATION_LEVEL_2) + else: + if recursive_flag == True: + # rm -rf + config.pki_log.info(log.PKIHELPER_RM_RF_1, name, + extra=config.PKI_INDENTATION_LEVEL_2) + shutil.rmtree(name) + else: + # rmdir + config.pki_log.info(log.PKIHELPER_RMDIR_1, name, + extra=config.PKI_INDENTATION_LEVEL_2) + os.rmdir(name) + except OSError as exc: + config.pki_log.error(log.PKI_OSERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise + return + + def exists(self, name): + try: + if not os.path.exists(name) or not os.path.isdir(name): + return False + else: + return True + except OSError as exc: + config.pki_log.error(log.PKI_OSERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + raise + + def is_empty(self, name): + try: + if not os.listdir(name): + config.pki_log.debug(log.PKIHELPER_DIRECTORY_IS_EMPTY_1, + name, extra=config.PKI_INDENTATION_LEVEL_2) + return True + else: + config.pki_log.debug(log.PKIHELPER_DIRECTORY_IS_NOT_EMPTY_1, + name, extra=config.PKI_INDENTATION_LEVEL_2) + return False + except OSError as exc: + config.pki_log.error(log.PKI_OSERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + raise + + def set_mode(self, name, uid=None, gid=None, + dir_perms=config.PKI_DEPLOYMENT_DEFAULT_DIR_PERMISSIONS, + file_perms=config.PKI_DEPLOYMENT_DEFAULT_FILE_PERMISSIONS, + symlink_perms=\ + config.PKI_DEPLOYMENT_DEFAULT_SYMLINK_PERMISSIONS, + dir_acls=None, file_acls=None, symlink_acls=None, + recursive_flag=True, critical_failure=True): + try: + if not os.path.exists(name) or not os.path.isdir(name): + config.pki_log.error( + log.PKI_DIRECTORY_MISSING_OR_NOT_A_DIRECTORY_1, name, + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKI_DIRECTORY_MISSING_OR_NOT_A_DIRECTORY_1 % name) + else: + config.pki_log.info( + log.PKIHELPER_SET_MODE_1, name, + extra=config.PKI_INDENTATION_LEVEL_2) + if uid == None: + uid = self.identity.get_uid() + if gid == None: + gid = self.identity.get_gid() + if recursive_flag == True: + for root, dirs, files in os.walk(name): + for name in files: + entity = os.path.join(root, name) + if not os.path.islink(entity): + temp_file = entity + config.pki_log.debug( + log.PKIHELPER_IS_A_FILE_1, temp_file, + extra=config.PKI_INDENTATION_LEVEL_3) + # chmod + config.pki_log.debug(log.PKIHELPER_CHMOD_2, + file_perms, temp_file, + extra=config.PKI_INDENTATION_LEVEL_3) + os.chmod(temp_file, file_perms) + # chown : + config.pki_log.debug(log.PKIHELPER_CHOWN_3, + uid, gid, temp_file, + extra=config.PKI_INDENTATION_LEVEL_3) + os.chown(temp_file, uid, gid) + # Store record in installation manifest + record = manifest.Record() + record.name = name + record.type = manifest.RECORD_TYPE_FILE + record.user = self.master_dict['pki_user'] + record.group = self.master_dict['pki_group'] + record.uid = uid + record.gid = gid + record.permissions = file_perms + record.acls = file_acls + self.manifest_db.append(record) + else: + symlink = entity + config.pki_log.debug( + log.PKIHELPER_IS_A_SYMLINK_1, symlink, + extra=config.PKI_INDENTATION_LEVEL_3) + # REMINDER: Due to POSIX compliance, 'lchmod' + # is NEVER implemented on Linux + # systems since 'chmod' CANNOT be + # run directly against symbolic + # links! + # chown -h : + config.pki_log.debug(log.PKIHELPER_CHOWN_H_3, + uid, gid, symlink, + extra=config.PKI_INDENTATION_LEVEL_3) + os.lchown(symlink, uid, gid) + # Store record in installation manifest + record = manifest.Record() + record.name = name + record.type = manifest.RECORD_TYPE_SYMLINK + record.user = self.master_dict['pki_user'] + record.group = self.master_dict['pki_group'] + record.uid = uid + record.gid = gid + record.permissions = symlink_perms + record.acls = symlink_acls + self.manifest_db.append(record) + for name in dirs: + temp_dir = os.path.join(root, name) + config.pki_log.debug( + log.PKIHELPER_IS_A_DIRECTORY_1, temp_dir, + extra=config.PKI_INDENTATION_LEVEL_3) + # chmod + config.pki_log.debug(log.PKIHELPER_CHMOD_2, + dir_perms, temp_dir, + extra=config.PKI_INDENTATION_LEVEL_3) + os.chmod(temp_dir, dir_perms) + # chown : + config.pki_log.debug(log.PKIHELPER_CHOWN_3, + uid, gid, temp_dir, + extra=config.PKI_INDENTATION_LEVEL_3) + os.chown(temp_dir, uid, gid) + # Store record in installation manifest + record = manifest.Record() + record.name = name + record.type = manifest.RECORD_TYPE_DIRECTORY + record.user = self.master_dict['pki_user'] + record.group = self.master_dict['pki_group'] + record.uid = uid + record.gid = gid + record.permissions = dir_perms + record.acls = dir_acls + self.manifest_db.append(record) + else: + config.pki_log.debug( + log.PKIHELPER_IS_A_DIRECTORY_1, name, + extra=config.PKI_INDENTATION_LEVEL_3) + name = os.path.join(root, name) + # chmod + config.pki_log.debug(log.PKIHELPER_CHMOD_2, + dir_perms, name, + extra=config.PKI_INDENTATION_LEVEL_3) + os.chmod(name, dir_perms) + # chown : + config.pki_log.debug(log.PKIHELPER_CHOWN_3, + uid, gid, name, + extra=config.PKI_INDENTATION_LEVEL_3) + os.chown(name, uid, gid) + # Store record in installation manifest + record = manifest.Record() + record.name = name + record.type = manifest.RECORD_TYPE_DIRECTORY + record.user = self.master_dict['pki_user'] + record.group = self.master_dict['pki_group'] + record.uid = uid + record.gid = gid + record.permissions = dir_perms + record.acls = dir_acls + self.manifest_db.append(record) + except OSError as exc: + config.pki_log.error(log.PKI_OSERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise + + def copy(self, old_name, new_name, uid=None, gid=None, + dir_perms=config.PKI_DEPLOYMENT_DEFAULT_DIR_PERMISSIONS, + file_perms=config.PKI_DEPLOYMENT_DEFAULT_FILE_PERMISSIONS, + symlink_perms=config.PKI_DEPLOYMENT_DEFAULT_SYMLINK_PERMISSIONS, + dir_acls=None, file_acls=None, symlink_acls=None, + recursive_flag=True, overwrite_flag=False, critical_failure=True): + try: + if not os.path.exists(old_name) or not os.path.isdir(old_name): + config.pki_log.error( + log.PKI_DIRECTORY_MISSING_OR_NOT_A_DIRECTORY_1, old_name, + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKI_DIRECTORY_MISSING_OR_NOT_A_DIRECTORY_1 % old_name) + else: + if os.path.exists(new_name): + if not overwrite_flag: + config.pki_log.error( + log.PKI_DIRECTORY_ALREADY_EXISTS_1, new_name, + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKI_DIRECTORY_ALREADY_EXISTS_1 % new_name) + if recursive_flag == True: + # cp -rp + config.pki_log.info(log.PKIHELPER_CP_RP_2, + old_name, new_name, + extra=config.PKI_INDENTATION_LEVEL_2) + # Due to a limitation in the 'shutil.copytree()' + # implementation which requires that + # 'The destination directory must not already exist.', + # an OSError exception is always thrown due to the + # implementation's unchecked call to 'os.makedirs(dst)'. + # Consequently, a 'patched' local copy of this routine has + # been included in this file with the appropriate fix. + pki_copytree(old_name, new_name) + else: + # cp -p + config.pki_log.info(log.PKIHELPER_CP_P_2, + old_name, new_name, + extra=config.PKI_INDENTATION_LEVEL_2) + shutil.copy2(old_name, new_name) + # set ownerships, permissions, and acls + # of newly created top-level directory + self.modify(new_name, uid, gid, dir_perms, dir_acls, + True, critical_failure) + # set ownerships, permissions, and acls + # of contents of newly created top-level directory + self.set_mode(new_name, uid, gid, + dir_perms, file_perms, symlink_perms, + dir_acls, file_acls, symlink_acls, + recursive_flag, critical_failure) + except OSError as exc: + config.pki_log.error(log.PKI_OSERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise + except shutil.Error as exc: + config.pki_log.error(log.PKI_SHUTIL_ERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise + return + +class File: + """PKI Deployment File Class (also used for executables)""" + + def __init__(self, deployer): + self.master_dict = deployer.master_dict + self.slots = deployer.slots + self.identity = deployer.identity + self.manifest_db = deployer.manifest_db + + def create(self, name, uid=None, gid=None, + perms=config.PKI_DEPLOYMENT_DEFAULT_FILE_PERMISSIONS, + acls=None, critical_failure=True): + try: + if not os.path.exists(name): + # touch + config.pki_log.info(log.PKIHELPER_TOUCH_1, name, + extra=config.PKI_INDENTATION_LEVEL_2) + open(name, "w").close() + # chmod + config.pki_log.debug(log.PKIHELPER_CHMOD_2, perms, name, + extra=config.PKI_INDENTATION_LEVEL_3) + os.chmod(name, perms) + # chown : + if uid == None: + uid = self.identity.get_uid() + if gid == None: + gid = self.identity.get_gid() + config.pki_log.debug(log.PKIHELPER_CHOWN_3, + uid, gid, name, + extra=config.PKI_INDENTATION_LEVEL_3) + os.chown(name, uid, gid) + # Store record in installation manifest + record = manifest.Record() + record.name = name + record.type = manifest.RECORD_TYPE_FILE + record.user = self.master_dict['pki_user'] + record.group = self.master_dict['pki_group'] + record.uid = uid + record.gid = gid + record.permissions = perms + record.acls = acls + self.manifest_db.append(record) + elif not os.path.isfile(name): + config.pki_log.error( + log.PKI_FILE_ALREADY_EXISTS_NOT_A_FILE_1, name, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise Exception(log.PKI_FILE_ALREADY_EXISTS_NOT_A_FILE_1 % name) + except OSError as exc: + if exc.errno == errno.EEXIST: + pass + else: + config.pki_log.error(log.PKI_OSERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise + return + + def modify(self, name, uid=None, gid=None, + perms=config.PKI_DEPLOYMENT_DEFAULT_FILE_PERMISSIONS, + acls=None, silent=False, critical_failure=True): + try: + if os.path.exists(name): + if not os.path.isfile(name): + config.pki_log.error( + log.PKI_FILE_ALREADY_EXISTS_NOT_A_FILE_1, + name, extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise Exception(log.PKI_FILE_ALREADY_EXISTS_NOT_A_FILE_1 % name) + # Always re-process each file whether it needs it or not + if not silent: + config.pki_log.info(log.PKIHELPER_MODIFY_FILE_1, name, + extra=config.PKI_INDENTATION_LEVEL_2) + # chmod + if not silent: + config.pki_log.debug(log.PKIHELPER_CHMOD_2, perms, name, + extra=config.PKI_INDENTATION_LEVEL_3) + os.chmod(name, perms) + # chown : + if uid == None: + uid = self.identity.get_uid() + if gid == None: + gid = self.identity.get_gid() + if not silent: + config.pki_log.debug(log.PKIHELPER_CHOWN_3, + uid, gid, name, + extra=config.PKI_INDENTATION_LEVEL_3) + os.chown(name, uid, gid) + # Store record in installation manifest + if not silent: + record = manifest.Record() + record.name = name + record.type = manifest.RECORD_TYPE_FILE + record.user = self.master_dict['pki_user'] + record.group = self.master_dict['pki_group'] + record.uid = uid + record.gid = gid + record.permissions = perms + record.acls = acls + self.manifest_db.append(record) + else: + config.pki_log.error( + log.PKI_FILE_MISSING_OR_NOT_A_FILE_1, name, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise Exception(log.PKI_FILE_MISSING_OR_NOT_A_FILE_1 % name) + except OSError as exc: + config.pki_log.error(log.PKI_OSERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise + return + + def delete(self, name, critical_failure=True): + try: + if not os.path.exists(name) or not os.path.isfile(name): + # Simply issue a warning and continue + config.pki_log.warning( + log.PKI_FILE_MISSING_OR_NOT_A_FILE_1, name, + extra=config.PKI_INDENTATION_LEVEL_2) + else: + # rm -f + config.pki_log.info(log.PKIHELPER_RM_F_1, name, + extra=config.PKI_INDENTATION_LEVEL_2) + os.remove(name) + except OSError as exc: + config.pki_log.error(log.PKI_OSERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise + return + + def exists(self, name): + try: + if not os.path.exists(name) or not os.path.isfile(name): + return False + else: + return True + except OSError as exc: + config.pki_log.error(log.PKI_OSERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + raise + + def copy(self, old_name, new_name, uid=None, gid=None, + perms=config.PKI_DEPLOYMENT_DEFAULT_FILE_PERMISSIONS, acls=None, + overwrite_flag=False, critical_failure=True): + try: + if not os.path.exists(old_name) or not os.path.isfile(old_name): + config.pki_log.error( + log.PKI_FILE_MISSING_OR_NOT_A_FILE_1, old_name, + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKI_FILE_MISSING_OR_NOT_A_FILE_1 % old_name) + else: + if os.path.exists(new_name): + if not overwrite_flag: + config.pki_log.error( + log.PKI_FILE_ALREADY_EXISTS_1, new_name, + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKI_FILE_ALREADY_EXISTS_1 % new_name) + # cp -p + config.pki_log.info(log.PKIHELPER_CP_P_2, + old_name, new_name, + extra=config.PKI_INDENTATION_LEVEL_2) + shutil.copy2(old_name, new_name) + if uid == None: + uid = self.identity.get_uid() + if gid == None: + gid = self.identity.get_gid() + # chmod + config.pki_log.debug(log.PKIHELPER_CHMOD_2, + perms, new_name, + extra=config.PKI_INDENTATION_LEVEL_3) + os.chmod(new_name, perms) + # chown : + config.pki_log.debug(log.PKIHELPER_CHOWN_3, + uid, gid, new_name, + extra=config.PKI_INDENTATION_LEVEL_3) + os.chown(new_name, uid, gid) + # Store record in installation manifest + record = manifest.Record() + record.name = new_name + record.type = manifest.RECORD_TYPE_FILE + record.user = self.master_dict['pki_user'] + record.group = self.master_dict['pki_group'] + record.uid = uid + record.gid = gid + record.permissions = perms + record.acls = acls + self.manifest_db.append(record) + except OSError as exc: + config.pki_log.error(log.PKI_OSERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise + except shutil.Error as exc: + config.pki_log.error(log.PKI_SHUTIL_ERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise + return + + def apply_slot_substitution( + self, name, uid=None, gid=None, + perms=config.PKI_DEPLOYMENT_DEFAULT_FILE_PERMISSIONS, + acls=None, critical_failure=True): + try: + if not os.path.exists(name) or not os.path.isfile(name): + config.pki_log.error( + log.PKI_FILE_MISSING_OR_NOT_A_FILE_1, name, + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKI_FILE_MISSING_OR_NOT_A_FILE_1 % name) + # applying in-place slot substitutions on + config.pki_log.info(log.PKIHELPER_APPLY_SLOT_SUBSTITUTION_1, + name, + extra=config.PKI_INDENTATION_LEVEL_2) + for line in fileinput.FileInput(name, inplace=1): + for slot in self.slots: + if slot != '__name__' and self.slots[slot] in line: + config.pki_log.debug( + log.PKIHELPER_SLOT_SUBSTITUTION_2, + self.slots[slot], self.master_dict[slot], + extra=config.PKI_INDENTATION_LEVEL_3) + line = line.replace(self.slots[slot], self.master_dict[slot]) + sys.stdout.write(line) + if uid == None: + uid = self.identity.get_uid() + if gid == None: + gid = self.identity.get_gid() + # chmod + config.pki_log.debug(log.PKIHELPER_CHMOD_2, + perms, name, + extra=config.PKI_INDENTATION_LEVEL_3) + os.chmod(name, perms) + # chown : + config.pki_log.debug(log.PKIHELPER_CHOWN_3, + uid, gid, name, + extra=config.PKI_INDENTATION_LEVEL_3) + os.chown(name, uid, gid) + # Store record in installation manifest + record = manifest.Record() + record.name = name + record.type = manifest.RECORD_TYPE_FILE + record.user = self.master_dict['pki_user'] + record.group = self.master_dict['pki_group'] + record.uid = uid + record.gid = gid + record.permissions = perms + record.acls = acls + self.manifest_db.append(record) + except OSError as exc: + config.pki_log.error(log.PKI_OSERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise + except shutil.Error as exc: + config.pki_log.error(log.PKI_SHUTIL_ERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise + return + + def copy_with_slot_substitution( + self, old_name, new_name, uid=None, gid=None, + perms=config.PKI_DEPLOYMENT_DEFAULT_FILE_PERMISSIONS, + acls=None, overwrite_flag=False, + critical_failure=True): + try: + if not os.path.exists(old_name) or not os.path.isfile(old_name): + config.pki_log.error( + log.PKI_FILE_MISSING_OR_NOT_A_FILE_1, old_name, + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKI_FILE_MISSING_OR_NOT_A_FILE_1 % old_name) + else: + if os.path.exists(new_name): + if not overwrite_flag: + config.pki_log.error( + log.PKI_FILE_ALREADY_EXISTS_1, new_name, + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKI_FILE_ALREADY_EXISTS_1 % new_name) + # copy to with slot substitutions + config.pki_log.info(log.PKIHELPER_COPY_WITH_SLOT_SUBSTITUTION_2, + old_name, new_name, + extra=config.PKI_INDENTATION_LEVEL_2) + with open(new_name, "w") as FILE: + for line in fileinput.FileInput(old_name): + for slot in self.slots: + if slot != '__name__' and self.slots[slot] in line: + config.pki_log.debug( + log.PKIHELPER_SLOT_SUBSTITUTION_2, + self.slots[slot], self.master_dict[slot], + extra=config.PKI_INDENTATION_LEVEL_3) + line = line.replace(self.slots[slot], self.master_dict[slot]) + FILE.write(line) + if uid == None: + uid = self.identity.get_uid() + if gid == None: + gid = self.identity.get_gid() + # chmod + config.pki_log.debug(log.PKIHELPER_CHMOD_2, + perms, new_name, + extra=config.PKI_INDENTATION_LEVEL_3) + os.chmod(new_name, perms) + # chown : + config.pki_log.debug(log.PKIHELPER_CHOWN_3, + uid, gid, new_name, + extra=config.PKI_INDENTATION_LEVEL_3) + os.chown(new_name, uid, gid) + # Store record in installation manifest + record = manifest.Record() + record.name = new_name + record.type = manifest.RECORD_TYPE_FILE + record.user = self.master_dict['pki_user'] + record.group = self.master_dict['pki_group'] + record.uid = uid + record.gid = gid + record.permissions = perms + record.acls = acls + self.manifest_db.append(record) + except OSError as exc: + config.pki_log.error(log.PKI_OSERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise + except shutil.Error as exc: + config.pki_log.error(log.PKI_SHUTIL_ERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise + return + + def generate_noise_file(self, name, random_bytes, uid=None, gid=None, + perms=config.PKI_DEPLOYMENT_DEFAULT_FILE_PERMISSIONS, + acls=None, critical_failure=True): + try: + if not os.path.exists(name): + # generating noise file called and + # filling it with random bytes + config.pki_log.info(log.PKIHELPER_NOISE_FILE_2, name, random_bytes, + extra=config.PKI_INDENTATION_LEVEL_2) + open(name, "w").close() + with open(name, "w") as FILE: + noise = ''.join(random.choice(string.ascii_letters + \ + string.digits) for x in range(random_bytes)) + FILE.write(noise) + # chmod + config.pki_log.debug(log.PKIHELPER_CHMOD_2, perms, name, + extra=config.PKI_INDENTATION_LEVEL_3) + os.chmod(name, perms) + # chown : + if uid == None: + uid = self.identity.get_uid() + if gid == None: + gid = self.identity.get_gid() + config.pki_log.debug(log.PKIHELPER_CHOWN_3, + uid, gid, name, + extra=config.PKI_INDENTATION_LEVEL_3) + os.chown(name, uid, gid) + # Store record in installation manifest + record = manifest.Record() + record.name = name + record.type = manifest.RECORD_TYPE_FILE + record.user = self.master_dict['pki_user'] + record.group = self.master_dict['pki_group'] + record.uid = uid + record.gid = gid + record.permissions = perms + record.acls = acls + self.manifest_db.append(record) + elif not os.path.isfile(name): + config.pki_log.error( + log.PKI_FILE_ALREADY_EXISTS_NOT_A_FILE_1, name, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise Exception(log.PKI_FILE_ALREADY_EXISTS_NOT_A_FILE_1 % name) + except OSError as exc: + if exc.errno == errno.EEXIST: + pass + else: + config.pki_log.error(log.PKI_OSERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise + return + +class Symlink: + """PKI Deployment Symbolic Link Class""" + + def __init__(self, deployer): + self.master_dict = deployer.master_dict + self.identity = deployer.identity + self.manifest_db = deployer.manifest_db + + def create(self, name, link, uid=None, gid=None, + acls=None, allow_dangling_symlink=False, critical_failure=True): + try: + if not os.path.exists(link): + if not os.path.exists(name): + config.pki_log.warning( + log.PKIHELPER_DANGLING_SYMLINK_2, link, name, + extra=config.PKI_INDENTATION_LEVEL_2) + if not allow_dangling_symlink: + raise Exception("Dangling symlink " + link + " not allowed") + # ln -s + config.pki_log.info(log.PKIHELPER_LINK_S_2, name, link, + extra=config.PKI_INDENTATION_LEVEL_2) + os.symlink(name, link) + # REMINDER: Due to POSIX compliance, 'lchmod' is NEVER + # implemented on Linux systems since 'chmod' + # CANNOT be run directly against symbolic links! + # chown -h : + if uid == None: + uid = self.identity.get_uid() + if gid == None: + gid = self.identity.get_gid() + config.pki_log.debug(log.PKIHELPER_CHOWN_H_3, + uid, gid, link, + extra=config.PKI_INDENTATION_LEVEL_3) + os.lchown(link, uid, gid) + # Store record in installation manifest + record = manifest.Record() + record.name = link + record.type = manifest.RECORD_TYPE_SYMLINK + record.user = self.master_dict['pki_user'] + record.group = self.master_dict['pki_group'] + record.uid = uid + record.gid = gid + record.permissions = \ + config.PKI_DEPLOYMENT_DEFAULT_SYMLINK_PERMISSIONS + record.acls = acls + self.manifest_db.append(record) + elif not os.path.islink(link): + config.pki_log.error( + log.PKI_SYMLINK_ALREADY_EXISTS_NOT_A_SYMLINK_1, link, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise Exception(log.PKI_SYMLINK_ALREADY_EXISTS_NOT_A_SYMLINK_1 % link) + except OSError as exc: + if exc.errno == errno.EEXIST: + pass + else: + config.pki_log.error(log.PKI_OSERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise + return + + def modify(self, link, uid=None, gid=None, + acls=None, silent=False, critical_failure=True): + try: + if os.path.exists(link): + if not os.path.islink(link): + config.pki_log.error( + log.PKI_SYMLINK_ALREADY_EXISTS_NOT_A_SYMLINK_1, + link, extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise Exception(log.PKI_SYMLINK_ALREADY_EXISTS_NOT_A_SYMLINK_1 % link) + # Always re-process each link whether it needs it or not + if not silent: + config.pki_log.info(log.PKIHELPER_MODIFY_SYMLINK_1, link, + extra=config.PKI_INDENTATION_LEVEL_2) + # REMINDER: Due to POSIX compliance, 'lchmod' is NEVER + # implemented on Linux systems since 'chmod' + # CANNOT be run directly against symbolic links! + # chown -h : + if uid == None: + uid = self.identity.get_uid() + if gid == None: + gid = self.identity.get_gid() + if not silent: + config.pki_log.debug(log.PKIHELPER_CHOWN_H_3, + uid, gid, link, + extra=config.PKI_INDENTATION_LEVEL_3) + os.lchown(link, uid, gid) + # Store record in installation manifest + if not silent: + record = manifest.Record() + record.name = link + record.type = manifest.RECORD_TYPE_SYMLINK + record.user = self.master_dict['pki_user'] + record.group = self.master_dict['pki_group'] + record.uid = uid + record.gid = gid + record.permissions = \ + config.PKI_DEPLOYMENT_DEFAULT_SYMLINK_PERMISSIONS + record.acls = acls + self.manifest_db.append(record) + else: + config.pki_log.error( + log.PKI_SYMLINK_MISSING_OR_NOT_A_SYMLINK_1, link, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise Exception(log.PKI_SYMLINK_MISSING_OR_NOT_A_SYMLINK_1 % link) + except OSError as exc: + config.pki_log.error(log.PKI_OSERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise + return + + def delete(self, link, critical_failure=True): + try: + if not os.path.exists(link) or not os.path.islink(link): + # Simply issue a warning and continue + config.pki_log.warning( + log.PKI_SYMLINK_MISSING_OR_NOT_A_SYMLINK_1, link, + extra=config.PKI_INDENTATION_LEVEL_2) + else: + # rm -f + config.pki_log.info(log.PKIHELPER_RM_F_1, link, + extra=config.PKI_INDENTATION_LEVEL_2) + os.remove(link) + except OSError as exc: + config.pki_log.error(log.PKI_OSERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise + return + + def exists(self, name): + try: + if not os.path.exists(name) or not os.path.islink(name): + return False + else: + return True + except OSError as exc: + config.pki_log.error(log.PKI_OSERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + raise + +class War: + """PKI Deployment War File Class""" + + def __init__(self, deployer): + self.master_dict = deployer.master_dict + + def explode(self, name, path, critical_failure=True): + try: + if os.path.exists(name) and os.path.isfile(name): + if not zipfile.is_zipfile(name): + config.pki_log.error( + log.PKI_FILE_NOT_A_WAR_FILE_1, + name, extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise Exception(log.PKI_FILE_NOT_A_WAR_FILE_1 % name) + if not os.path.exists(path) or not os.path.isdir(path): + config.pki_log.error( + log.PKI_DIRECTORY_MISSING_OR_NOT_A_DIRECTORY_1, + path, extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise Exception(log.PKI_DIRECTORY_MISSING_OR_NOT_A_DIRECTORY_1, path) + # jar -xf -C + config.pki_log.info(log.PKIHELPER_JAR_XF_C_2, name, path, + extra=config.PKI_INDENTATION_LEVEL_2) + # Open war file + war = zipfile.ZipFile(name, 'r') + # Extract contents of war file to path + war.extractall(path) + else: + config.pki_log.error( + log.PKI_FILE_MISSING_OR_NOT_A_FILE_1, name, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise Exception(log.PKI_FILE_MISSING_OR_NOT_A_FILE_1, name) + except OSError as exc: + config.pki_log.error(log.PKI_OSERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise + except zipfile.BadZipfile as exc: + config.pki_log.error(log.PKI_BADZIPFILE_ERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise + except zipfile.LargeZipFile as exc: + config.pki_log.error(log.PKI_LARGEZIPFILE_ERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise + return + +class Password: + """PKI Deployment Password Class""" + + def __init__(self, deployer): + self.master_dict = deployer.master_dict + + def create_password_conf(self, path, pin, pin_sans_token=False, + overwrite_flag=False, critical_failure=True): + try: + if os.path.exists(path): + if overwrite_flag: + config.pki_log.info( + log.PKIHELPER_PASSWORD_CONF_1, path, + extra=config.PKI_INDENTATION_LEVEL_2) + # overwrite the existing 'password.conf' file + with open(path, "wt") as fd: + if pin_sans_token == True: + fd.write(str(pin)) + elif self.master_dict['pki_subsystem'] in\ + config.PKI_APACHE_SUBSYSTEMS: + fd.write(self.master_dict['pki_self_signed_token'] + \ + ":" + str(pin)) + else: + fd.write(self.master_dict['pki_self_signed_token'] + \ + "=" + str(pin)) + else: + config.pki_log.info(log.PKIHELPER_PASSWORD_CONF_1, path, + extra=config.PKI_INDENTATION_LEVEL_2) + # create a new 'password.conf' file + with open(path, "wt") as fd: + if pin_sans_token == True: + fd.write(str(pin)) + elif self.master_dict['pki_subsystem'] in\ + config.PKI_APACHE_SUBSYSTEMS: + fd.write(self.master_dict['pki_self_signed_token'] + \ + ":" + str(pin)) + else: + fd.write(self.master_dict['pki_self_signed_token'] + \ + "=" + str(pin)) + except OSError as exc: + config.pki_log.error(log.PKI_OSERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise + return + + def create_client_pkcs12_password_conf(self, path, overwrite_flag=False, + critical_failure=True): + try: + if os.path.exists(path): + if overwrite_flag: + config.pki_log.info( + log.PKIHELPER_PASSWORD_CONF_1, path, + extra=config.PKI_INDENTATION_LEVEL_2) + # overwrite the existing 'pkcs12_password.conf' file + with open(path, "wt") as fd: + fd.write(self.master_dict['pki_client_pkcs12_password']) + else: + config.pki_log.info(log.PKIHELPER_PASSWORD_CONF_1, path, + extra=config.PKI_INDENTATION_LEVEL_2) + # create a new 'pkcs12_password.conf' file + with open(path, "wt") as fd: + fd.write(self.master_dict['pki_client_pkcs12_password']) + except OSError as exc: + config.pki_log.error(log.PKI_OSERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise + 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: + raise Exception(log.PKIHELPER_PASSWORD_NOT_FOUND_1 % token_name) + else: + return + return token_pwd + +class Certutil: + """PKI Deployment NSS 'certutil' Class""" + + def __init__(self, deployer): + self.master_dict = deployer.master_dict + + def create_security_databases(self, path, pki_cert_database, + pki_key_database, pki_secmod_database, + password_file=None, prefix=None, + critical_failure=True): + try: + # Compose this "certutil" command + command = "certutil" + " " + "-N" + # Provide a path to the NSS security databases + if path: + command = command + " " + "-d" + " " + path + else: + config.pki_log.error( + log.PKIHELPER_CERTUTIL_MISSING_PATH, + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_CERTUTIL_MISSING_PATH) + if password_file != None: + command = command + " " + "-f" + " " + password_file + if prefix != None: + command = command + " " + "-P" + " " + prefix + if not os.path.exists(path): + config.pki_log.error( + log.PKI_DIRECTORY_MISSING_OR_NOT_A_DIRECTORY_1, path, + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKI_DIRECTORY_MISSING_OR_NOT_A_DIRECTORY_1 % path) + if os.path.exists(pki_cert_database) or\ + os.path.exists(pki_key_database) or\ + os.path.exists(pki_secmod_database): + # Simply notify user that the security databases exist + config.pki_log.info( + log.PKI_SECURITY_DATABASES_ALREADY_EXIST_3, + pki_cert_database, + pki_key_database, + pki_secmod_database, + extra=config.PKI_INDENTATION_LEVEL_2) + else: + if password_file != None: + if not os.path.exists(password_file) or\ + not os.path.isfile(password_file): + config.pki_log.error( + log.PKI_FILE_MISSING_OR_NOT_A_FILE_1, + password_file, + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKI_FILE_MISSING_OR_NOT_A_FILE_1 % password_file) + # Display this "certutil" command + config.pki_log.info( + log.PKIHELPER_CREATE_SECURITY_DATABASES_1, + command, + extra=config.PKI_INDENTATION_LEVEL_2) + # Execute this "certutil" command + subprocess.call(command, shell=True) + except subprocess.CalledProcessError as exc: + config.pki_log.error(log.PKI_SUBPROCESS_ERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise + except OSError as exc: + config.pki_log.error(log.PKI_OSERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise + return + + def verify_certificate_exists(self, path, pki_cert_database, + pki_key_database, pki_secmod_database, + token, nickname, password_file=None, + silent=True, critical_failure=True): + try: + # Compose this "certutil" command + command = "certutil" + " " + "-L" + # Provide a path to the NSS security databases + if path: + command = command + " " + "-d" + " " + path + else: + config.pki_log.error( + log.PKIHELPER_CERTUTIL_MISSING_PATH, + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_CERTUTIL_MISSING_PATH) + # Specify the 'token' + if token: + command = command + " " + "-h" + " " + "'" + token + "'" + else: + config.pki_log.error( + log.PKIHELPER_CERTUTIL_MISSING_TOKEN, + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_CERTUTIL_MISSING_TOKEN) + # Specify the nickname of this self-signed certificate + if nickname: + command = command + " " + "-n" + " " + "'" + nickname + "'" + else: + config.pki_log.error( + log.PKIHELPER_CERTUTIL_MISSING_NICKNAME, + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_CERTUTIL_MISSING_NICKNAME) + # OPTIONALLY specify a password file + if password_file != None: + command = command + " " + "-f" + " " + password_file + # By default, execute this command silently + if silent != False: + command = command + " > /dev/null 2>&1" + if not os.path.exists(path): + config.pki_log.error( + log.PKI_DIRECTORY_MISSING_OR_NOT_A_DIRECTORY_1, path, + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKI_DIRECTORY_MISSING_OR_NOT_A_DIRECTORY_1 % path) + if not os.path.exists(pki_cert_database) or\ + not os.path.exists(pki_key_database) or\ + not os.path.exists(pki_secmod_database): + # NSS security databases MUST exist! + config.pki_log.error( + log.PKI_SECURITY_DATABASES_DO_NOT_EXIST_3, + pki_cert_database, + pki_key_database, + pki_secmod_database, + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKI_SECURITY_DATABASES_DO_NOT_EXIST_3 % (pki_cert_database, + pki_key_database, pki_secmod_database)) + if password_file != None: + if not os.path.exists(password_file) or\ + not os.path.isfile(password_file): + config.pki_log.error( + log.PKI_FILE_MISSING_OR_NOT_A_FILE_1, + password_file, + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKI_FILE_MISSING_OR_NOT_A_FILE_1 % password_file) + # Execute this "certutil" command + subprocess.check_call(command, shell=True) + except subprocess.CalledProcessError as exc: + return False + except OSError as exc: + config.pki_log.error(log.PKI_OSERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise + return True + + def generate_self_signed_certificate(self, path, pki_cert_database, + pki_key_database, pki_secmod_database, + token, nickname, + subject, serial_number, + validity_period, issuer_name, + trustargs, noise_file, + password_file=None, + critical_failure=True): + try: + # Compose this "certutil" command + command = "certutil" + " " + "-S" + # Provide a path to the NSS security databases + if path: + command = command + " " + "-d" + " " + path + else: + config.pki_log.error( + log.PKIHELPER_CERTUTIL_MISSING_PATH, + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_CERTUTIL_MISSING_PATH) + # Specify the 'token' + if token: + command = command + " " + "-h" + " " + "'" + token + "'" + else: + config.pki_log.error( + log.PKIHELPER_CERTUTIL_MISSING_TOKEN, + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_CERTUTIL_MISSING_TOKEN) + # Specify the nickname of this self-signed certificate + if nickname: + command = command + " " + "-n" + " " + "'" + nickname + "'" + else: + config.pki_log.error( + log.PKIHELPER_CERTUTIL_MISSING_NICKNAME, + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_CERTUTIL_MISSING_NICKNAME) + # Specify the subject name (RFC1485) + if subject: + command = command + " " + "-s" + " " + "'" + subject + "'" + else: + config.pki_log.error( + log.PKIHELPER_CERTUTIL_MISSING_SUBJECT, + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_CERTUTIL_MISSING_SUBJECT) + # Specify the serial number + if serial_number != None: + command = command + " " + "-m" + " " + str(serial_number) + else: + config.pki_log.error( + log.PKIHELPER_CERTUTIL_MISSING_SERIAL_NUMBER, + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_CERTUTIL_MISSING_SERIAL_NUMBER) + # Specify the months valid + if validity_period != None: + command = command + " " + "-v" + " " + str(validity_period) + else: + config.pki_log.error( + log.PKIHELPER_CERTUTIL_MISSING_VALIDITY_PERIOD, + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_CERTUTIL_MISSING_VALIDITY_PERIOD) + # Specify the nickname of the issuer certificate + if issuer_name: + command = command + " " + "-c" + " " + \ + "'" + issuer_name + "'" + else: + config.pki_log.error( + log.PKIHELPER_CERTUTIL_MISSING_ISSUER_NAME, + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_CERTUTIL_MISSING_ISSUER_NAME) + # Specify the certificate trust attributes + if trustargs: + command = command + " " + "-t" + " " + "'" + trustargs + "'" + else: + config.pki_log.error( + log.PKIHELPER_CERTUTIL_MISSING_TRUSTARGS, + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_CERTUTIL_MISSING_TRUSTARGS) + # Specify a noise file to be used for key generation + if noise_file: + command = command + " " + "-z" + " " + noise_file + else: + config.pki_log.error( + log.PKIHELPER_CERTUTIL_MISSING_NOISE_FILE, + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_CERTUTIL_MISSING_NOISE_FILE) + # OPTIONALLY specify a password file + if password_file != None: + command = command + " " + "-f" + " " + password_file + # ALWAYS self-sign this certificate + command = command + " " + "-x" + # ALWAYS mask the command-line output of this command + command = command + " " + "> /dev/null 2>&1" + # Display this "certutil" command + config.pki_log.info( + log.PKIHELPER_CERTUTIL_SELF_SIGNED_CERTIFICATE_1, command, + extra=config.PKI_INDENTATION_LEVEL_2) + if not os.path.exists(path): + config.pki_log.error( + log.PKI_DIRECTORY_MISSING_OR_NOT_A_DIRECTORY_1, path, + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKI_DIRECTORY_MISSING_OR_NOT_A_DIRECTORY_1 % path) + if not os.path.exists(pki_cert_database) or\ + not os.path.exists(pki_key_database) or\ + not os.path.exists(pki_secmod_database): + # NSS security databases MUST exist! + config.pki_log.error( + log.PKI_SECURITY_DATABASES_DO_NOT_EXIST_3, + pki_cert_database, + pki_key_database, + pki_secmod_database, + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKI_SECURITY_DATABASES_DO_NOT_EXIST_3 % (pki_cert_database, + pki_key_database, pki_secmod_database)) + if not os.path.exists(noise_file): + config.pki_log.error( + log.PKI_DIRECTORY_MISSING_OR_NOT_A_DIRECTORY_1, + noise_file, + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKI_DIRECTORY_MISSING_OR_NOT_A_DIRECTORY_1 % noise_file) + if password_file != None: + if not os.path.exists(password_file) or\ + not os.path.isfile(password_file): + config.pki_log.error( + log.PKI_FILE_MISSING_OR_NOT_A_FILE_1, + password_file, + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKI_FILE_MISSING_OR_NOT_A_FILE_1 % password_file) + # Execute this "certutil" command + subprocess.call(command, shell=True) + except subprocess.CalledProcessError as exc: + config.pki_log.error(log.PKI_SUBPROCESS_ERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise + except OSError as exc: + config.pki_log.error(log.PKI_OSERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise + return + + def import_cert(self, nickname, trust, input_file, password_file, + path=None, token=None, critical_failure=True): + try: + command = ["certutil", "-A"] + if path: + command.extend(["-d", path]) + + if token: + command.extend(["-h", token]) + + if nickname: + command.extend(["-n", nickname ]) + else: + config.pki_log.error( + log.PKIHELPER_CERTUTIL_MISSING_NICKNAME, + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_CERTUTIL_MISSING_NICKNAME) + + if trust: + command.extend(["-t", trust]) + else: + config.pki_log.error( + log.PKIHELPER_CERTUTIL_MISSING_TRUSTARGS, + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_CERTUTIL_MISSING_TRUSTARGS) + + if input_file: + command.extend(["-i", input_file]) + else: + config.pki_log.error( + log.PKIHELPER_CERTUTIL_MISSING_INPUT_FILE, + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_CERTUTIL_MISSING_INPUT_FILE) + + if password_file: + command.extend(["-f", password_file]) + else: + config.pki_log.error( + log.PKIHELPER_CERTUTIL_MISSING_PASSWORD_FILE, + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_CERTUTIL_MISSING_PASSWORD_FILE) + + config.pki_log.info(command, + extra=config.PKI_INDENTATION_LEVEL_2) + subprocess.call(command) + except subprocess.CalledProcessError as exc: + config.pki_log.error(log.PKI_SUBPROCESS_ERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise + except OSError as exc: + config.pki_log.error(log.PKI_OSERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise + return + + def generate_certificate_request(self, subject, key_size, + password_file, noise_file, + output_file=None, path=None, + ascii_format=None, token=None, + critical_failure=True): + try: + command = ["certutil", "-R"] + if path: + command.extend(["-d", path]) + else: + command.extend(["-d", "."]) + + if token: + command.extend(["-h", token]) + + if subject: + command.extend(["-s", subject]) + else: + config.pki_log.error( + log.PKIHELPER_CERTUTIL_MISSING_SUBJECT, + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_CERTUTIL_MISSING_SUBJECT) + + if key_size: + command.extend(["-g", str(key_size)]) + + if noise_file: + command.extend(["-z", noise_file]) + else: + config.pki_log.error( + log.PKIHELPER_CERTUTIL_MISSING_NOISE_FILE, + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_CERTUTIL_MISSING_NOISE_FILE) + + if password_file: + command.extend(["-f", password_file]) + else: + config.pki_log.error( + log.PKIHELPER_CERTUTIL_MISSING_PASSWORD_FILE, + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_CERTUTIL_MISSING_PASSWORD_FILE) + + if output_file: + command.extend(["-o", output_file]) + + # set acsii output + if ascii_format: + command.append("-a") + + # Display this "certutil" command + config.pki_log.info( + log.PKIHELPER_CERTUTIL_GENERATE_CSR_1, command, + extra=config.PKI_INDENTATION_LEVEL_2) + if not os.path.exists(noise_file): + config.pki_log.error( + log.PKI_DIRECTORY_MISSING_OR_NOT_A_DIRECTORY_1, + noise_file, + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKI_DIRECTORY_MISSING_OR_NOT_A_DIRECTORY_1 % noise_file) + if not os.path.exists(password_file) or\ + not os.path.isfile(password_file): + config.pki_log.error( + log.PKI_FILE_MISSING_OR_NOT_A_FILE_1, + password_file, + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKI_FILE_MISSING_OR_NOT_A_FILE_1 % password_file) + # Execute this "certutil" command + with open(os.devnull, "w") as fnull: + subprocess.call(command, stdout=fnull, stderr=fnull) + except subprocess.CalledProcessError as exc: + config.pki_log.error(log.PKI_SUBPROCESS_ERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise + except OSError as exc: + config.pki_log.error(log.PKI_OSERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise + return + +class PK12util: + """PKI Deployment pk12util class""" + + def __init__(self, deployer): + self.master_dict = deployer.master_dict + + def create_file(self, out_file, nickname, out_pwfile, + db_pwfile, path=None, critical_failure=True): + try: + command = ["pk12util"] + if path: + command.extend(["-d", path]) + if out_file: + command.extend(["-o", out_file]) + else: + config.pki_log.error( + log.PKIHELPER_PK12UTIL_MISSING_OUTFILE, + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_PK12UTIL_MISSING_OUTFILE) + if nickname: + command.extend(["-n", nickname]) + else: + config.pki_log.error( + log.PKIHELPER_PK12UTIL_MISSING_NICKNAME, + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_PK12UTIL_MISSING_NICKNAME) + if out_pwfile: + command.extend(["-w", out_pwfile]) + else: + config.pki_log.error( + log.PKIHELPER_PK12UTIL_MISSING_PWFILE, + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_PK12UTIL_MISSING_PWFILE) + if db_pwfile: + command.extend(["-k", db_pwfile]) + else: + config.pki_log.error( + log.PKIHELPER_PK12UTIL_MISSING_DBPWFILE, + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKIHELPER_PK12UTIL_MISSING_DBPWFILE) + + config.pki_log.info(command, + extra=config.PKI_INDENTATION_LEVEL_2) + with open(os.devnull, "w") as fnull: + subprocess.call(command, stdout=fnull, stderr=fnull) + except subprocess.CalledProcessError as exc: + config.pki_log.error(log.PKI_SUBPROCESS_ERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise + except OSError as exc: + config.pki_log.error(log.PKI_OSERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise + return + +class KRAConnector: + """PKI Deployment KRA Connector Class""" + + def __init__(self, deployer): + self.master_dict = deployer.master_dict + self.password = deployer.password + + def deregister(self, critical_failure=False): + try: + # this is applicable to KRAs only + if self.master_dict['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( + self.master_dict['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: + raise Exception(log.PKIHELPER_UNDEFINED_CA_HOST_PORT) + 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: + raise Exception(log.PKIHELPER_UNDEFINED_SUBSYSTEM_NICKNAME) + 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 = self.password.get_password( + self.master_dict['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: + raise Exception(log.PKIHELPER_UNDEFINED_TOKEN_PASSWD_1 % token_name) + 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: + raise + 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 '{}' -c '{}' "\ + "kraconnector-del {} {}".format( + caport, cahost, subsystemnick, + self.master_dict['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: + raise Exception(log.PKI_SUBPROCESS_ERROR_1 % output) + + def execute_using_sslget(self, caport, cahost, subsystemnick, + token_pwd, krahost, kraport): + 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, + self.master_dict['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 + subprocess.check_output(command,stderr=subprocess.STDOUT, + shell=True) + +class SecurityDomain: + """PKI Deployment Security Domain Class""" + + def __init__(self, deployer): + self.master_dict = deployer.master_dict + self.password = deployer.password + + def deregister(self, install_token, critical_failure=False): + # process this PKI subsystem instance's 'CS.cfg' + cs_cfg = PKIConfigParser.read_simple_configuration_file( + self.master_dict['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') + 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') + adminsport = cs_cfg.get('pkicreate.admin_secure_port', '') + typeval = cs_cfg.get('cs.type', '') + agentsport = cs_cfg.get('pkicreate.agent_secure_port', '') + + # 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: + raise Exception(log.PKIHELPER_SECURITY_DOMAIN_UNDEFINED) + else: + return + + config.pki_log.info(log.PKIHELPER_SECURITY_DOMAIN_CONTACT_1, + secname, + extra=config.PKI_INDENTATION_LEVEL_2) + listval = typeval.lower() + "List" + updateURL = "/ca/agent/ca/updateDomainXML" + + params = "name=" + "\"" + self.master_dict['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" + + 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( + self.master_dict['pki_database_path'], + params, adminUpdateURL, + sechost, secadminport) + output = subprocess.check_output(command, + stderr=subprocess.STDOUT, + shell=True) + except subprocess.CalledProcessError: + 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: + raise Exception("Cannot update domain using agent port") + 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('(.*?)', 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: + raise Exception(log.PKIHELPER_SECURITY_DOMAIN_UNREACHABLE_1 % secname) + elif status[0] != "0": + error = re.findall('(.*?)', 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: + raise Exception(log.PKIHELPER_SECURITY_DOMAIN_UPDATE_FAILURE_3 + % + (typeval, secname, error)) + 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( + self.master_dict['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: + raise Exception(log.PKIHELPER_UNDEFINED_SUBSYSTEM_NICKNAME) + 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 = self.password.get_password( + self.master_dict['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: + raise Exception(log.PKIHELPER_SECURITY_DOMAIN_UPDATE_FAILURE_2 + % + (typeval, secname)) + else: + return + + command = "/usr/bin/sslget -n '{}' -p '{}' -d '{}' -e '{}' "\ + "-v -r '{}' {}:{} 2>&1".format( + subsystemnick, token_pwd, + self.master_dict['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, + typeval, + secname, + extra=config.PKI_INDENTATION_LEVEL_2) + config.pki_log.warning( + log.PKIHELPER_SECURITY_DOMAIN_UNREACHABLE_1, + secname, + 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: + raise + + 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( + self.master_dict['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') - Selected security domain + + command = "/bin/pki -p '{}' -h '{}' -P https -u '{}' -w '{}' -d '{}' "\ + "securitydomain-get-install-token --hostname {} "\ + "--subsystem {}".format( + secadminport, sechost, secuser, secpass, + self.master_dict['pki_database_path'], + 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: + raise Exception(log.PKIHELPER_SECURITY_DOMAIN_GET_TOKEN_FAILURE_2 + % + (str(sechost), str(secadminport))) + 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: + raise + return None + +class Systemd: + """PKI Deployment 'systemd' Execution Management Class""" + + def __init__(self, deployer): + self.master_dict = deployer.master_dict + + def start(self, critical_failure=True): + try: + # Compose this "systemd" execution management command + if self.master_dict['pki_subsystem'] in config.PKI_APACHE_SUBSYSTEMS: + command = "systemctl" + " " + \ + "start" + " " + \ + "pki-apached" + "@" + \ + self.master_dict['pki_instance_name'] + "." + "service" + elif self.master_dict['pki_subsystem'] in config.PKI_TOMCAT_SUBSYSTEMS: + command = "systemctl" + " " + \ + "start" + " " + \ + "pki-tomcatd" + "@" + \ + self.master_dict['pki_instance_name'] + "." + "service" + # Display this "systemd" execution managment command + config.pki_log.info( + log.PKIHELPER_SYSTEMD_COMMAND_1, command, + extra=config.PKI_INDENTATION_LEVEL_2) + # Execute this "systemd" execution management command + subprocess.call(command, shell=True) + except subprocess.CalledProcessError as exc: + config.pki_log.error(log.PKI_SUBPROCESS_ERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise + return + + def stop(self, critical_failure=True): + try: + # Compose this "systemd" execution management command + if self.master_dict['pki_subsystem'] in config.PKI_APACHE_SUBSYSTEMS: + command = "systemctl" + " " + \ + "stop" + " " + \ + "pki-apached" + "@" + \ + self.master_dict['pki_instance_name'] + "." + "service" + elif self.master_dict['pki_subsystem'] in config.PKI_TOMCAT_SUBSYSTEMS: + command = "systemctl" + " " + \ + "stop" + " " + \ + "pki-tomcatd" + "@" + \ + self.master_dict['pki_instance_name'] + "." + "service" + # Display this "systemd" execution managment command + config.pki_log.info( + log.PKIHELPER_SYSTEMD_COMMAND_1, command, + extra=config.PKI_INDENTATION_LEVEL_2) + # Execute this "systemd" execution management command + subprocess.call(command, shell=True) + except subprocess.CalledProcessError as exc: + config.pki_log.error(log.PKI_SUBPROCESS_ERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise + return + + def restart(self, critical_failure=True): + try: + # Compose this "systemd" execution management command + if self.master_dict['pki_subsystem'] in config.PKI_APACHE_SUBSYSTEMS: + command = "systemctl" + " " + \ + "restart" + " " + \ + "pki-apached" + "@" + \ + self.master_dict['pki_instance_name'] + "." + "service" + elif self.master_dict['pki_subsystem'] in config.PKI_TOMCAT_SUBSYSTEMS: + command = "systemctl" + " " + \ + "restart" + " " + \ + "pki-tomcatd" + "@" + \ + self.master_dict['pki_instance_name'] + "." + "service" + # Display this "systemd" execution managment command + config.pki_log.info( + log.PKIHELPER_SYSTEMD_COMMAND_1, command, + extra=config.PKI_INDENTATION_LEVEL_2) + # Execute this "systemd" execution management command + subprocess.call(command, shell=True) + except subprocess.CalledProcessError as exc: + config.pki_log.error(log.PKI_SUBPROCESS_ERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + if critical_failure == True: + raise + return + + +class ConfigClient: + """PKI Deployment Configuration Client""" + + def __init__(self, deployer): + self.deployer = deployer + self.master_dict = deployer.master_dict + + def configure_pki_data(self, data): + config.pki_log.info(log.PKI_CONFIG_CONFIGURING_PKI_DATA, + extra=config.PKI_INDENTATION_LEVEL_2) + + connection = pki.client.PKIConnection( + protocol='https', + hostname=self.master_dict['pki_hostname'], + port=self.master_dict['pki_https_port'], + subsystem=self.master_dict['pki_subsystem_type']) + + try: + client = pki.system.SystemConfigClient(connection) + response = client.configure(data) + + config.pki_log.debug(log.PKI_CONFIG_RESPONSE_STATUS + \ + " " + str(response['status']), + extra=config.PKI_INDENTATION_LEVEL_2) + try: + certs = response['systemCerts'] + except KeyError: + # no system certs created + config.pki_log.debug("No new system certificates generated.", + extra=config.PKI_INDENTATION_LEVEL_2) + certs = [] + + if not isinstance(certs, types.ListType): + certs = [certs] + for cdata in certs: + if self.master_dict['pki_subsystem'] == "CA" and\ + config.str2bool(self.master_dict['pki_external']) and\ + not config.str2bool(self.master_dict['pki_external_step_two']): + # External CA Step 1 + if cdata['tag'].lower() == "signing": + config.pki_log.info(log.PKI_CONFIG_CDATA_REQUEST + \ + " " + cdata['request'], + extra=config.PKI_INDENTATION_LEVEL_2) + + # Save 'External CA Signing Certificate' CSR (Step 1) + config.pki_log.info(log.PKI_CONFIG_EXTERNAL_CSR_SAVE + \ + " '" + self.master_dict['pki_external_csr_path'] + "'", + extra=config.PKI_INDENTATION_LEVEL_2) + self.deployer.directory.create( + os.path.dirname(self.master_dict['pki_external_csr_path'])) + with open(self.master_dict['pki_external_csr_path'], "w") as f: + f.write(cdata['request']) + return + else: + config.pki_log.debug(log.PKI_CONFIG_CDATA_TAG + \ + " " + cdata['tag'], + extra=config.PKI_INDENTATION_LEVEL_2) + config.pki_log.debug(log.PKI_CONFIG_CDATA_CERT + \ + " " + cdata['cert'], + extra=config.PKI_INDENTATION_LEVEL_2) + config.pki_log.debug(log.PKI_CONFIG_CDATA_REQUEST + \ + " " + cdata['request'], + extra=config.PKI_INDENTATION_LEVEL_2) + + # Cloned PKI subsystems do not return an Admin Certificate + if not config.str2bool(self.master_dict['pki_clone']) and \ + not config.str2bool(self.master_dict['pki_import_admin_cert']): + admin_cert = response['adminCert']['cert'] + self.process_admin_cert(admin_cert) + + except Exception, e: + if hasattr(e, 'response'): + root = ET.fromstring(e.response.text) + if root.tag == 'PKIException': + message = root.findall('.//Message')[0].text + if message is not None: + config.pki_log.error(log.PKI_CONFIG_JAVA_CONFIGURATION_EXCEPTION + " " + message, + extra=config.PKI_INDENTATION_LEVEL_2) + raise + config.pki_log.error( + log.PKI_CONFIG_JAVA_CONFIGURATION_EXCEPTION + " " + str(e), + extra=config.PKI_INDENTATION_LEVEL_2) + raise + return + + def process_admin_cert(self, admin_cert): + config.pki_log.debug(log.PKI_CONFIG_RESPONSE_ADMIN_CERT + \ + " " + admin_cert, + extra=config.PKI_INDENTATION_LEVEL_2) + + # Store the Administration Certificate in a file + admin_cert_file = self.master_dict['pki_client_admin_cert'] + admin_cert_bin_file = admin_cert_file + ".der" + config.pki_log.debug(log.PKI_CONFIG_ADMIN_CERT_SAVE + \ + " '" + admin_cert_file + "'", + extra=config.PKI_INDENTATION_LEVEL_2) + with open(admin_cert_file, "w") as f: + f.write(admin_cert) + + # convert the cert file to binary + command = ["AtoB", admin_cert_file, admin_cert_bin_file] + config.pki_log.info(command, + extra=config.PKI_INDENTATION_LEVEL_2) + subprocess.call(command) + + os.chmod(admin_cert_file, + config.PKI_DEPLOYMENT_DEFAULT_FILE_PERMISSIONS) + + os.chmod(admin_cert_bin_file, + config.PKI_DEPLOYMENT_DEFAULT_FILE_PERMISSIONS) + + # Import the Administration Certificate + # into the client NSS security database + self.deployer.certutil.import_cert( + re.sub("'", "'", self.master_dict['pki_admin_nickname']), + "u,u,u", + admin_cert_bin_file, + self.master_dict['pki_client_password_conf'], + self.master_dict['pki_client_database_dir'], + None, + True) + + # create directory for p12 file if it does not exist + self.deployer.directory.create(os.path.dirname( + self.master_dict['pki_client_admin_cert_p12'])) + + # Export the Administration Certificate from the + # client NSS security database into a PKCS #12 file + self.deployer.pk12util.create_file( + self.master_dict['pki_client_admin_cert_p12'], + re.sub("'", "'", self.master_dict['pki_admin_nickname']), + self.master_dict['pki_client_pkcs12_password_conf'], + self.master_dict['pki_client_password_conf'], + self.master_dict['pki_client_database_dir']) + + os.chmod(self.master_dict['pki_client_admin_cert_p12'], + config.PKI_DEPLOYMENT_DEFAULT_SECURITY_DATABASE_PERMISSIONS) + + + def construct_pki_configuration_data(self): + config.pki_log.info(log.PKI_CONFIG_CONSTRUCTING_PKI_DATA, + extra=config.PKI_INDENTATION_LEVEL_2) + + data = pki.system.ConfigurationRequest() + + # Miscellaneous Configuration Information + data.pin = self.master_dict['pki_one_time_pin'] + data.subsystemName = self.master_dict['pki_subsystem_name'] + + # Cloning parameters + if self.master_dict['pki_instance_type'] == "Tomcat": + if config.str2bool(self.master_dict['pki_clone']): + self.set_cloning_parameters(data) + else: + data.isClone = "false" + + # Hierarchy + self.set_hierarchy_parameters(data) + + # Security Domain + if self.master_dict['pki_subsystem'] != "CA" or\ + config.str2bool(self.master_dict['pki_clone']) or\ + config.str2bool(self.master_dict['pki_subordinate']): + # PKI KRA, PKI OCSP, PKI RA, PKI TKS, PKI TPS, + # CA Clone, KRA Clone, OCSP Clone, TKS Clone, TPS Clone, or + # Subordinate CA + self.set_existing_security_domain(data) + else: + # PKI CA or External CA + self.set_new_security_domain(data) + + # database + if self.master_dict['pki_subsystem'] != "RA": + self.set_database_parameters(data) + + # backup + if self.master_dict['pki_instance_type'] == "Tomcat": + self.set_backup_parameters(data) + + # admin user + if not config.str2bool(self.master_dict['pki_clone']): + self.set_admin_parameters(data) + + # Issuing CA Information + self.set_issuing_ca_parameters(data) + + # Create system certs + self.set_system_certs(data) + + return data + + def set_system_certs(self, data): + systemCerts = [] + + # Create 'CA Signing Certificate' + if self.master_dict['pki_subsystem'] == "CA": + if not config.str2bool(self.master_dict['pki_clone']): + cert1 = self.create_system_cert("ca_signing") + cert1.signingAlgorithm = \ + self.master_dict['pki_ca_signing_signing_algorithm'] + if config.str2bool(self.master_dict['pki_external_step_two']): + # Load the 'External CA Signing Certificate' (Step 2) + print( + log.PKI_CONFIG_EXTERNAL_CA_LOAD + " " + \ + "'" + self.master_dict['pki_external_ca_cert_path'] + "'") + with open(self.master_dict['pki_external_ca_cert_path']) as f: + external_cert = f.read() + cert1.cert = external_cert + + # Load the 'External CA Signing Certificate Chain' (Step 2) + print( + log.PKI_CONFIG_EXTERNAL_CA_CHAIN_LOAD + " " + \ + "'" + self.master_dict['pki_external_ca_cert_chain_path'] + \ + "'") + with open(self.master_dict['pki_external_ca_cert_chain_path']) as f: + external_cert_chain = f.read() + + cert1.certChain = external_cert_chain + systemCerts.append(cert1) + + # Create 'OCSP Signing Certificate' + if not config.str2bool(self.master_dict['pki_clone']): + if self.master_dict['pki_subsystem'] == "CA" or\ + self.master_dict['pki_subsystem'] == "OCSP": + # External CA, Subordinate CA, PKI CA, or PKI OCSP + cert2 = self.create_system_cert("ocsp_signing") + cert2.signingAlgorithm = \ + self.master_dict['pki_ocsp_signing_signing_algorithm'] + systemCerts.append(cert2) + + # Create 'SSL Server Certificate' + # all subsystems + + # create new sslserver cert only if this is a new instance + cert3 = None + system_list = self.deployer.instance.tomcat_instance_subsystems() + if len(system_list) >= 2: + data.generateServerCert = "false" + for subsystem in system_list: + dst = self.master_dict['pki_instance_path'] + '/conf/' + \ + subsystem.lower() + '/CS.cfg' + if subsystem != self.master_dict['pki_subsystem'] and \ + os.path.exists(dst): + cert3 = self.retrieve_existing_server_cert(dst) + break + else: + cert3 = self.create_system_cert("ssl_server") + systemCerts.append(cert3) + + # Create 'Subsystem Certificate' + if not config.str2bool(self.master_dict['pki_clone']): + cert4 = self.create_system_cert("subsystem") + systemCerts.append(cert4) + + # Create 'Audit Signing Certificate' + if not config.str2bool(self.master_dict['pki_clone']): + if self.master_dict['pki_subsystem'] != "RA": + cert5 = self.create_system_cert("audit_signing") + cert5.signingAlgorithm = \ + self.master_dict['pki_audit_signing_signing_algorithm'] + systemCerts.append(cert5) + + # Create DRM Transport and storage Certificates + if not config.str2bool(self.master_dict['pki_clone']): + if self.master_dict['pki_subsystem'] == "KRA": + cert6 = self.create_system_cert("transport") + systemCerts.append(cert6) + + cert7 = self.create_system_cert("storage") + systemCerts.append(cert7) + + data.systemCerts = systemCerts + + def set_cloning_parameters(self, data): + data.isClone = "true" + data.cloneUri = self.master_dict['pki_clone_uri'] + data.p12File = self.master_dict['pki_clone_pkcs12_path'] + data.p12Password = self.master_dict['pki_clone_pkcs12_password'] + data.replicateSchema = self.master_dict['pki_clone_replicate_schema'] + data.replicationSecurity = \ + self.master_dict['pki_clone_replication_security'] + if self.master_dict['pki_clone_replication_master_port']: + data.masterReplicationPort = \ + self.master_dict['pki_clone_replication_master_port'] + if self.master_dict['pki_clone_replication_clone_port']: + data.cloneReplicationPort = \ + self.master_dict['pki_clone_replication_clone_port'] + + def set_hierarchy_parameters(self, data): + if self.master_dict['pki_subsystem'] == "CA": + if config.str2bool(self.master_dict['pki_clone']): + # Cloned CA + data.hierarchy = "root" + elif config.str2bool(self.master_dict['pki_external']): + # External CA + data.hierarchy = "join" + elif config.str2bool(self.master_dict['pki_subordinate']): + # Subordinate CA + data.hierarchy = "join" + else: + # PKI CA + data.hierarchy = "root" + + def set_existing_security_domain(self, data): + data.securityDomainType = "existingdomain" + data.securityDomainUri = self.master_dict['pki_security_domain_uri'] + data.securityDomainUser = self.master_dict['pki_security_domain_user'] + data.securityDomainPassword = self.master_dict['pki_security_domain_password'] + + def set_new_security_domain(self, data): + data.securityDomainType = "newdomain" + data.securityDomainName = self.master_dict['pki_security_domain_name'] + + def set_database_parameters(self, data): + data.dsHost = self.master_dict['pki_ds_hostname'] + data.dsPort = self.master_dict['pki_ds_ldap_port'] + data.baseDN = self.master_dict['pki_ds_base_dn'] + data.bindDN = self.master_dict['pki_ds_bind_dn'] + data.database = self.master_dict['pki_ds_database'] + data.bindpwd = self.master_dict['pki_ds_password'] + if config.str2bool(self.master_dict['pki_ds_remove_data']): + data.removeData = "true" + else: + data.removeData = "false" + if config.str2bool(self.master_dict['pki_ds_secure_connection']): + data.secureConn = "true" + else: + data.secureConn = "false" + + def set_backup_parameters(self, data): + if config.str2bool(self.master_dict['pki_backup_keys']): + data.backupKeys = "true" + data.backupFile = self.master_dict['pki_backup_keys_p12'] + data.backupPassword = self.master_dict['pki_backup_password'] + else: + data.backupKeys = "false" + + def set_admin_parameters(self, data): + data.adminEmail = self.master_dict['pki_admin_email'] + data.adminName = self.master_dict['pki_admin_name'] + data.adminPassword = self.master_dict['pki_admin_password'] + data.adminProfileID = self.master_dict['pki_admin_profile_id'] + data.adminUID = self.master_dict['pki_admin_uid'] + data.adminSubjectDN = self.master_dict['pki_admin_subject_dn'] + if config.str2bool(self.master_dict['pki_import_admin_cert']): + data.importAdminCert = "true" + # read config from file + with open(self.master_dict['pki_admin_cert_file']) as f: + b64 = f.read().replace('\n', '') + data.adminCert = b64 + else: + data.importAdminCert = "false" + data.adminSubjectDN = self.master_dict['pki_admin_subject_dn'] + if self.master_dict['pki_admin_cert_request_type'] == "pkcs10": + data.adminCertRequestType = "pkcs10" + + noise_file = os.path.join( + self.master_dict['pki_client_database_dir'], "noise") + + output_file = os.path.join( + self.master_dict['pki_client_database_dir'], "admin_pkcs10.bin") + + self.deployer.file.generate_noise_file( + noise_file, int(self.master_dict['pki_admin_keysize'])) + + self.deployer.certutil.generate_certificate_request( + self.master_dict['pki_admin_subject_dn'], + self.master_dict['pki_admin_keysize'], + self.master_dict['pki_client_password_conf'], + noise_file, + output_file, + self.master_dict['pki_client_database_dir'], + None, None, True) + + # convert output to ascii + command = ["BtoA", output_file, output_file + ".asc"] + config.pki_log.info(command, + extra=config.PKI_INDENTATION_LEVEL_2) + subprocess.call(command) + + with open(output_file + ".asc") as f: + b64 = f.read().replace('\n', '') + + data.adminCertRequest = b64 + else: + print "log.PKI_CONFIG_PKCS10_SUPPORT_ONLY" + raise Exception(log.PKI_CONFIG_PKCS10_SUPPORT_ONLY) + + def set_issuing_ca_parameters(self, data): + if self.master_dict['pki_subsystem'] != "CA" or\ + config.str2bool(self.master_dict['pki_clone']) or\ + config.str2bool(self.master_dict['pki_subordinate']) or\ + config.str2bool(self.master_dict['pki_external']): + # PKI KRA, PKI OCSP, PKI RA, PKI TKS, PKI TPS, + # CA Clone, KRA Clone, OCSP Clone, TKS Clone, TPS Clone, + # Subordinate CA, or External CA + data.issuingCA = self.master_dict['pki_issuing_ca'] + if self.master_dict['pki_subsystem'] == "CA" and\ + config.str2bool(self.master_dict['pki_external_step_two']): + # External CA Step 2 + data.stepTwo = "true" + + def create_system_cert(self, tag): + cert = pki.system.SystemCertData() + cert.tag = self.master_dict["pki_%s_tag" % tag] + cert.keyAlgorithm = self.master_dict["pki_%s_key_algorithm" % tag] + cert.keySize = self.master_dict["pki_%s_key_size" % tag] + cert.keyType = self.master_dict["pki_%s_key_type" % tag] + cert.nickname = self.master_dict["pki_%s_nickname" % tag] + cert.subjectDN = self.master_dict["pki_%s_subject_dn" % tag] + cert.token = self.master_dict["pki_%s_token" % tag] + return cert + + def retrieve_existing_server_cert(self, cfg_file): + cs_cfg = PKIConfigParser.read_simple_configuration_file(cfg_file) + cstype = cs_cfg.get('cs.type').lower() + cert = pki.system.SystemCertData() + cert.tag = self.master_dict["pki_ssl_server_tag"] + cert.keyAlgorithm = self.master_dict["pki_ssl_server_key_algorithm"] + cert.keySize = self.master_dict["pki_ssl_server_key_size"] + cert.keyType = self.master_dict["pki_ssl_server_key_type"] + cert.nickname = cs_cfg.get(cstype + ".sslserver.nickname") + cert.cert = cs_cfg.get(cstype + ".sslserver.cert") + cert.request = cs_cfg.get(cstype + ".sslserver.certreq") + cert.subjectDN = self.master_dict["pki_ssl_server_subject_dn"] + cert.token = cs_cfg.get(cstype + ".sslserver.tokenname") + return cert + +class PKIDeployer: + """Holds the global dictionaries and the utility objects""" + + def __init__(self, pki_master_dict, pki_slots_dict=None): + # Global dictionary variables + self.master_dict = pki_master_dict + self.slots = pki_slots_dict + self.manifest_db = [] + + # Utility objects + self.identity = Identity(self) + self.namespace = Namespace(self) + self.configuration_file = ConfigurationFile(self) + self.instance = Instance(self) + self.directory = Directory(self) + self.file = File(self) + self.symlink = Symlink(self) + self.war = War(self) + self.password = Password(self) + self.certutil = Certutil(self) + self.pk12util = PK12util(self) + self.kra_connector = KRAConnector(self) + self.security_domain = SecurityDomain(self) + self.systemd = Systemd(self) + self.config_client = ConfigClient(self) + + diff --git a/base/server/python/pki/server/deployment/pkilogging.py b/base/server/python/pki/server/deployment/pkilogging.py new file mode 100644 index 000000000..c91a7656f --- /dev/null +++ b/base/server/python/pki/server/deployment/pkilogging.py @@ -0,0 +1,76 @@ +#!/usr/bin/python -t +# Authors: +# Matthew Harmsen +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Copyright (C) 2012 Red Hat, Inc. +# All rights reserved. +# + +# System Imports +import logging +import os +import pprint + +sensitive_parameters = [] + +# Initialize 'pretty print' for objects +pp = pprint.PrettyPrinter(indent=4) + +def log_format(given_dict): + new_dict = {} + + # mask sensitive data + for key in given_dict: + if key in sensitive_parameters: + value = 'XXXXXXXX' + else: + value = given_dict[key] + new_dict[key] = value + + return pp.pformat(new_dict) + +# PKI Deployment Logging Functions +def enable_pki_logger(log_dir, log_name, log_level, console_log_level, name): + if not os.path.isdir(log_dir): + try: + os.makedirs(log_dir) + except OSError: + return OSError + + # Configure logger + logger = logging.getLogger(name) + logger.setLevel(log_level) + + # Configure console handler + console = logging.StreamHandler() + console.setLevel(console_log_level) + console_format = logging.Formatter('%(name)-12s: ' + \ + '%(levelname)-8s ' + \ + '%(indent)s%(message)s') + console.setFormatter(console_format) + logger.addHandler(console) + + # Configure file handler + log_file = logging.FileHandler(log_dir + "/" + log_name, 'w') + log_file.setLevel(log_level) + file_format = logging.Formatter('%(asctime)s %(name)-12s: ' + \ + '%(levelname)-8s ' + \ + '%(indent)s%(message)s', + '%Y-%m-%d %H:%M:%S') + log_file.setFormatter(file_format) + logger.addHandler(log_file) + + return logger diff --git a/base/server/python/pki/server/deployment/pkimanifest.py b/base/server/python/pki/server/deployment/pkimanifest.py new file mode 100644 index 000000000..dea2af275 --- /dev/null +++ b/base/server/python/pki/server/deployment/pkimanifest.py @@ -0,0 +1,104 @@ +#!/usr/bin/python -t +# Authors: +# Matthew Harmsen +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Copyright (C) 2012 Red Hat, Inc. +# All rights reserved. +# + +# System Imports +import csv + +# PKI Deployment Imports +from . import pkiconfig as config +from . import pkimessages as log + + +# PKI Deployment Manifest Constants +RECORD_TYPE_DIRECTORY = "directory" +RECORD_TYPE_FILE = "file" +RECORD_TYPE_SYMLINK = "symlink" + + +# PKI Deployment Manifest Record Class +class Record(object): + __slots__ = "name", \ + "type", \ + "user", \ + "group", \ + "uid", \ + "gid", \ + "permissions", \ + "acls", + + def __init__(self): + self.name = None + self.type = None + self.user = None + self.group = None + self.uid = None + self.gid = None + self.permissions = None + self.acls = None + + def items(self): + "dict style items" + return [ + (field_name, getattr(self, field_name)) + for field_name in self.__slots__] + + def __iter__(self): + "iterate over fields tuple/list style" + for field_name in self.__slots__: + yield getattr(self, field_name) + + def __getitem__(self, index): + "tuple/list style getitem" + return getattr(self, self.__slots__[index]) + + +# PKI Deployment Manifest File Class +class File: + + def __init__(self, database): + self.filename = None + self.database = database + + def register(self, name): + self.filename = name + + def write(self): + try: + with open(self.filename, "wt") as fd: + c = csv.writer(fd) + for record in self.database: + c.writerow(tuple(record)) + except IOError as exc: + config.pki_log.error(log.PKI_IOERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_1) + raise + + def read(self): + try: + with open(self.filename, "rt") as fd: + cr = csv.reader(fd) + for row in cr: + print tuple(row) + except IOError as exc: + config.pki_log.error(log.PKI_IOERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_1) + raise + diff --git a/base/server/python/pki/server/deployment/pkimessages.py b/base/server/python/pki/server/deployment/pkimessages.py new file mode 100644 index 000000000..2e1ecba45 --- /dev/null +++ b/base/server/python/pki/server/deployment/pkimessages.py @@ -0,0 +1,359 @@ +#!/usr/bin/python -t +# Authors: +# Matthew Harmsen +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Copyright (C) 2012 Red Hat, Inc. +# All rights reserved. +# + +# PKI Deployment Engine Messages +PKI_DICTIONARY_DEFAULT = "\n"\ +"=====================================================\n"\ +" DISPLAY CONTENTS OF PKI DEFAULT DICTIONARY\n"\ +"=====================================================" +PKI_DICTIONARY_MASTER = "\n"\ +"=====================================================\n"\ +" DISPLAY CONTENTS OF PKI MASTER DICTIONARY\n"\ +"=====================================================" +PKI_DICTIONARY_SLOTS = "\n"\ +"=====================================================\n"\ +" DISPLAY CONTENTS OF PKI SLOTS DICTIONARY\n"\ +"=====================================================" +PKI_DICTIONARY_SUBSYSTEM = "\n"\ +"=====================================================\n"\ +" DISPLAY CONTENTS OF PKI SUBSYSTEM DICTIONARY\n"\ +"=====================================================" +PKI_DICTIONARY_WEB_SERVER = "\n"\ +"=====================================================\n"\ +" DISPLAY CONTENTS OF PKI WEB SERVER DICTIONARY\n"\ +"=====================================================" +# NEVER print out 'sensitive' data dictionary!!! + + +# PKI Deployment Log Messages +PKI_VERBOSITY = \ +"VERBOSITY FLAGS CONSOLE MESSAGE LEVEL LOG MESSAGE LEVEL\n"\ +"=======================================================================\n"\ +" NONE error|warning error|warning|info|debug\n"\ +" -v error|warning|info error|warning|info|debug\n"\ +" -vv error|warning|info|debug error|warning|info|debug\n"\ +" " + + +# PKI Deployment Error Messages +PKI_BADZIPFILE_ERROR_1 = "zipfile.BadZipFile: %s!" +PKI_CONFIGURATION_RESTART_1 = " After configuration, the server can be "\ + "operated by the command:\n %s" +PKI_CONFIGURATION_URL_1 = " Please start the configuration by accessing:\n %s" +PKI_CONFIGURATION_WIZARD_RESTART_1 = "After configuration, the server can be "\ + "operated by the command:\n%s" +PKI_CONFIGURATION_WIZARD_URL_1 = "Configuration Wizard listening on\n%s" +PKI_DIRECTORY_ALREADY_EXISTS_1 = "Directory '%s' already exists!" +PKI_DIRECTORY_ALREADY_EXISTS_NOT_A_DIRECTORY_1 = "Directory '%s' already "\ + "exists BUT it is NOT a "\ + "directory!" +PKI_DIRECTORY_MISSING_OR_NOT_A_DIRECTORY_1 = "Directory '%s' is either "\ + "missing or is NOT a directory!" +PKI_DNS_DOMAIN_NOT_SET = "A valid DNS domain name MUST be established "\ + "to use PKI services!" +PKI_FILE_ALREADY_EXISTS_1 = "File '%s' already exists!" +PKI_FILE_ALREADY_EXISTS_NOT_A_FILE_1 = "File '%s' already "\ + "exists BUT it is NOT a "\ + "file!" +PKI_FILE_MISSING_OR_NOT_A_FILE_1 = "File '%s' is either missing "\ + "or is NOT a regular file!" +PKI_FILE_NOT_A_WAR_FILE_1 = "File '%s' is NOT a war file!" +PKI_INSTANCE_DOES_NOT_EXIST_1 = "PKI instance '%s' does NOT exist!" +PKI_SECURITY_DATABASES_ALREADY_EXIST_3 = "Security databases '%s', '%s', "\ + "and/or '%s' already exist!" +PKI_SECURITY_DATABASES_DO_NOT_EXIST_3 = "Security databases '%s', '%s', "\ + "and/or '%s' do NOT exist!" +PKI_SUBSYSTEM_NOT_INSTALLED_1 = "Package pki-%s is NOT installed!" +PKI_SUBSYSTEM_ALREADY_EXISTS_2 = "PKI subsystem '%s' for instance '%s' "\ + "already exists!" +PKI_SUBSYSTEM_DOES_NOT_EXIST_2 = "PKI subsystem '%s' for instance '%s' "\ + "does NOT exist!" + +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_OSERROR_1 = "OSError: %s!" +PKI_SHUTIL_ERROR_1 = "shutil.Error: %s!" +PKI_SUBPROCESS_ERROR_1 = "subprocess.CalledProcessError: %s!" +PKI_SYMLINK_ALREADY_EXISTS_1 = "Symlink '%s' already exists!" +PKI_SYMLINK_ALREADY_EXISTS_NOT_A_SYMLINK_1 = "Symlink '%s' already "\ + "exists BUT it is NOT a "\ + "symlink!" +PKI_SYMLINK_MISSING_OR_NOT_A_SYMLINK_1 = "Symlink '%s' is either missing "\ + "or is NOT a symbolic link!" +PKI_UNABLE_TO_PARSE_1 = "'Could not parse: '%s'" +PKI_UNABLE_TO_CREATE_LOG_DIRECTORY_1 = "Could not create log directory '%s'!" + + +# PKI Deployment 'pkispawn' and 'pkidestroy' Messages +PKIDESTROY_BEGIN_MESSAGE_2 = "BEGIN destroying subsystem '%s' of "\ + "instance '%s' . . ." +PKIDESTROY_END_MESSAGE_2 = "END destroying subsystem '%s' of "\ + "instance '%s'" +PKIDESTROY_EPILOG = \ +"REMINDER:\n\n"\ +" The default PKI instance path will be calculated and placed in front\n"\ +" of the mandatory '-i ' parameter, and the values that reside\n"\ +" in deployment configuration file that was most recently used\n"\ +" by this instance's 'pkispawn' (or 'pkispawn -u') command will be\n"\ +" utilized by 'pkidestroy' to remove this instance.\n\n"\ +" Finally, if an optional '-p ' is defined, this value WILL be\n"\ +" prepended to the default PKI instance path which is placed in front\n"\ +" of the specified '-i ' parameter.\n\n" + \ +PKI_VERBOSITY +PKISPAWN_BEGIN_MESSAGE_2 = "BEGIN spawning subsystem '%s' of "\ + "instance '%s' . . ." +PKISPAWN_END_MESSAGE_2 = "END spawning subsystem '%s' of "\ + "instance '%s'" +PKISPAWN_EPILOG = \ +"REMINDER:\n\n"\ +" If two or more Apache or Tomcat PKI 'instances' are specified via\n"\ +" separate configuration files, remember that the following parameters\n"\ +" MUST differ between PKI 'instances':\n\n"\ +" Apache: 'pki_instance_name', 'pki_http_port', and 'pki_https_port'\n"\ +" Tomcat: 'pki_instance_name', 'pki_http_port', 'pki_https_port',\n"\ +" 'pki_ajp_port', and 'pki_tomcat_server_port'\n\n"\ +" Finally, if an optional '-p ' is defined, this value WILL NOT\n"\ +" be prepended in front of the mandatory '-f '.\n\n" + \ +PKI_VERBOSITY + + +# PKI Deployment "Helper" Messages +PKIHELPER_APACHE_INSTANCE_SUBSYSTEMS_2 = "instance '%s' contains '%d' "\ + "Apache PKI subsystems" +PKIHELPER_APACHE_INSTANCES_2 = "PKI Apache registry '%s' contains '%d' "\ + "Apache PKI instances" +PKIHELPER_APPLY_SLOT_SUBSTITUTION_1 = "applying in-place "\ + "slot substitutions on '%s'" +PKIHELPER_CERTUTIL_GENERATE_CSR_1 = "executing '%s'" +PKIHELPER_CERTUTIL_MISSING_INPUT_FILE = "certutil: Missing "\ + "'-i input-file' option!" +PKIHELPER_CERTUTIL_MISSING_ISSUER_NAME = "certutil: Missing "\ + "'-c issuer-name' option!" +PKIHELPER_CERTUTIL_MISSING_NICKNAME = "certutil: Missing "\ + "'-n nickname' option!" +PKIHELPER_CERTUTIL_MISSING_NOISE_FILE = "certutil: Missing "\ + "'-z noise-file' option!" +PKIHELPER_CERTUTIL_MISSING_PASSWORD_FILE = "certutil: Missing "\ + "'-f password-file' option!" +PKIHELPER_CERTUTIL_MISSING_PATH = "certutil: Missing '-d path' option!" +PKIHELPER_CERTUTIL_MISSING_SERIAL_NUMBER = "certutil: Missing "\ + "'-m serial-number' option!" +PKIHELPER_CERTUTIL_MISSING_SUBJECT = "certutil: Missing '-s subject' option!" +PKIHELPER_CERTUTIL_MISSING_TOKEN = "certutil: Missing '-h token' option!" +PKIHELPER_CERTUTIL_MISSING_TRUSTARGS = "certutil: Missing "\ + "'-t trustargs' option!" +PKIHELPER_CERTUTIL_MISSING_VALIDITY_PERIOD = "certutil: Missing "\ + "'-v months-valid' option!" +PKIHELPER_CERTUTIL_SELF_SIGNED_CERTIFICATE_1 = "executing '%s'" +PKIHELPER_CHMOD_2 = "chmod %o %s" +PKIHELPER_CHOWN_3 = "chown %s:%s %s" +PKIHELPER_CHOWN_H_3 = "chown -h %s:%s %s" +PKIHELPER_COMMAND_LINE_PARAMETER_MISMATCH_2 = "the command-line parameter "\ + "'%s' DOES NOT match the "\ + "configuration file value '%s'!" +PKIHELPER_COPY_WITH_SLOT_SUBSTITUTION_2 = "copying '%s' --> '%s' "\ + "with slot substitution" +PKIHELPER_CP_P_2 = "cp -p %s %s" +PKIHELPER_CP_RP_2 = "cp -rp %s %s" +PKIHELPER_CREATE_SECURITY_DATABASES_1 = "executing '%s'" +PKIHELPER_DANGLING_SYMLINK_2 = "Dangling symlink '%s'-->'%s'" +PKIHELPER_DICTIONARY_MASTER_MISSING_KEY_1 = "KeyError: Master dictionary "\ + "is missing the key called '%s'!" +PKIHELPER_DIRECTORY_IS_EMPTY_1 = "directory '%s' is empty" +PKIHELPER_DIRECTORY_IS_NOT_EMPTY_1 = "directory '%s' is NOT empty" +PKIHELPER_GID_2 = "GID of '%s' is %s" +PKIHELPER_GROUP_1 = "retrieving GID for '%s' . . ." +PKIHELPER_GROUP_ADD_2 = "adding GID '%s' for group '%s' . . ." +PKIHELPER_GROUP_ADD_DEFAULT_2 = "adding default GID '%s' for group '%s' . . ." +PKIHELPER_GROUP_ADD_GID_KEYERROR_1 = "KeyError: pki_gid %s" +PKIHELPER_GROUP_ADD_KEYERROR_1 = "KeyError: pki_group %s" +PKIHELPER_INVALID_SELINUX_CONTEXT_FOR_PORT = "port %s has invalid selinux "\ + "context %s" +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'" +PKIHELPER_MODIFY_FILE_1 = "modifying '%s'" +PKIHELPER_MODIFY_SYMLINK_1 = "modifying '%s'" +PKIHELPER_MUTUALLY_EXCLUSIVE_CLONE_EXTERNAL_CA = "cloned CAs and external "\ + "CAs MUST be MUTUALLY "\ + "EXCLUSIVE in '%s'" +PKIHELPER_MUTUALLY_EXCLUSIVE_CLONE_EXTERNAL_SUB_CA = "cloned CAs, external "\ + "CAs, and subordinate CAs"\ + "MUST ALL be MUTUALLY "\ + "EXCLUSIVE in '%s'" +PKIHELPER_MUTUALLY_EXCLUSIVE_CLONE_SUB_CA = "cloned CAs and subordinate "\ + "CAs MUST be MUTUALLY "\ + "EXCLUSIVE in '%s'" +PKIHELPER_MUTUALLY_EXCLUSIVE_EXTERNAL_SUB_CA = "external CAs and subordinate "\ + "CAs MUST be MUTUALLY "\ + "EXCLUSIVE in '%s'" +PKIHELPER_NAMESPACE_COLLISION_2 = "PKI instance '%s' would produce a "\ + "namespace collision with '%s'!" +PKIHELPER_NAMESPACE_RESERVED_NAME_2 = "PKI instance '%s' is already a "\ + "reserved name under '%s'!" +PKIHELPER_NOISE_FILE_2 = "generating noise file called '%s' and "\ + "filling it with '%d' random bytes" +PKIHELPER_PASSWORD_CONF_1 = "generating '%s'" +PKIHELPER_PASSWORD_NOT_FOUND_1 = "no password found for '%s'!" +PKIHELPER_PK12UTIL_MISSING_DBPWFILE = "pk12util missing "\ + "-k db-password-file option!" +PKIHELPER_PK12UTIL_MISSING_NICKNAME = "pk12util missing "\ + "-n nickname option!" +PKIHELPER_PK12UTIL_MISSING_OUTFILE = "pk12util missing "\ + "-o output-file option!" +PKIHELPER_PK12UTIL_MISSING_PWFILE = "pk12util missing "\ + "-w pw-file option!" + +PKIHELPER_PKI_INSTANCE_SUBSYSTEMS_2 = "instance '%s' contains '%d' "\ + "PKI subsystems" +PKIHELPER_REMOVE_FILTER_SECTION_1 = "removing filter section from '%s'" +PKIHELPER_RM_F_1 = "rm -f %s" +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"\ + "Otherwise, manually delete the entry from the security domain master." +PKIHELPER_SECURITY_DOMAIN_UNREACHABLE_1 = \ + "security domain '%s' may be offline or unreachable!" +PKIHELPER_SECURITY_DOMAIN_UNREGISTERED_2 = \ + "this '%s' entry may not be registered with security domain '%s'!" +PKIHELPER_SECURITY_DOMAIN_UPDATE_FAILURE_2 = \ + "this '%s' entry will NOT be deleted from security domain '%s'!" +PKIHELPER_SECURITY_DOMAIN_UPDATE_FAILURE_3 = \ + "updateDomainXML FAILED to delete this '%s' entry from "\ + "security domain '%s': '%s'" +PKIHELPER_SECURITY_DOMAIN_UPDATE_SUCCESS_2 = \ + "updateDomainXML SUCCESSFULLY deleted this '%s' entry from "\ + "security domain '%s'" +PKIHELPER_SELINUX_DISABLED = "Selinux is disabled. Not checking port contexts" +PKIHELPER_SET_MODE_1 = "setting ownerships, permissions, and acls on '%s'" +PKIHELPER_SLOT_SUBSTITUTION_2 = "slot substitution: '%s' ==> '%s'" +PKIHELPER_SSLGET_OUTPUT_1 = "\n"\ + "Dump of 'sslget' output:\n"\ + "=====================================================\n"\ + "%s\n"\ + "=====================================================" +PKIHELPER_SYSTEMD_COMMAND_1 = "executing '%s'" +PKIHELPER_TOMCAT_INSTANCE_SUBSYSTEMS_2 = "instance '%s' contains '%d' "\ + "Tomcat PKI subsystems" +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' . . ." +PKIHELPER_USER_ADD_KEYERROR_1 = "KeyError: pki_user %s" +PKIHELPER_USER_ADD_UID_KEYERROR_1 = "KeyError: pki_uid %s" + +PKI_CONFIG_ADMIN_CERT_SAVE = "saving Admin Certificate to file:" +PKI_CONFIG_ADMIN_CERT_ATOB = "converting Admin Certificate to binary:" +PKI_CONFIG_CDATA_TAG = "tag:" +PKI_CONFIG_CDATA_CERT = "cert:" +PKI_CONFIG_CDATA_REQUEST = "request:" +PKI_CONFIG_CONFIGURING_PKI_DATA = "configuring PKI configuration data." +PKI_CONFIG_CONSTRUCTING_PKI_DATA = "constructing PKI configuration data." +PKI_CONFIG_PKCS10_SUPPORT_ONLY = "only the 'pkcs10' certificate request type "\ + "is currently supported" +PKI_CONFIG_EXTERNAL_CA_LOAD = "loading external CA signing certificate "\ + "from file:" +PKI_CONFIG_EXTERNAL_CA_CHAIN_LOAD = "loading external CA signing certificate "\ + "chain from file:" +PKI_CONFIG_EXTERNAL_CSR_SAVE = "saving CA Signing CSR to file:" +PKI_CONFIG_JAVA_CONFIGURATION_EXCEPTION = \ + "Exception from Java Configuration Servlet:" +PKI_CONFIG_RESPONSE_ADMIN_CERT = "adminCert:" +PKI_CONFIG_RESPONSE_STATUS = "status:" +PKI_CONFIG_NOT_YET_IMPLEMENTED_1 = " %s NOT YET IMPLEMENTED" +PKI_CHECK_STATUS_MESSAGE = " To check the status of the subsystem: \n"\ + " systemctl status pki-tomcatd\@%s.service" +PKI_ACCESS_URL = " The URL for the subsystem is: \n"\ + " https://%s:%s/%s" +PKI_INSTANCE_RESTART_MESSAGE = " To restart the subsystem: \n"\ + " systemctl restart pki-tomcatd\@%s.service" + + +PKI_SPAWN_INFORMATION_HEADER = "\n ==========================================================================\n"\ + " INSTALLATION SUMMARY\n"\ + " ==========================================================================\n" + +PKI_SPAWN_INFORMATION_FOOTER = "\n ==========================================================================\n" + + +# PKI Deployment "Scriptlet" Messages +ADMIN_DOMAIN_DESTROY_1 = "depopulating '%s'" +ADMIN_DOMAIN_SPAWN_1 = "populating '%s'" +CONFIGURATION_DESTROY_1 = "unconfiguring '%s'" +CONFIGURATION_SPAWN_1 = "configuring '%s'" +FINALIZATION_DESTROY_1 = "finalizing '%s'" +FINALIZATION_SPAWN_1 = "finalizing '%s'" +INITIALIZATION_DESTROY_1 = "initializing '%s'" +INITIALIZATION_SPAWN_1 = "initializing '%s'" +INSTANCE_DESTROY_1 = "depopulating '%s'" +INSTANCE_SPAWN_1 = "populating '%s'" +RESIDUAL_DESTROY_1 = "depopulating '%s'" +RESIDUAL_SPAWN_1 = "populating '%s'" +SECURITY_DATABASES_DESTROY_1 = "removing '%s'" +SECURITY_DATABASES_SPAWN_1 = "generating '%s'" +SELINUX_DESTROY_1 = "depopulating '%s'" +SELINUX_SPAWN_1 = "populating '%s'" +SELINUX_DISABLED_DESTROY_1 = "selinux disabled. skipping unlabelling '%s'" +SELINUX_DISABLED_SPAWN_1 = "selinux disabled. skipping labelling '%s'" +SLOT_ASSIGNMENT_DESTROY_1 = "unassigning slots for '%s'" +SLOT_ASSIGNMENT_SPAWN_1 = "assigning slots for '%s'" +SUBSYSTEM_DESTROY_1 = "depopulating '%s'" +SUBSYSTEM_SPAWN_1 = "populating '%s'" +WEBAPP_DEPLOYMENT_DESTROY_1 = "removing '%s'" +WEBAPP_DEPLOYMENT_SPAWN_1 = "deploying '%s'" +SKIP_ADMIN_DOMAIN_SPAWN_1 = "skip populating '%s'" +SKIP_CONFIGURATION_SPAWN_1 = "skip configuring '%s'" +SKIP_FINALIZATION_SPAWN_1 = "skip finalizing '%s'" +SKIP_INITIALIZATION_SPAWN_1 = "skip initializing '%s'" +SKIP_INSTANCE_SPAWN_1 = "skip populating '%s'" +SKIP_RESIDUAL_SPAWN_1 = "skip populating '%s'" +SKIP_SECURITY_DATABASES_SPAWN_1 = "skip generating '%s'" +SKIP_SELINUX_SPAWN_1 = "skip populating '%s'" +SKIP_SLOT_ASSIGNMENT_SPAWN_1 = "skip assigning slots for '%s'" +SKIP_SUBSYSTEM_SPAWN_1 = "skip populating '%s'" +SKIP_WEBAPP_DEPLOYMENT_SPAWN_1 = "skip deploying '%s'" diff --git a/base/server/python/pki/server/deployment/pkiparser.py b/base/server/python/pki/server/deployment/pkiparser.py new file mode 100644 index 000000000..8dbed8deb --- /dev/null +++ b/base/server/python/pki/server/deployment/pkiparser.py @@ -0,0 +1,1080 @@ +#!/usr/bin/python -t +# Authors: +# Matthew Harmsen +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Copyright (C) 2012 Red Hat, Inc. +# All rights reserved. +# + +# System Imports +import ConfigParser +import argparse +import getpass +import ldap +import logging +import os +import random +import requests +import string +import subprocess + +# PKI Imports +import pki +import pki.upgrade +import pki.account +import pki.client +import pki.system +from . import pkiconfig as config +from . import pkimessages as log +from . import pkilogging + + +class PKIConfigParser: + + COMMENT_CHAR = '#' + OPTION_CHAR = '=' + + def __init__(self, description, epilog): + self.pki_config = None + + #Read and process command-line options + self.arg_parser = argparse.ArgumentParser( + description=description, + add_help=False, + formatter_class=argparse.RawDescriptionHelpFormatter, + epilog=epilog) + + # Establish 'Mandatory' command-line options + self.mandatory = self.arg_parser.add_argument_group('mandatory arguments') + + # Establish 'Optional' command-line options + self.optional = self.arg_parser.add_argument_group('optional arguments') + self.optional.add_argument('-s', + dest='pki_subsystem', action='store', + nargs=1, choices=config.PKI_SUBSYSTEMS, + metavar='', + help='where is ' + 'CA, KRA, OCSP, RA, TKS, or TPS') + self.optional.add_argument('-h', '--help', + dest='help', action='help', + help='show this help message and exit') + self.optional.add_argument('-v', + dest='pki_verbosity', action='count', + help='display verbose information (details below)') + + # Establish 'Test' command-line options + test = self.arg_parser.add_argument_group('test arguments') + test.add_argument('-p', + dest='pki_root_prefix', action='store', + nargs=1, metavar='', + help='directory prefix to specify local directory ' + '[TEST ONLY]') + self.indent = 0 + self.ds_connection = None + self.sd_connection = None + + # Master and Slot dictionaries + self.pki_master_dict = dict() + self.pki_slots_dict = dict() + + # PKI Deployment Helper Functions + def process_command_line_arguments(self): + + # Parse command-line options + args = self.arg_parser.parse_args() + + # Process 'Mandatory' command-line options + + # Process 'Optional' command-line options + # '-v' + if args.pki_verbosity == 1: + config.pki_console_log_level = logging.INFO + elif args.pki_verbosity >= 2: + config.pki_console_log_level = logging.DEBUG + else: + # Set default log levels + config.pki_console_log_level = logging.WARNING + + # Debug log is always at DEBUG level + config.pki_log_level = logging.DEBUG + + # Process 'Test' command-line options + # '-p' + if args.pki_root_prefix is None: + config.pki_root_prefix = "" + else: + config.pki_root_prefix = str(args.pki_root_prefix).strip('[\']') + + return args + + + def validate(self): + + # Validate command-line options + if len(config.pki_root_prefix) > 0: + if not os.path.exists(config.pki_root_prefix) or\ + not os.path.isdir(config.pki_root_prefix): + print "ERROR: " + \ + log.PKI_DIRECTORY_MISSING_OR_NOT_A_DIRECTORY_1 % \ + config.pki_root_prefix + print + self.arg_parser.print_help() + self.arg_parser.exit(-1) + + # always default that configuration file exists + if not os.path.exists(config.default_deployment_cfg) or\ + not os.path.isfile(config.default_deployment_cfg): + print "ERROR: " + \ + log.PKI_FILE_MISSING_OR_NOT_A_FILE_1 % \ + config.default_deployment_cfg + print + self.arg_parser.print_help() + self.arg_parser.exit(-1) + + if config.user_deployment_cfg: + # verify user configuration file exists + if not os.path.exists(config.user_deployment_cfg) or\ + not os.path.isfile(config.user_deployment_cfg): + print "ERROR: " + \ + log.PKI_FILE_MISSING_OR_NOT_A_FILE_1 % \ + config.user_deployment_cfg + print + self.arg_parser.print_help() + self.arg_parser.exit(-1) + + + def init_config(self): + + # RESTEasy + resteasy_lib = subprocess.check_output(\ + 'source /etc/pki/pki.conf && echo $RESTEASY_LIB', + shell=True).strip() + + # JNI jar location + jni_jar_dir = subprocess.check_output(\ + 'source /usr/share/pki/etc/pki.conf && echo $JNI_JAR_DIR', + shell=True).strip() + + if config.pki_subsystem in config.PKI_TOMCAT_SUBSYSTEMS: + default_instance_name = 'pki-tomcat' + default_http_port = '8080' + default_https_port = '8443' + else: + default_instance_name = 'pki-apache' + default_http_port = '80' + default_https_port = '443' + + application_version = str(pki.upgrade.Version(pki.implementation_version())) + + self.pki_config = ConfigParser.SafeConfigParser({ + 'application_version': application_version, + 'pki_instance_name': default_instance_name, + 'pki_http_port': default_http_port, + 'pki_https_port': default_https_port, + 'pki_dns_domainname': config.pki_dns_domainname, + 'pki_subsystem': config.pki_subsystem, + 'pki_subsystem_type': config.pki_subsystem.lower(), + 'pki_root_prefix' : config.pki_root_prefix, + 'resteasy_lib': resteasy_lib, + 'jni_jar_dir': jni_jar_dir, + 'home_dir': os.path.expanduser("~"), + 'pki_hostname': config.pki_hostname}) + + # Make keys case-sensitive! + self.pki_config.optionxform = str + + config.user_config = ConfigParser.SafeConfigParser() + config.user_config.optionxform = str + + with open(config.default_deployment_cfg) as f: + self.pki_config.readfp(f) + + self.flatten_master_dict() + + + # The following code is based heavily upon + # "http://www.decalage.info/en/python/configparser" + @staticmethod + def read_simple_configuration_file(filename): + values = {} + with open(filename) as f: + for line in f: + # First, remove comments: + if PKIConfigParser.COMMENT_CHAR in line: + # split on comment char, keep only the part before + line, _ = line.split(PKIConfigParser.COMMENT_CHAR, 1) + # Second, find lines with an name=value: + if PKIConfigParser.OPTION_CHAR in line: + # split on name char: + name, value = line.split(PKIConfigParser.OPTION_CHAR, 1) + # strip spaces: + name = name.strip() + value = value.strip() + # store in dictionary: + values[name] = value + return values + + + def set_property(self, section, key, value): + if section != "DEFAULT" and not self.pki_config.has_section(section): + self.pki_config.add_section(section) + self.pki_config.set(section, key, value) + self.flatten_master_dict() + + if section != "DEFAULT" and not config.user_config.has_section(section): + config.user_config.add_section(section) + config.user_config.set(section, key, value) + + + def print_text(self, message): + print ' ' * self.indent + message + + def read_text(self, message, + section=None, key=None, default=None, + options=None, sign=':', allowEmpty=True, caseSensitive=True): + + if default is None and key is not None: + default = self.pki_master_dict[key] + if default: + message = message + ' [' + default + ']' + message = ' ' * self.indent + message + sign + ' ' + + done = False + while not done: + value = raw_input(message) + value = value.strip() + + if len(value) == 0: # empty value + if allowEmpty: + value = default + done = True + break + + else: # non-empty value + if options is not None: + for v in options: + if caseSensitive: + if v == value: + done = True + break + else: + if v.lower() == value.lower(): + done = True + break + else: + done = True + break + + value = value.replace("%", "%%") + if section: + self.set_property(section, key, value) + + return value + + + def read_password(self, message, section=None, key=None, + verifyMessage=None): + message = ' ' * self.indent + message + ': ' + if verifyMessage is not None: + verifyMessage = ' ' * self.indent + verifyMessage + ': ' + + while True: + password = '' + while len(password) == 0: + password = getpass.getpass(prompt=message) + + if verifyMessage is not None: + verification = '' + while len(verification) == 0: + verification = getpass.getpass(prompt=verifyMessage) + + if password != verification: + self.print_text('Passwords do not match.') + continue + + break + + password = password.replace("%", "%%") + if section: + self.set_property(section, key, password) + + return password + + def read_pki_configuration_file(self): + "Read configuration file sections into dictionaries" + rv = 0 + try: + if config.user_deployment_cfg: + print 'Loading deployment configuration from ' + config.user_deployment_cfg + '.' + self.pki_config.read([config.user_deployment_cfg]) + config.user_config.read([config.user_deployment_cfg]) + + except ConfigParser.ParsingError, err: + print err + rv = err + return rv + + + def flatten_master_dict(self): + self.pki_master_dict.update(__name__="PKI Master Dictionary") + + default_dict = dict(self.pki_config.items('DEFAULT')) + default_dict[0] = None + self.pki_master_dict.update(default_dict) + + web_server_dict = None + if config.pki_subsystem in config.PKI_TOMCAT_SUBSYSTEMS: + if self.pki_config.has_section('Tomcat'): + web_server_dict = dict(self.pki_config.items('Tomcat')) + else: + if self.pki_config.has_section('Apache'): + web_server_dict = dict(self.pki_config.items('Apache')) + + if web_server_dict: + web_server_dict[0] = None + self.pki_master_dict.update(web_server_dict) + + if self.pki_config.has_section(config.pki_subsystem): + subsystem_dict = dict(self.pki_config.items(config.pki_subsystem)) + subsystem_dict[0] = None + self.pki_master_dict.update(subsystem_dict) + + + def ds_connect(self): + + hostname = self.pki_master_dict['pki_ds_hostname'] + + if config.str2bool(self.pki_master_dict['pki_ds_secure_connection']): + protocol = 'ldaps' + port = self.pki_master_dict['pki_ds_ldaps_port'] + else: + protocol = 'ldap' + port = self.pki_master_dict['pki_ds_ldap_port'] + + self.ds_connection = ldap.initialize(protocol + '://' + hostname + ':' + port) + self.ds_connection.search_s('', ldap.SCOPE_BASE) + + def ds_bind(self): + self.ds_connection.simple_bind_s( + self.pki_master_dict['pki_ds_bind_dn'], + self.pki_master_dict['pki_ds_password']) + + def ds_base_dn_exists(self): + try: + results = self.ds_connection.search_s( + self.pki_master_dict['pki_ds_base_dn'], + ldap.SCOPE_BASE) + + if results is None or len(results) == 0: + return False + + return True + + except ldap.NO_SUCH_OBJECT: + return False + + def ds_close(self): + self.ds_connection.unbind_s() + + def sd_connect(self): + self.sd_connection = pki.client.PKIConnection( + protocol='https', + hostname=self.pki_master_dict['pki_security_domain_hostname'], + port=self.pki_master_dict['pki_security_domain_https_port'], + subsystem='ca') + + def sd_get_info(self): + sd = pki.system.SecurityDomainClient(self.sd_connection) + try: + info = sd.getSecurityDomainInfo() + except requests.exceptions.HTTPError as e: + config.pki_log.info( + "unable to access security domain through REST interface. " + \ + "Trying old interface. " + str(e), + extra=config.PKI_INDENTATION_LEVEL_2) + info = sd.getOldSecurityDomainInfo() + return info + + def sd_authenticate(self): + self.sd_connection.authenticate( + self.pki_master_dict['pki_security_domain_user'], + self.pki_master_dict['pki_security_domain_password']) + + account = pki.account.AccountClient(self.sd_connection) + try: + account.login() + account.logout() + except requests.exceptions.HTTPError as e: + code = e.response.status_code + if code == 404 or code == 501: + config.pki_log.warning( + "unable to validate security domain user/password " + \ + "through REST interface. Interface not available", + extra=config.PKI_INDENTATION_LEVEL_2) + else: + raise + + def compose_pki_master_dictionary(self): + "Create a single master PKI dictionary from the sectional dictionaries" + try: + # 'pkispawn'/'pkidestroy' name/value pairs + self.pki_master_dict['pki_deployment_executable'] = \ + config.pki_deployment_executable + self.pki_master_dict['pki_install_time'] = config.pki_install_time + self.pki_master_dict['pki_timestamp'] = config.pki_timestamp + self.pki_master_dict['pki_certificate_timestamp'] = \ + config.pki_certificate_timestamp + self.pki_master_dict['pki_architecture'] = config.pki_architecture + self.pki_master_dict['pki_default_deployment_cfg'] = config.default_deployment_cfg + self.pki_master_dict['pki_user_deployment_cfg'] = config.user_deployment_cfg + self.pki_master_dict['pki_deployed_instance_name'] = \ + config.pki_deployed_instance_name + # Generate random 'pin's for use as security database passwords + # and add these to the "sensitive" key value pairs read in from + # the configuration file + pin_low = 100000000000 + pin_high = 999999999999 + self.pki_master_dict['pki_pin'] = \ + random.randint(pin_low, pin_high) + self.pki_master_dict['pki_client_pin'] = \ + random.randint(pin_low, pin_high) + + self.flatten_master_dict() + + pkilogging.sensitive_parameters = self.pki_master_dict['sensitive_parameters'].split() + + # PKI Target (slot substitution) name/value pairs + self.pki_master_dict['pki_target_cs_cfg'] = \ + os.path.join( + self.pki_master_dict['pki_subsystem_configuration_path'], + "CS.cfg") + self.pki_master_dict['pki_target_registry'] = \ + os.path.join(self.pki_master_dict['pki_instance_registry_path'], + self.pki_master_dict['pki_instance_name']) + if self.pki_master_dict['pki_subsystem'] == "CA" and\ + config.str2bool(self.pki_master_dict['pki_external_step_two']): + # Use the 'pki_one_time_pin' established during the setup of + # External CA Step 1 + if os.path.exists(self.pki_master_dict['pki_target_cs_cfg'])\ + and\ + os.path.isfile(self.pki_master_dict['pki_target_cs_cfg']): + cs_cfg = self.read_simple_configuration_file( + self.pki_master_dict['pki_target_cs_cfg']) + self.pki_master_dict['pki_one_time_pin'] = \ + cs_cfg.get('preop.pin') + else: + config.pki_log.error(log.PKI_FILE_MISSING_OR_NOT_A_FILE_1, + self.pki_master_dict['pki_target_cs_cfg'], + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception(log.PKI_FILE_MISSING_OR_NOT_A_FILE_1) + else: + # Generate a one-time pin to be used prior to configuration + # and add this to the "sensitive" key value pairs read in from + # the configuration file + self.pki_master_dict['pki_one_time_pin'] = \ + ''.join(random.choice(string.ascii_letters + string.digits)\ + for x in range(20)) + if self.pki_master_dict['pki_subsystem'] in\ + config.PKI_TOMCAT_SUBSYSTEMS: + self.pki_master_dict['pki_target_catalina_properties'] = \ + os.path.join( + self.pki_master_dict['pki_instance_configuration_path'], + "catalina.properties") + self.pki_master_dict['pki_target_servercertnick_conf'] = \ + os.path.join( + self.pki_master_dict['pki_instance_configuration_path'], + "serverCertNick.conf") + self.pki_master_dict['pki_target_server_xml'] = \ + os.path.join( + self.pki_master_dict['pki_instance_configuration_path'], + "server.xml") + self.pki_master_dict['pki_target_context_xml'] = \ + os.path.join( + self.pki_master_dict['pki_instance_configuration_path'], + "context.xml") + self.pki_master_dict['pki_target_tomcat_conf_instance_id'] = \ + self.pki_master_dict['pki_root_prefix'] + \ + "/etc/sysconfig/" + \ + self.pki_master_dict['pki_instance_name'] + self.pki_master_dict['pki_target_tomcat_conf'] = \ + os.path.join( + self.pki_master_dict['pki_instance_configuration_path'], + "tomcat.conf") + # in-place slot substitution name/value pairs + self.pki_master_dict['pki_target_velocity_properties'] = \ + os.path.join( + self.pki_master_dict['pki_tomcat_webapps_subsystem_path'], + "WEB-INF", + "velocity.properties") + self.pki_master_dict['pki_target_subsystem_web_xml'] = \ + os.path.join( + self.pki_master_dict['pki_tomcat_webapps_subsystem_path'], + "WEB-INF", + "web.xml") + self.pki_master_dict['pki_target_subsystem_web_xml_orig'] = \ + os.path.join( + self.pki_master_dict['pki_tomcat_webapps_subsystem_path'], + "WEB-INF", + "web.xml.orig") + # subystem-specific slot substitution name/value pairs + if self.pki_master_dict['pki_subsystem'] == "CA": + self.pki_master_dict['pki_target_flatfile_txt'] = \ + os.path.join(self.pki_master_dict\ + ['pki_subsystem_configuration_path'], + "flatfile.txt") + self.pki_master_dict['pki_target_proxy_conf'] = \ + os.path.join(self.pki_master_dict\ + ['pki_subsystem_configuration_path'], + "proxy.conf") + self.pki_master_dict['pki_target_registry_cfg'] = \ + os.path.join(self.pki_master_dict\ + ['pki_subsystem_configuration_path'], + "registry.cfg") + # '*.profile' + self.pki_master_dict['pki_target_admincert_profile'] = \ + os.path.join(self.pki_master_dict\ + ['pki_subsystem_configuration_path'], + "adminCert.profile") + self.pki_master_dict['pki_target_caauditsigningcert_profile']\ + = os.path.join(self.pki_master_dict\ + ['pki_subsystem_configuration_path'], + "caAuditSigningCert.profile") + self.pki_master_dict['pki_target_cacert_profile'] = \ + os.path.join(self.pki_master_dict\ + ['pki_subsystem_configuration_path'], + "caCert.profile") + self.pki_master_dict['pki_target_caocspcert_profile'] = \ + os.path.join(self.pki_master_dict\ + ['pki_subsystem_configuration_path'], + "caOCSPCert.profile") + self.pki_master_dict['pki_target_servercert_profile'] = \ + os.path.join(self.pki_master_dict\ + ['pki_subsystem_configuration_path'], + "serverCert.profile") + self.pki_master_dict['pki_target_subsystemcert_profile'] = \ + os.path.join(self.pki_master_dict\ + ['pki_subsystem_configuration_path'], + "subsystemCert.profile") + # in-place slot substitution name/value pairs + self.pki_master_dict['pki_target_profileselect_template'] = \ + os.path.join( + self.pki_master_dict\ + ['pki_tomcat_webapps_subsystem_path'], + "ee", + self.pki_master_dict['pki_subsystem'].lower(), + "ProfileSelect.template") + elif self.pki_master_dict['pki_subsystem'] == "KRA": + # '*.profile' + self.pki_master_dict['pki_target_servercert_profile'] = \ + os.path.join(self.pki_master_dict\ + ['pki_subsystem_configuration_path'], + "serverCert.profile") + self.pki_master_dict['pki_target_storagecert_profile'] = \ + os.path.join(self.pki_master_dict\ + ['pki_subsystem_configuration_path'], + "storageCert.profile") + self.pki_master_dict['pki_target_subsystemcert_profile'] = \ + os.path.join(self.pki_master_dict\ + ['pki_subsystem_configuration_path'], + "subsystemCert.profile") + self.pki_master_dict['pki_target_transportcert_profile'] = \ + os.path.join(self.pki_master_dict\ + ['pki_subsystem_configuration_path'], + "transportCert.profile") + # Slot assignment name/value pairs + # NOTE: Master key == Slots key; Master value ==> Slots value + self.pki_master_dict['PKI_INSTANCE_NAME_SLOT'] = \ + self.pki_master_dict['pki_instance_name'] + self.pki_master_dict['PKI_INSTANCE_INITSCRIPT_SLOT'] = \ + os.path.join(self.pki_master_dict['pki_instance_path'], + self.pki_master_dict['pki_instance_name']) + self.pki_master_dict['PKI_REGISTRY_FILE_SLOT'] = \ + os.path.join(self.pki_master_dict['pki_subsystem_registry_path'], + self.pki_master_dict['pki_instance_name']) + if self.pki_master_dict['pki_subsystem'] in\ + config.PKI_APACHE_SUBSYSTEMS: + self.pki_master_dict['FORTITUDE_APACHE_SLOT'] = None + self.pki_master_dict['FORTITUDE_AUTH_MODULES_SLOT'] = None + self.pki_master_dict['FORTITUDE_DIR_SLOT'] = None + self.pki_master_dict['FORTITUDE_LIB_DIR_SLOT'] = None + self.pki_master_dict['FORTITUDE_MODULE_SLOT'] = None + self.pki_master_dict['FORTITUDE_NSS_MODULES_SLOT'] = None + self.pki_master_dict['HTTPD_CONF_SLOT'] = None + self.pki_master_dict['LIB_PREFIX_SLOT'] = None + self.pki_master_dict['NON_CLIENTAUTH_SECURE_PORT_SLOT'] = None + self.pki_master_dict['NSS_CONF_SLOT'] = None + self.pki_master_dict['OBJ_EXT_SLOT'] = None + self.pki_master_dict['PKI_LOCKDIR_SLOT'] = \ + os.path.join("/var/lock/pki", + "apache") + self.pki_master_dict['PKI_PIDDIR_SLOT'] = \ + os.path.join("/var/run/pki", + "apache") + self.pki_master_dict['PKI_WEB_SERVER_TYPE_SLOT'] = "apache" + self.pki_master_dict['PORT_SLOT'] = None + self.pki_master_dict['PROCESS_ID_SLOT'] = None + self.pki_master_dict['REQUIRE_CFG_PL_SLOT'] = None + self.pki_master_dict['SECURE_PORT_SLOT'] = None + self.pki_master_dict['SECURITY_LIBRARIES_SLOT'] = None + self.pki_master_dict['PKI_HOSTNAME_SLOT'] = None + self.pki_master_dict['SERVER_ROOT_SLOT'] = None + self.pki_master_dict['SYSTEM_LIBRARIES_SLOT'] = None + self.pki_master_dict['SYSTEM_USER_LIBRARIES_SLOT'] = None + self.pki_master_dict['TMP_DIR_SLOT'] = None + self.pki_master_dict['TPS_DIR_SLOT'] = None + elif self.pki_master_dict['pki_subsystem'] in\ + config.PKI_TOMCAT_SUBSYSTEMS: + self.pki_master_dict['INSTALL_TIME_SLOT'] = \ + self.pki_master_dict['pki_install_time'] + self.pki_master_dict['PKI_ADMIN_SECURE_PORT_SLOT'] = \ + self.pki_master_dict['pki_https_port'] + self.pki_master_dict\ + ['PKI_ADMIN_SECURE_PORT_CONNECTOR_NAME_SLOT'] = \ + "Unused" + self.pki_master_dict\ + ['PKI_ADMIN_SECURE_PORT_SERVER_COMMENT_SLOT'] = \ + "" + self.pki_master_dict['PKI_AGENT_CLIENTAUTH_SLOT'] = \ + "want" + self.pki_master_dict['PKI_AGENT_SECURE_PORT_SLOT'] = \ + self.pki_master_dict['pki_https_port'] + self.pki_master_dict['PKI_AJP_PORT_SLOT'] = \ + self.pki_master_dict['pki_ajp_port'] + self.pki_master_dict['PKI_AJP_REDIRECT_PORT_SLOT'] = \ + self.pki_master_dict['pki_https_port'] + self.pki_master_dict['PKI_CA_HOSTNAME_SLOT'] = \ + self.pki_master_dict['pki_ca_hostname'] + self.pki_master_dict['PKI_CA_PORT_SLOT'] = \ + self.pki_master_dict['pki_ca_port'] + self.pki_master_dict['PKI_CERT_DB_PASSWORD_SLOT'] = \ + self.pki_master_dict['pki_pin'] + self.pki_master_dict['PKI_CFG_PATH_NAME_SLOT'] = \ + self.pki_master_dict['pki_target_cs_cfg'] + self.pki_master_dict\ + ['PKI_CLOSE_SEPARATE_PORTS_SERVER_COMMENT_SLOT'] = \ + "-->" + self.pki_master_dict\ + ['PKI_CLOSE_SEPARATE_PORTS_WEB_COMMENT_SLOT'] = \ + "-->" + self.pki_master_dict['PKI_EE_SECURE_CLIENT_AUTH_PORT_SLOT'] = \ + self.pki_master_dict['pki_https_port'] + self.pki_master_dict\ + ['PKI_EE_SECURE_CLIENT_AUTH_PORT_CONNECTOR_NAME_SLOT'] = \ + "Unused" + self.pki_master_dict\ + ['PKI_EE_SECURE_CLIENT_AUTH_PORT_SERVER_COMMENT_SLOT'] = \ + "" + self.pki_master_dict['PKI_EE_SECURE_CLIENT_AUTH_PORT_UI_SLOT'] = \ + self.pki_master_dict['pki_https_port'] + self.pki_master_dict['PKI_EE_SECURE_PORT_SLOT'] = \ + self.pki_master_dict['pki_https_port'] + self.pki_master_dict['PKI_EE_SECURE_PORT_CONNECTOR_NAME_SLOT'] = \ + "Unused" + self.pki_master_dict['PKI_EE_SECURE_PORT_SERVER_COMMENT_SLOT'] = \ + "" + self.pki_master_dict['PKI_GROUP_SLOT'] = \ + self.pki_master_dict['pki_group'] + self.pki_master_dict['PKI_INSTANCE_PATH_SLOT'] = \ + self.pki_master_dict['pki_instance_path'] + self.pki_master_dict['PKI_INSTANCE_ROOT_SLOT'] = \ + self.pki_master_dict['pki_path'] + self.pki_master_dict['PKI_LOCKDIR_SLOT'] = \ + os.path.join("/var/lock/pki", + "tomcat") + self.pki_master_dict['PKI_HOSTNAME_SLOT'] = \ + self.pki_master_dict['pki_hostname'] + self.pki_master_dict\ + ['PKI_OPEN_SEPARATE_PORTS_SERVER_COMMENT_SLOT'] = \ + "" + self.pki_master_dict['PKI_CLOSE_ENABLE_PROXY_COMMENT_SLOT'] = \ + "-->" + self.pki_master_dict['PKI_PROXY_SECURE_PORT_SLOT'] = "" + self.pki_master_dict['PKI_PROXY_UNSECURE_PORT_SLOT'] = "" + self.pki_master_dict['PKI_OPEN_AJP_PORT_COMMENT_SLOT'] = \ + "" + self.pki_master_dict['PKI_SECURITY_MANAGER_SLOT'] = \ + self.pki_master_dict['pki_security_manager'] + self.pki_master_dict['PKI_SERVER_XML_CONF_SLOT'] = \ + self.pki_master_dict['pki_target_server_xml'] + self.pki_master_dict['PKI_SSL_SERVER_NICKNAME_SLOT'] = \ + self.pki_master_dict['pki_ssl_server_nickname'] + self.pki_master_dict['PKI_SUBSYSTEM_TYPE_SLOT'] = \ + self.pki_master_dict['pki_subsystem'].lower() + self.pki_master_dict['PKI_SYSTEMD_SERVICENAME_SLOT'] = \ + "pki-tomcatd" + "@" + \ + self.pki_master_dict['pki_instance_name'] + ".service" + self.pki_master_dict['PKI_UNSECURE_PORT_SLOT'] = \ + self.pki_master_dict['pki_http_port'] + self.pki_master_dict['PKI_UNSECURE_PORT_CONNECTOR_NAME_SLOT'] = \ + "Unsecure" + self.pki_master_dict['PKI_UNSECURE_PORT_SERVER_COMMENT_SLOT'] = \ + "" + self.pki_master_dict['PKI_USER_SLOT'] = \ + self.pki_master_dict['pki_user'] + self.pki_master_dict['PKI_WEB_SERVER_TYPE_SLOT'] = \ + "tomcat" + self.pki_master_dict['PKI_WEBAPPS_NAME_SLOT'] = \ + "webapps" + self.pki_master_dict['TOMCAT_CFG_SLOT'] = \ + self.pki_master_dict['pki_target_tomcat_conf'] + self.pki_master_dict['TOMCAT_INSTANCE_COMMON_LIB_SLOT'] = \ + os.path.join( + self.pki_master_dict['pki_tomcat_common_lib_path'], + "*.jar") + self.pki_master_dict['TOMCAT_LOG_DIR_SLOT'] = \ + self.pki_master_dict['pki_instance_log_path'] + self.pki_master_dict['TOMCAT_PIDFILE_SLOT'] = \ + "/var/run/pki/tomcat/" + self.pki_master_dict['pki_instance_name'] + ".pid" + self.pki_master_dict['TOMCAT_SERVER_PORT_SLOT'] = \ + self.pki_master_dict['pki_tomcat_server_port'] + self.pki_master_dict['TOMCAT_SSL2_CIPHERS_SLOT'] = \ + "-SSL2_RC4_128_WITH_MD5," + \ + "-SSL2_RC4_128_EXPORT40_WITH_MD5," + \ + "-SSL2_RC2_128_CBC_WITH_MD5," + \ + "-SSL2_RC2_128_CBC_EXPORT40_WITH_MD5," + \ + "-SSL2_DES_64_CBC_WITH_MD5," + \ + "-SSL2_DES_192_EDE3_CBC_WITH_MD5" + self.pki_master_dict['TOMCAT_SSL3_CIPHERS_SLOT'] = \ + "-SSL3_FORTEZZA_DMS_WITH_NULL_SHA," + \ + "-SSL3_FORTEZZA_DMS_WITH_RC4_128_SHA," + \ + "+SSL3_RSA_WITH_RC4_128_SHA," + \ + "-SSL3_RSA_EXPORT_WITH_RC4_40_MD5," + \ + "+SSL3_RSA_WITH_3DES_EDE_CBC_SHA," + \ + "+SSL3_RSA_WITH_DES_CBC_SHA," + \ + "-SSL3_RSA_EXPORT_WITH_RC2_CBC_40_MD5," + \ + "-SSL3_FORTEZZA_DMS_WITH_FORTEZZA_CBC_SHA," + \ + "-SSL_RSA_FIPS_WITH_DES_CBC_SHA," + \ + "+SSL_RSA_FIPS_WITH_3DES_EDE_CBC_SHA," + \ + "-SSL3_RSA_WITH_NULL_MD5," + \ + "-TLS_RSA_EXPORT1024_WITH_RC4_56_SHA," + \ + "-TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA," + \ + "+TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA" + self.pki_master_dict['TOMCAT_SSL_OPTIONS_SLOT'] = \ + "ssl2=true," + \ + "ssl3=true," + \ + "tls=true" + self.pki_master_dict['TOMCAT_TLS_CIPHERS_SLOT'] = \ + "-TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA," + \ + "-TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA," + \ + "+TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA," + \ + "+TLS_ECDH_RSA_WITH_AES_128_CBC_SHA," + \ + "+TLS_ECDH_RSA_WITH_AES_256_CBC_SHA," + \ + "-TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA," + \ + "+TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA," + \ + "+TLS_RSA_WITH_3DES_EDE_CBC_SHA," + \ + "+TLS_RSA_WITH_AES_128_CBC_SHA," + \ + "+TLS_RSA_WITH_AES_256_CBC_SHA," + \ + "+TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA," + \ + "+TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA," + \ + "-TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA," + \ + "-TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA," + \ + "-TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA," + \ + "+TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA," + \ + "+TLS_DHE_DSS_WITH_AES_128_CBC_SHA," + \ + "+TLS_DHE_DSS_WITH_AES_256_CBC_SHA," + \ + "+TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA," + \ + "+TLS_DHE_RSA_WITH_AES_128_CBC_SHA," + \ + "+TLS_DHE_RSA_WITH_AES_256_CBC_SHA" + if self.pki_master_dict['pki_subsystem'] == "CA": + self.pki_master_dict['PKI_ENABLE_RANDOM_SERIAL_NUMBERS'] = \ + self.pki_master_dict\ + ['pki_random_serial_numbers_enable'].lower() + # Shared Apache/Tomcat NSS security database name/value pairs + self.pki_master_dict['pki_shared_pfile'] = \ + os.path.join( + self.pki_master_dict['pki_instance_configuration_path'], + "pfile") + self.pki_master_dict['pki_shared_password_conf'] = \ + os.path.join( + self.pki_master_dict['pki_instance_configuration_path'], + "password.conf") + self.pki_master_dict['pki_cert_database'] = \ + os.path.join(self.pki_master_dict['pki_database_path'], + "cert8.db") + self.pki_master_dict['pki_key_database'] = \ + os.path.join(self.pki_master_dict['pki_database_path'], + "key3.db") + self.pki_master_dict['pki_secmod_database'] = \ + os.path.join(self.pki_master_dict['pki_database_path'], + "secmod.db") + self.pki_master_dict['pki_self_signed_token'] = "internal" + self.pki_master_dict['pki_self_signed_nickname'] = \ + self.pki_master_dict['pki_ssl_server_nickname'] + self.pki_master_dict['pki_self_signed_subject'] = \ + "cn=" + self.pki_master_dict['pki_hostname'] + "," + \ + "o=" + self.pki_master_dict['pki_certificate_timestamp'] + self.pki_master_dict['pki_self_signed_serial_number'] = 0 + self.pki_master_dict['pki_self_signed_validity_period'] = 12 + self.pki_master_dict['pki_self_signed_issuer_name'] = \ + "cn=" + self.pki_master_dict['pki_hostname'] + "," + \ + "o=" + self.pki_master_dict['pki_certificate_timestamp'] + self.pki_master_dict['pki_self_signed_trustargs'] = "CTu,CTu,CTu" + self.pki_master_dict['pki_self_signed_noise_file'] = \ + os.path.join( + self.pki_master_dict['pki_subsystem_configuration_path'], + "noise") + self.pki_master_dict['pki_self_signed_noise_bytes'] = 1024 + # Shared Apache/Tomcat NSS security database convenience symbolic links + self.pki_master_dict\ + ['pki_subsystem_configuration_password_conf_link'] = \ + os.path.join( + self.pki_master_dict['pki_subsystem_configuration_path'], + "password.conf") + + if not len(self.pki_master_dict['pki_client_database_password']): + # use randomly generated client 'pin' + self.pki_master_dict['pki_client_database_password'] = \ + str(self.pki_master_dict['pki_client_pin']) + + # Configuration scriptlet + # 'Security Domain' Configuration name/value pairs + # 'Subsystem Name' Configuration name/value pairs + # 'Token' Configuration name/value pairs + # + # Apache - [RA] + # Tomcat - [CA], [KRA], [OCSP], [TKS], [TPS] + # - [CA Clone], [KRA Clone], [OCSP Clone], [TKS Clone], [TPS Clone] + # - [External CA] + # - [Subordinate CA] + # + # The following variables are defined below: + # + # self.pki_master_dict['pki_security_domain_type'] + # self.pki_master_dict['pki_security_domain_uri'] + # + # The following variables are established via the specified PKI + # deployment configuration file and are NOT redefined below: + # + # self.pki_master_dict['pki_clone_pkcs12_password'] + # self.pki_master_dict['pki_security_domain_password'] + # self.pki_master_dict['pki_token_password'] + # self.pki_master_dict['pki_clone_pkcs12_path'] + # self.pki_master_dict['pki_clone_uri'] + # self.pki_master_dict['pki_security_domain_https_port'] + # self.pki_master_dict['pki_token_name'] + # + # The following variables are established via the specified PKI + # deployment configuration file and potentially overridden below: + # + # self.pki_master_dict['pki_security_domain_user'] + # self.pki_master_dict['pki_issuing_ca'] + # + + # if security domain user is not defined + if not len(self.pki_master_dict['pki_security_domain_user']): + + # use the CA admin uid if it's defined + if self.pki_config.has_option('CA', 'pki_admin_uid') and\ + len(self.pki_config.get('CA', 'pki_admin_uid')) > 0: + self.pki_master_dict['pki_security_domain_user'] = \ + self.pki_config.get('CA', 'pki_admin_uid') + + # or use the Default admin uid if it's defined + elif self.pki_config.has_option('DEFAULT', 'pki_admin_uid') and\ + len(self.pki_config.get('DEFAULT', 'pki_admin_uid')) > 0: + self.pki_master_dict['pki_security_domain_user'] = \ + self.pki_config.get('DEFAULT', 'pki_admin_uid') + + # otherwise use the default CA admin uid + else: + self.pki_master_dict['pki_security_domain_user'] = "caadmin" + + if config.pki_subsystem != "CA" or\ + config.str2bool(self.pki_master_dict['pki_clone']) or\ + config.str2bool(self.pki_master_dict['pki_subordinate']): + # PKI KRA, PKI OCSP, PKI RA, PKI TKS, PKI TPS, + # CA Clone, KRA Clone, OCSP Clone, TKS Clone, TPS Clone, or + # Subordinate CA + self.pki_master_dict['pki_security_domain_type'] = "existing" + self.pki_master_dict['pki_security_domain_uri'] = \ + "https" + "://" + \ + self.pki_master_dict['pki_security_domain_hostname'] + ":" + \ + self.pki_master_dict['pki_security_domain_https_port'] + + elif config.str2bool(self.pki_master_dict['pki_external']): + # External CA + self.pki_master_dict['pki_security_domain_type'] = "new" + if not len(self.pki_master_dict['pki_issuing_ca']): + self.pki_master_dict['pki_issuing_ca'] = "External CA" + else: + # PKI CA + self.pki_master_dict['pki_security_domain_type'] = "new" + + # 'External CA' Configuration name/value pairs + # + # Tomcat - [External CA] + # + # The following variables are established via the specified PKI + # deployment configuration file and are NOT redefined below: + # + # self.pki_master_dict['pki_external_ca_cert_chain_path'] + # self.pki_master_dict['pki_external_ca_cert_path'] + # self.pki_master_dict['pki_external_csr_path'] + # self.pki_master_dict['pki_external_step_two'] + # + + # 'Backup' Configuration name/value pairs + # + # Apache - [RA] + # Tomcat - [CA], [KRA], [OCSP], [TKS], [TPS] + # - [External CA] + # - [Subordinate CA] + # + # The following variables are established via the specified PKI + # deployment configuration file and are NOT redefined below: + # + # self.pki_master_dict['pki_backup_password'] + # self.pki_master_dict['pki_backup_keys'] + # + if config.str2bool(self.pki_master_dict['pki_backup_keys']): + # NOTE: ALWAYS store the PKCS #12 backup keys file + # in with the NSS "server" security databases + self.pki_master_dict['pki_backup_keys_p12'] = \ + self.pki_master_dict['pki_database_path'] + "/" + \ + self.pki_master_dict['pki_subsystem'].lower() + "_" + \ + "backup" + "_" + "keys" + "." + "p12" + + self.pki_master_dict['pki_admin_profile_id'] = "caAdminCert" + + if not 'pki_import_admin_cert' in self.pki_master_dict: + self.pki_master_dict['pki_import_admin_cert'] = 'false' + + self.pki_master_dict['pki_ca_signing_tag'] = "signing" + if self.pki_master_dict['pki_subsystem'] == "CA": + self.pki_master_dict['pki_ocsp_signing_tag'] = "ocsp_signing" + elif self.pki_master_dict['pki_subsystem'] == "OCSP": + self.pki_master_dict['pki_ocsp_signing_tag'] = "signing" + self.pki_master_dict['pki_ssl_server_tag'] = "sslserver" + self.pki_master_dict['pki_subsystem_tag'] = "subsystem" + self.pki_master_dict['pki_audit_signing_tag'] = "audit_signing" + self.pki_master_dict['pki_transport_tag'] = "transport" + self.pki_master_dict['pki_storage_tag'] = "storage" + + # Finalization name/value pairs + self.pki_master_dict['pki_default_deployment_cfg_replica'] = \ + os.path.join(self.pki_master_dict['pki_subsystem_registry_path'], + config.DEFAULT_DEPLOYMENT_CONFIGURATION) + self.pki_master_dict['pki_user_deployment_cfg_replica'] = \ + os.path.join(self.pki_master_dict['pki_subsystem_registry_path'], + config.USER_DEPLOYMENT_CONFIGURATION) + self.pki_master_dict['pki_user_deployment_cfg_spawn_archive'] = \ + self.pki_master_dict['pki_subsystem_archive_log_path'] + "/" + \ + "spawn" + "_" + \ + config.USER_DEPLOYMENT_CONFIGURATION + "." + \ + self.pki_master_dict['pki_timestamp'] + self.pki_master_dict['pki_manifest'] = \ + self.pki_master_dict['pki_subsystem_registry_path'] + "/" + \ + "manifest" + self.pki_master_dict['pki_manifest_spawn_archive'] = \ + self.pki_master_dict['pki_subsystem_archive_log_path'] + "/" + \ + "spawn" + "_" + "manifest" + "." + \ + self.pki_master_dict['pki_timestamp'] + # Construct the configuration URL containing the one-time pin + # and add this to the "sensitive" key value pairs read in from + # the configuration file + # + # NOTE: This is the one and only parameter containing a sensitive + # parameter that may be stored in a log file and displayed + # to the screen. + # + self.pki_master_dict['pki_configuration_url'] = \ + "https://{}:{}/{}/{}?pin={}".format( + self.pki_master_dict['pki_hostname'], + self.pki_master_dict['pki_https_port'], + self.pki_master_dict['pki_subsystem'].lower(), + "admin/console/config/login", + self.pki_master_dict['pki_one_time_pin']) + # Compose this "systemd" execution management command + if self.pki_master_dict['pki_subsystem'] in\ + config.PKI_APACHE_SUBSYSTEMS: + self.pki_master_dict['pki_registry_initscript_command'] = \ + "systemctl" + " " + \ + "restart" + " " + \ + "pki-apached" + "@" + \ + self.pki_master_dict['pki_instance_name'] + "." + "service" + elif self.pki_master_dict['pki_subsystem'] in\ + config.PKI_TOMCAT_SUBSYSTEMS: + self.pki_master_dict['pki_registry_initscript_command'] = \ + "systemctl" + " " + \ + "restart" + " " + \ + "pki-tomcatd" + "@" + \ + self.pki_master_dict['pki_instance_name'] + "." + "service" + except OSError as exc: + config.pki_log.error(log.PKI_OSERROR_1, exc, + extra=config.PKI_INDENTATION_LEVEL_2) + raise + except KeyError as err: + config.pki_log.error(log.PKIHELPER_DICTIONARY_MASTER_MISSING_KEY_1, + err, extra=config.PKI_INDENTATION_LEVEL_2) + raise + return + + + def compose_pki_slots_dictionary(self): + """Read the slots configuration file to create + the appropriate PKI slots dictionary""" + rv = 0 + try: + parser = ConfigParser.ConfigParser() + # Make keys case-sensitive! + parser.optionxform = str + parser.read(config.PKI_DEPLOYMENT_SLOTS_CONFIGURATION_FILE) + # Slots configuration file name/value pairs + if config.pki_subsystem in config.PKI_APACHE_SUBSYSTEMS: + self.pki_slots_dict = dict(parser.items('Apache')) + elif config.pki_subsystem in config.PKI_TOMCAT_SUBSYSTEMS: + self.pki_slots_dict = dict(parser.items('Tomcat')) + except ConfigParser.ParsingError, err: + rv = err + return rv diff --git a/base/server/python/pki/server/deployment/pkiscriptlet.py b/base/server/python/pki/server/deployment/pkiscriptlet.py new file mode 100644 index 000000000..f37bb1c15 --- /dev/null +++ b/base/server/python/pki/server/deployment/pkiscriptlet.py @@ -0,0 +1,41 @@ +#!/usr/bin/python -t +# Authors: +# Matthew Harmsen +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Copyright (C) 2012 Red Hat, Inc. +# All rights reserved. +# + +# System Imports +import abc + + +# PKI Deployment Abstract Base PKI Scriptlet +class AbstractBasePkiScriptlet(object): + __metaclass__ = abc.ABCMeta + + # pylint: disable-msg=W0613 + @abc.abstractmethod + def spawn(self, deployer): + """Retrieve data from the specified PKI dictionary and + use it to install a new PKI instance.""" + return + # pylint: disable-msg=W0613 + @abc.abstractmethod + def destroy(self, deployer): + """Retrieve data from the specified PKI dictionary and + use it to destroy an existing PKI instance.""" + return diff --git a/base/server/python/pki/server/deployment/scriptlets/__init__.py b/base/server/python/pki/server/deployment/scriptlets/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/base/server/python/pki/server/deployment/scriptlets/configuration.py b/base/server/python/pki/server/deployment/scriptlets/configuration.py new file mode 100644 index 000000000..004d8c28d --- /dev/null +++ b/base/server/python/pki/server/deployment/scriptlets/configuration.py @@ -0,0 +1,140 @@ +#!/usr/bin/python -t +# Authors: +# Matthew Harmsen +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Copyright (C) 2012 Red Hat, Inc. +# All rights reserved. +# + +import json + +# PKI Deployment Imports +from .. import pkiconfig as config +from .. import pkimessages as log +from .. import pkiscriptlet +import pki.system +import pki.encoder + + +# PKI Deployment Configuration Scriptlet +class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet): + rv = 0 + + def spawn(self, deployer): + + if config.str2bool(deployer.master_dict['pki_skip_configuration']): + config.pki_log.info(log.SKIP_CONFIGURATION_SPAWN_1, __name__, + extra=config.PKI_INDENTATION_LEVEL_1) + return self.rv + config.pki_log.info(log.CONFIGURATION_SPAWN_1, __name__, + extra=config.PKI_INDENTATION_LEVEL_1) + + # Place "slightly" less restrictive permissions on + # the top-level client directory ONLY + deployer.directory.create(deployer.master_dict['pki_client_subsystem_dir'], + uid=0, gid=0, + perms=config.PKI_DEPLOYMENT_DEFAULT_CLIENT_DIR_PERMISSIONS) + # Since 'certutil' does NOT strip the 'token=' portion of + # the 'token=password' entries, create a client password file + # which ONLY contains the 'password' for the purposes of + # allowing 'certutil' to generate the security databases + deployer.password.create_password_conf( + deployer.master_dict['pki_client_password_conf'], + deployer.master_dict['pki_client_database_password'], pin_sans_token=True) + deployer.file.modify(deployer.master_dict['pki_client_password_conf'], + uid=0, gid=0) + # Similarly, create a simple password file containing the + # PKCS #12 password used when exporting the "Admin Certificate" + # into a PKCS #12 file + deployer.password.create_client_pkcs12_password_conf( + deployer.master_dict['pki_client_pkcs12_password_conf']) + deployer.file.modify(deployer.master_dict['pki_client_pkcs12_password_conf']) + deployer.directory.create(deployer.master_dict['pki_client_database_dir'], + uid=0, gid=0) + deployer.certutil.create_security_databases( + deployer.master_dict['pki_client_database_dir'], + deployer.master_dict['pki_client_cert_database'], + deployer.master_dict['pki_client_key_database'], + deployer.master_dict['pki_client_secmod_database'], + password_file=deployer.master_dict['pki_client_password_conf']) + deployer.symlink.create(deployer.master_dict['pki_systemd_service'], + deployer.master_dict['pki_systemd_service_link']) + + # Start/Restart this Apache/Tomcat PKI Process + if deployer.master_dict['pki_subsystem'] in config.PKI_APACHE_SUBSYSTEMS: + apache_instance_subsystems = \ + deployer.instance.apache_instance_subsystems() + if apache_instance_subsystems == 1: + deployer.systemd.start() + elif apache_instance_subsystems > 1: + deployer.systemd.restart() + elif deployer.master_dict['pki_subsystem'] in config.PKI_TOMCAT_SUBSYSTEMS: + # Optionally prepare to enable a java debugger + # (e. g. - 'eclipse'): + if config.str2bool(deployer.master_dict['pki_enable_java_debugger']): + config.prepare_for_an_external_java_debugger( + deployer.master_dict['pki_target_tomcat_conf_instance_id']) + tomcat_instance_subsystems = \ + len(deployer.instance.tomcat_instance_subsystems()) + if tomcat_instance_subsystems == 1: + deployer.systemd.start() + elif tomcat_instance_subsystems > 1: + deployer.systemd.restart() + + # wait for startup + status = deployer.instance.wait_for_startup(60) + if status == None: + config.pki_log.error("server failed to restart", + extra=config.PKI_INDENTATION_LEVEL_2) + raise Exception("server failed to restart") + + # Optionally wait for debugger to attach (e. g. - 'eclipse'): + if config.str2bool(deployer.master_dict['pki_enable_java_debugger']): + config.wait_to_attach_an_external_java_debugger() + + # Construct PKI Subsystem Configuration Data + data = None + if deployer.master_dict['pki_instance_type'] == "Apache": + if deployer.master_dict['pki_subsystem'] == "RA": + config.pki_log.info(log.PKI_CONFIG_NOT_YET_IMPLEMENTED_1, + deployer.master_dict['pki_subsystem'], + extra=config.PKI_INDENTATION_LEVEL_2) + return self.rv + elif deployer.master_dict['pki_instance_type'] == "Tomcat": + # CA, KRA, OCSP, TKS, or TPS + data = deployer.config_client.construct_pki_configuration_data() + + # Configure the substem + deployer.config_client.configure_pki_data( + json.dumps(data, cls=pki.encoder.CustomTypeEncoder)) + + return self.rv + + def destroy(self, deployer): + + config.pki_log.info(log.CONFIGURATION_DESTROY_1, __name__, + extra=config.PKI_INDENTATION_LEVEL_1) + if deployer.master_dict['pki_subsystem'] in config.PKI_APACHE_SUBSYSTEMS and\ + deployer.instance.apache_instance_subsystems() == 1: + if deployer.directory.exists(deployer.master_dict['pki_client_dir']): + deployer.directory.delete(deployer.master_dict['pki_client_dir']) + deployer.symlink.delete(deployer.master_dict['pki_systemd_service_link']) + elif deployer.master_dict['pki_subsystem'] in config.PKI_TOMCAT_SUBSYSTEMS and\ + len(deployer.instance.tomcat_instance_subsystems()) == 1: + if deployer.directory.exists(deployer.master_dict['pki_client_dir']): + deployer.directory.delete(deployer.master_dict['pki_client_dir']) + deployer.symlink.delete(deployer.master_dict['pki_systemd_service_link']) + return self.rv diff --git a/base/server/python/pki/server/deployment/scriptlets/finalization.py b/base/server/python/pki/server/deployment/scriptlets/finalization.py new file mode 100644 index 000000000..0573c24ef --- /dev/null +++ b/base/server/python/pki/server/deployment/scriptlets/finalization.py @@ -0,0 +1,106 @@ +#!/usr/bin/python -t +# Authors: +# Matthew Harmsen +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Copyright (C) 2012 Red Hat, Inc. +# All rights reserved. +# + +# PKI Deployment Imports +from .. import pkiconfig as config +from .. import pkimanifest as manifest +from .. import pkimessages as log +from .. import pkiscriptlet + + +# PKI Deployment Finalization Scriptlet +class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet): + rv = 0 + + def spawn(self, deployer): + + if deployer.master_dict['pki_subsystem'] == "CA" and\ + config.str2bool(deployer.master_dict['pki_external_step_two']): + # must check for 'External CA Step 2' installation PRIOR to + # 'pki_skip_installation' since this value has been set to true + # by the initialization scriptlet + pass + elif config.str2bool(deployer.master_dict['pki_skip_installation']): + config.pki_log.info(log.SKIP_FINALIZATION_SPAWN_1, __name__, + extra=config.PKI_INDENTATION_LEVEL_1) + return self.rv + 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.master_dict['pki_user_deployment_cfg_replica'], + deployer.master_dict['pki_user_deployment_cfg_spawn_archive']) + # Save a copy of the installation manifest file + config.pki_log.info(log.PKI_MANIFEST_MESSAGE_1, deployer.master_dict['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.master_dict['pki_manifest']) + manifest_file.write() + deployer.file.modify(deployer.master_dict['pki_manifest'], silent=True) + + # Also, for debugging/auditing purposes, save a timestamped copy of + # this installation manifest file + deployer.file.copy(deployer.master_dict['pki_manifest'], + deployer.master_dict['pki_manifest_spawn_archive']) + # Optionally, programmatically 'restart' the configured PKI instance + if config.str2bool(deployer.master_dict['pki_restart_configured_instance']): + deployer.systemd.restart() + # Optionally, 'purge' the entire temporary client infrastructure + # including the client NSS security databases and password files + # + # WARNING: If the PKCS #12 file containing the Admin Cert was + # placed under this infrastructure, it may accidentally + # be deleted! + # + if config.str2bool(deployer.master_dict['pki_client_database_purge']): + if deployer.directory.exists(deployer.master_dict['pki_client_subsystem_dir']): + deployer.directory.delete(deployer.master_dict['pki_client_subsystem_dir']) + # If instance has not been configured, print the + # configuration URL to the log + if config.str2bool(deployer.master_dict['pki_skip_configuration']): + deployer.configuration_file.log_configuration_url() + # Log final process messages + config.pki_log.info(log.PKISPAWN_END_MESSAGE_2, + deployer.master_dict['pki_subsystem'], + deployer.master_dict['pki_instance_name'], + extra=config.PKI_INDENTATION_LEVEL_0) + deployer.file.modify(deployer.master_dict['pki_spawn_log'], silent=True) + return self.rv + + def destroy(self, deployer): + + config.pki_log.info(log.FINALIZATION_DESTROY_1, __name__, + extra=config.PKI_INDENTATION_LEVEL_1) + deployer.file.modify(deployer.master_dict['pki_destroy_log'], silent=True) + # Start this Apache/Tomcat PKI Process + if deployer.master_dict['pki_subsystem'] in config.PKI_APACHE_SUBSYSTEMS and\ + deployer.instance.apache_instance_subsystems() >= 1: + deployer.systemd.start() + elif deployer.master_dict['pki_subsystem'] in config.PKI_TOMCAT_SUBSYSTEMS and\ + len(deployer.instance.tomcat_instance_subsystems()) >= 1: + deployer.systemd.start() + config.pki_log.info(log.PKIDESTROY_END_MESSAGE_2, + deployer.master_dict['pki_subsystem'], + deployer.master_dict['pki_instance_name'], + extra=config.PKI_INDENTATION_LEVEL_0) + return self.rv diff --git a/base/server/python/pki/server/deployment/scriptlets/infrastructure_layout.py b/base/server/python/pki/server/deployment/scriptlets/infrastructure_layout.py new file mode 100644 index 000000000..5427eebca --- /dev/null +++ b/base/server/python/pki/server/deployment/scriptlets/infrastructure_layout.py @@ -0,0 +1,114 @@ +#!/usr/bin/python -t +# Authors: +# Matthew Harmsen +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Copyright (C) 2012 Red Hat, Inc. +# All rights reserved. +# + +# PKI Deployment Imports +from .. import pkiconfig as config +from .. import pkimessages as log +from .. import pkiscriptlet + + +# PKI Deployment Top-Level Infrastructure Layout Scriptlet +class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet): + rv = 0 + + def spawn(self, deployer): + + if config.str2bool(deployer.master_dict['pki_skip_installation']): + config.pki_log.info(log.SKIP_ADMIN_DOMAIN_SPAWN_1, __name__, + extra=config.PKI_INDENTATION_LEVEL_1) + return self.rv + config.pki_log.info(log.ADMIN_DOMAIN_SPAWN_1, __name__, + extra=config.PKI_INDENTATION_LEVEL_1) + # NOTE: It was determined that since the "pkidestroy" command + # relies upon a symbolic link to a replica of the original + # deployment configuration file used by the + # "pkispawn" command of an instance, it is necessary to + # create any required instance and subsystem directories + # in this top-level "infrastructure_layout" scriptlet + # (rather than the "instance_layout" and "subsystem_layout" + # scriptlets) so that a copy of this configuration file can + # be saved, and the required symbolic link can be created. + # + # establish the top-level infrastructure, instance, and subsystem + # registry directories for storage of a copy of the original + # deployment configuration file used to spawn this instance, + # and save a copy of this file + deployer.directory.create(deployer.master_dict['pki_registry_path']) + deployer.directory.create(deployer.master_dict['pki_instance_type_registry_path']) + deployer.directory.create(deployer.master_dict['pki_instance_registry_path']) + deployer.directory.create(deployer.master_dict['pki_subsystem_registry_path']) + deployer.file.copy(deployer.master_dict['pki_default_deployment_cfg'], + deployer.master_dict['pki_default_deployment_cfg_replica']) + + print "Storing deployment configuration into " + deployer.master_dict['pki_user_deployment_cfg_replica'] + "." + + # Archive the user deployment configuration excluding the sensitive parameters + sensitive_parameters = deployer.master_dict['sensitive_parameters'].split() + sections = config.user_config.sections() + for s in sections: + for k in sensitive_parameters: + config.user_config.set(s, k, 'XXXXXXXX') + with open(deployer.master_dict['pki_user_deployment_cfg_replica'], 'w') as f: + config.user_config.write(f) + + # establish top-level infrastructure, instance, and subsystem + # base directories and create the "registry" symbolic link that + # the "pkidestroy" executable relies upon + deployer.directory.create(deployer.master_dict['pki_path']) + deployer.directory.create(deployer.master_dict['pki_instance_path']) + deployer.directory.create(deployer.master_dict['pki_subsystem_path']) + deployer.symlink.create(deployer.master_dict['pki_instance_registry_path'], + deployer.master_dict['pki_subsystem_registry_link']) + # + # NOTE: If "infrastructure_layout" scriptlet execution has been + # successfully executed to this point, the "pkidestroy" command + # may always be utilized to remove the entire infrastructure. + # + # no need to establish top-level infrastructure logs + # since it now stores 'pkispawn'/'pkidestroy' logs + # and will already exist + # deployer.directory.create(deployer.master_dict['pki_log_path']) + # establish top-level infrastructure configuration + if deployer.master_dict['pki_configuration_path'] != \ + config.PKI_DEPLOYMENT_CONFIGURATION_ROOT: + deployer.directory.create(deployer.master_dict['pki_configuration_path']) + return self.rv + + def destroy(self, deployer): + + config.pki_log.info(log.ADMIN_DOMAIN_DESTROY_1, __name__, + extra=config.PKI_INDENTATION_LEVEL_1) + # remove top-level infrastructure base + if deployer.master_dict['pki_subsystem'] in config.PKI_SUBSYSTEMS and\ + deployer.instance.pki_instance_subsystems() == 0: + # remove top-level infrastructure base + deployer.directory.delete(deployer.master_dict['pki_path']) + # do NOT remove top-level infrastructure logs + # since it now stores 'pkispawn'/'pkidestroy' logs + # deployer.directory.delete(deployer.master_dict['pki_log_path']) + # remove top-level infrastructure configuration + if deployer.directory.is_empty(deployer.master_dict['pki_configuration_path'])\ + and deployer.master_dict['pki_configuration_path'] != \ + config.PKI_DEPLOYMENT_CONFIGURATION_ROOT: + deployer.directory.delete(deployer.master_dict['pki_configuration_path']) + # remove top-level infrastructure registry + deployer.directory.delete(deployer.master_dict['pki_registry_path']) + return self.rv diff --git a/base/server/python/pki/server/deployment/scriptlets/initialization.py b/base/server/python/pki/server/deployment/scriptlets/initialization.py new file mode 100644 index 000000000..54349fc01 --- /dev/null +++ b/base/server/python/pki/server/deployment/scriptlets/initialization.py @@ -0,0 +1,113 @@ +#!/usr/bin/python -t +# Authors: +# Matthew Harmsen +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Copyright (C) 2012 Red Hat, Inc. +# All rights reserved. +# + +# PKI Deployment Imports +from .. import pkiconfig as config +from .. import pkimessages as log +from .. import pkiscriptlet + + +# PKI Deployment Initialization Scriptlet +class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet): + rv = 0 + + def spawn(self, deployer): + + # begin official logging + config.pki_log.info(log.PKISPAWN_BEGIN_MESSAGE_2, + deployer.master_dict['pki_subsystem'], + deployer.master_dict['pki_instance_name'], + extra=config.PKI_INDENTATION_LEVEL_0) + if config.str2bool(deployer.master_dict['pki_skip_installation']): + config.pki_log.info(log.SKIP_INITIALIZATION_SPAWN_1, __name__, + extra=config.PKI_INDENTATION_LEVEL_1) + return self.rv + else: + config.pki_log.info(log.INITIALIZATION_SPAWN_1, __name__, + extra=config.PKI_INDENTATION_LEVEL_1) + if deployer.master_dict['pki_subsystem'] == "CA" and\ + config.str2bool(deployer.master_dict['pki_external_step_two']): + # verify that this type of "subsystem" currently EXISTS + # for this "instance" (External CA Step 2) + deployer.instance.verify_subsystem_exists() + deployer.master_dict['pki_skip_installation'] = "True" + else: + # verify that this type of "subsystem" does NOT yet + # exist for this "instance" + deployer.instance.verify_subsystem_does_not_exist() + # detect and avoid any namespace collisions + deployer.namespace.collision_detection() + # initialize 'uid' and 'gid' + deployer.identity.add_uid_and_gid(deployer.master_dict['pki_user'], deployer.master_dict['pki_group']) + # establish 'uid' and 'gid' + deployer.identity.set_uid(deployer.master_dict['pki_user']) + deployer.identity.set_gid(deployer.master_dict['pki_group']) + # verify existence of SENSITIVE configuration file data + deployer.configuration_file.verify_sensitive_data() + # verify existence of MUTUALLY EXCLUSIVE configuration file data + deployer.configuration_file.verify_mutually_exclusive_data() + # verify existence of PREDEFINED configuration file data + deployer.configuration_file.verify_predefined_configuration_file_data() + # verify selinux context of selected ports + deployer.configuration_file.populate_non_default_ports() + deployer.configuration_file.verify_selinux_ports() + return self.rv + + def destroy(self, deployer): + + # begin official logging + config.pki_log.info(log.PKIDESTROY_BEGIN_MESSAGE_2, + deployer.master_dict['pki_subsystem'], + deployer.master_dict['pki_instance_name'], + extra=config.PKI_INDENTATION_LEVEL_0) + config.pki_log.info(log.INITIALIZATION_DESTROY_1, __name__, + extra=config.PKI_INDENTATION_LEVEL_1) + # verify that this type of "subsystem" currently EXISTS + # for this "instance" + deployer.instance.verify_subsystem_exists() + # verify that the command-line parameters match the values + # that are present in the corresponding configuration file + deployer.configuration_file.verify_command_matches_configuration_file() + # establish 'uid' and 'gid' + deployer.identity.set_uid(deployer.master_dict['pki_user']) + deployer.identity.set_gid(deployer.master_dict['pki_group']) + # get ports to remove selinux context + deployer.configuration_file.populate_non_default_ports() + + # get deinstallation token + token = deployer.security_domain.get_installation_token( + config.pki_secdomain_user, config.pki_secdomain_pass) + + # remove kra connector from CA if this is a KRA + deployer.kra_connector.deregister() + + # de-register instance from its Security Domain + # + # NOTE: Since the security domain of an instance must be up + # and running in order to be de-registered, this step + # must be done PRIOR to instance shutdown because this + # instance's security domain may be a part of a + # tightly-coupled shared instance. + # + deployer.security_domain.deregister(token) + # ALWAYS Stop this Apache/Tomcat PKI Process + deployer.systemd.stop() + return self.rv diff --git a/base/server/python/pki/server/deployment/scriptlets/instance_layout.py b/base/server/python/pki/server/deployment/scriptlets/instance_layout.py new file mode 100644 index 000000000..081d64029 --- /dev/null +++ b/base/server/python/pki/server/deployment/scriptlets/instance_layout.py @@ -0,0 +1,184 @@ +#!/usr/bin/python -t +# Authors: +# Matthew Harmsen +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Copyright (C) 2012 Red Hat, Inc. +# All rights reserved. +# + +# System Imports +import os + + +# PKI Deployment Imports +from .. import pkiconfig as config +from .. import pkimessages as log +from .. import pkiscriptlet + + +# PKI Deployment Instance Layout Scriptlet +class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet): + rv = 0 + + def spawn(self, deployer): + + if config.str2bool(deployer.master_dict['pki_skip_installation']): + config.pki_log.info(log.SKIP_INSTANCE_SPAWN_1, __name__, + extra=config.PKI_INDENTATION_LEVEL_1) + return self.rv + config.pki_log.info(log.INSTANCE_SPAWN_1, __name__, + extra=config.PKI_INDENTATION_LEVEL_1) + # establish instance logs + deployer.directory.create(deployer.master_dict['pki_instance_log_path']) + # establish instance configuration + deployer.directory.create(deployer.master_dict['pki_instance_configuration_path']) + # establish Apache/Tomcat specific instance + if deployer.master_dict['pki_subsystem'] in config.PKI_TOMCAT_SUBSYSTEMS: + # establish Tomcat instance configuration + deployer.directory.copy(deployer.master_dict['pki_source_server_path'], + deployer.master_dict['pki_instance_configuration_path'], + overwrite_flag=True) + # establish Tomcat instance base + deployer.directory.create(deployer.master_dict['pki_tomcat_common_path']) + deployer.directory.create(deployer.master_dict['pki_tomcat_common_lib_path']) + # establish Tomcat instance library + deployer.directory.create(deployer.master_dict['pki_instance_lib']) + for name in os.listdir(deployer.master_dict['pki_tomcat_lib_path']): + deployer.symlink.create( + os.path.join( + deployer.master_dict['pki_tomcat_lib_path'], + name), + os.path.join( + deployer.master_dict['pki_instance_lib'], + name)) + deployer.symlink.create(deployer.master_dict['pki_instance_conf_log4j_properties'], + deployer.master_dict['pki_instance_lib_log4j_properties']) + deployer.directory.create(deployer.master_dict['pki_tomcat_tmpdir_path']) + deployer.directory.create(deployer.master_dict['pki_tomcat_webapps_path']) + deployer.directory.create(deployer.master_dict['pki_tomcat_work_path']) + deployer.directory.create(deployer.master_dict['pki_tomcat_work_catalina_path']) + deployer.directory.create(deployer.master_dict['pki_tomcat_work_catalina_host_path']) + deployer.directory.create( + deployer.master_dict['pki_tomcat_work_catalina_host_run_path']) + deployer.directory.create( + deployer.master_dict['pki_tomcat_work_catalina_host_subsystem_path']) + # establish Tomcat instance logs + # establish Tomcat instance registry + # establish Tomcat instance convenience symbolic links + deployer.symlink.create(deployer.master_dict['pki_tomcat_bin_path'], + deployer.master_dict['pki_tomcat_bin_link']) + deployer.symlink.create(deployer.master_dict['pki_tomcat_systemd'], + deployer.master_dict['pki_instance_systemd_link'], + uid=0, gid=0) + # establish Tomcat instance common lib jar symbolic links + deployer.symlink.create(deployer.master_dict['pki_apache_commons_collections_jar'], + deployer.master_dict['pki_apache_commons_collections_jar_link']) + deployer.symlink.create(deployer.master_dict['pki_apache_commons_lang_jar'], + deployer.master_dict['pki_apache_commons_lang_jar_link']) + deployer.symlink.create(deployer.master_dict['pki_apache_commons_logging_jar'], + deployer.master_dict['pki_apache_commons_logging_jar_link']) + deployer.symlink.create(deployer.master_dict['pki_commons_codec_jar'], + deployer.master_dict['pki_commons_codec_jar_link']) + deployer.symlink.create(deployer.master_dict['pki_httpclient_jar'], + deployer.master_dict['pki_httpclient_jar_link']) + deployer.symlink.create(deployer.master_dict['pki_httpcore_jar'], + deployer.master_dict['pki_httpcore_jar_link']) + deployer.symlink.create(deployer.master_dict['pki_javassist_jar'], + deployer.master_dict['pki_javassist_jar_link']) + deployer.symlink.create(deployer.master_dict['pki_resteasy_jaxrs_api_jar'], + deployer.master_dict['pki_resteasy_jaxrs_api_jar_link']) + deployer.symlink.create(deployer.master_dict['pki_jettison_jar'], + deployer.master_dict['pki_jettison_jar_link']) + deployer.symlink.create(deployer.master_dict['pki_jss_jar'], + deployer.master_dict['pki_jss_jar_link']) + deployer.symlink.create(deployer.master_dict['pki_ldapjdk_jar'], + deployer.master_dict['pki_ldapjdk_jar_link']) + deployer.symlink.create(deployer.master_dict['pki_tomcat_jar'], + deployer.master_dict['pki_tomcat_jar_link']) + deployer.symlink.create(deployer.master_dict['pki_resteasy_atom_provider_jar'], + deployer.master_dict['pki_resteasy_atom_provider_jar_link']) + deployer.symlink.create(deployer.master_dict['pki_resteasy_jaxb_provider_jar'], + deployer.master_dict['pki_resteasy_jaxb_provider_jar_link']) + deployer.symlink.create(deployer.master_dict['pki_resteasy_jaxrs_jar'], + deployer.master_dict['pki_resteasy_jaxrs_jar_link']) + deployer.symlink.create(deployer.master_dict['pki_resteasy_jettison_provider_jar'], + deployer.master_dict['pki_resteasy_jettison_provider_jar_link']) + deployer.symlink.create(deployer.master_dict['pki_scannotation_jar'], + deployer.master_dict['pki_scannotation_jar_link']) + if deployer.master_dict['pki_subsystem'] == 'TKS': + deployer.symlink.create(deployer.master_dict['pki_symkey_jar'], + deployer.master_dict['pki_symkey_jar_link']) + deployer.symlink.create(deployer.master_dict['pki_tomcatjss_jar'], + deployer.master_dict['pki_tomcatjss_jar_link']) + deployer.symlink.create(deployer.master_dict['pki_velocity_jar'], + deployer.master_dict['pki_velocity_jar_link']) + deployer.symlink.create(deployer.master_dict['pki_xerces_j2_jar'], + deployer.master_dict['pki_xerces_j2_jar_link']) + deployer.symlink.create(deployer.master_dict['pki_xml_commons_apis_jar'], + deployer.master_dict['pki_xml_commons_apis_jar_link']) + deployer.symlink.create(deployer.master_dict['pki_xml_commons_resolver_jar'], + deployer.master_dict['pki_xml_commons_resolver_jar_link']) + # establish shared NSS security databases for this instance + deployer.directory.create(deployer.master_dict['pki_database_path']) + # establish instance convenience symbolic links + deployer.symlink.create(deployer.master_dict['pki_database_path'], + deployer.master_dict['pki_instance_database_link']) + deployer.symlink.create(deployer.master_dict['pki_instance_configuration_path'], + deployer.master_dict['pki_instance_conf_link']) + deployer.symlink.create(deployer.master_dict['pki_instance_log_path'], + deployer.master_dict['pki_instance_logs_link']) + return self.rv + + def destroy(self, deployer): + + config.pki_log.info(log.INSTANCE_DESTROY_1, __name__, + extra=config.PKI_INDENTATION_LEVEL_1) + if deployer.master_dict['pki_subsystem'] == 'TKS': + deployer.symlink.delete(deployer.master_dict['pki_symkey_jar_link']) + if deployer.master_dict['pki_subsystem'] in config.PKI_APACHE_SUBSYSTEMS and\ + deployer.instance.apache_instance_subsystems() == 0: + # remove Apache instance base + deployer.directory.delete(deployer.master_dict['pki_instance_path']) + # remove Apache instance logs + # remove shared NSS security database path for this instance + deployer.directory.delete(deployer.master_dict['pki_database_path']) + # remove Apache instance configuration + deployer.directory.delete(deployer.master_dict['pki_instance_configuration_path']) + # remove Apache instance registry + deployer.directory.delete(deployer.master_dict['pki_instance_registry_path']) + # remove Apache PKI registry (if empty) + if deployer.instance.apache_instances() == 0: + deployer.directory.delete( + deployer.master_dict['pki_instance_type_registry_path']) + elif deployer.master_dict['pki_subsystem'] in config.PKI_TOMCAT_SUBSYSTEMS and\ + len(deployer.instance.tomcat_instance_subsystems()) == 0: + # remove Tomcat instance base + deployer.directory.delete(deployer.master_dict['pki_instance_path']) + # remove Tomcat instance logs + deployer.directory.delete(deployer.master_dict['pki_instance_log_path']) + # remove shared NSS security database path for this instance + deployer.directory.delete(deployer.master_dict['pki_database_path']) + # remove Tomcat instance configuration + deployer.directory.delete(deployer.master_dict['pki_instance_configuration_path']) + # remove PKI 'tomcat.conf' instance file + deployer.file.delete(deployer.master_dict['pki_target_tomcat_conf_instance_id']) + # remove Tomcat instance registry + deployer.directory.delete(deployer.master_dict['pki_instance_registry_path']) + # remove Tomcat PKI registry (if empty) + if deployer.instance.tomcat_instances() == 0: + deployer.directory.delete( + deployer.master_dict['pki_instance_type_registry_path']) + return self.rv diff --git a/base/server/python/pki/server/deployment/scriptlets/security_databases.py b/base/server/python/pki/server/deployment/scriptlets/security_databases.py new file mode 100644 index 000000000..3d3193cef --- /dev/null +++ b/base/server/python/pki/server/deployment/scriptlets/security_databases.py @@ -0,0 +1,114 @@ +#!/usr/bin/python -t +# Authors: +# Matthew Harmsen +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Copyright (C) 2012 Red Hat, Inc. +# All rights reserved. +# + +# PKI Deployment Imports +from .. import pkiconfig as config +from .. import pkimessages as log +from .. import pkiscriptlet + + +# PKI Deployment Security Databases Scriptlet +class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet): + rv = 0 + + def spawn(self, deployer): + + if config.str2bool(deployer.master_dict['pki_skip_installation']): + config.pki_log.info(log.SKIP_SECURITY_DATABASES_SPAWN_1, __name__, + extra=config.PKI_INDENTATION_LEVEL_1) + return self.rv + config.pki_log.info(log.SECURITY_DATABASES_SPAWN_1, __name__, + extra=config.PKI_INDENTATION_LEVEL_1) + deployer.password.create_password_conf( + deployer.master_dict['pki_shared_password_conf'], + deployer.master_dict['pki_pin']) + # Since 'certutil' does NOT strip the 'token=' portion of + # the 'token=password' entries, create a temporary server 'pfile' + # which ONLY contains the 'password' for the purposes of + # allowing 'certutil' to generate the security databases + deployer.password.create_password_conf( + deployer.master_dict['pki_shared_pfile'], + deployer.master_dict['pki_pin'], pin_sans_token=True) + deployer.file.modify(deployer.master_dict['pki_shared_password_conf']) + deployer.certutil.create_security_databases( + deployer.master_dict['pki_database_path'], + deployer.master_dict['pki_cert_database'], + deployer.master_dict['pki_key_database'], + deployer.master_dict['pki_secmod_database'], + password_file=deployer.master_dict['pki_shared_pfile']) + deployer.file.modify(deployer.master_dict['pki_cert_database'], perms=\ + config.PKI_DEPLOYMENT_DEFAULT_SECURITY_DATABASE_PERMISSIONS) + deployer.file.modify(deployer.master_dict['pki_key_database'], perms=\ + config.PKI_DEPLOYMENT_DEFAULT_SECURITY_DATABASE_PERMISSIONS) + deployer.file.modify(deployer.master_dict['pki_secmod_database'], perms=\ + config.PKI_DEPLOYMENT_DEFAULT_SECURITY_DATABASE_PERMISSIONS) + + if len(deployer.instance.tomcat_instance_subsystems()) < 2: + # only create a self signed cert for a new instance + rv = deployer.certutil.verify_certificate_exists( + deployer.master_dict['pki_database_path'], + deployer.master_dict['pki_cert_database'], + deployer.master_dict['pki_key_database'], + deployer.master_dict['pki_secmod_database'], + deployer.master_dict['pki_self_signed_token'], + deployer.master_dict['pki_self_signed_nickname'], + password_file=deployer.master_dict['pki_shared_pfile']) + if not rv: + deployer.file.generate_noise_file( + deployer.master_dict['pki_self_signed_noise_file'], + deployer.master_dict['pki_self_signed_noise_bytes']) + deployer.certutil.generate_self_signed_certificate( + deployer.master_dict['pki_database_path'], + deployer.master_dict['pki_cert_database'], + deployer.master_dict['pki_key_database'], + deployer.master_dict['pki_secmod_database'], + deployer.master_dict['pki_self_signed_token'], + deployer.master_dict['pki_self_signed_nickname'], + deployer.master_dict['pki_self_signed_subject'], + deployer.master_dict['pki_self_signed_serial_number'], + deployer.master_dict['pki_self_signed_validity_period'], + deployer.master_dict['pki_self_signed_issuer_name'], + deployer.master_dict['pki_self_signed_trustargs'], + deployer.master_dict['pki_self_signed_noise_file'], + password_file=deployer.master_dict['pki_shared_pfile']) + # Delete the temporary 'noise' file + deployer.file.delete(deployer.master_dict['pki_self_signed_noise_file']) + # Delete the temporary 'pfile' + deployer.file.delete(deployer.master_dict['pki_shared_pfile']) + return self.rv + + def destroy(self, deployer): + + config.pki_log.info(log.SECURITY_DATABASES_DESTROY_1, __name__, + extra=config.PKI_INDENTATION_LEVEL_1) + if deployer.master_dict['pki_subsystem'] in config.PKI_APACHE_SUBSYSTEMS and\ + deployer.instance.apache_instance_subsystems() == 0: + deployer.file.delete(deployer.master_dict['pki_cert_database']) + deployer.file.delete(deployer.master_dict['pki_key_database']) + deployer.file.delete(deployer.master_dict['pki_secmod_database']) + deployer.file.delete(deployer.master_dict['pki_shared_password_conf']) + elif deployer.master_dict['pki_subsystem'] in config.PKI_TOMCAT_SUBSYSTEMS and\ + len(deployer.instance.tomcat_instance_subsystems()) == 0: + deployer.file.delete(deployer.master_dict['pki_cert_database']) + deployer.file.delete(deployer.master_dict['pki_key_database']) + deployer.file.delete(deployer.master_dict['pki_secmod_database']) + deployer.file.delete(deployer.master_dict['pki_shared_password_conf']) + return self.rv diff --git a/base/server/python/pki/server/deployment/scriptlets/selinux_setup.py b/base/server/python/pki/server/deployment/scriptlets/selinux_setup.py new file mode 100644 index 000000000..177233afc --- /dev/null +++ b/base/server/python/pki/server/deployment/scriptlets/selinux_setup.py @@ -0,0 +1,204 @@ +#!/usr/bin/python -t +# Authors: +# Ade Lee +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Copyright (C) 2012 Red Hat, Inc. +# All rights reserved. +# + +import selinux +import time +if selinux.is_selinux_enabled(): + import seobject + +# PKI Deployment Imports +from .. import pkiconfig as config +from ..pkiconfig import pki_selinux_config_ports as ports +from .. import pkimessages as log +from .. import pkiscriptlet + + +# PKI Deployment Selinux Setup Scriptlet +class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet): + rv = 0 + suffix = "(/.*)?" + + def restore_context(self, master_dict): + selinux.restorecon(master_dict['pki_instance_path'], True) + selinux.restorecon(config.PKI_DEPLOYMENT_LOG_ROOT, True) + selinux.restorecon(master_dict['pki_instance_log_path'], True) + selinux.restorecon(master_dict['pki_instance_configuration_path'], True) + + def spawn(self, deployer): + + if config.str2bool(deployer.master_dict['pki_skip_installation']): + config.pki_log.info(log.SKIP_SELINUX_SPAWN_1, __name__, + extra=config.PKI_INDENTATION_LEVEL_1) + return self.rv + + if not bool(selinux.is_selinux_enabled()): + config.pki_log.info(log.SELINUX_DISABLED_SPAWN_1, __name__, + extra=config.PKI_INDENTATION_LEVEL_1) + return self.rv + + config.pki_log.info(log.SELINUX_SPAWN_1, __name__, + extra=config.PKI_INDENTATION_LEVEL_1) + # A maximum of 10 tries to create the SELinux contexts + counter = 0 + max_tries = 10 + while True: + try: + # check first if any transactions are required + if len(ports) == 0 and deployer.master_dict['pki_instance_name'] == \ + config.PKI_DEPLOYMENT_DEFAULT_TOMCAT_INSTANCE_NAME: + self.restore_context(deployer.master_dict) + return self.rv + + # add SELinux contexts when adding the first subsystem + if deployer.master_dict['pki_subsystem'] in config.PKI_APACHE_SUBSYSTEMS and\ + deployer.instance.apache_instance_subsystems() == 1 or\ + deployer.master_dict['pki_subsystem'] in config.PKI_TOMCAT_SUBSYSTEMS and\ + len(deployer.instance.tomcat_instance_subsystems()) == 1: + + trans = seobject.semanageRecords("targeted") + trans.start() + if deployer.master_dict['pki_instance_name'] != \ + config.PKI_DEPLOYMENT_DEFAULT_TOMCAT_INSTANCE_NAME: + + fcon = seobject.fcontextRecords() + + config.pki_log.info("adding selinux fcontext \"%s\"", + deployer.master_dict['pki_instance_path'] + self.suffix, + extra=config.PKI_INDENTATION_LEVEL_2) + fcon.add(deployer.master_dict['pki_instance_path'] + self.suffix, + config.PKI_INSTANCE_SELINUX_CONTEXT, "", "s0", "") + + config.pki_log.info("adding selinux fcontext \"%s\"", + deployer.master_dict['pki_instance_log_path'] + self.suffix, + extra=config.PKI_INDENTATION_LEVEL_2) + fcon.add(deployer.master_dict['pki_instance_log_path'] + self.suffix, + config.PKI_LOG_SELINUX_CONTEXT, "", "s0", "") + + config.pki_log.info("adding selinux fcontext \"%s\"", + deployer.master_dict['pki_instance_configuration_path'] + self.suffix, + extra=config.PKI_INDENTATION_LEVEL_2) + fcon.add(deployer.master_dict['pki_instance_configuration_path'] + self.suffix, + config.PKI_CFG_SELINUX_CONTEXT, "", "s0", "") + + config.pki_log.info("adding selinux fcontext \"%s\"", + deployer.master_dict['pki_database_path'] + self.suffix, + extra=config.PKI_INDENTATION_LEVEL_2) + fcon.add(deployer.master_dict['pki_database_path'] + self.suffix, + config.PKI_CERTDB_SELINUX_CONTEXT, "", "s0", "") + + portRecords = seobject.portRecords() + for port in ports: + config.pki_log.info("adding selinux port %s", port, + extra=config.PKI_INDENTATION_LEVEL_2) + portRecords.add(port, "tcp", "s0", config.PKI_PORT_SELINUX_CONTEXT) + + trans.finish() + + self.restore_context(deployer.master_dict) + break + except ValueError as e: + error_message = str(e) + config.pki_log.debug(error_message) + if error_message.strip() == "Could not start semanage transaction": + counter = counter + 1 + if counter >= max_tries: + raise + time.sleep(5) + config.pki_log.debug("Retrying to setup the selinux context ...") + else: + raise + + return self.rv + + def destroy(self, deployer): + + if not bool(selinux.is_selinux_enabled()): + config.pki_log.info(log.SELINUX_DISABLED_DESTROY_1, __name__, + extra=config.PKI_INDENTATION_LEVEL_1) + return self.rv + config.pki_log.info(log.SELINUX_DESTROY_1, __name__, + extra=config.PKI_INDENTATION_LEVEL_1) + + # check first if any transactions are required + if (len(ports) == 0 and deployer.master_dict['pki_instance_name'] == + config.PKI_DEPLOYMENT_DEFAULT_TOMCAT_INSTANCE_NAME): + return self.rv + # A maximum of 10 tries to delete the SELinux contexts + counter = 1 + max_tries = 10 + while True: + try: + # remove SELinux contexts when removing the last subsystem + if (deployer.master_dict['pki_subsystem'] in config.PKI_APACHE_SUBSYSTEMS and + deployer.instance.apache_instance_subsystems() == 0 or + deployer.master_dict['pki_subsystem'] in config.PKI_TOMCAT_SUBSYSTEMS and + len(deployer.instance.tomcat_instance_subsystems()) == 0): + + trans = seobject.semanageRecords("targeted") + trans.start() + + if deployer.master_dict['pki_instance_name'] != \ + config.PKI_DEPLOYMENT_DEFAULT_TOMCAT_INSTANCE_NAME: + + fcon = seobject.fcontextRecords() + + config.pki_log.info("deleting selinux fcontext \"%s\"", + deployer.master_dict['pki_instance_path'] + self.suffix, + extra=config.PKI_INDENTATION_LEVEL_2) + fcon.delete(deployer.master_dict['pki_instance_path'] + self.suffix , "") + + config.pki_log.info("deleting selinux fcontext \"%s\"", + deployer.master_dict['pki_instance_log_path'] + self.suffix, + extra=config.PKI_INDENTATION_LEVEL_2) + fcon.delete(deployer.master_dict['pki_instance_log_path'] + self.suffix, "") + + config.pki_log.info("deleting selinux fcontext \"%s\"", + deployer.master_dict['pki_instance_configuration_path'] + self.suffix, + extra=config.PKI_INDENTATION_LEVEL_2) + fcon.delete(deployer.master_dict['pki_instance_configuration_path'] + + self.suffix, "") + + config.pki_log.info("deleting selinux fcontext \"%s\"", + deployer.master_dict['pki_database_path'] + self.suffix, + extra=config.PKI_INDENTATION_LEVEL_2) + fcon.delete(deployer.master_dict['pki_database_path'] + self.suffix , "") + + portRecords = seobject.portRecords() + for port in ports: + config.pki_log.info("deleting selinux port %s", port, + extra=config.PKI_INDENTATION_LEVEL_2) + portRecords.delete(port, "tcp") + + trans.finish() + break + except ValueError as e: + error_message = str(e) + config.pki_log.debug(error_message) + if error_message.strip() == "Could not start semanage transaction": + counter = counter + 1 + if counter >= max_tries: + raise + time.sleep(5) + config.pki_log.debug("Retrying to remove selinux context ...") + else: + raise + + return self.rv diff --git a/base/server/python/pki/server/deployment/scriptlets/slot_substitution.py b/base/server/python/pki/server/deployment/scriptlets/slot_substitution.py new file mode 100644 index 000000000..726b6dfc0 --- /dev/null +++ b/base/server/python/pki/server/deployment/scriptlets/slot_substitution.py @@ -0,0 +1,96 @@ +#!/usr/bin/python -t +# Authors: +# Matthew Harmsen +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Copyright (C) 2012 Red Hat, Inc. +# All rights reserved. +# + +# PKI Deployment Imports +from .. import pkiconfig as config +from .. import pkimessages as log +from .. import pkiscriptlet + + +# PKI Deployment Slot Substitution Scriptlet +class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet): + rv = 0 + + def spawn(self, deployer): + + if config.str2bool(deployer.master_dict['pki_skip_installation']): + config.pki_log.info(log.SKIP_SLOT_ASSIGNMENT_SPAWN_1, __name__, + extra=config.PKI_INDENTATION_LEVEL_1) + return self.rv + config.pki_log.info(log.SLOT_ASSIGNMENT_SPAWN_1, __name__, + extra=config.PKI_INDENTATION_LEVEL_1) + deployer.file.copy_with_slot_substitution(deployer.master_dict['pki_source_cs_cfg'], + deployer.master_dict['pki_target_cs_cfg']) + deployer.file.copy_with_slot_substitution(deployer.master_dict['pki_source_registry'], + deployer.master_dict['pki_target_registry'], + uid=0, gid=0, overwrite_flag=True) + if deployer.master_dict['pki_subsystem'] in config.PKI_TOMCAT_SUBSYSTEMS: + deployer.file.copy_with_slot_substitution( + deployer.master_dict['pki_source_catalina_properties'], + deployer.master_dict['pki_target_catalina_properties'], + overwrite_flag=True) + deployer.file.copy_with_slot_substitution( + deployer.master_dict['pki_source_servercertnick_conf'], + deployer.master_dict['pki_target_servercertnick_conf'], + overwrite_flag=True) + deployer.file.copy_with_slot_substitution( + deployer.master_dict['pki_source_server_xml'], + deployer.master_dict['pki_target_server_xml'], + overwrite_flag=True) + deployer.file.copy_with_slot_substitution( + deployer.master_dict['pki_source_context_xml'], + deployer.master_dict['pki_target_context_xml'], + overwrite_flag=True) + deployer.file.copy_with_slot_substitution( + deployer.master_dict['pki_source_tomcat_conf'], + deployer.master_dict['pki_target_tomcat_conf_instance_id'], + uid=0, gid=0, overwrite_flag=True) + deployer.file.copy_with_slot_substitution( + deployer.master_dict['pki_source_tomcat_conf'], + deployer.master_dict['pki_target_tomcat_conf'], + overwrite_flag=True) + deployer.file.apply_slot_substitution( + deployer.master_dict['pki_target_velocity_properties']) + deployer.file.apply_slot_substitution( + deployer.master_dict['pki_target_subsystem_web_xml']) + # Strip "" section from subsystem "web.xml" + # This is ONLY necessary because XML comments cannot be "nested"! + # deployer.file.copy(deployer.master_dict['pki_target_subsystem_web_xml'], + # deployer.master_dict['pki_target_subsystem_web_xml_orig']) + # deployer.file.delete(deployer.master_dict['pki_target_subsystem_web_xml']) + # util.xml_file.remove_filter_section_from_web_xml( + # deployer.master_dict['pki_target_subsystem_web_xml_orig'], + # deployer.master_dict['pki_target_subsystem_web_xml']) + # deployer.file.delete(deployer.master_dict['pki_target_subsystem_web_xml_orig']) + if deployer.master_dict['pki_subsystem'] == "CA": + deployer.file.copy_with_slot_substitution( + deployer.master_dict['pki_source_proxy_conf'], + deployer.master_dict['pki_target_proxy_conf']) + deployer.file.apply_slot_substitution( + deployer.master_dict['pki_target_profileselect_template']) + return self.rv + + def destroy(self, deployer): + config.pki_log.info(log.SLOT_ASSIGNMENT_DESTROY_1, __name__, + extra=config.PKI_INDENTATION_LEVEL_1) + config.pki_log.info("NOTHING NEEDS TO BE IMPLEMENTED", + extra=config.PKI_INDENTATION_LEVEL_2) + return self.rv diff --git a/base/server/python/pki/server/deployment/scriptlets/subsystem_layout.py b/base/server/python/pki/server/deployment/scriptlets/subsystem_layout.py new file mode 100644 index 000000000..8aae3f6c6 --- /dev/null +++ b/base/server/python/pki/server/deployment/scriptlets/subsystem_layout.py @@ -0,0 +1,121 @@ +#!/usr/bin/python -t +# Authors: +# Matthew Harmsen +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Copyright (C) 2012 Red Hat, Inc. +# All rights reserved. +# + +# PKI Deployment Imports +from .. import pkiconfig as config +from .. import pkimessages as log +from .. import pkiscriptlet + + +# PKI Deployment Subsystem Layout Scriptlet +class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet): + rv = 0 + + def spawn(self, deployer): + + if config.str2bool(deployer.master_dict['pki_skip_installation']): + config.pki_log.info(log.SKIP_SUBSYSTEM_SPAWN_1, __name__, + extra=config.PKI_INDENTATION_LEVEL_1) + return self.rv + config.pki_log.info(log.SUBSYSTEM_SPAWN_1, __name__, + extra=config.PKI_INDENTATION_LEVEL_1) + # establish instance-based subsystem logs + deployer.directory.create(deployer.master_dict['pki_subsystem_log_path']) + deployer.directory.create(deployer.master_dict['pki_subsystem_archive_log_path']) + if deployer.master_dict['pki_subsystem'] in config.PKI_SIGNED_AUDIT_SUBSYSTEMS: + deployer.directory.create(deployer.master_dict['pki_subsystem_signed_audit_log_path']) + # establish instance-based subsystem configuration + deployer.directory.create(deployer.master_dict['pki_subsystem_configuration_path']) + # deployer.directory.copy(deployer.master_dict['pki_source_conf_path'], + # deployer.master_dict['pki_subsystem_configuration_path']) + # establish instance-based Apache/Tomcat specific subsystems + if deployer.master_dict['pki_subsystem'] in config.PKI_TOMCAT_SUBSYSTEMS: + # establish instance-based Tomcat PKI subsystem base + if deployer.master_dict['pki_subsystem'] == "CA": + deployer.directory.copy(deployer.master_dict['pki_source_emails'], + deployer.master_dict['pki_subsystem_emails_path']) + deployer.directory.copy(deployer.master_dict['pki_source_profiles'], + deployer.master_dict['pki_subsystem_profiles_path']) + # establish instance-based Tomcat PKI subsystem logs + # establish instance-based Tomcat PKI subsystem configuration + if deployer.master_dict['pki_subsystem'] == "CA": + deployer.file.copy(deployer.master_dict['pki_source_flatfile_txt'], + deployer.master_dict['pki_target_flatfile_txt']) + deployer.file.copy(deployer.master_dict['pki_source_registry_cfg'], + deployer.master_dict['pki_target_registry_cfg']) + # '*.profile' + deployer.file.copy(deployer.master_dict['pki_source_admincert_profile'], + deployer.master_dict['pki_target_admincert_profile']) + deployer.file.copy(deployer.master_dict['pki_source_caauditsigningcert_profile'], + deployer.master_dict['pki_target_caauditsigningcert_profile']) + deployer.file.copy(deployer.master_dict['pki_source_cacert_profile'], + deployer.master_dict['pki_target_cacert_profile']) + deployer.file.copy(deployer.master_dict['pki_source_caocspcert_profile'], + deployer.master_dict['pki_target_caocspcert_profile']) + deployer.file.copy(deployer.master_dict['pki_source_servercert_profile'], + deployer.master_dict['pki_target_servercert_profile']) + deployer.file.copy(deployer.master_dict['pki_source_subsystemcert_profile'], + deployer.master_dict['pki_target_subsystemcert_profile']) + elif deployer.master_dict['pki_subsystem'] == "KRA": + # '*.profile' + deployer.file.copy(deployer.master_dict['pki_source_servercert_profile'], + deployer.master_dict['pki_target_servercert_profile']) + deployer.file.copy(deployer.master_dict['pki_source_storagecert_profile'], + deployer.master_dict['pki_target_storagecert_profile']) + deployer.file.copy(deployer.master_dict['pki_source_subsystemcert_profile'], + deployer.master_dict['pki_target_subsystemcert_profile']) + deployer.file.copy(deployer.master_dict['pki_source_transportcert_profile'], + deployer.master_dict['pki_target_transportcert_profile']) + # establish instance-based Tomcat PKI subsystem registry + # establish instance-based Tomcat PKI subsystem convenience + # symbolic links + deployer.symlink.create(deployer.master_dict['pki_tomcat_webapps_path'], + deployer.master_dict['pki_subsystem_tomcat_webapps_link']) + # establish instance-based subsystem convenience symbolic links + deployer.symlink.create(deployer.master_dict['pki_instance_database_link'], + deployer.master_dict['pki_subsystem_database_link']) + deployer.symlink.create(deployer.master_dict['pki_subsystem_configuration_path'], + deployer.master_dict['pki_subsystem_conf_link']) + deployer.symlink.create(deployer.master_dict['pki_subsystem_log_path'], + deployer.master_dict['pki_subsystem_logs_link']) + deployer.symlink.create(deployer.master_dict['pki_instance_registry_path'], + deployer.master_dict['pki_subsystem_registry_link']) + return self.rv + + def destroy(self, deployer): + + config.pki_log.info(log.SUBSYSTEM_DESTROY_1, __name__, + extra=config.PKI_INDENTATION_LEVEL_1) + # remove instance-based subsystem base + if deployer.master_dict['pki_subsystem'] == "CA": + deployer.directory.delete(deployer.master_dict['pki_subsystem_emails_path']) + deployer.directory.delete(deployer.master_dict['pki_subsystem_profiles_path']) + deployer.directory.delete(deployer.master_dict['pki_subsystem_path']) + # remove instance-based subsystem logs + if deployer.master_dict['pki_subsystem'] in config.PKI_SIGNED_AUDIT_SUBSYSTEMS: + deployer.directory.delete(deployer.master_dict['pki_subsystem_signed_audit_log_path']) + deployer.directory.delete(deployer.master_dict['pki_subsystem_archive_log_path']) + deployer.directory.delete(deployer.master_dict['pki_subsystem_log_path']) + # remove instance-based subsystem configuration + deployer.directory.delete(deployer.master_dict['pki_subsystem_configuration_path']) + # remove instance-based subsystem registry + deployer.directory.delete(deployer.master_dict['pki_subsystem_registry_path']) + return self.rv diff --git a/base/server/python/pki/server/deployment/scriptlets/webapp_deployment.py b/base/server/python/pki/server/deployment/scriptlets/webapp_deployment.py new file mode 100644 index 000000000..ccbf4ea90 --- /dev/null +++ b/base/server/python/pki/server/deployment/scriptlets/webapp_deployment.py @@ -0,0 +1,165 @@ +#!/usr/bin/python -t +# Authors: +# Matthew Harmsen +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License along +# with this program; if not, write to the Free Software Foundation, Inc., +# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +# +# Copyright (C) 2012 Red Hat, Inc. +# All rights reserved. +# + +# System Imports +import os + +# PKI Deployment Imports +from .. import pkiconfig as config +from .. import pkimessages as log +from .. import pkiscriptlet + + +# PKI Web Application Deployment Scriptlet +class PkiScriptlet(pkiscriptlet.AbstractBasePkiScriptlet): + rv = 0 + + def spawn(self, deployer): + + if deployer.master_dict['pki_subsystem'] in config.PKI_TOMCAT_SUBSYSTEMS: + if config.str2bool(deployer.master_dict['pki_skip_installation']): + config.pki_log.info(log.SKIP_WEBAPP_DEPLOYMENT_SPAWN_1, + __name__, + extra=config.PKI_INDENTATION_LEVEL_1) + return self.rv + config.pki_log.info(log.WEBAPP_DEPLOYMENT_SPAWN_1, __name__, + extra=config.PKI_INDENTATION_LEVEL_1) + + # Copy /usr/share/pki/server/webapps/ROOT + # to /webapps/ROOT + deployer.directory.create(deployer.master_dict['pki_tomcat_webapps_root_path']) + deployer.directory.copy( + os.path.join( + config.PKI_DEPLOYMENT_SOURCE_ROOT, + "server", + "webapps", + "ROOT"), + deployer.master_dict['pki_tomcat_webapps_root_path'], + overwrite_flag=True) + + deployer.directory.create(deployer.master_dict['pki_tomcat_webapps_common_path']) + + # If desired and available, + # copy selected server theme + # to /webapps/pki + if config.str2bool(deployer.master_dict['pki_theme_enable']) and\ + os.path.exists(deployer.master_dict['pki_theme_server_dir']): + deployer.directory.copy(deployer.master_dict['pki_theme_server_dir'], + deployer.master_dict['pki_tomcat_webapps_common_path'], + overwrite_flag=True) + + # Copy /usr/share/pki/server/webapps/pki/js + # to /webapps/pki/js + deployer.directory.copy( + os.path.join( + config.PKI_DEPLOYMENT_SOURCE_ROOT, + "server", + "webapps", + "pki", + "js"), + os.path.join( + deployer.master_dict['pki_tomcat_webapps_common_path'], + "js"), + overwrite_flag=True) + + # Copy /usr/share/pki/server/webapps/pki/META-INF + # to /webapps/pki/META-INF + deployer.directory.copy( + os.path.join( + config.PKI_DEPLOYMENT_SOURCE_ROOT, + "server", + "webapps", + "pki", + "META-INF"), + os.path.join( + deployer.master_dict['pki_tomcat_webapps_common_path'], + "META-INF"), + overwrite_flag=True) + + # Copy /usr/share/pki/server/webapps/pki/admin + # to /webapps//admin + # TODO: common templates should be deployed in common webapp + deployer.directory.create(deployer.master_dict['pki_tomcat_webapps_subsystem_path']) + deployer.directory.copy( + os.path.join( + config.PKI_DEPLOYMENT_SOURCE_ROOT, + "server", + "webapps", + "pki", + "admin"), + os.path.join( + deployer.master_dict['pki_tomcat_webapps_subsystem_path'], + "admin"), + overwrite_flag=True) + + # Copy /usr/share/pki//webapps/ + # to /webapps/ + deployer.directory.copy( + os.path.join( + config.PKI_DEPLOYMENT_SOURCE_ROOT, + deployer.master_dict['pki_subsystem'].lower(), + "webapps", + deployer.master_dict['pki_subsystem'].lower()), + deployer.master_dict['pki_tomcat_webapps_subsystem_path'], + overwrite_flag=True) + + deployer.directory.create( + deployer.master_dict['pki_tomcat_webapps_subsystem_webinf_classes_path']) + deployer.directory.create( + deployer.master_dict['pki_tomcat_webapps_subsystem_webinf_lib_path']) + # establish Tomcat webapps subsystem WEB-INF lib symbolic links + deployer.symlink.create(deployer.master_dict['pki_certsrv_jar'], + deployer.master_dict['pki_certsrv_jar_link']) + deployer.symlink.create(deployer.master_dict['pki_cmsbundle'], + deployer.master_dict['pki_cmsbundle_jar_link']) + deployer.symlink.create(deployer.master_dict['pki_cmscore'], + deployer.master_dict['pki_cmscore_jar_link']) + deployer.symlink.create(deployer.master_dict['pki_cms'], + deployer.master_dict['pki_cms_jar_link']) + deployer.symlink.create(deployer.master_dict['pki_cmsutil'], + deployer.master_dict['pki_cmsutil_jar_link']) + deployer.symlink.create(deployer.master_dict['pki_nsutil'], + deployer.master_dict['pki_nsutil_jar_link']) + if deployer.master_dict['pki_subsystem'] == "CA": + deployer.symlink.create(deployer.master_dict['pki_ca_jar'], + deployer.master_dict['pki_ca_jar_link']) + elif deployer.master_dict['pki_subsystem'] == "KRA": + deployer.symlink.create(deployer.master_dict['pki_kra_jar'], + deployer.master_dict['pki_kra_jar_link']) + elif deployer.master_dict['pki_subsystem'] == "OCSP": + deployer.symlink.create(deployer.master_dict['pki_ocsp_jar'], + deployer.master_dict['pki_ocsp_jar_link']) + elif deployer.master_dict['pki_subsystem'] == "TKS": + deployer.symlink.create(deployer.master_dict['pki_tks_jar'], + deployer.master_dict['pki_tks_jar_link']) + elif deployer.master_dict['pki_subsystem'] == "TPS": + deployer.symlink.create(deployer.master_dict['pki_tps_jar'], + deployer.master_dict['pki_tps_jar_link']) + # set ownerships, permissions, and acls + deployer.directory.set_mode(deployer.master_dict['pki_tomcat_webapps_subsystem_path']) + return self.rv + + def destroy(self, deployer): + if deployer.master_dict['pki_subsystem'] in config.PKI_TOMCAT_SUBSYSTEMS: + config.pki_log.info(log.WEBAPP_DEPLOYMENT_DESTROY_1, __name__, + extra=config.PKI_INDENTATION_LEVEL_1) + deployer.directory.delete(deployer.master_dict['pki_tomcat_webapps_subsystem_path']) + return self.rv -- cgit