[Pki-devel] [PATCH] 641 Added CLI to update cert data and request in CS.cfg.

Endi Sukma Dewata edewata at redhat.com
Fri Sep 4 21:47:00 UTC 2015


On 9/1/2015 10:20 PM, Endi Sukma Dewata wrote:
> A set of new pki-server commands have been added to simplify
> updating the cert data and cert request stored in the CS.cfg with
> the cert data and cert request stored in the NSS and LDAP database,
> respectively.
>
> https://fedorahosted.org/pki/ticket/1551

ACKed by mharmsen. Fixed some pylint warnings. Pushed to master.

-- 
Endi S. Dewata
-------------- next part --------------
>From 9f7d83f0cfda059e7ceca41d7887c46bebb08f14 Mon Sep 17 00:00:00 2001
From: "Endi S. Dewata" <edewata at redhat.com>
Date: Wed, 2 Sep 2015 04:50:24 +0200
Subject: [PATCH] Added CLI to update cert data and request in CS.cfg.

A set of new pki-server commands have been added to simplify
updating the cert data and cert request stored in the CS.cfg with
the cert data and cert request stored in the NSS and LDAP database,
respectively.

https://fedorahosted.org/pki/ticket/1551
---
 base/server/python/pki/server/__init__.py      | 115 ++++++++-
 base/server/python/pki/server/ca.py            |  92 ++++++++
 base/server/python/pki/server/cli/ca.py        | 206 ++++++++++++++++
 base/server/python/pki/server/cli/subsystem.py | 313 +++++++++++++++++++++----
 base/server/python/pki/server/upgrade.py       |   3 +
 base/server/sbin/pki-server                    |   2 +
 6 files changed, 684 insertions(+), 47 deletions(-)
 create mode 100644 base/server/python/pki/server/ca.py
 create mode 100644 base/server/python/pki/server/cli/ca.py

diff --git a/base/server/python/pki/server/__init__.py b/base/server/python/pki/server/__init__.py
index 97b2e97992ad1daf0313127ce89f826cc3d0fb10..70e35b8f2c7bc66339dc315dcab946177d87d1a3 100644
--- a/base/server/python/pki/server/__init__.py
+++ b/base/server/python/pki/server/__init__.py
@@ -21,7 +21,11 @@
 
 from __future__ import absolute_import
 from lxml import etree
+import getpass
 import grp
+import io
+import ldap
+import operator
 import os
 import pwd
 import re
@@ -32,7 +36,7 @@ import pki
 INSTANCE_BASE_DIR = '/var/lib/pki'
 REGISTRY_DIR = '/etc/sysconfig/pki'
 SUBSYSTEM_TYPES = ['ca', 'kra', 'ocsp', 'tks', 'tps']
-
+SUBSYSTEM_CLASSES = {}
 
 class PKIServer(object):
 
@@ -66,6 +70,7 @@ class PKISubsystem(object):
             self.base_dir = instance.base_dir
 
         self.conf_dir = os.path.join(self.base_dir, 'conf')
+        self.cs_conf = os.path.join(self.conf_dir, 'CS.cfg')
 
         self.context_xml_template = os.path.join(
             pki.SHARE_DIR, self.name, 'conf', 'Catalina', 'localhost', self.name + '.xml')
@@ -73,9 +78,62 @@ class PKISubsystem(object):
         self.context_xml = os.path.join(
             instance.conf_dir, 'Catalina', 'localhost', self.name + '.xml')
 
+        self.config = {}
+        self.type = None
+        self.prefix = None
+
         # custom subsystem location
         self.doc_base = os.path.join(self.base_dir, 'webapps', self.name)
 
