summaryrefslogtreecommitdiff
path: root/cpp
diff options
context:
space:
mode:
Diffstat (limited to 'cpp')
-rw-r--r--cpp/src/qpid/broker/Broker.cpp6
-rw-r--r--cpp/src/qpid/broker/Broker.h2
-rw-r--r--cpp/src/qpid/management/ManagementAgent.cpp14
-rwxr-xr-xcpp/src/tests/acl.py155
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})