summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharles E. Rolke <chug@apache.org>2013-03-22 14:59:38 +0000
committerCharles E. Rolke <chug@apache.org>2013-03-22 14:59:38 +0000
commit4b57dd91ac5400fdfd9b5a66f793492c4cf040fc (patch)
tree977236654c51ca5c56329da16bd43d487b9bf565
parent998a026ec36087cfa5463a6dcbea2909fea7c5b8 (diff)
downloadqpid-python-4b57dd91ac5400fdfd9b5a66f793492c4cf040fc.tar.gz
QPID-4631: C++ Broker interbroker links protected by ACL
This patch has the Acl code to observe CREATE LINK rules and the new link cration logic in the broker connection handler. Several self tests are broken by this patch and only ha_test.py has been repaired. The fix for these self tests are indicators of what customers must do to deal with this new feature. git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/qpid-4631@1459822 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--qpid/cpp/src/qpid/acl/Acl.cpp10
-rw-r--r--qpid/cpp/src/qpid/acl/Acl.h5
-rw-r--r--qpid/cpp/src/qpid/acl/AclConnectionCounter.cpp2
-rw-r--r--qpid/cpp/src/qpid/acl/AclData.cpp2
-rw-r--r--qpid/cpp/src/qpid/acl/AclData.h1
-rw-r--r--qpid/cpp/src/qpid/acl/AclReader.cpp4
-rw-r--r--qpid/cpp/src/qpid/acl/management-schema.xml1
-rw-r--r--qpid/cpp/src/qpid/broker/AclModule.h5
-rw-r--r--qpid/cpp/src/qpid/broker/ConnectionHandler.cpp20
-rwxr-xr-xqpid/cpp/src/tests/ha_test.py11
10 files changed, 55 insertions, 6 deletions
diff --git a/qpid/cpp/src/qpid/acl/Acl.cpp b/qpid/cpp/src/qpid/acl/Acl.cpp
index aeee42563c..bdec6791b8 100644
--- a/qpid/cpp/src/qpid/acl/Acl.cpp
+++ b/qpid/cpp/src/qpid/acl/Acl.cpp
@@ -53,7 +53,7 @@ using qpid::management::Manageable;
using qpid::management::Args;
namespace _qmf = qmf::org::apache::qpid::acl;
-Acl::Acl (AclValues& av, Broker& b): aclValues(av), broker(&b), transferAcl(false),
+Acl::Acl (AclValues& av, Broker& b): aclValues(av), broker(&b), transferAcl(false), createlinkAcl(false),
connectionCounter(new ConnectionCounter(*this, aclValues.aclMaxConnectPerUser, aclValues.aclMaxConnectPerIp, aclValues.aclMaxConnectTotal)),
resourceCounter(new ResourceCounter(*this, aclValues.aclMaxQueuesPerUser)){
@@ -254,12 +254,17 @@ bool Acl::readAclFile(std::string& aclFile, std::string& errorText) {
Mutex::ScopedLock locker(dataLock);
data = d;
}
- transferAcl = data->transferAcl; // any transfer ACL
+ transferAcl = data->transferAcl; // any PUBLISH EXCHANGE transfer ACL
+ createlinkAcl = data->createlinkAcl; // any CREATE LINK ACL
if (data->transferAcl){
QPID_LOG(debug,"ACL: Transfer ACL is Enabled!");
}
+ if (data->createlinkAcl){
+ QPID_LOG(debug,"ACL: CREATE LINK ACL is Enabled!");
+ }
+
if (data->enforcingConnectionQuotas()){
QPID_LOG(debug, "ACL: Connection quotas are Enabled.");
}
@@ -271,6 +276,7 @@ bool Acl::readAclFile(std::string& aclFile, std::string& errorText) {
data->aclSource = aclFile;
if (mgmtObject!=0){
mgmtObject->set_transferAcl(transferAcl?1:0);
+ mgmtObject->set_createLinkAcl(createlinkAcl?1:0);
mgmtObject->set_policyFile(aclFile);
sys::AbsTime now = sys::AbsTime::now();
int64_t ns = sys::Duration(sys::EPOCH, now);
diff --git a/qpid/cpp/src/qpid/acl/Acl.h b/qpid/cpp/src/qpid/acl/Acl.h
index ea3c6586a3..9721a60fba 100644
--- a/qpid/cpp/src/qpid/acl/Acl.h
+++ b/qpid/cpp/src/qpid/acl/Acl.h
@@ -61,6 +61,7 @@ private:
acl::AclValues aclValues;
broker::Broker* broker;
bool transferAcl;
+ bool createlinkAcl;
boost::shared_ptr<AclData> data;
qmf::org::apache::qpid::acl::Acl::shared_ptr mgmtObject;
qpid::management::ManagementAgent* agent;
@@ -81,6 +82,10 @@ public:
return transferAcl;
};
+ inline virtual bool isCreatelinkAcl() {
+ return createlinkAcl;
+ };
+
inline virtual uint16_t getMaxConnectTotal() {
return aclValues.aclMaxConnectTotal;
};
diff --git a/qpid/cpp/src/qpid/acl/AclConnectionCounter.cpp b/qpid/cpp/src/qpid/acl/AclConnectionCounter.cpp
index 875137bf55..80a7a32790 100644
--- a/qpid/cpp/src/qpid/acl/AclConnectionCounter.cpp
+++ b/qpid/cpp/src/qpid/acl/AclConnectionCounter.cpp
@@ -288,7 +288,7 @@ std::string ConnectionCounter::getClientHost(const std::string mgmtId)
}
// no hyphen found - use whole string
- assert(false);
+ //assert(false);
return mgmtId;
}
diff --git a/qpid/cpp/src/qpid/acl/AclData.cpp b/qpid/cpp/src/qpid/acl/AclData.cpp
index 922f65ba69..5ffd0462dc 100644
--- a/qpid/cpp/src/qpid/acl/AclData.cpp
+++ b/qpid/cpp/src/qpid/acl/AclData.cpp
@@ -46,6 +46,7 @@ namespace acl {
AclData::AclData():
decisionMode(qpid::acl::DENY),
transferAcl(false),
+ createlinkAcl(false),
aclSource("UNKNOWN"),
connQuotaRulesExist(false),
connQuotaRuleSettings(new quotaRuleSet),
@@ -74,6 +75,7 @@ namespace acl {
delete[] actionList[cnt];
}
transferAcl = false;
+ createlinkAcl = false;
connQuotaRulesExist = false;
connQuotaRuleSettings->clear();
queueQuotaRulesExist = false;
diff --git a/qpid/cpp/src/qpid/acl/AclData.h b/qpid/cpp/src/qpid/acl/AclData.h
index c561b95e09..ad8b741be5 100644
--- a/qpid/cpp/src/qpid/acl/AclData.h
+++ b/qpid/cpp/src/qpid/acl/AclData.h
@@ -118,6 +118,7 @@ public:
aclAction* actionList[qpid::acl::ACTIONSIZE];
qpid::acl::AclResult decisionMode; // allow/deny[-log] if no matching rule found
bool transferAcl;
+ bool createlinkAcl;
std::string aclSource;
AclResult lookup(
diff --git a/qpid/cpp/src/qpid/acl/AclReader.cpp b/qpid/cpp/src/qpid/acl/AclReader.cpp
index 1fd5445b52..f0974b8585 100644
--- a/qpid/cpp/src/qpid/acl/AclReader.cpp
+++ b/qpid/cpp/src/qpid/acl/AclReader.cpp
@@ -160,6 +160,10 @@ namespace acl {
ocnt < acl::OBJECTSIZE;
(*i)->objStatus != aclRule::VALUE ? ocnt++ : ocnt = acl::OBJECTSIZE) {
+ // Observe existance of CREATE LINK rules
+ if (acnt == acl::ACT_CREATE && ocnt == acl::OBJ_LINK)
+ d->createlinkAcl = true;
+
//find the Object, create if not exist
if (d->actionList[acnt][ocnt] == NULL)
d->actionList[acnt][ocnt] =
diff --git a/qpid/cpp/src/qpid/acl/management-schema.xml b/qpid/cpp/src/qpid/acl/management-schema.xml
index 2ac20bb324..e0368db96b 100644
--- a/qpid/cpp/src/qpid/acl/management-schema.xml
+++ b/qpid/cpp/src/qpid/acl/management-schema.xml
@@ -26,6 +26,7 @@
<property name="maxConnectionsPerIp" type="uint16" access="RO" desc="Maximum allowed connections"/>
<property name="maxConnectionsPerUser" type="uint16" access="RO" desc="Maximum allowed connections"/>
<property name="maxQueuesPerUser" type="uint16" access="RO" desc="Maximum allowed queues"/>
+ <property name="createLinkAcl" type="bool" access="RO" desc="Create Link ACL rules may allow link creation"/>
<statistic name="aclDenyCount" type="count64" unit="request" desc="Number of ACL requests denied"/>
<statistic name="connectionDenyCount" type="count64" unit="connection" desc="Number of connections denied"/>
<statistic name="queueQuotaDenyCount" type="count64" unit="queue" desc="Number of queue creations denied"/>
diff --git a/qpid/cpp/src/qpid/broker/AclModule.h b/qpid/cpp/src/qpid/broker/AclModule.h
index c01697ace9..1c138c62a8 100644
--- a/qpid/cpp/src/qpid/broker/AclModule.h
+++ b/qpid/cpp/src/qpid/broker/AclModule.h
@@ -132,6 +132,11 @@ namespace broker {
// doTransferAcl pervents time consuming ACL calls on a per-message basis.
virtual bool doTransferAcl()=0;
+ // Federation link creation is denied unless ACL module is loaded and
+ // at least one CREATE LINK rule is specified.
+ // This flag indicates that a CREATE LINK rule was processed.
+ virtual bool isCreatelinkAcl()=0;
+
virtual uint16_t getMaxConnectTotal()=0;
virtual bool authorise(
diff --git a/qpid/cpp/src/qpid/broker/ConnectionHandler.cpp b/qpid/cpp/src/qpid/broker/ConnectionHandler.cpp
index 977c706ebd..39a8664aab 100644
--- a/qpid/cpp/src/qpid/broker/ConnectionHandler.cpp
+++ b/qpid/cpp/src/qpid/broker/ConnectionHandler.cpp
@@ -201,11 +201,25 @@ void ConnectionHandler::Handler::startOk(const ConnectionStartOkBody& body)
if (connection.isFederationLink()) {
AclModule* acl = connection.getBroker().getAcl();
FieldTable properties;
- if (acl && !acl->authorise(connection.getUserId(),acl::ACT_CREATE,acl::OBJ_LINK,"")){
+ if (acl) {
+ if (acl->isCreatelinkAcl()) {
+ if (!acl->authorise(connection.getUserId(),acl::ACT_CREATE,acl::OBJ_LINK,"")){
+ proxy.close(framing::connection::CLOSE_CODE_CONNECTION_FORCED,
+ QPID_MSG("ACL denied " << connection.getUserId()
+ << " creating a federation link"));
+ return;
+ }
+ } else {
+ proxy.close(framing::connection::CLOSE_CODE_CONNECTION_FORCED,
+ QPID_MSG("ACL denied " << connection.getUserId()
+ << ". Federation links require explicit CREATE LINK ACL rules"));
+ return;
+ }
+ } else {
proxy.close(framing::connection::CLOSE_CODE_CONNECTION_FORCED,
QPID_MSG("ACL denied " << connection.getUserId()
- << " creating a federation link"));
- return;
+ << ". Federation links require ACL module and explicit CREATE LINK ACL rules"));
+ return;
}
QPID_LOG(info, "Connection is a federation link");
}
diff --git a/qpid/cpp/src/tests/ha_test.py b/qpid/cpp/src/tests/ha_test.py
index f2ebb16ccc..5c42780f50 100755
--- a/qpid/cpp/src/tests/ha_test.py
+++ b/qpid/cpp/src/tests/ha_test.py
@@ -79,6 +79,17 @@ class HaBroker(Broker):
if ha_replicate is not None:
args += [ "--ha-replicate=%s"%ha_replicate ]
if brokers_url: args += [ "--ha-brokers-url", brokers_url ]
+ # Set up default ACL file to allow all create link
+ acl=os.path.join(os.getcwd(), "unrestricted.acl")
+ if not os.path.exists(acl):
+ aclf=file(acl,"w")
+ aclf.write("""
+acl allow all create link
+acl allow all all
+ """)
+ aclf.close()
+ if not "--acl-file" in args:
+ args += [ "--acl-file", acl, "--load-module", os.getenv("ACL_LIB") ]
Broker.__init__(self, test, args, **kwargs)
self.qpid_ha_path=os.path.join(os.getenv("PYTHON_COMMANDS"), "qpid-ha")
assert os.path.exists(self.qpid_ha_path)