+    def load(self):
+        self.config.clear()
+
+        lines = open(self.cs_conf).read().splitlines()
+
+        for line in lines:
+            parts = line.split('=', 1)
+            name = parts[0]
+            value = parts[1]
+            self.config[name] = value
+
+        self.type = self.config['cs.type']
+        self.prefix = self.type.lower()
+
+    def find_subsystem_certs(self):
+        certs = []
+
+        cert_ids = self.config['%s.cert.list' % self.name].split(',')
+        for cert_id in cert_ids:
+            cert = self.create_subsystem_cert_object(cert_id)
+            certs.append(cert)
+
+        return certs
+
+    def get_subsystem_cert(self, cert_id):
+        return self.create_subsystem_cert_object(cert_id)
+
+    def create_subsystem_cert_object(self, cert_id):
+        cert = {}
+        cert['id'] = cert_id
+        cert['nickname'] = self.config.get('%s.%s.nickname' % (self.name, cert_id), None)
+        cert['token'] = self.config.get('%s.%s.tokenname' % (self.name, cert_id), None)
+        cert['data'] = self.config.get('%s.%s.cert' % (self.name, cert_id), None)
+        cert['request'] = self.config.get('%s.%s.certreq' % (self.name, cert_id), None)
+        return cert
+
+    def update_subsystem_cert(self, cert):
+        cert_id = cert['id']
+        self.config['%s.%s.nickname' % (self.name, cert_id)] = cert.get('nickname', None)
+        self.config['%s.%s.tokenname' % (self.name, cert_id)] = cert.get('token', None)
+        self.config['%s.%s.cert' % (self.name, cert_id)] = cert.get('data', None)
+        self.config['%s.%s.certreq' % (self.name, cert_id)] = cert.get('request', None)
+
+    def save(self):
+        sorted_config = sorted(self.config.items(), key=operator.itemgetter(0))
+        with io.open(self.cs_conf, 'wb') as f:
+            for (key, value) in sorted_config:
+                f.write('%s=%s\n' % (key, value))
+
     def is_valid(self):
         return os.path.exists(self.conf_dir)
 
@@ -103,6 +161,21 @@ class PKISubsystem(object):
     def disable(self):
         self.instance.undeploy(self.name)
 
+    def open_database(self, name='internaldb'):
+
+        hostname = self.config['%s.ldapconn.host' % name]
+        port = self.config['%s.ldapconn.port' % name]
+        bind_dn = self.config['%s.ldapauth.bindDN' % name]
+
+        # TODO: add support for other authentication
+        # mechanisms (e.g. client cert authentication, LDAPI)
+        bind_password = self.instance.get_password(name)
+
+        con = ldap.initialize('ldap://%s:%s' % (hostname, port))
+        con.simple_bind_s(bind_dn, bind_password)
+
+        return con
+
     def __repr__(self):
         return str(self.instance) + '/' + self.name
 
@@ -120,6 +193,9 @@ class PKIInstance(object):
             self.base_dir = os.path.join(pki.BASE_DIR, name)
 
         self.conf_dir = os.path.join(self.base_dir, 'conf')
