Add client support for custom configuration file paths

This change adds client support for setting custom configuration
file paths, allowing users and developers to place their settings
file wherever they want. All client demo scripts have been updated
to support a '-s' flag that can be used to set the configuration
file for the demo. Client unit tests have also been updated to
include this change.
This commit is contained in:
Peter Hamilton 2018-04-17 14:41:04 -04:00
parent 583559195f
commit f9e32552f8
33 changed files with 166 additions and 45 deletions

View File

@ -45,15 +45,20 @@ class ConfigHelper(object):
# Timeout measured in seconds
DEFAULT_TIMEOUT = 30
def __init__(self):
def __init__(self, path=None):
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))
filenames = path
if not path:
filenames = CONFIG_FILE
if self.conf.read(filenames):
self.logger.debug("Using config file at {0}".format(filenames))
else:
self.logger.warning(
"Config file {0} not found".format(CONFIG_FILE))
"Config file {0} not found".format(filenames))
def get_valid_value(self, direct_value, config_section,
config_option_name, default_value):

View File

@ -44,7 +44,10 @@ if __name__ == '__main__':
algorithm = getattr(enums.CryptographicAlgorithm, algorithm, None)
# Build the client and connect to the server
with client.ProxyKmipClient(config=config) as client:
with client.ProxyKmipClient(
config=config,
config_file=opts.config_file
) as client:
try:
uid = client.create(
algorithm,

View File

@ -43,7 +43,10 @@ if __name__ == '__main__':
algorithm = getattr(enums.CryptographicAlgorithm, algorithm, None)
# Build the client and connect to the server
with client.ProxyKmipClient(config=config) as client:
with client.ProxyKmipClient(
config=config,
config_file=opts.config_file
) as client:
try:
public_uid, private_uid = client.create_key_pair(
algorithm,

View File

@ -54,7 +54,10 @@ if __name__ == '__main__':
message = binascii.unhexlify(message[1:])
# Build the client and connect to the server
with client.ProxyKmipClient(config=config) as client:
with client.ProxyKmipClient(
config=config,
config_file=opts.config_file
) as client:
# Decrypt the cipher text with the encryption key.
try:
plain_text = client.decrypt(

View File

@ -30,7 +30,10 @@ if __name__ == '__main__':
config = opts.config
# Build the client and connect to the server
with client.ProxyKmipClient(config=config) as client:
with client.ProxyKmipClient(
config=config,
config_file=opts.config_file
) as client:
# Create keys to use for derivation
try:
key_id = client.create(

View File

@ -37,7 +37,10 @@ if __name__ == '__main__':
sys.exit()
# Build the client and connect to the server
with client.ProxyKmipClient(config=config) as client:
with client.ProxyKmipClient(
config=config,
config_file=opts.config_file
) as client:
try:
client.destroy(uid)
logger.info("Successfully destroyed secret with ID: {0}".format(

View File

@ -50,7 +50,10 @@ if __name__ == '__main__':
message = bytes(message, 'utf-8')
# Build the client and connect to the server
with client.ProxyKmipClient(config=config) as client:
with client.ProxyKmipClient(
config=config,
config_file=opts.config_file
) as client:
# Create an encryption key.
try:
key_id = client.create(

View File

@ -37,7 +37,10 @@ if __name__ == '__main__':
sys.exit()
# Build the client and connect to the server
with client.ProxyKmipClient(config=config) as client:
with client.ProxyKmipClient(
config=config,
config_file=opts.config_file
) as client:
try:
secret = client.get(uid)
logger.info("Successfully retrieved secret with ID: {0}".format(

View File

@ -37,7 +37,10 @@ if __name__ == '__main__':
sys.exit()
# Build the client and connect to the server
with client.ProxyKmipClient(config=config) as client:
with client.ProxyKmipClient(
config=config,
config_file=opts.config_file
) as client:
try:
attribute_names = client.get_attribute_list(uid)
logger.info("Successfully retrieved {0} attribute names:".format(

View File

@ -53,7 +53,10 @@ if __name__ == '__main__':
attributes = [name_obj]
# Build the client and connect to the server
with client.ProxyKmipClient(config=config) as client:
with client.ProxyKmipClient(
config=config,
config_file=opts.config_file
) as client:
try:
uuids = client.locate(attributes=attributes)
logger.info("Located uuids: {0}".format(uuids))

View File

@ -48,7 +48,10 @@ if __name__ == '__main__':
algorithm = getattr(enums.CryptographicAlgorithm, algorithm, None)
# Build the client and connect to the server
with client.ProxyKmipClient(config=config) as client:
with client.ProxyKmipClient(
config=config,
config_file=opts.config_file
) as client:
try:
uid, mac_data = client.mac(data, uid, algorithm)
logger.info("Successfully done MAC using key with ID: "

View File

@ -91,7 +91,10 @@ if __name__ == '__main__':
cert.operation_policy_name = opts.operation_policy_name
# Build the client and connect to the server
with client.ProxyKmipClient(config=config) as client:
with client.ProxyKmipClient(
config=config,
config_file=opts.config_file
) as client:
try:
uid = client.register(cert)
logger.info("Successfully registered certificate with ID: "

View File

@ -39,7 +39,10 @@ if __name__ == '__main__':
obj.operation_policy_name = opts.operation_policy_name
# Build the client and connect to the server
with client.ProxyKmipClient(config=config) as client:
with client.ProxyKmipClient(
config=config,
config_file=opts.config_file
) as client:
try:
uid = client.register(obj)
logger.info("Successfully registered opaque object with ID: "

View File

@ -118,7 +118,10 @@ if __name__ == '__main__':
key.operation_policy_name = opts.operation_policy_name
# Build the client and connect to the server
with client.ProxyKmipClient(config=config) as client:
with client.ProxyKmipClient(
config=config,
config_file=opts.config_file
) as client:
try:
uid = client.register(key)
logger.info("Successfully registered private key with ID: "

View File

@ -60,7 +60,10 @@ if __name__ == '__main__':
key.operation_policy_name = opts.operation_policy_name
# Build the client and connect to the server
with client.ProxyKmipClient(config=config) as client:
with client.ProxyKmipClient(
config=config,
config_file=opts.config_file
) as client:
try:
uid = client.register(key)
logger.info("Successfully registered public key with ID: "

View File

@ -41,7 +41,10 @@ if __name__ == '__main__':
secret.operation_policy_name = opts.operation_policy_name
# Build the client and connect to the server
with client.ProxyKmipClient(config=config) as client:
with client.ProxyKmipClient(
config=config,
config_file=opts.config_file
) as client:
try:
uid = client.register(secret)
logger.info(

View File

@ -44,7 +44,10 @@ if __name__ == '__main__':
key.operation_policy_name = opts.operation_policy_name
# Build the client and connect to the server
with client.ProxyKmipClient(config=config) as client:
with client.ProxyKmipClient(
config=config,
config_file=opts.config_file
) as client:
try:
uid = client.register(key)
logger.info("Successfully registered symmetric key with ID: "

View File

@ -31,7 +31,10 @@ if __name__ == '__main__':
config = opts.config
# Build the client and connect to the server
with client.ProxyKmipClient(config=config) as client:
with client.ProxyKmipClient(
config=config,
config_file=opts.config_file
) as client:
# Create keys to use for derivation
try:
signing_key_id = client.register(

View File

@ -31,7 +31,10 @@ if __name__ == '__main__':
config = opts.config
# Build the client and connect to the server
with client.ProxyKmipClient(config=config) as client:
with client.ProxyKmipClient(
config=config,
config_file=opts.config_file
) as client:
# Create keys to use for derivation
try:
signing_key_id = client.register(

View File

@ -40,7 +40,7 @@ if __name__ == '__main__':
sys.exit()
# Build the client and connect to the server
client = KMIPProxy(config=config)
client = KMIPProxy(config=config, config_file=opts.config_file)
client.open()
# Activate the object

View File

@ -74,7 +74,7 @@ if __name__ == '__main__':
credential = credential_factory.create_credential(credential_type,
credential_value)
# Build the client and connect to the server
client = KMIPProxy(config=config)
client = KMIPProxy(config=config, config_file=opts.config_file)
client.open()
# Build the different object attributes

View File

@ -87,7 +87,7 @@ if __name__ == '__main__':
credential = credential_factory.create_credential(credential_type,
credential_value)
# Build the client and connect to the server
client = KMIPProxy(config=config)
client = KMIPProxy(config=config, config_file=opts.config_file)
client.open()
algorithm_obj = attribute_factory.create_attribute(attribute_type,

View File

@ -59,7 +59,7 @@ if __name__ == '__main__':
credential = credential_factory.create_credential(credential_type,
credential_value)
# Build the client and connect to the server
client = KMIPProxy(config=config)
client = KMIPProxy(config=config, config_file=opts.config_file)
client.open()
# Destroy the SYMMETRIC_KEY object

View File

@ -45,7 +45,7 @@ if __name__ == '__main__':
protocol_versions.append(ProtocolVersion(int(mm[0]), int(mm[1])))
# Build the client and connect to the server
client = KMIPProxy(config=config)
client = KMIPProxy(config=config, config_file=opts.config_file)
client.open()
result = client.discover_versions(protocol_versions=protocol_versions)

View File

@ -77,7 +77,7 @@ if __name__ == '__main__':
key_format_type = KeyFormatType(format_type_enum)
# Build the client and connect to the server
client = KMIPProxy(config=config)
client = KMIPProxy(config=config, config_file=opts.config_file)
client.open()
# Retrieve the SYMMETRIC_KEY object

View File

@ -64,7 +64,7 @@ if __name__ == '__main__':
credential = credential_factory.create_credential(credential_type,
credential_value)
# Build the client and connect to the server
client = KMIPProxy(config=config)
client = KMIPProxy(config=config, config_file=opts.config_file)
client.open()
# Build name attribute

View File

@ -56,7 +56,7 @@ if __name__ == '__main__':
QueryFunction(QueryFunctionEnum.QUERY_EXTENSION_MAP))
# Build the client and connect to the server
client = KMIPProxy(config=config)
client = KMIPProxy(config=config, config_file=opts.config_file)
client.open()
result = client.query(query_functions=query_functions)

View File

@ -72,7 +72,7 @@ if __name__ == '__main__':
# Build the client, connect to the server, register the secret, and
# disconnect from the server
client = KMIPProxy(config=config)
client = KMIPProxy(config=config, config_file=opts.config_file)
client.open()
result = client.register(object_type, template_attribute, secret)

View File

@ -41,7 +41,7 @@ if __name__ == '__main__':
sys.exit()
# Build the client and connect to the server
client = KMIPProxy(config=config)
client = KMIPProxy(config=config, config_file=opts.config_file)
client.open()
# Activate the object

View File

@ -86,6 +86,15 @@ def build_cli_parser(operation=None):
default="client",
dest="config",
help="Client configuration group to load from configuration file")
parser.add_option(
"-s",
"--config-file",
action="store",
type="str",
default=None,
dest="config_file",
help="Path to the client configuration file."
)
if operation is Operation.CREATE:
parser.add_option(

View File

@ -61,7 +61,8 @@ class ProxyKmipClient(object):
ssl_version=None,
username=None,
password=None,
config='client'):
config='client',
config_file=None):
"""
Construct a ProxyKmipClient.
@ -88,6 +89,9 @@ class ProxyKmipClient(object):
file. Use to load a specific set of configuration settings from
the configuration file, instead of specifying them manually.
Optional, defaults to the default client section, 'client'.
config_file (string): The path to the client's configuration file.
Optional, defaults to None.
"""
self.logger = logging.getLogger()
@ -104,7 +108,9 @@ class ProxyKmipClient(object):
ssl_version=ssl_version,
username=username,
password=password,
config=config)
config=config,
config_file=config_file
)
# TODO (peter-hamilton) Add a multiprocessing lock for synchronization.
self._is_open = False

View File

@ -59,6 +59,7 @@ from kmip.core.utils import BytearrayStream
import logging
import logging.config
import os
import six
import socket
import ssl
@ -73,15 +74,27 @@ class KMIPProxy:
cert_reqs=None, ssl_version=None, ca_certs=None,
do_handshake_on_connect=None,
suppress_ragged_eofs=None,
username=None, password=None, timeout=30, config='client'):
username=None, password=None, timeout=30, config='client',
config_file=None):
self.logger = logging.getLogger(__name__)
self.credential_factory = CredentialFactory()
self.config = config
if config_file:
if not isinstance(config_file, six.string_types):
raise ValueError(
"The client configuration file argument must be a string."
)
if not os.path.exists(config_file):
raise ValueError(
"The client configuration file '{}' does not "
"exist.".format(config_file)
)
self._set_variables(host, port, keyfile, certfile,
cert_reqs, ssl_version, ca_certs,
do_handshake_on_connect, suppress_ragged_eofs,
username, password, timeout)
username, password, timeout, config_file)
self.batch_items = []
self.conformance_clauses = [
@ -1553,8 +1566,8 @@ class KMIPProxy:
def _set_variables(self, host, port, keyfile, certfile,
cert_reqs, ssl_version, ca_certs,
do_handshake_on_connect, suppress_ragged_eofs,
username, password, timeout):
conf = ConfigHelper()
username, password, timeout, config_file):
conf = ConfigHelper(config_file)
# TODO: set this to a host list
self.host_list_str = conf.get_valid_value(

View File

@ -96,6 +96,32 @@ class TestKMIPClient(TestCase):
def tearDown(self):
super(TestKMIPClient, self).tearDown()
def test_init_with_invalid_config_file_value(self):
"""
Test that the right error is raised when an invalid configuration file
value is provided to the client.
"""
kwargs = {'config_file': 1}
self.assertRaisesRegexp(
ValueError,
"The client configuration file argument must be a string.",
KMIPProxy,
**kwargs
)
def test_init_with_invalid_config_file_path(self):
"""
Test that the right error is raised when an invalid configuration file
path is provided to the client.
"""
kwargs = {'config_file': 'invalid'}
self.assertRaisesRegexp(
ValueError,
"The client configuration file 'invalid' does not exist.",
KMIPProxy,
**kwargs
)
def test_close(self):
"""
Test that calling close on the client works as expected.
@ -646,13 +672,21 @@ class TestKMIPClient(TestCase):
host_list_string = '127.0.0.1,127.0.0.3, 127.0.0.5'
host_list_expected = ['127.0.0.1', '127.0.0.3', '127.0.0.5']
self.client._set_variables(host=host_list_string,
port=None, keyfile=None, certfile=None,
cert_reqs=None, ssl_version=None,
ca_certs=None,
do_handshake_on_connect=False,
suppress_ragged_eofs=None, username=None,
password=None, timeout=None)
self.client._set_variables(
host=host_list_string,
port=None,
keyfile=None,
certfile=None,
cert_reqs=None,
ssl_version=None,
ca_certs=None,
do_handshake_on_connect=False,
suppress_ragged_eofs=None,
username=None,
password=None,
timeout=None,
config_file=None
)
self.assertEqual(host_list_expected, self.client.host_list)
def test_host_is_invalid_input(self):