Attached is a patch that adds the script ipa-drm-install. This script will be used to install a drm in any ipa server that contains a Dogtag CA. Right now, it works for a master. I will add logic in a subsequent patch to allow the installation on a replica using the same script.
This patch is to applied on top of the previous one. So, patch 2 and then patch 3. I will create a patch to address the issues mentioned below, as well as some other formatting issues reported by pycharm. Thanks, Ade On Tue, 2014-04-15 at 11:41 -0400, Rob Crittenden wrote: > Ade Lee wrote: > > Attached a new patch to address some of the concerns below, specifically > > I created a new base class DogtagInstance, in which much of the common > > CA/KRA code is placed. I'm sure we could go further in reducing > > duplication, and I'm open to further suggestions and refinements. > > > > I did not tackle the packaging and spec file dependencies, because I'd > > like some clearer direction on how we want to proceed here. In any > > case, I think the splitting of the ipa packages into ca and possibly kra > > packages should be a separate patch. > > > > As before, with this patch you can: > > - install a ca and drm using ipa-server-install > > - install a ca and drm replica using > > ipa-replica-prepare <hostname> > > ipa-replica-install --setup-ca --setup-drm <replia file> > > > > You need to use a PKI build from the 10.2 (master) branch). One such > > build is given below: > > http://copr.fedoraproject.org/coprs/vakwetu/dogtag/repo/fedora-20-x86_64/vakwetu-dogtag-fedora-20-x86_64.repo > > The terms KRA and DRM tend to be used interchangeably. Should we pick one? > > Need to bump the version number in install/conf/ipa-pki-proxy.conf so > that upgrades get the new LocationMatch. > > ipa-replica-install still uses the if/then to set the value of > enable_drm when it can be reduced like you did in ipa-server-install. > > In ipa-server-install you have an extra comment, probably left for > yourself: # code to create drm here > > In dogtaginstance.py there are a few direct references to DRM in > comments and output. > > cainstance.py doesn't need to override is_installed.py > > I also don't think you need the explicit definitions for enable, > start_instance, etc. Those should be inherited from the DogtagInstance > class, in both cainstance.py and drminstance.py. > > I think spawn_instance should take an option to add things to nolog in > case there are server-independent things we don't want to log. > > I don't want to pile too much on, but it seems to me that if we are > going to copy in default.conf then we can do away with realm_info > completely and just use default.conf. Both would need to be supported > for a while though. Martin, what do you think? > > I still have quite a bit of functional testing to go. I've only > installed a fresh standalone master. Still need to do upgrade and > replication testing. > > rob >
>From fa31152ca6ff6bf5d6401b7bcf726a65e3904835 Mon Sep 17 00:00:00 2001 From: Ade Lee <[email protected]> Date: Tue, 15 Apr 2014 14:09:32 -0400 Subject: [PATCH] Added ipa-drm-install ipa-drm-install can be used (with no arguments) to add a DRM to an existing ipa instance that already contains a Dogtag CA. In a subsequent patch, I will add logic to this script to detect if a drm naming context exists, and if so, to look for a replica file for installing on a replica. --- freeipa.spec.in | 2 + install/po/Makefile.in | 1 + install/tools/Makefile.am | 1 + install/tools/ipa-dns-install | 1 + install/tools/ipa-drm-install | 196 ++++++++++++++++++++++++++++++++++++++ install/tools/ipa-upgradeconfig | 67 +------------ ipaserver/install/drminstance.py | 4 + ipaserver/install/dsinstance.py | 77 +++++++++++++++ ipaserver/install/installutils.py | 25 +++-- 9 files changed, 297 insertions(+), 77 deletions(-) create mode 100644 install/tools/ipa-drm-install diff --git a/freeipa.spec.in b/freeipa.spec.in index 8ae5e2e083e960c034c738b01d0655575253b6f7..bff9c1acc957dd2d963e15d4c4928f61e37f1d7c 100644 --- a/freeipa.spec.in +++ b/freeipa.spec.in @@ -143,6 +143,7 @@ Requires: selinux-policy >= 3.12.1-135 Requires(post): selinux-policy-base Requires: slapi-nis >= 0.47.7 Requires: pki-ca >= 10.1.1 +Requires: pki-kra >= 10.1.1 Requires: dogtag-pki-server-theme %if 0%{?rhel} Requires: subscription-manager @@ -622,6 +623,7 @@ fi %{_sbindir}/ipa-restore %{_sbindir}/ipa-ca-install %{_sbindir}/ipa-dns-install +%{_sbindir}/ipa-drm-install %{_sbindir}/ipa-server-install %{_sbindir}/ipa-replica-conncheck %{_sbindir}/ipa-replica-install diff --git a/install/po/Makefile.in b/install/po/Makefile.in index 6dca615c13acf8d40030da0318a1103f4ece1181..c8d7b6353e2b2b00f6e9e6f8cfe3bcc8f84ae73f 100644 --- a/install/po/Makefile.in +++ b/install/po/Makefile.in @@ -47,6 +47,7 @@ PY_EXPLICIT_FILES = \ install/tools/ipa-csreplica-manage \ install/tools/ipactl \ install/tools/ipa-dns-install \ + install/tools/ipa-drm-install \ install/tools/ipa-ldap-updater \ install/tools/ipa-managed-entries \ install/tools/ipa-nis-manage \ diff --git a/install/tools/Makefile.am b/install/tools/Makefile.am index 2cf66c6dfc1c272bb423253902e7339e7d159567..7f8e4a5a0217327662b57921314fcb03f60dc46c 100644 --- a/install/tools/Makefile.am +++ b/install/tools/Makefile.am @@ -7,6 +7,7 @@ SUBDIRS = \ sbin_SCRIPTS = \ ipa-ca-install \ ipa-dns-install \ + ipa-drm-install \ ipa-server-install \ ipa-adtrust-install \ ipa-replica-conncheck \ diff --git a/install/tools/ipa-dns-install b/install/tools/ipa-dns-install index d87007d2f67e0c652bb8084198393f878e0f0a9b..0a1da65de627de71e4d51c9d652cb5244ef14d47 100755 --- a/install/tools/ipa-dns-install +++ b/install/tools/ipa-dns-install @@ -31,6 +31,7 @@ from ipapython import ipautil, sysrestore from ipalib import api, errors, util from ipapython.config import IPAOptionParser from ipapython.ipa_log_manager import standard_logging_setup, root_logger +from ipapython.ipautil import DN log_file_name = "/var/log/ipaserver-install.log" diff --git a/install/tools/ipa-drm-install b/install/tools/ipa-drm-install new file mode 100644 index 0000000000000000000000000000000000000000..7af39a3c749964d93a87bc4b58f1f41f8bc87269 --- /dev/null +++ b/install/tools/ipa-drm-install @@ -0,0 +1,196 @@ +#! /usr/bin/python2 -E +# Authors: Ade Lee <[email protected]> +# +# 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 os +import sys +from ConfigParser import SafeConfigParser, NoOptionError + +from ipalib import api +from ipaserver.install import drminstance +from ipaserver.install import dsinstance +from ipaserver.install import installutils +from ipapython import version +from ipaserver.install.installutils import read_password +from ipapython import certmonger +from ipapython.ipa_log_manager import * +from ipapython import dogtag +from ipapython.config import IPAOptionParser +from ipapython import services as ipaservices + + +log_file_name = "/var/log/ipa-drm-install.log" + + +def uninstall(realm_name): + dogtag_constants = dogtag.configured_constants() + + drm_instance = drminstance.DRMInstance( + realm_name, dogtag_constants=dogtag_constants) + drm_instance.stop_tracking_certificates(dogtag_constants) + if drm_instance.is_installed(): + drm_instance.uninstall() + + dirs = [dogtag_constants.ALIAS_DIR] + ids = certmonger.check_state(dirs) + if ids: + root_logger.error( + "Some certificates may still be tracked by certmonger.\n" + "This will cause re-installation to fail.\n" + "Start the certmonger service and list the certificates being tracked\n" + "# getcert list\nThese may be untracked by executing\n" + "# getcert stop-tracking -i <request_id>\n" + "for each id in: %s" + % ', '.join(ids)) + + +def parse_options(): + usage = "%prog [options]" + parser = IPAOptionParser(usage=usage, version=version.VERSION) + parser.add_option("-d", "--debug", dest="debug", action="store_true", + default=False, help="gather extra debugging information") + parser.add_option("-p", "--password", dest="password", sensitive=True, + help="Directory Manager (existing master) password") + parser.add_option("-U", "--unattended", dest="unattended", + action="store_true", default=False, + help="unattended installation never prompts the user") + parser.add_option("", "--uninstall", dest="uninstall", + action="store_true", default=False, + help="uninstall an existing installation. The uninstall can " + "be run with --unattended option") + + options, args = parser.parse_args() + safe_options = parser.get_safe_opts(options) + + return safe_options, options + + +def main(): + log_file = "/var/log/ipa-drm-install.log" + safe_options, options = parse_options() + + if os.geteuid() != 0: + sys.exit("\nYou must be root to run this script.\n") + + if options.uninstall: + log_file = "/var/log/ipa-drm-uninstall.log" + + standard_logging_setup(log_file, debug=options.debug) + + print "\nThe log file for this operation can be found in " + log_file_name + root_logger.debug('%s was invoked with options: %s' % + (sys.argv[0], safe_options)) + + if options.unattended and options.password is None: + sys.exit("Directory Manager password must be specified using -p" + " in unattended mode") + + dm_password = options.password or \ + read_password("Directory Manager", confirm=False) + if dm_password is None: + sys.exit("Directory Manager password required") + + p = SafeConfigParser() + p.read("/etc/ipa/default.conf") + + try: + host_name = p.get('global', 'host') + realm_name = p.get('global', 'realm') + domain_name = p.get('global', 'domain') + except NoOptionError as e: + print "\nA required parameter is missing from /etc/ipa/default.conf\n" + raise e + + try: + dogtag_version = int(p.get('global', 'dogtag_version')) + ra_plugin = p.get('global', 'ra_plugin') + enable_ra = p.get('global', 'enable_ra') + except NoOptionError as e: + print "\nA Dogtag CA must first be installed, or a required " \ + "parameter is missing from /etc/ipa/default.conf\n" + raise e + + try: + enable_drm = p.get('global', 'enable_drm') + except NoOptionError: + enable_drm = None + + subject = dsinstance.DsInstance().find_subject_base() + + if options.uninstall: + if enable_drm is None: + sys.exit("There is no DRM installed on this system") + uninstall(realm_name) + + if enable_drm is not None and enable_drm == 'True': + sys.exit("DRM is already installed.") + + if enable_ra is not None and enable_ra == "True" and \ + ra_plugin is not None and ra_plugin == "dogtag": + if dogtag_version is not None and dogtag_version >= 10: + # correct dogtag version of CA installed + pass + else: + sys.exit("Dogtag must be version 10.1 or above to install DRM") + else: + sys.exit("Dogtag CA is not installed. Please install the CA first") + + # Initialize the ipalib api + cfg = dict( + in_server=True, + debug=options.debug, + ) + api.bootstrap(**cfg) + api.finalize() + + print "==============================================================================" + print "This program will setup Dogtag DRM for the FreeIPA Server." + print "" + + drm = drminstance.DRMInstance(realm_name, + dogtag_constants=dogtag.install_constants) + + drm.configure_instance(host_name, domain_name, dm_password, + dm_password, subject_base=subject) + + drm.enable_client_auth_to_db(drm.dogtag_constants.DRM_CS_CFG_PATH) + + # Restart apache for new proxy config file + ipaservices.knownservices.httpd.restart(capture_output=True) + + try: + with open("/etc/ipa/default.conf", "a") as fd: + fd.write("drm_enabled=True") + except IOError, e: + print "Failed to update /etc/ipa/default.conf" + root_logger.error(str(e)) + sys.exit(1) + + +fail_message = ''' +Your system may be partly configured. +Run /usr/sbin/ipa-drm-install --uninstall to clean up. +''' + +if __name__ == '__main__': + with installutils.private_ccache(): + installutils.run_script(main, log_file_name=log_file_name, + operation_name='ipa-drm-add', + fail_message=fail_message) diff --git a/install/tools/ipa-upgradeconfig b/install/tools/ipa-upgradeconfig index 87338d580b5be769e502d580cfbfa7c361fcde7c..267d5231576e6a3416d1a2c8ecf880b00b8fdbe5 100644 --- a/install/tools/ipa-upgradeconfig +++ b/install/tools/ipa-upgradeconfig @@ -40,9 +40,10 @@ from ipapython.config import IPAOptionParser from ipapython.ipa_log_manager import * from ipapython import certmonger from ipapython import dogtag -from ipaserver.install import installutils + from ipaserver.install import dsinstance from ipaserver.install import httpinstance +from ipaserver.install import installutils from ipaserver.install import memcacheinstance from ipaserver.install import bindinstance from ipaserver.install import service @@ -51,7 +52,6 @@ from ipaserver.install import certs from ipaserver.install import otpdinstance from ipaserver.install import sysupgrade - def parse_options(): parser = IPAOptionParser(version=version.VERSION) parser.add_option("-d", "--debug", dest="debug", action="store_true", @@ -824,66 +824,7 @@ def find_subject_base(): 3) Last resort, look in the certmap.conf itself 4) If all fails, log loudly and return None """ - root_logger.debug('Trying to find certificate subject base in sysupgrade') - subject_base = sysupgrade.get_upgrade_state('certmap.conf', 'subject_base') - - if subject_base: - root_logger.debug( - 'Found certificate subject base in sysupgrade: %s', - subject_base - ) - return subject_base - - root_logger.debug('Unable to find certificate subject base in sysupgrade') - root_logger.debug('Trying to find certificate subject base in DS') - - ds_is_running = services.knownservices.dirsrv.is_running() - if not ds_is_running: - try: - services.knownservices.dirsrv.start() - except ipautil.CalledProcessError as e: - root_logger.error('Cannot start DS to find certificate ' - 'subject base: %s', e) - else: - ds_is_running = True - - if ds_is_running: - try: - api.Backend.ldap2.connect(autobind=True) - except ipalib.errors.PublicError, e: - root_logger.error('Cannot connect to DS to find certificate ' - 'subject base: %s', e) - else: - ret = api.Command['config_show']() - api.Backend.ldap2.disconnect() - subject_base = str(ret['result']['ipacertificatesubjectbase'][0]) - root_logger.debug( - 'Found certificate subject base in DS: %s', - subject_base - ) - - if not subject_base: - root_logger.debug('Unable to find certificate subject base in DS') - root_logger.debug('Trying to find certificate subject base in ' - 'certmap.conf') - - certmap_dir = dsinstance.config_dirname( - dsinstance.realm_to_serverid(api.env.realm) - ) - try: - with open(os.path.join(certmap_dir, 'certmap.conf')) as f: - for line in f: - if line.startswith('certmap ipaca'): - subject_base = line.strip().split(',')[-1] - root_logger.debug( - 'Found certificate subject base in certmap.conf: ' - '%s', - subject_base - ) - - except IOError as e: - root_logger.error('Cannot open certmap.conf to find certificate ' - 'subject base: %s', e.strerror) + subject_base = dsinstance.DsInstance().find_subject_base() if subject_base: sysupgrade.set_upgrade_state( @@ -893,8 +834,6 @@ def find_subject_base(): ) return subject_base - root_logger.debug('Unable to find certificate subject base in ' - 'certmap.conf') root_logger.error('Unable to determine certificate subject base. ' 'certmap.conf will not be updated.') diff --git a/ipaserver/install/drminstance.py b/ipaserver/install/drminstance.py index 744b0973d7f4e0015279ce39e55bb85344237cf8..6eab9d8221d52351bdac4bfdf723c4a5474c9d9b 100644 --- a/ipaserver/install/drminstance.py +++ b/ipaserver/install/drminstance.py @@ -51,6 +51,10 @@ class DRMInstance(DogtagInstance): """ def __init__(self, realm, dogtag_constants=None): + """ + + :rtype : DRMInstance + """ if dogtag_constants is None: dogtag_constants = dogtag.configured_constants() diff --git a/ipaserver/install/dsinstance.py b/ipaserver/install/dsinstance.py index 9256c12449b69e7752d421a3a3947d0feabfe840..5c20860fcb04d14ef6fadd41fcc54159cc78b740 100644 --- a/ipaserver/install/dsinstance.py +++ b/ipaserver/install/dsinstance.py @@ -39,6 +39,7 @@ import ldap from ipaserver.install import ldapupdate from ipaserver.install import replication from ipaserver.install import sysupgrade +from ipalib import api from ipalib import errors from ipalib.constants import CACERT from ipapython.dn import DN @@ -933,3 +934,79 @@ class DsInstance(service.Service): pass self.ldap_disconnect() + + def find_subject_base(self): + """ + Try to find the current value of certificate subject base. + 1) Look in sysupgrade first + 2) If no value is found there, look in DS (start DS if necessary) + 3) Last resort, look in the certmap.conf itself + 4) If all fails, log loudly and return None + """ + root_logger.debug( + 'Trying to find certificate subject base in sysupgrade') + subject_base = sysupgrade.get_upgrade_state( + 'certmap.conf', 'subject_base') + + if subject_base: + root_logger.debug( + 'Found certificate subject base in sysupgrade: %s', + subject_base) + return subject_base + + root_logger.debug( + 'Unable to find certificate subject base in sysupgrade') + root_logger.debug( + 'Trying to find certificate subject base in DS') + + ds_is_running = is_ds_running() + if not ds_is_running: + try: + self.start() + except ipautil.CalledProcessError as e: + root_logger.error('Cannot start DS to find certificate ' + 'subject base: %s', e) + else: + ds_is_running = True + + if ds_is_running: + try: + api.Backend.ldap2.connect(autobind=True) + except errors.PublicError, e: + root_logger.error('Cannot connect to DS to find certificate ' + 'subject base: %s', e) + else: + ret = api.Command['config_show']() + api.Backend.ldap2.disconnect() + subject_base = str( + ret['result']['ipacertificatesubjectbase'][0]) + root_logger.debug( + 'Found certificate subject base in DS: %s', subject_base) + + if not subject_base: + root_logger.debug('Unable to find certificate subject base in DS') + root_logger.debug('Trying to find certificate subject base in ' + 'certmap.conf') + + certmap_dir = config_dirname( + realm_to_serverid(api.env.realm) + ) + try: + with open(os.path.join(certmap_dir, 'certmap.conf')) as f: + for line in f: + if line.startswith('certmap ipaca'): + subject_base = line.strip().split(',')[-1] + root_logger.debug( + 'Found certificate subject base in certmap.conf: ' + '%s', subject_base) + + except IOError as e: + root_logger.error('Cannot open certmap.conf to find certificate ' + 'subject base: %s', e.strerror) + + if subject_base: + return subject_base + + root_logger.debug('Unable to find certificate subject base in ' + 'certmap.conf') + return None diff --git a/ipaserver/install/installutils.py b/ipaserver/install/installutils.py index d7d8160d010b6dd8d424fbed3ee87f8aa528202a..7ae541393bb00822dcc619dfb1be549e8aaa4017 100644 --- a/ipaserver/install/installutils.py +++ b/ipaserver/install/installutils.py @@ -40,7 +40,6 @@ from ipapython.ipa_log_manager import * from ipalib.util import validate_hostname from ipapython import config from ipalib import errors -from ipapython.dn import DN from ipaserver.install import certs from ipapython import services as ipaservices @@ -172,7 +171,7 @@ def verify_fqdn(host_name, no_host_dns=False, local_hostname=True): raise HostReverseLookupError("The host name %s does not match the reverse lookup %s" % (host_name, revname)) verified.add(address) -def record_in_hosts(ip, host_name=None, file="/etc/hosts"): +def record_in_hosts(ip, host_name=None, conf_file="/etc/hosts"): """ Search record in /etc/hosts - static table lookup for hostnames @@ -182,9 +181,9 @@ def record_in_hosts(ip, host_name=None, file="/etc/hosts"): :param ip: IP address :param host_name: Optional hostname to search - :param file: Optional path to the lookup table + :param conf_file: Optional path to the lookup table """ - hosts = open(file, 'r').readlines() + hosts = open(conf_file, 'r').readlines() for line in hosts: line = line.rstrip('\n') fields = line.partition('#')[0].split() @@ -204,13 +203,13 @@ def record_in_hosts(ip, host_name=None, file="/etc/hosts"): return None return (hosts_ip, names) except IndexError: - print "Warning: Erroneous line '%s' in %s" % (line, file) + print "Warning: Erroneous line '%s' in %s" % (line, conf_file) continue return None -def add_record_to_hosts(ip, host_name, file="/etc/hosts"): - hosts_fd = open(file, 'r+') +def add_record_to_hosts(ip, host_name, conf_file="/etc/hosts"): + hosts_fd = open(conf_file, 'r+') hosts_fd.seek(0, 2) hosts_fd.write(ip+'\t'+host_name+' '+host_name.split('.')[0]+'\n') hosts_fd.close() @@ -502,7 +501,7 @@ def get_server_ip_address(host_name, fstore, unattended, options): sys.exit(1) return ip - + def expand_replica_info(filename, password): """ Decrypt and expand a replica installation file into a temporary @@ -510,20 +509,20 @@ def expand_replica_info(filename, password): """ top_dir = tempfile.mkdtemp("ipa") tarfile = top_dir+"/files.tar" - dir = top_dir + "/realm_info" + dir_path = top_dir + "/realm_info" ipautil.decrypt_file(filename, tarfile, password, top_dir) ipautil.run(["tar", "xf", tarfile, "-C", top_dir]) os.remove(tarfile) - return top_dir, dir + return top_dir, dir_path -def read_replica_info(dir, rconfig): +def read_replica_info(dir_path, rconfig): """ Read the contents of a replica installation file. rconfig is a ReplicaConfig object """ - filename = dir + "/realm_info" + filename = dir_path + "/realm_info" fd = open(filename) config = SafeConfigParser() config.readfp(fd) @@ -779,7 +778,7 @@ def check_pkcs12(pkcs12_info, ca_file, hostname): raise ScriptError( '%s server certificates found in %s, expecting only one' % (len(server_certs), pkcs12_filename)) - [(server_cert_name, server_cert_trust)] = server_certs + [(server_cert_name, _server_cert_trust)] = server_certs # Check we have the whole cert chain & the CA is in it trust_chain = nssdb.get_trust_chain(server_cert_name) -- 1.9.0
_______________________________________________ Freeipa-devel mailing list [email protected] https://www.redhat.com/mailman/listinfo/freeipa-devel
