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 2015/12/10 18:21:35 UTC
qpid-dispatch git commit: Add policy lookup function to return
settings for (user, host,
app) access. Add self tests to exercise the lookup using the example policy
file.
Repository: qpid-dispatch
Updated Branches:
refs/heads/crolke-DISPATCH-188-1 2766ff113 -> 8f7deddf4
Add policy lookup function to return settings for (user, host, app) access.
Add self tests to exercise the lookup using the example policy file.
Project: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/commit/8f7deddf
Tree: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/tree/8f7deddf
Diff: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/diff/8f7deddf
Branch: refs/heads/crolke-DISPATCH-188-1
Commit: 8f7deddf406c63cefb47310abec88c4ae6e207d9
Parents: 2766ff1
Author: Chuck Rolke <cr...@redhat.com>
Authored: Thu Dec 10 12:17:25 2015 -0500
Committer: Chuck Rolke <cr...@redhat.com>
Committed: Thu Dec 10 12:17:25 2015 -0500
----------------------------------------------------------------------
.../qpid_dispatch_internal/management/policy.py | 175 ++++++++++++++++++-
tests/system_tests_policy.py | 58 ++++++
2 files changed, 232 insertions(+), 1 deletion(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/8f7deddf/python/qpid_dispatch_internal/management/policy.py
----------------------------------------------------------------------
diff --git a/python/qpid_dispatch_internal/management/policy.py b/python/qpid_dispatch_internal/management/policy.py
index 74a3b0d..6cadb1d 100644
--- a/python/qpid_dispatch_internal/management/policy.py
+++ b/python/qpid_dispatch_internal/management/policy.py
@@ -647,7 +647,168 @@ class Policy():
#
# Runtime query interface
#
-
+ def policy_aggregate_limits(self, upolicy, policy, settingname):
+ """
+ Force a max count value into user policy
+ param[in,out] upolicy user policy receiving aggregations
+ param[in] policy Internal policy holding settings to be aggregated
+ param[in] settingname setting of interest
+ """
+ if settingname in policy:
+ upolicy[settingname] = policy[settingname]
+
+ def policy_aggregate_policy_int(self, upolicy, policy, roles, settingname):
+ """
+ Pull int out of policy.policies[role] and install into upolicy if > existing
+ param[in,out] upolicy user policy receiving aggregations
+ param[in] policy Internal policy holding settings to be aggregated
+ param[in] settingname setting of interest
+ """
+ if not 'policies' in policy:
+ return
+ policies = policy['policies']
+ for role in roles:
+ if role in policies:
+ rpol = policies[role]
+ if settingname in rpol:
+ sp = rpol[settingname]
+ if settingname in upolicy:
+ up = upolicy[settingname]
+ if sp > up:
+ # policy bumps up user setting
+ upolicy[settingname] = sp
+ else:
+ # user policy is already better
+ pass
+ else:
+ # user policy doesn't have setting so force it
+ upolicy[settingname] = sp
+ else:
+ # no setting of this name in the role's policy
+ pass
+ else:
+ # no policy for this role
+ pass
+
+ def policy_aggregate_policy_bool(self, upolicy, policy, roles, settingname):
+ """
+ Pull bool out of policy and install into upolicy if true
+ param[in,out] upolicy user policy receiving aggregations
+ param[in] policy Internal policy holding settings to be aggregated
+ param[in] settingname setting of interest
+ """
+ if not 'policies' in policy:
+ return
+ policies = policy['policies']
+ for role in roles:
+ if role in policies:
+ rpol = policies[role]
+ if settingname in rpol:
+ if rpol[settingname]:
+ upolicy[settingname] = True
+ else:
+ # no setting of this name in the role's policy
+ pass
+ else:
+ # no policy for this role
+ pass
+
+ def policy_aggregate_policy_list(self, upolicy, policy, roles, settingname):
+ """
+ Pull list out of policy and append into upolicy
+ param[in,out] upolicy user policy receiving aggregations
+ param[in] policy Internal policy holding settings to be aggregated
+ param[in] settingname setting of interest
+ """
+ if not 'policies' in policy:
+ return
+ policies = policy['policies']
+ for role in roles:
+ if role in policies:
+ rpol = policies[role]
+ if settingname in rpol:
+ sp = rpol[settingname]
+ if settingname in upolicy:
+ upolicy[settingname].extend( sp )
+ else:
+ # user policy doesn't have setting so force it
+ upolicy[settingname] = sp
+ else:
+ # no setting of this name in the role's policy
+ pass
+ else:
+ # no policy for this role
+ pass
+
+ def policy_lookup(self, user, host, app, upolicy):
+ """
+ Determine if a user on host accessing app is allowed.
+ @param[in] user connection authId
+ @param[in] host connection remote host numeric IP address
+ @param[in] app application user is accessing
+ @param[out] upolicy dict holding connection and policy values
+ @return if allowed by policy
+ # TODO: use lookaside list for precomputed (user, host, app) policy
+ # Note: the upolicy output is a non-nested dict with settings of interest
+ # TODO: figure out decent defaults for upolicy settings that are undefined
+ """
+ try:
+ settings = self.data[app]
+ # User allowed to connect from host?
+ allowed = False
+ restricted = False
+ uhs = HostStruct(host)
+ uroles = []
+ if 'roles' in settings:
+ for r in settings['roles']:
+ if user in settings['roles'][r]:
+ restricted = True
+ uroles.append(r)
+ #print "XXX user %s has roles %s " % (user, uroles)
+ uorigins = []
+ if 'connectionPolicy' in settings:
+ for ur in uroles:
+ if ur in settings['connectionPolicy']:
+ uorigins.extend(settings['connectionPolicy'][ur])
+ #print "XXX user %s has origins %s" % (user, uorigins)
+ if 'connectionOrigins' in settings:
+ for co in settings['connectionOrigins']:
+ if co in uorigins:
+ for cohost in settings['connectionOrigins'][co]:
+ if cohost.match_bin(uhs):
+ #print "XXX user %s passes origin test at %s" % (user, uhs.dump())
+ allowed = True
+ break
+ if allowed:
+ break
+ if not allowed and not restricted:
+ if 'connectionAllowUnrestricted' in settings:
+ allowed = settings['connectionAllowUnrestricted']
+ if not allowed:
+ return False
+ # Return connection limits and aggregation of role settings
+ uroles.append(user) # user roles also includes username directly
+ self.policy_aggregate_limits (upolicy, settings, "policyVersion")
+ self.policy_aggregate_limits (upolicy, settings, "maximumConnections")
+ self.policy_aggregate_limits (upolicy, settings, "maximumConnectionsPerUser")
+ self.policy_aggregate_limits (upolicy, settings, "maximumConnectionsPerHost")
+ self.policy_aggregate_policy_int (upolicy, settings, uroles, "max_frame_size")
+ self.policy_aggregate_policy_int (upolicy, settings, uroles, "max_message_size")
+ self.policy_aggregate_policy_int (upolicy, settings, uroles, "max_session_window")
+ self.policy_aggregate_policy_int (upolicy, settings, uroles, "max_sessions")
+ self.policy_aggregate_policy_int (upolicy, settings, uroles, "max_senders")
+ self.policy_aggregate_policy_int (upolicy, settings, uroles, "max_receivers")
+ self.policy_aggregate_policy_bool(upolicy, settings, uroles, "allow_dynamic_src")
+ self.policy_aggregate_policy_bool(upolicy, settings, uroles, "allow_anonymous_sender")
+ self.policy_aggregate_policy_list(upolicy, settings, uroles, "sources")
+ self.policy_aggregate_policy_list(upolicy, settings, uroles, "targets")
+ return True
+ except Exception, e:
+ #print str(e)
+ #pdb.set_trace()
+ return False
+
+
#
# HACK ALERT: Temporary
# Functions related to main
@@ -679,6 +840,18 @@ def main_except(argv):
p = ("%s" % policy.policy_read(pname))
print(p.replace('\\n', '\n'))
+ # Lookups
+ upolicy = {}
+ res = policy.policy_lookup('zeke', '192.168.100.5', 'photoserver', upolicy)
+ print "Lookup zeke from 192.168.100.5. Expect true and max_frame_size 44444. Result is %s" % res
+ print "Resulting policy is: %s" % upolicy
+
+ upolicy = {}
+ res = policy.policy_lookup('ellen', '72.135.2.9', 'photoserver', upolicy)
+ print "Lookup ellen from 72.135.2.9. Expect true and max_frame_size 666666. Result is %s" % res
+ print "Resulting policy is: %s" % upolicy
+
+
def main(argv):
try:
main_except(argv)
http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/8f7deddf/tests/system_tests_policy.py
----------------------------------------------------------------------
diff --git a/tests/system_tests_policy.py b/tests/system_tests_policy.py
index 1661d22..e61e380 100644
--- a/tests/system_tests_policy.py
+++ b/tests/system_tests_policy.py
@@ -158,5 +158,63 @@ class PolicyHostAddrTest(TestCase):
self.expect_deny( "::1,::2,::3", "arg count")
self.expect_deny( "0:ff:0,0:fe:ffff:ffff::0", "a > b")
+class PolicyFile(TestCase):
+
+ policy = Policy("../../../tests/policy-1")
+
+ def dict_compare(self, d1, d2):
+ d1_keys = set(d1.keys())
+ d2_keys = set(d2.keys())
+ intersect_keys = d1_keys.intersection(d2_keys)
+ added = d1_keys - d2_keys
+ removed = d2_keys - d1_keys
+ modified = {o : (d1[o], d2[o]) for o in intersect_keys if d1[o] != d2[o]}
+ same = set(o for o in intersect_keys if d1[o] == d2[o])
+ return len(added) == 0 and len(removed) == 0 and len(modified) == 0
+
+ def test_policy1_test_zeke_ok(self):
+ upolicy = {}
+ self.assertTrue(
+ PolicyFile.policy.policy_lookup('zeke', '192.168.100.5', 'photoserver', upolicy) )
+ self.assertTrue(upolicy['policyVersion'] == '1')
+ self.assertTrue(upolicy['maximumConnections'] == '10')
+ self.assertTrue(upolicy['maximumConnectionsPerUser'] == '5')
+ self.assertTrue(upolicy['maximumConnectionsPerHost'] == '5')
+ self.assertTrue(upolicy['max_frame_size'] == 444444)
+ self.assertTrue(upolicy['max_message_size'] == 444444)
+ self.assertTrue(upolicy['max_session_window'] == 444444)
+ self.assertTrue(upolicy['max_sessions'] == 4)
+ self.assertTrue(upolicy['max_senders'] == 44)
+ self.assertTrue(upolicy['max_receivers'] == 44)
+ self.assertTrue(upolicy['allow_anonymous_sender'])
+ self.assertTrue(upolicy['allow_dynamic_src'])
+ self.assertTrue(len(upolicy['targets']) == 1)
+ self.assertTrue('private' in upolicy['targets'])
+ self.assertTrue(len(upolicy['sources']) == 1)
+ self.assertTrue('private' in upolicy['sources'])
+
+ def test_policy1_test_zeke_bad_IP(self):
+ upolicy = {}
+ self.assertFalse(
+ PolicyFile.policy.policy_lookup('zeke', '10.18.0.1', 'photoserver', upolicy) )
+ self.assertFalse(
+ PolicyFile.policy.policy_lookup('zeke', '72.135.2.9', 'photoserver', upolicy) )
+ self.assertFalse(
+ PolicyFile.policy.policy_lookup('zeke', '127.0.0.1', 'photoserver', upolicy) )
+
+ def test_policy1_test_zeke_bad_app(self):
+ upolicy = {}
+ self.assertFalse(
+ PolicyFile.policy.policy_lookup('zeke', '192.168.100.5','galleria', upolicy) )
+
+ def test_policy1_test_users_same_permissions(self):
+ zpolicy = {}
+ self.assertTrue(
+ PolicyFile.policy.policy_lookup('zeke', '192.168.100.5', 'photoserver', zpolicy) )
+ ypolicy = {}
+ self.assertTrue(
+ PolicyFile.policy.policy_lookup('ynot', '10.48.255.254', 'photoserver', ypolicy) )
+ self.assertTrue( self.dict_compare(zpolicy, ypolicy) )
+
if __name__ == '__main__':
unittest.main(main_module())
---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org