summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCharles E. Rolke <chug@apache.org>2012-08-20 20:09:43 +0000
committerCharles E. Rolke <chug@apache.org>2012-08-20 20:09:43 +0000
commit8250f1d4d4c13fe09bb72e70e3720c5d9436e561 (patch)
tree3602a0cdbea3e73b2892aa7c7622086745113f2f
parenta2eb4becc8e99524415183fe05ea407c87ff3798 (diff)
downloadqpid-python-8250f1d4d4c13fe09bb72e70e3720c5d9436e561.tar.gz
QPID-4230 (review 6645) Username substition keywords in Acl file.
git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1375195 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r--qpid/cpp/src/qpid/acl/AclData.cpp183
-rw-r--r--qpid/cpp/src/qpid/acl/AclData.h15
-rw-r--r--qpid/cpp/src/qpid/acl/AclReader.cpp9
-rw-r--r--qpid/cpp/src/qpid/broker/AclModule.h4
-rwxr-xr-xqpid/cpp/src/tests/acl.py540
5 files changed, 738 insertions, 13 deletions
diff --git a/qpid/cpp/src/qpid/acl/AclData.cpp b/qpid/cpp/src/qpid/acl/AclData.cpp
index a07176dc76..7c14d0985d 100644
--- a/qpid/cpp/src/qpid/acl/AclData.cpp
+++ b/qpid/cpp/src/qpid/acl/AclData.cpp
@@ -25,6 +25,13 @@ namespace qpid {
namespace acl {
//
+ // Instantiate the substitution keyword string
+ //
+ const std::string AclData::USER_SUBSTITUTION_KEYWORD = "${user}";
+ const std::string AclData::DOMAIN_SUBSTITUTION_KEYWORD = "${domain}";
+ const std::string AclData::USERDOMAIN_SUBSTITUTION_KEYWORD = "${userdomain}";
+
+ //
// constructor
//
AclData::AclData():
@@ -147,7 +154,17 @@ namespace acl {
// the calling args and not in the param map.
if (rulePropMapItr->first == acl::SPECPROP_NAME)
{
- if (matchProp(rulePropMapItr->second, name))
+ // substitute user name into object name
+ bool result;
+ if (rsItr->ruleHasUserSub[PROP_NAME]) {
+ std::string sName(rulePropMapItr->second);
+ substituteUserId(sName, id);
+ result = matchProp(sName, name);
+ } else {
+ result = matchProp(rulePropMapItr->second, name);
+ }
+
+ if (result)
{
QPID_LOG(debug, "ACL: lookup name '" << name
<< "' matched with rule name '"
@@ -222,7 +239,20 @@ namespace acl {
break;
default:
- if (matchProp(rulePropMapItr->second, lookupParamItr->second))
+ bool result;
+ if ((SPECPROP_ALTERNATE == rulePropMapItr->first && rsItr->ruleHasUserSub[PROP_ALTERNATE]) ||
+ (SPECPROP_ROUTINGKEY == rulePropMapItr->first && rsItr->ruleHasUserSub[PROP_ROUTINGKEY]) ||
+ (SPECPROP_QUEUENAME == rulePropMapItr->first && rsItr->ruleHasUserSub[PROP_QUEUENAME]))
+ {
+ // These properties are allowed to have username substitution
+ std::string sName(rulePropMapItr->second);
+ substituteUserId(sName, id);
+ result = matchProp(sName, lookupParamItr->second);
+ } else {
+ result = matchProp(rulePropMapItr->second, lookupParamItr->second);
+ }
+
+ if (result)
{
QPID_LOG(debug, "ACL: the pair("
<< AclHelper::getPropertyStr(lookupParamItr->first)
@@ -346,7 +376,18 @@ namespace acl {
bool match =true;
if (rsItr->pubExchNameInRule)
{
- if (matchProp(rsItr->pubExchName, name))
+ // substitute user name into object name
+ bool result;
+
+ if (rsItr->ruleHasUserSub[PROP_NAME]) {
+ std::string sName(rsItr->pubExchName);
+ substituteUserId(sName, id);
+ result = matchProp(sName, name);
+ } else {
+ result = matchProp(rsItr->pubExchName, name);
+ }
+
+ if (result)
{
QPID_LOG(debug, "ACL: Rule: " << rsItr->rawRuleNum << " lookup exchange name '"
<< name << "' matched with rule name '"
@@ -364,18 +405,40 @@ namespace acl {
if (match && rsItr->pubRoutingKeyInRule)
{
- if (rsItr->matchRoutingKey(routingKey))
+ if ((routingKey.find(USER_SUBSTITUTION_KEYWORD, 0) != std::string::npos) ||
+ (routingKey.find(DOMAIN_SUBSTITUTION_KEYWORD, 0) != std::string::npos) ||
+ (routingKey.find(USERDOMAIN_SUBSTITUTION_KEYWORD, 0) != std::string::npos))
{
- QPID_LOG(debug, "ACL: Rule: " << rsItr->rawRuleNum << " lookup key name '"
- << routingKey << "' matched with rule routing key '"
- << rsItr->pubRoutingKey << "'");
+ // The user is not allowed to present a routing key with the substitution key in it
+ QPID_LOG(debug, "ACL: Rule: " << rsItr->rawRuleNum <<
+ " User-specified routing key has substitution wildcard:" << routingKey
+ << ". Rule match prohibited.");
+ match = false;
}
else
{
- QPID_LOG(debug, "ACL: Rule: " << rsItr->rawRuleNum << " lookup key name '"
- << routingKey << "' did not match with rule routing key '"
- << rsItr->pubRoutingKey << "'");
- match = false;
+ bool result;
+ if (rsItr->ruleHasUserSub[PROP_ROUTINGKEY]) {
+ std::string sKey(routingKey);
+ substituteKeywords(sKey, id);
+ result = rsItr->matchRoutingKey(sKey);
+ } else {
+ result = rsItr->matchRoutingKey(routingKey);
+ }
+
+ if (result)
+ {
+ QPID_LOG(debug, "ACL: Rule: " << rsItr->rawRuleNum << " lookup key name '"
+ << routingKey << "' matched with rule routing key '"
+ << rsItr->pubRoutingKey << "'");
+ }
+ else
+ {
+ QPID_LOG(debug, "ACL: Rule: " << rsItr->rawRuleNum << " lookup key name '"
+ << routingKey << "' did not match with rule routing key '"
+ << rsItr->pubRoutingKey << "'");
+ match = false;
+ }
}
}
@@ -501,4 +564,102 @@ namespace acl {
return true;
}
+ const std::string DOMAIN_SEPARATOR("@");
+ const std::string PERIOD(".");
+ const std::string UNDERSCORE("_");
+ //
+ // substituteString
+ // Given a name string from an Acl rule, substitute the replacement into it
+ // wherever the placeholder directs.
+ //
+ void AclData::substituteString(std::string& targetString,
+ const std::string& placeholder,
+ const std::string& replacement)
+ {
+ assert (!placeholder.empty());
+ if (placeholder.empty())
+ return;
+ size_t start_pos(0);
+ while((start_pos = targetString.find(placeholder, start_pos)) != std::string::npos)
+ {
+ targetString.replace(start_pos, placeholder.length(), replacement);
+ start_pos += replacement.length();
+ }
+ }
+
+
+ //
+ // normalizeUserId
+ // Given a name string return it in a form usable as topic keys:
+ // change "@" and "." to "_".
+ //
+ std::string AclData::normalizeUserId(const std::string& userId)
+ {
+ std::string normalId(userId);
+ substituteString(normalId, DOMAIN_SEPARATOR, UNDERSCORE);
+ substituteString(normalId, PERIOD, UNDERSCORE);
+ return normalId;
+ }
+
+
+ //
+ // substituteUserId
+ // Given an Acl rule and an authenticated userId
+ // do the keyword substitutions on the rule.
+ //
+ void AclData::AclData::substituteUserId(std::string& ruleString,
+ const std::string& userId)
+ {
+ size_t locDomSeparator(0);
+ std::string user("");
+ std::string domain("");
+ std::string userdomain = normalizeUserId(userId);
+
+ locDomSeparator = userId.find(DOMAIN_SEPARATOR);
+ if (std::string::npos == locDomSeparator) {
+ // "@" not found. There's just a user name
+ user = normalizeUserId(userId);
+ } else {
+ // "@" found, split the names. Domain may be blank.
+ user = normalizeUserId(userId.substr(0,locDomSeparator));
+ domain = normalizeUserId(userId.substr(locDomSeparator+1));
+ }
+
+ substituteString(ruleString, USER_SUBSTITUTION_KEYWORD, user);
+ substituteString(ruleString, DOMAIN_SUBSTITUTION_KEYWORD, domain);
+ substituteString(ruleString, USERDOMAIN_SUBSTITUTION_KEYWORD, userdomain);
+ }
+
+
+ //
+ // substituteKeywords
+ // Given an Acl rule and an authenticated userId
+ // do reverse keyword substitutions on the rule.
+ // That is, replace the normalized name in the rule string with
+ // the keyword that represents it. This stragegy is used for
+ // topic key lookups where the keyword string proper is in the
+ // topic key search tree.
+ //
+ void AclData::AclData::substituteKeywords(std::string& ruleString,
+ const std::string& userId)
+ {
+ size_t locDomSeparator(0);
+ std::string user("");
+ std::string domain("");
+ std::string userdomain = normalizeUserId(userId);
+
+ locDomSeparator = userId.find(DOMAIN_SEPARATOR);
+ if (std::string::npos == locDomSeparator) {
+ // "@" not found. There's just a user name
+ user = normalizeUserId(userId);
+ } else {
+ // "@" found, split the names
+ user = normalizeUserId(userId.substr(0,locDomSeparator));
+ domain = normalizeUserId(userId.substr(locDomSeparator+1));
+ }
+ std::string oRule(ruleString);
+ substituteString(ruleString, userdomain, USERDOMAIN_SUBSTITUTION_KEYWORD);
+ substituteString(ruleString, user, USER_SUBSTITUTION_KEYWORD);
+ substituteString(ruleString, domain, DOMAIN_SUBSTITUTION_KEYWORD);
+ }
}}
diff --git a/qpid/cpp/src/qpid/acl/AclData.h b/qpid/cpp/src/qpid/acl/AclData.h
index ca0a676a1c..b4b13c44b6 100644
--- a/qpid/cpp/src/qpid/acl/AclData.h
+++ b/qpid/cpp/src/qpid/acl/AclData.h
@@ -62,6 +62,7 @@ public:
boost::shared_ptr<topicTester> pTTest;
bool pubExchNameInRule;
std::string pubExchName;
+ std::vector<bool> ruleHasUserSub;
Rule (int ruleNum, qpid::acl::AclResult res, specPropertyMap& p) :
rawRuleNum(ruleNum),
@@ -71,7 +72,8 @@ public:
pubRoutingKey(),
pTTest(boost::shared_ptr<topicTester>(new topicTester())),
pubExchNameInRule(false),
- pubExchName()
+ pubExchName(),
+ ruleHasUserSub(PROPERTYSIZE, false)
{}
@@ -132,6 +134,17 @@ public:
bool matchProp(const std::string & src, const std::string& src1);
void clear ();
+ static const std::string USER_SUBSTITUTION_KEYWORD;
+ static const std::string DOMAIN_SUBSTITUTION_KEYWORD;
+ static const std::string USERDOMAIN_SUBSTITUTION_KEYWORD;
+ void substituteString(std::string& targetString,
+ const std::string& placeholder,
+ const std::string& replacement);
+ std::string normalizeUserId(const std::string& userId);
+ void substituteUserId(std::string& ruleString,
+ const std::string& userId);
+ void substituteKeywords(std::string& ruleString,
+ const std::string& userId);
AclData();
virtual ~AclData();
diff --git a/qpid/cpp/src/qpid/acl/AclReader.cpp b/qpid/cpp/src/qpid/acl/AclReader.cpp
index f9be49b88d..fae67d0325 100644
--- a/qpid/cpp/src/qpid/acl/AclReader.cpp
+++ b/qpid/cpp/src/qpid/acl/AclReader.cpp
@@ -103,6 +103,15 @@ namespace acl {
} else {
AclData::Rule rule(cnt, (*i)->res, (*i)->props);
+ // Record which properties have the user substitution string
+ for (pmCitr pItr=rule.props.begin(); pItr!=rule.props.end(); pItr++) {
+ if ((pItr->second.find(AclData::USER_SUBSTITUTION_KEYWORD, 0) != std::string::npos) ||
+ (pItr->second.find(AclData::DOMAIN_SUBSTITUTION_KEYWORD, 0) != std::string::npos) ||
+ (pItr->second.find(AclData::USERDOMAIN_SUBSTITUTION_KEYWORD, 0) != std::string::npos)) {
+ rule.ruleHasUserSub[pItr->first] = true;
+ }
+ }
+
// Action -> Object -> map<user -> set<Rule> >
std::ostringstream actionstr;
for (int acnt = ((*i)->actionAll ? 0 : (*i)->action);
diff --git a/qpid/cpp/src/qpid/broker/AclModule.h b/qpid/cpp/src/qpid/broker/AclModule.h
index f1eb0fc5f9..4caf8ed3ce 100644
--- a/qpid/cpp/src/qpid/broker/AclModule.h
+++ b/qpid/cpp/src/qpid/broker/AclModule.h
@@ -78,7 +78,9 @@ namespace acl {
PROP_SCHEMACLASS,
PROP_POLICYTYPE,
PROP_MAXQUEUESIZE,
- PROP_MAXQUEUECOUNT };
+ PROP_MAXQUEUECOUNT,
+ PROPERTYSIZE // PROPERTYSIZE must be last in list
+ };
// Property used in ACL spec file
// Note for properties common to file processing/rule storage and to
diff --git a/qpid/cpp/src/tests/acl.py b/qpid/cpp/src/tests/acl.py
index 23886d59c5..102796cba6 100755
--- a/qpid/cpp/src/tests/acl.py
+++ b/qpid/cpp/src/tests/acl.py
@@ -1704,6 +1704,546 @@ class ACLTests(TestBase010):
result = None
+ #=====================================
+ # User name substitution
+ #=====================================
+
+ def test_user_name_substitution(self):
+ """
+ Test name substitution internals, limits, and edge cases.
+ """
+ aclf = self.get_acl_file()
+ aclf.write('# begin hack alert: allow anonymous to access the lookup debug functions\n')
+ aclf.write('acl allow-log anonymous create queue\n')
+ aclf.write('acl allow-log anonymous all exchange name=qmf.*\n')
+ aclf.write('acl allow-log anonymous all exchange name=amq.direct\n')
+ aclf.write('acl allow-log anonymous all exchange name=qpid.management\n')
+ aclf.write('acl allow-log anonymous access method name=*\n')
+ aclf.write('# end hack alert\n')
+ aclf.write('acl allow all create queue name=tmp-${userdomain}\n')
+ aclf.write('acl allow all create queue name=${userdomain}-tmp\n')
+ aclf.write('acl allow all create queue name=tmp-${userdomain}-tmp\n')
+ aclf.write('acl allow all create queue name=tmp-${userdomain}-tmp-${userdomain}\n')
+ aclf.write('acl allow all create queue name=temp0-${userdomain}\n')
+ aclf.write('acl allow all access queue name=temp0-${userdomain}\n')
+ aclf.write('acl allow all purge queue name=temp0-${userdomain}\n')
+ aclf.write('acl allow all consume queue name=temp0-${userdomain}\n')
+ aclf.write('acl allow all delete queue name=temp0-${userdomain}\n')
+ aclf.write('acl allow all create exchange name=temp0-${userdomain}\n')
+ aclf.write('acl allow all access exchange name=temp0-${userdomain}\n')
+ aclf.write('acl allow all bind exchange name=temp0-${userdomain}\n')
+ aclf.write('acl allow all unbind exchange name=temp0-${userdomain}\n')
+ aclf.write('acl allow all delete exchange name=temp0-${userdomain}\n')
+ aclf.write('acl allow all publish exchange name=temp0-${userdomain}\n')
+
+ aclf.write('acl allow all publish exchange name=X routingkey=${userdomain}.cd.e\n')
+ aclf.write('acl allow all publish exchange name=X routingkey=a.*.${userdomain}\n')
+ aclf.write('acl allow all publish exchange name=X routingkey=b.#.${userdomain}\n')
+ aclf.write('acl allow all publish exchange name=X routingkey=*.${userdomain}.#.y\n')
+
+ aclf.write('acl allow all create queue name=user-${user}\n')
+ aclf.write('acl allow all publish exchange name=U routingkey=${user}.cd.e\n')
+ aclf.write('acl allow all publish exchange name=U routingkey=a.*.${user}\n')
+ aclf.write('acl allow all publish exchange name=U routingkey=b.#.${user}\n')
+ aclf.write('acl allow all publish exchange name=U routingkey=*.${user}.#.y\n')
+
+ aclf.write('acl allow all create queue name=domain-${domain}\n')
+ aclf.write('acl allow all publish exchange name=D routingkey=${domain}.cd.e\n')
+ aclf.write('acl allow all publish exchange name=D routingkey=a.*.${domain}\n')
+ aclf.write('acl allow all publish exchange name=D routingkey=b.#.${domain}\n')
+ aclf.write('acl allow all publish exchange name=D routingkey=*.${domain}.#.y\n')
+
+ # Resolving ${user}_${domain} into ${userdomain} works for everything but routing keys
+ aclf.write('acl allow all create queue name=mixed-OK-${user}_${domain}\n')
+ # For routing keys ${user}_${domain} will be parsed into ${userdomain}.
+ # Routing keys not be found when the rule specifies ${user}_${domain}.
+ aclf.write('acl allow all publish exchange name=NOGO routingkey=${user}_${domain}.cd.e\n')
+ # This works since it is does not conflict with ${userdomain}
+ aclf.write('acl allow all publish exchange name=OK routingkey=${user}___${domain}.cd.e\n')
+
+ aclf.write('acl deny-log all all\n')
+ aclf.close()
+
+ result = self.reload_acl()
+ if (result):
+ self.fail(result)
+
+ self.Lookup("alice@QPID", "create", "queue", "tmp-alice_QPID", {}, "allow")
+ self.Lookup("bob@QPID", "create", "queue", "bob_QPID-tmp", {}, "allow")
+ self.Lookup("charlie@QPID", "create", "queue", "tmp-charlie_QPID-tmp", {}, "allow")
+ self.Lookup("dave@QPID", "create", "queue", "tmp-dave_QPID-tmp-dave_QPID", {}, "allow")
+ self.Lookup("ed@BIG.COM", "create", "queue", "tmp-ed_BIG_COM", {}, "allow")
+ self.Lookup("c.e.r@BIG.GER.COM", "create", "queue", "tmp-c_e_r_BIG_GER_COM", {}, "allow")
+ self.Lookup("c@", "create", "queue", "tmp-c_", {}, "allow")
+ self.Lookup("someuser", "create", "queue", "tmp-someuser", {}, "allow")
+
+ self.Lookup("alice@QPID", "create", "queue", "tmp-${user}", {}, "deny-log")
+
+ self.Lookup("bob@QPID", "create", "exchange", "temp0-bob_QPID", {}, "allow")
+ self.Lookup("bob@QPID", "access", "exchange", "temp0-bob_QPID", {}, "allow")
+ self.Lookup("bob@QPID", "bind", "exchange", "temp0-bob_QPID", {}, "allow")
+ self.Lookup("bob@QPID", "unbind", "exchange", "temp0-bob_QPID", {}, "allow")
+ self.Lookup("bob@QPID", "delete", "exchange", "temp0-bob_QPID", {}, "allow")
+ self.LookupPublish("bob@QPID", "temp0-bob_QPID", "x", "allow")
+
+ self.Lookup("bob@QPID", "create", "queue", "temp0-bob_QPID", {}, "allow")
+ self.Lookup("bob@QPID", "access", "queue", "temp0-bob_QPID", {}, "allow")
+ self.Lookup("bob@QPID", "purge", "queue", "temp0-bob_QPID", {}, "allow")
+ self.Lookup("bob@QPID", "consume", "queue", "temp0-bob_QPID", {}, "allow")
+ self.Lookup("bob@QPID", "delete", "queue", "temp0-bob_QPID", {}, "allow")
+
+ self.Lookup("alice@QPID", "access", "queue", "temp0-bob_QPID", {}, "deny-log")
+
+ # aclKey: "${userdomain}.cd.e"
+ self.LookupPublish("uPlain1@COMPANY", "X", "uPlain1_COMPANY.cd.e", "allow")
+ # aclKey: "a.*.${userdomain}"
+ self.LookupPublish("uStar1@COMPANY", "X", "a.xx.uStar1_COMPANY", "allow")
+ self.LookupPublish("uStar1@COMPANY", "X", "a.b", "deny-log")
+ # aclKey: "b.#.${userdomain}"
+ self.LookupPublish("uHash1@COMPANY", "X", "b.uHash1_COMPANY", "allow")
+ self.LookupPublish("uHash1@COMPANY", "X", "b.x.uHash1_COMPANY", "allow")
+ self.LookupPublish("uHash1@COMPANY", "X", "b..x.y.zz.uHash1_COMPANY", "allow")
+ self.LookupPublish("uHash1@COMPANY", "X", "b.uHash1_COMPANY.", "deny-log")
+ self.LookupPublish("uHash1@COMPANY", "X", "q.x.uHash1_COMPANY", "deny-log")
+ # aclKey: "*.${userdomain}.#.y"
+ self.LookupPublish("uMixed1@COMPANY", "X", "a.uMixed1_COMPANY.y", "allow")
+ self.LookupPublish("uMixed1@COMPANY", "X", "a.uMixed1_COMPANY.p.qq.y", "allow")
+ self.LookupPublish("uMixed1@COMPANY", "X", "a.a.uMixed1_COMPANY.y", "deny-log")
+ self.LookupPublish("uMixed1@COMPANY", "X", "aa.uMixed1_COMPANY.b.c", "deny-log")
+ self.LookupPublish("uMixed1@COMPANY.COM", "X", "a.uMixed1_COMPANY_COM.y", "allow")
+
+
+ self.Lookup("bob@QPID", "create", "queue", "user-bob", {}, "allow")
+ # aclKey: "${user}.cd.e"
+ self.LookupPublish("uPlain1@COMPANY", "U", "uPlain1.cd.e", "allow")
+ # aclKey: "a.*.${user}"
+ self.LookupPublish("uStar1@COMPANY", "U", "a.xx.uStar1", "allow")
+ self.LookupPublish("uStar1@COMPANY", "U", "a.b", "deny-log")
+ # aclKey: "b.#.${user}"
+ self.LookupPublish("uHash1@COMPANY", "U", "b.uHash1", "allow")
+ self.LookupPublish("uHash1@COMPANY", "U", "b.x.uHash1", "allow")
+ self.LookupPublish("uHash1@COMPANY", "U", "b..x.y.zz.uHash1", "allow")
+ self.LookupPublish("uHash1@COMPANY", "U", "b.uHash1.", "deny-log")
+ self.LookupPublish("uHash1@COMPANY", "U", "q.x.uHash1", "deny-log")
+ # aclKey: "*.${user}.#.y"
+ self.LookupPublish("uMixed1@COMPANY", "U", "a.uMixed1.y", "allow")
+ self.LookupPublish("uMixed1@COMPANY", "U", "a.uMixed1.p.qq.y", "allow")
+ self.LookupPublish("uMixed1@COMPANY", "U", "a.a.uMixed1.y", "deny-log")
+ self.LookupPublish("uMixed1@COMPANY", "U", "aa.uMixed1.b.c", "deny-log")
+ self.LookupPublish("uMixed1@COMPANY.COM", "U", "a.uMixed1.y", "allow")
+
+
+ self.Lookup("bob@QPID", "create", "queue", "domain-QPID", {}, "allow")
+ # aclKey: "${domain}.cd.e"
+ self.LookupPublish("uPlain1@COMPANY", "D", "COMPANY.cd.e", "allow")
+ # aclKey: "a.*.${domain}"
+ self.LookupPublish("uStar1@COMPANY", "D", "a.xx.COMPANY", "allow")
+ self.LookupPublish("uStar1@COMPANY", "D", "a.b", "deny-log")
+ # aclKey: "b.#.${domain}"
+ self.LookupPublish("uHash1@COMPANY", "D", "b.COMPANY", "allow")
+ self.LookupPublish("uHash1@COMPANY", "D", "b.x.COMPANY", "allow")
+ self.LookupPublish("uHash1@COMPANY", "D", "b..x.y.zz.COMPANY", "allow")
+ self.LookupPublish("uHash1@COMPANY", "D", "b.COMPANY.", "deny-log")
+ self.LookupPublish("uHash1@COMPANY", "D", "q.x.COMPANY", "deny-log")
+ # aclKey: "*.${domain}.#.y"
+ self.LookupPublish("uMixed1@COMPANY", "D", "a.COMPANY.y", "allow")
+ self.LookupPublish("uMixed1@COMPANY", "D", "a.COMPANY.p.qq.y", "allow")
+ self.LookupPublish("uMixed1@COMPANY", "D", "a.a.COMPANY.y", "deny-log")
+ self.LookupPublish("uMixed1@COMPANY", "D", "aa.COMPANY.b.c", "deny-log")
+ self.LookupPublish("uMixed1@COMPANY.COM", "D", "a.COMPANY_COM.y", "allow")
+
+ self.Lookup("uPlain1@COMPANY", "create", "queue", "mixed-OK-uPlain1_COMPANY", {}, "allow")
+ self.LookupPublish("uPlain1@COMPANY", "NOGO", "uPlain1_COMPANY.cd.e", "deny-log")
+ self.LookupPublish("uPlain1@COMPANY", "OK", "uPlain1___COMPANY.cd.e", "allow")
+
+
+ #=====================================
+ # User name substitution details
+ #=====================================
+ # User name substitution allows for three flavors of keyword in the Acl file.
+ # Given a user name of bob.user@QPID.COM the keywords are normalized and resolve as follows:
+ # ${userdomain} - bob_user_QPID_COM
+ # ${user} - bob_user
+ # ${domain} - QPID_COM
+ #
+ # The following substitution tests are very similar but differ in the flavor of keyword used
+ # in the rules. The tests results using the different keywords differ slightly in how permissive
+ # the rules become.
+ # ${userdomain} limits access to one authenticated user
+ # ${user} limits access to a user name regardless of user's domain
+ # ${domain} limits access to a domain regardless of user name
+ #
+
+ def test_user_name_substitution_userdomain(self):
+ """
+ Test a setup where users can create, bind, and publish to a main exchange and queue.
+ Allow access to a single alternate exchange and queue.
+ """
+ aclf = self.get_acl_file()
+ aclf.write('# begin hack alert: allow anonymous to access the lookup debug functions\n')
+ aclf.write('acl allow-log anonymous create queue\n')
+ aclf.write('acl allow-log anonymous all exchange name=qmf.*\n')
+ aclf.write('acl allow-log anonymous all exchange name=amq.direct\n')
+ aclf.write('acl allow-log anonymous all exchange name=qpid.management\n')
+ aclf.write('acl allow-log anonymous access method name=*\n')
+ aclf.write('# end hack alert\n')
+ # Create primary queue and exchange:
+ # allow predefined alternate
+ # deny any other alternate
+ # allow no alternate
+ aclf.write('acl allow all create queue name=${userdomain}-work alternate=${userdomain}-work2\n')
+ aclf.write('acl deny all create queue name=${userdomain}-work alternate=*\n')
+ aclf.write('acl allow all create queue name=${userdomain}-work\n')
+ aclf.write('acl allow all create exchange name=${userdomain}-work alternate=${userdomain}-work2\n')
+ aclf.write('acl deny all create exchange name=${userdomain}-work alternate=*\n')
+ aclf.write('acl allow all create exchange name=${userdomain}-work\n')
+ # Create backup queue and exchange
+ # Deny any alternate
+ aclf.write('acl deny all create queue name=${userdomain}-work2 alternate=*\n')
+ aclf.write('acl allow all create queue name=${userdomain}-work2\n')
+ aclf.write('acl deny all create exchange name=${userdomain}-work2 alternate=*\n')
+ aclf.write('acl allow all create exchange name=${userdomain}-work2\n')
+ # Bind/unbind primary exchange
+ # Use only predefined routingkey and queuename
+ aclf.write('acl allow all bind exchange name=${userdomain}-work routingkey=${userdomain} queuename=${userdomain}-work\n')
+ aclf.write('acl allow all unbind exchange name=${userdomain}-work routingkey=${userdomain} queuename=${userdomain}-work\n')
+ # Bind/unbind backup exchange
+ # Use only predefined routingkey and queuename
+ aclf.write('acl allow all bind exchange name=${userdomain}-work2 routingkey=${userdomain} queuename=${userdomain}-work2\n')
+ aclf.write('acl allow all unbind exchange name=${userdomain}-work2 routingkey=${userdomain} queuename=${userdomain}-work2\n')
+ # Access primary exchange
+ # Use only predefined routingkey and queuename
+ aclf.write('acl allow all access exchange name=${userdomain}-work routingkey=${userdomain} queuename=${userdomain}-work\n')
+ # Access backup exchange
+ # Use only predefined routingkey and queuename
+ aclf.write('acl allow all access exchange name=${userdomain}-work2 routingkey=${userdomain} queuename=${userdomain}-work2\n')
+ # Publish primary exchange
+ # Use only predefined routingkey
+ aclf.write('acl allow all publish exchange name=${userdomain}-work routingkey=${userdomain}\n')
+ # Publish backup exchange
+ # Use only predefined routingkey
+ aclf.write('acl allow all publish exchange name=${userdomain}-work2 routingkey=${userdomain}\n')
+ # deny mode
+ aclf.write('acl deny all all\n')
+ aclf.close()
+
+ result = self.reload_acl()
+ if (result):
+ self.fail(result)
+
+ # create queues
+ self.Lookup("bob@QPID", "create", "queue", "bob_QPID-work", {}, "allow")
+ self.Lookup("bob@QPID", "create", "queue", "bob_QPID-work2", {}, "allow")
+ self.Lookup("bob@QPID", "create", "queue", "joe_QPID-work", {}, "deny")
+ self.Lookup("bob@QPID", "create", "queue", "joe_QPID-work2", {}, "deny")
+ self.Lookup("bob@QPID", "create", "queue", "bob_QPID-work3", {}, "deny")
+ self.Lookup("bob@QPID", "create", "queue", "bob_QPID-work", {"alternate":"bob_QPID-work2"}, "allow")
+ self.Lookup("bob@QPID", "create", "queue", "bob_QPID-work", {"alternate":"joe_QPID-work2"}, "deny")
+ self.Lookup("bob@QPID", "create", "queue", "bob_QPID-work2", {"alternate":"someexchange"}, "deny")
+ # create exchanges
+ self.Lookup("bob@QPID", "create", "exchange", "bob_QPID-work", {}, "allow")
+ self.Lookup("bob@QPID", "create", "exchange", "bob_QPID-work2",{}, "allow")
+ self.Lookup("bob@QPID", "create", "exchange", "joe_QPID-work", {}, "deny")
+ self.Lookup("bob@QPID", "create", "exchange", "joe_QPID-work2",{}, "deny")
+ self.Lookup("bob@QPID", "create", "exchange", "bob_QPID-work3",{}, "deny")
+ self.Lookup("bob@QPID", "create", "exchange", "bob_QPID-work", {"alternate":"bob_QPID-work2"}, "allow")
+ self.Lookup("bob@QPID", "create", "exchange", "bob_QPID-work2",{"alternate":"someexchange"}, "deny")
+ # bind/unbind/access
+ self.Lookup("bob@QPID", "bind", "exchange", "bob_QPID-work", {}, "deny")
+ self.Lookup("bob@QPID", "bind", "exchange", "bob_QPID-work", {"routingkey":"bob_QPID"}, "deny")
+ self.Lookup("bob@QPID", "bind", "exchange", "bob_QPID-work", { "queuename":"bob_QPID-work"}, "deny")
+ self.Lookup("bob@QPID", "bind", "exchange", "bob_QPID-work", {"routingkey":"bob_QPID", "queuename":"bob_QPID-work"}, "allow")
+ self.Lookup("bob@QPID", "bind", "exchange", "joe_QPID-work", {"routingkey":"bob_QPID", "queuename":"bob_QPID-work"}, "deny")
+ self.Lookup("bob@QPID", "bind", "exchange", "bob_QPID-work", {"routingkey":"joe_QPID", "queuename":"bob_QPID-work"}, "deny")
+ self.Lookup("bob@QPID", "bind", "exchange", "bob_QPID-work", {"routingkey":"bob_QPID", "queuename":"joe_QPID-work"}, "deny")
+
+ self.Lookup("bob@QPID", "bind", "exchange", "bob_QPID-work2", {}, "deny")
+ self.Lookup("bob@QPID", "bind", "exchange", "bob_QPID-work2", {"routingkey":"bob_QPID"}, "deny")
+ self.Lookup("bob@QPID", "bind", "exchange", "bob_QPID-work2", { "queuename":"bob_QPID-work2"}, "deny")
+ self.Lookup("bob@QPID", "bind", "exchange", "bob_QPID-work2", {"routingkey":"bob_QPID", "queuename":"bob_QPID-work2"}, "allow")
+ self.Lookup("bob@QPID", "bind", "exchange", "joe_QPID-work2", {"routingkey":"bob_QPID", "queuename":"bob_QPID-work2"}, "deny")
+ self.Lookup("bob@QPID", "bind", "exchange", "bob_QPID-work2", {"routingkey":"joe_QPID", "queuename":"bob_QPID-work2"}, "deny")
+ self.Lookup("bob@QPID", "bind", "exchange", "bob_QPID-work2", {"routingkey":"bob_QPID", "queuename":"joe_QPID-work2"}, "deny")
+
+ self.Lookup("bob@QPID", "unbind", "exchange", "bob_QPID-work", {}, "deny")
+ self.Lookup("bob@QPID", "unbind", "exchange", "bob_QPID-work", {"routingkey":"bob_QPID"}, "deny")
+ self.Lookup("bob@QPID", "unbind", "exchange", "bob_QPID-work", { "queuename":"bob_QPID-work"}, "deny")
+ self.Lookup("bob@QPID", "unbind", "exchange", "bob_QPID-work", {"routingkey":"bob_QPID", "queuename":"bob_QPID-work"}, "allow")
+ self.Lookup("bob@QPID", "unbind", "exchange", "joe_QPID-work", {"routingkey":"bob_QPID", "queuename":"bob_QPID-work"}, "deny")
+ self.Lookup("bob@QPID", "unbind", "exchange", "bob_QPID-work", {"routingkey":"joe_QPID", "queuename":"bob_QPID-work"}, "deny")
+ self.Lookup("bob@QPID", "unbind", "exchange", "bob_QPID-work", {"routingkey":"bob_QPID", "queuename":"joe_QPID-work"}, "deny")
+
+ self.Lookup("bob@QPID", "unbind", "exchange", "bob_QPID-work2", {}, "deny")
+ self.Lookup("bob@QPID", "unbind", "exchange", "bob_QPID-work2", {"routingkey":"bob_QPID"}, "deny")
+ self.Lookup("bob@QPID", "unbind", "exchange", "bob_QPID-work2", { "queuename":"bob_QPID-work2"}, "deny")
+ self.Lookup("bob@QPID", "unbind", "exchange", "bob_QPID-work2", {"routingkey":"bob_QPID", "queuename":"bob_QPID-work2"}, "allow")
+ self.Lookup("bob@QPID", "unbind", "exchange", "joe_QPID-work2", {"routingkey":"bob_QPID", "queuename":"bob_QPID-work2"}, "deny")
+ self.Lookup("bob@QPID", "unbind", "exchange", "bob_QPID-work2", {"routingkey":"joe_QPID", "queuename":"bob_QPID-work2"}, "deny")
+ self.Lookup("bob@QPID", "unbind", "exchange", "bob_QPID-work2", {"routingkey":"bob_QPID", "queuename":"joe_QPID-work2"}, "deny")
+
+ self.Lookup("bob@QPID", "access", "exchange", "bob_QPID-work", {}, "deny")
+ self.Lookup("bob@QPID", "access", "exchange", "bob_QPID-work", {"routingkey":"bob_QPID"}, "deny")
+ self.Lookup("bob@QPID", "access", "exchange", "bob_QPID-work", { "queuename":"bob_QPID-work"}, "deny")
+ self.Lookup("bob@QPID", "access", "exchange", "bob_QPID-work", {"routingkey":"bob_QPID", "queuename":"bob_QPID-work"}, "allow")
+ self.Lookup("bob@QPID", "access", "exchange", "joe_QPID-work", {"routingkey":"bob_QPID", "queuename":"bob_QPID-work"}, "deny")
+ self.Lookup("bob@QPID", "access", "exchange", "bob_QPID-work", {"routingkey":"joe_QPID", "queuename":"bob_QPID-work"}, "deny")
+ self.Lookup("bob@QPID", "access", "exchange", "bob_QPID-work", {"routingkey":"bob_QPID", "queuename":"joe_QPID-work"}, "deny")
+
+ self.Lookup("bob@QPID", "access", "exchange", "bob_QPID-work2", {}, "deny")
+ self.Lookup("bob@QPID", "access", "exchange", "bob_QPID-work2", {"routingkey":"bob_QPID"}, "deny")
+ self.Lookup("bob@QPID", "access", "exchange", "bob_QPID-work2", { "queuename":"bob_QPID-work2"}, "deny")
+ self.Lookup("bob@QPID", "access", "exchange", "bob_QPID-work2", {"routingkey":"bob_QPID", "queuename":"bob_QPID-work2"}, "allow")
+ self.Lookup("bob@QPID", "access", "exchange", "joe_QPID-work2", {"routingkey":"bob_QPID", "queuename":"bob_QPID-work2"}, "deny")
+ self.Lookup("bob@QPID", "access", "exchange", "bob_QPID-work2", {"routingkey":"joe_QPID", "queuename":"bob_QPID-work2"}, "deny")
+ self.Lookup("bob@QPID", "access", "exchange", "bob_QPID-work2", {"routingkey":"bob_QPID", "queuename":"joe_QPID-work2"}, "deny")
+ # publish
+ self.LookupPublish("bob@QPID", "bob_QPID-work", "bob_QPID", "allow")
+ self.LookupPublish("bob@QPID", "bob_QPID-work2", "bob_QPID", "allow")
+ self.LookupPublish("bob@QPID", "joe_QPID-work", "bob_QPID", "deny")
+ self.LookupPublish("bob@QPID", "joe_QPID-work2", "bob_QPID", "deny")
+ self.LookupPublish("bob@QPID", "bob_QPID-work", "joe_QPID", "deny")
+ self.LookupPublish("bob@QPID", "bob_QPID-work2", "joe_QPID", "deny")
+
+
+ def test_user_name_substitution_user(self):
+ """
+ Test a setup where users can create, bind, and publish to a main exchange and queue.
+ Allow access to a single backup exchange and queue.
+ """
+ aclf = self.get_acl_file()
+ aclf.write('# begin hack alert: allow anonymous to access the lookup debug functions\n')
+ aclf.write('acl allow-log anonymous create queue\n')
+ aclf.write('acl allow-log anonymous all exchange name=qmf.*\n')
+ aclf.write('acl allow-log anonymous all exchange name=amq.direct\n')
+ aclf.write('acl allow-log anonymous all exchange name=qpid.management\n')
+ aclf.write('acl allow-log anonymous access method name=*\n')
+ aclf.write('# end hack alert\n')
+ # Create primary queue and exchange
+ # allow predefined alternate
+ # deny any other alternate
+ # allow no alternate
+ aclf.write('acl allow all create queue name=${user}-work alternate=${user}-work2\n')
+ aclf.write('acl deny all create queue name=${user}-work alternate=*\n')
+ aclf.write('acl allow all create queue name=${user}-work\n')
+ aclf.write('acl allow all create exchange name=${user}-work alternate=${user}-work2\n')
+ aclf.write('acl deny all create exchange name=${user}-work alternate=*\n')
+ aclf.write('acl allow all create exchange name=${user}-work\n')
+ # Create backup queue and exchange
+ # Deny any alternate
+ aclf.write('acl deny all create queue name=${user}-work2 alternate=*\n')
+ aclf.write('acl allow all create queue name=${user}-work2\n')
+ aclf.write('acl deny all create exchange name=${user}-work2 alternate=*\n')
+ aclf.write('acl allow all create exchange name=${user}-work2\n')
+ # Bind/unbind primary exchange
+ # Use only predefined routingkey and queuename
+ aclf.write('acl allow all bind exchange name=${user}-work routingkey=${user} queuename=${user}-work\n')
+ aclf.write('acl allow all unbind exchange name=${user}-work routingkey=${user} queuename=${user}-work\n')
+ # Bind/unbind backup exchange
+ # Use only predefined routingkey and queuename
+ aclf.write('acl allow all bind exchange name=${user}-work2 routingkey=${user} queuename=${user}-work2\n')
+ aclf.write('acl allow all unbind exchange name=${user}-work2 routingkey=${user} queuename=${user}-work2\n')
+ # Access primary exchange
+ # Use only predefined routingkey and queuename
+ aclf.write('acl allow all access exchange name=${user}-work routingkey=${user} queuename=${user}-work\n')
+ # Access backup exchange
+ # Use only predefined routingkey and queuename
+ aclf.write('acl allow all access exchange name=${user}-work2 routingkey=${user} queuename=${user}-work2\n')
+ # Publish primary exchange
+ # Use only predefined routingkey
+ aclf.write('acl allow all publish exchange name=${user}-work routingkey=${user}\n')
+ # Publish backup exchange
+ # Use only predefined routingkey
+ aclf.write('acl allow all publish exchange name=${user}-work2 routingkey=${user}\n')
+ # deny mode
+ aclf.write('acl deny all all\n')
+ aclf.close()
+
+ result = self.reload_acl()
+ if (result):
+ self.fail(result)
+
+ # create queues
+ self.Lookup("bob@QPID", "create", "queue", "bob-work", {}, "allow")
+ self.Lookup("bob@QPID", "create", "queue", "bob-work2", {}, "allow")
+ self.Lookup("bob@QPID", "create", "queue", "joe-work", {}, "deny")
+ self.Lookup("bob@QPID", "create", "queue", "joe-work2", {}, "deny")
+ self.Lookup("bob@QPID", "create", "queue", "bob-work3", {}, "deny")
+ self.Lookup("bob@QPID", "create", "queue", "bob-work", {"alternate":"bob-work2"}, "allow")
+ self.Lookup("bob@QPID", "create", "queue", "bob-work", {"alternate":"joe-work2"}, "deny")
+ self.Lookup("bob@QPID", "create", "queue", "bob-work2", {"alternate":"someexchange"},"deny")
+ # create exchanges
+ self.Lookup("bob@QPID", "create", "exchange", "bob-work", {}, "allow")
+ self.Lookup("bob@QPID", "create", "exchange", "bob-work2",{}, "allow")
+ self.Lookup("bob@QPID", "create", "exchange", "joe-work", {}, "deny")
+ self.Lookup("bob@QPID", "create", "exchange", "joe-work2",{}, "deny")
+ self.Lookup("bob@QPID", "create", "exchange", "bob-work3",{}, "deny")
+ self.Lookup("bob@QPID", "create", "exchange", "bob-work", {"alternate":"bob-work2"}, "allow")
+ self.Lookup("bob@QPID", "create", "exchange", "bob-work2",{"alternate":"someexchange"},"deny")
+ # bind/unbind/access
+ self.Lookup("bob@QPID", "bind", "exchange", "bob-work", {}, "deny")
+ self.Lookup("bob@QPID", "bind", "exchange", "bob-work", {"routingkey":"bob"}, "deny")
+ self.Lookup("bob@QPID", "bind", "exchange", "bob-work", { "queuename":"bob-work"}, "deny")
+ self.Lookup("bob@QPID", "bind", "exchange", "bob-work", {"routingkey":"bob", "queuename":"bob-work"}, "allow")
+ self.Lookup("bob@QPID", "bind", "exchange", "joe-work", {"routingkey":"bob", "queuename":"bob-work"}, "deny")
+ self.Lookup("bob@QPID", "bind", "exchange", "bob-work", {"routingkey":"joe", "queuename":"bob-work"}, "deny")
+ self.Lookup("bob@QPID", "bind", "exchange", "bob-work", {"routingkey":"bob", "queuename":"joe-work"}, "deny")
+
+ self.Lookup("bob@QPID", "bind", "exchange", "bob-work2", {}, "deny")
+ self.Lookup("bob@QPID", "bind", "exchange", "bob-work2", {"routingkey":"bob"}, "deny")
+ self.Lookup("bob@QPID", "bind", "exchange", "bob-work2", { "queuename":"bob-work2"}, "deny")
+ self.Lookup("bob@QPID", "bind", "exchange", "bob-work2", {"routingkey":"bob", "queuename":"bob-work2"}, "allow")
+ self.Lookup("bob@QPID", "bind", "exchange", "joe-work2", {"routingkey":"bob", "queuename":"bob-work2"}, "deny")
+ self.Lookup("bob@QPID", "bind", "exchange", "bob-work2", {"routingkey":"joe", "queuename":"bob-work2"}, "deny")
+ self.Lookup("bob@QPID", "bind", "exchange", "bob-work2", {"routingkey":"bob", "queuename":"joe-work2"}, "deny")
+
+ self.Lookup("bob@QPID", "unbind", "exchange", "bob-work", {}, "deny")
+ self.Lookup("bob@QPID", "unbind", "exchange", "bob-work", {"routingkey":"bob"}, "deny")
+ self.Lookup("bob@QPID", "unbind", "exchange", "bob-work", { "queuename":"bob-work"}, "deny")
+ self.Lookup("bob@QPID", "unbind", "exchange", "bob-work", {"routingkey":"bob", "queuename":"bob-work"}, "allow")
+ self.Lookup("bob@QPID", "unbind", "exchange", "joe-work", {"routingkey":"bob", "queuename":"bob-work"}, "deny")
+ self.Lookup("bob@QPID", "unbind", "exchange", "bob-work", {"routingkey":"joe", "queuename":"bob-work"}, "deny")
+ self.Lookup("bob@QPID", "unbind", "exchange", "bob-work", {"routingkey":"bob", "queuename":"joe-work"}, "deny")
+
+ self.Lookup("bob@QPID", "unbind", "exchange", "bob-work2", {}, "deny")
+ self.Lookup("bob@QPID", "unbind", "exchange", "bob-work2", {"routingkey":"bob"}, "deny")
+ self.Lookup("bob@QPID", "unbind", "exchange", "bob-work2", { "queuename":"bob-work2"}, "deny")
+ self.Lookup("bob@QPID", "unbind", "exchange", "bob-work2", {"routingkey":"bob", "queuename":"bob-work2"}, "allow")
+ self.Lookup("bob@QPID", "unbind", "exchange", "joe-work2", {"routingkey":"bob", "queuename":"bob-work2"}, "deny")
+ self.Lookup("bob@QPID", "unbind", "exchange", "bob-work2", {"routingkey":"joe", "queuename":"bob-work2"}, "deny")
+ self.Lookup("bob@QPID", "unbind", "exchange", "bob-work2", {"routingkey":"bob", "queuename":"joe-work2"}, "deny")
+
+ self.Lookup("bob@QPID", "access", "exchange", "bob-work", {}, "deny")
+ self.Lookup("bob@QPID", "access", "exchange", "bob-work", {"routingkey":"bob"}, "deny")
+ self.Lookup("bob@QPID", "access", "exchange", "bob-work", { "queuename":"bob-work"}, "deny")
+ self.Lookup("bob@QPID", "access", "exchange", "bob-work", {"routingkey":"bob", "queuename":"bob-work"}, "allow")
+ self.Lookup("bob@QPID", "access", "exchange", "joe-work", {"routingkey":"bob", "queuename":"bob-work"}, "deny")
+ self.Lookup("bob@QPID", "access", "exchange", "bob-work", {"routingkey":"joe", "queuename":"bob-work"}, "deny")
+ self.Lookup("bob@QPID", "access", "exchange", "bob-work", {"routingkey":"bob", "queuename":"joe-work"}, "deny")
+
+ self.Lookup("bob@QPID", "access", "exchange", "bob-work2", {}, "deny")
+ self.Lookup("bob@QPID", "access", "exchange", "bob-work2", {"routingkey":"bob"}, "deny")
+ self.Lookup("bob@QPID", "access", "exchange", "bob-work2", { "queuename":"bob-work2"}, "deny")
+ self.Lookup("bob@QPID", "access", "exchange", "bob-work2", {"routingkey":"bob", "queuename":"bob-work2"}, "allow")
+ self.Lookup("bob@QPID", "access", "exchange", "joe-work2", {"routingkey":"bob", "queuename":"bob-work2"}, "deny")
+ self.Lookup("bob@QPID", "access", "exchange", "bob-work2", {"routingkey":"joe", "queuename":"bob-work2"}, "deny")
+ self.Lookup("bob@QPID", "access", "exchange", "bob-work2", {"routingkey":"bob", "queuename":"joe-work2"}, "deny")
+ # publish
+ self.LookupPublish("bob@QPID", "bob-work", "bob", "allow")
+ self.LookupPublish("bob@QPID", "bob-work2", "bob", "allow")
+ self.LookupPublish("bob@QPID", "joe-work", "bob", "deny")
+ self.LookupPublish("bob@QPID", "joe-work2", "bob", "deny")
+ self.LookupPublish("bob@QPID", "bob-work", "joe", "deny")
+ self.LookupPublish("bob@QPID", "bob-work2", "joe", "deny")
+
+
+ def test_user_name_substitution_domain(self):
+ """
+ Test a setup where users can create, bind, and publish to a main exchange and queue.
+ Allow access to a single backup exchange and queue.
+ """
+ aclf = self.get_acl_file()
+ aclf.write('# begin hack alert: allow anonymous to access the lookup debug functions\n')
+ aclf.write('acl allow-log anonymous create queue\n')
+ aclf.write('acl allow-log anonymous all exchange name=qmf.*\n')
+ aclf.write('acl allow-log anonymous all exchange name=amq.direct\n')
+ aclf.write('acl allow-log anonymous all exchange name=qpid.management\n')
+ aclf.write('acl allow-log anonymous access method name=*\n')
+ aclf.write('# end hack alert\n')
+ # Create primary queue and exchange
+ # allow predefined alternate
+ # deny any other alternate
+ # allow no alternate
+ aclf.write('acl allow all create queue name=${domain}-work alternate=${domain}-work2\n')
+ aclf.write('acl deny all create queue name=${domain}-work alternate=*\n')
+ aclf.write('acl allow all create queue name=${domain}-work\n')
+ aclf.write('acl allow all create exchange name=${domain}-work alternate=${domain}-work2\n')
+ aclf.write('acl deny all create exchange name=${domain}-work alternate=*\n')
+ aclf.write('acl allow all create exchange name=${domain}-work\n')
+ # Create backup queue and exchange
+ # Deny any alternate
+ aclf.write('acl deny all create queue name=${domain}-work2 alternate=*\n')
+ aclf.write('acl allow all create queue name=${domain}-work2\n')
+ aclf.write('acl deny all create exchange name=${domain}-work2 alternate=*\n')
+ aclf.write('acl allow all create exchange name=${domain}-work2\n')
+ # Bind/unbind primary exchange
+ # Use only predefined routingkey and queuename
+ aclf.write('acl allow all bind exchange name=${domain}-work routingkey=${domain} queuename=${domain}-work\n')
+ aclf.write('acl allow all unbind exchange name=${domain}-work routingkey=${domain} queuename=${domain}-work\n')
+ # Bind/unbind backup exchange
+ # Use only predefined routingkey and queuename
+ aclf.write('acl allow all bind exchange name=${domain}-work2 routingkey=${domain} queuename=${domain}-work2\n')
+ aclf.write('acl allow all unbind exchange name=${domain}-work2 routingkey=${domain} queuename=${domain}-work2\n')
+ # Access primary exchange
+ # Use only predefined routingkey and queuename
+ aclf.write('acl allow all access exchange name=${domain}-work routingkey=${domain} queuename=${domain}-work\n')
+ # Access backup exchange
+ # Use only predefined routingkey and queuename
+ aclf.write('acl allow all access exchange name=${domain}-work2 routingkey=${domain} queuename=${domain}-work2\n')
+ # Publish primary exchange
+ # Use only predefined routingkey
+ aclf.write('acl allow all publish exchange name=${domain}-work routingkey=${domain}\n')
+ # Publish backup exchange
+ # Use only predefined routingkey
+ aclf.write('acl allow all publish exchange name=${domain}-work2 routingkey=${domain}\n')
+ # deny mode
+ aclf.write('acl deny all all\n')
+ aclf.close()
+
+ result = self.reload_acl()
+ if (result):
+ self.fail(result)
+
+ # create queues
+ self.Lookup("bob@QPID", "create", "queue", "QPID-work", {}, "allow")
+ self.Lookup("bob@QPID", "create", "queue", "QPID-work2", {}, "allow")
+ self.Lookup("bob@QPID", "create", "queue", "QPID-work3", {}, "deny")
+ self.Lookup("bob@QPID", "create", "queue", "QPID-work", {"alternate":"QPID-work2"}, "allow")
+ self.Lookup("bob@QPID", "create", "queue", "QPID-work", {"alternate":"bob_QPID-work2"},"deny")
+ self.Lookup("bob@QPID", "create", "queue", "QPID-work", {"alternate":"joe_QPID-work2"},"deny")
+ self.Lookup("bob@QPID", "create", "queue", "QPID-work2", {"alternate":"someexchange"}, "deny")
+ # create exchanges
+ self.Lookup("bob@QPID", "create", "exchange", "QPID-work", {}, "allow")
+ self.Lookup("bob@QPID", "create", "exchange", "QPID-work2",{}, "allow")
+ self.Lookup("bob@QPID", "create", "exchange", "QPID-work3",{}, "deny")
+ self.Lookup("bob@QPID", "create", "exchange", "QPID-work", {"alternate":"QPID-work2"}, "allow")
+ self.Lookup("bob@QPID", "create", "exchange", "QPID-work2",{"alternate":"someexchange"}, "deny")
+ # bind/unbind/access
+ self.Lookup("bob@QPID", "bind", "exchange", "QPID-work", {}, "deny")
+ self.Lookup("bob@QPID", "bind", "exchange", "QPID-work", {"routingkey":"QPID"}, "deny")
+ self.Lookup("bob@QPID", "bind", "exchange", "QPID-work", { "queuename":"QPID-work"}, "deny")
+ self.Lookup("bob@QPID", "bind", "exchange", "QPID-work", {"routingkey":"QPID", "queuename":"QPID-work"}, "allow")
+
+ self.Lookup("bob@QPID", "bind", "exchange", "QPID-work2", {}, "deny")
+ self.Lookup("bob@QPID", "bind", "exchange", "QPID-work2", {"routingkey":"QPID"}, "deny")
+ self.Lookup("bob@QPID", "bind", "exchange", "QPID-work2", { "queuename":"QPID-work2"}, "deny")
+ self.Lookup("bob@QPID", "bind", "exchange", "QPID-work2", {"routingkey":"QPID", "queuename":"QPID-work2"}, "allow")
+
+ self.Lookup("bob@QPID", "unbind", "exchange", "QPID-work", {}, "deny")
+ self.Lookup("bob@QPID", "unbind", "exchange", "QPID-work", {"routingkey":"QPID"}, "deny")
+ self.Lookup("bob@QPID", "unbind", "exchange", "QPID-work", { "queuename":"QPID-work"}, "deny")
+ self.Lookup("bob@QPID", "unbind", "exchange", "QPID-work", {"routingkey":"QPID", "queuename":"QPID-work"}, "allow")
+
+ self.Lookup("bob@QPID", "unbind", "exchange", "QPID-work2", {}, "deny")
+ self.Lookup("bob@QPID", "unbind", "exchange", "QPID-work2", {"routingkey":"QPID"}, "deny")
+ self.Lookup("bob@QPID", "unbind", "exchange", "QPID-work2", { "queuename":"QPID-work2"}, "deny")
+ self.Lookup("bob@QPID", "unbind", "exchange", "QPID-work2", {"routingkey":"QPID", "queuename":"QPID-work2"}, "allow")
+
+ self.Lookup("bob@QPID", "access", "exchange", "QPID-work", {}, "deny")
+ self.Lookup("bob@QPID", "access", "exchange", "QPID-work", {"routingkey":"QPID"}, "deny")
+ self.Lookup("bob@QPID", "access", "exchange", "QPID-work", { "queuename":"QPID-work"}, "deny")
+ self.Lookup("bob@QPID", "access", "exchange", "QPID-work", {"routingkey":"QPID", "queuename":"QPID-work"}, "allow")
+
+ self.Lookup("bob@QPID", "access", "exchange", "QPID-work2", {}, "deny")
+ self.Lookup("bob@QPID", "access", "exchange", "QPID-work2", {"routingkey":"QPID"}, "deny")
+ self.Lookup("bob@QPID", "access", "exchange", "QPID-work2", { "queuename":"QPID-work2"}, "deny")
+ self.Lookup("bob@QPID", "access", "exchange", "QPID-work2", {"routingkey":"QPID", "queuename":"QPID-work2"}, "allow")
+ # publish
+ self.LookupPublish("bob@QPID", "QPID-work", "QPID", "allow")
+ self.LookupPublish("bob@QPID", "QPID-work2", "QPID", "allow")
+ self.LookupPublish("joe@QPID", "QPID-work", "QPID", "allow")
+ self.LookupPublish("joe@QPID", "QPID-work2", "QPID", "allow")
+
+
class BrokerAdmin:
def __init__(self, broker, username=None, password=None):
self.connection = qpid.messaging.Connection(broker)