From 9c73ef7a5ac10acd6a50d5d52bd721fc2faa5919 Mon Sep 17 00:00:00 2001 From: Kim van der Riet Date: Thu, 28 Feb 2013 16:14:30 +0000 Subject: Update from trunk r1375509 through r1450773 git-svn-id: https://svn.apache.org/repos/asf/qpid/branches/asyncstore@1451244 13f79535-47bb-0310-9956-ffa450edef68 --- .../security/access/config/AclActionTest.java | 66 +++ .../access/config/AclRulePredicatesTest.java | 87 ++++ .../server/security/access/config/ActionTest.java | 95 +++++ .../security/access/config/ClientActionTest.java | 79 ++++ .../access/config/PlainConfigurationTest.java | 463 +++++++++++++++++++++ .../server/security/access/config/RuleTest.java | 53 +++ .../access/firewall/HostnameFirewallRuleTest.java | 99 +++++ .../access/firewall/NetworkFirewallRuleTest.java | 115 +++++ .../security/access/plugins/AccessControlTest.java | 355 ---------------- .../plugins/DefaultAccessControlFactoryTest.java | 69 +++ .../access/plugins/DefaultAccessControlTest.java | 368 ++++++++++++++++ .../access/plugins/PlainConfigurationTest.java | 394 ------------------ .../security/access/plugins/RuleSetTest.java | 92 ++-- 13 files changed, 1534 insertions(+), 801 deletions(-) create mode 100644 java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/AclActionTest.java create mode 100644 java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/AclRulePredicatesTest.java create mode 100644 java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/ActionTest.java create mode 100644 java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/ClientActionTest.java create mode 100644 java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/PlainConfigurationTest.java create mode 100644 java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/RuleTest.java create mode 100644 java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/firewall/HostnameFirewallRuleTest.java create mode 100644 java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/firewall/NetworkFirewallRuleTest.java delete mode 100644 java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/AccessControlTest.java create mode 100644 java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlFactoryTest.java create mode 100644 java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlTest.java delete mode 100644 java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/PlainConfigurationTest.java (limited to 'java/broker-plugins/access-control/src/test') diff --git a/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/AclActionTest.java b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/AclActionTest.java new file mode 100644 index 0000000000..14620cff70 --- /dev/null +++ b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/AclActionTest.java @@ -0,0 +1,66 @@ +/* + * 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.config; + +import static org.mockito.Mockito.*; + +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.firewall.FirewallRule; + +import junit.framework.TestCase; + +public class AclActionTest extends TestCase +{ + public void testEqualsAndHashCode() + { + AclRulePredicates predicates = createAclRulePredicates(); + ObjectType objectType = ObjectType.EXCHANGE; + Operation operation = Operation.ACCESS; + + AclAction aclAction = new AclAction(operation, objectType, predicates); + AclAction equalAclAction = new AclAction(operation, objectType, predicates); + + assertTrue(aclAction.equals(aclAction)); + assertTrue(aclAction.equals(equalAclAction)); + assertTrue(equalAclAction.equals(aclAction)); + + assertTrue(aclAction.hashCode() == equalAclAction.hashCode()); + + assertFalse("Different operation should cause aclActions to be unequal", + aclAction.equals(new AclAction(Operation.BIND, objectType, predicates))); + + assertFalse("Different operation type should cause aclActions to be unequal", + aclAction.equals(new AclAction(operation, ObjectType.GROUP, predicates))); + + assertFalse("Different predicates should cause aclActions to be unequal", + aclAction.equals(new AclAction(operation, objectType, createAclRulePredicates()))); + + } + + private AclRulePredicates createAclRulePredicates() + { + AclRulePredicates predicates = mock(AclRulePredicates.class); + when(predicates.getFirewallRule()).thenReturn(mock(FirewallRule.class)); + when(predicates.getObjectProperties()).thenReturn(mock(ObjectProperties.class)); + return predicates; + } + +} diff --git a/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/AclRulePredicatesTest.java b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/AclRulePredicatesTest.java new file mode 100644 index 0000000000..93b765d0fb --- /dev/null +++ b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/AclRulePredicatesTest.java @@ -0,0 +1,87 @@ +/* + * 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.config; + +import static org.apache.qpid.server.security.access.ObjectProperties.Property.*; + +import org.apache.qpid.server.security.access.firewall.FirewallRule; +import org.apache.qpid.server.security.access.firewall.FirewallRuleFactory; + +import static org.mockito.Mockito.*; + +import junit.framework.TestCase; + +public class AclRulePredicatesTest extends TestCase +{ + private AclRulePredicates _aclRulePredicates = new AclRulePredicates(); + private FirewallRuleFactory _firewallRuleFactory = mock(FirewallRuleFactory.class); + + @Override + protected void setUp() throws Exception + { + _aclRulePredicates.setFirewallRuleFactory(_firewallRuleFactory); + + when(_firewallRuleFactory.createForHostname((String[]) any())).thenReturn(mock(FirewallRule.class)); + when(_firewallRuleFactory.createForNetwork((String[]) any())).thenReturn(mock(FirewallRule.class)); + } + + public void testParse() + { + String name = "name"; + String className = "class"; + + _aclRulePredicates.parse(NAME.name(), name); + _aclRulePredicates.parse(CLASS.name(), className); + + assertEquals(name, _aclRulePredicates.getObjectProperties().get(NAME)); + assertEquals(className, _aclRulePredicates.getObjectProperties().get(CLASS)); + } + + public void testParseHostnameFirewallRule() + { + String hostname = "hostname1,hostname2"; + _aclRulePredicates.parse(FROM_HOSTNAME.name(), hostname); + + verify(_firewallRuleFactory).createForHostname(new String[] {"hostname1", "hostname2"}); + } + + public void testParseNetworkFirewallRule() + { + _aclRulePredicates.setFirewallRuleFactory(_firewallRuleFactory); + + String networks = "network1,network2"; + _aclRulePredicates.parse(FROM_NETWORK.name(), networks); + + verify(_firewallRuleFactory).createForNetwork(new String[] {"network1", "network2"}); + } + + public void testParseThrowsExceptionIfBothHostnameAndNetworkSpecified() + { + _aclRulePredicates.parse(FROM_NETWORK.name(), "network1,network2"); + try + { + _aclRulePredicates.parse(FROM_HOSTNAME.name(), "hostname1,hostname2"); + fail("Exception not thrown"); + } + catch(IllegalStateException e) + { + // pass + } + } +} diff --git a/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/ActionTest.java b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/ActionTest.java new file mode 100644 index 0000000000..00e06106bf --- /dev/null +++ b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/ActionTest.java @@ -0,0 +1,95 @@ +/* + * 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.config; + +import static org.mockito.Mockito.*; + +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 junit.framework.TestCase; + +public class ActionTest extends TestCase +{ + private ObjectProperties _properties1 = mock(ObjectProperties.class); + private ObjectProperties _properties2 = mock(ObjectProperties.class); + + public void testMatchesReturnsTrueForMatchingActions() + { + when(_properties1.matches(_properties2)).thenReturn(true); + + assertMatches( + new Action(Operation.CONSUME, ObjectType.QUEUE, _properties1), + new Action(Operation.CONSUME, ObjectType.QUEUE, _properties2)); + } + + public void testMatchesReturnsFalseWhenOperationsDiffer() + { + assertDoesntMatch( + new Action(Operation.CONSUME, ObjectType.QUEUE, _properties1), + new Action(Operation.CREATE, ObjectType.QUEUE, _properties1)); + } + + public void testMatchesReturnsFalseWhenOperationTypesDiffer() + { + assertDoesntMatch( + new Action(Operation.CREATE, ObjectType.QUEUE, _properties1), + new Action(Operation.CREATE, ObjectType.EXCHANGE, _properties1)); + } + + public void testMatchesReturnsFalseWhenOperationPropertiesDiffer() + { + assertDoesntMatch( + new Action(Operation.CREATE, ObjectType.QUEUE, _properties1), + new Action(Operation.CREATE, ObjectType.QUEUE, _properties2)); + } + + public void testMatchesReturnsFalseWhenMyOperationPropertiesIsNull() + { + assertDoesntMatch( + new Action(Operation.CREATE, ObjectType.QUEUE, (ObjectProperties)null), + new Action(Operation.CREATE, ObjectType.QUEUE, _properties1)); + } + + public void testMatchesReturnsFalseWhenOtherOperationPropertiesIsNull() + { + assertDoesntMatch( + new Action(Operation.CREATE, ObjectType.QUEUE, _properties1), + new Action(Operation.CREATE, ObjectType.QUEUE, (ObjectProperties)null)); + } + + public void testMatchesReturnsTrueWhenBothOperationPropertiesAreNull() + { + assertMatches( + new Action(Operation.CREATE, ObjectType.QUEUE, (ObjectProperties)null), + new Action(Operation.CREATE, ObjectType.QUEUE, (ObjectProperties)null)); + } + + private void assertMatches(Action action1, Action action2) + { + assertTrue(action1 + " should match " + action2, action1.matches(action2)); + } + + private void assertDoesntMatch(Action action1, Action action2) + { + assertFalse(action1 + " should not match " + action2, action1.matches(action2)); + } + +} diff --git a/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/ClientActionTest.java b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/ClientActionTest.java new file mode 100644 index 0000000000..ae5d3fda74 --- /dev/null +++ b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/ClientActionTest.java @@ -0,0 +1,79 @@ +/* + * 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.config; + +import static org.mockito.Mockito.*; + +import java.net.InetAddress; + +import org.apache.qpid.server.security.access.firewall.FirewallRule; + +import junit.framework.TestCase; + +public class ClientActionTest extends TestCase +{ + private Action _action = mock(Action.class); + private AclAction _ruleAction = mock(AclAction.class); + private InetAddress _addressOfClient = mock(InetAddress.class); + + private ClientAction _clientAction = new ClientAction(_action); + + public void testMatches_returnsTrueWhenActionsMatchAndNoFirewallRule() + { + when(_action.matches(any(Action.class))).thenReturn(true); + when(_ruleAction.getFirewallRule()).thenReturn(null); + + assertTrue(_clientAction.matches(_ruleAction, _addressOfClient)); + } + + public void testMatches_returnsFalseWhenActionsDontMatch() + { + FirewallRule firewallRule = mock(FirewallRule.class); + when(firewallRule.matches(_addressOfClient)).thenReturn(true); + + when(_action.matches(any(Action.class))).thenReturn(false); + when(_ruleAction.getFirewallRule()).thenReturn(firewallRule); + + assertFalse(_clientAction.matches(_ruleAction, _addressOfClient)); + } + + public void testMatches_returnsTrueWhenActionsAndFirewallRuleMatch() + { + FirewallRule firewallRule = mock(FirewallRule.class); + when(firewallRule.matches(_addressOfClient)).thenReturn(true); + + when(_action.matches(any(Action.class))).thenReturn(true); + when(_ruleAction.getFirewallRule()).thenReturn(firewallRule); + + assertTrue(_clientAction.matches(_ruleAction, _addressOfClient)); + } + + public void testMatches_ignoresFirewallRuleIfClientAddressIsNull() + { + FirewallRule firewallRule = mock(FirewallRule.class); + + when(_action.matches(any(Action.class))).thenReturn(true); + when(_ruleAction.getFirewallRule()).thenReturn(firewallRule); + + assertTrue(_clientAction.matches(_ruleAction, null)); + + verifyZeroInteractions(firewallRule); + } + +} diff --git a/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/PlainConfigurationTest.java b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/PlainConfigurationTest.java new file mode 100644 index 0000000000..cbfc9003c8 --- /dev/null +++ b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/PlainConfigurationTest.java @@ -0,0 +1,463 @@ +/* + * 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.config; + +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileWriter; +import java.io.PrintWriter; +import java.util.Map; + +import junit.framework.TestCase; + +import org.apache.qpid.server.configuration.IllegalConfigurationException; +import org.apache.qpid.server.security.access.ObjectProperties; +import org.apache.qpid.server.security.access.ObjectProperties.Property; +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.Rule; +import org.apache.qpid.server.security.access.config.RuleSet; + +/** + * These tests check that the ACL file parsing works correctly. + * + * For each message that can be returned in a {@link ConfigurationException}, an ACL file is created that should trigger this + * particular message. + */ +public class PlainConfigurationTest extends TestCase +{ + private PlainConfiguration writeACLConfig(String...aclData) throws Exception + { + File acl = File.createTempFile(getClass().getName() + getName(), "acl"); + acl.deleteOnExit(); + + // Write ACL file + PrintWriter aclWriter = new PrintWriter(new FileWriter(acl)); + for (String line : aclData) + { + aclWriter.println(line); + } + aclWriter.close(); + + // Load ruleset + PlainConfiguration configFile = new PlainConfiguration(acl); + configFile.load(); + return configFile; + } + + public void testMissingACLConfig() throws Exception + { + try + { + // Load ruleset + ConfigurationFile configFile = new PlainConfiguration(new File("doesnotexist")); + configFile.load(); + + fail("fail"); + } + catch (IllegalConfigurationException ce) + { + assertEquals(String.format(PlainConfiguration.CONFIG_NOT_FOUND_MSG, "doesnotexist"), ce.getMessage()); + assertTrue(ce.getCause() instanceof FileNotFoundException); + } + } + + public void testACLFileSyntaxContinuation() throws Exception + { + try + { + writeACLConfig("ACL ALLOW ALL \\ ALL"); + fail("fail"); + } + catch (IllegalConfigurationException ce) + { + assertEquals(String.format(PlainConfiguration.PREMATURE_CONTINUATION_MSG, 1), ce.getMessage()); + } + } + + public void testACLFileSyntaxTokens() throws Exception + { + try + { + writeACLConfig("ACL unparsed ALL ALL"); + fail("fail"); + } + catch (IllegalConfigurationException ce) + { + assertEquals(String.format(PlainConfiguration.PARSE_TOKEN_FAILED_MSG, 1), ce.getMessage()); + assertTrue(ce.getCause() instanceof IllegalArgumentException); + assertEquals("Not a valid permission: unparsed", ce.getCause().getMessage()); + } + } + + public void testACLFileSyntaxNotEnoughACL() throws Exception + { + try + { + writeACLConfig("ACL ALLOW"); + fail("fail"); + } + catch (IllegalConfigurationException ce) + { + assertEquals(String.format(PlainConfiguration.NOT_ENOUGH_ACL_MSG, 1), ce.getMessage()); + } + } + + public void testACLFileSyntaxNotEnoughConfig() throws Exception + { + try + { + writeACLConfig("CONFIG"); + fail("fail"); + } + catch (IllegalConfigurationException ce) + { + assertEquals(String.format(PlainConfiguration.NOT_ENOUGH_TOKENS_MSG, 1), ce.getMessage()); + } + } + + public void testACLFileSyntaxNotEnough() throws Exception + { + try + { + writeACLConfig("INVALID"); + fail("fail"); + } + catch (IllegalConfigurationException ce) + { + assertEquals(String.format(PlainConfiguration.NOT_ENOUGH_TOKENS_MSG, 1), ce.getMessage()); + } + } + + public void testACLFileSyntaxPropertyKeyOnly() throws Exception + { + try + { + writeACLConfig("ACL ALLOW adk CREATE QUEUE name"); + fail("fail"); + } + catch (IllegalConfigurationException ce) + { + assertEquals(String.format(PlainConfiguration.PROPERTY_KEY_ONLY_MSG, 1), ce.getMessage()); + } + } + + public void testACLFileSyntaxPropertyNoEquals() throws Exception + { + try + { + writeACLConfig("ACL ALLOW adk CREATE QUEUE name test"); + fail("fail"); + } + catch (IllegalConfigurationException ce) + { + assertEquals(String.format(PlainConfiguration.PROPERTY_NO_EQUALS_MSG, 1), ce.getMessage()); + } + } + + public void testACLFileSyntaxPropertyNoValue() throws Exception + { + try + { + writeACLConfig("ACL ALLOW adk CREATE QUEUE name ="); + fail("fail"); + } + catch (IllegalConfigurationException ce) + { + assertEquals(String.format(PlainConfiguration.PROPERTY_NO_VALUE_MSG, 1), ce.getMessage()); + } + } + + /** + * Tests interpretation of an acl rule with no object properties. + * + */ + public void testValidRule() throws Exception + { + final PlainConfiguration config = writeACLConfig("ACL DENY-LOG user1 ACCESS VIRTUALHOST"); + final RuleSet rs = config.getConfiguration(); + assertEquals(1, rs.getRuleCount()); + + final Map rules = rs.getAllRules(); + assertEquals(1, rules.size()); + final Rule rule = rules.get(0); + assertEquals("Rule has unexpected identity", "user1", rule.getIdentity()); + assertEquals("Rule has unexpected operation", Operation.ACCESS, rule.getAction().getOperation()); + assertEquals("Rule has unexpected operation", ObjectType.VIRTUALHOST, rule.getAction().getObjectType()); + assertEquals("Rule has unexpected object properties", ObjectProperties.EMPTY, rule.getAction().getProperties()); + } + + /** + * Tests interpretation of an acl rule with object properties quoted in single quotes. + */ + public void testValidRuleWithSingleQuotedProperty() throws Exception + { + final PlainConfiguration config = writeACLConfig("ACL ALLOW all CREATE EXCHANGE name = \'value\'"); + final RuleSet rs = config.getConfiguration(); + assertEquals(1, rs.getRuleCount()); + + final Map rules = rs.getAllRules(); + assertEquals(1, rules.size()); + final Rule rule = rules.get(0); + assertEquals("Rule has unexpected identity", "all", rule.getIdentity()); + assertEquals("Rule has unexpected operation", Operation.CREATE, rule.getAction().getOperation()); + assertEquals("Rule has unexpected operation", ObjectType.EXCHANGE, rule.getAction().getObjectType()); + final ObjectProperties expectedProperties = new ObjectProperties(); + expectedProperties.setName("value"); + assertEquals("Rule has unexpected object properties", expectedProperties, rule.getAction().getProperties()); + } + + /** + * Tests interpretation of an acl rule with object properties quoted in double quotes. + */ + public void testValidRuleWithDoubleQuotedProperty() throws Exception + { + final PlainConfiguration config = writeACLConfig("ACL ALLOW all CREATE EXCHANGE name = \"value\""); + final RuleSet rs = config.getConfiguration(); + assertEquals(1, rs.getRuleCount()); + + final Map rules = rs.getAllRules(); + assertEquals(1, rules.size()); + final Rule rule = rules.get(0); + assertEquals("Rule has unexpected identity", "all", rule.getIdentity()); + assertEquals("Rule has unexpected operation", Operation.CREATE, rule.getAction().getOperation()); + assertEquals("Rule has unexpected operation", ObjectType.EXCHANGE, rule.getAction().getObjectType()); + final ObjectProperties expectedProperties = new ObjectProperties(); + expectedProperties.setName("value"); + assertEquals("Rule has unexpected object properties", expectedProperties, rule.getAction().getProperties()); + } + + /** + * Tests interpretation of an acl rule with many object properties. + */ + public void testValidRuleWithManyProperties() throws Exception + { + final PlainConfiguration config = writeACLConfig("ACL ALLOW admin DELETE QUEUE name=name1 owner = owner1"); + final RuleSet rs = config.getConfiguration(); + assertEquals(1, rs.getRuleCount()); + + final Map rules = rs.getAllRules(); + assertEquals(1, rules.size()); + final Rule rule = rules.get(0); + assertEquals("Rule has unexpected identity", "admin", rule.getIdentity()); + assertEquals("Rule has unexpected operation", Operation.DELETE, rule.getAction().getOperation()); + assertEquals("Rule has unexpected operation", ObjectType.QUEUE, rule.getAction().getObjectType()); + final ObjectProperties expectedProperties = new ObjectProperties(); + expectedProperties.setName("name1"); + expectedProperties.put(Property.OWNER, "owner1"); + assertEquals("Rule has unexpected operation", expectedProperties, rule.getAction().getProperties()); + } + + /** + * Tests interpretation of an acl rule with object properties containing wildcards. Values containing + * hashes must be quoted otherwise they are interpreted as comments. + */ + public void testValidRuleWithWildcardProperties() throws Exception + { + final PlainConfiguration config = writeACLConfig("ACL ALLOW all CREATE EXCHANGE routingKey = \'news.#\'", + "ACL ALLOW all CREATE EXCHANGE routingKey = \'news.co.#\'", + "ACL ALLOW all CREATE EXCHANGE routingKey = *.co.medellin"); + final RuleSet rs = config.getConfiguration(); + assertEquals(3, rs.getRuleCount()); + + final Map rules = rs.getAllRules(); + assertEquals(3, rules.size()); + final Rule rule1 = rules.get(0); + assertEquals("Rule has unexpected identity", "all", rule1.getIdentity()); + assertEquals("Rule has unexpected operation", Operation.CREATE, rule1.getAction().getOperation()); + assertEquals("Rule has unexpected operation", ObjectType.EXCHANGE, rule1.getAction().getObjectType()); + final ObjectProperties expectedProperties1 = new ObjectProperties(); + expectedProperties1.put(Property.ROUTING_KEY,"news.#"); + assertEquals("Rule has unexpected object properties", expectedProperties1, rule1.getAction().getProperties()); + + final Rule rule2 = rules.get(10); + final ObjectProperties expectedProperties2 = new ObjectProperties(); + expectedProperties2.put(Property.ROUTING_KEY,"news.co.#"); + assertEquals("Rule has unexpected object properties", expectedProperties2, rule2.getAction().getProperties()); + + final Rule rule3 = rules.get(20); + final ObjectProperties expectedProperties3 = new ObjectProperties(); + expectedProperties3.put(Property.ROUTING_KEY,"*.co.medellin"); + assertEquals("Rule has unexpected object properties", expectedProperties3, rule3.getAction().getProperties()); + } + + /** + * Tests that rules are case insignificant. + */ + public void testMixedCaseRuleInterpretation() throws Exception + { + final PlainConfiguration config = writeACLConfig("AcL deny-LOG User1 BiND Exchange Name=AmQ.dIrect"); + final RuleSet rs = config.getConfiguration(); + assertEquals(1, rs.getRuleCount()); + + final Map rules = rs.getAllRules(); + assertEquals(1, rules.size()); + final Rule rule = rules.get(0); + assertEquals("Rule has unexpected identity", "User1", rule.getIdentity()); + assertEquals("Rule has unexpected operation", Operation.BIND, rule.getAction().getOperation()); + assertEquals("Rule has unexpected operation", ObjectType.EXCHANGE, rule.getAction().getObjectType()); + final ObjectProperties expectedProperties = new ObjectProperties("AmQ.dIrect"); + assertEquals("Rule has unexpected object properties", expectedProperties, rule.getAction().getProperties()); + } + + /** + * Tests whitespace is supported. Note that currently the Java implementation permits comments to + * be introduced anywhere in the ACL, whereas the C++ supports only whitespace at the beginning of + * of line. + */ + public void testCommentsSuppported() throws Exception + { + final PlainConfiguration config = writeACLConfig("#Comment", + "ACL DENY-LOG user1 ACCESS VIRTUALHOST # another comment", + " # final comment with leading whitespace"); + final RuleSet rs = config.getConfiguration(); + assertEquals(1, rs.getRuleCount()); + + final Map rules = rs.getAllRules(); + assertEquals(1, rules.size()); + final Rule rule = rules.get(0); + assertEquals("Rule has unexpected identity", "user1", rule.getIdentity()); + assertEquals("Rule has unexpected operation", Operation.ACCESS, rule.getAction().getOperation()); + assertEquals("Rule has unexpected operation", ObjectType.VIRTUALHOST, rule.getAction().getObjectType()); + assertEquals("Rule has unexpected object properties", ObjectProperties.EMPTY, rule.getAction().getProperties()); + } + + /** + * Tests interpretation of an acl rule using mixtures of tabs/spaces as token separators. + * + */ + public void testWhitespace() throws Exception + { + final PlainConfiguration config = writeACLConfig("ACL\tDENY-LOG\t\t user1\t \tACCESS VIRTUALHOST"); + final RuleSet rs = config.getConfiguration(); + assertEquals(1, rs.getRuleCount()); + + final Map rules = rs.getAllRules(); + assertEquals(1, rules.size()); + final Rule rule = rules.get(0); + assertEquals("Rule has unexpected identity", "user1", rule.getIdentity()); + assertEquals("Rule has unexpected operation", Operation.ACCESS, rule.getAction().getOperation()); + assertEquals("Rule has unexpected operation", ObjectType.VIRTUALHOST, rule.getAction().getObjectType()); + assertEquals("Rule has unexpected object properties", ObjectProperties.EMPTY, rule.getAction().getProperties()); + } + + /** + * Tests interpretation of an acl utilising line continuation. + */ + public void testLineContination() throws Exception + { + final PlainConfiguration config = writeACLConfig("ACL DENY-LOG user1 \\", + "ACCESS VIRTUALHOST"); + final RuleSet rs = config.getConfiguration(); + assertEquals(1, rs.getRuleCount()); + + final Map rules = rs.getAllRules(); + assertEquals(1, rules.size()); + final Rule rule = rules.get(0); + assertEquals("Rule has unexpected identity", "user1", rule.getIdentity()); + assertEquals("Rule has unexpected operation", Operation.ACCESS, rule.getAction().getOperation()); + assertEquals("Rule has unexpected operation", ObjectType.VIRTUALHOST, rule.getAction().getObjectType()); + 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(IllegalConfigurationException e) + { + assertTrue(e.getMessage().contains("GROUP keyword not supported")); + } + } + + public void testManagementRuleParsing() throws Exception + { + validateRule(writeACLConfig("ACL ALLOW user1 ALL MANAGEMENT"), + "user1", Operation.ALL, ObjectType.MANAGEMENT, ObjectProperties.EMPTY); + + validateRule(writeACLConfig("ACL ALLOW user1 ACCESS MANAGEMENT"), + "user1", Operation.ACCESS, ObjectType.MANAGEMENT, ObjectProperties.EMPTY); + } + + 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 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/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/RuleTest.java b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/RuleTest.java new file mode 100644 index 0000000000..2ae7759679 --- /dev/null +++ b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/RuleTest.java @@ -0,0 +1,53 @@ +/* + * 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.config; + +import static org.mockito.Mockito.*; + +import org.apache.qpid.server.security.access.Permission; + +import junit.framework.TestCase; + +public class RuleTest extends TestCase +{ + public void testEqualsAndHashCode() + { + AclAction aclAction = mock(AclAction.class); + String identity = "identity"; + Permission allow = Permission.ALLOW; + + Rule rule = new Rule(identity, aclAction, allow); + Rule equalRule = new Rule(identity, aclAction, allow); + + assertTrue(rule.equals(rule)); + assertTrue(rule.equals(equalRule)); + assertTrue(equalRule.equals(rule)); + + assertTrue(rule.hashCode() == equalRule.hashCode()); + + assertFalse("Different identity should cause rules to be unequal", + rule.equals(new Rule("identity2", aclAction, allow))); + + assertFalse("Different action should cause rules to be unequal", + rule.equals(new Rule(identity, mock(AclAction.class), allow))); + + assertFalse("Different permission should cause rules to be unequal", + rule.equals(new Rule(identity, aclAction, Permission.DENY))); + } +} diff --git a/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/firewall/HostnameFirewallRuleTest.java b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/firewall/HostnameFirewallRuleTest.java new file mode 100644 index 0000000000..be82cb294a --- /dev/null +++ b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/firewall/HostnameFirewallRuleTest.java @@ -0,0 +1,99 @@ +/* + * 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.firewall; + +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +import java.net.InetAddress; + +import org.apache.qpid.server.security.access.firewall.HostnameFirewallRule; + +import junit.framework.TestCase; + +public class HostnameFirewallRuleTest extends TestCase +{ + private InetAddress _addressNotInRule; + + private HostnameFirewallRule _HostnameFirewallRule; + + @Override + protected void setUp() throws Exception + { + _addressNotInRule = InetAddress.getByName("127.0.0.1"); + } + + public void testSingleHostname() throws Exception + { + String hostnameInRule = "hostnameInRule"; + InetAddress addressWithMatchingHostname = mock(InetAddress.class); + when(addressWithMatchingHostname.getCanonicalHostName()).thenReturn(hostnameInRule); + + _HostnameFirewallRule = new HostnameFirewallRule(hostnameInRule); + + assertFalse(_HostnameFirewallRule.matches(_addressNotInRule)); + assertTrue(_HostnameFirewallRule.matches(addressWithMatchingHostname)); + } + + public void testSingleHostnameWilcard() throws Exception + { + String hostnameInRule = ".*FOO.*"; + InetAddress addressWithMatchingHostname = mock(InetAddress.class); + when(addressWithMatchingHostname.getCanonicalHostName()).thenReturn("xxFOOxx"); + + _HostnameFirewallRule = new HostnameFirewallRule(hostnameInRule); + + assertFalse(_HostnameFirewallRule.matches(_addressNotInRule)); + assertTrue(_HostnameFirewallRule.matches(addressWithMatchingHostname)); + } + + public void testMultipleHostnames() throws Exception + { + String[] hostnamesInRule = new String[] {"hostnameInRule1", "hostnameInRule2"}; + + _HostnameFirewallRule = new HostnameFirewallRule(hostnamesInRule); + + assertFalse(_HostnameFirewallRule.matches(_addressNotInRule)); + for (String hostnameInRule : hostnamesInRule) + { + InetAddress addressWithMatchingHostname = mock(InetAddress.class); + when(addressWithMatchingHostname.getCanonicalHostName()).thenReturn(hostnameInRule); + + assertTrue(_HostnameFirewallRule.matches(addressWithMatchingHostname)); + } + } + + public void testEqualsAndHashCode() + { + String hostname1 = "hostname1"; + String hostname2 = "hostname2"; + + HostnameFirewallRule rule = new HostnameFirewallRule(hostname1, hostname2); + HostnameFirewallRule equalRule = new HostnameFirewallRule(hostname1, hostname2); + + assertTrue(rule.equals(rule)); + assertTrue(rule.equals(equalRule)); + assertTrue(equalRule.equals(rule)); + + assertTrue(rule.hashCode() == equalRule.hashCode()); + + assertFalse("Different hostnames should cause rules to be unequal", + rule.equals(new HostnameFirewallRule(hostname1, "different-hostname"))); + } +} diff --git a/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/firewall/NetworkFirewallRuleTest.java b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/firewall/NetworkFirewallRuleTest.java new file mode 100644 index 0000000000..e521039db2 --- /dev/null +++ b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/firewall/NetworkFirewallRuleTest.java @@ -0,0 +1,115 @@ +/* + * 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.firewall; + +import java.net.InetAddress; + +import org.apache.qpid.server.security.access.firewall.NetworkFirewallRule; + +import junit.framework.TestCase; + +public class NetworkFirewallRuleTest extends TestCase +{ + private static final String LOCALHOST_IP = "127.0.0.1"; + private static final String OTHER_IP_1 = "192.168.23.1"; + private static final String OTHER_IP_2 = "192.168.23.2"; + + private InetAddress _addressNotInRule; + + private NetworkFirewallRule _networkFirewallRule; + + @Override + protected void setUp() throws Exception + { + _addressNotInRule = InetAddress.getByName(LOCALHOST_IP); + } + + public void testIpRule() throws Exception + { + String ipAddressInRule = OTHER_IP_1; + + _networkFirewallRule = new NetworkFirewallRule(ipAddressInRule); + + assertFalse(_networkFirewallRule.matches(_addressNotInRule)); + assertTrue(_networkFirewallRule.matches(InetAddress.getByName(ipAddressInRule))); + } + + public void testNetMask() throws Exception + { + String ipAddressInRule = "192.168.23.0/24"; + _networkFirewallRule = new NetworkFirewallRule(ipAddressInRule); + + assertFalse(_networkFirewallRule.matches(InetAddress.getByName("192.168.24.1"))); + assertTrue(_networkFirewallRule.matches(InetAddress.getByName("192.168.23.0"))); + assertTrue(_networkFirewallRule.matches(InetAddress.getByName("192.168.23.255"))); + } + + public void testWildcard() throws Exception + { + // Test xxx.xxx.* + + assertFalse(new NetworkFirewallRule("192.168.*") + .matches(InetAddress.getByName("192.169.1.0"))); + + assertTrue(new NetworkFirewallRule("192.168.*") + .matches(InetAddress.getByName("192.168.1.0"))); + + assertTrue(new NetworkFirewallRule("192.168.*") + .matches(InetAddress.getByName("192.168.255.255"))); + + // Test xxx.xxx.xxx.* + + assertFalse(new NetworkFirewallRule("192.168.1.*") + .matches(InetAddress.getByName("192.169.2.0"))); + + assertTrue(new NetworkFirewallRule("192.168.1.*") + .matches(InetAddress.getByName("192.168.1.0"))); + + assertTrue(new NetworkFirewallRule("192.168.1.*") + .matches(InetAddress.getByName("192.168.1.255"))); + } + + public void testMultipleNetworks() throws Exception + { + String[] ipAddressesInRule = new String[] {OTHER_IP_1, OTHER_IP_2}; + + _networkFirewallRule = new NetworkFirewallRule(ipAddressesInRule); + + assertFalse(_networkFirewallRule.matches(_addressNotInRule)); + for (String ipAddressInRule : ipAddressesInRule) + { + assertTrue(_networkFirewallRule.matches(InetAddress.getByName(ipAddressInRule))); + } + } + + public void testEqualsAndHashCode() + { + NetworkFirewallRule rule = new NetworkFirewallRule(LOCALHOST_IP, OTHER_IP_1); + NetworkFirewallRule equalRule = new NetworkFirewallRule(LOCALHOST_IP, OTHER_IP_1); + + assertTrue(rule.equals(rule)); + assertTrue(rule.equals(equalRule)); + assertTrue(equalRule.equals(rule)); + + assertTrue(rule.hashCode() == equalRule.hashCode()); + + assertFalse("Different networks should cause rules to be unequal", + rule.equals(new NetworkFirewallRule(LOCALHOST_IP, OTHER_IP_2))); + } +} diff --git a/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/AccessControlTest.java b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/AccessControlTest.java deleted file mode 100644 index 5db02d10ce..0000000000 --- a/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/AccessControlTest.java +++ /dev/null @@ -1,355 +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.util.Arrays; - -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.sasl.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 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(); - 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); - // 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 testAclGroupMembershipAllowsOperation() 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); - } - - /** - * Tests that a deny rule expressed with an External groupname denies an operation performed by a thread running - * by a user who belongs to the same group. - */ - public void testExternalGroupMembershipDeniesOperation() throws ConfigurationException - { - setUpGroupAccessControl(); - SecurityManager.setThreadSubject(TestPrincipalUtils.createTestSubject("user3", "extGroup1")); - - final Result result = _plugin.authorise(Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY); - assertEquals(Result.DENIED, result); - } - - /** - * 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); - } - - /** - * 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); - } - - /** - * 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/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlFactoryTest.java b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlFactoryTest.java new file mode 100644 index 0000000000..ca1f19098f --- /dev/null +++ b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlFactoryTest.java @@ -0,0 +1,69 @@ +package org.apache.qpid.server.security.access.plugins; + +import java.io.File; +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Pattern; + +import org.apache.qpid.server.configuration.IllegalConfigurationException; +import org.apache.qpid.server.security.AccessControl; +import org.apache.qpid.test.utils.QpidTestCase; +import org.apache.qpid.test.utils.TestFileUtils; + +public class DefaultAccessControlFactoryTest extends QpidTestCase +{ + public void testCreateInstanceWhenAclFileIsNotPresent() + { + DefaultAccessControlFactory factory = new DefaultAccessControlFactory(); + Map attributes = new HashMap(); + AccessControl acl = factory.createInstance(attributes); + assertNull("ACL was created without a configuration file", acl); + } + + public void testCreateInstanceWhenAclFileIsSpecified() + { + File aclFile = TestFileUtils.createTempFile(this, ".acl", "ACL ALLOW all all"); + DefaultAccessControlFactory factory = new DefaultAccessControlFactory(); + Map attributes = new HashMap(); + attributes.put(DefaultAccessControlFactory.ATTRIBUTE_ACL_FILE, aclFile.getAbsolutePath()); + AccessControl acl = factory.createInstance(attributes); + + assertNotNull("ACL was not created from acl file: " + aclFile.getAbsolutePath(), acl); + } + + public void testCreateInstanceWhenAclFileIsSpecifiedButDoesNotExist() + { + File aclFile = new File(TMP_FOLDER, "my-non-existing-acl-" + System.currentTimeMillis()); + assertFalse("ACL file " + aclFile.getAbsolutePath() + " actually exists but should not", aclFile.exists()); + DefaultAccessControlFactory factory = new DefaultAccessControlFactory(); + Map attributes = new HashMap(); + attributes.put(DefaultAccessControlFactory.ATTRIBUTE_ACL_FILE, aclFile.getAbsolutePath()); + try + { + factory.createInstance(attributes); + fail("It should not be possible to create ACL from non existing file"); + } + catch (IllegalConfigurationException e) + { + assertTrue("Unexpected exception message", Pattern.matches("ACL file '.*' is not found", e.getMessage())); + } + } + + public void testCreateInstanceWhenAclFileIsSpecifiedAsNonString() + { + DefaultAccessControlFactory factory = new DefaultAccessControlFactory(); + Map attributes = new HashMap(); + Integer aclFile = new Integer(0); + attributes.put(DefaultAccessControlFactory.ATTRIBUTE_ACL_FILE, aclFile); + try + { + factory.createInstance(attributes); + fail("It should not be possible to create ACL from Integer"); + } + catch (IllegalConfigurationException e) + { + assertEquals("Unexpected exception message", "Expected '" + DefaultAccessControlFactory.ATTRIBUTE_ACL_FILE + + "' attribute value of type String but was " + Integer.class + ": " + aclFile, e.getMessage()); + } + } +} diff --git a/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/DefaultAccessControlTest.java b/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/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); + } +} diff --git a/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/PlainConfigurationTest.java b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/PlainConfigurationTest.java deleted file mode 100644 index c2282694fb..0000000000 --- a/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/PlainConfigurationTest.java +++ /dev/null @@ -1,394 +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.io.FileNotFoundException; -import java.io.FileWriter; -import java.io.PrintWriter; -import java.util.Map; - -import junit.framework.TestCase; - -import org.apache.commons.configuration.ConfigurationException; -import org.apache.qpid.server.security.access.ObjectProperties; -import org.apache.qpid.server.security.access.ObjectProperties.Property; -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.Rule; -import org.apache.qpid.server.security.access.config.RuleSet; - -/** - * These tests check that the ACL file parsing works correctly. - * - * For each message that can be returned in a {@link ConfigurationException}, an ACL file is created that should trigger this - * particular message. - */ -public class PlainConfigurationTest extends TestCase -{ - private PlainConfiguration writeACLConfig(String...aclData) throws Exception - { - File acl = File.createTempFile(getClass().getName() + getName(), "acl"); - acl.deleteOnExit(); - - // Write ACL file - PrintWriter aclWriter = new PrintWriter(new FileWriter(acl)); - for (String line : aclData) - { - aclWriter.println(line); - } - aclWriter.close(); - - // Load ruleset - PlainConfiguration configFile = new PlainConfiguration(acl); - configFile.load(); - return configFile; - } - - public void testMissingACLConfig() throws Exception - { - try - { - // Load ruleset - ConfigurationFile configFile = new PlainConfiguration(new File("doesnotexist")); - configFile.load(); - - fail("fail"); - } - catch (ConfigurationException ce) - { - assertEquals(String.format(PlainConfiguration.CONFIG_NOT_FOUND_MSG, "doesnotexist"), ce.getMessage()); - assertTrue(ce.getCause() instanceof FileNotFoundException); - } - } - - public void testACLFileSyntaxContinuation() throws Exception - { - try - { - writeACLConfig("ACL ALLOW ALL \\ ALL"); - fail("fail"); - } - catch (ConfigurationException ce) - { - assertEquals(String.format(PlainConfiguration.PREMATURE_CONTINUATION_MSG, 1), ce.getMessage()); - } - } - - public void testACLFileSyntaxTokens() throws Exception - { - try - { - writeACLConfig("ACL unparsed ALL ALL"); - fail("fail"); - } - catch (ConfigurationException ce) - { - assertEquals(String.format(PlainConfiguration.PARSE_TOKEN_FAILED_MSG, 1), ce.getMessage()); - assertTrue(ce.getCause() instanceof IllegalArgumentException); - assertEquals("Not a valid permission: unparsed", ce.getCause().getMessage()); - } - } - - 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 - { - writeACLConfig("ACL ALLOW"); - fail("fail"); - } - catch (ConfigurationException ce) - { - assertEquals(String.format(PlainConfiguration.NOT_ENOUGH_ACL_MSG, 1), ce.getMessage()); - } - } - - public void testACLFileSyntaxNotEnoughConfig() throws Exception - { - try - { - writeACLConfig("CONFIG"); - fail("fail"); - } - catch (ConfigurationException ce) - { - assertEquals(String.format(PlainConfiguration.NOT_ENOUGH_TOKENS_MSG, 1), ce.getMessage()); - } - } - - public void testACLFileSyntaxNotEnough() throws Exception - { - try - { - writeACLConfig("INVALID"); - fail("fail"); - } - catch (ConfigurationException ce) - { - assertEquals(String.format(PlainConfiguration.NOT_ENOUGH_TOKENS_MSG, 1), ce.getMessage()); - } - } - - public void testACLFileSyntaxPropertyKeyOnly() throws Exception - { - try - { - writeACLConfig("ACL ALLOW adk CREATE QUEUE name"); - fail("fail"); - } - catch (ConfigurationException ce) - { - assertEquals(String.format(PlainConfiguration.PROPERTY_KEY_ONLY_MSG, 1), ce.getMessage()); - } - } - - public void testACLFileSyntaxPropertyNoEquals() throws Exception - { - try - { - writeACLConfig("ACL ALLOW adk CREATE QUEUE name test"); - fail("fail"); - } - catch (ConfigurationException ce) - { - assertEquals(String.format(PlainConfiguration.PROPERTY_NO_EQUALS_MSG, 1), ce.getMessage()); - } - } - - public void testACLFileSyntaxPropertyNoValue() throws Exception - { - try - { - writeACLConfig("ACL ALLOW adk CREATE QUEUE name ="); - fail("fail"); - } - catch (ConfigurationException ce) - { - assertEquals(String.format(PlainConfiguration.PROPERTY_NO_VALUE_MSG, 1), ce.getMessage()); - } - } - - /** - * Tests interpretation of an acl rule with no object properties. - * - */ - public void testValidRule() throws Exception - { - final PlainConfiguration config = writeACLConfig("ACL DENY-LOG user1 ACCESS VIRTUALHOST"); - final RuleSet rs = config.getConfiguration(); - assertEquals(1, rs.getRuleCount()); - - final Map rules = rs.getAllRules(); - assertEquals(1, rules.size()); - final Rule rule = rules.get(0); - assertEquals("Rule has unexpected identity", "user1", rule.getIdentity()); - assertEquals("Rule has unexpected operation", Operation.ACCESS, rule.getAction().getOperation()); - assertEquals("Rule has unexpected operation", ObjectType.VIRTUALHOST, rule.getAction().getObjectType()); - assertEquals("Rule has unexpected object properties", ObjectProperties.EMPTY, rule.getAction().getProperties()); - } - - /** - * Tests interpretation of an acl rule with object properties quoted in single quotes. - */ - public void testValidRuleWithSingleQuotedProperty() throws Exception - { - final PlainConfiguration config = writeACLConfig("ACL ALLOW all CREATE EXCHANGE name = \'value\'"); - final RuleSet rs = config.getConfiguration(); - assertEquals(1, rs.getRuleCount()); - - final Map rules = rs.getAllRules(); - assertEquals(1, rules.size()); - final Rule rule = rules.get(0); - assertEquals("Rule has unexpected identity", "all", rule.getIdentity()); - assertEquals("Rule has unexpected operation", Operation.CREATE, rule.getAction().getOperation()); - assertEquals("Rule has unexpected operation", ObjectType.EXCHANGE, rule.getAction().getObjectType()); - final ObjectProperties expectedProperties = new ObjectProperties(); - expectedProperties.setName("value"); - assertEquals("Rule has unexpected object properties", expectedProperties, rule.getAction().getProperties()); - } - - /** - * Tests interpretation of an acl rule with object properties quoted in double quotes. - */ - public void testValidRuleWithDoubleQuotedProperty() throws Exception - { - final PlainConfiguration config = writeACLConfig("ACL ALLOW all CREATE EXCHANGE name = \"value\""); - final RuleSet rs = config.getConfiguration(); - assertEquals(1, rs.getRuleCount()); - - final Map rules = rs.getAllRules(); - assertEquals(1, rules.size()); - final Rule rule = rules.get(0); - assertEquals("Rule has unexpected identity", "all", rule.getIdentity()); - assertEquals("Rule has unexpected operation", Operation.CREATE, rule.getAction().getOperation()); - assertEquals("Rule has unexpected operation", ObjectType.EXCHANGE, rule.getAction().getObjectType()); - final ObjectProperties expectedProperties = new ObjectProperties(); - expectedProperties.setName("value"); - assertEquals("Rule has unexpected object properties", expectedProperties, rule.getAction().getProperties()); - } - - /** - * Tests interpretation of an acl rule with many object properties. - */ - public void testValidRuleWithManyProperties() throws Exception - { - final PlainConfiguration config = writeACLConfig("ACL ALLOW admin DELETE QUEUE name=name1 owner = owner1"); - final RuleSet rs = config.getConfiguration(); - assertEquals(1, rs.getRuleCount()); - - final Map rules = rs.getAllRules(); - assertEquals(1, rules.size()); - final Rule rule = rules.get(0); - assertEquals("Rule has unexpected identity", "admin", rule.getIdentity()); - assertEquals("Rule has unexpected operation", Operation.DELETE, rule.getAction().getOperation()); - assertEquals("Rule has unexpected operation", ObjectType.QUEUE, rule.getAction().getObjectType()); - final ObjectProperties expectedProperties = new ObjectProperties(); - expectedProperties.setName("name1"); - expectedProperties.put(Property.OWNER, "owner1"); - assertEquals("Rule has unexpected operation", expectedProperties, rule.getAction().getProperties()); - } - - /** - * Tests interpretation of an acl rule with object properties containing wildcards. Values containing - * hashes must be quoted otherwise they are interpreted as comments. - */ - public void testValidRuleWithWildcardProperties() throws Exception - { - final PlainConfiguration config = writeACLConfig("ACL ALLOW all CREATE EXCHANGE routingKey = \'news.#\'", - "ACL ALLOW all CREATE EXCHANGE routingKey = \'news.co.#\'", - "ACL ALLOW all CREATE EXCHANGE routingKey = *.co.medellin"); - final RuleSet rs = config.getConfiguration(); - assertEquals(3, rs.getRuleCount()); - - final Map rules = rs.getAllRules(); - assertEquals(3, rules.size()); - final Rule rule1 = rules.get(0); - assertEquals("Rule has unexpected identity", "all", rule1.getIdentity()); - assertEquals("Rule has unexpected operation", Operation.CREATE, rule1.getAction().getOperation()); - assertEquals("Rule has unexpected operation", ObjectType.EXCHANGE, rule1.getAction().getObjectType()); - final ObjectProperties expectedProperties1 = new ObjectProperties(); - expectedProperties1.put(Property.ROUTING_KEY,"news.#"); - assertEquals("Rule has unexpected object properties", expectedProperties1, rule1.getAction().getProperties()); - - final Rule rule2 = rules.get(10); - final ObjectProperties expectedProperties2 = new ObjectProperties(); - expectedProperties2.put(Property.ROUTING_KEY,"news.co.#"); - assertEquals("Rule has unexpected object properties", expectedProperties2, rule2.getAction().getProperties()); - - final Rule rule3 = rules.get(20); - final ObjectProperties expectedProperties3 = new ObjectProperties(); - expectedProperties3.put(Property.ROUTING_KEY,"*.co.medellin"); - assertEquals("Rule has unexpected object properties", expectedProperties3, rule3.getAction().getProperties()); - } - - /** - * Tests that rules are case insignificant. - */ - public void testMixedCaseRuleInterpretation() throws Exception - { - final PlainConfiguration config = writeACLConfig("AcL deny-LOG User1 BiND Exchange Name=AmQ.dIrect"); - final RuleSet rs = config.getConfiguration(); - assertEquals(1, rs.getRuleCount()); - - final Map rules = rs.getAllRules(); - assertEquals(1, rules.size()); - final Rule rule = rules.get(0); - assertEquals("Rule has unexpected identity", "User1", rule.getIdentity()); - assertEquals("Rule has unexpected operation", Operation.BIND, rule.getAction().getOperation()); - assertEquals("Rule has unexpected operation", ObjectType.EXCHANGE, rule.getAction().getObjectType()); - final ObjectProperties expectedProperties = new ObjectProperties("AmQ.dIrect"); - assertEquals("Rule has unexpected object properties", expectedProperties, rule.getAction().getProperties()); - } - - /** - * Tests whitespace is supported. Note that currently the Java implementation permits comments to - * be introduced anywhere in the ACL, whereas the C++ supports only whitespace at the beginning of - * of line. - */ - public void testCommentsSuppported() throws Exception - { - final PlainConfiguration config = writeACLConfig("#Comment", - "ACL DENY-LOG user1 ACCESS VIRTUALHOST # another comment", - " # final comment with leading whitespace"); - final RuleSet rs = config.getConfiguration(); - assertEquals(1, rs.getRuleCount()); - - final Map rules = rs.getAllRules(); - assertEquals(1, rules.size()); - final Rule rule = rules.get(0); - assertEquals("Rule has unexpected identity", "user1", rule.getIdentity()); - assertEquals("Rule has unexpected operation", Operation.ACCESS, rule.getAction().getOperation()); - assertEquals("Rule has unexpected operation", ObjectType.VIRTUALHOST, rule.getAction().getObjectType()); - assertEquals("Rule has unexpected object properties", ObjectProperties.EMPTY, rule.getAction().getProperties()); - } - - /** - * Tests interpretation of an acl rule using mixtures of tabs/spaces as token separators. - * - */ - public void testWhitespace() throws Exception - { - final PlainConfiguration config = writeACLConfig("ACL\tDENY-LOG\t\t user1\t \tACCESS VIRTUALHOST"); - final RuleSet rs = config.getConfiguration(); - assertEquals(1, rs.getRuleCount()); - - final Map rules = rs.getAllRules(); - assertEquals(1, rules.size()); - final Rule rule = rules.get(0); - assertEquals("Rule has unexpected identity", "user1", rule.getIdentity()); - assertEquals("Rule has unexpected operation", Operation.ACCESS, rule.getAction().getOperation()); - assertEquals("Rule has unexpected operation", ObjectType.VIRTUALHOST, rule.getAction().getObjectType()); - assertEquals("Rule has unexpected object properties", ObjectProperties.EMPTY, rule.getAction().getProperties()); - } - - /** - * Tests interpretation of an acl utilising line continuation. - */ - public void testLineContination() throws Exception - { - final PlainConfiguration config = writeACLConfig("ACL DENY-LOG user1 \\", - "ACCESS VIRTUALHOST"); - final RuleSet rs = config.getConfiguration(); - assertEquals(1, rs.getRuleCount()); - - final Map rules = rs.getAllRules(); - assertEquals(1, rules.size()); - final Rule rule = rules.get(0); - assertEquals("Rule has unexpected identity", "user1", rule.getIdentity()); - assertEquals("Rule has unexpected operation", Operation.ACCESS, rule.getAction().getOperation()); - assertEquals("Rule has unexpected operation", ObjectType.VIRTUALHOST, rule.getAction().getObjectType()); - assertEquals("Rule has unexpected object properties", ObjectProperties.EMPTY, rule.getAction().getProperties()); - } - -} diff --git a/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/RuleSetTest.java b/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/RuleSetTest.java index f7cc60543d..181d693614 100644 --- a/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/RuleSetTest.java +++ b/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)); } } -- cgit v1.2.1