ACL Enhancement to support queue limit policies
-----------------------------------------------
Key: QPID-2108
URL: https://issues.apache.org/jira/browse/QPID-2108
Project: Qpid
Issue Type: Improvement
Components: C++ Broker
Affects Versions: 0.5
Reporter: Tim Platten
It is a requirement for us to be able to enforce queue limit policies using the
ACL authorisation mechanism. I therefore propose the following enhancement:
Add three new properties to the "create queue" rule: limitpolicy, maxqueuesize
and maxqueuecount. The policy test can be implemented using existing code, but
the numeric limits require a less-than-or-equal test. I.e. if a value for
maxqueuesize is specified in the ACL file, an exception will be thrown if a
value greater than this is specified in declareQueue. A value less than or
equal would be acceptable. If maxqueuecount and/or maxqueuesize were omitted
from the rule or specified as zero, the corresponding check would interpret the
value as "unlimited".
Proposed code changes follow (prefixed with change-bar "|").
AclModule.h
.
.
.
enum Property {PROP_NAME, PROP_DURABLE, PROP_OWNER, PROP_ROUTINGKEY,
PROP_PASSIVE, PROP_AUTODELETE, PROP_EXCLUSIVE, PROP_TYPE,
PROP_ALTERNATE, PROP_QUEUENAME, PROP_SCHEMAPACKAGE,
| PROP_SCHEMACLASS, PROP_LIMITPOLICY, PROP_MAXQUEUESIZE,
PROP_MAXQUEUECOUNT};
.
.
.
static inline Property getProperty(const std::string& str) {
if (str.compare("name") == 0) return PROP_NAME;
if (str.compare("durable") == 0) return PROP_DURABLE;
if (str.compare("owner") == 0) return PROP_OWNER;
if (str.compare("routingkey") == 0) return PROP_ROUTINGKEY;
if (str.compare("passive") == 0) return PROP_PASSIVE;
if (str.compare("autodelete") == 0) return PROP_AUTODELETE;
if (str.compare("exclusive") == 0) return PROP_EXCLUSIVE;
if (str.compare("type") == 0) return PROP_TYPE;
if (str.compare("alternate") == 0) return PROP_ALTERNATE;
if (str.compare("queuename") == 0) return PROP_QUEUENAME;
if (str.compare("schemapackage") == 0) return PROP_SCHEMAPACKAGE;
if (str.compare("schemaclass") == 0) return PROP_SCHEMACLASS;
| if (str.compare("limitpolicy") == 0) return PROP_LIMITPOLICY;
| if (str.compare("maxqueuesize") == 0) return PROP_MAXQUEUESIZE;
| if (str.compare("maxqueuecount") == 0) return PROP_MAXQUEUECOUNT;
throw str;
}
static inline std::string getPropertyStr(const Property p) {
switch (p) {
case PROP_NAME: return "name";
case PROP_DURABLE: return "durable";
case PROP_OWNER: return "owner";
case PROP_ROUTINGKEY: return "routingkey";
case PROP_PASSIVE: return "passive";
case PROP_AUTODELETE: return "autodelete";
case PROP_EXCLUSIVE: return "exclusive";
case PROP_TYPE: return "type";
case PROP_ALTERNATE: return "alternate";
case PROP_QUEUENAME: return "queuename";
case PROP_SCHEMAPACKAGE: return "schemapackage";
case PROP_SCHEMACLASS: return "schemaclass";
| case PROP_LIMITPOLICY: return "limitpolicy";
| case PROP_MAXQUEUESIZE: return "maxqueuesize";
| case PROP_MAXQUEUECOUNT: return "maxqueuecount";
default: assert(false); // should never get here
}
return "";
}
.
.
.
// == Queues ==
propSetPtr p4(new propSet);
| p4->insert(PROP_ALTERNATE);
| p4->insert(PROP_PASSIVE);
| p4->insert(PROP_DURABLE);
| p4->insert(PROP_EXCLUSIVE);
| p4->insert(PROP_AUTODELETE);
| p4->insert(PROP_LIMITPOLICY);
| p4->insert(PROP_MAXQUEUESIZE);
| p4->insert(PROP_MAXQUEUECOUNT);
Note that currently (Qpid 0.5) this code appears to be incorrectly
dereferencing p3 instead of p4.
SessionAdapter.cpp
.
.
.
void SessionAdapter::QueueHandlerImpl::declare(const string& name, const
string& alternateExchange,
bool passive, bool durable, bool
exclusive,
bool autoDelete, const
qpid::framing::FieldTable& arguments)
{
AclModule* acl = getBroker().getAcl();
if (acl) {
std::map<acl::Property, std::string> params;
params.insert(make_pair(acl::PROP_ALTERNATE, alternateExchange));
params.insert(make_pair(acl::PROP_PASSIVE, std::string(passive ? "true"
: "false") ));
params.insert(make_pair(acl::PROP_DURABLE, std::string(durable ? "true"
: "false")));
params.insert(make_pair(acl::PROP_EXCLUSIVE, std::string(exclusive ?
"true" : "false")));
params.insert(make_pair(acl::PROP_AUTODELETE, std::string(autoDelete ?
"true" : "false")));
| params.insert(make_pair(acl::PROP_LIMITPOLICY,
arguments.getAsString("qpid.policy_type")));
| params.insert(make_pair(acl::PROP_MAXQUEUECOUNT,
boost::lexical_cast<string>(arguments.getAsInt("qpid.max_count"))));
| params.insert(make_pair(acl::PROP_MAXQUEUESIZE,
boost::lexical_cast<string>(arguments.getAsInt64("qpid.max_size"))));
if
(!acl->authorise(getConnection().getUserId(),acl::ACT_CREATE,acl::OBJ_QUEUE,name,¶ms)
)
throw NotAllowedException(QPID_MSG("ACL denied queue create request
from " << getConnection().getUserId()));
}
AclData.cpp
.
.
.
|#include <boost/lexical_cast.hpp>
.
.
.
AclResult AclData::lookup(const std::string& id, const Action& action, const
ObjectType& objType, const std::string& name, std::map<Property, std::string>*
params)
{
AclResult aclresult = decisionMode;
if (actionList[action] && actionList[action][objType]){
AclData::actObjItr itrRule =
actionList[action][objType]->find(id);
if (itrRule == actionList[action][objType]->end())
itrRule = actionList[action][objType]->find("*");
if (itrRule != actionList[action][objType]->end() ) {
//loop the vector
for (ruleSetItr i=itrRule->second.begin();
i<itrRule->second.end(); i++) {
// loop the names looking for match
bool match =true;
for (propertyMapItr pMItr =
i->props.begin(); (pMItr != i->props.end()) && match; pMItr++)
{
//match name is exists first
if (pMItr->first ==
acl::PROP_NAME){
if
(!matchProp(pMItr->second, name)){
match= false;
}
}else if (params){ //match
pMItr against params
propertyMapItr paramItr
= params->find (pMItr->first);
if (paramItr ==
params->end()){
match = false;
| }else if ( pMItr->first
== acl::PROP_MAXQUEUECOUNT || pMItr->first == acl::PROP_MAXQUEUESIZE ) {
| if ( pMItr->first
== paramItr->first ) {
| uint64_t aclMax
= boost::lexical_cast<uint64_t>(pMItr->second);
| uint64_t
paramMax = boost::lexical_cast<uint64_t>(paramItr->second);
| if (( aclMax )
&& ( paramMax == 0 || paramMax > aclMax ))
| match =
false;
| }
}else if
(!matchProp(pMItr->second, paramItr->second)){
match = false;
}
}
}
if (match) return
getACLResult(i->logOnly, i->log);
}
}
}
return aclresult;
}
--
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.
---------------------------------------------------------------------
Apache Qpid - AMQP Messaging Implementation
Project: http://qpid.apache.org
Use/Interact: mailto:[email protected]