From 65cba5397294ddd5349bdb9837c4a10d91f2ca0b Mon Sep 17 00:00:00 2001 From: Robert Gemmell Date: Fri, 12 Oct 2012 11:44:13 +0000 Subject: QPID-4335, QPID-4353: Refactored broker plugins to use simplified ServiceLoader-based model rather than embedding Felix to use OSGi. Removed the ability to reload security configuration because this feature is not very useful in its current form and was making our code hard to refactor. Modified all tests to use jars rather than classes. This makes them closer to real-world deployments, e.g. the META-INF/services file is read from within the jar. Also moved various system tests from their respective modules into "systests". This removes the need for most modules to depend on systests, thus simplifying our dependency graph. Applied patch from myself, Keith Wall and Phil Harvey git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1397519 13f79535-47bb-0310-9956-ffa450edef68 --- .../java/broker-plugins/access-control/MANIFEST.MF | 41 --- qpid/java/broker-plugins/access-control/build.xml | 4 +- .../security/access/plugins/AccessControl.java | 144 -------- .../access/plugins/AccessControlActivator.java | 41 --- .../access/plugins/AccessControlConfiguration.java | 83 ----- .../access/plugins/DefaultAccessControl.java | 122 +++++++ .../plugins/DefaultAccessControlFactory.java | 47 +++ ....apache.qpid.server.plugin.AccessControlFactory | 1 + .../security/access/plugins/AccessControlTest.java | 404 --------------------- .../access/plugins/DefaultAccessControlTest.java | 368 +++++++++++++++++++ 10 files changed, 539 insertions(+), 716 deletions(-) delete mode 100644 qpid/java/broker-plugins/access-control/MANIFEST.MF delete mode 100644 qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControl.java delete mode 100644 qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControlActivator.java delete mode 100644 qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControlConfiguration.java create mode 100644 qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControl.java create mode 100644 qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlFactory.java create mode 100644 qpid/java/broker-plugins/access-control/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.AccessControlFactory delete mode 100644 qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/AccessControlTest.java create mode 100644 qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlTest.java (limited to 'qpid/java/broker-plugins/access-control') diff --git a/qpid/java/broker-plugins/access-control/MANIFEST.MF b/qpid/java/broker-plugins/access-control/MANIFEST.MF deleted file mode 100644 index a8fb99995e..0000000000 --- a/qpid/java/broker-plugins/access-control/MANIFEST.MF +++ /dev/null @@ -1,41 +0,0 @@ -Manifest-Version: 1.0 -Bundle-ManifestVersion: 2 -Bundle-Name: Qpid Broker-Plugins Access Control -Bundle-SymbolicName: broker-plugins-access-control -Bundle-Description: Access control plugin for Qpid. -Bundle-License: http://www.apache.org/licenses/LICENSE-2.0.txt -Bundle-DocURL: http://qpid.apache.org/acl.html -Bundle-Version: 1.0.0 -Bundle-Activator: org.apache.qpid.server.security.access.plugins.AccessControlActivator -Bundle-RequiredExecutionEnvironment: JavaSE-1.5 -Bundle-ClassPath: . -Bundle-ActivationPolicy: lazy -Import-Package: org.apache.qpid, - org.apache.qpid.exchange, - org.apache.qpid.framing, - org.apache.qpid.protocol, - org.apache.qpid.server.configuration, - org.apache.qpid.server.configuration.plugins, - org.apache.qpid.server.exchange, - org.apache.qpid.server.logging, - org.apache.qpid.server.logging.actors, - org.apache.qpid.server.logging.subjects, - org.apache.qpid.server.plugins, - org.apache.qpid.server.queue, - org.apache.qpid.server.registry, - org.apache.qpid.server.security, - org.apache.qpid.server.security.access, - org.apache.qpid.server.virtualhost, - org.apache.qpid.util, - org.apache.commons.configuration;version=1.0.0, - org.apache.commons.lang;version=1.0.0, - org.apache.commons.lang.builder;version=1.0.0, - org.apache.log4j;version=1.0.0, - javax.management;version=1.0.0, - javax.management.openmbean;version=1.0.0, - javax.security.auth;version=1.0.0, - org.osgi.util.tracker;version=1.0.0, - org.osgi.framework;version=1.3 -Private-Package: org.apache.qpid.server.security.access.config, - org.apache.qpid.server.security.access.logging -Export-Package: org.apache.qpid.server.security.access.plugins diff --git a/qpid/java/broker-plugins/access-control/build.xml b/qpid/java/broker-plugins/access-control/build.xml index df3346788c..193eac4d3d 100644 --- a/qpid/java/broker-plugins/access-control/build.xml +++ b/qpid/java/broker-plugins/access-control/build.xml @@ -18,10 +18,8 @@ --> - + - - 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 deleted file mode 100644 index d94948237f..0000000000 --- a/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControl.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * - * 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 - * regarding copyright ownership. The ASF licenses this file - * 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.plugins; - -import java.net.InetAddress; -import java.net.InetSocketAddress; - -import javax.security.auth.Subject; - -import org.apache.commons.configuration.ConfigurationException; -import org.apache.commons.lang.ObjectUtils; -import org.apache.log4j.Logger; -import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; -import org.apache.qpid.server.security.AbstractPlugin; -import org.apache.qpid.server.security.Result; -import org.apache.qpid.server.security.SecurityManager; -import org.apache.qpid.server.security.SecurityPluginFactory; -import org.apache.qpid.server.security.access.ObjectProperties; -import org.apache.qpid.server.security.access.ObjectType; -import org.apache.qpid.server.security.access.Operation; -import org.apache.qpid.server.security.access.config.RuleSet; - -/** - * This access control plugin implements version two plain text access control. - */ -public class AccessControl extends AbstractPlugin -{ - private static final Logger _logger = Logger.getLogger(AccessControl.class); - - private RuleSet _ruleSet; - - public static final SecurityPluginFactory FACTORY = new SecurityPluginFactory() - { - public Class getPluginClass() - { - return AccessControl.class; - } - - public String getPluginName() - { - return AccessControl.class.getName(); - } - - public AccessControl newInstance(ConfigurationPlugin config) throws ConfigurationException - { - AccessControlConfiguration configuration = config.getConfiguration(AccessControlConfiguration.class.getName()); - - // If there is no configuration for this plugin then don't load it. - if (configuration == null) - { - return null; - } - - AccessControl plugin = new AccessControl(); - plugin.configure(configuration); - return plugin; - } - }; - - public Result getDefault() - { - return _ruleSet.getDefault(); - } - - /** - * Object instance access authorisation. - * - * Delegate to the {@link #authorise(Operation, ObjectType, ObjectProperties)} method, with - * the operation set to ACCESS and no object properties. - */ - public Result access(ObjectType objectType, Object inetSocketAddress) - { - InetAddress addressOfClient = null; - - if(inetSocketAddress != null) - { - addressOfClient = ((InetSocketAddress) inetSocketAddress).getAddress(); - } - - return authoriseFromAddress(Operation.ACCESS, objectType, ObjectProperties.EMPTY, addressOfClient); - } - - /** - * 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 - * user the plugin will abstain. - */ - public Result authorise(Operation operation, ObjectType objectType, ObjectProperties properties) - { - return authoriseFromAddress(operation, objectType, properties, null); - } - - public Result authoriseFromAddress(Operation operation, ObjectType objectType, ObjectProperties properties, InetAddress addressOfClient) - { - final Subject subject = SecurityManager.getThreadSubject(); - // Abstain if there is no subject/principal associated with this thread - if (subject == null || subject.getPrincipals().size() == 0) - { - return Result.ABSTAIN; - } - - if(_logger.isDebugEnabled()) - { - _logger.debug("Checking " + operation + " " + objectType + " " + ObjectUtils.defaultIfNull(addressOfClient, "")); - } - - try - { - return _ruleSet.check(subject, operation, objectType, properties, addressOfClient); - } - catch(Exception e) - { - _logger.error("Unable to check " + operation + " " + objectType + " " + ObjectUtils.defaultIfNull(addressOfClient, ""), e); - return Result.DENIED; - } - } - - public void configure(ConfigurationPlugin config) - { - super.configure(config); - - AccessControlConfiguration accessConfig = (AccessControlConfiguration) getConfig(); - - _ruleSet = accessConfig.getRuleSet(); - } -} diff --git a/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControlActivator.java b/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControlActivator.java deleted file mode 100644 index 7c83446cf1..0000000000 --- a/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControlActivator.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * - * 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 - * regarding copyright ownership. The ASF licenses this file - * 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.plugins; - -import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory; -import org.apache.qpid.server.security.SecurityPluginActivator; -import org.apache.qpid.server.security.SecurityPluginFactory; - -/** - * The OSGi {@link org.osgi.framework.BundleActivator} for {@link AccessControl}. - */ -public class AccessControlActivator extends SecurityPluginActivator -{ - public SecurityPluginFactory getFactory() - { - return AccessControl.FACTORY; - } - - public ConfigurationPluginFactory getConfigurationFactory() - { - return AccessControlConfiguration.FACTORY; - } -} 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 deleted file mode 100644 index 63f7e254ae..0000000000 --- a/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/AccessControlConfiguration.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * - * 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 - * regarding copyright ownership. The ASF licenses this file - * 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.plugins; - -import java.io.File; -import java.util.Arrays; -import java.util.List; - -import org.apache.commons.configuration.Configuration; -import org.apache.commons.configuration.ConfigurationException; -import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; -import org.apache.qpid.server.configuration.plugins.ConfigurationPluginFactory; -import org.apache.qpid.server.security.access.config.ConfigurationFile; -import org.apache.qpid.server.security.access.config.PlainConfiguration; -import org.apache.qpid.server.security.access.config.RuleSet; - -public class AccessControlConfiguration extends ConfigurationPlugin -{ - public static final ConfigurationPluginFactory FACTORY = new ConfigurationPluginFactory() - { - public ConfigurationPlugin newInstance(String path, Configuration config) throws ConfigurationException - { - ConfigurationPlugin instance = new AccessControlConfiguration(); - instance.setConfiguration(path, config); - return instance; - } - - public List getParentPaths() - { - return Arrays.asList("security.acl", "virtualhosts.virtualhost.security.acl"); - } - }; - - private RuleSet _ruleSet; - - public String[] getElementsProcessed() - { - return new String[] { "" }; - } - - public String getFileName() - { - return getConfig().getString(""); - } - - public void validateConfiguration() throws ConfigurationException - { - String filename = getFileName(); - if (filename == null) - { - throw new ConfigurationException("No ACL file name specified"); - } - - File aclFile = new File(filename); - - ConfigurationFile configFile = new PlainConfiguration(aclFile); - _ruleSet = configFile.load(); - } - - public RuleSet getRuleSet() - { - return _ruleSet; - } - -} diff --git a/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControl.java b/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControl.java new file mode 100644 index 0000000000..19b9135ea6 --- /dev/null +++ b/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControl.java @@ -0,0 +1,122 @@ +/* + * + * 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 + * regarding copyright ownership. The ASF licenses this file + * 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.plugins; + +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.io.File; + +import javax.security.auth.Subject; + +import org.apache.commons.configuration.ConfigurationException; +import org.apache.commons.lang.ObjectUtils; +import org.apache.log4j.Logger; +import org.apache.qpid.server.security.Result; +import org.apache.qpid.server.security.SecurityManager; +import org.apache.qpid.server.security.AccessControl; +import org.apache.qpid.server.security.access.ObjectProperties; +import org.apache.qpid.server.security.access.ObjectType; +import org.apache.qpid.server.security.access.Operation; +import org.apache.qpid.server.security.access.config.ConfigurationFile; +import org.apache.qpid.server.security.access.config.PlainConfiguration; +import org.apache.qpid.server.security.access.config.RuleSet; + +public class DefaultAccessControl implements AccessControl +{ + private static final Logger _logger = Logger.getLogger(DefaultAccessControl.class); + + private RuleSet _ruleSet; + + public DefaultAccessControl(String fileName) throws ConfigurationException + { + if (_logger.isDebugEnabled()) + { + _logger.debug("Creating AccessControl instance using file: " + fileName); + } + File aclFile = new File(fileName); + + ConfigurationFile configFile = new PlainConfiguration(aclFile); + _ruleSet = configFile.load(); + } + + DefaultAccessControl(RuleSet rs) throws ConfigurationException + { + _ruleSet = rs; + } + + public Result getDefault() + { + return _ruleSet.getDefault(); + } + + /** + * Object instance access authorisation. + * + * Delegate to the {@link #authorise(Operation, ObjectType, ObjectProperties)} method, with + * the operation set to ACCESS and no object properties. + */ + public Result access(ObjectType objectType, Object inetSocketAddress) + { + InetAddress addressOfClient = null; + + if(inetSocketAddress != null) + { + addressOfClient = ((InetSocketAddress) inetSocketAddress).getAddress(); + } + + return authoriseFromAddress(Operation.ACCESS, objectType, ObjectProperties.EMPTY, addressOfClient); + } + + /** + * 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 + * user the plugin will abstain. + */ + public Result authorise(Operation operation, ObjectType objectType, ObjectProperties properties) + { + return authoriseFromAddress(operation, objectType, properties, null); + } + + public Result authoriseFromAddress(Operation operation, ObjectType objectType, ObjectProperties properties, InetAddress addressOfClient) + { + final Subject subject = SecurityManager.getThreadSubject(); + // Abstain if there is no subject/principal associated with this thread + if (subject == null || subject.getPrincipals().size() == 0) + { + return Result.ABSTAIN; + } + + if(_logger.isDebugEnabled()) + { + _logger.debug("Checking " + operation + " " + objectType + " " + ObjectUtils.defaultIfNull(addressOfClient, "")); + } + + try + { + return _ruleSet.check(subject, operation, objectType, properties, addressOfClient); + } + catch(Exception e) + { + _logger.error("Unable to check " + operation + " " + objectType + " " + ObjectUtils.defaultIfNull(addressOfClient, ""), e); + return Result.DENIED; + } + } +} diff --git a/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlFactory.java b/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlFactory.java new file mode 100644 index 0000000000..38ea61357e --- /dev/null +++ b/qpid/java/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlFactory.java @@ -0,0 +1,47 @@ +/* + * + * 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 + * regarding copyright ownership. The ASF licenses this file + * 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.plugins; + +import org.apache.commons.configuration.Configuration; +import org.apache.commons.configuration.ConfigurationException; +import org.apache.qpid.server.plugin.AccessControlFactory; +import org.apache.qpid.server.security.AccessControl; + +public class DefaultAccessControlFactory implements AccessControlFactory +{ + public AccessControl createInstance(Configuration securityConfiguration) + { + String aclConfiguration = securityConfiguration.getString("acl"); + if(aclConfiguration == null) + { + return null; + } + + try + { + return new DefaultAccessControl(aclConfiguration); + } + catch (ConfigurationException e) + { + throw new RuntimeException("caught exception during instance creation", e); + } + } +} diff --git a/qpid/java/broker-plugins/access-control/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.AccessControlFactory b/qpid/java/broker-plugins/access-control/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.AccessControlFactory new file mode 100644 index 0000000000..85b942383f --- /dev/null +++ b/qpid/java/broker-plugins/access-control/src/main/resources/META-INF/services/org.apache.qpid.server.plugin.AccessControlFactory @@ -0,0 +1 @@ +org.apache.qpid.server.security.access.plugins.DefaultAccessControlFactory 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 deleted file mode 100644 index a65c442bcf..0000000000 --- a/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/AccessControlTest.java +++ /dev/null @@ -1,404 +0,0 @@ -/* - * - * 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 - * regarding copyright ownership. The ASF licenses this file - * 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.plugins; - -import static org.mockito.Mockito.*; - -import java.net.InetAddress; -import java.net.InetSocketAddress; - -import javax.security.auth.Subject; - -import junit.framework.TestCase; - -import org.apache.commons.configuration.ConfigurationException; -import org.apache.qpid.server.configuration.plugins.ConfigurationPlugin; -import org.apache.qpid.server.logging.UnitTestMessageLogger; -import org.apache.qpid.server.logging.actors.CurrentActor; -import org.apache.qpid.server.logging.actors.TestLogActor; -import org.apache.qpid.server.security.Result; -import org.apache.qpid.server.security.SecurityManager; -import org.apache.qpid.server.security.access.ObjectProperties; -import org.apache.qpid.server.security.access.ObjectType; -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.TestPrincipalUtils; - -/** - * 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(); - - private void setUpGroupAccessControl() throws ConfigurationException - { - configureAccessControl(createGroupRuleSet()); - } - - private void configureAccessControl(final RuleSet rs) throws ConfigurationException - { - _plugin = (AccessControl) AccessControl.FACTORY.newInstance(createConfiguration(rs)); - SecurityManager.setThreadSubject(null); - CurrentActor.set(new TestLogActor(messageLogger)); - } - - private RuleSet createGroupRuleSet() - { - final RuleSet rs = new RuleSet(); - - // Rule expressed with username - rs.grant(0, "user1", Permission.ALLOW, 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); - - return rs; - } - - protected void tearDown() throws Exception - { - super.tearDown(); - SecurityManager.setThreadSubject(null); - } - - /** - * ACL plugin must always abstain if there is no subject attached to the thread. - */ - public void testNoSubjectAlwaysAbstains() throws ConfigurationException - { - setUpGroupAccessControl(); - SecurityManager.setThreadSubject(null); - - final Result result = _plugin.authorise(Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); - assertEquals(Result.ABSTAIN, result); - } - - /** - * Tests that an allow rule expressed with a username allows an operation performed by a thread running - * with the same username. - */ - public void testUsernameAllowsOperation() throws ConfigurationException - { - setUpGroupAccessControl(); - SecurityManager.setThreadSubject(TestPrincipalUtils.createTestSubject("user1")); - - final Result result = _plugin.authorise(Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); - assertEquals(Result.ALLOWED, result); - } - - /** - * Tests that an allow rule expressed with an ACL groupname allows an operation performed by a thread running - * by a user who belongs to the same group.. - */ - public void testGroupMembershipAllowsOperation() throws ConfigurationException - { - setUpGroupAccessControl(); - - 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 a groupname denies an operation performed by a thread running - * by a user who belongs to the same group. - */ - public void testGroupMembershipDeniesOperation() throws ConfigurationException - { - setUpGroupAccessControl(); - authoriseAndAssertResult(Result.DENIED, "user3", DENIED_GROUP); - } - - /** - * Tests that the catch all deny denies the operation and logs with the logging actor. - */ - public void testCatchAllRuleDeniesUnrecognisedUsername() throws ConfigurationException - { - setUpGroupAccessControl(); - SecurityManager.setThreadSubject(TestPrincipalUtils.createTestSubject("unknown", "unkgroup1", "unkgroup2")); - - assertEquals("Expecting zero messages before test", 0, messageLogger.getLogMessages().size()); - final Result result = _plugin.authorise(Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); - assertEquals(Result.DENIED, result); - - assertEquals("Expecting one message before test", 1, messageLogger.getLogMessages().size()); - assertTrue("Logged message does not contain expected string", messageLogger.messageContains(0, "ACL-1002")); - } - - /** - * Tests that a grant access method rule allows any access operation to be performed on any component - */ - public void testAuthoriseAccessMethodWhenAllAccessOperationsAllowedOnAllComponents() throws ConfigurationException - { - final RuleSet rs = new RuleSet(); - - // grant user4 access right on any method in any component - rs.grant(1, "user4", Permission.ALLOW, Operation.ACCESS, ObjectType.METHOD, new ObjectProperties(ObjectProperties.STAR)); - configureAccessControl(rs); - SecurityManager.setThreadSubject(TestPrincipalUtils.createTestSubject("user4")); - - ObjectProperties actionProperties = new ObjectProperties("getName"); - actionProperties.put(ObjectProperties.Property.COMPONENT, "Test"); - - final Result result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, actionProperties); - assertEquals(Result.ALLOWED, result); - } - - /** - * Tests that a grant access method rule allows any access operation to be performed on a specified component - */ - public void testAuthoriseAccessMethodWhenAllAccessOperationsAllowedOnSpecifiedComponent() throws ConfigurationException - { - final RuleSet rs = new RuleSet(); - - // grant user5 access right on any methods in "Test" component - ObjectProperties ruleProperties = new ObjectProperties(ObjectProperties.STAR); - ruleProperties.put(ObjectProperties.Property.COMPONENT, "Test"); - rs.grant(1, "user5", Permission.ALLOW, Operation.ACCESS, ObjectType.METHOD, ruleProperties); - configureAccessControl(rs); - SecurityManager.setThreadSubject(TestPrincipalUtils.createTestSubject("user5")); - - ObjectProperties actionProperties = new ObjectProperties("getName"); - actionProperties.put(ObjectProperties.Property.COMPONENT, "Test"); - Result result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, actionProperties); - assertEquals(Result.ALLOWED, result); - - actionProperties.put(ObjectProperties.Property.COMPONENT, "Test2"); - result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, actionProperties); - assertEquals(Result.DEFER, result); - } - - public void testAccess() throws Exception - { - Subject subject = TestPrincipalUtils.createTestSubject("user1"); - SecurityManager.setThreadSubject(subject); - - RuleSet mockRuleSet = mock(RuleSet.class); - ConfigurationPlugin accessControlConfiguration = createConfiguration(mockRuleSet); - - InetAddress inetAddress = InetAddress.getLocalHost(); - InetSocketAddress inetSocketAddress = new InetSocketAddress(inetAddress, 1); - - AccessControl accessControl = AccessControl.FACTORY.newInstance(accessControlConfiguration); - - accessControl.access(ObjectType.VIRTUALHOST, inetSocketAddress); - - verify(mockRuleSet).check(subject, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY, inetAddress); - } - - public void testAccessIsDeniedIfRuleThrowsException() throws Exception - { - Subject subject = TestPrincipalUtils.createTestSubject("user1"); - SecurityManager.setThreadSubject(subject); - - InetAddress inetAddress = InetAddress.getLocalHost(); - InetSocketAddress inetSocketAddress = new InetSocketAddress(inetAddress, 1); - - RuleSet mockRuleSet = mock(RuleSet.class); - when(mockRuleSet.check( - subject, - Operation.ACCESS, - ObjectType.VIRTUALHOST, - ObjectProperties.EMPTY, - inetAddress)).thenThrow(new RuntimeException()); - - ConfigurationPlugin accessControlConfiguration = createConfiguration(mockRuleSet); - - AccessControl accessControl = AccessControl.FACTORY.newInstance(accessControlConfiguration); - Result result = accessControl.access(ObjectType.VIRTUALHOST, inetSocketAddress); - - assertEquals(Result.DENIED, result); - } - - - /** - * Tests that a grant access method rule allows any access operation to be performed on a specified component - */ - public void testAuthoriseAccessMethodWhenSpecifiedAccessOperationsAllowedOnSpecifiedComponent() throws ConfigurationException - { - final RuleSet rs = new RuleSet(); - - // grant user6 access right on "getAttribute" method in "Test" component - ObjectProperties ruleProperties = new ObjectProperties("getAttribute"); - ruleProperties.put(ObjectProperties.Property.COMPONENT, "Test"); - rs.grant(1, "user6", Permission.ALLOW, Operation.ACCESS, ObjectType.METHOD, ruleProperties); - configureAccessControl(rs); - SecurityManager.setThreadSubject(TestPrincipalUtils.createTestSubject("user6")); - - ObjectProperties properties = new ObjectProperties("getAttribute"); - properties.put(ObjectProperties.Property.COMPONENT, "Test"); - Result result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, properties); - assertEquals(Result.ALLOWED, result); - - properties.put(ObjectProperties.Property.COMPONENT, "Test2"); - result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, properties); - assertEquals(Result.DEFER, result); - - properties = new ObjectProperties("getAttribute2"); - properties.put(ObjectProperties.Property.COMPONENT, "Test"); - result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, properties); - assertEquals(Result.DEFER, result); - } - - /** - * Tests that granting of all method rights on a method allows a specified operation to be performed on any component - */ - public void testAuthoriseAccessUpdateMethodWhenAllRightsGrantedOnSpecifiedMethodForAllComponents() throws ConfigurationException - { - final RuleSet rs = new RuleSet(); - - // grant user8 all rights on method queryNames in all component - rs.grant(1, "user8", Permission.ALLOW, Operation.ALL, ObjectType.METHOD, new ObjectProperties("queryNames")); - configureAccessControl(rs); - SecurityManager.setThreadSubject(TestPrincipalUtils.createTestSubject("user8")); - - ObjectProperties properties = new ObjectProperties(); - properties.put(ObjectProperties.Property.COMPONENT, "Test"); - properties.put(ObjectProperties.Property.NAME, "queryNames"); - - Result result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, properties); - assertEquals(Result.ALLOWED, result); - - result = _plugin.authorise(Operation.UPDATE, ObjectType.METHOD, properties); - assertEquals(Result.ALLOWED, result); - - properties = new ObjectProperties("getAttribute"); - properties.put(ObjectProperties.Property.COMPONENT, "Test"); - result = _plugin.authorise(Operation.UPDATE, ObjectType.METHOD, properties); - assertEquals(Result.DEFER, result); - - result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, properties); - assertEquals(Result.DEFER, result); - } - - /** - * Tests that granting of all method rights allows any operation to be performed on any component - */ - public void testAuthoriseAccessUpdateMethodWhenAllRightsGrantedOnAllMethodsInAllComponents() throws ConfigurationException - { - final RuleSet rs = new RuleSet(); - - // grant user9 all rights on any method in all component - rs.grant(1, "user9", Permission.ALLOW, Operation.ALL, ObjectType.METHOD, new ObjectProperties()); - configureAccessControl(rs); - SecurityManager.setThreadSubject(TestPrincipalUtils.createTestSubject("user9")); - - ObjectProperties properties = new ObjectProperties("queryNames"); - properties.put(ObjectProperties.Property.COMPONENT, "Test"); - - Result result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, properties); - assertEquals(Result.ALLOWED, result); - - result = _plugin.authorise(Operation.UPDATE, ObjectType.METHOD, properties); - assertEquals(Result.ALLOWED, result); - - properties = new ObjectProperties("getAttribute"); - properties.put(ObjectProperties.Property.COMPONENT, "Test"); - result = _plugin.authorise(Operation.UPDATE, ObjectType.METHOD, properties); - assertEquals(Result.ALLOWED, result); - - result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, properties); - assertEquals(Result.ALLOWED, result); - } - - /** - * Tests that granting of access method rights with mask allows matching operations to be performed on the specified component - */ - public void testAuthoriseAccessMethodWhenMatchingAcessOperationsAllowedOnSpecifiedComponent() throws ConfigurationException - { - final RuleSet rs = new RuleSet(); - - // grant user9 all rights on "getAttribute*" methods in Test component - ObjectProperties ruleProperties = new ObjectProperties(); - ruleProperties.put(ObjectProperties.Property.COMPONENT, "Test"); - ruleProperties.put(ObjectProperties.Property.NAME, "getAttribute*"); - - rs.grant(1, "user9", Permission.ALLOW, Operation.ACCESS, ObjectType.METHOD, ruleProperties); - configureAccessControl(rs); - SecurityManager.setThreadSubject(TestPrincipalUtils.createTestSubject("user9")); - - ObjectProperties properties = new ObjectProperties("getAttributes"); - properties.put(ObjectProperties.Property.COMPONENT, "Test"); - Result result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, properties); - assertEquals(Result.ALLOWED, result); - - properties = new ObjectProperties("getAttribute"); - properties.put(ObjectProperties.Property.COMPONENT, "Test"); - result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, properties); - assertEquals(Result.ALLOWED, result); - - properties = new ObjectProperties("getAttribut"); - properties.put(ObjectProperties.Property.COMPONENT, "Test"); - result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, properties); - 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. - */ - private ConfigurationPlugin createConfiguration(final RuleSet rs) - { - final ConfigurationPlugin cp = new ConfigurationPlugin() - { - @SuppressWarnings("unchecked") - public AccessControlConfiguration getConfiguration(final String plugin) - { - return new AccessControlConfiguration() - { - public RuleSet getRuleSet() - { - return rs; - } - }; - } - - public String[] getElementsProcessed() - { - throw new UnsupportedOperationException(); - } - }; - - return cp; - } -} diff --git a/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlTest.java b/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlTest.java new file mode 100644 index 0000000000..a8406308c0 --- /dev/null +++ b/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlTest.java @@ -0,0 +1,368 @@ +/* + * + * 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 + * regarding copyright ownership. The ASF licenses this file + * 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.plugins; + +import static org.mockito.Mockito.*; + +import java.net.InetAddress; +import java.net.InetSocketAddress; + +import javax.security.auth.Subject; + +import junit.framework.TestCase; + +import org.apache.commons.configuration.ConfigurationException; +import org.apache.qpid.server.logging.UnitTestMessageLogger; +import org.apache.qpid.server.logging.actors.CurrentActor; +import org.apache.qpid.server.logging.actors.TestLogActor; +import org.apache.qpid.server.security.Result; +import org.apache.qpid.server.security.SecurityManager; +import org.apache.qpid.server.security.access.ObjectProperties; +import org.apache.qpid.server.security.access.ObjectType; +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.TestPrincipalUtils; + +/** + * In these tests, the ruleset is configured programmatically rather than from an external file. + * + * @see RuleSetTest + */ +public class DefaultAccessControlTest extends TestCase +{ + private static final String ALLOWED_GROUP = "allowed_group"; + private static final String DENIED_GROUP = "denied_group"; + + private DefaultAccessControl _plugin = null; // Class under test + private final UnitTestMessageLogger messageLogger = new UnitTestMessageLogger(); + + private void setUpGroupAccessControl() throws ConfigurationException + { + configureAccessControl(createGroupRuleSet()); + } + + private void configureAccessControl(final RuleSet rs) throws ConfigurationException + { + _plugin = new DefaultAccessControl(rs); + SecurityManager.setThreadSubject(null); + CurrentActor.set(new TestLogActor(messageLogger)); + } + + private RuleSet createGroupRuleSet() + { + final RuleSet rs = new RuleSet(); + + // Rule expressed with username + rs.grant(0, "user1", Permission.ALLOW, 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); + + return rs; + } + + protected void tearDown() throws Exception + { + super.tearDown(); + SecurityManager.setThreadSubject(null); + } + + /** + * ACL plugin must always abstain if there is no subject attached to the thread. + */ + public void testNoSubjectAlwaysAbstains() throws ConfigurationException + { + setUpGroupAccessControl(); + SecurityManager.setThreadSubject(null); + + final Result result = _plugin.authorise(Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); + assertEquals(Result.ABSTAIN, result); + } + + /** + * Tests that an allow rule expressed with a username allows an operation performed by a thread running + * with the same username. + */ + public void testUsernameAllowsOperation() throws ConfigurationException + { + setUpGroupAccessControl(); + SecurityManager.setThreadSubject(TestPrincipalUtils.createTestSubject("user1")); + + final Result result = _plugin.authorise(Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); + assertEquals(Result.ALLOWED, result); + } + + /** + * Tests that an allow rule expressed with an ACL groupname allows an operation performed by a thread running + * by a user who belongs to the same group.. + */ + public void testGroupMembershipAllowsOperation() throws ConfigurationException + { + setUpGroupAccessControl(); + + 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 a groupname denies an operation performed by a thread running + * by a user who belongs to the same group. + */ + public void testGroupMembershipDeniesOperation() throws ConfigurationException + { + setUpGroupAccessControl(); + authoriseAndAssertResult(Result.DENIED, "user3", DENIED_GROUP); + } + + /** + * Tests that the catch all deny denies the operation and logs with the logging actor. + */ + public void testCatchAllRuleDeniesUnrecognisedUsername() throws ConfigurationException + { + setUpGroupAccessControl(); + SecurityManager.setThreadSubject(TestPrincipalUtils.createTestSubject("unknown", "unkgroup1", "unkgroup2")); + + assertEquals("Expecting zero messages before test", 0, messageLogger.getLogMessages().size()); + final Result result = _plugin.authorise(Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); + assertEquals(Result.DENIED, result); + + assertEquals("Expecting one message before test", 1, messageLogger.getLogMessages().size()); + assertTrue("Logged message does not contain expected string", messageLogger.messageContains(0, "ACL-1002")); + } + + /** + * Tests that a grant access method rule allows any access operation to be performed on any component + */ + public void testAuthoriseAccessMethodWhenAllAccessOperationsAllowedOnAllComponents() throws ConfigurationException + { + final RuleSet rs = new RuleSet(); + + // grant user4 access right on any method in any component + rs.grant(1, "user4", Permission.ALLOW, Operation.ACCESS, ObjectType.METHOD, new ObjectProperties(ObjectProperties.STAR)); + configureAccessControl(rs); + SecurityManager.setThreadSubject(TestPrincipalUtils.createTestSubject("user4")); + + ObjectProperties actionProperties = new ObjectProperties("getName"); + actionProperties.put(ObjectProperties.Property.COMPONENT, "Test"); + + final Result result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, actionProperties); + assertEquals(Result.ALLOWED, result); + } + + /** + * Tests that a grant access method rule allows any access operation to be performed on a specified component + */ + public void testAuthoriseAccessMethodWhenAllAccessOperationsAllowedOnSpecifiedComponent() throws ConfigurationException + { + final RuleSet rs = new RuleSet(); + + // grant user5 access right on any methods in "Test" component + ObjectProperties ruleProperties = new ObjectProperties(ObjectProperties.STAR); + ruleProperties.put(ObjectProperties.Property.COMPONENT, "Test"); + rs.grant(1, "user5", Permission.ALLOW, Operation.ACCESS, ObjectType.METHOD, ruleProperties); + configureAccessControl(rs); + SecurityManager.setThreadSubject(TestPrincipalUtils.createTestSubject("user5")); + + ObjectProperties actionProperties = new ObjectProperties("getName"); + actionProperties.put(ObjectProperties.Property.COMPONENT, "Test"); + Result result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, actionProperties); + assertEquals(Result.ALLOWED, result); + + actionProperties.put(ObjectProperties.Property.COMPONENT, "Test2"); + result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, actionProperties); + assertEquals(Result.DEFER, result); + } + + public void testAccess() throws Exception + { + Subject subject = TestPrincipalUtils.createTestSubject("user1"); + SecurityManager.setThreadSubject(subject); + + RuleSet mockRuleSet = mock(RuleSet.class); + + InetAddress inetAddress = InetAddress.getLocalHost(); + InetSocketAddress inetSocketAddress = new InetSocketAddress(inetAddress, 1); + + DefaultAccessControl accessControl = new DefaultAccessControl(mockRuleSet); + + accessControl.access(ObjectType.VIRTUALHOST, inetSocketAddress); + + verify(mockRuleSet).check(subject, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY, inetAddress); + } + + public void testAccessIsDeniedIfRuleThrowsException() throws Exception + { + Subject subject = TestPrincipalUtils.createTestSubject("user1"); + SecurityManager.setThreadSubject(subject); + + InetAddress inetAddress = InetAddress.getLocalHost(); + InetSocketAddress inetSocketAddress = new InetSocketAddress(inetAddress, 1); + + RuleSet mockRuleSet = mock(RuleSet.class); + when(mockRuleSet.check( + subject, + Operation.ACCESS, + ObjectType.VIRTUALHOST, + ObjectProperties.EMPTY, + inetAddress)).thenThrow(new RuntimeException()); + + DefaultAccessControl accessControl = new DefaultAccessControl(mockRuleSet); + Result result = accessControl.access(ObjectType.VIRTUALHOST, inetSocketAddress); + + assertEquals(Result.DENIED, result); + } + + + /** + * Tests that a grant access method rule allows any access operation to be performed on a specified component + */ + public void testAuthoriseAccessMethodWhenSpecifiedAccessOperationsAllowedOnSpecifiedComponent() throws ConfigurationException + { + final RuleSet rs = new RuleSet(); + + // grant user6 access right on "getAttribute" method in "Test" component + ObjectProperties ruleProperties = new ObjectProperties("getAttribute"); + ruleProperties.put(ObjectProperties.Property.COMPONENT, "Test"); + rs.grant(1, "user6", Permission.ALLOW, Operation.ACCESS, ObjectType.METHOD, ruleProperties); + configureAccessControl(rs); + SecurityManager.setThreadSubject(TestPrincipalUtils.createTestSubject("user6")); + + ObjectProperties properties = new ObjectProperties("getAttribute"); + properties.put(ObjectProperties.Property.COMPONENT, "Test"); + Result result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, properties); + assertEquals(Result.ALLOWED, result); + + properties.put(ObjectProperties.Property.COMPONENT, "Test2"); + result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, properties); + assertEquals(Result.DEFER, result); + + properties = new ObjectProperties("getAttribute2"); + properties.put(ObjectProperties.Property.COMPONENT, "Test"); + result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, properties); + assertEquals(Result.DEFER, result); + } + + /** + * Tests that granting of all method rights on a method allows a specified operation to be performed on any component + */ + public void testAuthoriseAccessUpdateMethodWhenAllRightsGrantedOnSpecifiedMethodForAllComponents() throws ConfigurationException + { + final RuleSet rs = new RuleSet(); + + // grant user8 all rights on method queryNames in all component + rs.grant(1, "user8", Permission.ALLOW, Operation.ALL, ObjectType.METHOD, new ObjectProperties("queryNames")); + configureAccessControl(rs); + SecurityManager.setThreadSubject(TestPrincipalUtils.createTestSubject("user8")); + + ObjectProperties properties = new ObjectProperties(); + properties.put(ObjectProperties.Property.COMPONENT, "Test"); + properties.put(ObjectProperties.Property.NAME, "queryNames"); + + Result result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, properties); + assertEquals(Result.ALLOWED, result); + + result = _plugin.authorise(Operation.UPDATE, ObjectType.METHOD, properties); + assertEquals(Result.ALLOWED, result); + + properties = new ObjectProperties("getAttribute"); + properties.put(ObjectProperties.Property.COMPONENT, "Test"); + result = _plugin.authorise(Operation.UPDATE, ObjectType.METHOD, properties); + assertEquals(Result.DEFER, result); + + result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, properties); + assertEquals(Result.DEFER, result); + } + + /** + * Tests that granting of all method rights allows any operation to be performed on any component + */ + public void testAuthoriseAccessUpdateMethodWhenAllRightsGrantedOnAllMethodsInAllComponents() throws ConfigurationException + { + final RuleSet rs = new RuleSet(); + + // grant user9 all rights on any method in all component + rs.grant(1, "user9", Permission.ALLOW, Operation.ALL, ObjectType.METHOD, new ObjectProperties()); + configureAccessControl(rs); + SecurityManager.setThreadSubject(TestPrincipalUtils.createTestSubject("user9")); + + ObjectProperties properties = new ObjectProperties("queryNames"); + properties.put(ObjectProperties.Property.COMPONENT, "Test"); + + Result result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, properties); + assertEquals(Result.ALLOWED, result); + + result = _plugin.authorise(Operation.UPDATE, ObjectType.METHOD, properties); + assertEquals(Result.ALLOWED, result); + + properties = new ObjectProperties("getAttribute"); + properties.put(ObjectProperties.Property.COMPONENT, "Test"); + result = _plugin.authorise(Operation.UPDATE, ObjectType.METHOD, properties); + assertEquals(Result.ALLOWED, result); + + result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, properties); + assertEquals(Result.ALLOWED, result); + } + + /** + * Tests that granting of access method rights with mask allows matching operations to be performed on the specified component + */ + public void testAuthoriseAccessMethodWhenMatchingAcessOperationsAllowedOnSpecifiedComponent() throws ConfigurationException + { + final RuleSet rs = new RuleSet(); + + // grant user9 all rights on "getAttribute*" methods in Test component + ObjectProperties ruleProperties = new ObjectProperties(); + ruleProperties.put(ObjectProperties.Property.COMPONENT, "Test"); + ruleProperties.put(ObjectProperties.Property.NAME, "getAttribute*"); + + rs.grant(1, "user9", Permission.ALLOW, Operation.ACCESS, ObjectType.METHOD, ruleProperties); + configureAccessControl(rs); + SecurityManager.setThreadSubject(TestPrincipalUtils.createTestSubject("user9")); + + ObjectProperties properties = new ObjectProperties("getAttributes"); + properties.put(ObjectProperties.Property.COMPONENT, "Test"); + Result result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, properties); + assertEquals(Result.ALLOWED, result); + + properties = new ObjectProperties("getAttribute"); + properties.put(ObjectProperties.Property.COMPONENT, "Test"); + result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, properties); + assertEquals(Result.ALLOWED, result); + + properties = new ObjectProperties("getAttribut"); + properties.put(ObjectProperties.Property.COMPONENT, "Test"); + result = _plugin.authorise(Operation.ACCESS, ObjectType.METHOD, properties); + 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); + } +} -- cgit v1.2.1