summaryrefslogtreecommitdiffstats
path: root/ipaserver/install/drminstance.py
diff options
context:
space:
mode:
Diffstat (limited to 'ipaserver/install/drminstance.py')
-rw-r--r--ipaserver/install/drminstance.py337
1 files changed, 337 insertions, 0 deletions
diff --git a/ipaserver/install/drminstance.py b/ipaserver/install/drminstance.py
new file mode 100644
index 000000000..744b0973d
--- /dev/null
+++ b/ipaserver/install/drminstance.py
@@ -0,0 +1,337 @@
+# Authors: Ade Lee <alee@redhat.com>
+#
+# Copyright (C) 2014 Red Hat
+# see file 'COPYING' for use and warranty information
+#
+# 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, either version 3 of the License, or
+# (at your option) any later version.
+#
+# 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, see <http://www.gnu.org/licenses/>.
+#
+
+import ConfigParser
+import os
+import pwd
+import shutil
+import sys
+import tempfile
+
+from ipalib import api
+from ipapython import dogtag
+from ipapython import ipautil
+from ipapython import services as ipaservices
+from ipapython.dn import DN
+from ipaserver.install import certs
+from ipaserver.install import cainstance
+from ipaserver.install import dsinstance
+from ipaserver.install import service
+from ipaserver.install.dogtaginstance import DogtagInstance
+from ipaserver.install.dogtaginstance import DEFAULT_DSPORT, PKI_USER
+from ipapython.ipa_log_manager import *
+
+# When IPA is installed with DNS support, this CNAME should hold all IPA
+# replicas with DRM configured
+IPA_DRM_RECORD = "ipa-drm"
+
+class DRMInstance(DogtagInstance):
+ """
+ We assume that the CA has already been installed, and we use the
+ same tomcat instance to host both the CA and DRM.
+ The mod_nss database will contain the RA agent cert that will be used
+ to do authenticated requests against dogtag. The RA agent cert will
+ be the same for both the CA and DRM.
+ """
+
+ def __init__(self, realm, dogtag_constants=None):
+ if dogtag_constants is None:
+ dogtag_constants = dogtag.configured_constants()
+
+ DogtagInstance.__init__(self, realm, "KRA", "DRM server",
+ dogtag_constants)
+ self.basedn = DN(('o', 'ipadrm'))
+ self.tracking_nicknames = ['auditSigningCert cert-pki-drm',
+ 'transportCert cert-pki-drm',
+ 'storageCert cert-pki-drm']
+
+ def configure_instance(self, host_name, domain, dm_password,
+ admin_password, ds_port=DEFAULT_DSPORT,
+ pkcs12_info=None, master_host=None,
+ master_replication_port=None,
+ subject_base=None):
+ """Create a DRM instance.
+
+ To create a clone, pass in pkcs12_info.
+ """
+ self.fqdn = host_name
+ self.domain = domain
+ self.dm_password = dm_password
+ self.admin_password = admin_password
+ self.ds_port = ds_port
+ self.pkcs12_info = pkcs12_info
+ if self.pkcs12_info is not None:
+ self.clone = True
+ self.master_host = master_host
+ self.master_replication_port = master_replication_port
+ if subject_base is None:
+ self.subject_base = DN(('O', self.realm))
+ else:
+ self.subject_base = subject_base
+
+ # Confirm that a DRM does not already exist
+ if self.is_installed():
+ raise RuntimeError(
+ "DRM already installed.")
+ # Confirm that a Dogtag 10 CA instance already exists
+ ca = cainstance.CAInstance(
+ api.env.realm, certs.NSS_DIR,
+ dogtag_constants = dogtag.Dogtag10Constants)
+ if not ca.is_installed():
+ raise RuntimeError(
+ "DRM configuration failed. "
+ "A Dogtag CA must be installed first")
+
+ self.step("configuring DRM instance", self.__spawn_instance)
+ self.step("restarting DRM", self.restart_instance)
+ self.step("configure certificate renewals", self.configure_renewal)
+ self.step("Configure HTTP to proxy connections",
+ self.http_proxy)
+
+ self.start_creation(runtime=210)
+
+ def start_instance(self):
+ DogtagInstance.start_instance(self)
+
+ def stop_instance(self):
+ DogtagInstance.stop_instance(self)
+
+ def restart_instance(self):
+ DogtagInstance.restart_instance(self)
+
+ def http_proxy(self):
+ DogtagInstance.http_proxy(self)
+
+ def __spawn_instance(self):
+ """
+ Create and configure a new DRM instance using pkispawn.
+ Creates a configuration file with IPA-specific
+ parameters and passes it to the base class to call pkispawn
+ """
+
+ # Create an empty and secured file
+ (cfg_fd, cfg_file) = tempfile.mkstemp()
+ os.close(cfg_fd)
+ pent = pwd.getpwnam(PKI_USER)
+ os.chown(cfg_file, pent.pw_uid, pent.pw_gid)
+
+ # Create KRA configuration
+ config = ConfigParser.ConfigParser()
+ config.optionxform = str
+ config.add_section("KRA")
+
+ # Security Domain Authentication
+ config.set("KRA", "pki_security_domain_https_port", "443")
+ config.set("KRA", "pki_security_domain_password", self.admin_password)
+ config.set("KRA", "pki_security_domain_user", "admin")
+
+ # issuing ca
+ config.set("KRA", "pki_issuing_ca_uri", "https://%s" %
+ ipautil.format_netloc(self.fqdn, 443))
+
+ # Server
+ config.set("KRA", "pki_enable_proxy", "True")
+ config.set("KRA", "pki_restart_configured_instance", "False")
+ config.set("KRA", "pki_backup_keys", "True")
+ config.set("KRA", "pki_backup_password", self.admin_password)
+
+ # Client security database
+ config.set("KRA", "pki_client_database_dir", self.agent_db)
+ config.set("KRA", "pki_client_database_password", self.admin_password)
+ config.set("KRA", "pki_client_database_purge", "False")
+ config.set("KRA", "pki_client_pkcs12_password", self.admin_password)
+
+ # Administrator
+ config.set("KRA", "pki_admin_name", "admin")
+ config.set("KRA", "pki_admin_uid", "admin")
+ config.set("KRA", "pki_admin_email", "root@localhost")
+ config.set("KRA", "pki_admin_password", self.admin_password)
+ config.set("KRA", "pki_admin_nickname", "ipa-ca-agent")
+ config.set("KRA", "pki_admin_subject_dn",
+ str(DN(('cn', 'ipa-ca-agent'), self.subject_base)))
+ config.set("KRA", "pki_import_admin_cert", "True")
+ config.set("KRA", "pki_admin_cert_file",
+ "/root/.dogtag/pki-tomcat/ca_admin.cert")
+ config.set("KRA", "pki_client_admin_cert_p12", "/root/ca-agent.p12")
+
+ # Directory server
+ config.set("KRA", "pki_ds_ldap_port", str(self.ds_port))
+ config.set("KRA", "pki_ds_password", self.dm_password)
+ config.set("KRA", "pki_ds_base_dn", self.basedn)
+ config.set("KRA", "pki_ds_database", "ipakra")
+
+ # Certificate subject DN's
+ config.set("KRA", "pki_subsystem_subject_dn",
+ str(DN(('cn', 'CA Subsystem'), self.subject_base)))
+ config.set("KRA", "pki_ssl_server_subject_dn",
+ str(DN(('cn', self.fqdn), self.subject_base)))
+ config.set("KRA", "pki_audit_signing_subject_dn",
+ str(DN(('cn', 'DRM Audit'), self.subject_base)))
+ config.set("KRA", "pki_transport_subject_dn",
+ str(DN(('cn', 'DRM Transport Certificate'), self.subject_base)))
+ config.set("KRA", "pki_storage_subject_dn",
+ str(DN(('cn', 'DRM Storage Certificate'), self.subject_base)))
+
+ # Certificate nicknames
+ # Note that both the server certs and subsystem certs reuse
+ # the ca certs.
+ config.set("KRA", "pki_subsystem_nickname",
+ "subsystemCert cert-pki-ca")
+ config.set("KRA", "pki_ssl_server_nickname",
+ "Server-Cert cert-pki-ca")
+ config.set("KRA", "pki_audit_signing_nickname",
+ "auditSigningCert cert-pki-drm")
+ config.set("KRA", "pki_transport_nickname",
+ "transportCert cert-pki-drm")
+ config.set("KRA", "pki_storage_nickname",
+ "storageCert cert-pki-drm")
+
+ # Shared db settings
+ # Needed because CA and KRA share the same database
+ # We will use the dbuser created for the CA
+ config.set("KRA", "pki_share_db", "True")
+ config.set("KRA", "pki_share_dbuser_dn",
+ str(DN(('uid', 'pkidbuser'),('ou', 'people'),('o','ipaca'))))
+
+
+ if (self.clone):
+ drmfile = self.pkcs12_info[0]
+ shutil.copy(drmfile, "/tmp/drm.p12")
+ pent = pwd.getpwnam(PKI_USER)
+ os.chown("/tmp/drm.p12", pent.pw_uid, pent.pw_gid)
+
+ # Security domain registration
+ config.set("KRA", "pki_security_domain_hostname", self.master_host)
+ config.set("KRA", "pki_security_domain_https_port", "443")
+ config.set("KRA", "pki_security_domain_user", "admin")
+ config.set("KRA", "pki_security_domain_password",
+ self.admin_password)
+
+ # Clone
+ config.set("KRA", "pki_clone", "True")
+ config.set("KRA", "pki_clone_pkcs12_path", "/tmp/drm.p12")
+ config.set("KRA", "pki_clone_pkcs12_password", self.dm_password)
+ config.set("KRA", "pki_clone_replication_security", "TLS")
+ config.set("KRA", "pki_clone_replication_master_port",
+ str(self.master_replication_port))
+ config.set("KRA", "pki_clone_replication_clone_port",
+ dogtag.install_constants.DS_PORT)
+ config.set("KRA", "pki_clone_replicate_schema", "False")
+ config.set("KRA", "pki_clone_uri",
+ "https://%s" % ipautil.format_netloc(self.master_host, 443))
+
+ # Generate configuration file
+ with open(cfg_file, "wb") as f:
+ config.write(f)
+
+ try:
+ DogtagInstance.spawn_instance(self, cfg_file)
+ finally:
+ os.remove(cfg_file)
+
+ shutil.move("/var/lib/pki/pki-tomcat/alias/kra_backup_keys.p12",
+ "/root/kracert.p12")
+
+ root_logger.debug("completed creating DRM instance")
+
+ def update_cert_config(self, nickname, cert, dogtag_constants=None):
+ """
+ When renewing a DRM subsystem certificate the configuration file
+ needs to get the new certificate as well.
+
+ nickname is one of the known nicknames.
+ cert is a DER-encoded certificate.
+ """
+
+ if dogtag_constants is None:
+ dogtag_constants = dogtag.configured_constants()
+
+ # The cert directive to update per nickname
+ directives = {
+ 'auditSigningCert cert-pki-drm': 'kra.audit_signing.cert',
+ 'storageCert cert-pki-drm': 'kra.storage.cert',
+ 'transportCert cert-pki-drm': 'kra.transport.cert',
+ 'subsystemCert cert-pki-drm': 'kra.subsystem.cert',
+ 'Server-Cert cert-pki-ca': 'kra.sslserver.cert'}
+
+ DogtagInstance.update_cert_config(
+ self, nickname, cert, directives,
+ dogtag.configured_constants().DRM_CS_CFG_PATH,
+ dogtag_constants)
+
+
+def install_replica_drm(config, postinstall=False):
+ """
+ Install a DRM on a replica.
+
+ There are two modes of doing this controlled:
+ - While the replica is being installed
+ - Post-replica installation
+
+ config is a ReplicaConfig object
+
+ Returns a DRM instance
+ """
+ # note that the cacert.p12 file is regenerated during the
+ # ipa-replica-prepare process and should include all the certs
+ # for the CA and DRM
+ drmfile = config.dir + "/cacert.p12"
+
+ if not ipautil.file_exists(drmfile):
+ raise RuntimeError(
+ "Unable to clone DRM."
+ " cacert.p12 file not found in replica file")
+
+ drm = DRMInstance(config.realm_name,
+ dogtag_constants=dogtag.install_constants)
+ drm.dm_password = config.dirman_password
+ drm.subject_base = config.subject_base
+ if drm.is_installed():
+ sys.exit("A DRM is already configured on this system.")
+
+ drm.configure_instance(config.host_name, config.domain_name,
+ config.dirman_password, config.dirman_password,
+ pkcs12_info=(drmfile,),
+ master_host=config.master_host_name,
+ master_replication_port=config.ca_ds_port,
+ subject_base=config.subject_base)
+
+ # Restart httpd since we changed it's config and added ipa-pki-proxy.conf
+ if postinstall:
+ ipaservices.knownservices.httpd.restart()
+
+
+ # The dogtag DS instance needs to be restarted after installation.
+ # The procedure for this is: stop dogtag, stop DS, start DS, start
+ # dogtag
+
+ service.print_msg("Restarting the directory and DRM servers")
+ drm.stop(dogtag.install_constants.PKI_INSTANCE_NAME)
+ ipaservices.knownservices.dirsrv.restart()
+ drm.start(dogtag.install_constants.PKI_INSTANCE_NAME)
+
+ return drm
+
+if __name__ == "__main__":
+ standard_logging_setup("install.log")
+ ds = dsinstance.DsInstance()
+
+ drm = DRMInstance("EXAMPLE.COM")
+ drm.configure_instance("drmtest.example.com", "example.com",
+ "password", "password")