Adds a configuration file

Adds a configuration file to allow users to modify settings for the
client and server. The configured settings can be overridden by
directly passing values when a kmip server or client is initialized.
Additionally, if the config file or config options are not found,
pre-set default values will be used.
This commit is contained in:
Kaitlin Farr 2014-09-17 00:24:58 -07:00
parent 736711ce23
commit 0212ee898c
12 changed files with 399 additions and 68 deletions

View File

@ -2,4 +2,4 @@
set -eu
python3.3 ../kmip/demos/server.py
python ../kmip/demos/server.py

View File

@ -0,0 +1,84 @@
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
try:
from configparser import SafeConfigParser
except ImportError:
from ConfigParser import SafeConfigParser
import logging
import os
FILE_PATH = os.path.dirname(os.path.abspath(__file__))
CONFIG_FILE = os.path.normpath(os.path.join(FILE_PATH, '../kmipconfig.ini'))
class ConfigHelper(object):
NONE_VALUE = 'None'
DEFAULT_HOST = "127.0.0.1"
DEFAULT_PORT = 5696
DEFAULT_CERTFILE = os.path.normpath(os.path.join(
FILE_PATH, '../demos/certs/server.crt'))
DEFAULT_KEYFILE = os.path.normpath(os.path.join(
FILE_PATH, '../demos/certs/server.key'))
DEFAULT_CA_CERTS = os.path.normpath(os.path.join(
FILE_PATH, '../demos/certs/server.crt'))
DEFAULT_SSL_VERSION = 'PROTOCOL_SSLv23'
def __init__(self):
self.logger = logging.getLogger(__name__)
self.conf = SafeConfigParser()
if self.conf.read(CONFIG_FILE):
self.logger.debug("Using config file at {0}".format(CONFIG_FILE))
else:
self.logger.warning(
"Config file {0} not found".format(CONFIG_FILE))
def get_valid_value(self, direct_value, config_section,
config_option_name, default_value):
"""Returns a value that can be used as a parameter in client or
server. If a direct_value is given, that value will be returned
instead of the value from the config file. If the appropriate config
file option is not found, the default_value is returned.
:param direct_value: represents a direct value that should be used.
supercedes values from config files
:param config_section: which section of the config file to use
:param config_option_name: name of config option value
:param default_value: default value to be used if other options not
found
:returns: a value that can be used as a parameter
"""
ARG_MSG = "Using given value '{0}' for {1}"
CONF_MSG = "Using value '{0}' from configuration file {1} for {2}"
DEFAULT_MSG = "Using default value '{0}' for {1}"
if direct_value:
return_value = direct_value
self.logger.debug(ARG_MSG.format(direct_value, config_option_name))
else:
try:
return_value = self.conf.get(config_section,
config_option_name)
self.logger.debug(CONF_MSG.format(return_value,
CONFIG_FILE,
config_option_name))
except:
return_value = default_value
self.logger.debug(DEFAULT_MSG.format(default_value,
config_option_name))
if return_value == self.NONE_VALUE:
return None
else:
return return_value

View File

