diff options
author | Alan Conway <aconway@apache.org> | 2011-09-07 17:28:04 +0000 |
---|---|---|
committer | Alan Conway <aconway@apache.org> | 2011-09-07 17:28:04 +0000 |
commit | 47c16ba2e19ad4bb149258312f86b4bcd7b04d24 (patch) | |
tree | bc3bbee7e5438ed2ea4a583e759801956edc1893 /cpp | |
parent | 12ff1511fa1483c7a3c683e2502e854a02144202 (diff) | |
download | qpid-python-47c16ba2e19ad4bb149258312f86b4bcd7b04d24.tar.gz |
Bug 730017, QPID-3475: Cluster authentication ignores cluster-* settings.
When a broker joins a cluster, it should be authenticated authenticate
using the options --cluster-username, --cluster-password and
--cluster-mechanism. The broker was ignoring the settings and joining
the cluster even if an invalid user or password are supplied.
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk/qpid@1166279 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp')
-rw-r--r-- | cpp/src/qpid/cluster/Connection.cpp | 4 | ||||
-rw-r--r-- | cpp/src/qpid/cluster/SecureConnectionFactory.cpp | 8 | ||||
-rw-r--r-- | cpp/src/qpid/cluster/UpdateClient.cpp | 1 | ||||
-rwxr-xr-x | cpp/src/tests/cluster_tests.py | 115 |
4 files changed, 123 insertions, 5 deletions
diff --git a/cpp/src/qpid/cluster/Connection.cpp b/cpp/src/qpid/cluster/Connection.cpp index 0feb4c19ff..015301573e 100644 --- a/cpp/src/qpid/cluster/Connection.cpp +++ b/cpp/src/qpid/cluster/Connection.cpp @@ -99,7 +99,9 @@ Connection::Connection(Cluster& c, sys::ConnectionOutputHandler& out, external, isLink, isCatchUp ? ++catchUpId : 0, - isCatchUp), // isCatchUp => shadow + // The first catch-up connection is not considered a shadow + // as it needs to be authenticated. + isCatchUp && self.second > 1), expectProtocolHeader(isLink), mcastFrameHandler(cluster.getMulticast(), self), updateIn(c.getUpdateReceiver()), diff --git a/cpp/src/qpid/cluster/SecureConnectionFactory.cpp b/cpp/src/qpid/cluster/SecureConnectionFactory.cpp index 6ddef66226..2672d8360c 100644 --- a/cpp/src/qpid/cluster/SecureConnectionFactory.cpp +++ b/cpp/src/qpid/cluster/SecureConnectionFactory.cpp @@ -7,9 +7,9 @@ * 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 @@ -48,7 +48,7 @@ SecureConnectionFactory::create(ProtocolVersion v, sys::OutputControl& out, cons if (clusterCodec) { SecureConnectionPtr sc(new SecureConnection()); clusterCodec->setSecureConnection(sc.get()); - sc->setCodec(codec); + sc->setCodec(codec); return sc.release(); } return 0; @@ -63,7 +63,7 @@ SecureConnectionFactory::create(sys::OutputControl& out, const std::string& id, if (clusterCodec) { SecureConnectionPtr sc(new SecureConnection()); clusterCodec->setSecureConnection(sc.get()); - sc->setCodec(codec); + sc->setCodec(codec); return sc.release(); } return 0; diff --git a/cpp/src/qpid/cluster/UpdateClient.cpp b/cpp/src/qpid/cluster/UpdateClient.cpp index 3142b44d71..2be1bf1f77 100644 --- a/cpp/src/qpid/cluster/UpdateClient.cpp +++ b/cpp/src/qpid/cluster/UpdateClient.cpp @@ -151,6 +151,7 @@ void UpdateClient::run() { try { connection.open(updateeUrl, connectionSettings); session = connection.newSession(UPDATE); + session.sync(); update(); done(); } catch (const std::exception& e) { diff --git a/cpp/src/tests/cluster_tests.py b/cpp/src/tests/cluster_tests.py index e4d5bdab04..4e3339650b 100755 --- a/cpp/src/tests/cluster_tests.py +++ b/cpp/src/tests/cluster_tests.py @@ -164,6 +164,121 @@ acl allow all all self.fail("Expected exception") except messaging.exceptions.NotFound: pass + def test_sasl_join(self): + """Verify SASL authentication between brokers when joining a cluster.""" + sasl_config=os.path.join(self.rootdir, "sasl_config") + + # Valid user/password, ensure queue is created. + c = cluster[0].connect(username="zig", password="zig") + c.session().sender("ziggy;{create:always}") + c.close() + c = cluster[1].connect(username="zig", password="zig") + c.session().receiver("ziggy;{assert:always}") + c.close() + for b in cluster: b.ready() # Make sure all brokers still running. + + # Valid user, bad password + try: + cluster[0].connect(username="zig", password="foo").close() + self.fail("Expected exception") + except messaging.exceptions.ConnectionError: pass + for b in cluster: b.ready() # Make sure all brokers still running. + + # Bad user ID + try: + cluster[0].connect(username="foo", password="bar").close() + self.fail("Expected exception") + except messaging.exceptions.ConnectionError: pass + for b in cluster: b.ready() # Make sure all brokers still running. + + # Action disallowed by ACL + c = cluster[0].connect(username="zag", password="zag") + try: + s = c.session() + s.sender("zaggy;{create:always}") + s.close() + self.fail("Expected exception") + except messaging.exceptions.UnauthorizedAccess: pass + # make sure the queue was not created at the other node. + c = cluster[0].connect(username="zag", password="zag") + try: + s = c.session() + s.sender("zaggy;{assert:always}") + s.close() + self.fail("Expected exception") + except messaging.exceptions.NotFound: pass + + def test_sasl_join(self): + """Verify SASL authentication between brokers when joining a cluster.""" + # Valid user/password, ensure queue is created. + c = cluster[0].connect(username="zig", password="zig") + c.session().sender("ziggy;{create:always}") + c.close() + c = cluster[1].connect(username="zig", password="zig") + c.session().receiver("ziggy;{assert:always}") + c.close() + for b in cluster: b.ready() # Make sure all brokers still running. + + # Valid user, bad password + try: + cluster[0].connect(username="zig", password="foo").close() + self.fail("Expected exception") + except messaging.exceptions.ConnectionError: pass + for b in cluster: b.ready() # Make sure all brokers still running. + + # Bad user ID + try: + cluster[0].connect(username="foo", password="bar").close() + self.fail("Expected exception") + except messaging.exceptions.ConnectionError: pass + for b in cluster: b.ready() # Make sure all brokers still running. + + # Action disallowed by ACL + c = cluster[0].connect(username="zag", password="zag") + try: + s = c.session() + s.sender("zaggy;{create:always}") + s.close() + self.fail("Expected exception") + except messaging.exceptions.UnauthorizedAccess: pass + # make sure the queue was not created at the other node. + c = cluster[0].connect(username="zag", password="zag") + try: + s = c.session() + s.sender("zaggy;{assert:always}") + s.close() + self.fail("Expected exception") + except messaging.exceptions.NotFound: pass + + def test_sasl_join(self): + """Verify SASL authentication between brokers when joining a cluster.""" + sasl_config=os.path.join(self.rootdir, "sasl_config") + # Test with a valid username/password + cluster = self.cluster(1, args=["--auth", "yes", + "--sasl-config", sasl_config, + "--load-module", os.getenv("ACL_LIB"), + "--cluster-username=zig", + "--cluster-password=zig", + "--cluster-mechanism=PLAIN" + ]) + cluster.start() + cluster.ready() + c = cluster[1].connect(username="zag", password="zag") + + # Test with an invalid username/password + cluster = self.cluster(1, args=["--auth", "yes", + "--sasl-config", sasl_config, + "--load-module", os.getenv("ACL_LIB"), + "--cluster-username=x", + "--cluster-password=y", + "--cluster-mechanism=PLAIN" + ]) + try: + cluster.start(expect=EXPECT_EXIT_OK) + cluster[1].ready() + self.fail("Expected exception") + except: pass + def test_user_id_update(self): """Ensure that user-id of an open session is updated to new cluster members""" sasl_config=os.path.join(self.rootdir, "sasl_config") |