+        self.password_conf = os.path.join(self.conf_dir, 'password.conf')
+
+        self.nssdb_dir = os.path.join(self.base_dir, 'alias')
         self.lib_dir = os.path.join(self.base_dir, 'lib')
 
         self.registry_dir = os.path.join(
@@ -136,6 +212,8 @@ class PKIInstance(object):
         self.uid = None
         self.gid = None
 
+        self.passwords = {}
+
         self.subsystems = []
 
     def is_valid(self):
@@ -158,6 +236,7 @@ class PKIInstance(object):
         return rc == 0
 
     def load(self):
+        # load UID and GID
         with open(self.registry_file, 'r') as registry:
             lines = registry.readlines()
 
@@ -173,11 +252,41 @@ class PKIInstance(object):
                 self.group = m.group(1)
                 self.gid = grp.getgrnam(self.group).gr_gid
 
+        # load passwords
+        self.passwords.clear()
+        lines = open(self.password_conf).read().splitlines()
+
+        for line in lines:
+            parts = line.split('=', 1)
+            name = parts[0]
+            value = parts[1]
+            self.passwords[name] = value
+
+        # load subsystems
         for subsystem_name in os.listdir(self.registry_dir):
-            if subsystem_name in pki.server.SUBSYSTEM_TYPES:
-                subsystem = PKISubsystem(self, subsystem_name)
+            if subsystem_name in SUBSYSTEM_TYPES:
+                if subsystem_name in SUBSYSTEM_CLASSES:
+                    subsystem = SUBSYSTEM_CLASSES[subsystem_name](self)
+                else:
+                    subsystem = PKISubsystem(self, subsystem_name)
+                subsystem.load()
                 self.subsystems.append(subsystem)
 
+    def get_password(self, name):
+        if name in self.passwords:
+            return self.passwords[name]
+
+        password = getpass.getpass(prompt='Enter password for %s: ' % name)
+        self.passwords[name] = password
+
+        return password
+
+    def get_subsystem(self, name):
+        for subsystem in self.subsystems:
+            if name == subsystem.name:
+                return subsystem
+        return None
+
     def is_deployed(self, webapp_name):
         context_xml = os.path.join(
             self.conf_dir, 'Catalina', 'localhost', webapp_name + '.xml')
diff --git a/base/server/python/pki/server/ca.py b/base/server/python/pki/server/ca.py
new file mode 100644
index 0000000000000000000000000000000000000000..70ebf4dd1044ecad32a0cf072ba45c6ace5eacea
--- /dev/null
+++ b/base/server/python/pki/server/ca.py
@@ -0,0 +1,92 @@
+#!/usr/bin/python
+# Authors:
+#     Endi S. Dewata <edewata at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Copyright (C) 2015 Red Hat, Inc.
+# All rights reserved.
+#
+
+from __future__ import absolute_import
+import ldap
+import ldap.filter
+
+import pki
+import pki.server
+
+
+class CASubsystem(pki.server.PKISubsystem):
+
+    def __init__(self, instance):
+        super(CASubsystem, self).__init__(instance, 'ca')
+
+    def find_cert_requests(self, cert=None):
+
+        base_dn = self.config['internaldb.basedn']
+
+        if cert:
+            escaped_value = ldap.filter.escape_filter_chars(cert)
+            search_filter = '(extdata-req--005fissued--005fcert=%s)' % escaped_value
+
+        else:
+            search_filter = '(objectClass=*)'
+
+        con = self.open_database()
+
+        entries = con.search_s(
+            'ou=ca,ou=requests,%s' % base_dn,
+            ldap.SCOPE_ONELEVEL,
+            search_filter,
+            None)
+
+        con.unbind_s()
+
+        requests = []
+        for entry in entries:
+            requests.append(self.create_request_object(entry))
+
+        return requests
+
+    def get_cert_requests(self, request_id):
+
+        base_dn = self.config['internaldb.basedn']
+
+        con = self.open_database()
+
+        entries = con.search_s(
+            'cn=%s,ou=ca,ou=requests,%s' % (request_id, base_dn),
+            ldap.SCOPE_BASE,
+            '(objectClass=*)',
+            None)
+
+        con.unbind_s()
+
+        entry = entries[0]
+        return self.create_request_object(entry)
+
+    def create_request_object(self, entry):
+
+        attrs = entry[1]
+
+        request = {}
+        request['id'] = attrs['cn'][0]
+        request['type'] = attrs['requestType'][0]
+        request['status'] = attrs['requestState'][0]
+        request['request'] = attrs['extdata-cert--005frequest'][0]
+
+        return request
+
+
+pki.server.SUBSYSTEM_CLASSES['ca'] = CASubsystem
diff --git a/base/server/python/pki/server/cli/ca.py b/base/server/python/pki/server/cli/ca.py
new file mode 100644
index 0000000000000000000000000000000000000000..2ad8652f4fddd032779941cb7e2ae4e643c25e0a
--- /dev/null
+++ b/base/server/python/pki/server/cli/ca.py
@@ -0,0 +1,206 @@
+#!/usr/bin/python
+# Authors:
+#     Endi S. Dewata <edewata at redhat.com>
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; version 2 of the License.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, write to the Free Software Foundation, Inc.,
+# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+#
+# Copyright (C) 2015 Red Hat, Inc.
+# All rights reserved.
+#
+
+from __future__ import absolute_import
+from __future__ import print_function
+import getopt
+import io
+import sys
+
+import pki.cli
+import pki.server.ca
+
+
+class CACLI(pki.cli.CLI):
+
+    def __init__(self):
+        super(CACLI, self).__init__(
+            'ca', 'CA management commands')
+
+        self.add_module(CACertCLI())
+
+
+class CACertCLI(pki.cli.CLI):
+
+    def __init__(self):
+        super(CACertCLI, self).__init__(
+            'cert', 'CA certificates management commands')
+
+        self.add_module(CACertRequestCLI())
+
+
+class CACertRequestCLI(pki.cli.CLI):
+
+    def __init__(self):
+        super(CACertRequestCLI, self).__init__(
+            'request', 'CA certificate requests management commands')
+
+        self.add_module(CACertRequestFindCLI())
+        self.add_module(CACertRequestShowCLI())
+
+    @staticmethod
+    def print_request(request, details=False):
+        print('  Request ID: %s' % request['id'])
+        print('  Type: %s' % request['type'])
+        print('  Status: %s' % request['status'])
+
+        if details:
+            print('  Request: %s' % request['request'])
+
+
+class CACertRequestFindCLI(pki.cli.CLI):
+
+    def __init__(self):
+        super(CACertRequestFindCLI, self).__init__(
+            'find', 'Find CA certificate requests')
+
+    def usage(self):
+        print('Usage: pki-server ca-cert-request-find [OPTIONS]')
+        print()
+        print('  -i, --instance <instance ID>    Instance ID (default: pki-tomcat).')
+        print('      --cert                      Issued certificate.')
+        print('      --cert-file                 File containing issued certificate.')
+        print('  -v, --verbose                   Run in verbose mode.')
+        print('      --help                      Show help message.')
+        print()
+
+    def execute(self, args):
+
+        try:
+            opts, _ = getopt.gnu_getopt(args, 'i:v', [
+                'instance=', 'cert=', 'cert-file=',
+                'verbose', 'help'])
+
+        except getopt.GetoptError as e:
+            print('ERROR: ' + str(e))
+            self.usage()
+            sys.exit(1)
+
+        instance_name = 'pki-tomcat'
+        cert = None
+
+        for o, a in opts:
+            if o in ('-i', '--instance'):
+                instance_name = a
+
+            elif o == '--cert':
+                cert = a
+
+            elif o == '--cert-file':
+                with io.open(a, 'rb') as f:
+                    cert = f.read()
+
+            elif o in ('-v', '--verbose'):
+                self.set_verbose(True)
+
+            elif o == '--help':
+                self.print_help()
+                sys.exit()
+
+            else:
+                print('ERROR: unknown option ' + o)
+                self.usage()
+                sys.exit(1)
+
+        instance = pki.server.PKIInstance(instance_name)
+        instance.load()
+
+        subsystem = instance.get_subsystem('ca')
+        results = subsystem.find_cert_requests(cert=cert)
+
+        self.print_message('%s entries matched' % len(results))
+
+        first = True
+        for request in results:
+            if first:
+                first = False
+            else:
+                print()
+
+            CACertRequestCLI.print_request(request)
+
+
+class CACertRequestShowCLI(pki.cli.CLI):
+
+    def __init__(self):
+        super(CACertRequestShowCLI, self).__init__(
+            'show', 'Show CA certificate request')
+
+    def usage(self):
+        print('Usage: pki-server ca-cert-request-show <request ID> [OPTIONS]')
+        print()
+        print('  -i, --instance <instance ID>    Instance ID (default: pki-tomcat).')
+        print('  -v, --verbose                   Run in verbose mode.')
+        print('      --help                      Show help message.')
+        print()
+
+    def execute(self, args):
+
+        try:
+            opts, args = getopt.gnu_getopt(args, 'i:v', [
+                'instance=', 'output-file=',
+                'verbose', 'help'])
+
+        except getopt.GetoptError as e:
+            print('ERROR: ' + str(e))
+            self.usage()
+            sys.exit(1)
+
+        if len(args) != 1:
+            print('ERROR: missing request ID')
+            self.usage()
+            sys.exit(1)
+
+        request_id = args[0]
+        instance_name = 'pki-tomcat'
+        output_file = None
+
+        for o, a in opts:
+            if o in ('-i', '--instance'):
+                instance_name = a
+
+            elif o == '--output-file':
+                output_file = a
+
+            elif o in ('-v', '--verbose'):
+                self.set_verbose(True)
+
+            elif o == '--help':
+                self.print_help()
+                sys.exit()
+
+            else:
+                print('ERROR: unknown option ' + o)
+                self.usage()
+                sys.exit(1)
+
+        instance = pki.server.PKIInstance(instance_name)
+        instance.load()
+
+        subsystem = instance.get_subsystem('ca')
+        request = subsystem.get_cert_requests(request_id)
+
+        if output_file:
+            with io.open(output_file, 'wb') as f:
+                f.write(request['request'])
+
+        else:
+            CACertRequestCLI.print_request(request, details=True)
diff --git a/base/server/python/pki/server/cli/subsystem.py b/base/server/python/pki/server/cli/subsystem.py
index b1c20af59de460cc9d8e9ae4a6288787082cc02a..688a5c6ed0bd7d93b87163f31e926ba4d8deca48 100644
--- a/base/server/python/pki/server/cli/subsystem.py
+++ b/base/server/python/pki/server/cli/subsystem.py
@@ -21,8 +21,10 @@
 
 from __future__ import absolute_import
 from __future__ import print_function
+import base64
 import getopt
-import os
+import nss.nss as nss
+import string
 import sys
 
 import pki.cli
@@ -40,6 +42,8 @@ class SubsystemCLI(pki.cli.CLI):
         self.add_module(SubsystemFindCLI())
         self.add_module(SubsystemShowCLI())
 
+        self.add_module(SubsystemCertCLI())
+
     @staticmethod
     def print_subsystem(subsystem):
         print('  Subsystem ID: %s' % subsystem.name)
@@ -55,7 +59,7 @@ class SubsystemFindCLI(pki.cli.CLI):
     def usage(self):
         print('Usage: pki-server subsystem-find [OPTIONS]')
         print()
-        print('  -i, --instance <instance ID>    Instance ID.')
+        print('  -i, --instance <instance ID>    Instance ID (default: pki-tomcat).')
         print('  -v, --verbose                   Run in verbose mode.')
         print('      --help                      Show help message.')
         print()
@@ -72,7 +76,7 @@ class SubsystemFindCLI(pki.cli.CLI):
             self.usage()
             sys.exit(1)
 
-        instance_name = None
+        instance_name = 'pki-tomcat'
 
         for o, a in opts:
             if o in ('-i', '--instance'):
@@ -90,28 +94,13 @@ class SubsystemFindCLI(pki.cli.CLI):
                 self.usage()
                 sys.exit(1)
 
-        if not instance_name:
-            print('ERROR: missing instance ID')
-            self.usage()
-            sys.exit(1)
-
         instance = pki.server.PKIInstance(instance_name)
         instance.load()
 
-        results = []
-
-        for name in os.listdir(instance.base_dir):
-
-            subsystem = pki.server.PKISubsystem(instance, name)
-            if not subsystem.is_valid():
-                continue
-
-            results.append(subsystem)
-
-        self.print_message('%s entries matched' % len(results))
+        self.print_message('%s entries matched' % len(instance.subsystems))
 
         first = True
-        for subsystem in results:
+        for subsystem in instance.subsystems:
             if first:
                 first = False
             else:
@@ -128,7 +117,7 @@ class SubsystemShowCLI(pki.cli.CLI):
     def usage(self):
         print('Usage: pki-server subsystem-show [OPTIONS] <subsystem ID>')
         print()
-        print('  -i, --instance <instance ID>    Instance ID.')
+        print('  -i, --instance <instance ID>    Instance ID (default: pki-tomcat).')
         print('  -v, --verbose                   Run in verbose mode.')
         print('      --help                      Show help message.')
         print()
@@ -151,7 +140,7 @@ class SubsystemShowCLI(pki.cli.CLI):
             sys.exit(1)
 
         subsystem_name = args[0]
-        instance_name = None
+        instance_name = 'pki-tomcat'
 
         for o, a in opts:
             if o in ('-i', '--instance'):
@@ -169,15 +158,10 @@ class SubsystemShowCLI(pki.cli.CLI):
                 self.usage()
                 sys.exit(1)
 
-        if not instance_name:
-            print('ERROR: missing instance ID')
-            self.usage()
-            sys.exit(1)
-
         instance = pki.server.PKIInstance(instance_name)
         instance.load()
 
-        subsystem = pki.server.PKISubsystem(instance, subsystem_name)
+        subsystem = instance.get_subsystem(subsystem_name)
 
         SubsystemCLI.print_subsystem(subsystem)
 
@@ -190,7 +174,7 @@ class SubsystemEnableCLI(pki.cli.CLI):
     def usage(self):
         print('Usage: pki-server subsystem-enable [OPTIONS] <subsystem ID>')
         print()
-        print('  -i, --instance <instance ID>    Instance ID.')
+        print('  -i, --instance <instance ID>    Instance ID (default: pki-tomcat).')
         print('  -v, --verbose                   Run in verbose mode.')
         print('      --help                      Show help message.')
         print()
@@ -213,7 +197,7 @@ class SubsystemEnableCLI(pki.cli.CLI):
             sys.exit(1)
 
         subsystem_name = args[0]
-        instance_name = None
+        instance_name = 'pki-tomcat'
 
         for o, a in opts:
             if o in ('-i', '--instance'):
@@ -231,15 +215,10 @@ class SubsystemEnableCLI(pki.cli.CLI):
                 self.usage()
                 sys.exit(1)
 
-        if not instance_name:
-            print('ERROR: missing instance ID')
-            self.usage()
-            sys.exit(1)
-
         instance = pki.server.PKIInstance(instance_name)
         instance.load()
 
-        subsystem = pki.server.PKISubsystem(instance, subsystem_name)
+        subsystem = instance.get_subsystem(subsystem_name)
         subsystem.enable()
 
         self.print_message('Enabled "%s" subsystem' % subsystem_name)
@@ -257,7 +236,7 @@ class SubsystemDisableCLI(pki.cli.CLI):
     def usage(self):
         print('Usage: pki-server subsystem-disable [OPTIONS] <subsystem ID>')
         print()
-        print('  -i, --instance <instance ID>    Instance ID.')
+        print('  -i, --instance <instance ID>    Instance ID (default: pki-tomcat).')
         print('  -v, --verbose                   Run in verbose mode.')
         print('      --help                      Show help message.')
         print()
@@ -280,7 +259,7 @@ class SubsystemDisableCLI(pki.cli.CLI):
             sys.exit(1)
 
         subsystem_name = args[0]
-        instance_name = None
+        instance_name = 'pki-tomcat'
 
         for o, a in opts:
             if o in ('-i', '--instance'):
@@ -298,17 +277,263 @@ class SubsystemDisableCLI(pki.cli.CLI):
                 self.usage()
                 sys.exit(1)
 
-        if not instance_name:
-            print('ERROR: missing instance ID')
-            self.usage()
-            sys.exit(1)
-
         instance = pki.server.PKIInstance(instance_name)
         instance.load()
 
-        subsystem = pki.server.PKISubsystem(instance, subsystem_name)
+        subsystem = instance.get_subsystem(subsystem_name)
         subsystem.disable()
 
         self.print_message('Disabled "%s" subsystem' % subsystem_name)
 
         SubsystemCLI.print_subsystem(subsystem)
+
+
+class SubsystemCertCLI(pki.cli.CLI):
+
+    def __init__(self):
+        super(SubsystemCertCLI, self).__init__(
+            'cert', 'Subsystem certificate management commands')
+
+        self.add_module(SubsystemCertFindCLI())
+        self.add_module(SubsystemCertShowCLI())
+        self.add_module(SubsystemCertUpdateCLI())
+
+    @staticmethod
+    def print_subsystem_cert(cert):
+        print('  Cert ID: %s' % cert['id'])
+        print('  Nickname: %s' % cert['nickname'])
+        print('  Token: %s' % cert['token'])
+        print('  Certificate: %s' % cert['data'])
+        print('  Request: %s' % cert['request'])
+
+
+class SubsystemCertFindCLI(pki.cli.CLI):
+
+    def __init__(self):
+        super(SubsystemCertFindCLI, self).__init__(
+            'find', 'Find subsystem certificates')
+
+    def usage(self):
+        print('Usage: pki-server subsystem-cert-find [OPTIONS] <subsystem ID>')
+        print()
+        print('  -i, --instance <instance ID>    Instance ID (default: pki-tomcat).')
+        print('  -v, --verbose                   Run in verbose mode.')
+        print('      --help                      Show help message.')
+        print()
+
+    def execute(self, argv):
+
+        try:
+            opts, args = getopt.getopt(argv, 'i:v', [
+                'instance=',
+                'verbose', 'help'])
+
+        except getopt.GetoptError as e:
+            print('ERROR: ' + str(e))
+            self.usage()
+            sys.exit(1)
+
+        if len(args) != 1:
+            print('ERROR: missing subsystem ID')
+            self.usage()
+            sys.exit(1)
+
+        subsystem_name = args[0]
+        instance_name = 'pki-tomcat'
+
+        for o, a in opts:
+            if o in ('-i', '--instance'):
+                instance_name = a
+
+            elif o in ('-v', '--verbose'):
+                self.set_verbose(True)
+
+            elif o == '--help':
+                self.print_help()
+                sys.exit()
+
+            else:
+                print('ERROR: unknown option ' + o)
+                self.usage()
+                sys.exit(1)
+
+        instance = pki.server.PKIInstance(instance_name)
+        instance.load()
+
+        subsystem = instance.get_subsystem(subsystem_name)
+        results = subsystem.find_subsystem_certs()
+
+        self.print_message('%s entries matched' % len(results))
+
+        first = True
+        for cert in results:
+            if first:
+                first = False
+            else:
+                print()
+
+            SubsystemCertCLI.print_subsystem_cert(cert)
+
+
+class SubsystemCertShowCLI(pki.cli.CLI):
+
+    def __init__(self):
+        super(SubsystemCertShowCLI, self).__init__(
+            'show', 'Show subsystem certificate')
+
+    def usage(self):
+        print('Usage: pki-server subsystem-cert-show [OPTIONS] <subsystem ID> <cert ID>')
+        print()
+        print('  -i, --instance <instance ID>    Instance ID (default: pki-tomcat).')
+        print('  -v, --verbose                   Run in verbose mode.')
+        print('      --help                      Show help message.')
+        print()
+
+    def execute(self, argv):
+
+        try:
+            opts, args = getopt.getopt(argv, 'i:v', [
+                'instance=',
+                'verbose', 'help'])
+
+        except getopt.GetoptError as e:
+            print('ERROR: ' + str(e))
+            self.usage()
+            sys.exit(1)
+
+        if len(args) < 1:
+            print('ERROR: missing subsystem ID')
+            self.usage()
+            sys.exit(1)
+
+        if len(args) < 2:
+            print('ERROR: missing cert ID')
+            self.usage()
+            sys.exit(1)
+
+        subsystem_name = args[0]
+        cert_id = args[1]
+        instance_name = 'pki-tomcat'
+
+        for o, a in opts:
+            if o in ('-i', '--instance'):
+                instance_name = a
+
+            elif o in ('-v', '--verbose'):
+                self.set_verbose(True)
+
+            elif o == '--help':
+                self.print_help()
+                sys.exit()
+
+            else:
+                print('ERROR: unknown option ' + o)
+                self.usage()
+                sys.exit(1)
+
+        instance = pki.server.PKIInstance(instance_name)
+        instance.load()
+
+        subsystem = instance.get_subsystem(subsystem_name)
+        subsystem_cert = subsystem.get_subsystem_cert(cert_id)
+
+        SubsystemCertCLI.print_subsystem_cert(subsystem_cert)
+
+
+class SubsystemCertUpdateCLI(pki.cli.CLI):
+
+    def __init__(self):
+        super(SubsystemCertUpdateCLI, self).__init__(
+            'update', 'Update subsystem certificate')
+
+    def usage(self):
+        print('Usage: pki-server subsystem-cert-update [OPTIONS] <subsystem ID> <cert ID>')
+        print()
+        print('  -i, --instance <instance ID>    Instance ID (default: pki-tomcat).')
+        print('  -v, --verbose                   Run in verbose mode.')
+        print('      --help                      Show help message.')
+        print()
+
+    def execute(self, argv):
+
+        try:
+            opts, args = getopt.getopt(argv, 'i:v', [
+                'instance=',
+                'verbose', 'help'])
+
+        except getopt.GetoptError as e:
+            print('ERROR: ' + str(e))
+            self.usage()
+            sys.exit(1)
+
+        if len(args) < 1:
+            print('ERROR: missing subsystem ID')
+            self.usage()
+            sys.exit(1)
+
+        if len(args) < 2:
+            print('ERROR: missing cert ID')
+            self.usage()
+            sys.exit(1)
+
+        subsystem_name = args[0]
+        cert_id = args[1]
+        instance_name = 'pki-tomcat'
+
+        for o, a in opts:
+            if o in ('-i', '--instance'):
+                instance_name = a
+
+            elif o in ('-v', '--verbose'):
+                self.set_verbose(True)
+
+            elif o == '--help':
+                self.print_help()
+                sys.exit()
+
+            else:
+                print('ERROR: unknown option ' + o)
+                self.usage()
+                sys.exit(1)
+
+        instance = pki.server.PKIInstance(instance_name)
+        instance.load()
+
+        subsystem = instance.get_subsystem(subsystem_name)
+        subsystem_cert = subsystem.get_subsystem_cert(cert_id)
+
+        # get cert data from NSS database
+        nss.nss_init(instance.nssdb_dir)
+        nss_cert = nss.find_cert_from_nickname(subsystem_cert['nickname'])
+        data = base64.b64encode(nss_cert.der_data)
+        del nss_cert
+        nss.nss_shutdown()
+        subsystem_cert['data'] = data
+
+        # format cert data for LDAP database
+        lines = [data[i:i+64] for i in range(0, len(data), 64)]
+        data = string.join(lines, '\r\n') + '\r\n'
+
+        # get cert request from local CA
+        # TODO: add support for remote CA
+        ca = instance.get_subsystem('ca')
+        results = ca.find_cert_requests(cert=data)
+        cert_request = results[-1]
+        request = cert_request['request']
+
+        # format cert request for CS.cfg
+        lines = request.splitlines()
+        if lines[0] == '-----BEGIN CERTIFICATE REQUEST-----':
+            lines = lines[1:]
+        if lines[-1] == '-----END CERTIFICATE REQUEST-----':
+            lines = lines[:-1]
+        request = string.join(lines, '')
+        subsystem_cert['request'] = request
+
+        # store cert data and request in CS.cfg
+        subsystem.update_subsystem_cert(subsystem_cert)
+        subsystem.save()
+
+        self.print_message('Updated "%s" subsystem certificate' % cert_id)
+
+        SubsystemCertCLI.print_subsystem_cert(subsystem_cert)
diff --git a/base/server/python/pki/server/upgrade.py b/base/server/python/pki/server/upgrade.py
index a0e52b22b87035f6b39c388002f63eb8af2eb4ff..ffe7c891d92c4fd16a5e42bdc4d268c2251a0604 100644
--- a/base/server/python/pki/server/upgrade.py
+++ b/base/server/python/pki/server/upgrade.py
@@ -215,6 +215,7 @@ class PKIServerUpgrader(pki.upgrade.PKIUpgrader):
         if self.subsystemName:
             subsystem = pki.server.PKISubsystem(instance, self.subsystemName)
             subsystem.validate()
+            subsystem.load()
             return [subsystem]
 
         subsystem_list = []
@@ -229,6 +230,7 @@ class PKIServerUpgrader(pki.upgrade.PKIUpgrader):
                         instance,
                         subsystemName)
                     subsystem.validate()
