diff options
author | Ted Ross <tross@apache.org> | 2010-11-09 21:15:03 +0000 |
---|---|---|
committer | Ted Ross <tross@apache.org> | 2010-11-09 21:15:03 +0000 |
commit | 4870a01b7976362d3836ba0d56291f01b7f2e6af (patch) | |
tree | 921b002956ec18c7fe5602b0641e9dd8395b7f98 /cpp | |
parent | d282da7e6f515ded59a76b4dfbc2bedab8f7f6d7 (diff) | |
download | qpid-python-4870a01b7976362d3836ba0d56291f01b7f2e6af.tar.gz |
QPID-2934 Feature to pass the authenticated userId to QMF agent method handlers for authorization
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk/qpid@1033232 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'cpp')
-rw-r--r-- | cpp/examples/qmf-agent/example.cpp | 12 | ||||
-rw-r--r-- | cpp/examples/qmf-agent/schema.xml | 3 | ||||
-rw-r--r-- | cpp/include/qpid/management/Manageable.h | 5 | ||||
-rw-r--r-- | cpp/include/qpid/management/ManagementObject.h | 5 | ||||
-rwxr-xr-x | cpp/managementgen/qmfgen/schema.py | 26 | ||||
-rw-r--r-- | cpp/managementgen/qmfgen/templates/Class.h | 6 | ||||
-rw-r--r-- | cpp/src/qpid/agent/ManagementAgentImpl.cpp | 18 | ||||
-rw-r--r-- | cpp/src/qpid/agent/ManagementAgentImpl.h | 9 | ||||
-rw-r--r-- | cpp/src/qpid/management/Manageable.cpp | 5 | ||||
-rw-r--r-- | cpp/src/qpid/management/ManagementAgent.cpp | 8 |
10 files changed, 69 insertions, 28 deletions
diff --git a/cpp/examples/qmf-agent/example.cpp b/cpp/examples/qmf-agent/example.cpp index b432c2a065..f9be4f0164 100644 --- a/cpp/examples/qmf-agent/example.cpp +++ b/cpp/examples/qmf-agent/example.cpp @@ -24,6 +24,7 @@ #include <qpid/agent/ManagementAgent.h> #include <qpid/sys/Mutex.h> #include <qpid/sys/Time.h> +#include <qpid/log/Statement.h> #include "qpid/types/Variant.h" #include "qmf/org/apache/qpid/agent/example/Parent.h" #include "qmf/org/apache/qpid/agent/example/Child.h" @@ -72,7 +73,8 @@ public: { return mgmtObject; } void doLoop(); - status_t ManagementMethod (uint32_t methodId, Args& args, string& text); + bool AuthorizeMethod(uint32_t methodId, Args& args, const string& userId); + status_t ManagementMethod(uint32_t methodId, Args& args, string& text); }; class ChildClass : public Manageable @@ -137,6 +139,14 @@ void CoreClass::doLoop() } } + +bool CoreClass::AuthorizeMethod(uint32_t methodId, Args& args, const string& userId) +{ + QPID_LOG(trace, "AuthorizeMethod for methodId=" << methodId << " userId=" << userId); + return methodId != _qmf::Parent::METHOD_AUTH_FAIL; +} + + Manageable::status_t CoreClass::ManagementMethod(uint32_t methodId, Args& args, string& /*text*/) { Mutex::ScopedLock _lock(vectorLock); diff --git a/cpp/examples/qmf-agent/schema.xml b/cpp/examples/qmf-agent/schema.xml index 84dc8b7643..2a3bb461cc 100644 --- a/cpp/examples/qmf-agent/schema.xml +++ b/cpp/examples/qmf-agent/schema.xml @@ -45,6 +45,9 @@ <arg name="aList" dir="IO" type="list"/> </method> + <method name="auth_fail" desc="Method that fails authorization"> + </method> + </class> diff --git a/cpp/include/qpid/management/Manageable.h b/cpp/include/qpid/management/Manageable.h index 7a72cc1592..1e5cd8bc42 100644 --- a/cpp/include/qpid/management/Manageable.h +++ b/cpp/include/qpid/management/Manageable.h @@ -63,6 +63,11 @@ class QPID_COMMON_EXTERN Manageable // method being called and must be down-cast to the appropriate sub class // before use. virtual status_t ManagementMethod(uint32_t methodId, Args& args, std::string& text); + + // This optional method can be overridden to allow the agent application to + // authorize method invocations. Return true iff the authenticated user identified + // in userId us authorized to execute the method. + virtual bool AuthorizeMethod(uint32_t methodId, Args& args, const std::string& userId); }; inline Manageable::~Manageable(void) {} diff --git a/cpp/include/qpid/management/ManagementObject.h b/cpp/include/qpid/management/ManagementObject.h index 59a7f00603..dec5a63ee9 100644 --- a/cpp/include/qpid/management/ManagementObject.h +++ b/cpp/include/qpid/management/ManagementObject.h @@ -175,7 +175,8 @@ protected: virtual void mapDecodeValues(const types::Variant::Map& map) = 0; virtual void doMethod(std::string& methodName, const types::Variant::Map& inMap, - types::Variant::Map& outMap) = 0; + types::Variant::Map& outMap, + const std::string& userId) = 0; QPID_COMMON_EXTERN void writeTimestamps(types::Variant::Map& map) const; QPID_COMMON_EXTERN void readTimestamps(const types::Variant::Map& buf); @@ -187,7 +188,7 @@ protected: virtual void readProperties(const std::string&) {} virtual void writeProperties(std::string&) const {} virtual void writeStatistics(std::string&, bool = false) {} - virtual void doMethod(std::string&, const std::string&, std::string&) {} + virtual void doMethod(std::string&, const std::string&, std::string&, const std::string&) {} QPID_COMMON_EXTERN virtual void setReference(ObjectId objectId); diff --git a/cpp/managementgen/qmfgen/schema.py b/cpp/managementgen/qmfgen/schema.py index f01d5ee9b2..fdbc7c7be8 100755 --- a/cpp/managementgen/qmfgen/schema.py +++ b/cpp/managementgen/qmfgen/schema.py @@ -1228,12 +1228,12 @@ class SchemaClass: inArgCount = inArgCount + 1 if methodCount == 0: - stream.write ("string&, const string&, string& outStr") + stream.write ("string&, const string&, string& outStr, const string&") else: if inArgCount == 0: - stream.write ("string& methodName, const string&, string& outStr") + stream.write ("string& methodName, const string&, string& outStr, const string& userId") else: - stream.write ("string& methodName, const string& inStr, string& outStr") + stream.write ("string& methodName, const string& inStr, string& outStr, const string& userId") def genDoMapMethodArgs (self, stream, variables): @@ -1248,16 +1248,16 @@ class SchemaClass: if methodCount == 0: stream.write ("string&," + " const ::qpid::types::Variant::Map&," + - " ::qpid::types::Variant::Map& outMap") + " ::qpid::types::Variant::Map& outMap, const string&") else: if inArgCount == 0: stream.write ("string& methodName," + " const ::qpid::types::Variant::Map&," + - " ::qpid::types::Variant::Map& outMap") + " ::qpid::types::Variant::Map& outMap, const string& userId") else: stream.write ("string& methodName," + " const ::qpid::types::Variant::Map& inMap," + - " ::qpid::types::Variant::Map& outMap") + " ::qpid::types::Variant::Map& outMap, const string& userId") def genHiLoStatResets (self, stream, variables): for inst in self.statistics: @@ -1367,8 +1367,13 @@ class SchemaClass: arg.dir.lower () + "_" +\ arg.name, "inBuf") + ";\n") - stream.write (" status = coreObject->ManagementMethod (METHOD_" +\ + stream.write (" bool allow = coreObject->AuthorizeMethod(METHOD_" +\ + method.getName().upper() + ", ioArgs, userId);\n") + stream.write (" if (allow)\n") + stream.write (" status = coreObject->ManagementMethod (METHOD_" +\ method.getName().upper() + ", ioArgs, text);\n") + stream.write (" else\n") + stream.write (" status = Manageable::STATUS_FORBIDDEN;\n") stream.write (" outBuf.putLong (status);\n") stream.write (" outBuf.putMediumString(::qpid::management::Manageable::StatusText (status, text));\n") for arg in method.args: @@ -1402,8 +1407,13 @@ class SchemaClass: arg.name, "inMap") - stream.write (" status = coreObject->ManagementMethod (METHOD_" +\ + stream.write (" bool allow = coreObject->AuthorizeMethod(METHOD_" +\ + method.getName().upper() + ", ioArgs, userId);\n") + stream.write (" if (allow)\n") + stream.write (" status = coreObject->ManagementMethod (METHOD_" +\ method.getName().upper() + ", ioArgs, text);\n") + stream.write (" else\n") + stream.write (" status = Manageable::STATUS_FORBIDDEN;\n") stream.write (" outMap[\"_status_code\"] = (uint32_t) status;\n") stream.write (" outMap[\"_status_text\"] = ::qpid::management::Manageable::StatusText(status, text);\n") for arg in method.args: diff --git a/cpp/managementgen/qmfgen/templates/Class.h b/cpp/managementgen/qmfgen/templates/Class.h index cdb31c4c9e..4bcd423a26 100644 --- a/cpp/managementgen/qmfgen/templates/Class.h +++ b/cpp/managementgen/qmfgen/templates/Class.h @@ -79,7 +79,8 @@ class /*MGEN:Class.NameCap*/ : public ::qpid::management::ManagementObject void mapDecodeValues(const ::qpid::types::Variant::Map& map); void doMethod(std::string& methodName, const ::qpid::types::Variant::Map& inMap, - ::qpid::types::Variant::Map& outMap); + ::qpid::types::Variant::Map& outMap, + const std::string& userId); std::string getKey() const; /*MGEN:IF(Root.GenQMFv1)*/ uint32_t writePropertiesSize() const; @@ -88,7 +89,8 @@ class /*MGEN:Class.NameCap*/ : public ::qpid::management::ManagementObject void writeStatistics(std::string& buf, bool skipHeaders = false); void doMethod(std::string& methodName, const std::string& inBuf, - std::string& outBuf); + std::string& outBuf, + const std::string& userId); /*MGEN:ENDIF*/ writeSchemaCall_t getWriteSchemaCall() { return writeSchema; } diff --git a/cpp/src/qpid/agent/ManagementAgentImpl.cpp b/cpp/src/qpid/agent/ManagementAgentImpl.cpp index b3f1d57a9a..0a1c07a232 100644 --- a/cpp/src/qpid/agent/ManagementAgentImpl.cpp +++ b/cpp/src/qpid/agent/ManagementAgentImpl.cpp @@ -360,7 +360,7 @@ uint32_t ManagementAgentImpl::pollCallbacks(uint32_t callLimit) methodQueue.pop_front(); { sys::Mutex::ScopedUnlock unlock(agentLock); - invokeMethodRequest(item->body, item->cid, item->replyTo); + invokeMethodRequest(item->body, item->cid, item->replyTo, item->userId); delete item; } } @@ -559,7 +559,7 @@ void ManagementAgentImpl::handleConsoleAddedIndication() QPID_LOG(trace, "RCVD ConsoleAddedInd"); } -void ManagementAgentImpl::invokeMethodRequest(const string& body, const string& cid, const string& replyTo) +void ManagementAgentImpl::invokeMethodRequest(const string& body, const string& cid, const string& replyTo, const string& userId) { string methodName; bool failed = false; @@ -606,7 +606,7 @@ void ManagementAgentImpl::invokeMethodRequest(const string& body, const string& Manageable::STATUS_UNKNOWN_OBJECT); failed = true; } else { - oPtr->doMethod(methodName, inArgs, callMap); + oPtr->doMethod(methodName, inArgs, callMap, userId); if (callMap["_status_code"].asUint32() == 0) { outMap["_arguments"] = Variant::Map(); @@ -837,12 +837,12 @@ void ManagementAgentImpl::handleLocateRequest(const string&, const string& cid, } } -void ManagementAgentImpl::handleMethodRequest(const string& body, const string& cid, const string& replyTo) +void ManagementAgentImpl::handleMethodRequest(const string& body, const string& cid, const string& replyTo, const string& userId) { if (extThread) { sys::Mutex::ScopedLock lock(agentLock); - methodQueue.push_back(new QueuedMethod(cid, replyTo, body)); + methodQueue.push_back(new QueuedMethod(cid, replyTo, body, userId)); if (pipeHandle != 0) { pipeHandle->write("X", 1); } else if (notifyable != 0) { @@ -861,7 +861,7 @@ void ManagementAgentImpl::handleMethodRequest(const string& body, const string& inCallback = false; } } else { - invokeMethodRequest(body, cid, replyTo); + invokeMethodRequest(body, cid, replyTo, userId); } QPID_LOG(trace, "RCVD MethodRequest"); @@ -876,13 +876,17 @@ void ManagementAgentImpl::received(Message& msg) replyToKey = rt.getRoutingKey(); } + string userId; + if (mp.hasUserId()) + userId = mp.getUserId(); + if (mp.hasAppId() && mp.getAppId() == "qmf2") { string opcode = mp.getApplicationHeaders().getAsString("qmf.opcode"); string cid = msg.getMessageProperties().getCorrelationId(); if (opcode == "_agent_locate_request") handleLocateRequest(msg.getData(), cid, replyToKey); - else if (opcode == "_method_request") handleMethodRequest(msg.getData(), cid, replyToKey); + else if (opcode == "_method_request") handleMethodRequest(msg.getData(), cid, replyToKey, userId); else if (opcode == "_query_request") handleGetQuery(msg.getData(), cid, replyToKey); else { QPID_LOG(warning, "Support for QMF V2 Opcode [" << opcode << "] TBD!!!"); diff --git a/cpp/src/qpid/agent/ManagementAgentImpl.h b/cpp/src/qpid/agent/ManagementAgentImpl.h index 59f6c0b99c..09d98d237b 100644 --- a/cpp/src/qpid/agent/ManagementAgentImpl.h +++ b/cpp/src/qpid/agent/ManagementAgentImpl.h @@ -128,12 +128,13 @@ class ManagementAgentImpl : public ManagementAgent, public client::MessageListen }; struct QueuedMethod { - QueuedMethod(const std::string& _cid, const std::string& _reply, const std::string& _body) : - cid(_cid), replyTo(_reply), body(_body) {} + QueuedMethod(const std::string& _cid, const std::string& _reply, const std::string& _body, const std::string& _uid) : + cid(_cid), replyTo(_reply), body(_body), userId(_uid) {} std::string cid; std::string replyTo; std::string body; + std::string userId; }; typedef std::deque<QueuedMethod*> MethodQueue; @@ -282,11 +283,11 @@ class ManagementAgentImpl : public ManagementAgent, public client::MessageListen void handlePackageRequest (qpid::framing::Buffer& inBuffer); void handleClassQuery (qpid::framing::Buffer& inBuffer); void handleSchemaRequest (qpid::framing::Buffer& inBuffer, uint32_t sequence, const std::string& replyTo); - void invokeMethodRequest (const std::string& body, const std::string& cid, const std::string& replyTo); + void invokeMethodRequest (const std::string& body, const std::string& cid, const std::string& replyTo, const std::string& userId); void handleGetQuery (const std::string& body, const std::string& cid, const std::string& replyTo); void handleLocateRequest (const std::string& body, const std::string& sequence, const std::string& replyTo); - void handleMethodRequest (const std::string& body, const std::string& sequence, const std::string& replyTo); + void handleMethodRequest (const std::string& body, const std::string& sequence, const std::string& replyTo, const std::string& userId); void handleConsoleAddedIndication(); void getHeartbeatContent (qpid::types::Variant::Map& map); }; diff --git a/cpp/src/qpid/management/Manageable.cpp b/cpp/src/qpid/management/Manageable.cpp index a3593e73e3..651215ffb5 100644 --- a/cpp/src/qpid/management/Manageable.cpp +++ b/cpp/src/qpid/management/Manageable.cpp @@ -46,3 +46,8 @@ Manageable::status_t Manageable::ManagementMethod (uint32_t, Args&, std::string& return STATUS_UNKNOWN_METHOD; } +bool Manageable::AuthorizeMethod(uint32_t, Args&, const std::string&) +{ + return true; +} + diff --git a/cpp/src/qpid/management/ManagementAgent.cpp b/cpp/src/qpid/management/ManagementAgent.cpp index 09494f1d8e..f33ebcd68d 100644 --- a/cpp/src/qpid/management/ManagementAgent.cpp +++ b/cpp/src/qpid/management/ManagementAgent.cpp @@ -1083,8 +1083,8 @@ void ManagementAgent::handleMethodRequestLH(Buffer& inBuffer, const string& repl return; } + string userId = ((const qpid::broker::ConnectionState*) connToken)->getUserId(); if (acl != 0) { - string userId = ((const qpid::broker::ConnectionState*) connToken)->getUserId(); map<acl::Property, string> params; params[acl::PROP_SCHEMAPACKAGE] = packageName; params[acl::PROP_SCHEMACLASS] = className; @@ -1115,7 +1115,7 @@ void ManagementAgent::handleMethodRequestLH(Buffer& inBuffer, const string& repl outBuffer.record(); sys::Mutex::ScopedUnlock u(userLock); string outBuf; - iter->second->doMethod(methodName, inArgs, outBuf); + iter->second->doMethod(methodName, inArgs, outBuf, userId); outBuffer.putRawData(outBuf); } catch(exception& e) { outBuffer.restore(); @@ -1193,8 +1193,8 @@ void ManagementAgent::handleMethodRequestLH (const string& body, const string& r return; } + string userId = ((const qpid::broker::ConnectionState*) connToken)->getUserId(); if (acl != 0) { - string userId = ((const qpid::broker::ConnectionState*) connToken)->getUserId(); map<acl::Property, string> params; params[acl::PROP_SCHEMAPACKAGE] = iter->second->getPackageName(); params[acl::PROP_SCHEMACLASS] = iter->second->getClassName(); @@ -1214,7 +1214,7 @@ void ManagementAgent::handleMethodRequestLH (const string& body, const string& r try { sys::Mutex::ScopedUnlock u(userLock); - iter->second->doMethod(methodName, inArgs, callMap); + iter->second->doMethod(methodName, inArgs, callMap, userId); errorCode = callMap["_status_code"].asUint32(); if (errorCode == 0) { outMap["_arguments"] = Variant::Map(); |