summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEndi S. Dewata <edewata@redhat.com>2016-02-19 15:09:49 +0100
committerEndi S. Dewata <edewata@redhat.com>2016-04-02 06:10:24 +0200
commit9667921a5a2489a3fccc6f4f7f7af88f60eadbd2 (patch)
tree6989057c4a7759e8ecf96542da6538454515e1e7
parent943b62447dc41286e172bd8e11f747a0f524695b (diff)
downloadpki-9667921a5a2489a3fccc6f4f7f7af88f60eadbd2.tar.gz
pki-9667921a5a2489a3fccc6f4f7f7af88f60eadbd2.tar.xz
pki-9667921a5a2489a3fccc6f4f7f7af88f60eadbd2.zip
Added pki-server commands to export system certificates.
Some pki-server commands have been added to simplify exporting the required certificates for subsystem installations. These commands will invoke the pki pkcs12 utility to export the certificates from the instance NSS database. The pki-server ca-cert-chain-export command will export the the certificate chain needed for installing additional subsystems running on a separate instance. The pki-server <subsystem>-clone-prepare commands will export the certificates required for cloning a subsystem. https://fedorahosted.org/pki/ticket/1742
-rw-r--r--base/common/python/pki/nssdb.py23
-rw-r--r--base/server/python/pki/server/__init__.py121
-rw-r--r--base/server/python/pki/server/cli/ca.py202
-rw-r--r--base/server/python/pki/server/cli/instance.py94
-rw-r--r--base/server/python/pki/server/cli/kra.py139
-rw-r--r--base/server/python/pki/server/cli/ocsp.py138
-rw-r--r--base/server/python/pki/server/cli/subsystem.py74
-rw-r--r--base/server/python/pki/server/cli/tks.py138
-rw-r--r--base/server/python/pki/server/cli/tps.py138
-rw-r--r--base/server/sbin/pki-server9
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())