+                    subsystem.load()
                     subsystem_list.append(subsystem)
         else:
             for subsystemName in pki.server.SUBSYSTEM_TYPES:
@@ -241,6 +243,7 @@ class PKIServerUpgrader(pki.upgrade.PKIUpgrader):
                         instance,
                         subsystemName)
                     subsystem.validate()
+                    subsystem.load()
                     subsystem_list.append(subsystem)
 
         subsystem_list.sort()
diff --git a/base/server/sbin/pki-server b/base/server/sbin/pki-server
index d479788debbaed8c58f977023463b3033636e1c3..f3e784a1539a4cff82cdc765da53f2cb01b27a3c 100644
--- a/base/server/sbin/pki-server
+++ b/base/server/sbin/pki-server
@@ -25,6 +25,7 @@ import getopt
 import sys
 
 import pki.cli
+import pki.server.cli.ca
 import pki.server.cli.instance
 import pki.server.cli.subsystem
 import pki.server.cli.migrate
@@ -38,6 +39,7 @@ class PKIServerCLI(pki.cli.CLI):
             'pki-server',
             'PKI server command-line interface')
 
+        self.add_module(pki.server.cli.ca.CACLI())
         self.add_module(pki.server.cli.instance.InstanceCLI())
         self.add_module(pki.server.cli.subsystem.SubsystemCLI())
         self.add_module(pki.server.cli.migrate.MigrateCLI())
-- 
2.4.3



More information about the Pki-devel mailing list