diff options
Diffstat (limited to 'cpp')
-rw-r--r-- | cpp/src/qpid/broker/Broker.cpp | 6 | ||||
-rw-r--r-- | cpp/src/qpid/broker/Broker.h | 2 | ||||
-rw-r--r-- | cpp/src/qpid/management/ManagementAgent.cpp | 14 | ||||
-rwxr-xr-x | cpp/src/tests/acl.py | 155 |
4 files changed, 146 insertions, 31 deletions
diff --git a/cpp/src/qpid/broker/Broker.cpp b/cpp/src/qpid/broker/Broker.cpp index c5662d763a..695a926f74 100644 --- a/cpp/src/qpid/broker/Broker.cpp +++ b/cpp/src/qpid/broker/Broker.cpp @@ -593,7 +593,7 @@ void Broker::createObject(const std::string& type, const std::string& name, } } else if (type == TYPE_EXCHANGE || type == TYPE_TOPIC) { bool durable(false); - std::string exchangeType; + std::string exchangeType("topic"); std::string alternateExchange; Variant::Map extensions; for (Variant::Map::const_iterator i = properties.begin(); i != properties.end(); ++i) { @@ -787,7 +787,7 @@ std::pair<boost::shared_ptr<Queue>, bool> Broker::createQueue( Exchange::shared_ptr alternate; if (!alternateExchange.empty()) { alternate = exchanges.get(alternateExchange); - if (!alternate) framing::NotFoundException(QPID_MSG("Alternate exchange does not exist: " << alternateExchange)); + if (!alternate) throw framing::NotFoundException(QPID_MSG("Alternate exchange does not exist: " << alternateExchange)); } std::pair<Queue::shared_ptr, bool> result = queues.declare(name, durable, autodelete, owner); @@ -859,7 +859,7 @@ std::pair<Exchange::shared_ptr, bool> Broker::createExchange( Exchange::shared_ptr alternate; if (!alternateExchange.empty()) { alternate = exchanges.get(alternateExchange); - if (!alternate) framing::NotFoundException(QPID_MSG("Alternate exchange does not exist: " << alternateExchange)); + if (!alternate) throw framing::NotFoundException(QPID_MSG("Alternate exchange does not exist: " << alternateExchange)); } std::pair<Exchange::shared_ptr, bool> result; diff --git a/cpp/src/qpid/broker/Broker.h b/cpp/src/qpid/broker/Broker.h index d85927c43c..32c3d7936f 100644 --- a/cpp/src/qpid/broker/Broker.h +++ b/cpp/src/qpid/broker/Broker.h @@ -153,7 +153,7 @@ public: void setLogLevel(const std::string& level); std::string getLogLevel(); void createObject(const std::string& type, const std::string& name, - const qpid::types::Variant::Map& properties, bool lenient, const ConnectionState* context); + const qpid::types::Variant::Map& properties, bool strict, const ConnectionState* context); void deleteObject(const std::string& type, const std::string& name, const qpid::types::Variant::Map& options, const ConnectionState* context); diff --git a/cpp/src/qpid/management/ManagementAgent.cpp b/cpp/src/qpid/management/ManagementAgent.cpp index 8b4defaa73..f88b9c0931 100644 --- a/cpp/src/qpid/management/ManagementAgent.cpp +++ b/cpp/src/qpid/management/ManagementAgent.cpp @@ -75,6 +75,18 @@ namespace { } return n2; } + +struct ScopedManagementContext +{ + ScopedManagementContext(const qpid::broker::ConnectionState* context) + { + setManagementExecutionContext(context); + } + ~ScopedManagementContext() + { + setManagementExecutionContext(0); + } +}; } @@ -2238,7 +2250,7 @@ void ManagementAgent::dispatchAgentCommandLH(Message& msg, bool viaLocal) uint32_t bufferLen = inBuffer.getPosition(); inBuffer.reset(); - setManagementExecutionContext((const qpid::broker::ConnectionState*) msg.getPublisher()); + ScopedManagementContext context((const qpid::broker::ConnectionState*) msg.getPublisher()); const framing::FieldTable *headers = msg.getApplicationHeaders(); if (headers && msg.getAppId() == "qmf2") { diff --git a/cpp/src/tests/acl.py b/cpp/src/tests/acl.py index 2d6a5b489d..bd6031d1fd 100755 --- a/cpp/src/tests/acl.py +++ b/cpp/src/tests/acl.py @@ -26,10 +26,11 @@ from qpid.datatypes import uuid4 from qpid.testlib import TestBase010 from qmf.console import Session from qpid.datatypes import Message +import qpid.messaging class ACLFile: - def __init__(self): - self.f = open('data_dir/policy.acl','w'); + def __init__(self, policy='data_dir/policy.acl'): + self.f = open(policy,'w') def write(self,line): self.f.write(line) @@ -50,14 +51,24 @@ class ACLTests(TestBase010): acl = self.qmf.getObjects(_class="acl")[0] return acl.reloadACLFile() + def get_acl_file(self): + return ACLFile(self.config.defines.get("policy-file", "data_dir/policy.acl")) + def setUp(self): - aclf = ACLFile() + aclf = self.get_acl_file() aclf.write('acl allow all all\n') aclf.close() TestBase010.setUp(self) self.startQmf() self.reload_acl() - + + def tearDown(self): + aclf = self.get_acl_file() + aclf.write('acl allow all all\n') + aclf.close() + self.reload_acl() + TestBase010.tearDown(self) + #===================================== # ACL general tests #===================================== @@ -66,7 +77,7 @@ class ACLTests(TestBase010): """ Test the deny all mode """ - aclf = ACLFile() + aclf = self.get_acl_file() aclf.write('acl allow anonymous all all\n') aclf.write('acl allow bob@QPID create queue\n') aclf.write('acl deny all all') @@ -94,7 +105,7 @@ class ACLTests(TestBase010): """ Test the allow all mode """ - aclf = ACLFile() + aclf = self.get_acl_file() aclf.write('acl deny bob@QPID bind exchange\n') aclf.write('acl allow all all') aclf.close() @@ -126,7 +137,7 @@ class ACLTests(TestBase010): """ Test empty groups """ - aclf = ACLFile() + aclf = self.get_acl_file() aclf.write('acl group\n') aclf.write('acl group admins bob@QPID joe@QPID\n') aclf.write('acl allow all all') @@ -140,7 +151,7 @@ class ACLTests(TestBase010): """ Test illegal acl formats """ - aclf = ACLFile() + aclf = self.get_acl_file() aclf.write('acl group admins bob@QPID joe@QPID\n') aclf.write('acl allow all all') aclf.close() @@ -154,7 +165,7 @@ class ACLTests(TestBase010): Test illegal extension lines """ - aclf = ACLFile() + aclf = self.get_acl_file() aclf.write('group admins bob@QPID \n') aclf.write(' \ \n') aclf.write('joe@QPID \n') @@ -172,7 +183,7 @@ class ACLTests(TestBase010): """ Test proper extention lines """ - aclf = ACLFile() + aclf = self.get_acl_file() aclf.write('group test1 joe@EXAMPLE.com \\ \n') # should be allowed aclf.write(' jack@EXAMPLE.com \\ \n') # should be allowed aclf.write('jill@TEST.COM \\ \n') # should be allowed @@ -189,7 +200,7 @@ class ACLTests(TestBase010): Test a user defined without a realm Ex. group admin rajith """ - aclf = ACLFile() + aclf = self.get_acl_file() aclf.write('group admin bob\n') # shouldn't be allowed aclf.write('acl deny admin bind exchange\n') aclf.write('acl allow all all') @@ -204,7 +215,7 @@ class ACLTests(TestBase010): Test a user defined without a realm Ex. group admin rajith """ - aclf = ACLFile() + aclf = self.get_acl_file() aclf.write('group test1 joe@EXAMPLE.com\n') # should be allowed aclf.write('group test2 jack_123-jill@EXAMPLE.com\n') # should be allowed aclf.write('group test4 host/somemachine.example.com@EXAMPLE.COM\n') # should be allowed @@ -215,7 +226,7 @@ class ACLTests(TestBase010): if (result.text.find("ACL format error",0,len(result.text)) != -1): self.fail(result) - aclf = ACLFile() + aclf = self.get_acl_file() aclf.write('group test1 joe$H@EXAMPLE.com\n') # shouldn't be allowed aclf.write('acl allow all all') aclf.close() @@ -233,7 +244,7 @@ class ACLTests(TestBase010): Test illegal queue policy """ - aclf = ACLFile() + aclf = self.get_acl_file() aclf.write('acl deny bob@QPID create queue name=q2 exclusive=true policytype=ding\n') aclf.write('acl allow all all') aclf.close() @@ -249,7 +260,7 @@ class ACLTests(TestBase010): Test illegal queue policy """ - aclf = ACLFile() + aclf = self.get_acl_file() aclf.write('acl deny bob@QPID create queue name=q2 maxqueuesize=-1\n') aclf.write('acl allow all all') aclf.close() @@ -260,7 +271,7 @@ class ACLTests(TestBase010): if (result.text != expected): self.fail(result) - aclf = ACLFile() + aclf = self.get_acl_file() aclf.write('acl deny bob@QPID create queue name=q2 maxqueuesize=9223372036854775808\n') aclf.write('acl allow all all') aclf.close() @@ -277,7 +288,7 @@ class ACLTests(TestBase010): Test illegal queue policy """ - aclf = ACLFile() + aclf = self.get_acl_file() aclf.write('acl deny bob@QPID create queue name=q2 maxqueuecount=-1\n') aclf.write('acl allow all all') aclf.close() @@ -288,7 +299,7 @@ class ACLTests(TestBase010): if (result.text != expected): self.fail(result) - aclf = ACLFile() + aclf = self.get_acl_file() aclf.write('acl deny bob@QPID create queue name=q2 maxqueuecount=9223372036854775808\n') aclf.write('acl allow all all') aclf.close() @@ -308,7 +319,7 @@ class ACLTests(TestBase010): """ Test cases for queue acl in allow mode """ - aclf = ACLFile() + aclf = self.get_acl_file() aclf.write('acl deny bob@QPID create queue name=q1 durable=true passive=true\n') aclf.write('acl deny bob@QPID create queue name=q2 exclusive=true policytype=ring\n') aclf.write('acl deny bob@QPID access queue name=q3\n') @@ -411,7 +422,7 @@ class ACLTests(TestBase010): """ Test cases for queue acl in deny mode """ - aclf = ACLFile() + aclf = self.get_acl_file() aclf.write('acl allow bob@QPID create queue name=q1 durable=true passive=true\n') aclf.write('acl allow bob@QPID create queue name=q2 exclusive=true policytype=ring\n') aclf.write('acl allow bob@QPID access queue name=q3\n') @@ -534,7 +545,7 @@ class ACLTests(TestBase010): """ Test cases for exchange acl in allow mode """ - aclf = ACLFile() + aclf = self.get_acl_file() aclf.write('acl deny bob@QPID create exchange name=testEx durable=true passive=true\n') aclf.write('acl deny bob@QPID create exchange name=ex1 type=direct\n') aclf.write('acl deny bob@QPID access exchange name=myEx queuename=q1 routingkey=rk1.*\n') @@ -665,7 +676,7 @@ class ACLTests(TestBase010): """ Test cases for exchange acl in deny mode """ - aclf = ACLFile() + aclf = self.get_acl_file() aclf.write('acl allow bob@QPID create exchange name=myEx durable=true passive=false\n') aclf.write('acl allow bob@QPID bind exchange name=amq.topic queuename=bar routingkey=foo.*\n') aclf.write('acl allow bob@QPID unbind exchange name=amq.topic queuename=bar routingkey=foo.*\n') @@ -772,6 +783,52 @@ class ACLTests(TestBase010): if (403 == e.args[0].error_code): self.fail("ACL should allow exchange delete request for myEx"); + def test_create_and_delete_exchange_via_qmf(self): + """ + Test acl is enforced when creating/deleting via QMF + methods. Note that in order to be able to send the QMF methods + and receive the responses a significant amount of permissions + need to be enabled (TODO: can the set below be narrowed down + at all?) + """ + aclf = self.get_acl_file() + aclf.write('acl allow bob@QPID create exchange\n') + aclf.write('acl allow admin@QPID delete exchange\n') + aclf.write('acl allow all access exchange\n') + aclf.write('acl allow all bind exchange\n') + aclf.write('acl allow all create queue\n') + aclf.write('acl allow all access queue\n') + aclf.write('acl allow all delete queue\n') + aclf.write('acl allow all consume queue\n') + aclf.write('acl allow all access method\n') + aclf.write('acl deny all all') + aclf.close() + + result = self.reload_acl() + if (result.text.find("format error",0,len(result.text)) != -1): + self.fail(result) + + bob = BrokerAdmin(self.config.broker, "bob", "bob") + bob.create_exchange("my-exchange") #should pass + #cleanup by deleting exchange + try: + bob.delete_exchange("my-exchange") #should fail + self.fail("ACL should deny exchange delete request for my-exchange"); + except Exception, e: + self.assertEqual(7,e.args[0]["error_code"]) + self.assertTrue(e.args[0]["error_text"].find("unauthorized-access") == 0) + admin = BrokerAdmin(self.config.broker, "admin", "admin") + admin.delete_exchange("my-exchange") #should pass + + anonymous = BrokerAdmin(self.config.broker) + try: + anonymous.create_exchange("another-exchange") #should fail + self.fail("ACL should deny exchange create request for another-exchange"); + except Exception, e: + self.assertEqual(7,e.args[0]["error_code"]) + self.assertTrue(e.args[0]["error_text"].find("unauthorized-access") == 0) + + #===================================== # ACL consume tests #===================================== @@ -780,7 +837,7 @@ class ACLTests(TestBase010): """ Test cases for consume in allow mode """ - aclf = ACLFile() + aclf = self.get_acl_file() aclf.write('acl deny bob@QPID consume queue name=q1\n') aclf.write('acl deny bob@QPID consume queue name=q2\n') aclf.write('acl allow all all') @@ -826,7 +883,7 @@ class ACLTests(TestBase010): """ Test cases for consume in allow mode """ - aclf = ACLFile() + aclf = self.get_acl_file() aclf.write('acl allow bob@QPID consume queue name=q1\n') aclf.write('acl allow bob@QPID consume queue name=q2\n') aclf.write('acl allow bob@QPID create queue\n') @@ -872,7 +929,7 @@ class ACLTests(TestBase010): """ Test various publish acl """ - aclf = ACLFile() + aclf = self.get_acl_file() aclf.write('acl deny bob@QPID publish exchange name=amq.direct routingkey=rk1\n') aclf.write('acl deny bob@QPID publish exchange name=amq.topic\n') aclf.write('acl deny bob@QPID publish exchange name=myEx routingkey=rk2\n') @@ -921,7 +978,7 @@ class ACLTests(TestBase010): """ Test various publish acl """ - aclf = ACLFile() + aclf = self.get_acl_file() aclf.write('acl allow bob@QPID publish exchange name=amq.direct routingkey=rk1\n') aclf.write('acl allow bob@QPID publish exchange name=amq.topic\n') aclf.write('acl allow bob@QPID publish exchange name=myEx routingkey=rk2\n') @@ -972,3 +1029,49 @@ class ACLTests(TestBase010): except qpid.session.SessionException, e: if (403 == e.args[0].error_code): self.fail("ACL should allow message transfer to exchange amq.direct with routing key rk1"); + +class BrokerAdmin: + def __init__(self, broker, username=None, password=None): + self.connection = qpid.messaging.Connection(broker) + if username: + self.connection.username = username + self.connection.password = password + self.connection.sasl_mechanisms = "PLAIN" + self.connection.open() + self.session = self.connection.session() + self.sender = self.session.sender("qmf.default.direct/broker") + self.reply_to = "responses-#; {create:always}" + self.receiver = self.session.receiver(self.reply_to) + + def invoke(self, method, arguments): + content = { + "_object_id": {"_object_name": "org.apache.qpid.broker:broker:amqp-broker"}, + "_method_name": method, + "_arguments": arguments + } + request = qpid.messaging.Message(reply_to=self.reply_to, content=content) + request.properties["x-amqp-0-10.app-id"] = "qmf2" + request.properties["qmf.opcode"] = "_method_request" + self.sender.send(request) + response = self.receiver.fetch() + self.session.acknowledge() + if response.properties['x-amqp-0-10.app-id'] == 'qmf2': + if response.properties['qmf.opcode'] == '_method_response': + return response.content['_arguments'] + elif response.properties['qmf.opcode'] == '_exception': + raise Exception(response.content['_values']) + else: raise Exception("Invalid response received, unexpected opcode: %s" % response.properties['qmf.opcode']) + else: raise Exception("Invalid response received, not a qmfv2 method: %s" % response.properties['x-amqp-0-10.app-id']) + def create_exchange(self, name, exchange_type=None, options={}): + properties = options + if exchange_type: properties["exchange_type"] = exchange_type + self.invoke("create", {"type": "exchange", "name":name, "properties":properties}) + + def create_queue(self, name, properties={}): + self.invoke("create", {"type": "queue", "name":name, "properties":properties}) + + def delete_exchange(self, name): + self.invoke("delete", {"type": "exchange", "name":name}) + + def delete_queue(self, name): + self.invoke("delete", {"type": "queue", "name":name}) |