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/02/15 18:31:25 UTC

qpid-dispatch git commit: Add config processing to pull in a folder of .json policyRuleset definitions using only a normal .conf-format file. Rename the policy items related to ingress hosts. Improve descriptions in qdrouterd.conf. Add a CMake configured

Repository: qpid-dispatch
Updated Branches:
  refs/heads/crolke-DISPATCH-188-1 5ca5f43d8 -> 63033a65e


Add config processing to pull in a folder of .json policyRuleset definitions
using only a normal .conf-format file.
Rename the policy items related to ingress hosts.
Improve descriptions in qdrouterd.conf.
Add a CMake configured demonstration of policyFolder processing.


Project: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/repo
Commit: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/commit/63033a65
Tree: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/tree/63033a65
Diff: http://git-wip-us.apache.org/repos/asf/qpid-dispatch/diff/63033a65

Branch: refs/heads/crolke-DISPATCH-188-1
Commit: 63033a65e66ea6c13bbf4a1ed6256eb0bdb285ec
Parents: 5ca5f43
Author: Chuck Rolke <cr...@redhat.com>
Authored: Mon Feb 15 11:32:02 2016 -0500
Committer: Chuck Rolke <cr...@redhat.com>
Committed: Mon Feb 15 11:32:02 2016 -0500

----------------------------------------------------------------------
 python/qpid_dispatch/management/qdrouter.json   |  25 +++--
 .../qpid_dispatch_internal/management/config.py |  14 ++-
 .../policy/policy_local.py                      |  40 +++----
 src/policy.c                                    |  12 +--
 tests/CMakeLists.txt                            |   4 +
 tests/policy-1/management-access.json           |  26 +++++
 tests/policy-1/policy-boardwalk.json            |  77 ++++++++++++++
 tests/policy-1/policy-photoserver.json          | 104 -------------------
 tests/policy-1/policy-safari.json               |  78 ++++++++++++++
 .../test-policy-conf-includes-folder.conf.in    |  64 ++++++++++++
 tests/policy-2/test-router-with-policy.json.in  |   5 +-
 11 files changed, 306 insertions(+), 143 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/63033a65/python/qpid_dispatch/management/qdrouter.json
----------------------------------------------------------------------
diff --git a/python/qpid_dispatch/management/qdrouter.json b/python/qpid_dispatch/management/qdrouter.json
index 6162f3d..4b09550 100644
--- a/python/qpid_dispatch/management/qdrouter.json
+++ b/python/qpid_dispatch/management/qdrouter.json
@@ -1015,7 +1015,14 @@
                 "enableAccessRules": {
                     "type": "boolean",
                     "default": false,
-                    "description": "Enable user rule set connection denial.",
+                    "description": "Enable user rule set processing and connection denial.",
+                    "required": false,
+                    "create": true
+                },
+                "policyFolder": {
+                    "type": "path",
+                    "default": "",
+                    "description": "The path to a folder that holds policyRuleset definition .json files. For a small system the rulesets may all be defined in this file. At a larger scale it is better to have the policy files in their own folder and to have none of the rulesets defined here. All rulesets in all .json files in this folder are processed.",
                     "required": false,
                     "create": true
                 },
