diff options
Diffstat (limited to 'base')
-rw-r--r-- | base/common/python/pki/nssdb.py | 23 | ||||
-rw-r--r-- | base/server/python/pki/server/__init__.py | 121 | ||||
-rw-r--r-- | base/server/python/pki/server/cli/ca.py | 202 | ||||
-rw-r--r-- | base/server/python/pki/server/cli/instance.py | 94 | ||||
-rw-r--r-- | base/server/python/pki/server/cli/kra.py | 139 | ||||
-rw-r--r-- | base/server/python/pki/server/cli/ocsp.py | 138 | ||||
-rw-r--r-- | base/server/python/pki/server/cli/subsystem.py | 74 | ||||
-rw-r--r-- | base/server/python/pki/server/cli/tks.py | 138 | ||||
-rw-r--r-- | base/server/python/pki/server/cli/tps.py | 138 | ||||
-rw-r--r-- | base/server/sbin/pki-server | 9 |
10 files changed, 1037 insertions, 39 deletions
diff --git a/base/common/python/pki/nssdb.py b/base/common/python/pki/nssdb.py index 67fd90b4c..219d824fd 100644 --- a/base/common/python/pki/nssdb.py +++ b/base/common/python/pki/nssdb.py @@ -502,7 +502,8 @@ class NSSDatabase(object): finally: shutil.rmtree(tmpdir) - def export_pkcs12(self, pkcs12_file, nickname, pkcs12_password=None, pkcs12_password_file=None): + def export_pkcs12(self, pkcs12_file, nicknames=None, pkcs12_password=None, + pkcs12_password_file=None): tmpdir = tempfile.mkdtemp() @@ -519,14 +520,24 @@ class NSSDatabase(object): raise Exception('Missing PKCS #12 password') cmd = [ - 'pk12util', + 'pki', '-d', self.directory, - '-k', self.password_file, - '-o', pkcs12_file, - '-w', password_file, - '-n', nickname + '-C', self.password_file ] + if self.token and self.token != 'internal': + cmd.extend(['--token', self.token]) + + cmd.extend(['pkcs12-export']) + + cmd.extend([ + '--pkcs12', pkcs12_file, + '--pkcs12-password-file', password_file + ]) + + if nicknames: + cmd.extend(nicknames) + subprocess.check_call(cmd) finally: diff --git a/base/server/python/pki/server/__init__.py b/base/server/python/pki/server/__init__.py index b2fffd5e6..4376135e7 100644 --- a/base/server/python/pki/server/__init__.py +++ b/base/server/python/pki/server/__init__.py @@ -63,10 +63,9 @@ class PKISubsystem(object): def __init__(self, instance, subsystem_name): self.instance = instance - self.name = subsystem_name - self.type = instance.type + self.name = subsystem_name # e.g. ca, kra - if self.type >= 10: + if instance.type >= 10: self.base_dir = os.path.join(self.instance.base_dir, self.name) else: self.base_dir = instance.base_dir @@ -81,8 +80,8 @@ class PKISubsystem(object): instance.conf_dir, 'Catalina', 'localhost', self.name + '.xml') self.config = {} - self.type = None - self.prefix = None + self.type = None # e.g. CA, KRA + self.prefix = None # e.g. ca, kra # custom subsystem location self.doc_base = os.path.join(self.base_dir, 'webapps', self.name) @@ -101,7 +100,7 @@ class PKISubsystem(object): self.type = self.config['cs.type'] self.prefix = self.type.lower() - def find_subsystem_certs(self): + def find_system_certs(self): certs = [] cert_ids = self.config['%s.cert.list' % self.name].split(',') @@ -130,6 +129,116 @@ class PKISubsystem(object): 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 export_system_cert( + self, + cert_id, + pkcs12_file, + pkcs12_password_file, + new_file=False): + + cert = self.get_subsystem_cert(cert_id) + nickname = cert['nickname'] + token = cert['token'] + if token == 'Internal Key Storage Token': + token = 'internal' + nssdb_password = self.instance.get_password(token) + + tmpdir = tempfile.mkdtemp() + + try: + nssdb_password_file = os.path.join(tmpdir, 'password.txt') + with open(nssdb_password_file, 'w') as f: + f.write(nssdb_password) + + # add the certificate, key, and chain + cmd = [ + 'pki', + '-d', self.instance.nssdb_dir, + '-C', nssdb_password_file + ] + + if token and token != 'internal': + cmd.extend(['--token', token]) + + cmd.extend([ + 'pkcs12-cert-add', + '--pkcs12', pkcs12_file, + '--pkcs12-password-file', pkcs12_password_file, + ]) + + if new_file: + cmd.extend(['--new-file']) + + cmd.extend([ + nickname + ]) + + subprocess.check_call(cmd) + + finally: + shutil.rmtree(tmpdir) + + def export_cert_chain( + self, + pkcs12_file, + pkcs12_password_file): + + # use subsystem certificate to get certificate chain + cert = self.get_subsystem_cert('subsystem') + nickname = cert['nickname'] + token = cert['token'] + if token == 'Internal Key Storage Token': + token = 'internal' + nssdb_password = self.instance.get_password(token) + + tmpdir = tempfile.mkdtemp() + + try: + nssdb_password_file = os.path.join(tmpdir, 'password.txt') + with open(nssdb_password_file, 'w') as f: + f.write(nssdb_password) + + # export the certificate, key, and chain + cmd = [ + 'pki', + '-d', self.instance.nssdb_dir, + '-C', nssdb_password_file + ] + + if token and token != 'internal': + cmd.extend(['--token', token]) + + cmd.extend([ + 'pkcs12-export', + '--pkcs12', pkcs12_file, + '--pkcs12-password-file', pkcs12_password_file, + nickname + ]) + + subprocess.check_call(cmd) + + # remove the certificate and key, but keep the chain + cmd = [ + 'pki', + '-d', self.instance.nssdb_dir, + '-C', nssdb_password_file + ] + + if token and token != 'internal': + cmd.extend(['--token', token]) + + cmd.extend([ + 'pkcs12-cert-del', + '--pkcs12', pkcs12_file, + '--pkcs12-password-file', pkcs12_password_file, + nickname + ]) + + subprocess.check_call(cmd) + + finally: + shutil.rmtree(tmpdir) + def save(self): sorted_config = sorted(self.config.items(), key=operator.itemgetter(0)) with io.open(self.cs_conf, 'wb') as f: diff --git a/base/server/python/pki/server/cli/ca.py b/base/server/python/pki/server/cli/ca.py index 2ad8652f4..af0d941f5 100644 --- a/base/server/python/pki/server/cli/ca.py +++ b/base/server/python/pki/server/cli/ca.py @@ -23,10 +23,12 @@ from __future__ import absolute_import from __future__ import print_function import getopt import io +import os +import shutil import sys +import tempfile import pki.cli -import pki.server.ca class CACLI(pki.cli.CLI): @@ -36,6 +38,7 @@ class CACLI(pki.cli.CLI): 'ca', 'CA management commands') self.add_module(CACertCLI()) + self.add_module(CACloneCLI()) class CACertCLI(pki.cli.CLI): @@ -44,9 +47,106 @@ class CACertCLI(pki.cli.CLI): super(CACertCLI, self).__init__( 'cert', 'CA certificates management commands') + self.add_module(CACertChainCLI()) self.add_module(CACertRequestCLI()) +class CACertChainCLI(pki.cli.CLI): + + def __init__(self): + super(CACertChainCLI, self).__init__( + 'chain', 'CA certificate chain management commands') + + self.add_module(CACertChainExportCLI()) + + +class CACertChainExportCLI(pki.cli.CLI): + + def __init__(self): + super(CACertChainExportCLI, self).__init__( + 'export', 'Export certificate chain') + + def print_help(self): + print('Usage: pki-server ca-cert-chain-export [OPTIONS]') + print() + print(' -i, --instance <instance ID> Instance ID (default: pki-tomcat).') + print(' --pkcs12-file PKCS #12 file to store certificates and keys.') + print(' --pkcs12-password Password for the PKCS #12 file.') + print(' --pkcs12-password-file File containing the PKCS #12 password.') + 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=', 'pkcs12-file=', 'pkcs12-password=', 'pkcs12-password-file=', + 'verbose', 'help']) + + except getopt.GetoptError as e: + print('ERROR: ' + str(e)) + self.print_help() + sys.exit(1) + + instance_name = 'pki-tomcat' + pkcs12_file = None + pkcs12_password = None + + for o, a in opts: + if o in ('-i', '--instance'): + instance_name = a + + elif o == '--pkcs12-file': + pkcs12_file = a + + elif o == '--pkcs12-password': + pkcs12_password = a + + elif o == '--pkcs12-password-file': + with io.open(a, 'rb') as f: + pkcs12_password = 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.print_help() + sys.exit(1) + + if not pkcs12_file: + print('ERROR: Missing PKCS #12 file') + self.print_help() + sys.exit(1) + + if not pkcs12_password: + print('ERROR: Missing PKCS #12 password') + self.print_help() + sys.exit(1) + + instance = pki.server.PKIInstance(instance_name) + instance.load() + + subsystem = instance.get_subsystem('ca') + + tmpdir = tempfile.mkdtemp() + + try: + pkcs12_password_file = os.path.join(tmpdir, 'pkcs12_password.txt') + with open(pkcs12_password_file, 'w') as f: + f.write(pkcs12_password) + + subsystem.export_cert_chain(pkcs12_file, pkcs12_password_file) + + finally: + shutil.rmtree(tmpdir) + + class CACertRequestCLI(pki.cli.CLI): def __init__(self): @@ -204,3 +304,103 @@ class CACertRequestShowCLI(pki.cli.CLI): else: CACertRequestCLI.print_request(request, details=True) + + +class CACloneCLI(pki.cli.CLI): + + def __init__(self): + super(CACloneCLI, self).__init__( + 'clone', 'CA clone management commands') + + self.add_module(CAClonePrepareCLI()) + + +class CAClonePrepareCLI(pki.cli.CLI): + + def __init__(self): + super(CAClonePrepareCLI, self).__init__( + 'prepare', 'Prepare CA clone') + + def print_help(self): + print('Usage: pki-server ca-clone-prepare [OPTIONS]') + print() + print(' -i, --instance <instance ID> Instance ID (default: pki-tomcat).') + print(' --pkcs12-file PKCS #12 file to store certificates and keys.') + print(' --pkcs12-password Password for the PKCS #12 file.') + print(' --pkcs12-password-file File containing the PKCS #12 password.') + 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=', 'pkcs12-file=', 'pkcs12-password=', 'pkcs12-password-file=', + 'verbose', 'help']) + + except getopt.GetoptError as e: + print('ERROR: ' + str(e)) + self.print_help() + sys.exit(1) + + instance_name = 'pki-tomcat' + pkcs12_file = None + pkcs12_password = None + + for o, a in opts: + if o in ('-i', '--instance'): + instance_name = a + + elif o == '--pkcs12-file': + pkcs12_file = a + + elif o == '--pkcs12-password': + pkcs12_password = a + + elif o == '--pkcs12-password-file': + with io.open(a, 'rb') as f: + pkcs12_password = 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.print_help() + sys.exit(1) + + if not pkcs12_file: + print('ERROR: Missing PKCS #12 file') + self.print_help() + sys.exit(1) + + if not pkcs12_password: + print('ERROR: Missing PKCS #12 password') + self.print_help() + sys.exit(1) + + instance = pki.server.PKIInstance(instance_name) + instance.load() + + subsystem = instance.get_subsystem('ca') + + tmpdir = tempfile.mkdtemp() + + try: + pkcs12_password_file = os.path.join(tmpdir, 'pkcs12_password.txt') + with open(pkcs12_password_file, 'w') as f: + f.write(pkcs12_password) + + subsystem.export_system_cert( + 'subsystem', pkcs12_file, pkcs12_password_file, new_file=True) + subsystem.export_system_cert('signing', pkcs12_file, pkcs12_password_file) + subsystem.export_system_cert('ocsp_signing', pkcs12_file, pkcs12_password_file) + subsystem.export_system_cert('audit_signing', pkcs12_file, pkcs12_password_file) + + finally: + shutil.rmtree(tmpdir) diff --git a/base/server/python/pki/server/cli/instance.py b/base/server/python/pki/server/cli/instance.py index 9f0788b69..f69c3f8fd 100644 --- a/base/server/python/pki/server/cli/instance.py +++ b/base/server/python/pki/server/cli/instance.py @@ -20,6 +20,7 @@ # import getopt +import getpass import os import sys @@ -34,6 +35,7 @@ class InstanceCLI(pki.cli.CLI): super(InstanceCLI, self).__init__('instance', 'Instance management commands') + self.add_module(InstanceCertCLI()) self.add_module(InstanceFindCLI()) self.add_module(InstanceShowCLI()) self.add_module(InstanceStartCLI()) @@ -48,6 +50,98 @@ class InstanceCLI(pki.cli.CLI): print ' Active: %s' % instance.is_active() +class InstanceCertCLI(pki.cli.CLI): + + def __init__(self): + super(InstanceCertCLI, self).__init__( + 'cert', 'Instance certificate management commands') + + self.add_module(InstanceCertExportCLI()) + + +class InstanceCertExportCLI(pki.cli.CLI): + + def __init__(self): + super(InstanceCertExportCLI, self).__init__( + 'export', 'Export subsystem certificate') + + def print_help(self): # flake8: noqa + print('Usage: pki-server instance-cert-export [OPTIONS]') + print() + print(' -i, --instance <instance ID> Instance ID (default: pki-tomcat).') + print(' --pkcs12-file <path> Output file to store the exported certificate and key in PKCS #12 format.') + print(' --pkcs12-password <password> Password for the PKCS #12 file.') + print(' --pkcs12-password-file <path> Input file containing the password for the PKCS #12 file.') + print(' -v, --verbose Run in verbose mode.') + print(' --help Show help message.') + print() + + def execute(self, argv): + + try: + opts, _ = getopt.gnu_getopt(argv, 'i:v', [ + 'instance=', + 'pkcs12-file=', 'pkcs12-password=', 'pkcs12-password-file=', + 'verbose', 'help']) + + except getopt.GetoptError as e: + print('ERROR: ' + str(e)) + self.print_help() + sys.exit(1) + + instance_name = 'pki-tomcat' + pkcs12_file = None + pkcs12_password = None + pkcs12_password_file = None + + for o, a in opts: + if o in ('-i', '--instance'): + instance_name = a + + elif o == '--pkcs12-file': + pkcs12_file = a + + elif o == '--pkcs12-password': + pkcs12_password = a + + elif o == '--pkcs12-password-file': + pkcs12_password_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.print_help() + sys.exit(1) + + if not pkcs12_file: + print('ERROR: missing output file') + self.print_help() + sys.exit(1) + + instance = pki.server.PKIInstance(instance_name) + instance.load() + + if not pkcs12_password and not pkcs12_password_file: + pkcs12_password = getpass.getpass(prompt='Enter password for PKCS #12 file: ') + + nssdb = instance.open_nssdb() + try: + nssdb.export_pkcs12( + pkcs12_file=pkcs12_file, + pkcs12_password=pkcs12_password, + pkcs12_password_file=pkcs12_password_file) + finally: + nssdb.close() + + self.print_message('Exported certificates') + + class InstanceFindCLI(pki.cli.CLI): def __init__(self): diff --git a/base/server/python/pki/server/cli/kra.py b/base/server/python/pki/server/cli/kra.py new file mode 100644 index 000000000..d1b27dbc1 --- /dev/null +++ b/base/server/python/pki/server/cli/kra.py @@ -0,0 +1,139 @@ +# Authors: +# Endi S. Dewata <edewata@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) 2016 Red Hat, Inc. +# All rights reserved. +# + +from __future__ import absolute_import +from __future__ import print_function +import getopt +import io +import os +import shutil +import sys +import tempfile + +import pki.cli + + +class KRACLI(pki.cli.CLI): + + def __init__(self): + super(KRACLI, self).__init__( + 'kra', 'KRA management commands') + + self.add_module(KRACloneCLI()) + + +class KRACloneCLI(pki.cli.CLI): + + def __init__(self): + super(KRACloneCLI, self).__init__( + 'clone', 'KRA clone management commands') + + self.add_module(KRAClonePrepareCLI()) + + +class KRAClonePrepareCLI(pki.cli.CLI): + + def __init__(self): + super(KRAClonePrepareCLI, self).__init__( + 'prepare', 'Prepare KRA clone') + + def print_help(self): + print('Usage: pki-server kra-clone-prepare [OPTIONS]') + print() + print(' -i, --instance <instance ID> Instance ID (default: pki-tomcat).') + print(' --pkcs12-file PKCS #12 file to store certificates and keys.') + print(' --pkcs12-password Password for the PKCS #12 file.') + print(' --pkcs12-password-file File containing the PKCS #12 password.') + 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=', 'pkcs12-file=', 'pkcs12-password=', 'pkcs12-password-file=', + 'verbose', 'help']) + + except getopt.GetoptError as e: + print('ERROR: ' + str(e)) + self.print_help() + sys.exit(1) + + instance_name = 'pki-tomcat' + pkcs12_file = None + pkcs12_password = None + + for o, a in opts: + if o in ('-i', '--instance'): + instance_name = a + + elif o == '--pkcs12-file': + pkcs12_file = a + + elif o == '--pkcs12-password': + pkcs12_password = a + + elif o == '--pkcs12-password-file': + with io.open(a, 'rb') as f: + pkcs12_password = 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.print_help() + sys.exit(1) + + if not pkcs12_file: + print('ERROR: Missing PKCS #12 file') + self.print_help() + sys.exit(1) + + if not pkcs12_password: + print('ERROR: Missing PKCS #12 password') + self.print_help() + sys.exit(1) + + instance = pki.server.PKIInstance(instance_name) + instance.load() + + subsystem = instance.get_subsystem('kra') + + tmpdir = tempfile.mkdtemp() + + try: + pkcs12_password_file = os.path.join(tmpdir, 'pkcs12_password.txt') + with open(pkcs12_password_file, 'w') as f: + f.write(pkcs12_password) + + subsystem.export_system_cert( + 'subsystem', pkcs12_file, pkcs12_password_file, new_file=True) + subsystem.export_system_cert('transport', pkcs12_file, pkcs12_password_file) + subsystem.export_system_cert('storage', pkcs12_file, pkcs12_password_file) + subsystem.export_system_cert('audit_signing', pkcs12_file, pkcs12_password_file) + + finally: + shutil.rmtree(tmpdir) diff --git a/base/server/python/pki/server/cli/ocsp.py b/base/server/python/pki/server/cli/ocsp.py new file mode 100644 index 000000000..7b1b43487 --- /dev/null +++ b/base/server/python/pki/server/cli/ocsp.py @@ -0,0 +1,138 @@ +# Authors: +# Endi S. Dewata <edewata@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) 2016 Red Hat, Inc. +# All rights reserved. +# + +from __future__ import absolute_import +from __future__ import print_function +import getopt +import io +import os +import shutil +import sys +import tempfile + +import pki.cli + + +class OCSPCLI(pki.cli.CLI): + + def __init__(self): + super(OCSPCLI, self).__init__( + 'ocsp', 'OCSP management commands') + + self.add_module(OCSPCloneCLI()) + + +class OCSPCloneCLI(pki.cli.CLI): + + def __init__(self): + super(OCSPCloneCLI, self).__init__( + 'clone', 'OCSP clone management commands') + + self.add_module(OCSPClonePrepareCLI()) + + +class OCSPClonePrepareCLI(pki.cli.CLI): + + def __init__(self): + super(OCSPClonePrepareCLI, self).__init__( + 'prepare', 'Prepare OCSP clone') + + def print_help(self): + print('Usage: pki-server ocsp-clone-prepare [OPTIONS]') + print() + print(' -i, --instance <instance ID> Instance ID (default: pki-tomcat).') + print(' --pkcs12-file PKCS #12 file to store certificates and keys.') + print(' --pkcs12-password Password for the PKCS #12 file.') + print(' --pkcs12-password-file File containing the PKCS #12 password.') + 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=', 'pkcs12-file=', 'pkcs12-password=', 'pkcs12-password-file=', + 'verbose', 'help']) + + except getopt.GetoptError as e: + print('ERROR: ' + str(e)) + self.print_help() + sys.exit(1) + + instance_name = 'pki-tomcat' + pkcs12_file = None + pkcs12_password = None + + for o, a in opts: + if o in ('-i', '--instance'): + instance_name = a + + elif o == '--pkcs12': + pkcs12_file = a + + elif o == '--pkcs12-password': + pkcs12_password = a + + elif o == '--pkcs12-password-file': + with io.open(a, 'rb') as f: + pkcs12_password = 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.print_help() + sys.exit(1) + + if not pkcs12_file: + print('ERROR: Missing PKCS #12 file') + self.print_help() + sys.exit(1) + + if not pkcs12_password: + print('ERROR: Missing PKCS #12 password') + self.print_help() + sys.exit(1) + + instance = pki.server.PKIInstance(instance_name) + instance.load() + + subsystem = instance.get_subsystem('ocsp') + + tmpdir = tempfile.mkdtemp() + + try: + pkcs12_password_file = os.path.join(tmpdir, 'pkcs12_password.txt') + with open(pkcs12_password_file, 'w') as f: + f.write(pkcs12_password) + + subsystem.export_system_cert( + 'subsystem', pkcs12_file, pkcs12_password_file, new_file=True) + subsystem.export_system_cert('signing', pkcs12_file, pkcs12_password_file) + subsystem.export_system_cert('audit_signing', pkcs12_file, pkcs12_password_file) + + finally: + shutil.rmtree(tmpdir) diff --git a/base/server/python/pki/server/cli/subsystem.py b/base/server/python/pki/server/cli/subsystem.py index 3af19269b..92d4c3deb 100644 --- a/base/server/python/pki/server/cli/subsystem.py +++ b/base/server/python/pki/server/cli/subsystem.py @@ -300,12 +300,14 @@ class SubsystemCertCLI(pki.cli.CLI): self.add_module(SubsystemCertUpdateCLI()) @staticmethod - def print_subsystem_cert(cert): + def print_subsystem_cert(cert, show_all=False): 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']) + + if show_all: + print(' Certificate: %s' % cert['data']) + print(' Request: %s' % cert['request']) class SubsystemCertFindCLI(pki.cli.CLI): @@ -314,10 +316,11 @@ class SubsystemCertFindCLI(pki.cli.CLI): super(SubsystemCertFindCLI, self).__init__( 'find', 'Find subsystem certificates') - def usage(self): + def print_help(self): print('Usage: pki-server subsystem-cert-find [OPTIONS] <subsystem ID>') print() print(' -i, --instance <instance ID> Instance ID (default: pki-tomcat).') + print(' --show-all Show all attributes.') print(' -v, --verbose Run in verbose mode.') print(' --help Show help message.') print() @@ -326,26 +329,30 @@ class SubsystemCertFindCLI(pki.cli.CLI): try: opts, args = getopt.gnu_getopt(argv, 'i:v', [ - 'instance=', + 'instance=', 'show-all', 'verbose', 'help']) except getopt.GetoptError as e: print('ERROR: ' + str(e)) - self.usage() + self.print_help() sys.exit(1) if len(args) != 1: print('ERROR: missing subsystem ID') - self.usage() + self.print_help() sys.exit(1) subsystem_name = args[0] instance_name = 'pki-tomcat' + show_all = False for o, a in opts: if o in ('-i', '--instance'): instance_name = a + elif o == '--show-all': + show_all = True + elif o in ('-v', '--verbose'): self.set_verbose(True) @@ -355,14 +362,14 @@ class SubsystemCertFindCLI(pki.cli.CLI): else: print('ERROR: unknown option ' + o) - self.usage() + self.print_help() sys.exit(1) instance = pki.server.PKIInstance(instance_name) instance.load() subsystem = instance.get_subsystem(subsystem_name) - results = subsystem.find_subsystem_certs() + results = subsystem.find_system_certs() self.print_message('%s entries matched' % len(results)) @@ -373,7 +380,7 @@ class SubsystemCertFindCLI(pki.cli.CLI): else: print() - SubsystemCertCLI.print_subsystem_cert(cert) + SubsystemCertCLI.print_subsystem_cert(cert, show_all) class SubsystemCertShowCLI(pki.cli.CLI): @@ -447,8 +454,8 @@ class SubsystemCertExportCLI(pki.cli.CLI): super(SubsystemCertExportCLI, self).__init__( 'export', 'Export subsystem certificate') - def usage(self): - print('Usage: pki-server subsystem-cert-export [OPTIONS] <subsystem ID> <cert ID>') + def print_help(self): # flake8: noqa + print('Usage: pki-server subsystem-cert-export [OPTIONS] <subsystem ID> [cert ID]') print() print(' -i, --instance <instance ID> Instance ID (default: pki-tomcat).') print(' --cert-file <path> Output file to store the exported certificate in PEM format.') @@ -470,21 +477,16 @@ class SubsystemCertExportCLI(pki.cli.CLI): except getopt.GetoptError as e: print('ERROR: ' + str(e)) - self.usage() + self.print_help() 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() + self.print_help() sys.exit(1) subsystem_name = args[0] - cert_id = args[1] + instance_name = 'pki-tomcat' cert_file = None csr_file = None @@ -520,19 +522,28 @@ class SubsystemCertExportCLI(pki.cli.CLI): else: print('ERROR: unknown option ' + o) - self.usage() + self.print_help() sys.exit(1) - if not cert_file and not csr_file and not pkcs12_file: + if not pkcs12_file: print('ERROR: missing output file') - self.usage() + self.print_help() 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) + subsystem_cert = None + + if len(args) >= 2: + cert_id = args[1] + subsystem_cert = subsystem.get_subsystem_cert(cert_id) + + if (cert_file or csr_file) and not subsystem_cert: + print('ERROR: missing cert ID') + self.print_help() + sys.exit(1) if cert_file: @@ -551,17 +562,28 @@ class SubsystemCertExportCLI(pki.cli.CLI): if not pkcs12_password and not pkcs12_password_file: pkcs12_password = getpass.getpass(prompt='Enter password for PKCS #12 file: ') + nicknames = [] + + if subsystem_cert: + nicknames.append(subsystem_cert['nickname']) + + else: + subsystem_certs = subsystem.find_system_certs() + for subsystem_cert in subsystem_certs: + nicknames.append(subsystem_cert['nickname']) + nssdb = instance.open_nssdb() try: nssdb.export_pkcs12( pkcs12_file=pkcs12_file, - nickname=subsystem_cert['nickname'], + nicknames=nicknames, pkcs12_password=pkcs12_password, pkcs12_password_file=pkcs12_password_file) + finally: nssdb.close() - self.print_message('Exported %s certificate' % cert_id) + self.print_message('Export complete') class SubsystemCertUpdateCLI(pki.cli.CLI): diff --git a/base/server/python/pki/server/cli/tks.py b/base/server/python/pki/server/cli/tks.py new file mode 100644 index 000000000..39343db98 --- /dev/null +++ b/base/server/python/pki/server/cli/tks.py @@ -0,0 +1,138 @@ +# Authors: +# Endi S. Dewata <edewata@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) 2016 Red Hat, Inc. +# All rights reserved. +# + +from __future__ import absolute_import +from __future__ import print_function +import getopt +import io +import os +import shutil +import sys +import tempfile + +import pki.cli + + +class TKSCLI(pki.cli.CLI): + + def __init__(self): + super(TKSCLI, self).__init__( + 'tks', 'TKS management commands') + + self.add_module(TKSCloneCLI()) + + +class TKSCloneCLI(pki.cli.CLI): + + def __init__(self): + super(TKSCloneCLI, self).__init__( + 'clone', 'TKS clone management commands') + + self.add_module(TKSClonePrepareCLI()) + + +class TKSClonePrepareCLI(pki.cli.CLI): + + def __init__(self): + super(TKSClonePrepareCLI, self).__init__( + 'prepare', 'Prepare TKS clone') + + def print_help(self): + print('Usage: pki-server tks-clone-prepare [OPTIONS]') + print() + print(' -i, --instance <instance ID> Instance ID (default: pki-tomcat).') + print(' --pkcs12-file PKCS #12 file to store certificates and keys.') + print(' --pkcs12-password Password for the PKCS #12 file.') + print(' --pkcs12-password-file File containing the PKCS #12 password.') + 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=', 'pkcs12-file=', 'pkcs12-password=', 'pkcs12-password-file=', + 'verbose', 'help']) + + except getopt.GetoptError as e: + print('ERROR: ' + str(e)) + self.print_help() + sys.exit(1) + + instance_name = 'pki-tomcat' + pkcs12_file = None + pkcs12_password = None + + for o, a in opts: + if o in ('-i', '--instance'): + instance_name = a + + elif o == '--pkcs12-file': + pkcs12_file = a + + elif o == '--pkcs12-password': + pkcs12_password = a + + elif o == '--pkcs12-password-file': + with io.open(a, 'rb') as f: + pkcs12_password = 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.print_help() + sys.exit(1) + + if not pkcs12_file: + print('ERROR: Missing PKCS #12 file') + self.print_help() + sys.exit(1) + + if not pkcs12_password: + print('ERROR: Missing PKCS #12 password') + self.print_help() + sys.exit(1) + + instance = pki.server.PKIInstance(instance_name) + instance.load() + + subsystem = instance.get_subsystem('tks') + + tmpdir = tempfile.mkdtemp() + + try: + pkcs12_password_file = os.path.join(tmpdir, 'pkcs12_password.txt') + with open(pkcs12_password_file, 'w') as f: + f.write(pkcs12_password) + + subsystem.export_system_cert( + 'subsystem', pkcs12_file, pkcs12_password_file, new_file=True) + subsystem.export_system_cert('signing', pkcs12_file, pkcs12_password_file) + subsystem.export_system_cert('audit_signing', pkcs12_file, pkcs12_password_file) + + finally: + shutil.rmtree(tmpdir) diff --git a/base/server/python/pki/server/cli/tps.py b/base/server/python/pki/server/cli/tps.py new file mode 100644 index 000000000..05045cb0d --- /dev/null +++ b/base/server/python/pki/server/cli/tps.py @@ -0,0 +1,138 @@ +# Authors: +# Endi S. Dewata <edewata@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) 2016 Red Hat, Inc. +# All rights reserved. +# + +from __future__ import absolute_import +from __future__ import print_function +import getopt +import io +import os +import shutil +import sys +import tempfile + +import pki.cli + + +class TPSCLI(pki.cli.CLI): + + def __init__(self): + super(TPSCLI, self).__init__( + 'tps', 'TPS management commands') + + self.add_module(TPSCloneCLI()) + + +class TPSCloneCLI(pki.cli.CLI): + + def __init__(self): + super(TPSCloneCLI, self).__init__( + 'clone', 'TPS clone management commands') + + self.add_module(TPSClonePrepareCLI()) + + +class TPSClonePrepareCLI(pki.cli.CLI): + + def __init__(self): + super(TPSClonePrepareCLI, self).__init__( + 'prepare', 'Prepare TPS clone') + + def print_help(self): + print('Usage: pki-server tps-clone-prepare [OPTIONS]') + print() + print(' -i, --instance <instance ID> Instance ID (default: pki-tomcat).') + print(' --pkcs12-file PKCS #12 file to store certificates and keys.') + print(' --pkcs12-password Password for the PKCS #12 file.') + print(' --pkcs12-password-file File containing the PKCS #12 password.') + 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=', 'pkcs12-file=', 'pkcs12-password=', 'pkcs12-password-file=', + 'verbose', 'help']) + + except getopt.GetoptError as e: + print('ERROR: ' + str(e)) + self.print_help() + sys.exit(1) + + instance_name = 'pki-tomcat' + pkcs12_file = None + pkcs12_password = None + + for o, a in opts: + if o in ('-i', '--instance'): + instance_name = a + + elif o == '--pkcs12-file': + pkcs12_file = a + + elif o == '--pkcs12-password': + pkcs12_password = a + + elif o == '--pkcs12-password-file': + with io.open(a, 'rb') as f: + pkcs12_password = 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.print_help() + sys.exit(1) + + if not pkcs12_file: + print('ERROR: Missing PKCS #12 file') + self.print_help() + sys.exit(1) + + if not pkcs12_password: + print('ERROR: Missing PKCS #12 password') + self.print_help() + sys.exit(1) + + instance = pki.server.PKIInstance(instance_name) + instance.load() + + subsystem = instance.get_subsystem('tps') + + tmpdir = tempfile.mkdtemp() + + try: + pkcs12_password_file = os.path.join(tmpdir, 'pkcs12_password.txt') + with open(pkcs12_password_file, 'w') as f: + f.write(pkcs12_password) + + subsystem.export_system_cert( + 'subsystem', pkcs12_file, pkcs12_password_file, new_file=True) + subsystem.export_system_cert('signing', pkcs12_file, pkcs12_password_file) + subsystem.export_system_cert('audit_signing', pkcs12_file, pkcs12_password_file) + + finally: + shutil.rmtree(tmpdir) diff --git a/base/server/sbin/pki-server b/base/server/sbin/pki-server index cdfd98ee1..cf56d1bc4 100644 --- a/base/server/sbin/pki-server +++ b/base/server/sbin/pki-server @@ -24,6 +24,10 @@ import sys import pki.cli import pki.server.cli.ca +import pki.server.cli.kra +import pki.server.cli.ocsp +import pki.server.cli.tks +import pki.server.cli.tps import pki.server.cli.instance import pki.server.cli.subsystem import pki.server.cli.migrate @@ -37,6 +41,11 @@ class PKIServerCLI(pki.cli.CLI): super(PKIServerCLI, self).__init__('pki-server', 'PKI server command-line interface') self.add_module(pki.server.cli.ca.CACLI()) + self.add_module(pki.server.cli.kra.KRACLI()) + self.add_module(pki.server.cli.ocsp.OCSPCLI()) + self.add_module(pki.server.cli.tks.TKSCLI()) + self.add_module(pki.server.cli.tps.TPSCLI()) + self.add_module(pki.server.cli.instance.InstanceCLI()) self.add_module(pki.server.cli.subsystem.SubsystemCLI()) self.add_module(pki.server.cli.migrate.MigrateCLI()) |