This is an automated email from the ASF dual-hosted git repository.

kgiusti pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/qpid-dispatch.git


The following commit(s) were added to refs/heads/main by this push:
     new 1f384f7  DISPATCH-2310: limit router identifiers to 127 characters 
maximum
1f384f7 is described below

commit 1f384f7a038a27987016e4ddbaa23d919bc87a37
Author: Kenneth Giusti <[email protected]>
AuthorDate: Wed Jan 19 18:02:25 2022 -0500

    DISPATCH-2310: limit router identifiers to 127 characters maximum
---
 include/qpid/dispatch/router.h                     |  2 +
 .../qpid_dispatch_internal/management/qdrouter.py  | 43 ++++++++++++---------
 tests/system_tests_bad_configuration.py            | 44 ++++++++++++++++++++++
 tests/system_tests_routing_protocol.py             | 12 +++---
 4 files changed, 79 insertions(+), 22 deletions(-)

diff --git a/include/qpid/dispatch/router.h b/include/qpid/dispatch/router.h
index 2feaa75..a69cf40 100644
--- a/include/qpid/dispatch/router.h
+++ b/include/qpid/dispatch/router.h
@@ -33,6 +33,8 @@
 
 #include <stdbool.h>
 
+#define QD_ROUTER_ID_MAX 127  // max length of router id in chars
+
 typedef struct qdr_core_t   qdr_core_t;
 typedef struct qd_router_t  qd_router_t;
 typedef struct qd_address_t qd_address_t;
diff --git a/python/qpid_dispatch_internal/management/qdrouter.py 
b/python/qpid_dispatch_internal/management/qdrouter.py
index 2d406ee..e677f7e 100644
--- a/python/qpid_dispatch_internal/management/qdrouter.py
+++ b/python/qpid_dispatch_internal/management/qdrouter.py
@@ -34,6 +34,7 @@ class QdSchema(schema.Schema):
 
     CONFIGURATION_ENTITY = "configurationEntity"
     OPERATIONAL_ENTITY = "operationalEntity"
+    ROUTER_ID_MAX_LEN = 127
 
     def __init__(self):
         """Load schema."""
@@ -53,35 +54,43 @@ class QdSchema(schema.Schema):
         entities = list(entities)  # Iterate twice
         super(QdSchema, self).validate_add(attributes, entities)
         entities.append(attributes)
-        router_mode = listener_connector_role = listener_role = None
+        router_mode = router_id = listener_connector_role = listener_role = 
None
         for e in entities:
             short_type = self.short_name(e['type'])
             if short_type == "router":
                 router_mode = e['mode']
+                if 'id' in e:
+                    router_id = e['id']
             if short_type in ["listener", "connector"]:
                 if short_type == "listener":
                     listener_role = e['role']
                 list_conn_entity = e
                 listener_connector_role = e['role']
 
