You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@qpid.apache.org by ch...@apache.org on 2016/05/11 21:21:25 UTC
qpid-dispatch git commit: DISPATCH-331: Define a default policy for
when Open hostname policy is absent or is to be ignored
Repository: qpid-dispatch
Updated Branches:
refs/heads/master 2138da722 -> 590d79ef9
DISPATCH-331: Define a default policy for when Open hostname policy is absent or is to be ignored
Project: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/commit/590d79ef
Tree: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/tree/590d79ef
Diff: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/diff/590d79ef
Branch: refs/heads/master
Commit: 590d79ef9e3472c5fc1376e52b3574eedc442fb9
Parents: 2138da7
Author: Chuck Rolke <cr...@redhat.com>
Authored: Wed May 11 17:19:23 2016 -0400
Committer: Chuck Rolke <cr...@redhat.com>
Committed: Wed May 11 17:19:23 2016 -0400
----------------------------------------------------------------------
python/qpid_dispatch/management/qdrouter.json | 14 ++++++
.../qpid_dispatch_internal/management/config.py | 5 ++
.../policy/policy_local.py | 51 +++++++++++++++++---
.../policy/policy_manager.py | 12 +++++
tests/router_policy_test.py | 44 +++++++++++++++++
5 files changed, 118 insertions(+), 8 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/590d79ef/python/qpid_dispatch/management/qdrouter.json
----------------------------------------------------------------------
diff --git a/python/qpid_dispatch/management/qdrouter.json b/python/qpid_dispatch/management/qdrouter.json
index e977438..9eafdbf 100644
--- a/python/qpid_dispatch/management/qdrouter.json
+++ b/python/qpid_dispatch/management/qdrouter.json
@@ -1328,6 +1328,20 @@
"required": false,
"create": true
},
+ "defaultApplication": {
+ "type": "string",
+ "default": "",
+ "description": "Application policyRuleset to use for connections with no open.hostname or a hostname that does not match any existing policy. For users that don't wish to use open.hostname or any multi-tennancy feature, this default policy can be the only policy in effect for the network.",
+ "required": false,
+ "create": true
+ },
+ "defaultApplicationEnabled": {
+ "type": "boolean",
+ "default": false,
+ "description": "Enable defaultApplication policy fallback logic.",
+ "required": false,
+ "create": true
+ },
"connectionsProcessed": {"type": "integer", "graph": true},
"connectionsDenied": {"type": "integer", "graph": true},
"connectionsCurrent": {"type": "integer", "graph": true}
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/590d79ef/python/qpid_dispatch_internal/management/config.py
----------------------------------------------------------------------
diff --git a/python/qpid_dispatch_internal/management/config.py b/python/qpid_dispatch_internal/management/config.py
index 6a5e741..c95d1f3 100644
--- a/python/qpid_dispatch_internal/management/config.py
+++ b/python/qpid_dispatch_internal/management/config.py
@@ -183,6 +183,8 @@ def configure_dispatch(dispatch, lib_handle, filename):
from qpid_dispatch_internal.display_name.display_name import DisplayNameService
displayname_service = DisplayNameService("$displayname")
policyFolder = config.by_type('policy')[0]['policyFolder']
+ policyDefaultApplication = config.by_type('policy')[0]['defaultApplication']
+ policyDefaultApplicationEnabled = config.by_type('policy')[0]['defaultApplicationEnabled']
# Remaining configuration
for t in "fixedAddress", "listener", "connector", "waypoint", "linkRoutePattern", \
"router.config.address", "router.config.linkRoute", "router.config.autoLink", \
@@ -207,3 +209,6 @@ def configure_dispatch(dispatch, lib_handle, filename):
pconfig = PolicyConfig(os.path.join(apath, i))
for a in pconfig.by_type("policyRuleset"):
agent.configure(a)
+
+ # Set policy default application after all rulesets loaded
+ agent.policy.set_default_application(policyDefaultApplication, policyDefaultApplicationEnabled)
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/590d79ef/python/qpid_dispatch_internal/policy/policy_local.py
----------------------------------------------------------------------
diff --git a/python/qpid_dispatch_internal/policy/policy_local.py b/python/qpid_dispatch_internal/policy/policy_local.py
index b690c52..cb62896 100644
--- a/python/qpid_dispatch_internal/policy/policy_local.py
+++ b/python/qpid_dispatch_internal/policy/policy_local.py
@@ -486,6 +486,16 @@ class PolicyLocal(object):
# Entries created as connection AMQP Opens arrive
# Entries destroyed as sockets closed
self._connections = {}
+
+ # _default_application is a string
+ # holds the name of the policyRuleset to use when the
+ # open.hostname is not found in the rulesetdb
+ self._default_application = ""
+
+ # _default_application_enabled is a boolean
+ # controls default application fallback logic
+ self._default_application_enabled = False
+
#
# Service interfaces
#
@@ -549,11 +559,27 @@ class PolicyLocal(object):
"""
return self.rulesetdb.keys()
+ def set_default_application(self, name, enabled):
+ """
+ Set the default application name and control its enablement.
+ Raise PolicyError if the named application is enabled but absent.
+ @param name: the name of the default application
+ @param enabled: default application ruleset logic is active
+ @return: none
+ """
+ self._default_application = name
+ self._default_application_enabled = enabled
+ if enabled:
+ if not name in self.policy_db_get_names():
+ raise PolicyError("Policy fallback defaultApplication '%s' does not exist" % name)
+ self._manager.log_info("Policy fallback defaultApplication is enabled: '%s'" % name)
+ else:
+ self._manager.log_info("Policy fallback defaultApplication is disabled")
#
# Runtime query interface
#
- def lookup_user(self, user, host, app, conn_name, conn_id):
+ def lookup_user(self, user, host, app_in, conn_name, conn_id):
"""
Lookup function called from C.
Determine if a user on host accessing app through AMQP Open is allowed
@@ -562,19 +588,24 @@ class PolicyLocal(object):
returns true then it has registered and counted the connection.
@param[in] user connection authId
@param[in] host connection remote host numeric IP address as string
- @param[in] app application user is accessing
+ @param[in] app_in application user is accessing
@param[in] conn_name connection name used for tracking reports
@param[in] conn_id internal connection id
@return settings user-group name if allowed; "" if not allowed
"""
try:
- if not app in self.rulesetdb:
- self._manager.log_info(
- "DENY AMQP Open for user '%s', host '%s', application '%s': "
- "No policy defined for application" % (user, host, app))
- return ""
+ app = app_in
+ if not app_in in self.rulesetdb:
+ if self._default_application_enabled:
+ app = self._default_application
+ else:
+ self._manager.log_info(
+ "DENY AMQP Open for user '%s', host '%s', application '%s': "
+ "No policy defined for application" % (user, host, app))
+ return ""
ruleset = self.rulesetdb[app]
+
if not app in self.statsdb:
msg = (
"DENY AMQP Open for user '%s', host '%s', application '%s': "
@@ -641,7 +672,7 @@ class PolicyLocal(object):
# return failure
return ""
- def lookup_settings(self, appname, name, upolicy):
+ def lookup_settings(self, appname_in, name, upolicy):
"""
Given a settings name, return the aggregated policy blob.
@param[in] appname: application user is accessing
@@ -652,6 +683,10 @@ class PolicyLocal(object):
# Note: the upolicy output is a non-nested dict with settings of interest
"""
try:
+ appname = appname_in
+ if not appname in self.rulesetdb and self._default_application_enabled:
+ appname = self._default_application
+
if not appname in self.rulesetdb:
self._manager.log_info(
"lookup_settings fail for application '%s', user group '%s': "
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/590d79ef/python/qpid_dispatch_internal/policy/policy_manager.py
----------------------------------------------------------------------
diff --git a/python/qpid_dispatch_internal/policy/policy_manager.py b/python/qpid_dispatch_internal/policy/policy_manager.py
index a2823c8..7cb72fb 100644
--- a/python/qpid_dispatch_internal/policy/policy_manager.py
+++ b/python/qpid_dispatch_internal/policy/policy_manager.py
@@ -78,6 +78,18 @@ class PolicyManager(object):
self._policy_local.create_ruleset(attributes)
#
+ # Management interface to set the default application
+ #
+ def set_default_application(self, name, enabled):
+ """
+ Set default application
+ @param name:
+ @param enabled
+ @return:
+ """
+ self._policy_local.set_default_application(name, enabled)
+
+ #
# Runtime query interface
#
def lookup_user(self, user, host, app, conn_name, conn_id):
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/590d79ef/tests/router_policy_test.py
----------------------------------------------------------------------
diff --git a/tests/router_policy_test.py b/tests/router_policy_test.py
index 9b37567..c2359f2 100644
--- a/tests/router_policy_test.py
+++ b/tests/router_policy_test.py
@@ -190,6 +190,50 @@ class PolicyFile(TestCase):
PolicyFile.policy.lookup_settings('photoserver', 'unknown', upolicy)
)
+class PolicyFileApplicationFallback(TestCase):
+ manager = MockPolicyManager()
+ policy = PolicyLocal(manager)
+ policy.test_load_config()
+
+ def test_bad_app_fallback(self):
+ # Show that with no fallback the user cannot connect
+ self.assertTrue(
+ self.policy.lookup_user('zeke', '192.168.100.5', 'galleria', "connid", 5) == '')
+
+ # Enable the fallback defaultApplication and show the same user can now connect
+ self.policy.set_default_application('photoserver', True)
+ settingsname = self.policy.lookup_user('zeke', '192.168.100.5', 'galleria', "connid", 5)
+ self.assertTrue(settingsname == 'test')
+
+ # Show that the fallback settings are returned
+ upolicy = {}
+ self.assertTrue(
+ self.policy.lookup_settings('phony*app*name', settingsname, upolicy)
+ )
+ self.assertTrue(upolicy['maxFrameSize'] == 444444)
+ self.assertTrue(upolicy['maxMessageSize'] == 444444)
+ self.assertTrue(upolicy['maxSessionWindow'] == 444444)
+ self.assertTrue(upolicy['maxSessions'] == 4)
+ self.assertTrue(upolicy['maxSenders'] == 44)
+ self.assertTrue(upolicy['maxReceivers'] == 44)
+ self.assertTrue(upolicy['allowAnonymousSender'])
+ self.assertTrue(upolicy['allowDynamicSrc'])
+ self.assertTrue(upolicy['targets'] == 'private')
+ self.assertTrue(upolicy['sources'] == 'private')
+
+ # Disable fallback and show failure again
+ self.policy.set_default_application('', False)
+ self.assertTrue(
+ self.policy.lookup_user('zeke', '192.168.100.5', 'galleria', "connid", 5) == '')
+
+ # Configuration will not allow default application to point to bogus app ruleset
+ was_allowed = True
+ try:
+ self.policy.set_default_application('foobar', True)
+ except:
+ was_allowed = False
+ self.assertTrue(was_allowed == False)
+
class PolicyAppConnectionMgrTests(TestCase):
def test_policy_app_conn_mgr_fail_by_total(self):
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org