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