-            # There are 4 roles for listeners - normal, inter-router, 
route-container, edge
-            if router_mode and listener_connector_role:
-                # Standalone routers cannot have inter-router or edge 
listeners/connectors
-                if router_mode == "standalone" and listener_connector_role in 
('inter-router', 'edge'):
-                    raise schema.ValidationError(
-                        "role='standalone' not allowed to connect to or accept 
connections from other routers.")
+        if router_id is not None:
+            if len(router_id) > self.ROUTER_ID_MAX_LEN:
+                raise schema.ValidationError(
+                    'Router ID "%s" exceeds the maximum allowed length (%d'
+                    ' characters)' % (router_id, self.ROUTER_ID_MAX_LEN))
 
-                # Only interior routers can have inter-router 
listeners/connectors
-                if router_mode != "interior" and listener_connector_role == 
"inter-router":
-                    raise schema.ValidationError(
-                        "role='inter-router' only allowed with router 
mode='interior' for %s" % list_conn_entity)
+        # There are 4 roles for listeners - normal, inter-router, 
route-container, edge
+        if router_mode and listener_connector_role:
+            # Standalone routers cannot have inter-router or edge 
listeners/connectors
+            if router_mode == "standalone" and listener_connector_role in 
('inter-router', 'edge'):
+                raise schema.ValidationError(
+                    "role='standalone' not allowed to connect to or accept 
connections from other routers.")
 
-            if router_mode and listener_role:
-                # Edge routers cannot have edge listeners. Other edge routers 
cannot make connections into this
-                # edge router
-                if router_mode == "edge" and listener_role == "edge":
-                    raise schema.ValidationError(
-                        "role='edge' only allowed with router mode='interior' 
for %s" % list_conn_entity)
+            # Only interior routers can have inter-router listeners/connectors
+            if router_mode != "interior" and listener_connector_role == 
"inter-router":
+                raise schema.ValidationError(
+                    "role='inter-router' only allowed with router 
mode='interior' for %s" % list_conn_entity)
+
+        if router_mode and listener_role:
+            # Edge routers cannot have edge listeners. Other edge routers 
cannot make connections into this
+            # edge router
+            if router_mode == "edge" and listener_role == "edge":
+                raise schema.ValidationError(
+                    "role='edge' only allowed with router mode='interior' for 
%s" % list_conn_entity)
 
     def is_configuration(self, entity_type):
         return entity_type and self.configuration_entity in 
entity_type.all_bases
diff --git a/tests/system_tests_bad_configuration.py 
b/tests/system_tests_bad_configuration.py
index b80fc20..4d52bb8 100644
--- a/tests/system_tests_bad_configuration.py
+++ b/tests/system_tests_bad_configuration.py
@@ -244,3 +244,47 @@ class RouterTestIdFailWhiteSpace(TestCase):
         if "AttributeError" not in out:
             print("output: ", out)
             assert False, "AttributeError not in process output"
+
+
+class RouterTestIdFailTooLong(TestCase):
+    """
+    This test case sets up a router using a configuration router id
+    that is illegal (too long). The router should not start.
+    """
+    @classmethod
+    def setUpClass(cls):
+        super(RouterTestIdFailTooLong, cls).setUpClass()
+        cls.name = "test-router-id-too-long"
+
+    def __init__(self, test_method):
+        TestCase.__init__(self, test_method)
+
+    @classmethod
+    def tearDownClass(cls):
+        super(RouterTestIdFailTooLong, cls).tearDownClass()
+
+    def test_verify_reject_too_long_id(self):
+        """
+        Writes illegal config, runs router, examines console output
+        """
+        bad_name = 'X' * 128  # max valid name < 128 characters
+        parent_path = os.path.dirname(os.getcwd())
+        conf_path = os.path.join(parent_path, 
"setUpClass/test-router-long-id.conf")
+        with open(conf_path, 'w') as router_conf:
+            router_conf.write("router { \n")
+            router_conf.write("    id: %s \n" % bad_name)
+            router_conf.write("}")
+        lib_include_path = os.path.join(os.environ["QPID_DISPATCH_HOME"], 
"python")
+        p = self.popen(
+            ['qdrouterd', '-c', conf_path, '-I', lib_include_path],
+            stdin=PIPE, stdout=PIPE, stderr=STDOUT, expect=Process.EXIT_FAIL,
+            universal_newlines=True)
+        out = p.communicate(timeout=TIMEOUT)[0]
+        try:
+            p.teardown()
+        except Exception as e:
+            raise Exception("%s\n%s" % (e, out))
+
+        if p.returncode == 0 or "exceeds the maximum allowed length" not in 
out:
+            print("output:\n [%s]\n" % out, flush=True)
+            assert False, "Router accepted an ID of illegal length"
diff --git a/tests/system_tests_routing_protocol.py 
b/tests/system_tests_routing_protocol.py
index 552baa7..cbb2e40 100644
--- a/tests/system_tests_routing_protocol.py
+++ b/tests/system_tests_routing_protocol.py
@@ -211,6 +211,8 @@ class HugeRouterIdTest(TestCase):
 
     Deploy a mesh of four routers with ids > 64 octets in length.
     """
+    MAX_ID_LEN = 127
+
     @classmethod
     def setUpClass(cls):
         super(HugeRouterIdTest, cls).setUpClass()
@@ -235,27 +237,27 @@ class HugeRouterIdTest(TestCase):
         ir_port_C = cls.tester.get_port()
         ir_port_D = cls.tester.get_port()
 
-        name_suffix = "." + "X" * 128
+        name_suffix = "X" * (cls.MAX_ID_LEN - 2)
 
-        cls.RA_name = 'A' + name_suffix
+        cls.RA_name = 'A.' + name_suffix
         cls.RA = router(cls.RA_name,
                         [('listener', {'role': 'inter-router', 'port': 
ir_port_A}),
                          ('connector', {'role': 'inter-router', 'port': 
ir_port_B}),
                          ('connector', {'role': 'inter-router', 'port': 
ir_port_C}),
                          ('connector', {'role': 'inter-router', 'port': 
ir_port_D})])
 
-        cls.RB_name = 'B' + name_suffix
+        cls.RB_name = 'B.' + name_suffix
         cls.RB = router(cls.RB_name,
                         [('listener', {'role': 'inter-router', 'port': 
ir_port_B}),
                          ('connector', {'role': 'inter-router', 'port': 
ir_port_C}),
                          ('connector', {'role': 'inter-router', 'port': 
ir_port_D})])
 
-        cls.RC_name = 'C' + name_suffix
+        cls.RC_name = 'C.' + name_suffix
         cls.RC = router(cls.RC_name,
                         [('listener', {'role': 'inter-router', 'port': 
ir_port_C}),
                          ('connector', {'role': 'inter-router', 'port': 
ir_port_D})])
 
-        cls.RD_name = 'D' + name_suffix
+        cls.RD_name = 'D.' + name_suffix
         cls.RD = router(cls.RD_name,
                         [('listener', {'role': 'inter-router', 'port': 
ir_port_D})])
 

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to