From 05b5b8411a8cb1ab65f9dfa2c48108da413f8e81 Mon Sep 17 00:00:00 2001
From: Peter Hamilton <peter.allen.hamilton@gmail.com>
Date: Wed, 11 Apr 2018 11:39:50 -0400
Subject: [PATCH] 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.
---
 kmip/core/exceptions.py                       |   6 +
 kmip/services/server/engine.py                |  69 +----
 kmip/services/server/monitor.py               | 131 +++++----
 kmip/services/server/server.py                |  52 +++-
 .../tests/unit/services/server/test_engine.py | 252 ++++++------------
 .../unit/services/server/test_monitor.py      | 139 ++++++++--
 .../tests/unit/services/server/test_server.py |  95 ++++++-
 7 files changed, 413 insertions(+), 331 deletions(-)

diff --git a/kmip/core/exceptions.py b/kmip/core/exceptions.py
index eb228de..dbc1d8b 100644
--- a/kmip/core/exceptions.py
+++ b/kmip/core/exceptions.py
@@ -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__()
diff --git a/kmip/services/server/engine.py b/kmip/services/server/engine.py
index 99bcfb9..fcda637 100644
--- a/kmip/services/server/engine.py
+++ b/kmip/services/server/engine.py
@@ -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(
diff --git a/kmip/services/server/monitor.py b/kmip/services/server/monitor.py
index 5239765..a3cd6b4 100644
--- a/kmip/services/server/monitor.py
+++ b/kmip/services/server/monitor.py
@@ -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, [])
diff --git a/kmip/services/server/server.py b/kmip/services/server/server.py
index 6647b6c..c99572a 100644
--- a/kmip/services/server/server.py
+++ b/kmip/services/server/server.py
@@ -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:
diff --git a/kmip/tests/unit/services/server/test_engine.py b/kmip/tests/unit/services/server/test_engine.py
index ded97a8..425cba9 100644
--- a/kmip/tests/unit/services/server/test_engine.py
+++ b/kmip/tests/unit/services/server/test_engine.py
@@ -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()
 
diff --git a/kmip/tests/unit/services/server/test_monitor.py b/kmip/tests/unit/services/server/test_monitor.py
index 23aba0b..7f4c435 100644
--- a/kmip/tests/unit/services/server/test_monitor.py
+++ b/kmip/tests/unit/services/server/test_monitor.py
@@ -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):
         """
diff --git a/kmip/tests/unit/services/server/test_server.py b/kmip/tests/unit/services/server/test_server.py
index 991f17c..e576d06 100644
--- a/kmip/tests/unit/services/server/test_server.py
+++ b/kmip/tests/unit/services/server/test_server.py
@@ -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.