summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAde Lee <alee@redhat.com>2014-03-18 11:23:30 -0400
committerAde Lee <alee@redhat.com>2014-04-14 09:45:50 -0400
commitc701cd561d7ad9086e8c2ea7023cc2abd7abc868 (patch)
treeabb381546b04d9d9379249aeead85ae0c50f43f1
parentf10ec17c03dfe6bdf46903e89f68fa588664fdc0 (diff)
downloadfreeipa-alee_drm_install.tar.gz
freeipa-alee_drm_install.tar.xz
freeipa-alee_drm_install.zip
Add a DRM to IPAalee_drm_install
This patch adds the capability of installing a Dogtag DRM to an IPA instance. With this patch, when ipa-server-install is run, a Dogtag CA and a Dogtag DRM are created. The DRM shares the same tomcat instance and DS instance as the Dogtag CA. Moreover, the same admin user/agent (and agent cert) can be used for both subsystems. Certmonger is also confgured to monitor the new subsystem certificates. It is also possible to clone the DRM. When the IPA instance is cloned, if --enable-ca and --enable-drm are specified, the DRM is cloned as well. Installing a DRM requires the user to have a Dogtag CA instance. We can look into possibly relaxing that requirement in a later patch. The install scripts have been refactored somewhat to minimize duplication of code. A new base class dogtagintance.py has been introduced containing code that is common to DRM and CA installs. This will become very useful when we add more PKI subsystems. I am still working on patches for a ipa-drm-install script, which would be used to add a DRM to an existing master (that includes a dogtag CA), or an existing clone.
-rw-r--r--install/conf/ipa-pki-proxy.conf4
-rw-r--r--install/restart_scripts/renew_ca_cert13
-rwxr-xr-xinstall/tools/ipa-ca-install2
-rwxr-xr-xinstall/tools/ipa-replica-install31
-rwxr-xr-xinstall/tools/ipa-server-install37
-rw-r--r--install/tools/ipa-upgradeconfig2
-rw-r--r--ipapython/dogtag.py1
-rw-r--r--ipaserver/install/cainstance.py410
-rw-r--r--ipaserver/install/dogtaginstance.py311
-rw-r--r--ipaserver/install/drminstance.py337
-rw-r--r--ipaserver/install/installutils.py17
-rw-r--r--ipaserver/install/ipa_replica_prepare.py1
12 files changed, 869 insertions, 297 deletions
diff --git a/install/conf/ipa-pki-proxy.conf b/install/conf/ipa-pki-proxy.conf
index 224cdd45b..9a6345898 100644
--- a/install/conf/ipa-pki-proxy.conf
+++ b/install/conf/ipa-pki-proxy.conf
@@ -11,7 +11,7 @@ ProxyRequests Off
</LocationMatch>
# matches for admin port and installer
-<LocationMatch "^/ca/admin/ca/getCertChain|^/ca/admin/ca/getConfigEntries|^/ca/admin/ca/getCookie|^/ca/admin/ca/getStatus|^/ca/admin/ca/securityDomainLogin|^/ca/admin/ca/getDomainXML|^/ca/rest/installer/installToken|^/ca/admin/ca/updateNumberRange|^/ca/rest/securityDomain/domainInfo|^/ca/rest/account/login|^/ca/admin/ca/tokenAuthenticate|^/ca/admin/ca/updateNumberRange|^/ca/admin/ca/updateDomainXML|^/ca/rest/account/logout|^/ca/rest/securityDomain/installToken">
+<LocationMatch "^/ca/admin/ca/getCertChain|^/ca/admin/ca/getConfigEntries|^/ca/admin/ca/getCookie|^/ca/admin/ca/getStatus|^/ca/admin/ca/securityDomainLogin|^/ca/admin/ca/getDomainXML|^/ca/rest/installer/installToken|^/ca/admin/ca/updateNumberRange|^/ca/rest/securityDomain/domainInfo|^/ca/rest/account/login|^/ca/admin/ca/tokenAuthenticate|^/ca/admin/ca/updateNumberRange|^/ca/admin/ca/updateDomainXML|^/ca/rest/account/logout|^/ca/rest/securityDomain/installToken|^/ca/admin/ca/updateConnector|^/ca/admin/ca/getSubsystemCert|^/kra/admin/kra/updateNumberRange|^/kra/admin/kra/getConfigEntries">
NSSOptions +StdEnvVars +ExportCertData +StrictRequire +OptRenegotiate
NSSVerifyClient none
ProxyPassMatch ajp://localhost:$DOGTAG_PORT
@@ -19,7 +19,7 @@ ProxyRequests Off
</LocationMatch>
# matches for agent port and eeca port
-<LocationMatch "^/ca/agent/ca/displayBySerial|^/ca/agent/ca/doRevoke|^/ca/agent/ca/doUnrevoke|^/ca/agent/ca/updateDomainXML|^/ca/eeca/ca/profileSubmitSSLClient">
+<LocationMatch "^/ca/agent/ca/displayBySerial|^/ca/agent/ca/doRevoke|^/ca/agent/ca/doUnrevoke|^/ca/agent/ca/updateDomainXML|^/ca/eeca/ca/profileSubmitSSLClient|^/kra/agent/kra/connector">
NSSOptions +StdEnvVars +ExportCertData +StrictRequire +OptRenegotiate
NSSVerifyClient require
ProxyPassMatch ajp://localhost:$DOGTAG_PORT
diff --git a/install/restart_scripts/renew_ca_cert b/install/restart_scripts/renew_ca_cert
index 2663887d6..d9c98d5ce 100644
--- a/install/restart_scripts/renew_ca_cert
+++ b/install/restart_scripts/renew_ca_cert
@@ -21,17 +21,13 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
import sys
-import os
import syslog
-import tempfile
-import shutil
import traceback
-from ipapython import dogtag, certmonger, ipautil
+from ipapython import dogtag, ipautil
from ipapython import services as ipaservices
-from ipalib import api, errors, x509, util
-from ipaserver.install import certs, cainstance, installutils
-from ipaserver.plugins.ldap2 import ldap2
+from ipalib import api
+from ipaserver.install import certs, cainstance
def main():
nickname = sys.argv[1]
@@ -68,9 +64,8 @@ def main():
syslog.syslog(syslog.LOG_ERR, 'No certificate %s found.' % nickname)
sys.exit(1)
- cainstance.update_cert_config(nickname, cert, configured_constants)
-
ca = cainstance.CAInstance(api.env.realm, certs.NSS_DIR)
+ ca.update_cert_config(nickname, cert, configured_constants)
if ca.is_renewal_master():
cainstance.update_people_entry(cert)
diff --git a/install/tools/ipa-ca-install b/install/tools/ipa-ca-install
index 26f6993a0..a5801204f 100755
--- a/install/tools/ipa-ca-install
+++ b/install/tools/ipa-ca-install
@@ -183,7 +183,7 @@ def main():
ipautil.realm_to_suffix(config.realm_name))
# This is done within stopped_service context, which restarts CA
- CA.enable_client_auth_to_db()
+ CA.enable_client_auth_to_db(CA.dogtag_constants.CS_CFG_PATH)
# Install CA DNS records
install_dns_records(config, options)
diff --git a/install/tools/ipa-replica-install b/install/tools/ipa-replica-install
index f5e7197b5..192dc0d42 100755
--- a/install/tools/ipa-replica-install
+++ b/install/tools/ipa-replica-install
@@ -38,9 +38,10 @@ from ipaserver.install import otpdinstance
from ipaserver.install.replication import replica_conn_check, ReplicationManager
from ipaserver.install.installutils import (ReplicaConfig, expand_replica_info,
read_replica_info, get_host_name, BadHostError, private_ccache,
- read_replica_info_dogtag_port)
+ read_replica_info_dogtag_port, read_replica_info_drm_enabled)
from ipaserver.plugins.ldap2 import ldap2
from ipaserver.install import cainstance
+from ipaserver.install import drminstance
from ipalib import api, errors, util
from ipalib.constants import CACERT
from ipapython import version
@@ -63,6 +64,8 @@ def parse_options():
basic_group = OptionGroup(parser, "basic options")
basic_group.add_option("--setup-ca", dest="setup_ca", action="store_true",
default=False, help="configure a dogtag CA")
+ basic_group.add_option("--setup-drm", dest="setup_drm", action="store_true",
+ default=False, help="configure a dogtag DRM")
basic_group.add_option("--ip-address", dest="ip_address",
type="ip", ip_local=True,
help="Replica server IP Address")
@@ -540,6 +543,15 @@ def main():
print 'CA cannot be installed in CA-less setup.'
sys.exit(1)
+ config.setup_drm = options.setup_drm
+ if config.setup_drm:
+ if not config.setup_ca:
+ print "CA must be installed with the KRA"
+ sys.exit(1)
+ if not read_replica_info_drm_enabled(config.dir):
+ print "DRM is not installed on the master system"
+ sys.exit(1)
+
installutils.verify_fqdn(config.master_host_name, options.no_host_dns)
# check connection
@@ -573,6 +585,10 @@ def main():
else:
fd.write("enable_ra=False\n")
fd.write("ra_plugin=none\n")
+ if config.setup_drm:
+ fd.write("enable_drm=True\n")
+ else:
+ fd.write("enable_drm=False\n")
fd.write("mode=production\n")
fd.close()
finally:
@@ -683,7 +699,7 @@ def main():
ipautil.realm_to_suffix(config.realm_name))
# This is done within stopped_service context, which restarts CA
- CA.enable_client_auth_to_db()
+ CA.enable_client_auth_to_db(CA.dogtag_constants.CS_CFG_PATH)
krb = install_krb(config, setup_pkinit=options.setup_pkinit)
http = install_http(config, auto_redirect=options.ui_redirect)
@@ -706,9 +722,14 @@ def main():
service.print_msg("Applying LDAP updates")
ds.apply_updates()
- # Restart ds and krb after configurations have been changed
- service.print_msg("Restarting the directory server")
- ds.restart()
+ if options.setup_drm:
+ drm = drminstance.install_replica_drm(config)
+ service.print_msg("Restarting the directory server")
+ ds.restart()
+ drm.enable_client_auth_to_db(drm.dogtag_constants.DRM_CS_CFG_PATH)
+ else:
+ service.print_msg("Restarting the directory server")
+ ds.restart()
service.print_msg("Restarting the KDC")
krb.restart()
diff --git a/install/tools/ipa-server-install b/install/tools/ipa-server-install
index 34393b7df..46e5f180a 100755
--- a/install/tools/ipa-server-install
+++ b/install/tools/ipa-server-install
@@ -3,7 +3,7 @@
# Simo Sorce <ssorce@redhat.com>
# Rob Crittenden <rcritten@redhat.com>
#
-# Copyright (C) 2007-2010 Red Hat
+# Copyright (C) 2007-2014 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
@@ -53,6 +53,7 @@ from ipaserver.install import httpinstance
from ipaserver.install import ntpinstance
from ipaserver.install import certs
from ipaserver.install import cainstance
+from ipaserver.install import drminstance
from ipaserver.install import memcacheinstance
from ipaserver.install import otpdinstance
from ipaserver.install import sysupgrade
@@ -492,11 +493,19 @@ def uninstall():
dogtag_constants=dogtag_constants)
if cads_instance.is_configured():
cads_instance.uninstall()
- cainstance.stop_tracking_certificates(dogtag_constants)
+
+ drm_instance = drminstance.DRMInstance(
+ api.env.realm, dogtag_constants=dogtag_constants)
+ drm_instance.stop_tracking_certificates(dogtag_constants)
+ if drm_instance.is_installed():
+ drm_instance.uninstall()
+
ca_instance = cainstance.CAInstance(
api.env.realm, certs.NSS_DIR, dogtag_constants=dogtag_constants)
+ ca_instance.stop_tracking_certificates(dogtag_constants)
if ca_instance.is_configured():
ca_instance.uninstall()
+
bindinstance.BindInstance(fstore).uninstall()
httpinstance.HTTPInstance(fstore).uninstall()
krbinstance.KrbInstance(fstore).uninstall()
@@ -754,6 +763,7 @@ def main():
setup_ca = False
else:
setup_ca = True
+ setup_drm = True
# Figure out what external CA step we're in. See cainstance.py for more
# info on the 3 states.
@@ -770,6 +780,8 @@ def main():
print "This includes:"
if setup_ca:
print " * Configure a stand-alone CA (dogtag) for certificate management"
+ if setup_drm:
+ print " * Configure a stand-alone DRM (dogtag) for key storage"
if options.conf_ntp:
print " * Configure the Network Time Daemon (ntpd)"
print " * Create and configure an instance of Directory Server"
@@ -1016,6 +1028,7 @@ def main():
else:
fd.write("enable_ra=False\n")
fd.write("ra_plugin=none\n")
+ fd.write("enable_drm=%s\n" % setup_drm)
fd.write("mode=production\n")
fd.close()
@@ -1117,7 +1130,7 @@ def main():
ipautil.realm_to_suffix(realm_name), ['caRenewalMaster'])
# This is done within stopped_service context, which restarts CA
- ca.enable_client_auth_to_db()
+ ca.enable_client_auth_to_db(ca.dogtag_constants.CS_CFG_PATH)
krb = krbinstance.KrbInstance(fstore)
if options.pkinit_pkcs12:
@@ -1194,6 +1207,17 @@ def main():
service.print_msg("Restarting the web server")
http.restart()
+ if setup_drm:
+ # code to create drm here
+ drm = drminstance.DRMInstance(realm_name,
+ dogtag_constants=dogtag.install_constants)
+ drm.configure_instance(host_name, domain_name, dm_password,
+ dm_password, subject_base=options.subject)
+
+ # This is done within stopped_service context, which restarts DRM
+ ds.restart()
+ drm.enable_client_auth_to_db(drm.dogtag_constants.DRM_CS_CFG_PATH)
+
# Set the admin user kerberos password
ds.change_admin_password(admin_password)
@@ -1246,9 +1270,10 @@ def main():
print ""
if setup_ca:
- print "Be sure to back up the CA certificate stored in /root/cacert.p12"
- print "This file is required to create replicas. The password for this"
- print "file is the Directory Manager password"
+ print "Be sure to back up the CA certificates stored in /root/cacert.p12"
+ print "and the DRM certificates stored in /root/drmcert.p12"
+ print "These files are required to create replicas. The password for these"
+ print "files is the Directory Manager password"
else:
print "In order for Firefox autoconfiguration to work you will need to"
print "use a SSL signing certificate. See the IPA documentation for more details."
diff --git a/install/tools/ipa-upgradeconfig b/install/tools/ipa-upgradeconfig
index d77a33816..87338d580 100644
--- a/install/tools/ipa-upgradeconfig
+++ b/install/tools/ipa-upgradeconfig
@@ -675,7 +675,7 @@ def certificate_renewal_update(ca):
# Ok, now we need to stop tracking, then we can start tracking them
# again with new configuration:
- cainstance.stop_tracking_certificates(dogtag_constants)
+ ca.stop_tracking_certificates(dogtag_constants)
if not sysupgrade.get_upgrade_state('dogtag',
'certificate_renewal_update_1'):
diff --git a/ipapython/dogtag.py b/ipapython/dogtag.py
index f829b9340..8c6c8ff06 100644
--- a/ipapython/dogtag.py
+++ b/ipapython/dogtag.py
@@ -61,6 +61,7 @@ class Dogtag10Constants(object):
PASSWORD_CONF_PATH = '%s/conf/password.conf' % PKI_ROOT
SERVICE_PROFILE_DIR = '%s/ca/profiles/ca' % PKI_ROOT
ALIAS_DIR = '/etc/pki/pki-tomcat/alias'
+ DRM_CS_CFG_PATH = '%s/conf/kra/CS.cfg' % PKI_ROOT
SERVICE_NAME = 'pki_tomcatd'
diff --git a/ipaserver/install/cainstance.py b/ipaserver/install/cainstance.py
index f52870424..8d627efa3 100644
--- a/ipaserver/install/cainstance.py
+++ b/ipaserver/install/cainstance.py
@@ -19,51 +19,47 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
-import pwd
+import array
+import base64
+import binascii
+import ConfigParser
+import dbus
+import httplib
+import ldap
import os
-import sys
+import pwd
import re
+import shutil
+import stat
+import subprocess
+import sys
+import syslog
import time
-import ldap
-import base64
-import array
import tempfile
-import binascii
-import shutil
-import httplib
import urllib
import xml.dom.minidom
-import stat
-import syslog
-import ConfigParser
-import dbus
-from ipapython import dogtag
-from ipapython.certdb import get_ca_nickname
-from ipapython import certmonger
from ipalib import api
from ipalib import pkcs10, x509
from ipalib import errors
-from ipapython.dn import DN
-import subprocess
-import traceback
+from ipapython import dogtag
+from ipapython import certmonger
from ipapython import ipautil
from ipapython import services as ipaservices
from ipapython import ipaldap
-from ipaserver.install import service
-from ipaserver.install import installutils
-from ipaserver.install import dsinstance
-from ipaserver.install import certs
-from ipaserver.install.installutils import stopped_service
-from ipaserver.plugins import ldap2
+from ipapython.certdb import get_ca_nickname
+from ipapython.dn import DN
from ipapython.ipa_log_manager import *
-HTTPD_CONFD = "/etc/httpd/conf.d/"
-DEFAULT_DSPORT = dogtag.install_constants.DS_PORT
+from ipaserver.install import certs
+from ipaserver.install import dsinstance
+from ipaserver.install import installutils
+from ipaserver.install import service
+from ipaserver.install.dogtaginstance import DogtagInstance
+from ipaserver.install.dogtaginstance import PKI_USER, DEFAULT_DSPORT
+from ipaserver.plugins import ldap2
-PKI_USER = "pkiuser"
-PKI_DS_USER = dogtag.install_constants.DS_USER
# When IPA is installed with DNS support, this CNAME should hold all IPA
# replicas with CA configured
@@ -86,23 +82,6 @@ RootDNPwd= $PASSWORD
ConfigFile = /usr/share/pki/ca/conf/database.ldif
"""
-def check_inst():
- """
- Validate that the appropriate dogtag/RHCS packages have been installed.
- """
-
- # Check for a couple of binaries we need
- if not os.path.exists(dogtag.install_constants.SPAWN_BINARY):
- return False
- if not os.path.exists(dogtag.install_constants.DESTROY_BINARY):
- return False
-
- # This is the template tomcat file for a CA
- if not os.path.exists('/usr/share/pki/ca/conf/server.xml'):
- return False
-
- return True
-
def get_preop_pin(instance_root, instance_name):
# Only used for Dogtag 9
preop_pin = None
@@ -282,7 +261,7 @@ class CADSInstance(service.Service):
serverid = self.restore_state("serverid")
# Just eat this state if it exists
- running = self.restore_state("running")
+ _running = self.restore_state("running")
if not enabled is None and not enabled:
ipaservices.knownservices.dirsrv.disable()
@@ -295,40 +274,14 @@ class CADSInstance(service.Service):
dsdb.untrack_server_cert("Server-Cert")
dsinstance.erase_ds_instance_data(serverid)
- user_exists = self.restore_state("user_exists")
+ _user_exists = self.restore_state("user_exists")
# At one time we removed this user on uninstall. That can potentially
# orphan files, or worse, if another useradd runs in the intermim,
# cause files to have a new owner.
-def stop_tracking_certificates(dogtag_constants):
- """Stop tracking our certificates. Called on uninstall.
- """
- cmonger = ipaservices.knownservices.certmonger
- ipaservices.knownservices.messagebus.start()
- cmonger.start()
-
- for nickname in ['Server-Cert cert-pki-ca',
- 'auditSigningCert cert-pki-ca',
- 'ocspSigningCert cert-pki-ca',
- 'subsystemCert cert-pki-ca']:
- try:
- certmonger.stop_tracking(
- dogtag_constants.ALIAS_DIR, nickname=nickname)
- except (ipautil.CalledProcessError, RuntimeError), e:
- root_logger.error(
- "certmonger failed to stop tracking certificate: %s" % str(e))
-
- try:
- certmonger.stop_tracking('/etc/httpd/alias', nickname='ipaCert')
- except (ipautil.CalledProcessError, RuntimeError), e:
- root_logger.error(
- "certmonger failed to stop tracking certificate: %s" % str(e))
- cmonger.stop()
-
-
-class CAInstance(service.Service):
+class CAInstance(DogtagInstance):
"""
When using a dogtag CA the DS database contains just the
server cert for DS. The mod_nss database will contain the RA agent
@@ -349,19 +302,8 @@ class CAInstance(service.Service):
if dogtag_constants is None:
dogtag_constants = dogtag.configured_constants()
- service.Service.__init__(self,
- '%sd' % dogtag_constants.PKI_INSTANCE_NAME,
- service_desc="certificate server"
- )
-
- self.dogtag_constants = dogtag_constants
- self.realm = realm
- self.dm_password = None
- self.admin_password = None
- self.fqdn = None
- self.domain = None
- self.pkcs12_info = None
- self.clone = False
+ DogtagInstance.__init__(self, realm, "CA", "certificate server",
+ dogtag_constants)
# for external CAs
self.external = 0
@@ -370,23 +312,12 @@ class CAInstance(service.Service):
self.cert_chain_file = None
self.create_ra_agent_db = True
- # The same database is used for mod_nss because the NSS context
- # will already have been initialized by Apache by the time
- # mod_python wants to do things.
self.canickname = get_ca_nickname(realm)
- self.basedn = DN(('o', 'ipaca'))
- self.ca_agent_db = tempfile.mkdtemp(prefix = "tmp-")
self.ra_agent_db = ra_db
self.ra_agent_pwd = self.ra_agent_db + "/pwdfile.txt"
- self.ds_port = DEFAULT_DSPORT
- self.security_domain_name = "IPA"
- self.server_root = dogtag_constants.SERVER_ROOT
self.ra_cert = None
self.requestId = None
- def __del__(self):
- shutil.rmtree(self.ca_agent_db, ignore_errors=True)
-
def is_installed(self):
"""
Installing with an external CA is a two-step process. This
@@ -446,10 +377,10 @@ class CAInstance(service.Service):
if not ipautil.dir_exists("/var/lib/pki-ca"):
self.step("creating pki-ca instance", self.create_instance)
self.step("configuring certificate server instance", self.__configure_instance)
- self.step("stopping certificate server instance to update CS.cfg", self.__stop)
+ self.step("stopping certificate server instance to update CS.cfg", self.stop_instance)
self.step("disabling nonces", self.__disable_nonce)
self.step("set up CRL publishing", self.__enable_crl_publish)
- self.step("starting certificate server instance", self.__start)
+ self.step("starting certificate server instance", self.start_instance)
# Step 1 of external is getting a CSR so we don't need to do these
# steps until we get a cert back from the external CA.
if self.external != 1:
@@ -464,9 +395,10 @@ class CAInstance(service.Service):
self.step("enabling Subject Key Identifier", self.enable_subject_key_identifier)
self.step("enabling CRL and OCSP extensions for certificates", self.__set_crl_ocsp_extensions)
self.step("setting audit signing renewal to 2 years", self.set_audit_renewal)
- self.step("configuring certificate server to start on boot", self.__enable)
+ self.step("configuring certificate server to start on boot",
+ self.enable)
if not self.clone:
- self.step("restarting certificate server", self.__restart_instance)
+ self.step("restarting certificate server", self.restart_instance)
self.step("requesting RA certificate from CA", self.__request_ra_certificate)
self.step("issuing RA agent certificate", self.__issue_ra_cert)
self.step("adding RA agent as a trusted user", self.__configure_ra)
@@ -475,22 +407,31 @@ class CAInstance(service.Service):
if not self.clone:
self.step("configure RA certificate renewal", self.configure_agent_renewal)
self.step("configure Server-Cert certificate renewal", self.track_servercert)
- self.step("Configure HTTP to proxy connections", self.__http_proxy)
+ self.step("Configure HTTP to proxy connections",
+ self.http_proxy)
self.start_creation(runtime=210)
- def __stop(self):
- self.stop()
+ def enable(self):
+ DogtagInstance.enable(self)
+
+ def start_instance(self):
+ DogtagInstance.start_instance(self)
- def __start(self):
- self.start()
+ 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 CA instance using pkispawn.
- pkispawn requires a configuration file with IPA-specific
- parameters.
+ Creates the config file with IPA specific parameters
+ and passes it to the base class to call pkispawn
"""
# Create an empty and secured file
@@ -512,7 +453,7 @@ class CAInstance(service.Service):
config.set("CA", "pki_backup_password", self.admin_password)
# Client security database
- config.set("CA", "pki_client_database_dir", self.ca_agent_db)
+ config.set("CA", "pki_client_database_dir", self.agent_db)
config.set("CA", "pki_client_database_password", self.admin_password)
config.set("CA", "pki_client_database_purge", "False")
config.set("CA", "pki_client_pkcs12_password", self.admin_password)
@@ -589,21 +530,8 @@ class CAInstance(service.Service):
with open(cfg_file, "wb") as f:
config.write(f)
- # Define the things we don't want logged
- nolog = (self.admin_password, self.dm_password,)
-
- args = ["/usr/sbin/pkispawn", "-s", "CA", "-f", cfg_file ]
-
- with open(cfg_file) as f:
- root_logger.debug(
- 'Contents of pkispawn configuration file (%s):\n%s' %
- (cfg_file, ipautil.nolog_replace(f.read(), nolog)))
-
try:
- ipautil.run(args, nolog=nolog)
- except ipautil.CalledProcessError, e:
- root_logger.critical("failed to configure ca instance %s" % e)
- raise RuntimeError('Configuration of CA failed')
+ DogtagInstance.spawn_instance(self, cfg_file)
finally:
os.remove(cfg_file)
@@ -645,14 +573,6 @@ class CAInstance(service.Service):
]
ipautil.run(args, env={'PKI_HOSTNAME':self.fqdn})
- def __enable(self):
- self.backup_state("enabled", self.is_enabled())
- # We do not let the system start IPA components on its own,
- # Instead we reply on the IPA init script to start only enabled
- # components as found in our LDAP configuration tree
- # We need to install DS before we can actually ldap_enable a service.
- # so actual enablement is delayed.
-
def __create_ca_user(self):
try:
pwd.getpwnam(PKI_USER)
@@ -678,7 +598,7 @@ class CAInstance(service.Service):
args = ["/usr/bin/perl", "/usr/bin/pkisilent", "ConfigureCA",
"-cs_hostname", self.fqdn,
"-cs_port", str(self.dogtag_constants.ADMIN_SECURE_PORT),
- "-client_certdb_dir", self.ca_agent_db,
+ "-client_certdb_dir", self.agent_db,
"-client_certdb_pwd", self.admin_password,
"-preop_pin" , preop_pin,
"-domain_name", self.security_domain_name,
@@ -777,14 +697,6 @@ class CAInstance(service.Service):
root_logger.debug("completed creating ca instance")
- def __restart_instance(self):
- try:
- self.restart(self.dogtag_constants.PKI_INSTANCE_NAME)
- except Exception:
- # TODO: roll back here?
- root_logger.debug(traceback.format_exc())
- root_logger.critical("Failed to restart the certificate server. See the installation log for details.")
-
def __disable_nonce(self):
# Turn off Nonces
update_result = installutils.update_file(
@@ -804,7 +716,7 @@ class CAInstance(service.Service):
# Look thru the cert chain to get all the certs we need to add
# trust for
- p = subprocess.Popen(["/usr/bin/certutil", "-d", self.ca_agent_db,
+ p = subprocess.Popen(["/usr/bin/certutil", "-d", self.agent_db,
"-O", "-n", "ipa-ca-agent"], stdout=subprocess.PIPE)
chain = p.stdout.read()
@@ -823,7 +735,7 @@ class CAInstance(service.Service):
self.__run_certutil(
['-M', '-t', 'CT,C,C', '-n',
nick],
- database=self.ca_agent_db, pwd_file=self.admin_password)
+ database=self.agent_db, pwd_file=self.admin_password)
finally:
os.remove(admin_name)
@@ -839,12 +751,12 @@ class CAInstance(service.Service):
'-v',
'-n', 'ipa-ca-agent',
'-p', self.admin_password,
- '-d', self.ca_agent_db,
+ '-d', self.agent_db,
'-r', '/ca/agent/ca/profileReview?requestId=%s' % self.requestId,
'%s' % ipautil.format_netloc(
self.fqdn, self.dogtag_constants.AGENT_SECURE_PORT),
]
- (stdout, stderr, returncode) = ipautil.run(args, nolog=(self.admin_password,))
+ (stdout, _stderr, _returncode) = ipautil.run(args, nolog=(self.admin_password,))
data = stdout.split(self.dogtag_constants.RACERT_LINE_SEP)
params = get_defList(data)
@@ -860,13 +772,13 @@ class CAInstance(service.Service):
'-v',
'-n', 'ipa-ca-agent',
'-p', self.admin_password,
- '-d', self.ca_agent_db,
+ '-d', self.agent_db,
'-e', params,
'-r', '/ca/agent/ca/profileProcess',
'%s' % ipautil.format_netloc(
self.fqdn, self.dogtag_constants.AGENT_SECURE_PORT),
]
- (stdout, stderr, returncode) = ipautil.run(args, nolog=(self.admin_password,))
+ (stdout, _stderr, _returncode) = ipautil.run(args, nolog=(self.admin_password,))
data = stdout.split(self.dogtag_constants.RACERT_LINE_SEP)
outputList = get_outputList(data)
@@ -971,7 +883,7 @@ class CAInstance(service.Service):
os.close(f)
os.chmod(self.ra_agent_pwd, stat.S_IRUSR)
- (stdout, stderr, returncode) = self.__run_certutil(["-N"])
+ (_stdout, _stderr, _returncode) = self.__run_certutil(["-N"])
def __get_ca_chain(self):
try:
@@ -989,7 +901,7 @@ class CAInstance(service.Service):
ipautil.run(["/usr/bin/pk12util",
"-n", "ipa-ca-agent",
"-o", "/root/ca-agent.p12",
- "-d", self.ca_agent_db,
+ "-d", self.agent_db,
"-k", pwd_name,
"-w", pwd_name])
finally:
@@ -1007,7 +919,7 @@ class CAInstance(service.Service):
# makes openssl throw up.
data = base64.b64decode(chain)
- (certlist, stderr, returncode) = ipautil.run(["/usr/bin/openssl",
+ (certlist, _stderr, _returncode) = ipautil.run(["/usr/bin/openssl",
"pkcs7",
"-inform",
"DER",
@@ -1029,7 +941,7 @@ class CAInstance(service.Service):
(chain_fd, chain_name) = tempfile.mkstemp()
os.write(chain_fd, certlist[st:en+25])
os.close(chain_fd)
- (rdn, subject_dn) = certs.get_cert_nickname(certlist[st:en+25])
+ (_rdn, subject_dn) = certs.get_cert_nickname(certlist[st:en+25])
if subject_dn == ca_dn:
nick = get_ca_nickname(self.realm)
else:
@@ -1051,7 +963,10 @@ class CAInstance(service.Service):
# Generate our CSR. The result gets put into stdout
try:
- (stdout, stderr, returncode) = self.__run_certutil(["-R", "-k", "rsa", "-g", "2048", "-s", str(DN(('CN', 'IPA RA'), self.subject_base)), "-z", noise_name, "-a"])
+ (stdout, _stderr, _returncode) = self.__run_certutil(
+ ["-R", "-k", "rsa", "-g", "2048", "-s",
+ str(DN(('CN', 'IPA RA'), self.subject_base)),
+ "-z", noise_name, "-a"])
finally:
os.remove(noise_name)
@@ -1266,73 +1181,30 @@ class CAInstance(service.Service):
'OU=pki-ipa, O=IPA', str(self.subject_base)):
print "Updating subject_base in CA template failed"
- def enable_client_auth_to_db(self):
- """
- Enable client auth connection to the internal db.
- """
- caconfig = dogtag.install_constants.CS_CFG_PATH
-
- with stopped_service(self.dogtag_constants.SERVICE_NAME,
- instance_name=self.dogtag_constants.PKI_INSTANCE_NAME):
-
- # Enable file publishing, disable LDAP
- installutils.set_directive(caconfig,
- 'authz.instance.DirAclAuthz.ldap.ldapauth.authtype',
- 'SslClientAuth', quotes=False, separator='=')
- installutils.set_directive(caconfig,
- 'authz.instance.DirAclAuthz.ldap.ldapauth.bindDN',
- 'uid=pkidbuser,ou=people,o=ipa-ca', quotes=False, separator='=')
- installutils.set_directive(caconfig,
- 'authz.instance.DirAclAuthz.ldap.ldapauth.clientCertNickname',
- 'subsystemCert cert-pki-ca', quotes=False, separator='=')
- installutils.set_directive(caconfig,
- 'authz.instance.DirAclAuthz.ldap.ldapconn.port',
- str(dogtag.install_constants.DS_SECURE_PORT),
- quotes=False, separator='=')
- installutils.set_directive(caconfig,
- 'authz.instance.DirAclAuthz.ldap.ldapconn.secureConn',
- 'true', quotes=False, separator='=')
-
- installutils.set_directive(caconfig, 'internaldb.ldapauth.authtype',
- 'SslClientAuth', quotes=False, separator='=')
- installutils.set_directive(caconfig, 'internaldb.ldapauth.bindDN',
- 'uid=pkidbuser,ou=people,o=ipa-ca', quotes=False, separator='=')
- installutils.set_directive(caconfig,
- 'internaldb.ldapauth.clientCertNickname',
- 'subsystemCert cert-pki-ca', quotes=False, separator='=')
- installutils.set_directive(caconfig, 'internaldb.ldapconn.port',
- str(dogtag.install_constants.DS_SECURE_PORT),
- quotes=False, separator='=')
- installutils.set_directive(caconfig,
- 'internaldb.ldapconn.secureConn', 'true', quotes=False,
- separator='=')
-
def uninstall(self):
- if self.is_configured():
- self.print_msg("Unconfiguring CA")
-
enabled = self.restore_state("enabled")
if not enabled is None and not enabled:
self.disable()
- try:
- if self.dogtag_constants.DOGTAG_VERSION >= 10:
- ipautil.run(["/usr/sbin/pkidestroy", "-i",
- self.dogtag_constants.PKI_INSTANCE_NAME,
- "-s", "CA"])
- else:
+ if self.dogtag_constants.DOGTAG_VERSION >= 10:
+ DogtagInstance.uninstall(self)
+ else:
+ if self.is_configured():
+ self.print_msg("Unconfiguring CA")
+
+ try:
ipautil.run(["/usr/bin/pkiremove",
"-pki_instance_root=/var/lib",
"-pki_instance_name=%s" %
self.dogtag_constants.PKI_INSTANCE_NAME,
"--force"])
- except ipautil.CalledProcessError, e:
- root_logger.critical("failed to uninstall CA instance %s" % e)
+ except ipautil.CalledProcessError, e:
+ root_logger.critical("failed to uninstall CA instance %s" % e)
# At one time we removed this user on uninstall. That can potentially
# orphan files, or worse, if another useradd runs in the intermim,
# cause files to have a new owner.
- user_exists = self.restore_state("user_exists")
+ _user_exists = self.restore_state("user_exists")
ipaservices.knownservices.messagebus.start()
cmonger = ipaservices.knownservices.certmonger
@@ -1365,23 +1237,12 @@ class CAInstance(service.Service):
def publish_ca_cert(self, location):
args = ["-L", "-n", self.canickname, "-a"]
- (cert, err, returncode) = self.__run_certutil(args)
+ (cert, _err, _returncode) = self.__run_certutil(args)
fd = open(location, "w+")
fd.write(cert)
fd.close()
os.chmod(location, 0444)
- def __http_proxy(self):
- template_filename = ipautil.SHARE_DIR + "ipa-pki-proxy.conf"
- sub_dict = dict(
- DOGTAG_PORT=self.dogtag_constants.AJP_PORT,
- CLONE='' if self.clone else '#',
- FQDN=self.fqdn,
- )
- template = ipautil.template_file(template_filename, sub_dict)
- with open(HTTPD_CONFD + "ipa-pki-proxy.conf", "w") as fd:
- fd.write(template)
-
def configure_certmonger_renewal(self):
"""
Create a new CA type for certmonger that will retrieve updated
@@ -1425,24 +1286,14 @@ class CAInstance(service.Service):
'Unable to determine PIN for CA instance: %s' % e)
def configure_renewal(self):
- pin = self.__get_ca_pin()
+ """
+ Configure system certificates for renewal.
+ """
+ nicknames = ['auditSigningCert cert-pki-ca',
+ 'ocspSigningCert cert-pki-ca',
+ 'subsystemCert cert-pki-ca']
- # Server-Cert cert-pki-ca is renewed per-server
- for nickname in ['auditSigningCert cert-pki-ca',
- 'ocspSigningCert cert-pki-ca',
- 'subsystemCert cert-pki-ca']:
- try:
- certmonger.dogtag_start_tracking(
- ca='dogtag-ipa-ca-renew-agent',
- nickname=nickname,
- pin=pin,
- pinfile=None,
- secdir=self.dogtag_constants.ALIAS_DIR,
- pre_command='stop_pkicad',
- post_command='renew_ca_cert "%s"' % nickname)
- except (ipautil.CalledProcessError, RuntimeError), e:
- root_logger.error(
- "certmonger failed to start tracking certificate: %s" % e)
+ DogtagInstance.configure_renewal(self, nicknames)
def track_servercert(self):
"""
@@ -1464,6 +1315,26 @@ class CAInstance(service.Service):
root_logger.error(
"certmonger failed to start tracking certificate: %s" % e)
+ def stop_tracking_certificates(self, dogtag_constants):
+ """Stop tracking our certificates. Called on uninstall.
+ """
+ nicknames = ['Server-Cert cert-pki-ca',
+ 'auditSigningCert cert-pki-ca',
+ 'ocspSigningCert cert-pki-ca',
+ 'subsystemCert cert-pki-ca']
+ DogtagInstance.stop_tracking_certificates(
+ self, dogtag_constants, nicknames)
+
+ cmonger = ipaservices.knownservices.certmonger
+ ipaservices.knownservices.messagebus.start()
+ cmonger.start()
+ try:
+ certmonger.stop_tracking('/etc/httpd/alias', nickname='ipaCert')
+ except (ipautil.CalledProcessError, RuntimeError), e:
+ root_logger.error(
+ "certmonger failed to stop tracking certificate: %s" % str(e))
+ cmonger.stop()
+
def enable_subject_key_identifier(self):
"""
See if Subject Key Identifier is set in the profile and if not, add it.
@@ -1518,13 +1389,14 @@ class CAInstance(service.Service):
"""
# Check the default validity period of the audit signing cert
# and set it to 2 years if it is 6 months.
- range = installutils.get_directive(
+ cert_range = installutils.get_directive(
'%s/caSignedLogCert.cfg' % self.dogtag_constants.SERVICE_PROFILE_DIR,
'policyset.caLogSigningSet.2.default.params.range',
separator='='
)
- root_logger.debug('caSignedLogCert.cfg profile validity range is %s' % range)
- if range == "180":
+ root_logger.debug(
+ 'caSignedLogCert.cfg profile validity range is %s' % cert_range)
+ if cert_range == "180":
installutils.set_directive(
'%s/caSignedLogCert.cfg' % self.dogtag_constants.SERVICE_PROFILE_DIR,
'policyset.caLogSigningSet.2.default.params.range',
@@ -1549,15 +1421,39 @@ class CAInstance(service.Service):
dn = DN(('cn', 'CA'), ('cn', api.env.host), ('cn', 'masters'),
('cn', 'ipa'), ('cn', 'etc'), api.env.basedn)
- filter = '(ipaConfigString=caRenewalMaster)'
+ renewal_filter = '(ipaConfigString=caRenewalMaster)'
try:
- self.admin_conn.get_entries(base_dn=dn, filter=filter,
+ self.admin_conn.get_entries(base_dn=dn, filter=renewal_filter,
attrs_list=[])
except errors.NotFound:
return False
return True
+ def update_cert_config(self, nickname, cert, dogtag_constants=None):
+ """
+ When renewing a CA 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-ca': 'ca.audit_signing.cert',
+ 'ocspSigningCert cert-pki-ca': 'ca.ocsp_signing.cert',
+ 'caSigningCert cert-pki-ca': 'ca.signing.cert',
+ 'subsystemCert cert-pki-ca': 'ca.subsystem.cert',
+ 'Server-Cert cert-pki-ca': 'ca.sslserver.cert'}
+
+ DogtagInstance.update_cert_config(
+ self, nickname, cert, directives,
+ dogtag.configured_constants().CS_CFG_PATH,
+ dogtag_constants)
+
def replica_ca_install_check(config):
if not config.setup_ca:
@@ -1644,11 +1540,6 @@ def install_replica_ca(config, postinstall=False):
if ca.is_installed():
sys.exit("A CA is already configured on this system.")
- pkcs12_info = None
- if ipautil.file_exists(config.dir + "/dogtagcert.p12"):
- pkcs12_info = (config.dir + "/dogtagcert.p12",
- config.dir + "/dirsrv_pin.txt")
-
ca = CAInstance(config.realm_name, certs.NSS_DIR,
dogtag_constants=dogtag.install_constants)
if postinstall:
@@ -1687,33 +1578,6 @@ def install_replica_ca(config, postinstall=False):
return ca
-def update_cert_config(nickname, cert, dogtag_constants=None):
- """
- When renewing a CA 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-ca': 'ca.audit_signing.cert',
- 'ocspSigningCert cert-pki-ca': 'ca.ocsp_signing.cert',
- 'caSigningCert cert-pki-ca': 'ca.signing.cert',
- 'subsystemCert cert-pki-ca': 'ca.subsystem.cert',
- 'Server-Cert cert-pki-ca': 'ca.sslserver.cert'}
-
- with stopped_service(dogtag_constants.SERVICE_NAME,
- instance_name=dogtag_constants.PKI_INSTANCE_NAME):
-
- installutils.set_directive(dogtag.configured_constants().CS_CFG_PATH,
- directives[nickname],
- base64.b64encode(cert),
- quotes=False, separator='=')
-
def update_people_entry(dercert):
"""
Update the userCerticate for an entry in the dogtag ou=People. This
@@ -1749,11 +1613,11 @@ def update_people_entry(dercert):
conn.connect(
bind_dn=DN(('cn', 'directory manager')), bind_pw=dm_password)
- filter = conn.make_filter(
+ db_filter = conn.make_filter(
{'description': ';%s;%s' % (issuer, subject)},
exact=False, trailing_wildcard=False)
try:
- entries = conn.get_entries(base_dn, conn.SCOPE_SUBTREE, filter)
+ entries = conn.get_entries(base_dn, conn.SCOPE_SUBTREE, db_filter)
except errors.NotFound:
entries = []
diff --git a/ipaserver/install/dogtaginstance.py b/ipaserver/install/dogtaginstance.py
new file mode 100644
index 000000000..b482d8e08
--- /dev/null
+++ b/ipaserver/install/dogtaginstance.py
@@ -0,0 +1,311 @@
+# 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 base64
+import os
+import shutil
+import tempfile
+import traceback
+
+from ipapython import certmonger
+from ipapython import dogtag
+from ipapython import ipautil
+from ipapython import services as ipaservices
+from ipapython.dn import DN
+from ipaserver.install import service
+from ipaserver.install import installutils
+from ipaserver.install.installutils import stopped_service
+from ipapython.ipa_log_manager import *
+
+HTTPD_CONFD = "/etc/httpd/conf.d/"
+DEFAULT_DSPORT = dogtag.install_constants.DS_PORT
+
+PKI_USER = "pkiuser"
+PKI_DS_USER = dogtag.install_constants.DS_USER
+
+
+def check_inst(subsystem):
+ """
+ Validate that the appropriate dogtag/RHCS packages have been installed.
+ """
+
+ # Check for a couple of binaries we need
+ if not os.path.exists(dogtag.install_constants.SPAWN_BINARY):
+ return False
+ if not os.path.exists(dogtag.install_constants.DESTROY_BINARY):
+ return False
+
+ # This is the template tomcat file for a DRM
+ if not os.path.exists('/usr/share/pki/%s/conf/server.xml' % subsystem):
+ return False
+
+ return True
+
+class DogtagInstance(service.Service):
+ """
+ This is the base class for a Dogtag 10+ instance, which uses a
+ shared tomcat instance and DS to host the relevant subsystems.
+
+ It contains functions that will be common to installations of the
+ CA, KRA, and eventually TKS and TPS.
+ """
+
+ def __init__(self, realm, subsystem, service_desc, dogtag_constants=None):
+ if dogtag_constants is None:
+ dogtag_constants = dogtag.configured_constants()
+
+ service.Service.__init__(self,
+ '%sd' % dogtag_constants.PKI_INSTANCE_NAME,
+ service_desc=service_desc
+ )
+
+ self.dogtag_constants = dogtag_constants
+ self.realm = realm
+ self.dm_password = None
+ self.admin_password = None
+ self.fqdn = None
+ self.domain = None
+ self.pkcs12_info = None
+ self.clone = False
+
+ self.basedn = DN(('o', 'ipa%s' % subsystem.lower()))
+ self.agent_db = tempfile.mkdtemp(prefix = "tmp-")
+ self.ds_port = DEFAULT_DSPORT
+ self.server_root = dogtag_constants.SERVER_ROOT
+ self.subsystem = subsystem
+ self.security_domain_name = "IPA"
+ self.tracking_nicknames = None
+
+ def __del__(self):
+ shutil.rmtree(self.agent_db, ignore_errors=True)
+
+ def is_installed(self):
+ """
+ Determine if subsystem instance has been installed.
+
+ Returns True/False
+ """
+ return os.path.exists(os.path.join(
+ self.server_root, self.dogtag_constants.PKI_INSTANCE_NAME,
+ self.subsystem.lower()))
+
+ def spawn_instance(self, cfg_file):
+ """
+ Create and configure a new Dogtag instance using pkispawn.
+ Passes in a configuration file with IPA-specific
+ parameters.
+ """
+ subsystem = self.subsystem
+
+ # Define the things we don't want logged
+ nolog = (self.admin_password, self.dm_password,)
+
+ args = ["/usr/sbin/pkispawn",
+ "-s", subsystem,
+ "-f", cfg_file ]
+
+ with open(cfg_file) as f:
+ root_logger.debug(
+ 'Contents of pkispawn configuration file (%s):\n%s' %
+ (cfg_file, ipautil.nolog_replace(f.read(), nolog)))
+
+ try:
+ ipautil.run(args, nolog=nolog)
+ except ipautil.CalledProcessError, e:
+ root_logger.critical("failed to configure %s instance %s" %
+ (subsystem, e))
+ raise RuntimeError('Configuration of %s failed' % subsystem)
+
+ def enable(self):
+ self.backup_state("enabled", self.is_enabled())
+
+ def restart_instance(self):
+ try:
+ self.restart(self.dogtag_constants.PKI_INSTANCE_NAME)
+ except Exception:
+ root_logger.debug(traceback.format_exc())
+ root_logger.critical(
+ "Failed to restart the Dogtag instance."
+ "See the installation log for details.")
+
+ def start_instance(self):
+ try:
+ self.start(self.dogtag_constants.PKI_INSTANCE_NAME)
+ except Exception:
+ root_logger.debug(traceback.format_exc())
+ root_logger.critical(
+ "Failed to restart the Dogtag instance."
+ "See the installation log for details.")
+
+ def stop_instance(self):
+ try:
+ self.stop(self.dogtag_constants.PKI_INSTANCE_NAME)
+ except Exception:
+ root_logger.debug(traceback.format_exc())
+ root_logger.critical(
+ "Failed to restart the Dogtag instance."
+ "See the installation log for details.")
+
+ def enable_client_auth_to_db(self, config):
+ """
+ Enable client auth connection to the internal db.
+ Path to CS.cfg config file passed in.
+ """
+
+ with stopped_service(self.dogtag_constants.SERVICE_NAME,
+ instance_name=self.dogtag_constants.PKI_INSTANCE_NAME):
+
+ installutils.set_directive(config,
+ 'authz.instance.DirAclAuthz.ldap.ldapauth.authtype',
+ 'SslClientAuth', quotes=False, separator='=')
+ installutils.set_directive(config,
+ 'authz.instance.DirAclAuthz.ldap.ldapauth.bindDN',
+ 'uid=pkidbuser,ou=people,o=ipaca', quotes=False, separator='=')
+ installutils.set_directive(config,
+ 'authz.instance.DirAclAuthz.ldap.ldapauth.clientCertNickname',
+ 'subsystemCert cert-pki-ca', quotes=False, separator='=')
+ installutils.set_directive(config,
+ 'authz.instance.DirAclAuthz.ldap.ldapconn.port',
+ str(dogtag.install_constants.DS_SECURE_PORT),
+ quotes=False, separator='=')
+ installutils.set_directive(config,
+ 'authz.instance.DirAclAuthz.ldap.ldapconn.secureConn',
+ 'true', quotes=False, separator='=')
+
+ installutils.set_directive(config, 'internaldb.ldapauth.authtype',
+ 'SslClientAuth', quotes=False, separator='=')
+ installutils.set_directive(config, 'internaldb.ldapauth.bindDN',
+ 'uid=pkidbuser,ou=people,o=ipaca', quotes=False, separator='=')
+ installutils.set_directive(config,
+ 'internaldb.ldapauth.clientCertNickname',
+ 'subsystemCert cert-pki-ca', quotes=False, separator='=')
+ installutils.set_directive(config, 'internaldb.ldapconn.port',
+ str(dogtag.install_constants.DS_SECURE_PORT),
+ quotes=False, separator='=')
+ installutils.set_directive(config,
+ 'internaldb.ldapconn.secureConn', 'true', quotes=False,
+ separator='=')
+
+ def uninstall(self):
+ if self.is_installed():
+ self.print_msg("Unconfiguring %s" % self.subsystem)
+
+ try:
+ ipautil.run(["/usr/sbin/pkidestroy", "-i",
+ self.dogtag_constants.PKI_INSTANCE_NAME,
+ "-s", self.subsystem])
+ except ipautil.CalledProcessError, e:
+ root_logger.critical("failed to uninstall %s instance %s"
+ % (self.subsystem,e))
+
+ def http_proxy(self):
+ ''' Update the http proxy file '''
+ template_filename = ipautil.SHARE_DIR + "ipa-pki-proxy.conf"
+ sub_dict = dict(
+ DOGTAG_PORT=self.dogtag_constants.AJP_PORT,
+ CLONE='' if self.clone else '#',
+ FQDN=self.fqdn,
+ )
+ template = ipautil.template_file(template_filename, sub_dict)
+ with open(HTTPD_CONFD + "ipa-pki-proxy.conf", "w") as fd:
+ fd.write(template)
+
+ def __get_pin(self):
+ try:
+ return certmonger.get_pin('internal',
+ dogtag_constants=self.dogtag_constants)
+ except IOError, e:
+ root_logger.debug(
+ 'Unable to determine PIN for DRM instance: %s' % str(e))
+ raise RuntimeError(e)
+
+ def configure_renewal(self, nicknames=None):
+ ''' Configure certmonger to renew system certs
+
+ @param nickname: list of nicknames
+ '''
+ cmonger = ipaservices.knownservices.certmonger
+ cmonger.enable()
+ ipaservices.knownservices.messagebus.start()
+ cmonger.start()
+
+ pin = self.__get_pin()
+
+ if nicknames is None:
+ nicknames = self.tracking_nicknames
+
+ for nickname in nicknames:
+ try:
+ certmonger.dogtag_start_tracking(
+ ca='dogtag-ipa-ca-renew-agent',
+ nickname=nickname,
+ pin=pin,
+ pinfile=None,
+ secdir=self.dogtag_constants.ALIAS_DIR,
+ pre_command='stop_pkicad',
+ post_command='renew_ca_cert "%s"' % nickname)
+ except (ipautil.CalledProcessError, RuntimeError), e:
+ root_logger.error(
+ "certmonger failed to start tracking certificate: %s" %
+ str(e))
+
+ def stop_tracking_certificates(self, dogtag_constants, nicknames = None):
+ """Stop tracking our certificates. Called on uninstall.
+ """
+ cmonger = ipaservices.knownservices.certmonger
+ ipaservices.knownservices.messagebus.start()
+ cmonger.start()
+
+ if nicknames is None:
+ nicknames = self.tracking_nicknames
+
+ for nickname in nicknames:
+ try:
+ certmonger.stop_tracking(
+ dogtag_constants.ALIAS_DIR, nickname=nickname)
+ except (ipautil.CalledProcessError, RuntimeError), e:
+ root_logger.error(
+ "certmonger failed to stop tracking certificate: %s"
+ % str(e))
+
+ cmonger.stop()
+
+ def update_cert_config(self, nickname, cert, directives, cs_cfg,
+ 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.
+ directives is the list of directives to be updated for the subsystem
+ cs_cfg is the path to the CS.cfg file
+ """
+
+ if dogtag_constants is None:
+ dogtag_constants = dogtag.configured_constants()
+
+ with stopped_service(dogtag_constants.SERVICE_NAME,
+ instance_name=dogtag_constants.PKI_INSTANCE_NAME):
+ installutils.set_directive(
+ cs_cfg,
+ directives[nickname],
+ base64.b64encode(cert),
+ quotes=False,
+ separator='=')
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")
diff --git a/ipaserver/install/installutils.py b/ipaserver/install/installutils.py
index daf81e890..d7d8160d0 100644
--- a/ipaserver/install/installutils.py
+++ b/ipaserver/install/installutils.py
@@ -554,6 +554,23 @@ def read_replica_info_dogtag_port(config_dir):
return dogtag_master_ds_port
+def read_replica_info_drm_enabled(config_dir):
+ """
+ Check the replica info to determine if a DRM has been installed
+ on the master
+ """
+ default_file = config_dir + "/default.conf"
+ if not ipautil.file_exists(default_file):
+ return False
+ else:
+ with open(default_file) as fd:
+ config = SafeConfigParser()
+ config.readfp(fd)
+
+ enable_drm = bool(config.get("global", "enable_drm"))
+ return enable_drm
+
+
def check_server_configuration():
"""
Check if IPA server is configured on the system.
diff --git a/ipaserver/install/ipa_replica_prepare.py b/ipaserver/install/ipa_replica_prepare.py
index e71dd22e4..df3c1a17b 100644
--- a/ipaserver/install/ipa_replica_prepare.py
+++ b/ipaserver/install/ipa_replica_prepare.py
@@ -370,6 +370,7 @@ class ReplicaPrepare(admintool.AdminTool):
cacert_filename = "/var/kerberos/krb5kdc/cacert.pem"
if ipautil.file_exists(cacert_filename):
self.copy_info_file(cacert_filename, "cacert.pem")
+ self.copy_info_file("/etc/ipa/default.conf", "default.conf")
def save_config(self):
self.log.info("Finalizing configuration")