From d2e247798a36225880ef6050716cc7576fe2ad7f Mon Sep 17 00:00:00 2001 From: "Endi S. Dewata" Date: Wed, 14 Jun 2017 23:08:29 +0200 Subject: Added banner validation during server startup. Some pki-server CLIs have been added to inspect and validate the content of the banner file. The PKI server startup script has been modified to validate the content of the banner file using the new CLI. https://pagure.io/dogtagpki/issue/2671 Change-Id: Ibc51afee184d0a720cc0d2961af08ef75d2b54c4 --- base/server/python/pki/server/__init__.py | 8 ++ base/server/python/pki/server/cli/banner.py | 186 ++++++++++++++++++++++++++++ 2 files changed, 194 insertions(+) create mode 100644 base/server/python/pki/server/cli/banner.py (limited to 'base/server/python') diff --git a/base/server/python/pki/server/__init__.py b/base/server/python/pki/server/__init__.py index 46c6711ed..0852b121b 100644 --- a/base/server/python/pki/server/__init__.py +++ b/base/server/python/pki/server/__init__.py @@ -19,6 +19,7 @@ # from __future__ import absolute_import +import codecs from lxml import etree import functools import getpass @@ -501,6 +502,7 @@ class PKIInstance(object): self.conf_dir = os.path.join(CONFIG_BASE_DIR, name) self.log_dir = os.path.join(LOG_BASE_DIR, name) + self.banner_file = os.path.join(self.conf_dir, 'banner.txt') self.password_conf = os.path.join(self.conf_dir, 'password.conf') self.external_certs_conf = os.path.join( self.conf_dir, 'external_certs.conf') @@ -792,6 +794,12 @@ class PKIInstance(object): self.conf_dir, 'Catalina', 'localhost', webapp_name + '.xml') os.remove(context_xml) + def banner_installed(self): + return os.path.exists(self.banner_file) + + def get_banner(self): + return codecs.open(self.banner_file, "UTF-8").read().strip() + def __repr__(self): if self.type == 9: return "Dogtag 9 " + self.name diff --git a/base/server/python/pki/server/cli/banner.py b/base/server/python/pki/server/cli/banner.py new file mode 100644 index 000000000..98f8f164c --- /dev/null +++ b/base/server/python/pki/server/cli/banner.py @@ -0,0 +1,186 @@ +# Authors: +# Endi S. Dewata +# +# 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) 2017 Red Hat, Inc. +# All rights reserved. +# + +from __future__ import absolute_import +from __future__ import print_function +import codecs +import getopt +from lxml import etree +import sys +import traceback + +import pki.cli + + +class BannerCLI(pki.cli.CLI): + + def __init__(self): + super(BannerCLI, self).__init__('banner', + 'Banner management commands') + + self.add_module(BannerShowCLI()) + self.add_module(BannerValidateCLI()) + + +class BannerShowCLI(pki.cli.CLI): + + def __init__(self): + super(BannerShowCLI, self).__init__('show', 'Show banner') + + def usage(self): + print('Usage: pki-server banner-show [OPTIONS]') + print() + print(' -i, --instance Instance ID (default: pki-tomcat).') + 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=', + 'verbose', 'help']) + + except getopt.GetoptError as e: + print('ERROR: ' + str(e)) + self.usage() + sys.exit(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.usage() + sys.exit() + + else: + print('ERROR: unknown option ' + o) + self.usage() + sys.exit(1) + + instance = pki.server.PKIInstance(instance_name) + + if not instance.is_valid(): + print('ERROR: Invalid instance %s.' % instance_name) + sys.exit(1) + + instance.load() + + if not instance.banner_installed(): + print('ERROR: Banner is not installed') + sys.exit(1) + + print(instance.get_banner()) + + +class BannerValidateCLI(pki.cli.CLI): + + def __init__(self): + super(BannerValidateCLI, self).__init__('validate', 'Validate banner') + + def usage(self): + print('Usage: pki-server banner-validate [OPTIONS]') + print() + print(' -i, --instance Instance ID (default: pki-tomcat).') + print(' --file Validate specified banner 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=', 'file=', + 'verbose', 'help']) + + except getopt.GetoptError as e: + print('ERROR: ' + str(e)) + self.usage() + sys.exit(1) + + instance_name = 'pki-tomcat' + banner_file = None + + for o, a in opts: + if o in ('-i', '--instance'): + instance_name = a + + elif o == '--file': + banner_file = a + + elif o in ('-v', '--verbose'): + self.set_verbose(True) + + elif o == '--help': + self.usage() + sys.exit() + + else: + print('ERROR: unknown option ' + o) + self.usage() + sys.exit(1) + + if banner_file: + + # load banner from file + banner = codecs.open(banner_file, "UTF-8").read().strip() + + else: + + # load banner from instance + instance = pki.server.PKIInstance(instance_name) + + if not instance.is_valid(): + print('ERROR: Invalid instance %s.' % instance_name) + sys.exit(1) + + instance.load() + + if not instance.banner_installed(): + self.print_message('Banner is not installed') + return + + banner = instance.get_banner() + + if not banner: + print('ERROR: Banner is empty') + sys.exit(1) + + xml_banner = "" + banner + "" + + try: + parser = etree.XMLParser() + etree.fromstring(xml_banner, parser) + + self.print_message('Banner is valid') + + except etree.XMLSyntaxError as e: + if self.verbose: + traceback.print_exc() + print('ERROR: Banner contains invalid character(s)') + sys.exit(1) -- cgit