[Freeipa-devel] [PATCH] 6 - Dogtag DRM -IPA plugin

Fraser Tweedale ftweedal at redhat.com
Wed May 28 06:48:18 UTC 2014


On Tue, May 27, 2014 at 05:57:40PM -0400, Ade Lee wrote:
> There have been a couple of changes in the Dogtag interface, that
> require some changes in the IPA patches.  Also, I had to add back a
> function in order to rebase to the latest IPA code.
> 
> Most are the patches are as before, attached to this email by default.
> 
> The latest Dogtag 10.2 build with the relevant changes needed to work
> with these patches is at: 
> http://copr.fedoraproject.org/coprs/vakwetu/dogtag/
> 
> Ade
> 

ACK.

ipa-server-install worked fine for me, and the formatting changes
seem good.  Patch 0003 did not apply cleanly on master (due to minor
conflict in 71c6d2f:installutils.py); an updated patch 0003 is
attached.
-------------- next part --------------
>From d4bd77e498156a976a81bf6c166069087bcb4d8a Mon Sep 17 00:00:00 2001
From: Ade Lee <alee at redhat.com>
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 |  23 +++--
 9 files changed, 296 insertions(+), 76 deletions(-)
 create mode 100644 install/tools/ipa-drm-install

diff --git a/freeipa.spec.in b/freeipa.spec.in
index 7ed989ec33a423646a5a3925894b52b85b101ec9..98782477857830d184aa48fb3792a94bf223b749 100644
--- a/freeipa.spec.in
+++ b/freeipa.spec.in
@@ -145,6 +145,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
@@ -646,6 +647,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 78acc2d9bce02203cc97346b8797ec3ae40a3044..4684416685c06b919f3750f7a6cb064286b3b76d 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 <alee at 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 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 5f751becb1ab8604667e4f0d7a2f10a754ff7201..b45b3179abb877f876a16ccea61b8f72872cb8c7 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 32cf6bb707928bfc8c8286019593204370460bd3..c5a20a42acb9187b72fc456eae63d81a59da358c 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, service
 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()
@@ -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.3



More information about the Freeipa-devel mailing list