@@ -1028,7 +1035,7 @@
         "policyRuleset": {
             "description": "Per application definition of the locations from which users may connect and the groups to which users belong.",
             "extends": "configurationEntity",
-	    "operations": ["CREATE"],
+            "operations": ["CREATE"],
             "attributes": {
                 "applicationName": {
                     "type": "string",
@@ -1058,32 +1065,32 @@
                 },
                 "userGroups": {
                     "type": "map",
-                    "description": "A map where each key is a user group name and the corresponding value is a list of users in that group. Users who are assigned to one or more groups are deemed 'restricted'. Restricted users are subject to connection ingress policy and are assigned policy settings based on the assigned user groups. Unrestricted users may be allowed or denied. If unrestricted users are allowed to connect then they are assigned to user group default.",
+                    "description": "A map where each key is a user group name and the corresponding value is a CSV string naming the users in that group. Users who are assigned to one or more groups are deemed 'restricted'. Restricted users are subject to connection ingress policy and are assigned policy settings based on the assigned user groups. Unrestricted users may be allowed or denied. If unrestricted users are allowed to connect then they are assigned to user group default.",
                     "required": false,
                     "create": true
                 },
-                "connectionGroups": {
+                "ingressHostGroups": {
                     "type": "map",
-                    "description": "A map where each key is a connection group name and the corresponding value is a list of IP addresses in that group. IP addresses may be numeric IPv4 or IPv6 host address or comma separated host ranges.  The wildcard host address '*' represents any host address.",
+                    "description": "A map where each key is an ingress host group name and the corresponding value is a CSV string naming the IP addresses or address ranges in that group. IP addresses may be FQDN strings or numeric IPv4 or IPv6 host addresses. A host range is two host addresses of the same address family separated with a hyphen.  The wildcard host address '*' represents any host address.",
                     "required": false,
                     "create": true
                 },
-                "connectionIngressPolicies": {
+                "ingressPolicies": {
                     "type": "map",
-                    "description": "A map where each key is a user group name and the corresponding value is a list of connection groups. Users who are members of the user group are allowed to connect only from a host in one of the named connection policy groups.",
+                    "description": "A map where each key is a user group name and the corresponding value is a CSV string naming the ingress host group names that restrict the ingress host for the user group. Users who are members of the user group are allowed to connect only from a host in one of the named ingress host groups.",
                     "required": false,
                     "create": true
                 },
                 "connectionAllowDefault": {
                     "type": "boolean",
-                    "description": "Unrestricted users, those who are not members of a defined user group, are allowed to connect to this application.",
+                    "description": "Unrestricted users, those who are not members of a defined user group, are allowed to connect to this application. Unrestricted users are assigned to the 'default' user group and receive 'default' settings.",
                     "default": false,
                     "required": false,
                     "create": true
                 },
                 "settings": {
                     "type": "map",
-                    "description": "A map where each key is a connection group name and the corresponding settings for that group.",
+                    "description": "A map where each key is a user group name and the value is a map of the corresponding settings for that group.",
                     "required": false,
                     "create": true
                 }

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/63033a65/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 8e5ef2b..ed5ecdd 100644
--- a/python/qpid_dispatch_internal/management/config.py
+++ b/python/qpid_dispatch_internal/management/config.py
@@ -22,6 +22,7 @@ Configuration file parsing
 """
 
 import json, re, sys
+import os
 from copy import copy
 from qpid_dispatch.management.entity import camelcase
 from ..dispatch import QdDll
@@ -160,8 +161,9 @@ def configure_dispatch(dispatch, lib_handle, filename):
     qd.qd_dispatch_prepare(dispatch)
     agent.activate("$management")
     qd.qd_router_setup_late(dispatch) # Actions requiring active management agent.
+    policyFolder = config.by_type('policy')[0]['policyFolder']
 
-    # Remaining configuration
+    # Remaining configuration from qdrouterd.conf
 
     for t in "fixedAddress", "listener", "connector", "waypoint", "linkRoutePattern", \
              "policy", "policyRuleset":
@@ -169,4 +171,12 @@ def configure_dispatch(dispatch, lib_handle, filename):
     for e in config.entities:
         configure(e)
 
-
+    # Load the policyRulesets from the .json files in policyFolder
+    # Only policyRulesets are loaded. Other entities are silently discarded.
+    if not policyFolder == '':
+        apath = os.path.abspath(policyFolder)
+        for i in os.listdir(policyFolder):
+            if i.endswith(".json"):
+                pconfig = Config(os.path.join(apath, i))
+                for a in pconfig.by_type("policyRuleset"):
+                    agent.configure(a)

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/63033a65/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 82854a8..a87e399 100644
--- a/python/qpid_dispatch_internal/policy/policy_local.py
+++ b/python/qpid_dispatch_internal/policy/policy_local.py
@@ -45,8 +45,8 @@ class PolicyKeys(object):
     KW_MAXCONNPERHOST              = "maxConnPerHost"
     KW_MAXCONNPERUSER              = "maxConnPerUser"
     KW_USER_GROUPS                 = "userGroups"
-    KW_CONNECTION_GROUPS           = "connectionGroups"
-    KW_CONNECTION_INGRESS_POLICIES = "connectionIngressPolicies"
+    KW_INGRESS_HOST_GROUPS         = "ingressHostGroups"
+    KW_INGRESS_POLICIES            = "ingressPolicies"
     KW_CONNECTION_ALLOW_DEFAULT    = "connectionAllowDefault"
     KW_SETTINGS                    = "settings"
 
@@ -103,8 +103,8 @@ class PolicyCompiler(object):
         PolicyKeys.KW_MAXCONNPERHOST,
         PolicyKeys.KW_MAXCONNPERUSER,
         PolicyKeys.KW_USER_GROUPS,
-        PolicyKeys.KW_CONNECTION_GROUPS,
-        PolicyKeys.KW_CONNECTION_INGRESS_POLICIES,
+        PolicyKeys.KW_INGRESS_HOST_GROUPS,
+        PolicyKeys.KW_INGRESS_POLICIES,
         PolicyKeys.KW_CONNECTION_ALLOW_DEFAULT,
         PolicyKeys.KW_SETTINGS
         ]
@@ -155,7 +155,7 @@ class PolicyCompiler(object):
 
     def compile_connection_groups(self, name, submap_in, submap_out, warnings, errors):
         """
-        Handle an connectionGroups submap.
+        Handle an ingressHostGroups submap.
         Each origin value is verified. On a successful run the submap
         is replaced parsed lists of HostAddr objects.
         @param[in] name application name
@@ -168,7 +168,7 @@ class PolicyCompiler(object):
                   warnings[] may contain info and errors[0] will hold the
                   description of why the origin was rejected.
         """
-        key = PolicyKeys.KW_CONNECTION_GROUPS
+        key = PolicyKeys.KW_INGRESS_HOST_GROUPS
         for coname in submap_in:
             try:
                 ostr = str(submap_in[coname])
@@ -263,8 +263,8 @@ class PolicyCompiler(object):
         policy_out[PolicyKeys.KW_MAXCONNPERHOST] = 0
         policy_out[PolicyKeys.KW_MAXCONNPERUSER] = 0
         policy_out[PolicyKeys.KW_USER_GROUPS] = {}
-        policy_out[PolicyKeys.KW_CONNECTION_GROUPS] = {}
-        policy_out[PolicyKeys.KW_CONNECTION_INGRESS_POLICIES] = {}
+        policy_out[PolicyKeys.KW_INGRESS_HOST_GROUPS] = {}
+        policy_out[PolicyKeys.KW_INGRESS_POLICIES] = {}
         policy_out[PolicyKeys.KW_CONNECTION_ALLOW_DEFAULT] = False
         policy_out[PolicyKeys.KW_SETTINGS] = {}
 
@@ -284,15 +284,15 @@ class PolicyCompiler(object):
                     return False
                 policy_out[key] = val
             elif key in [PolicyKeys.KW_USER_GROUPS,
-                         PolicyKeys.KW_CONNECTION_GROUPS,
-                         PolicyKeys.KW_CONNECTION_INGRESS_POLICIES
+                         PolicyKeys.KW_INGRESS_HOST_GROUPS,
+                         PolicyKeys.KW_INGRESS_POLICIES
                          ]:
                 try:
                     if not type(val) is dict:
                         errors.append("Application '%s' option '%s' must be of type 'dict' but is '%s'" %
                                       (name, key, type(val)))
                         return False
-                    if key == PolicyKeys.KW_CONNECTION_GROUPS:
+                    if key == PolicyKeys.KW_INGRESS_HOST_GROUPS:
                         # Conection groups are lists of IP addresses that need to be
                         # converted into binary structures for comparisons.
                         val_out = {}
@@ -301,7 +301,7 @@ class PolicyCompiler(object):
                         policy_out[key] = {}
                         policy_out[key].update(val_out)
                     else:
-                        # deduplicate connectionIngressPolicy and userGroups lists
+                        # deduplicate ingressPolicy and userGroups lists
                         for k,v in val.iteritems():
                             v = [x.strip(' ') for x in v.split(PolicyKeys.KC_CONFIG_LIST_SEP)]
                             v = list(set(v))
@@ -354,11 +354,11 @@ class PolicyCompiler(object):
                               (name))
                 return False
 
-        # Each ingress policy name references must exist in connection_groups
-        for cipname, cip in policy_out[PolicyKeys.KW_CONNECTION_INGRESS_POLICIES].iteritems():
+        # Each ingress policy name references must exist in ingressHostGroups
+        for cipname, cip in policy_out[PolicyKeys.KW_INGRESS_POLICIES].iteritems():
             for co in cip:
-                if not co in policy_out[PolicyKeys.KW_CONNECTION_GROUPS]:
-                    errors.append("Application '%s' connection ingress policy '%s' references connection group '%s' but that group does not exist"
+                if not co in policy_out[PolicyKeys.KW_INGRESS_HOST_GROUPS]:
+                    errors.append("Application '%s' connection ingress policy '%s' references ingress host group '%s' but that group does not exist"
                                   (name, cipname, co))
                     return False
 
@@ -559,14 +559,14 @@ class PolicyLocal(object):
                     stats.count_other_denial()
                     return ""
             # User in usergroup allowed to connect from host?
-            if usergroup in ruleset[PolicyKeys.KW_CONNECTION_INGRESS_POLICIES]:
+            if usergroup in ruleset[PolicyKeys.KW_INGRESS_POLICIES]:
                 # User's usergroup is restricted to connecting from a host
                 # defined by the group's ingress policy
                 allowed = False
                 uhs = HostStruct(host)
-                cglist = ruleset[PolicyKeys.KW_CONNECTION_INGRESS_POLICIES][usergroup]
+                cglist = ruleset[PolicyKeys.KW_INGRESS_POLICIES][usergroup]
                 for cg in cglist:
-                    for cohost in ruleset[PolicyKeys.KW_CONNECTION_GROUPS][cg]:
+                    for cohost in ruleset[PolicyKeys.KW_INGRESS_HOST_GROUPS][cg]:
                         if cohost.match_bin(uhs):
                             allowed = True
                             break
@@ -650,7 +650,7 @@ class PolicyLocal(object):
 
 
     def test_load_config(self):
-        ruleset_str = '["policyAccessRuleset", {"applicationName": "photoserver","maxConnections": 50,"maxConnPerUser": 5,"maxConnPerHost": 20,"userGroups": {"anonymous":       "anonymous","users":           "u1, u2","paidsubscribers": "p1, p2","test":            "zeke, ynot","admin":           "alice, bob","superuser":       "ellen"},"connectionGroups": {"Ten18":     "10.18.0.0-10.18.255.255","EllensWS":  "72.135.2.9","TheLabs":   "10.48.0.0-10.48.255.255, 192.168.100.0-192.168.100.255","localhost": "127.0.0.1, ::1","TheWorld":  "*"},"connectionIngressPolicies": {"anonymous":       "TheWorld","users":           "TheWorld","paidsubscribers": "TheWorld","test":            "TheLabs","admin":           "Ten18, TheLabs, localhost","superuser":       "EllensWS, localhost"},"connectionAllowDefault": true,'
+        ruleset_str = '["policyAccessRuleset", {"applicationName": "photoserver","maxConnections": 50,"maxConnPerUser": 5,"maxConnPerHost": 20,"userGroups": {"anonymous":       "anonymous","users":           "u1, u2","paidsubscribers": "p1, p2","test":            "zeke, ynot","admin":           "alice, bob","superuser":       "ellen"},"ingressHostGroups": {"Ten18":     "10.18.0.0-10.18.255.255","EllensWS":  "72.135.2.9","TheLabs":   "10.48.0.0-10.48.255.255, 192.168.100.0-192.168.100.255","localhost": "127.0.0.1, ::1","TheWorld":  "*"},"ingressPolicies": {"anonymous":       "TheWorld","users":           "TheWorld","paidsubscribers": "TheWorld","test":            "TheLabs","admin":           "Ten18, TheLabs, localhost","superuser":       "EllensWS, localhost"},"connectionAllowDefault": true,'
         ruleset_str += '"settings": {'
         ruleset_str += '"anonymous":      {"maxFrameSize": 111111,"maxMessageSize":   111111,"maxSessionWindow": 111111,"maxSessions":           1,"maxSenders":           11,"maxReceivers":         11,"allowDynamicSrc":      false,"allowAnonymousSender": false,"sources": "public",                           "targets": ""},'
         ruleset_str += '"users":          {"maxFrameSize": 222222,"maxMessageSize":   222222,"maxSessionWindow": 222222,"maxSessions":           2,"maxSenders":           22,"maxReceivers":         22,"allowDynamicSrc":      false,"allowAnonymousSender": false,"sources": "public, private",                  "targets": "public"},'

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/63033a65/src/policy.c
----------------------------------------------------------------------
diff --git a/src/policy.c b/src/policy.c
index 7e06199..bddcef9 100644
--- a/src/policy.c
+++ b/src/policy.c
@@ -76,7 +76,7 @@ struct qd_policy_t {
     void                 *py_policy_manager;
                           // configured settings
     int                   max_connection_limit;
-    char                 *policyDb;
+    char                 *policyFolder;
     bool                  enableAccessRules;
                           // live statistics
     int                   connections_processed;
@@ -94,7 +94,7 @@ qd_policy_t *qd_policy(qd_dispatch_t *qd)
     policy->qd                   = qd;
     policy->log_source           = qd_log_source("POLICY");
     policy->max_connection_limit = 0;
-    policy->policyDb             = 0;
+    policy->policyFolder         = 0;
     policy->enableAccessRules    = false;
     policy->connections_processed= 0;
     policy->connections_denied   = 0;
@@ -110,8 +110,8 @@ qd_policy_t *qd_policy(qd_dispatch_t *qd)
  **/
 void qd_policy_free(qd_policy_t *policy)
 {
-    if (policy->policyDb)
-        free(policy->policyDb);
+    if (policy->policyFolder)
+        free(policy->policyFolder);
     free(policy);
 }
 
@@ -124,8 +124,8 @@ qd_error_t qd_entity_configure_policy(qd_policy_t *policy, qd_entity_t *entity)
     policy->max_connection_limit = qd_entity_opt_long(entity, "maximumConnections", 0); CHECK();
     if (policy->max_connection_limit < 0)
         return qd_error(QD_ERROR_CONFIG, "maximumConnections must be >= 0");
-    policy->policyDb =
-        qd_entity_opt_string(entity, "policyDb", 0); CHECK();
+    policy->policyFolder =
+        qd_entity_opt_string(entity, "policyFolder", 0); CHECK();
     policy->enableAccessRules = qd_entity_opt_bool(entity, "enableAccessRules", false); CHECK();
     qd_log(policy->log_source, QD_LOG_INFO, "Configured maximumConnections: %d", policy->max_connection_limit);
     return QD_ERROR_NONE;

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/63033a65/tests/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt
index 82041b1..e752c2a 100644
--- a/tests/CMakeLists.txt
+++ b/tests/CMakeLists.txt
@@ -125,6 +125,10 @@ configure_file(${CMAKE_CURRENT_SOURCE_DIR}/sasl_configs/tests-mech-PLAIN.conf.in
 file(COPY      ${CMAKE_CURRENT_SOURCE_DIR}/policy-2/policy-photoserver-sasl.sasldb  DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/policy-2)
 configure_file(${CMAKE_CURRENT_SOURCE_DIR}/policy-2/policy-photoserver-sasl.conf.in ${CMAKE_CURRENT_BINARY_DIR}/policy-2/policy-photoserver-sasl.conf)
 configure_file(${CMAKE_CURRENT_SOURCE_DIR}/policy-2/test-router-with-policy.json.in ${CMAKE_CURRENT_BINARY_DIR}/policy-2/test-router-with-policy.json)
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/policy-1/test-policy-conf-includes-folder.conf.in ${CMAKE_CURRENT_BINARY_DIR}/policy-1/test-policy-conf-includes-folder.conf)
+file(COPY      ${CMAKE_CURRENT_SOURCE_DIR}/policy-1/management-access.json  DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/policy-1/)
+file(COPY      ${CMAKE_CURRENT_SOURCE_DIR}/policy-1/policy-boardwalk.json   DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/policy-1/)
+file(COPY      ${CMAKE_CURRENT_SOURCE_DIR}/policy-1/policy-safari.json      DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/policy-1/)
 
 # following install() functions will be called only if you do a make "install"
 install(FILES ${SYSTEM_TEST_FILES}

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/63033a65/tests/policy-1/management-access.json
----------------------------------------------------------------------
diff --git a/tests/policy-1/management-access.json b/tests/policy-1/management-access.json
new file mode 100644
index 0000000..5b4370f
--- /dev/null
+++ b/tests/policy-1/management-access.json
@@ -0,0 +1,26 @@
+# A policy to allow unrestricted access to management
+# through port 22000
+[
+  ["policyRuleset", {
+      "applicationName": "0.0.0.0:22000",
+      "maxConnections": 50,
+      "maxConnPerUser": 5,
+      "maxConnPerHost": 20,
+      "connectionAllowDefault": true,
+      "settings": {
+        "default" : {
+          "maxFrameSize":     222222,
+          "maxMessageSize":   222222,
+          "maxSessionWindow": 222222,
+          "maxSessions":           2,
+          "maxSenders":           22,
+          "maxReceivers":         22,
+          "allowDynamicSrc":      true,
+          "allowAnonymousSender": true,
+          "sources": "$management",
+          "targets": "$management"
+        }
+      }
+    }
+  ]
+]

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/63033a65/tests/policy-1/policy-boardwalk.json
----------------------------------------------------------------------
diff --git a/tests/policy-1/policy-boardwalk.json b/tests/policy-1/policy-boardwalk.json
new file mode 100644
index 0000000..dc3b91e
--- /dev/null
+++ b/tests/policy-1/policy-boardwalk.json
@@ -0,0 +1,77 @@
+[
+    # The boardwalk policy ruleset
+    ["policyRuleset",
+        {
+            "applicationName": "boardwalk",
+            "maxConnections": 10,
+            "maxConnPerUser": 2,
+            "maxConnPerHost": 5,
+            "userGroups": {
+                "anonymous": "anonymous",
+                "users": "u1 u2 u3",
+                "superuser": "ellen"
+            },
+            "ingressHostGroups": {
+                "Ten18": "10.18.0.0-10.18.255.255",
+                "EllensWS": "72.135.2.9",
+                "TheLabs": "10.48.0.0-10.48.255.255, 192.168.0.0-192.168.255.255",
+                "Localhost": "127.0.0.1, ::1"
+            },
+            "ingressPolicies": {
+                "anonymous": "Ten18, TheLabs",
+                "superuser": "Localhost, EllensWS"
+            },
+            "connectionAllowDefault": true,
+            "settings": {
+                "anonymous": {
+                    "maxFrameSize": 111111,
+                    "maxMessageSize": 111111,
+                    "maxSessionWindow": 111111,
+                    "maxSessions": 1,
+                    "maxSenders": 11,
+                    "maxReceivers": 11,
+                    "allowDynamicSrc": false,
+                    "allowAnonymousSender": false,
+                    "sources": "public",
+                    "targets": ""
+                },
+                "users": {
+                    "maxFrameSize": 222222,
+                    "maxMessageSize": 222222,
+                    "maxSessionWindow": 222222,
+                    "maxSessions": 2,
+                    "maxSenders": 22,
+                    "maxReceivers": 22,
+                    "allowDynamicSrc": false,
+                    "allowAnonymousSender": false,
+                    "sources": "public, private",
+                    "targets": "public"
+                },
+                "superuser": {
+                    "maxFrameSize": 666666,
+                    "maxMessageSize": 666666,
+                    "maxSessionWindow": 666666,
+                    "maxSessions": 6,
+                    "maxSenders": 66,
+                    "maxReceivers": 66,
+                    "allowDynamicSrc": false,
+                    "allowAnonymousSender": false,
+                    "sources": "public, private, management, root",
+                    "targets": "public, private, management, root"
+                },
+                "default": {
+                    "maxFrameSize": 222222,
+                    "maxMessageSize": 222222,
+                    "maxSessionWindow": 222222,
+                    "maxSessions": 2,
+                    "maxSenders": 22,
+                    "maxReceivers": 22,
+                    "allowDynamicSrc": false,
+                    "allowAnonymousSender": false,
+                    "sources": "public, private",
+                    "targets": "public"
+                }
+            }
+        }
+    ]
+]

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/63033a65/tests/policy-1/policy-photoserver.json
----------------------------------------------------------------------
diff --git a/tests/policy-1/policy-photoserver.json b/tests/policy-1/policy-photoserver.json
deleted file mode 100644
index 6e13689..0000000
--- a/tests/policy-1/policy-photoserver.json
+++ /dev/null
@@ -1,104 +0,0 @@
-{
-    "photoserver": {
-        "maxConnections": 10,
-        "maxConnPerUser": 5,
-        "maxConnPerHost": 5,
-        "groups": {
-            "anonymous":       ["anonymous"],
-            "users":           ["u1", "u2"],
-            "paidsubscribers": ["p1", "p2"],
-            "test":            ["zeke", "ynot"],
-            "admin":           ["alice", "bob", "ellen"],
-            "superuser":       ["ellen"]
-            },
-        "connectionOrigins": {
-            "Ten18":      ["10.18.0.0,10.18.255.255"],
-            "EllensWS":   ["72.135.2.9"],
-            "TheLabs":    ["10.48.0.0,10.48.255.255",
-                           "192.168.100.0,192.168.100.255"],
-            "Localhost":  ["127.0.0.1",
-                           "::1"],
-            "TheWorld":   ["*"]
-            },
-        "connectionPolicy": {
-            "admin":       ["Ten18", "TheLabs", "Localhost"],
-            "test":        ["TheLabs"],
-            "superuser":   ["Localhost", "EllensWS"]
-            },
-        "connectionAllowDefault": true,
-        "policies": {
-            "anonymous" : {
-                "maxFrameSize"         : 111111,
-                "maxMessageSize"       : 111111,
-                "maxSessionWindow"     : 111111,
-                "maxSessions"          : 1,
-                "maxSenders"           : 11,
-                "maxReceivers"         : 11,
-                "allowDynamicSrc"      : false,
-                "allowAnonymousSender" : false,
-                "sources"              : ["public"],
-                "targets"              : []
-                },
-            "users" : {
-                "maxFrameSize"         : 222222,
-                "maxMessageSize"       : 222222,
-                "maxSessionWindow"     : 222222,
-                "maxSessions"          : 2,
-                "maxSenders"           : 22,
-                "maxReceivers"         : 22,
-                "allowDynamicSrc"      : false,
-                "allowAnonymousSender" : false,
-                "sources"              : ["public", "private"],
-                "targets"              : ["public"]
-                },
-            "paidsubscribers" : {
-                "maxFrameSize"         : 333333,
-                "maxMessageSize"       : 333333,
-                "maxSessionWindow"     : 333333,
-                "maxSessions"          : 3,
-                "maxSenders"           : 33,
-                "maxReceivers"         : 33,
-                "allowDynamicSrc"      : true,
-                "allowAnonymousSender" : false,
-                "sources"              : ["public", "private"],
-                "targets"              : ["public", "private"]
-                },
-            "test" : {
-                "maxFrameSize"         : 444444,
-                "maxMessageSize"       : 444444,
-                "maxSessionWindow"     : 444444,
-                "maxSessions"          : 4,
-                "maxSenders"           : 44,
-                "maxReceivers"         : 44,
-                "allowDynamicSrc"      : true,
-                "allowAnonymousSender" : true,
-                "sources"              : ["private"],
-                "targets"              : ["private"]
-                },
-            "admin" : {
-                "maxFrameSize"         : 555555,
-                "maxMessageSize"       : 555555,
-                "maxSessionWindow"     : 555555,
-                "maxSessions"          : 5,
-                "maxSenders"           : 55,
-                "maxReceivers"         : 55,
-                "allowDynamicSrc"      : true,
-                "allowAnonymousSender" : true,
-                "sources"              : ["public", "private", "management"],
-                "targets"              : ["public", "private", "management"]
-                },
-            "superuser" : {
-                "maxFrameSize"         : 666666,
-                "maxMessageSize"       : 666666,
-                "maxSessionWindow"     : 666666,
-                "maxSessions"          : 6,
-                "maxSenders"           : 66,
-                "maxReceivers"         : 66,
-                "allowDynamicSrc"      : false,
-                "allowAnonymousSender" : false,
-                "sources"              : ["public", "private", "management", "root"],
-                "targets"              : ["public", "private", "management", "root"]
-                }
-            }
-    }
-}

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/63033a65/tests/policy-1/policy-safari.json
----------------------------------------------------------------------
diff --git a/tests/policy-1/policy-safari.json b/tests/policy-1/policy-safari.json
new file mode 100644
index 0000000..d55cccd
--- /dev/null
+++ b/tests/policy-1/policy-safari.json
@@ -0,0 +1,78 @@
+[
+    # The safari policy ruleset
+    ["policyRuleset",
+        {
+            "applicationName": "safari",
+            "maxConnections": 10,
+            "maxConnPerUser": 2,
+            "maxConnPerHost": 5,
+            "userGroups": {
+                "anonymous": "anonymous",
+                "clients": "moja mbili",
+                "guides": "kata hapa"
+            },
+            "ingressHostGroups": {
+                "basecamp": "72.135.2.9",
+                "mobile": "10.48.0.0-10.48.255.255, 192.168.0.0-192.168.255.255",
+                "Localhost": "127.0.0.1, ::1",
+		"TheWorld": "*"
+            },
+            "ingressPolicies": {
+                "anonymous": "TheWorld",
+                "clients": "basecamp",
+		"guides": "basecamp, mobile, Localhost"
+            },
+            "connectionAllowDefault": true,
+            "settings": {
+                "anonymous": {
+                    "maxFrameSize": 111111,
+                    "maxMessageSize": 111111,
+                    "maxSessionWindow": 111111,
+                    "maxSessions": 1,
+                    "maxSenders": 11,
+                    "maxReceivers": 11,
+                    "allowDynamicSrc": false,
+                    "allowAnonymousSender": false,
+                    "sources": "public",
+                    "targets": ""
+                },
+                "clients": {
+                    "maxFrameSize": 222222,
+                    "maxMessageSize": 222222,
+                    "maxSessionWindow": 222222,
+                    "maxSessions": 2,
+                    "maxSenders": 22,
+                    "maxReceivers": 22,
+                    "allowDynamicSrc": false,
+                    "allowAnonymousSender": false,
+                    "sources": "public, private",
+                    "targets": "public"
+                },
+                "guides": {
+                    "maxFrameSize": 666666,
+                    "maxMessageSize": 666666,
+                    "maxSessionWindow": 666666,
+                    "maxSessions": 6,
+                    "maxSenders": 66,
+                    "maxReceivers": 66,
+                    "allowDynamicSrc": false,
+                    "allowAnonymousSender": false,
+                    "sources": "public, private, management, root",
+                    "targets": "public, private, management, root"
+                },
+                "default": {
+                    "maxFrameSize": 222222,
+                    "maxMessageSize": 222222,
+                    "maxSessionWindow": 222222,
+                    "maxSessions": 2,
+                    "maxSenders": 22,
+                    "maxReceivers": 22,
+                    "allowDynamicSrc": false,
+                    "allowAnonymousSender": false,
+                    "sources": "public, private",
+                    "targets": "public"
+                }
+            }
+        }
+    ]
+]

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/63033a65/tests/policy-1/test-policy-conf-includes-folder.conf.in
----------------------------------------------------------------------
diff --git a/tests/policy-1/test-policy-conf-includes-folder.conf.in b/tests/policy-1/test-policy-conf-includes-folder.conf.in
new file mode 100644
index 0000000..b6f0413
--- /dev/null
+++ b/tests/policy-1/test-policy-conf-includes-folder.conf.in
@@ -0,0 +1,64 @@
+##
+## Licensed to the Apache Software Foundation (ASF) under one
+## or more contributor license agreements.  See the NOTICE file
+## distributed with this work for additional information
+## regarding copyright ownership.  The ASF licenses this file
+## to you under the Apache License, Version 2.0 (the
+## "License"); you may not use this file except in compliance
+## with the License.  You may obtain a copy of the License at
+##
+##   http://www.apache.org/licenses/LICENSE-2.0
+##
+## Unless required by applicable law or agreed to in writing,
+## software distributed under the License is distributed on an
+## "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+## KIND, either express or implied.  See the License for the
+## specific language governing permissions and limitations
+## under the License
+##
+
+
+##
+## Container section - Configures the general operation of the AMQP container.
+##
+container {
+    ##
+    ## workerThreads - The number of threads that will be created to
+    ## process message traffic and other application work (timers, nonAmqp
+    ## file descriptors, etc.)
+    ##
+    ## The number of threads should be related to the number of available
+    ## processor cores.  To fully utilize a quad-core system, set the
+    ## number of threads to 4.
+    ##
+    workerThreads: 4
+
+    ##
+    ## containerName - The name of the AMQP container.  If not specified,
+    ## the container name will be set to a value of the container's
+    ## choosing.  The automatically assigned container name is not
+    ## guaranteed to be persistent across restarts of the container.
+    ##
+    containerName: Qpid.Dispatch.Router.A
+}
+
+router {
+    mode: standalone
+    routerId: QDR
+}
+
+
+##
+## Listeners and Connectors
+##
+listener {
+    addr: 0.0.0.0
+    port: 22000
+    saslMechanisms: ANONYMOUS
+}
+
+policy {
+    maximumConnections: 10
+    enableAccessRules: true
+    policyFolder: ${CMAKE_CURRENT_BINARY_DIR}/policy-1
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/qpid-dispatch/blob/63033a65/tests/policy-2/test-router-with-policy.json.in
----------------------------------------------------------------------
diff --git a/tests/policy-2/test-router-with-policy.json.in b/tests/policy-2/test-router-with-policy.json.in
index f5d9098..e28d75c 100644
--- a/tests/policy-2/test-router-with-policy.json.in
+++ b/tests/policy-2/test-router-with-policy.json.in
@@ -28,6 +28,7 @@
 	"maximumConnections": 20,
 	"enableAccessRules": "true"
     }],
+# Some ruleset
     ["policyRuleset", {
       "applicationName": "photoserver",
       "maxConnections": 50,
@@ -41,14 +42,14 @@
         "admin":           "alice, bob",
         "superuser":       "ellen"
       },
-      "connectionGroups": {
+      "ingressHostGroups": {
         "Ten18":     "10.18.0.0-10.18.255.255",
         "EllensWS":  "72.135.2.9",
         "TheLabs":   "10.48.0.0-10.48.255.255, 192.168.100.0-192.168.100.255",
         "localhost": "127.0.0.1, ::1",
         "TheWorld":  "*"
       },
-      "connectionIngressPolicies": {
+      "ingressPolicies": {
         "anonymous":       "TheWorld",
         "users":           "TheWorld",
         "paidsubscribers": "TheWorld",


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@qpid.apache.org
For additional commands, e-mail: commits-help@qpid.apache.org