Integrate policy file monitoring with the server

This change updates the server, integrating policy file monitoring
and restructuring the engine. The top-level server entity now
handles loading policy files using the PolicyDirectoryMonitor
subprocess. A shared memory dictionary is used to share newly
modified policy data across the session threads managed by the
server and used by the engine. The legacy policy loading code in
the engine has been removed.

Unit tests have been added and modified for both the server and
engine to verify the functionality of these modifications.
This commit is contained in:
Peter Hamilton 2018-04-11 11:39:50 -04:00
parent 3c59dcf61a
commit 05b5b8411a
7 changed files with 413 additions and 331 deletions

View File

@ -311,6 +311,12 @@ class InvalidPrimitiveLength(Exception):
pass
class ShutdownError(Exception):
"""
An error generated when a problem occurs with shutting down the server.
"""
class StreamNotEmptyError(Exception):
def __init__(self, cls, extra):
super(StreamNotEmptyError, self).__init__()

View File

@ -15,7 +15,6 @@
import copy
import logging
import os
import six
import sqlalchemy
@ -42,8 +41,6 @@ from kmip.core.messages import payloads
from kmip.core import misc
from kmip.core import policy as operation_policy
from kmip.pie import factory
from kmip.pie import objects
from kmip.pie import sqltypes
@ -77,7 +74,7 @@ class KmipEngine(object):
* Cryptographic usage mask enforcement per object type
"""
def __init__(self, policy_path=None):
def __init__(self, policies=None):
"""
Create a KmipEngine.
@ -124,69 +121,9 @@ class KmipEngine(object):
}
self._attribute_policy = policy.AttributePolicy(self._protocol_version)
self._operation_policies = copy.deepcopy(operation_policy.policies)
self._load_operation_policies(policy_path)
self._operation_policies = policies
self._client_identity = [None, None]
def _load_operation_policies(self, policy_path):
if (policy_path is None) or (not os.path.isdir(policy_path)):
self._logger.warning(
"The specified operation policy directory{0} is not "
"valid. No user-defined policies will be loaded.".format(
" (" + policy_path + ")" if policy_path else ''
)
)
return dict()
else:
self._logger.info(
"Loading user-defined operation policy files from: {0}".format(
policy_path
)
)
for filename in os.listdir(policy_path):
file_path = os.path.join(policy_path, filename)
if os.path.isfile(file_path):
self._logger.info(
"Loading user-defined operation policies "
"from file: {0}".format(file_path)
)
try:
policies = operation_policy.read_policy_from_file(
file_path
)
except ValueError as e:
self._logger.error(
"A failure occurred while loading policies."
)
self._logger.exception(e)
continue
reserved_policies = ['default', 'public']
for policy_name in six.iterkeys(policies):
if policy_name in reserved_policies:
self._logger.warning(
"Loaded policy '{0}' overwrites a reserved "
"policy and will be thrown out.".format(
policy_name
)
)
elif policy_name in six.iterkeys(
self._operation_policies
):
self._logger.warning(
"Loaded policy '{0}' overwrites a "
"preexisting policy and will be thrown "
"out.".format(policy_name)
)
else:
self._operation_policies.update([(
policy_name,
policies.get(policy_name)
)])
def _get_enum_string(self, e):
return ''.join([x.capitalize() for x in e.name.split('_')])
@ -982,6 +919,8 @@ class KmipEngine(object):
object_type.unique_identifier == uid
).one()
# TODO (peter-hamilton) Add debug log with policy contents?
# Determine if the request should be carried out under the object's
# operation policy. If not, feign ignorance of the object.
is_allowed = self._is_allowed_by_operation_policy(

View File

@ -35,7 +35,7 @@ class PolicyDirectoryMonitor(multiprocessing.Process):
A file monitor that tracks modifications made within the policy directory.
"""
def __init__(self, policy_directory, policy_store):
def __init__(self, policy_directory, policy_store, live_monitoring=True):
"""
Set up the file monitor with the policy directory to track.
@ -46,11 +46,15 @@ class PolicyDirectoryMonitor(multiprocessing.Process):
multiprocessing resource manager. Used to store and share the
policy information across server processes and threads.
Required.
live_monitoring (boolean): A boolean indicating whether or not
live monitoring should continue indefinitely. Optional,
defaults to True.
"""
super(PolicyDirectoryMonitor, self).__init__()
self.halt_trigger = multiprocessing.Event()
self.policy_directory = policy_directory
self.live_monitoring = live_monitoring
self.file_timestamps = None
self.policy_cache = None
@ -71,69 +75,77 @@ class PolicyDirectoryMonitor(multiprocessing.Process):
def stop(self):
self.halt_trigger.set()
def scan_policies(self):
"""
Scan the policy directory for policy data.
"""
policy_files = get_json_files(self.policy_directory)
for f in set(policy_files) - set(self.policy_files):
self.file_timestamps[f] = 0
for f in set(self.policy_files) - set(policy_files):
self.logger.info("Removing policies for file: {}".format(f))
self.file_timestamps.pop(f, None)
for p in self.policy_cache.keys():
self.disassociate_policy_and_file(p, f)
for p in [k for k, v in self.policy_map.items() if v == f]:
self.restore_or_delete_policy(p)
self.policy_files = policy_files
for f in sorted(self.file_timestamps.keys()):
t = os.path.getmtime(f)
if t > self.file_timestamps[f]:
self.logger.info("Loading policies for file: {}".format(f))
self.file_timestamps[f] = t
old_p = [k for k, v in self.policy_map.items() if v == f]
try:
new_p = operation_policy.read_policy_from_file(f)
except ValueError:
self.logger.error("Failure loading file: {}".format(f))
self.logger.debug("", exc_info=True)
continue
for p in new_p.keys():
self.logger.info("Loading policy: {}".format(p))
if p in self.reserved_policies:
self.logger.warning(
"Policy '{}' overwrites a reserved policy and "
"will be thrown out.".format(p)
)
continue
if p in sorted(self.policy_store.keys()):
self.logger.debug(
"Policy '{}' overwrites an existing "
"policy.".format(p)
)
if f != self.policy_map.get(p):
self.policy_cache.get(p).append(
(
time.time(),
self.policy_map.get(p),
self.policy_store.get(p)
)
)
else:
self.policy_cache[p] = []
self.policy_store[p] = new_p.get(p)
self.policy_map[p] = f
for p in set(old_p) - set(new_p.keys()):
self.disassociate_policy_and_file(p, f)
self.restore_or_delete_policy(p)
def run(self):
"""
Start monitoring operation policy files.
"""
self.initialize_tracking_structures()
self.logger.info("Starting up the operation policy file monitor.")
while not self.halt_trigger.is_set():
time.sleep(1)
policy_files = get_json_files(self.policy_directory)
for f in set(policy_files) - set(self.policy_files):
self.file_timestamps[f] = 0
for f in set(self.policy_files) - set(policy_files):
self.logger.info("Removing policies for file: {}".format(f))
self.file_timestamps.pop(f, None)
for p in self.policy_cache.keys():
self.disassociate_policy_and_file(p, f)
for p in [k for k, v in self.policy_map.items() if v == f]:
self.restore_or_delete_policy(p)
self.policy_files = policy_files
for f in sorted(self.file_timestamps.keys()):
t = os.path.getmtime(f)
if t > self.file_timestamps[f]:
self.logger.info("Loading policies for file: {}".format(f))
self.file_timestamps[f] = t
old_p = [k for k, v in self.policy_map.items() if v == f]
try:
new_p = operation_policy.read_policy_from_file(f)
except ValueError:
self.logger.error("Failure loading file: {}".format(f))
self.logger.debug("", exc_info=True)
continue
for p in new_p.keys():
self.logger.info("Loading policy: {}".format(p))
if p in self.reserved_policies:
self.logger.warning(
"Policy '{}' overwrites a reserved policy and "
"will be thrown out.".format(p)
)
continue
if p in sorted(self.policy_store.keys()):
self.logger.debug(
"Policy '{}' overwrites an existing "
"policy.".format(p)
)
if f != self.policy_map.get(p):
self.policy_cache.get(p).append(
(
time.time(),
self.policy_map.get(p),
self.policy_store.get(p)
)
)
else:
self.policy_cache[p] = []
self.policy_store[p] = new_p.get(p)
self.policy_map[p] = f
for p in set(old_p) - set(new_p.keys()):
self.disassociate_policy_and_file(p, f)
self.restore_or_delete_policy(p)
self.logger.info("Stopping the operation policy file monitor.")
if self.live_monitoring:
self.logger.info("Starting up the operation policy file monitor.")
while not self.halt_trigger.is_set():
time.sleep(1)
self.scan_policies()
self.logger.info("Stopping the operation policy file monitor.")
else:
self.scan_policies()
def initialize_tracking_structures(self):
self.file_timestamps = {}
@ -142,7 +154,8 @@ class PolicyDirectoryMonitor(multiprocessing.Process):
self.policy_map = {}
for k in self.policy_store.keys():
self.policy_store.pop(k, None)
if k not in self.reserved_policies:
self.policy_store.pop(k, None)
def disassociate_policy_and_file(self, policy, file_name):
c = self.policy_cache.get(policy, [])

View File

@ -13,20 +13,25 @@
# License for the specific language governing permissions and limitations
# under the License.
import copy
import logging
import logging.handlers as handlers
import multiprocessing
import optparse
import os
import signal
import six
import socket
import ssl
import sys
import threading
from kmip.core import exceptions
from kmip.core import policy as operation_policy
from kmip.services import auth
from kmip.services.server import config
from kmip.services.server import engine
from kmip.services.server import monitor
from kmip.services.server import session
@ -53,7 +58,8 @@ class KmipServer(object):
policy_path=None,
enable_tls_client_auth=None,
tls_cipher_suites=None,
logging_level=None
logging_level=None,
live_policies=False
):
"""
Create a KmipServer.
@ -113,6 +119,10 @@ class KmipServer(object):
level for the server. All log messages logged at this level or
higher in criticality will be logged. All log messages lower
in criticality will not be logged. Optional, defaults to None.
live_policies (boolean): A boolean indicating if the operation
policy directory should be actively monitored to autoload any
policy changes while the server is running. Optional, defaults
to False.
"""
self._logger = logging.getLogger('kmip.server')
self._setup_logging(log_path)
@ -131,6 +141,8 @@ class KmipServer(object):
tls_cipher_suites,
logging_level
)
self.live_policies = live_policies
self.policies = {}
self._logger.setLevel(self.config.settings.get('logging_level'))
@ -140,9 +152,6 @@ class KmipServer(object):
else:
self.auth_suite = auth.BasicAuthenticationSuite(cipher_suites)
self._engine = engine.KmipEngine(
self.config.settings.get('policy_path')
)
self._session_id = 1
self._is_serving = False
@ -223,6 +232,29 @@ class KmipServer(object):
NetworkingError: Raised if the TLS socket cannot be bound to the
network address.
"""
self.manager = multiprocessing.Manager()
self.policies = self.manager.dict()
policies = copy.deepcopy(operation_policy.policies)
for policy_name, policy_set in six.iteritems(policies):
self.policies[policy_name] = policy_set
self.policy_monitor = monitor.PolicyDirectoryMonitor(
self.config.settings.get('policy_path'),
self.policies,
self.live_policies
)
def interrupt_handler(trigger, frame):
self.policy_monitor.stop()
signal.signal(signal.SIGINT, interrupt_handler)
signal.signal(signal.SIGTERM, interrupt_handler)
self.policy_monitor.start()
self._engine = engine.KmipEngine(
policies=self.policies
)
self._logger.info("Starting server socket handler.")
# Create a TCP stream socket and configure it for immediate reuse.
@ -328,6 +360,16 @@ class KmipServer(object):
"Server failed to shutdown socket handler."
)
if hasattr(self, "policy_monitor"):
try:
self.policy_monitor.stop()
self.policy_monitor.join()
except Exception as e:
self._logger.exception(e)
raise exceptions.ShutdownError(
"Server failed to clean up the policy monitor."
)
def serve(self):
"""
Serve client connections.
@ -595,6 +637,8 @@ def main(args=None):
if opts.logging_level:
kwargs['logging_level'] = opts.logging_level
kwargs['live_policies'] = True
# Create and start the server.
s = KmipServer(**kwargs)
with s:

View File

@ -148,179 +148,6 @@ class TestKmipEngine(testtools.TestCase):
}
create_engine_mock.assert_called_once_with(*args, **fargs)
def test_load_operation_policies(self):
"""
Test that the KmipEngine can correctly load operation policies.
"""
e = engine.KmipEngine()
e._logger = mock.MagicMock()
policy_file = tempfile.NamedTemporaryFile(
dir=self.temp_dir
)
with open(policy_file.name, 'w') as f:
f.write(
'{"test": '
'{"default": {"CERTIFICATE": {"LOCATE": "ALLOW_ALL"}}}}'
)
self.assertEqual(2, len(e._operation_policies))
e._load_operation_policies(self.temp_dir)
e._logger.info.assert_any_call(
"Loading user-defined operation policy files from: {0}".format(
self.temp_dir
)
)
e._logger.info.assert_any_call(
"Loading user-defined operation policies from file: {0}".format(
policy_file.name
)
)
self.assertEqual(3, len(e._operation_policies))
self.assertIn('test', e._operation_policies.keys())
test_policy = {
'default': {
enums.ObjectType.CERTIFICATE: {
enums.Operation.LOCATE: enums.Policy.ALLOW_ALL
}
}
}
self.assertEqual(test_policy, e._operation_policies.get('test'))
def test_load_operation_policies_with_file_read_error(self):
"""
Test that the KmipEngine can correctly handle load errors.
"""
e = engine.KmipEngine()
e._logger = mock.MagicMock()
policy_file = tempfile.NamedTemporaryFile(
dir=self.temp_dir
)
with open(policy_file.name, 'w') as f:
f.write(
'{"test": {"INVALID": {"LOCATE": "ALLOW_ALL"}}}'
)
self.assertEqual(2, len(e._operation_policies))
e._load_operation_policies(self.temp_dir)
e._logger.info.assert_any_call(
"Loading user-defined operation policy files from: {0}".format(
self.temp_dir
)
)
e._logger.info.assert_any_call(
"Loading user-defined operation policies from file: {0}".format(
policy_file.name
)
)
e._logger.error.assert_called_once_with(
"A failure occurred while loading policies."
)
e._logger.exception.assert_called_once()
self.assertEqual(2, len(e._operation_policies))
def test_load_operation_policies_with_reserved(self):
"""
Test that the KmipEngine can correctly load operation policies, even
when a policy attempts to overwrite a reserved one.
"""
e = engine.KmipEngine()
e._logger = mock.MagicMock()
policy_file = tempfile.NamedTemporaryFile(
dir=self.temp_dir
)
with open(policy_file.name, 'w') as f:
f.write(
'{"public": {"CERTIFICATE": {"LOCATE": "ALLOW_ALL"}}}'
)
self.assertEqual(2, len(e._operation_policies))
e._load_operation_policies(self.temp_dir)
e._logger.info.assert_any_call(
"Loading user-defined operation policy files from: {0}".format(
self.temp_dir
)
)
e._logger.info.assert_any_call(
"Loading user-defined operation policies from file: {0}".format(
policy_file.name
)
)
e._logger.warning.assert_called_once_with(
"Loaded policy 'public' overwrites a reserved policy and will "
"be thrown out."
)
self.assertEqual(2, len(e._operation_policies))
def test_load_operation_policies_with_duplicate(self):
"""
Test that the KmipEngine can correctly load operation policies, even
when a policy is defined multiple times.
"""
self.skip('Refactor')
e = engine.KmipEngine()
e._logger = mock.MagicMock()
policy_file_a = tempfile.NamedTemporaryFile(
dir=self.temp_dir
)
with open(policy_file_a.name, 'w') as f:
f.write(
'{"test": {"CERTIFICATE": {"LOCATE": "ALLOW_ALL"}}}'
)
policy_file_b = tempfile.NamedTemporaryFile(
dir=self.temp_dir
)
with open(policy_file_b.name, 'w') as f:
f.write(
'{"test": {"CERTIFICATE": {"LOCATE": "ALLOW_ALL"}}}'
)
self.assertEqual(2, len(e._operation_policies))
e._load_operation_policies(self.temp_dir)
e._logger.info.assert_any_call(
"Loading user-defined operation policy files from: {0}".format(
self.temp_dir
)
)
e._logger.info.assert_any_call(
"Loading user-defined operation policies from file: {0}".format(
policy_file_a.name
)
)
e._logger.info.assert_any_call(
"Loading user-defined operation policies from file: {0}".format(
policy_file_b.name
)
)
e._logger.warning.assert_called_once_with(
"Loaded policy 'test' overwrites a preexisting policy and will "
"be thrown out."
)
self.assertEqual(3, len(e._operation_policies))
self.assertIn('test', e._operation_policies.keys())
test_policy = {
enums.ObjectType.CERTIFICATE: {
enums.Operation.LOCATE: enums.Policy.ALLOW_ALL
}
}
self.assertEqual(test_policy, e._operation_policies.get('test'))
def test_version_operation_match(self):
"""
Test that a valid response is generated when trying to invoke an
@ -957,6 +784,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
obj_a = pie_objects.OpaqueObject(b'', enums.OpaqueDataType.NONE)
@ -981,6 +809,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
args = ('1', )
@ -1007,6 +836,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
test_exception = exc.MultipleResultsFound()
e._data_session.query = mock.MagicMock(side_effect=test_exception)
e._logger = mock.MagicMock()
@ -1033,6 +863,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
obj_a = pie_objects.OpaqueObject(b'', enums.OpaqueDataType.NONE)
@ -1419,6 +1250,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
symmetric_key = pie_objects.SymmetricKey(
@ -1481,6 +1313,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
symmetric_key = pie_objects.SymmetricKey(
@ -2196,6 +2029,7 @@ class TestKmipEngine(testtools.TestCase):
Test that the lookup for a non-existent policy is handled correctly.
"""
e = engine.KmipEngine()
e._operation_policies = {}
e._logger = mock.MagicMock()
result = e.get_relevant_policy_section('invalid')
@ -2524,6 +2358,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=False)
e._logger = mock.MagicMock()
e._client_identity = 'test'
@ -3677,6 +3512,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
e._cryptography_engine.logger = mock.MagicMock()
@ -3851,6 +3687,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
e._cryptography_engine.logger = mock.MagicMock()
@ -3968,6 +3805,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
e._cryptography_engine.logger = mock.MagicMock()
@ -4003,6 +3841,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
e._cryptography_engine.logger = mock.MagicMock()
@ -4042,6 +3881,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
e._cryptography_engine.logger = mock.MagicMock()
@ -4162,6 +4002,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
e._cryptography_engine.logger = mock.MagicMock()
@ -4219,6 +4060,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
e._cryptography_engine.logger = mock.MagicMock()
@ -4280,6 +4122,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
e._cryptography_engine.logger = mock.MagicMock()
@ -4337,6 +4180,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
e._cryptography_engine.logger = mock.MagicMock()
@ -4402,6 +4246,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
obj_a = pie_objects.OpaqueObject(b'', enums.OpaqueDataType.NONE)
@ -4485,6 +4330,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
key = (b'\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
@ -4580,6 +4426,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
obj_a = pie_objects.OpaqueObject(b'', enums.OpaqueDataType.NONE)
@ -4686,6 +4533,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
obj_a = pie_objects.SymmetricKey(
@ -4793,6 +4641,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=False)
e._logger = mock.MagicMock()
e._client_identity = 'test'
@ -4824,6 +4673,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
e._cryptography_engine.logger = mock.MagicMock()
@ -4937,6 +4787,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
e._cryptography_engine.logger = mock.MagicMock()
@ -5003,6 +4854,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
e._cryptography_engine.logger = mock.MagicMock()
@ -5067,6 +4919,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
e._cryptography_engine.logger = mock.MagicMock()
@ -5111,6 +4964,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
e._cryptography_engine.logger = mock.MagicMock()
@ -5162,6 +5016,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
e._cryptography_engine.logger = mock.MagicMock()
@ -5226,6 +5081,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
e._cryptography_engine.logger = mock.MagicMock()
@ -5290,6 +5146,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
e._cryptography_engine.logger = mock.MagicMock()
@ -5355,6 +5212,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
e._cryptography_engine.logger = mock.MagicMock()
@ -5420,6 +5278,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
e._cryptography_engine.logger = mock.MagicMock()
@ -5485,6 +5344,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
secret = pie_objects.SymmetricKey(
@ -5541,6 +5401,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
secret = pie_objects.SymmetricKey(
@ -5624,6 +5485,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=False)
e._logger = mock.MagicMock()
e._client_identity = 'test'
@ -5657,6 +5519,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
secret = pie_objects.SymmetricKey(
@ -5734,6 +5597,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
secret = pie_objects.SymmetricKey(
@ -5810,6 +5674,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=False)
e._logger = mock.MagicMock()
e._client_identity = 'test'
@ -5843,6 +5708,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
managed_object = pie_objects.SymmetricKey(
@ -5913,6 +5779,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
managed_object = pie_objects.OpaqueObject(
@ -5953,6 +5820,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
managed_object = pie_objects.SymmetricKey(
@ -5989,6 +5857,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=False)
e._logger = mock.MagicMock()
e._client_identity = 'test'
@ -6021,6 +5890,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
managed_object = pie_objects.SymmetricKey(
@ -6169,6 +6039,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
managed_object = pie_objects.SymmetricKey(
@ -6211,6 +6082,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
managed_object = pie_objects.SymmetricKey(
@ -6255,6 +6127,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
managed_object = pie_objects.OpaqueObject(
@ -6299,6 +6172,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=False)
e._logger = mock.MagicMock()
e._client_identity = 'test'
@ -6337,6 +6211,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
obj_a = pie_objects.OpaqueObject(b'', enums.OpaqueDataType.NONE)
@ -6445,6 +6320,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=False)
e._logger = mock.MagicMock()
e._client_identity = 'test'
@ -6479,6 +6355,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
key = (b'\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
@ -6871,6 +6748,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
e._cryptography_engine.logger = mock.MagicMock()
@ -6937,6 +6815,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
e._cryptography_engine.logger = mock.MagicMock()
@ -6999,6 +6878,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
e._cryptography_engine.logger = mock.MagicMock()
@ -7051,6 +6931,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
e._cryptography_engine.logger = mock.MagicMock()
@ -7102,6 +6983,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
e._cryptography_engine.logger = mock.MagicMock()
@ -7158,6 +7040,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
e._cryptography_engine.logger = mock.MagicMock()
@ -7217,6 +7100,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
e._cryptography_engine.logger = mock.MagicMock()
@ -7286,6 +7170,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
e._cryptography_engine.logger = mock.MagicMock()
@ -7338,6 +7223,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
e._cryptography_engine.logger = mock.MagicMock()
@ -7389,6 +7275,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
e._cryptography_engine.logger = mock.MagicMock()
@ -7445,6 +7332,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
e._cryptography_engine.logger = mock.MagicMock()
@ -7501,6 +7389,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
e._cryptography_engine.logger = mock.MagicMock()
@ -7637,6 +7526,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
e._cryptography_engine.logger = mock.MagicMock()
@ -7690,6 +7580,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
e._cryptography_engine.logger = mock.MagicMock()
@ -7732,6 +7623,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
e._cryptography_engine.logger = mock.MagicMock()
@ -7790,6 +7682,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
e._cryptography_engine.logger = mock.MagicMock()
@ -7847,6 +7740,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
e._cryptography_engine.logger = mock.MagicMock()
@ -7915,6 +7809,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
key = (b'\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00'
@ -7992,6 +7887,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
e._cryptography_engine.logger = mock.MagicMock()
@ -8040,6 +7936,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
e._cryptography_engine.logger = mock.MagicMock()
@ -8089,6 +7986,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
attribute_factory = factory.AttributeFactory()
@ -8214,6 +8112,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
attribute_factory = factory.AttributeFactory()
@ -8424,6 +8323,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
attribute_factory = factory.AttributeFactory()
@ -8565,6 +8465,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
attribute_factory = factory.AttributeFactory()
@ -8773,6 +8674,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
e._cryptography_engine.logger = mock.MagicMock()
@ -8866,6 +8768,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
e._cryptography_engine.logger = mock.MagicMock()
@ -8946,6 +8849,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
e._cryptography_engine.logger = mock.MagicMock()
@ -8990,6 +8894,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
e._cryptography_engine.logger = mock.MagicMock()
@ -9077,6 +8982,7 @@ class TestKmipEngine(testtools.TestCase):
e._data_store = self.engine
e._data_store_session_factory = self.session_factory
e._data_session = e._data_store_session_factory()
e._is_allowed_by_operation_policy = mock.Mock(return_value=True)
e._logger = mock.MagicMock()
e._cryptography_engine.logger = mock.MagicMock()

View File

@ -493,33 +493,6 @@ class TestPolicyDirectoryMonitor(testtools.TestCase):
},
cache[0][2]
)
# self.assertEqual(
# {
# 'policy_A': [],
# 'policy_B': [
# (
# 1480043060.870089,
# os.path.join(self.tmp_dir, "policy_2.json"),
# {
# 'groups': {
# 'group_B': {
# enums.ObjectType.SYMMETRIC_KEY: {
# enums.Operation.GET:
# enums.Policy.ALLOW_ALL,
# enums.Operation.LOCATE:
# enums.Policy.ALLOW_ALL,
# enums.Operation.DESTROY:
# enums.Policy.ALLOW_ALL
# }
# }
# }
# }
# )
# ],
# 'policy_C': []
# },
# m.policy_cache
# )
self.assertEqual(3, len(m.policy_store.keys()))
self.assertEqual(
@ -1888,6 +1861,114 @@ class TestPolicyDirectoryMonitor(testtools.TestCase):
m.policy_store.get("policy_D", None)
)
def test_run_without_live_monitoring(self):
"""
Test that the PolicyDirectoryMonitor can load policy files and track
them properly even when operating in a one-shot scanning mode.
"""
m = monitor.PolicyDirectoryMonitor(
self.tmp_dir,
multiprocessing.Manager().dict(),
live_monitoring=False
)
m.logger = mock.MagicMock(logging.Logger)
m.halt_trigger = mock.MagicMock(multiprocessing.synchronize.Event)
m.halt_trigger.is_set.side_effect = [False, True]
write_file(self.tmp_dir, "policy_1.json", POLICY_1)
write_file(self.tmp_dir, "policy_2.json", POLICY_2)
self.assertEqual({}, m.file_timestamps)
self.assertEqual({}, m.policy_cache)
self.assertEqual([], m.policy_files)
self.assertEqual({}, m.policy_map)
self.assertEqual([], m.policy_store.keys())
m.run()
m.logger.info.assert_any_call(
"Loading policies for file: {}".format(
os.path.join(self.tmp_dir, "policy_1.json")
)
)
m.logger.info.assert_any_call("Loading policy: policy_A")
m.logger.info.assert_any_call(
"Loading policies for file: {}".format(
os.path.join(self.tmp_dir, "policy_2.json")
)
)
m.logger.info.assert_any_call("Loading policy: policy_B")
m.logger.info.assert_any_call("Loading policy: policy_C")
self.assertEqual(2, len(m.policy_files))
path = os.path.join(self.tmp_dir, "policy_1.json")
self.assertEqual(
os.path.getmtime(path),
m.file_timestamps.get(path, None)
)
self.assertIn(path, m.policy_files)
self.assertEqual(path, m.policy_map.get("policy_A", None))
path = os.path.join(self.tmp_dir, "policy_2.json")
self.assertEqual(
os.path.getmtime(path),
m.file_timestamps.get(path, None)
)
self.assertIn(path, m.policy_files)
self.assertEqual(path, m.policy_map.get("policy_B", None))
self.assertEqual(path, m.policy_map.get("policy_C", None))
self.assertEqual(
{
"policy_A": [],
"policy_B": [],
"policy_C": []
},
m.policy_cache
)
self.assertEqual(3, len(m.policy_store.keys()))
self.assertEqual(
{
"groups": {
"group_A": {
enums.ObjectType.SYMMETRIC_KEY: {
enums.Operation.GET: enums.Policy.ALLOW_ALL,
enums.Operation.DESTROY: enums.Policy.ALLOW_ALL
}
}
}
},
m.policy_store.get("policy_A", None)
)
self.assertEqual(
{
"groups": {
"group_B": {
enums.ObjectType.SYMMETRIC_KEY: {
enums.Operation.GET: enums.Policy.ALLOW_ALL,
enums.Operation.LOCATE: enums.Policy.ALLOW_ALL,
enums.Operation.DESTROY: enums.Policy.ALLOW_ALL
}
}
}
},
m.policy_store.get("policy_B", None)
)
self.assertEqual(
{
"groups": {
"group_C": {
enums.ObjectType.SYMMETRIC_KEY: {
enums.Operation.GET: enums.Policy.ALLOW_ALL,
enums.Operation.DESTROY: enums.Policy.DISALLOW_ALL
}
}
}
},
m.policy_store.get("policy_C", None)
)
def test_initialize_tracking_structures(self):
"""
Test that the PolicyDirectoryMonitor can correctly initialize/reset the
@ -1903,6 +1984,7 @@ class TestPolicyDirectoryMonitor(testtools.TestCase):
m.policy_files = ["a", "b"]
m.policy_map["a"] = "b"
m.policy_store["a"] = {"c": 2}
m.policy_store["default"] = {"c": 3}
m.initialize_tracking_structures()
@ -1910,7 +1992,8 @@ class TestPolicyDirectoryMonitor(testtools.TestCase):
self.assertEqual({}, m.policy_cache)
self.assertEqual([], m.policy_files)
self.assertEqual({}, m.policy_map)
self.assertEqual([], m.policy_store.keys())
self.assertEqual(["default"], m.policy_store.keys())
self.assertEqual({"c": 3}, m.policy_store.get("default"))
def test_disassociate_policy_and_file(self):
"""

View File

@ -51,7 +51,6 @@ class TestKmipServer(testtools.TestCase):
self.assertTrue(logging_mock.called)
self.assertIsInstance(s.auth_suite, auth.BasicAuthenticationSuite)
self.assertIsNotNone(s._engine)
self.assertEqual(1, s._session_id)
self.assertFalse(s._is_serving)
@ -167,13 +166,27 @@ class TestKmipServer(testtools.TestCase):
self.assertEqual('TLS1.2', s.config.settings.get('auth_suite'))
self.assertIsNotNone(s.auth_suite)
@mock.patch('multiprocessing.Manager')
@mock.patch('kmip.services.server.monitor.PolicyDirectoryMonitor')
@mock.patch('kmip.services.server.engine.KmipEngine')
@mock.patch('kmip.services.server.server.KmipServer._setup_logging')
def test_start(self, logging_mock, engine_mock):
def test_start(self,
logging_mock,
engine_mock,
monitor_mock,
manager_mock):
"""
Test that starting the KmipServer either runs as expected or generates
the expected error.
"""
monitor_instance_mock = mock.MagicMock()
monitor_mock.return_value = monitor_instance_mock
dict_mock = mock.MagicMock()
manager_instance_mock = mock.MagicMock()
manager_instance_mock.dict.return_value = dict_mock
manager_mock.return_value = manager_instance_mock
a_mock = mock.MagicMock()
b_mock = mock.MagicMock()
@ -196,7 +209,18 @@ class TestKmipServer(testtools.TestCase):
socket_mock.return_value = a_mock
ssl_mock.return_value = b_mock
manager_mock.assert_not_called()
monitor_mock.assert_not_called()
s.start()
manager_mock.assert_called_once_with()
monitor_mock.assert_called_once_with(
None,
dict_mock,
False
)
self.assertIsNotNone(s._engine)
s._logger.info.assert_any_call(
"Starting server socket handler."
)
@ -223,8 +247,20 @@ class TestKmipServer(testtools.TestCase):
"127.0.0.1:5696"
)
monitor_instance_mock.stop.assert_not_called()
handler = signal.getsignal(signal.SIGINT)
handler(None, None)
monitor_instance_mock.stop.assert_called_once_with()
monitor_instance_mock.stop.reset_mock()
monitor_instance_mock.stop.assert_not_called()
handler = signal.getsignal(signal.SIGTERM)
handler(None, None)
monitor_instance_mock.stop.assert_called_once_with()
self.assertTrue(s._is_serving)
manager_mock.reset_mock()
monitor_mock.reset_mock()
a_mock.reset_mock()
b_mock.reset_mock()
@ -237,6 +273,9 @@ class TestKmipServer(testtools.TestCase):
test_exception = Exception()
b_mock.bind.side_effect = test_exception
manager_mock.assert_not_called()
monitor_mock.assert_not_called()
regex = (
"Server failed to bind socket handler to 127.0.0.1:5696"
)
@ -245,6 +284,13 @@ class TestKmipServer(testtools.TestCase):
regex,
s.start
)
manager_mock.assert_called_once_with()
monitor_mock.assert_called_once_with(
None,
dict_mock,
False
)
s._logger.info.assert_any_call(
"Starting server socket handler."
)
@ -368,6 +414,50 @@ class TestKmipServer(testtools.TestCase):
s._socket.close.assert_called_once_with()
s._logger.exception(test_exception)
@mock.patch('kmip.services.server.engine.KmipEngine')
@mock.patch('kmip.services.server.server.KmipServer._setup_logging')
def test_stop_with_monitor_shutdown_error(self, logging_mock, engine_mock):
"""
Test that the right calls and log messages are triggered when stopping
the server results in an error while shutting down the policy monitor.
"""
s = server.KmipServer(
hostname='127.0.0.1',
port=5696,
config_path=None,
policy_path=None
)
s._logger = mock.MagicMock()
s._socket = mock.MagicMock()
s.policy_monitor = mock.MagicMock()
test_exception = Exception()
s.policy_monitor.join.side_effect = test_exception
# Test the expected behavior for a normal server stop sequence
thread_mock = mock.MagicMock()
thread_mock.join = mock.MagicMock()
thread_mock.is_alive = mock.MagicMock(return_value=False)
thread_mock.name = 'TestThread'
regex = "Server failed to clean up the policy monitor."
self.assertRaisesRegexp(
exceptions.ShutdownError,
regex,
s.stop
)
s._logger.info.assert_any_call(
"Cleaning up remaining connection threads."
)
s._logger.info.assert_any_call(
"Shutting down server socket handler."
)
s._socket.shutdown.assert_called_once_with(socket.SHUT_RDWR)
s._socket.close.assert_called_once_with()
s.policy_monitor.stop.assert_called_once_with()
s.policy_monitor.join.assert_called_once_with()
s._logger.exception(test_exception)
@mock.patch('kmip.services.server.engine.KmipEngine')
@mock.patch('kmip.services.server.server.KmipServer._setup_logging')
def test_serve(self, logging_mock, engine_mock):
@ -468,6 +558,7 @@ class TestKmipServer(testtools.TestCase):
policy_path=None
)
s._logger = mock.MagicMock()
s._engine = engine_mock
# Test that the right calls and log messages are made when
# starting a new session.