@ -14,8 +14,8 @@
# under the License.
import logging
import os
import optparse
import os
import sys
from kmip.services.kmip_server import KMIPServer
@ -23,12 +23,15 @@ from kmip.services.kmip_server import KMIPServer
FILE_PATH = os.path.dirname(os.path.abspath(__file__))
def run_server(host='127.0.0.1', port=5696,
cert_file=FILE_PATH + '/../tests/utils/certs/server.crt',
key_file=FILE_PATH + '/../tests/utils/certs/server.key'):
def run_server(host, port, keyfile, certfile, cert_reqs, ssl_version,
ca_certs, do_handshake_on_connect, suppress_ragged_eofs):
logger = logging.getLogger(__name__)
server = KMIPServer(host, port, cert_file, key_file)
server = KMIPServer(host=host, port=port, certfile=certfile,
keyfile=keyfile, cert_reqs=cert_reqs,
ssl_version=ssl_version, ca_certs=ca_certs,
do_handshake_on_connect=do_handshake_on_connect,
suppress_ragged_eofs=suppress_ragged_eofs)
logger.info('Starting the KMIP server')
@ -47,23 +50,40 @@ def run_server(host='127.0.0.1', port=5696,
def build_cli_parser():
parser = optparse.OptionParser(usage="%prog [options]",
description="Run KMIP Server")
parser.add_option("-n", "--hostname", action="store", default='127.0.0.1',
dest="hostname",
parser.add_option("-n", "--host", action="store", default=None,
dest="host",
help="Hostname/IP address of platform running the KMIP "
"server (e.g., localhost, 127.0.0.1)")
parser.add_option("-p", "--port", action="store", default=5696,
parser.add_option("-p", "--port", action="store", default=None,
dest="port", help="Port number for KMIP services")
parser.add_option("-c", "--cert_file", action="store",
default=FILE_PATH + '/../tests/utils/certs/server.crt',
dest="cert_file")
parser.add_option("-k", "--key_file", action="store",
default=FILE_PATH + '/../tests/utils/certs/server.key',
dest="key_file")
parser.add_option("-c", "--certfile", action="store", default=None,
dest="certfile")
parser.add_option("-k", "--keyfile", action="store", default=None,
dest="keyfile")
parser.add_option("-r", "--cert_reqs", action="store", default=None,
dest="cert_reqs")
parser.add_option("-s", "--ssl_version", action="store", default=None,
dest="ssl_version")
parser.add_option("-a", "--ca_certs", action="store", default=None,
dest="ca_certs")
parser.add_option("-d", "--do_handshake_on_connect", action="store",
default=None, dest="do_handshake_on_connect")
parser.add_option("-e", "--suppress_ragged_eofs", action="store",
default=None, dest="suppress_ragged_eofs")
return parser
if __name__ == '__main__':
parser = build_cli_parser()
opts, args = parser.parse_args(sys.argv[1:])
run_server(opts.hostname, opts.port, opts.cert_file, opts.key_file)
run_server(host=opts.host,
port=opts.port,
certfile=opts.certfile,
keyfile=opts.keyfile,
cert_reqs=opts.cert_reqs,
ssl_version=opts.ssl_version,
ca_certs=opts.ca_certs,
do_handshake_on_connect=opts.do_handshake_on_connect,
suppress_ragged_eofs=opts.suppress_ragged_eofs)

21
kmip/kmipconfig.ini Normal file
View File

@ -0,0 +1,21 @@
[client]
host=127.0.0.1
port=5696
keyfile=None
certfile=None
cert_reqs=CERT_REQUIRED
ssl_version=PROTOCOL_SSLv23
ca_certs=../demos/certs/server.crt
do_handshake_on_connect=True
suppress_ragged_eofs=True
[server]
host=127.0.0.1
port=5696
keyfile=../demos/certs/server.key
certfile=../demos/certs/server.crt
cert_reqs=CERT_NONE
ssl_version=PROTOCOL_SSLv23
ca_certs=None
do_handshake_on_connect=True
suppress_ragged_eofs=True

View File

@ -35,6 +35,8 @@ from kmip.core.messages import operations
from kmip.services.kmip_protocol import KMIPProtocol
from kmip.core.config_helper import ConfigHelper
from kmip.core.utils import BytearrayStream
import logging
@ -44,29 +46,36 @@ import socket
import ssl
FILE_PATH = os.path.dirname(os.path.abspath(__file__))
CONFIG_FILE = os.path.normpath(os.path.join(FILE_PATH, '../kmipconfig.ini'))
class KMIPProxy(KMIP):
# TODO (peter-hamilton) Move these defaults into config
def __init__(self, hostname='127.0.0.1', port=5696,
ca_certs_file=FILE_PATH + '/../tests/utils/certs/server.crt'):
def __init__(self, host=None, port=None, keyfile=None, certfile=None,
cert_reqs=None, ssl_version=None, ca_certs=None,
do_handshake_on_connect=None,
suppress_ragged_eofs=None):
super(self.__class__, self).__init__()
self.logger = logging.getLogger(__name__)
self.hostname = hostname
self.port = port
self._set_variables(host, port, keyfile, certfile,
cert_reqs, ssl_version, ca_certs,
do_handshake_on_connect, suppress_ragged_eofs)
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
if ca_certs_file is not None:
self.socket = ssl.wrap_socket(sock,
ca_certs=ca_certs_file,
cert_reqs=ssl.CERT_REQUIRED)
else:
self.socket = sock
self.socket = ssl.wrap_socket(
sock,
keyfile=self.keyfile,
certfile=self.certfile,
cert_reqs=self.cert_reqs,
ssl_version=self.ssl_version,
ca_certs=self.ca_certs,
do_handshake_on_connect=self.do_handshake_on_connect,
suppress_ragged_eofs=self.suppress_ragged_eofs)
self.protocol = KMIPProtocol(self.socket)
def open(self):
self.socket.connect((self.hostname, self.port))
self.socket.connect((self.host, self.port))
def close(self):
self.socket.shutdown(socket.SHUT_RDWR)
@ -285,3 +294,43 @@ class KMIPProxy(KMIP):
def _receive_message(self):
return self.protocol.read()
def _set_variables(self, host, port, keyfile, certfile,
cert_reqs, ssl_version, ca_certs,
do_handshake_on_connect, suppress_ragged_eofs):
conf = ConfigHelper()
self.host = conf.get_valid_value(
host, 'client', 'host', conf.DEFAULT_HOST)
self.port = int(conf.get_valid_value(
port, 'client', 'port', conf.DEFAULT_PORT))
self.keyfile = conf.get_valid_value(
keyfile, 'client', 'keyfile', None)
self.certfile = conf.get_valid_value(
certfile, 'client', 'certfile', None)
self.cert_reqs = getattr(ssl, conf.get_valid_value(
cert_reqs, 'client', 'cert_reqs', 'CERT_REQUIRED'))
self.ssl_version = getattr(ssl, conf.get_valid_value(
ssl_version, 'client', 'ssl_version', conf.DEFAULT_SSL_VERSION))
self.ca_certs = conf.get_valid_value(
ca_certs, 'client', 'ca_certs', conf.DEFAULT_CA_CERTS)
if conf.get_valid_value(
do_handshake_on_connect, 'client',
'do_handshake_on_connect', 'True') == 'True':
self.do_handshake_on_connect = True
else:
self.do_handshake_on_connect = False
if conf.get_valid_value(
suppress_ragged_eofs, 'client',
'suppress_ragged_eofs', 'True') == 'True':
self.suppress_ragged_eofs = True
else:
self.suppress_ragged_eofs = False

View File

@ -13,10 +13,12 @@
# License for the specific language governing permissions and limitations
# under the License.
import logging
import os
import socket
import ssl
from kmip.core.config_helper import ConfigHelper
from kmip.core.server import KMIPImpl
from kmip.services.kmip_protocol import KMIPProtocolFactory
@ -26,16 +28,22 @@ FILE_PATH = os.path.dirname(os.path.abspath(__file__))
class KMIPServer(object):
def __init__(self, host='127.0.0.1', port=5696,
cert_file=None, key_file=None):
def __init__(self, host=None, port=None, keyfile=None, certfile=None,
cert_reqs=None, ssl_version=None, ca_certs=None,
do_handshake_on_connect=None, suppress_ragged_eofs=None):
self.logger = logging.getLogger(__name__)
self._set_variables(host, port, keyfile, certfile, cert_reqs,
ssl_version, ca_certs, do_handshake_on_connect,
suppress_ragged_eofs)
handler = KMIPImpl()
self._processor = Processor(handler)
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.socket.bind((host, int(port)))
self.cert_file = cert_file
self.key_file = key_file
self.socket.bind((self.host, self.port))
def close(self):
self.socket.shutdown(socket.SHUT_RDWR)
@ -45,11 +53,16 @@ class KMIPServer(object):
self.socket.listen(0)
while True:
connection, address = self.socket.accept()
if self.cert_file and self.key_file:
connection = ssl.wrap_socket(connection,
server_side=True,
certfile=self.cert_file,
keyfile=self.key_file)
connection = ssl.wrap_socket(
connection,
keyfile=self.keyfile,
certfile=self.certfile,
server_side=True,
cert_reqs=self.cert_reqs,
ssl_version=self.ssl_version,
ca_certs=self.ca_certs,
do_handshake_on_connect=self.do_handshake_on_connect,
suppress_ragged_eofs=self.suppress_ragged_eofs)
factory = KMIPProtocolFactory()
protocol = factory.getProtocol(connection)
@ -58,3 +71,40 @@ class KMIPServer(object):
self._processor.process(protocol, protocol)
except Exception:
connection.close()
def _set_variables(self, host, port, keyfile, certfile, cert_reqs,
ssl_version, ca_certs, do_handshake_on_connect,
suppress_ragged_eofs):
conf = ConfigHelper()
self.host = conf.get_valid_value(host, 'server',
'host', conf.DEFAULT_HOST)
self.port = int(conf.get_valid_value(port, 'server',
'port', conf.DEFAULT_PORT))
self.keyfile = conf.get_valid_value(
keyfile, 'server', 'keyfile', conf.DEFAULT_CERTFILE)
self.certfile = conf.get_valid_value(
certfile, 'server', 'certfile', conf.DEFAULT_KEYFILE)
self.cert_reqs = getattr(ssl, conf.get_valid_value(
cert_reqs, 'server', 'cert_reqs', 'CERT_NONE'))
self.ssl_version = getattr(ssl, conf.get_valid_value(
ssl_version, 'server', 'ssl_version', conf.DEFAULT_SSL_VERSION))
self.ca_certs = conf.get_valid_value(
ca_certs, 'server', 'ca_certs', None)
if conf.get_valid_value(
do_handshake_on_connect, 'server',
'do_handshake_on_connect', 'True') == 'True':
self.do_handshake_on_connect = True
else:
self.do_handshake_on_connect = False
if conf.get_valid_value(
suppress_ragged_eofs, 'server',
'suppress_ragged_eofs', 'True') == 'True':
self.suppress_ragged_eofs = True
else:
self.suppress_ragged_eofs = False

View File

@ -0,0 +1,94 @@
# Copyright (c) 2014 The Johns Hopkins University/Applied Physics Laboratory
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
try:
import configparser
except ImportError:
import ConfigParser as configparser
from testtools import TestCase
from mock import MagicMock
from mock import Mock
from kmip.core.config_helper import ConfigHelper
class TestConfigHelper(TestCase):
def setUp(self):
def side_effect(arg1, arg2):
if arg1 == 'conf_test_section' and arg2 == 'conf_test_option':
return 'conf_test_value'
elif arg1 == 'conf_test_section' and arg2 == 'conf_null_option':
return ConfigHelper.NONE_VALUE
else:
raise configparser.NoSectionError
super(TestConfigHelper, self).setUp()
self.config_helper = ConfigHelper()
self.config_helper.conf = MagicMock()
self.config_helper.conf.get = Mock(side_effect=side_effect)
def tearDown(self):
super(TestConfigHelper, self).tearDown()
def test_get_valid_value_null_input(self):
value = self.config_helper.get_valid_value(None, None, None, None)
self.assertEqual(None, value)
def test_get_valid_value_direct_value_is_none(self):
value = self.config_helper.get_valid_value(ConfigHelper.NONE_VALUE,
'conf_test_section',
'conf_test_option',
'test_default_option')
self.assertFalse(self.config_helper.conf.get.called)
self.assertEqual(None, value)
def test_get_valid_value_config_value_is_none(self):
value = self.config_helper.get_valid_value(None,
'conf_test_section',
'conf_null_option',
'test_default_option')
self.assertTrue(self.config_helper.conf.get.called)
self.config_helper.conf.get.assert_called_with('conf_test_section',
'conf_null_option')
self.assertEqual(None, value)
def test_get_valid_value_returns_direct(self):
value = self.config_helper.get_valid_value('test_direct_value',
'conf_test_section',
'conf_test_option',
'test_default_value')
self.assertFalse(self.config_helper.conf.get.called)
self.assertEqual('test_direct_value', value)
def test_get_valid_value_returns_conf_value(self):
value = self.config_helper.get_valid_value(None,
'conf_test_section',
'conf_test_option',
'test_default_value')
self.assertTrue(self.config_helper.conf.get.called)
self.config_helper.conf.get.assert_called_with('conf_test_section',
'conf_test_option')
self.assertEqual(value, 'conf_test_value')
def test_get_valid_value_returns_default(self):
value = self.config_helper.get_valid_value(None,
'invalid_section',
'invalid_option',
'test_default_value')
self.assertTrue(self.config_helper.conf.get.called)
self.config_helper.conf.get.assert_called_with('invalid_section',
'invalid_option')
self.assertEqual(value, 'test_default_value')

View File

@ -51,6 +51,8 @@ class TestKMIPClient(TestCase):
STARTUP_TIME = 1.0
SHUTDOWN_TIME = 0.1
KMIP_PORT = 9090
CA_CERTS_PATH = os.path.normpath(os.path.join(os.path.dirname(
os.path.abspath(__file__)), '../../demos/certs/server.crt'))
def setUp(self):
super(TestKMIPClient, self).setUp()
@ -72,7 +74,8 @@ class TestKMIPClient(TestCase):
# Set up and open the client proxy; shutdown the server if open fails
try:
self.client = KMIPProxy(port=self.KMIP_PORT)
self.client = KMIPProxy(port=self.KMIP_PORT,
ca_certs=self.CA_CERTS_PATH)
self.client.open()
except Exception as e:
self._shutdown_server()

View File

@ -1,16 +0,0 @@
-----BEGIN CERTIFICATE REQUEST-----
MIICijCCAXICAQAwRTELMAkGA1UEBhMCQVUxEzARBgNVBAgMClNvbWUtU3RhdGUx
ITAfBgNVBAoMGEludGVybmV0IFdpZGdpdHMgUHR5IEx0ZDCCASIwDQYJKoZIhvcN
AQEBBQADggEPADCCAQoCggEBAKcLbcQbhvzQ/5JB/omGt+VHXbnUinWKygYPNdJH
5dvt0DVUNRvlvjTjkrNqTTVGiAdSuhxylW6NB7/aJ5Cen3J22NT01O7g5JNsNrrD
wvOUNLnaMYCtIaMaHPrLFqTbSwlUoCbwY1W9/PWb63IorZOrs4iT0DhBqal6gshU
FXYPYqTtseO+lMwTh9ETIcnV8wwFCieX4czmQKcBZCBXShkyepSW/JczaYEelxhl
fsAvNWKnvLE0SCOM2wp7XaB4Rjx0wbenQQvg0KqksIBXBa/Xm2YNyzonnPpG59Ho
Auap3ZP6ZqgdRy9CYNK92j17ZGzrxG5FWNeGKSCJUi7O7/sCAwEAAaAAMA0GCSqG
SIb3DQEBBQUAA4IBAQAkMXNZFu+fcAAf/iKNAeG2p/ptKvFMIkm0JUp9zHhidm21
tgAjRMwOTKNQfGRKb1nVV45W8YBSaw3iZR50FKJPBmoO+S63InRJe4YhywcMQNXC
RH37IVxKzGl5NmfPqLmEAD/VGTKbqQr27YDQ/azwGhjPrjN3gSx5YklySSefQRuU
PQOvxYe2jA8fAo6kf0QFtxOPK2DVvnP2CQqyIOHdybWFeYrTWCiXWLDoKrkmACbE
SCLXT7dZaM7+BvrkMDNz85co7ik7fFUZgxeEWVYwVhnscg7/gJBSCvxFIBeoK9oP
TyJ0SuVK9fr8U3neXbQozmWc5WqYpISS8LGbJ/6H
-----END CERTIFICATE REQUEST-----

View File

@ -18,17 +18,22 @@ import optparse
import os
import sys
from kmip.core.config_helper import ConfigHelper
from kmip.services.kmip_server import KMIPServer
FILE_PATH = os.path.dirname(os.path.abspath(__file__))
def run_server(host='127.0.0.1', port=5696,
cert_file=FILE_PATH + '/certs/server.crt',
key_file=FILE_PATH + '/certs/server.key'):
def run_server(host, port, certfile, keyfile, cert_reqs, ssl_version,
ca_certs, do_handshake_on_connect, suppress_ragged_eofs):
logger = logging.getLogger(__name__)
server = KMIPServer(host, port, cert_file, key_file)
server = KMIPServer(host=host, port=port, keyfile=keyfile,
certfile=certfile, cert_reqs=cert_reqs,
ssl_version=ssl_version, ca_certs=ca_certs,
do_handshake_on_connect=do_handshake_on_connect,
suppress_ragged_eofs=suppress_ragged_eofs)
logger.info('Starting the KMIP server')
@ -47,18 +52,31 @@ def run_server(host='127.0.0.1', port=5696,
def build_cli_parser():
parser = optparse.OptionParser(usage="%prog [options]",
description="Run KMIP Server")
parser.add_option("-n", "--hostname", action="store", default='127.0.0.1',
dest="hostname",
parser.add_option("-n", "--host", action="store", default='127.0.0.1',
dest="host",
help="Hostname/IP address of platform running the KMIP "
"server (e.g., localhost, 127.0.0.1)")
parser.add_option("-p", "--port", action="store", default=5696,
dest="port", help="Port number for KMIP services")
parser.add_option("-c", "--cert_file", action="store",
default=FILE_PATH + '/certs/server.crt',
dest="cert_file")
parser.add_option("-k", "--key_file", action="store",
default=FILE_PATH + '/certs/server.key',
dest="key_file")
parser.add_option("-k", "--keyfile", action="store",
default=os.path.normpath(os.path.join(
FILE_PATH, '../../demos/certs/server.key')),
dest="keyfile")
parser.add_option("-c", "--certfile", action="store",
default=os.path.normpath(os.path.join(
FILE_PATH, '../../demos/certs/server.crt')),
dest="certfile")
parser.add_option("-r", "--cert_reqs", action="store",
default="CERT_NONE", dest="cert_reqs")
parser.add_option("-s", "--ssl_version", action="store",
default='PROTOCOL_SSLv23', dest="ssl_version")
parser.add_option("-a", "--ca_certs", action="store",
default=ConfigHelper.NONE_VALUE, dest="ca_certs")
parser.add_option("-d", "--do_handshake_on_connect", action="store",
default="True", dest="do_handshake_on_connect")
parser.add_option("-e", "--suppress_ragged_eofs", action="store",
default="True", dest="suppress_ragged_eofs")
return parser
if __name__ == '__main__':
@ -66,4 +84,12 @@ if __name__ == '__main__':
opts, args = parser.parse_args(sys.argv[1:])
run_server(opts.hostname, opts.port, opts.cert_file, opts.key_file)
run_server(host=opts.host,
port=opts.port,
certfile=opts.certfile,
keyfile=opts.keyfile,
cert_reqs=opts.cert_reqs,
ssl_version=opts.ssl_version,
ca_certs=opts.ca_certs,
do_handshake_on_connect=opts.do_handshake_on_connect,
suppress_ragged_eofs=opts.suppress_ragged_eofs)