summaryrefslogtreecommitdiff
path: root/qpid/java/broker-plugins/access-control
diff options
context:
space:
mode:
authorRobert Gemmell <robbie@apache.org>2012-08-24 15:33:00 +0000
committerRobert Gemmell <robbie@apache.org>2012-08-24 15:33:00 +0000
commit881f4a51e4b9e44f888366fc06f6070f47921b90 (patch)
treec081e6cd763dde58e1f9254cdddbba872be619b6 /qpid/java/broker-plugins/access-control
parent3196cc6e0e4f6c537ab7f3694d7b2e454cd97fbc (diff)
downloadqpid-python-881f4a51e4b9e44f888366fc06f6070f47921b90.tar.gz
QPID-4236, QPID-4237, QPID-4245: Added group management functionality, and exposed it via the web management interface. Removed group definition functionality from the ACL plugin. The ACL plugin uses groups but no longer defines them.
Introduced SubjectCreator as a facade to AuthenticationManager and group management classes. Applied access control to user and group management. Fixed bug in choosing between update and creation in RestServlet. Moved lots of RestTest helper methods to RestTestHelper. Fixed authentication, authorisation, and status logging when using the web ui. Applied patch from Philip Harvey <phil@philharveyonline.com>, Keith Wall and myself. git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1376968 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'qpid/java/broker-plugins/access-control')
-rw-r--r--qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/PlainConfiguration.java70
-rw-r--r--qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/Rule.java20
-rw-r--r--qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/RuleSet.java61
-rw-r--r--qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControl.java8
-rw-r--r--qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControlConfiguration.java4
-rw-r--r--qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/AccessControlTest.java51
-rw-r--r--qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/PlainConfigurationTest.java86
-rw-r--r--qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/RuleSetTest.java92
8 files changed, 185 insertions, 207 deletions
diff --git a/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/PlainConfiguration.java b/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/PlainConfiguration.java
index 9a08eb6499..afaece6138 100644
--- a/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/PlainConfiguration.java
+++ b/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/PlainConfiguration.java
@@ -1,5 +1,5 @@
/*
- *
+ *
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
@@ -7,16 +7,16 @@
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
- *
+ *
* http://www.apache.org/licenses/LICENSE-2.0
- *
+ *
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
- *
+ *
*/
package org.apache.qpid.server.security.access.config;
@@ -44,43 +44,41 @@ public class PlainConfiguration extends AbstractConfiguration
public static final Character COMMENT = '#';
public static final Character CONTINUATION = '\\';
- public static final String GROUP = "group";
public static final String ACL = "acl";
public static final String CONFIG = "config";
public static final String UNRECOGNISED_INITIAL_MSG = "Unrecognised initial token '%s' at line %d";
public static final String NOT_ENOUGH_TOKENS_MSG = "Not enough tokens at line %d";
- public static final String NUMBER_NOT_ALLOWED_MSG = "Number not allowed before '%s' at line %d";
+ public static final String NUMBER_NOT_ALLOWED_MSG = "Number not allowed before '%s' at line %d";
public static final String CANNOT_LOAD_MSG = "Cannot load config file %s";
public static final String PREMATURE_CONTINUATION_MSG = "Premature continuation character at line %d";
public static final String PREMATURE_EOF_MSG = "Premature end of file reached at line %d";
public static final String PARSE_TOKEN_FAILED_MSG = "Failed to parse token at line %d";
public static final String CONFIG_NOT_FOUND_MSG = "Cannot find config file %s";
- public static final String NOT_ENOUGH_GROUP_MSG = "Not enough data for a group at line %d";
public static final String NOT_ENOUGH_ACL_MSG = "Not enough data for an acl at line %d";
public static final String NOT_ENOUGH_CONFIG_MSG = "Not enough data for config at line %d";
public static final String BAD_ACL_RULE_NUMBER_MSG = "Invalid rule number at line %d";
public static final String PROPERTY_KEY_ONLY_MSG = "Incomplete property (key only) at line %d";
public static final String PROPERTY_NO_EQUALS_MSG = "Incomplete property (no equals) at line %d";
public static final String PROPERTY_NO_VALUE_MSG = "Incomplete property (no value) at line %d";
-
+
private StreamTokenizer _st;
public PlainConfiguration(File file)
{
super(file);
}
-
+
@Override
public RuleSet load() throws ConfigurationException
{
RuleSet ruleSet = super.load();
-
+
try
{
_st = new StreamTokenizer(new BufferedReader(new FileReader(getFile())));
_st.resetSyntax(); // setup the tokenizer
-
+
_st.commentChar(COMMENT); // single line comments
_st.eolIsSignificant(true); // return EOL as a token
_st.ordinaryChar('='); // equals is a token
@@ -97,7 +95,7 @@ public class PlainConfiguration extends AbstractConfiguration
_st.wordChars('*', '*'); // star
_st.wordChars('@', '@'); // at
_st.wordChars(':', ':'); // colon
-
+
// parse the acl file lines
Stack<String> stack = new Stack<String>();
int current;
@@ -111,7 +109,7 @@ public class PlainConfiguration extends AbstractConfiguration
{
break; // blank line
}
-
+
// pull out the first token from the bottom of the stack and check arguments exist
String first = stack.firstElement();
stack.removeElementAt(0);
@@ -119,13 +117,13 @@ public class PlainConfiguration extends AbstractConfiguration
{
throw new ConfigurationException(String.format(NOT_ENOUGH_TOKENS_MSG, getLine()));
}
-
+
// check for and parse optional initial number for ACL lines
Integer number = null;
if (StringUtils.isNumeric(first))
{
// set the acl number and get the next element
- number = Integer.valueOf(first);
+ number = Integer.valueOf(first);
first = stack.firstElement();
stack.removeElementAt(0);
}
@@ -136,9 +134,9 @@ public class PlainConfiguration extends AbstractConfiguration
}
else if (number == null)
{
- if (StringUtils.equalsIgnoreCase(GROUP, first))
+ if(StringUtils.equalsIgnoreCase("GROUP", first))
{
- parseGroup(stack);
+ throw new ConfigurationException(String.format("GROUP keyword not supported. Groups should defined via a Group Provider, not in the ACL file.", getLine()));
}
else if (StringUtils.equalsIgnoreCase(CONFIG, first))
{
@@ -153,7 +151,7 @@ public class PlainConfiguration extends AbstractConfiguration
{
throw new ConfigurationException(String.format(NUMBER_NOT_ALLOWED_MSG, first, getLine()));
}
-
+
// reset stack, start next line
stack.clear();
break;
@@ -171,7 +169,7 @@ public class PlainConfiguration extends AbstractConfiguration
{
break; // continue reading next line
}
-
+
// invalid location for continuation character (add one to line beacuse we ate the EOL)
throw new ConfigurationException(String.format(PREMATURE_CONTINUATION_MSG, getLine() + 1));
}
@@ -185,7 +183,7 @@ public class PlainConfiguration extends AbstractConfiguration
}
}
} while (current != StreamTokenizer.TT_EOF);
-
+
if (!stack.isEmpty())
{
throw new ConfigurationException(String.format(PREMATURE_EOF_MSG, getLine()));
@@ -203,20 +201,10 @@ public class PlainConfiguration extends AbstractConfiguration
{
throw new ConfigurationException(String.format(CANNOT_LOAD_MSG, getFile().getName()), ioe);
}
-
+
return ruleSet;
}
-
- private void parseGroup(List<String> args) throws ConfigurationException
- {
- if (args.size() < 2)
- {
- throw new ConfigurationException(String.format(NOT_ENOUGH_GROUP_MSG, getLine()));
- }
-
- getConfiguration().addGroup(args.get(0), args.subList(1, args.size()));
- }
-
+
private void parseAcl(Integer number, List<String> args) throws ConfigurationException
{
if (args.size() < 3)
@@ -227,12 +215,12 @@ public class PlainConfiguration extends AbstractConfiguration
Permission permission = Permission.parse(args.get(0));
String identity = args.get(1);
Operation operation = Operation.parse(args.get(2));
-
+
if (number != null && !getConfiguration().isValidNumber(number))
{
throw new ConfigurationException(String.format(BAD_ACL_RULE_NUMBER_MSG, getLine()));
}
-
+
if (args.size() == 3)
{
getConfiguration().grant(number, identity, permission, operation);
@@ -245,7 +233,7 @@ public class PlainConfiguration extends AbstractConfiguration
getConfiguration().grant(number, identity, permission, operation, object, properties);
}
}
-
+
private void parseConfig(List<String> args) throws ConfigurationException
{
if (args.size() < 3)
@@ -254,10 +242,10 @@ public class PlainConfiguration extends AbstractConfiguration
}
Map<String, Boolean> properties = toPluginProperties(args);
-
+
getConfiguration().configure(properties);
}
-
+
/** Converts a {@link List} of "name", "=", "value" tokens into a {@link Map}. */
protected ObjectProperties toObjectProperties(List<String> args) throws ConfigurationException
{
@@ -279,14 +267,14 @@ public class PlainConfiguration extends AbstractConfiguration
throw new ConfigurationException(String.format(PROPERTY_NO_VALUE_MSG, getLine()));
}
String value = i.next();
-
+
// parse property key
ObjectProperties.Property property = ObjectProperties.Property.parse(key);
properties.put(property, value);
}
return properties;
}
-
+
/** Converts a {@link List} of "name", "=", "value" tokens into a {@link Map}. */
protected Map<String, Boolean> toPluginProperties(List<String> args) throws ConfigurationException
{
@@ -307,14 +295,14 @@ public class PlainConfiguration extends AbstractConfiguration
{
throw new ConfigurationException(String.format(PROPERTY_NO_VALUE_MSG, getLine()));
}
-
+
// parse property value and save
Boolean value = Boolean.valueOf(i.next());
properties.put(key, value);
}
return properties;
}
-
+
protected int getLine()
{
return _st.lineno() - 1;
diff --git a/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/Rule.java b/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/Rule.java
index 15d6b67192..5e98e0bd1b 100644
--- a/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/Rule.java
+++ b/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/Rule.java
@@ -29,7 +29,7 @@ import org.apache.qpid.server.security.access.Permission;
/**
* An access control v2 rule.
- *
+ *
* A rule consists of {@link Permission} for a particular identity to perform an {@link Action}. The identity
* may be either a user or a group.
*/
@@ -37,13 +37,13 @@ public class Rule implements Comparable<Rule>
{
/** String indicating all identitied. */
public static final String ALL = "all";
-
+
private Integer _number;
private Boolean _enabled = Boolean.TRUE;
private String _identity;
private Action _action;
private Permission _permission;
-
+
public Rule(Integer number, String identity, Action action, Permission permission)
{
setNumber(number);
@@ -51,27 +51,27 @@ public class Rule implements Comparable<Rule>
setAction(action);
setPermission(permission);
}
-
+
public Rule(String identity, Action action, Permission permission)
{
this(null, identity, action, permission);
}
-
+
public boolean isEnabled()
{
return _enabled;
}
-
+
public void setEnabled(boolean enabled)
{
_enabled = enabled;
}
-
+
public void enable()
{
_enabled = Boolean.TRUE;
}
-
+
public void disable()
{
_enabled = Boolean.FALSE;
@@ -96,7 +96,7 @@ public class Rule implements Comparable<Rule>
{
_identity = identity;
}
-
+
public Action getAction()
{
return _action;
@@ -136,7 +136,7 @@ public class Rule implements Comparable<Rule>
return false;
}
Rule r = (Rule) o;
-
+
return new EqualsBuilder()
.append(getIdentity(), r.getIdentity())
.append(getAction(), r.getAction())
diff --git a/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/RuleSet.java b/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/RuleSet.java
index 815df99f80..2477455de4 100644
--- a/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/RuleSet.java
+++ b/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/RuleSet.java
@@ -19,7 +19,6 @@
package org.apache.qpid.server.security.access.config;
import java.security.Principal;
-import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumMap;
@@ -66,7 +65,6 @@ public class RuleSet
private static final Integer _increment = 10;
- private final Map<String, List<String>> _aclGroups = new HashMap<String, List<String>>();
private final SortedMap<Integer, Rule> _rules = new TreeMap<Integer, Rule>();
private final Map<Subject, Map<Operation, Map<ObjectType, List<Rule>>>> _cache =
new WeakHashMap<Subject, Map<Operation, Map<ObjectType, List<Rule>>>>();
@@ -79,14 +77,13 @@ public class RuleSet
}
/**
- * Clear the contents, including acl groups, rules and configuration.
+ * Clear the contents, including acl rules and configuration.
*/
public void clear()
{
_rules.clear();
_cache.clear();
_config.clear();
- _aclGroups.clear();
}
public int getRuleCount()
@@ -222,53 +219,6 @@ public class RuleSet
_rules.get(Integer.valueOf(ruleNumber)).disable();
}
- public boolean addGroup(String group, List<String> constituents)
- {
- _cache.clear();
-
- if (_aclGroups.containsKey(group))
- {
- // cannot redefine
- return false;
- }
- else
- {
- _aclGroups.put(group, new ArrayList<String>());
- }
-
- for (String name : constituents)
- {
- if (name.equalsIgnoreCase(group))
- {
- // recursive definition
- return false;
- }
-
- if (!checkName(name))
- {
- // invalid name
- return false;
- }
-
- if (_aclGroups.containsKey(name))
- {
- // is a group
- _aclGroups.get(group).addAll(_aclGroups.get(name));
- }
- else
- {
- // is a user
- if (!isvalidUserName(name))
- {
- // invalid username
- return false;
- }
- _aclGroups.get(group).add(name);
- }
- }
- return true;
- }
-
/** Return true if the name is well-formed (contains legal characters). */
protected boolean checkName(String name)
{
@@ -312,12 +262,6 @@ public class RuleSet
return true;
}
- // CPP broker authorise function prototype
- // virtual bool authorise(const std::string& id, const Action& action, const ObjectType& objType,
- // const std::string& name, std::map<Property, std::string>* params=0)
-
- // Possibly add a String name paramater?
-
/**
* Check the authorisation granted to a particular identity for an operation on an object type with
* specific properties.
@@ -446,8 +390,7 @@ public class RuleSet
{
final Principal principal = iterator.next();
- if (rule.getIdentity().equalsIgnoreCase(principal.getName())
- || (_aclGroups.containsKey(rule.getIdentity()) && _aclGroups.get(rule.getIdentity()).contains(principal.getName())))
+ if (rule.getIdentity().equalsIgnoreCase(principal.getName()))
{
return true;
}
diff --git a/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControl.java b/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControl.java
index d8a5bd4085..d36ae810c6 100644
--- a/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControl.java
+++ b/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControl.java
@@ -40,9 +40,9 @@ import org.apache.qpid.server.security.access.config.RuleSet;
public class AccessControl extends AbstractPlugin
{
public static final Logger _logger = Logger.getLogger(AccessControl.class);
-
+
private RuleSet _ruleSet;
-
+
public static final SecurityPluginFactory<AccessControl> FACTORY = new SecurityPluginFactory<AccessControl>()
{
public Class<AccessControl> getPluginClass()
@@ -86,7 +86,7 @@ public class AccessControl extends AbstractPlugin
{
return authorise(Operation.ACCESS, objectType, ObjectProperties.EMPTY);
}
-
+
/**
* Check if an operation is authorised by asking the configuration object about the access
* control rules granted to the current thread's {@link Subject}. If there is no current
@@ -100,7 +100,7 @@ public class AccessControl extends AbstractPlugin
{
return Result.ABSTAIN;
}
-
+
_logger.debug("Checking " + operation + " " + objectType);
return _ruleSet.check(subject, operation, objectType, properties);
}
diff --git a/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControlConfiguration.java b/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControlConfiguration.java
index c4db6db820..63f7e254ae 100644
--- a/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControlConfiguration.java
+++ b/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControlConfiguration.java
@@ -34,7 +34,7 @@ import org.apache.qpid.server.security.access.config.RuleSet;
public class AccessControlConfiguration extends ConfigurationPlugin
{
- public static final ConfigurationPluginFactory FACTORY = new ConfigurationPluginFactory()
+ public static final ConfigurationPluginFactory FACTORY = new ConfigurationPluginFactory()
{
public ConfigurationPlugin newInstance(String path, Configuration config) throws ConfigurationException
{
@@ -70,7 +70,7 @@ public class AccessControlConfiguration extends ConfigurationPlugin
}
File aclFile = new File(filename);
-
+
ConfigurationFile configFile = new PlainConfiguration(aclFile);
_ruleSet = configFile.load();
}
diff --git a/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/AccessControlTest.java b/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/AccessControlTest.java
index 5db02d10ce..2385bcc3dd 100644
--- a/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/AccessControlTest.java
+++ b/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/AccessControlTest.java
@@ -20,8 +20,6 @@
*/
package org.apache.qpid.server.security.access.plugins;
-import java.util.Arrays;
-
import junit.framework.TestCase;
import org.apache.commons.configuration.ConfigurationException;
@@ -37,19 +35,22 @@ import org.apache.qpid.server.security.access.Operation;
import org.apache.qpid.server.security.access.Permission;
import org.apache.qpid.server.security.access.config.Rule;
import org.apache.qpid.server.security.access.config.RuleSet;
-import org.apache.qpid.server.security.auth.sasl.TestPrincipalUtils;
+import org.apache.qpid.server.security.auth.TestPrincipalUtils;
/**
- * Unit test for ACL V2 plugin.
- *
+ * Unit test for ACL V2 plugin.
+ *
* This unit test tests the AccessControl class and it collaboration with {@link RuleSet},
* {@link SecurityManager} and {@link CurrentActor}. The ruleset is configured programmatically,
* rather than from an external file.
- *
+ *
* @see RuleSetTest
*/
public class AccessControlTest extends TestCase
{
+ private static final String ALLOWED_GROUP = "allowed_group";
+ private static final String DENIED_GROUP = "denied_group";
+
private AccessControl _plugin = null; // Class under test
private final UnitTestMessageLogger messageLogger = new UnitTestMessageLogger();
@@ -68,14 +69,12 @@ public class AccessControlTest extends TestCase
private RuleSet createGroupRuleSet()
{
final RuleSet rs = new RuleSet();
- rs.addGroup("aclGroup1", Arrays.asList(new String[] {"member1", "Member2"}));
// Rule expressed with username
rs.grant(0, "user1", Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
- // Rule expressed with a acl group
- rs.grant(1, "aclGroup1", Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
- // Rule expressed with an external group
- rs.grant(2, "extGroup1", Permission.DENY, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
+ // Rules expressed with groups
+ rs.grant(1, ALLOWED_GROUP, Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
+ rs.grant(2, DENIED_GROUP, Permission.DENY, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
// Catch all rule
rs.grant(3, Rule.ALL, Permission.DENY_LOG, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
@@ -117,31 +116,23 @@ public class AccessControlTest extends TestCase
* Tests that an allow rule expressed with an <b>ACL groupname</b> allows an operation performed by a thread running
* by a user who belongs to the same group..
*/
- public void testAclGroupMembershipAllowsOperation() throws ConfigurationException
+ public void testGroupMembershipAllowsOperation() throws ConfigurationException
{
setUpGroupAccessControl();
- SecurityManager.setThreadSubject(TestPrincipalUtils.createTestSubject("member1"));
- Result result = _plugin.authorise(Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
- assertEquals(Result.ALLOWED, result);
-
- SecurityManager.setThreadSubject(TestPrincipalUtils.createTestSubject("Member2"));
-
- result = _plugin.authorise(Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
- assertEquals(Result.ALLOWED, result);
+ authoriseAndAssertResult(Result.ALLOWED, "member of allowed group", ALLOWED_GROUP);
+ authoriseAndAssertResult(Result.DENIED, "member of denied group", DENIED_GROUP);
+ authoriseAndAssertResult(Result.ALLOWED, "another member of allowed group", ALLOWED_GROUP);
}
/**
- * Tests that a deny rule expressed with an <b>External groupname</b> denies an operation performed by a thread running
+ * Tests that a deny rule expressed with a <b>groupname</b> denies an operation performed by a thread running
* by a user who belongs to the same group.
*/
- public void testExternalGroupMembershipDeniesOperation() throws ConfigurationException
+ public void testGroupMembershipDeniesOperation() throws ConfigurationException
{
setUpGroupAccessControl();
- SecurityManager.setThreadSubject(TestPrincipalUtils.createTestSubject("user3", "extGroup1"));
-
- final Result result = _plugin.authorise(Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
- assertEquals(Result.DENIED, result);
+ authoriseAndAssertResult(Result.DENIED, "user3", DENIED_GROUP);
}
/**
@@ -325,6 +316,14 @@ public class AccessControlTest extends TestCase
assertEquals(Result.DEFER, result);
}
+ private void authoriseAndAssertResult(Result expectedResult, String userName, String... groups)
+ {
+ SecurityManager.setThreadSubject(TestPrincipalUtils.createTestSubject(userName, groups));
+
+ Result result = _plugin.authorise(Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
+ assertEquals(expectedResult, result);
+ }
+
/**
* Creates a configuration plugin for the {@link AccessControl} plugin.
*/
diff --git a/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/PlainConfigurationTest.java b/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/PlainConfigurationTest.java
index c2282694fb..be4962615c 100644
--- a/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/PlainConfigurationTest.java
+++ b/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/PlainConfigurationTest.java
@@ -108,19 +108,6 @@ public class PlainConfigurationTest extends TestCase
}
}
- public void testACLFileSyntaxNotEnoughGroup() throws Exception
- {
- try
- {
- writeACLConfig("GROUP blah");
- fail("fail");
- }
- catch (ConfigurationException ce)
- {
- assertEquals(String.format(PlainConfiguration.NOT_ENOUGH_GROUP_MSG, 1), ce.getMessage());
- }
- }
-
public void testACLFileSyntaxNotEnoughACL() throws Exception
{
try
@@ -391,4 +378,77 @@ public class PlainConfigurationTest extends TestCase
assertEquals("Rule has unexpected object properties", ObjectProperties.EMPTY, rule.getAction().getProperties());
}
+ public void testUserRuleParsing() throws Exception
+ {
+ validateRule(writeACLConfig("ACL ALLOW user1 CREATE USER"),
+ "user1", Operation.CREATE, ObjectType.USER, ObjectProperties.EMPTY);
+ validateRule(writeACLConfig("ACL ALLOW user1 CREATE USER name=\"otherUser\""),
+ "user1", Operation.CREATE, ObjectType.USER, new ObjectProperties("otherUser"));
+
+ validateRule(writeACLConfig("ACL ALLOW user1 DELETE USER"),
+ "user1", Operation.DELETE, ObjectType.USER, ObjectProperties.EMPTY);
+ validateRule(writeACLConfig("ACL ALLOW user1 DELETE USER name=\"otherUser\""),
+ "user1", Operation.DELETE, ObjectType.USER, new ObjectProperties("otherUser"));
+
+ validateRule(writeACLConfig("ACL ALLOW user1 UPDATE USER"),
+ "user1", Operation.UPDATE, ObjectType.USER, ObjectProperties.EMPTY);
+ validateRule(writeACLConfig("ACL ALLOW user1 UPDATE USER name=\"otherUser\""),
+ "user1", Operation.UPDATE, ObjectType.USER, new ObjectProperties("otherUser"));
+
+ validateRule(writeACLConfig("ACL ALLOW user1 ALL USER"),
+ "user1", Operation.ALL, ObjectType.USER, ObjectProperties.EMPTY);
+ validateRule(writeACLConfig("ACL ALLOW user1 ALL USER name=\"otherUser\""),
+ "user1", Operation.ALL, ObjectType.USER, new ObjectProperties("otherUser"));
+ }
+
+ public void testGroupRuleParsing() throws Exception
+ {
+ validateRule(writeACLConfig("ACL ALLOW user1 CREATE GROUP"),
+ "user1", Operation.CREATE, ObjectType.GROUP, ObjectProperties.EMPTY);
+ validateRule(writeACLConfig("ACL ALLOW user1 CREATE GROUP name=\"groupName\""),
+ "user1", Operation.CREATE, ObjectType.GROUP, new ObjectProperties("groupName"));
+
+ validateRule(writeACLConfig("ACL ALLOW user1 DELETE GROUP"),
+ "user1", Operation.DELETE, ObjectType.GROUP, ObjectProperties.EMPTY);
+ validateRule(writeACLConfig("ACL ALLOW user1 DELETE GROUP name=\"groupName\""),
+ "user1", Operation.DELETE, ObjectType.GROUP, new ObjectProperties("groupName"));
+
+ validateRule(writeACLConfig("ACL ALLOW user1 UPDATE GROUP"),
+ "user1", Operation.UPDATE, ObjectType.GROUP, ObjectProperties.EMPTY);
+ validateRule(writeACLConfig("ACL ALLOW user1 UPDATE GROUP name=\"groupName\""),
+ "user1", Operation.UPDATE, ObjectType.GROUP, new ObjectProperties("groupName"));
+
+ validateRule(writeACLConfig("ACL ALLOW user1 ALL GROUP"),
+ "user1", Operation.ALL, ObjectType.GROUP, ObjectProperties.EMPTY);
+ validateRule(writeACLConfig("ACL ALLOW user1 ALL GROUP name=\"groupName\""),
+ "user1", Operation.ALL, ObjectType.GROUP, new ObjectProperties("groupName"));
+ }
+
+ /** explicitly test for exception indicating that this functionality has been moved to Group Providers */
+ public void testGroupDefinitionThrowsException() throws Exception
+ {
+ try
+ {
+ writeACLConfig("GROUP group1 bob alice");
+ fail("Expected exception not thrown");
+ }
+ catch(ConfigurationException e)
+ {
+ assertTrue(e.getMessage().contains("GROUP keyword not supported"));
+ }
+ }
+
+ private void validateRule(final PlainConfiguration config, String username, Operation operation, ObjectType objectType, ObjectProperties objectProperties)
+ {
+ final RuleSet rs = config.getConfiguration();
+ assertEquals(1, rs.getRuleCount());
+
+ final Map<Integer, Rule> rules = rs.getAllRules();
+ assertEquals(1, rules.size());
+ final Rule rule = rules.get(0);
+ assertEquals("Rule has unexpected identity", username, rule.getIdentity());
+ assertEquals("Rule has unexpected operation", operation, rule.getAction().getOperation());
+ assertEquals("Rule has unexpected operation", objectType, rule.getAction().getObjectType());
+ assertEquals("Rule has unexpected object properties", objectProperties, rule.getAction().getProperties());
+ }
}
diff --git a/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/RuleSetTest.java b/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/RuleSetTest.java
index f7cc60543d..181d693614 100644
--- a/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/RuleSetTest.java
+++ b/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/RuleSetTest.java
@@ -22,7 +22,6 @@
package org.apache.qpid.server.security.access.plugins;
import java.security.Principal;
-import java.util.Arrays;
import javax.security.auth.Subject;
@@ -34,8 +33,7 @@ import org.apache.qpid.server.security.access.Operation;
import org.apache.qpid.server.security.access.Permission;
import org.apache.qpid.server.security.access.config.Rule;
import org.apache.qpid.server.security.access.config.RuleSet;
-import org.apache.qpid.server.security.auth.sasl.TestPrincipalUtils;
-import org.apache.qpid.server.security.auth.sasl.UsernamePrincipal;
+import org.apache.qpid.server.security.auth.TestPrincipalUtils;
import org.apache.qpid.test.utils.QpidTestCase;
/**
@@ -46,10 +44,7 @@ import org.apache.qpid.test.utils.QpidTestCase;
* access control mechanism is validated by checking whether operations would be authorised by calling the
* {@link RuleSet#check(Principal, Operation, ObjectType, ObjectProperties)} method.
*
- * It ensure that permissions can be granted correctly on users directly, ACL groups (that is those
- * groups declared directly in the ACL itself), and External groups (that is a group from an External
- * Authentication Provider, such as an LDAP).
-
+ * It ensure that permissions can be granted correctly on users directly and on groups.
*/
public class RuleSetTest extends QpidTestCase
{
@@ -316,63 +311,36 @@ public class RuleSetTest extends QpidTestCase
assertEquals(Result.ALLOWED, _ruleSet.check(TestPrincipalUtils.createTestSubject("userb"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY));
}
- /**
- * Tests support for ACL groups (i.e. inline groups declared in the ACL file itself).
- */
- public void testAclGroupsSupported()
+ public void testGroupsSupported()
{
- assertTrue(_ruleSet.addGroup("aclgroup", Arrays.asList(new String[] {"usera", "userb"})));
-
- _ruleSet.grant(1, "aclgroup", Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
- assertEquals(1, _ruleSet.getRuleCount());
-
- assertEquals(Result.ALLOWED, _ruleSet.check(TestPrincipalUtils.createTestSubject("usera"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY));
- assertEquals(Result.ALLOWED, _ruleSet.check(TestPrincipalUtils.createTestSubject("userb"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY));
- assertEquals(Result.DEFER, _ruleSet.check(TestPrincipalUtils.createTestSubject("userc"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY));
- }
-
- /**
- * Tests support for nested ACL groups.
- */
- public void testNestedAclGroupsSupported()
- {
- assertTrue(_ruleSet.addGroup("aclgroup1", Arrays.asList(new String[] {"userb"})));
- assertTrue(_ruleSet.addGroup("aclgroup2", Arrays.asList(new String[] {"usera", "aclgroup1"})));
-
- _ruleSet.grant(1, "aclgroup2", Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
- assertEquals(1, _ruleSet.getRuleCount());
+ String allowGroup = "allowGroup";
+ String deniedGroup = "deniedGroup";
- assertEquals(Result.ALLOWED, _ruleSet.check(TestPrincipalUtils.createTestSubject("usera"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY));
- assertEquals(Result.ALLOWED, _ruleSet.check(TestPrincipalUtils.createTestSubject("userb"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY));
- }
+ _ruleSet.grant(1, allowGroup, Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
+ _ruleSet.grant(2, deniedGroup, Permission.DENY, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
- /**
- * Tests support for nested External groups (i.e. those groups coming from an external source such as an LDAP).
- */
- public void testExternalGroupsSupported()
- {
- _ruleSet.grant(1, "extgroup1", Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
- _ruleSet.grant(2, "extgroup2", Permission.DENY, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
assertEquals(2, _ruleSet.getRuleCount());
- assertEquals(Result.ALLOWED, _ruleSet.check(TestPrincipalUtils.createTestSubject("usera", "extgroup1"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY));
- assertEquals(Result.DENIED, _ruleSet.check(TestPrincipalUtils.createTestSubject("userb", "extgroup2"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY));
+ assertEquals(Result.ALLOWED, _ruleSet.check(TestPrincipalUtils.createTestSubject("usera", allowGroup),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY));
+ assertEquals(Result.DENIED, _ruleSet.check(TestPrincipalUtils.createTestSubject("userb", deniedGroup),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY));
+ assertEquals(Result.DEFER, _ruleSet.check(TestPrincipalUtils.createTestSubject("user", "group not mentioned in acl"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY));
}
/**
* Rule order in the ACL determines the outcome of the check. This test ensures that a user who is
- * granted explicit permission on an object, is granted that access even although late a group
+ * granted explicit permission on an object, is granted that access even though a group
* to which the user belongs is later denied the permission.
*/
public void testAllowDeterminedByRuleOrder()
{
- assertTrue(_ruleSet.addGroup("aclgroup", Arrays.asList(new String[] {"usera"})));
+ String group = "group";
+ String user = "user";
- _ruleSet.grant(1, "usera", Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
- _ruleSet.grant(2, "aclgroup", Permission.DENY, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
+ _ruleSet.grant(1, user, Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
+ _ruleSet.grant(2, group, Permission.DENY, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
assertEquals(2, _ruleSet.getRuleCount());
- assertEquals(Result.ALLOWED, _ruleSet.check(TestPrincipalUtils.createTestSubject("usera"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY));
+ assertEquals(Result.ALLOWED, _ruleSet.check(TestPrincipalUtils.createTestSubject(user, group),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY));
}
/**
@@ -381,13 +349,33 @@ public class RuleSetTest extends QpidTestCase
*/
public void testDenyDeterminedByRuleOrder()
{
- assertTrue(_ruleSet.addGroup("aclgroup", Arrays.asList(new String[] {"usera"})));
+ String group = "aclgroup";
+ String user = "usera";
- _ruleSet.grant(1, "aclgroup", Permission.DENY, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
- _ruleSet.grant(2, "usera", Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
+ _ruleSet.grant(1, group, Permission.DENY, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
+ _ruleSet.grant(2, user, Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
assertEquals(2, _ruleSet.getRuleCount());
- assertEquals(Result.DENIED, _ruleSet.check(TestPrincipalUtils.createTestSubject("usera"),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY));
+ assertEquals(Result.DENIED, _ruleSet.check(TestPrincipalUtils.createTestSubject(user, group),Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY));
+ }
+
+ public void testUserInMultipleGroups()
+ {
+ String allowedGroup = "group1";
+ String deniedGroup = "group2";
+
+ _ruleSet.grant(1, allowedGroup, Permission.ALLOW, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
+ _ruleSet.grant(2, deniedGroup, Permission.DENY, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY);
+
+ Subject subjectInBothGroups = TestPrincipalUtils.createTestSubject("user", allowedGroup, deniedGroup);
+ Subject subjectInDeniedGroupAndOneOther = TestPrincipalUtils.createTestSubject("user", deniedGroup, "some other group");
+ Subject subjectInAllowedGroupAndOneOther = TestPrincipalUtils.createTestSubject("user", allowedGroup, "some other group");
+
+ assertEquals(Result.ALLOWED, _ruleSet.check(subjectInBothGroups,Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY));
+
+ assertEquals(Result.DENIED, _ruleSet.check(subjectInDeniedGroupAndOneOther,Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY));
+
+ assertEquals(Result.ALLOWED, _ruleSet.check(subjectInAllowedGroupAndOneOther,Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY));
}
}