From dfc6efe401a678748436f2a238acd06a1c8bbced Mon Sep 17 00:00:00 2001 From: Keith Wall Date: Fri, 28 Sep 2012 12:46:31 +0000 Subject: QPID-4334: addressed Keith's review comments. Also moved PlainConfigurationTest to the correct package. Applied patch from Philip Harvey . git-svn-id: https://svn.apache.org/repos/asf/qpid/trunk@1391431 13f79535-47bb-0310-9956-ffa450edef68 --- .../server/security/access/config/ActionTest.java | 95 +++++ .../access/config/PlainConfigurationTest.java | 463 +++++++++++++++++++++ .../access/plugins/PlainConfigurationTest.java | 463 --------------------- 3 files changed, 558 insertions(+), 463 deletions(-) create mode 100644 qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/ActionTest.java create mode 100644 qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/PlainConfigurationTest.java delete mode 100644 qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/PlainConfigurationTest.java (limited to 'qpid/java/broker-plugins/access-control/src/test') diff --git a/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/ActionTest.java b/qpid/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/qpid/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/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/PlainConfigurationTest.java b/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/PlainConfigurationTest.java new file mode 100644 index 0000000000..21d8ff4400 --- /dev/null +++ b/qpid/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.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 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()); + } + + public void testUserRuleParsing() throws Exception + { + validateRule(writeACLConfig("ACL ALLOW user1 CREATE USER"), + "user1", Operation.CREATE, ObjectType.USER, ObjectProperties.EMPTY); + validateRule(writeACLConfig("ACL ALLOW user1 CREATE USER name=\"otherUser\""), + "user1", Operation.CREATE, ObjectType.USER, new ObjectProperties("otherUser")); + + validateRule(writeACLConfig("ACL ALLOW user1 DELETE USER"), + "user1", Operation.DELETE, ObjectType.USER, ObjectProperties.EMPTY); + validateRule(writeACLConfig("ACL ALLOW user1 DELETE USER name=\"otherUser\""), + "user1", Operation.DELETE, ObjectType.USER, new ObjectProperties("otherUser")); + + validateRule(writeACLConfig("ACL ALLOW user1 UPDATE USER"), + "user1", Operation.UPDATE, ObjectType.USER, ObjectProperties.EMPTY); + validateRule(writeACLConfig("ACL ALLOW user1 UPDATE USER name=\"otherUser\""), + "user1", Operation.UPDATE, ObjectType.USER, new ObjectProperties("otherUser")); + + validateRule(writeACLConfig("ACL ALLOW user1 ALL USER"), + "user1", Operation.ALL, ObjectType.USER, ObjectProperties.EMPTY); + validateRule(writeACLConfig("ACL ALLOW user1 ALL USER name=\"otherUser\""), + "user1", Operation.ALL, ObjectType.USER, new ObjectProperties("otherUser")); + } + + public void testGroupRuleParsing() throws Exception + { + validateRule(writeACLConfig("ACL ALLOW user1 CREATE GROUP"), + "user1", Operation.CREATE, ObjectType.GROUP, ObjectProperties.EMPTY); + validateRule(writeACLConfig("ACL ALLOW user1 CREATE GROUP name=\"groupName\""), + "user1", Operation.CREATE, ObjectType.GROUP, new ObjectProperties("groupName")); + + validateRule(writeACLConfig("ACL ALLOW user1 DELETE GROUP"), + "user1", Operation.DELETE, ObjectType.GROUP, ObjectProperties.EMPTY); + validateRule(writeACLConfig("ACL ALLOW user1 DELETE GROUP name=\"groupName\""), + "user1", Operation.DELETE, ObjectType.GROUP, new ObjectProperties("groupName")); + + validateRule(writeACLConfig("ACL ALLOW user1 UPDATE GROUP"), + "user1", Operation.UPDATE, ObjectType.GROUP, ObjectProperties.EMPTY); + validateRule(writeACLConfig("ACL ALLOW user1 UPDATE GROUP name=\"groupName\""), + "user1", Operation.UPDATE, ObjectType.GROUP, new ObjectProperties("groupName")); + + validateRule(writeACLConfig("ACL ALLOW user1 ALL GROUP"), + "user1", Operation.ALL, ObjectType.GROUP, ObjectProperties.EMPTY); + validateRule(writeACLConfig("ACL ALLOW user1 ALL GROUP name=\"groupName\""), + "user1", Operation.ALL, ObjectType.GROUP, new ObjectProperties("groupName")); + } + + /** explicitly test for exception indicating that this functionality has been moved to Group Providers */ + public void testGroupDefinitionThrowsException() throws Exception + { + try + { + writeACLConfig("GROUP group1 bob alice"); + fail("Expected exception not thrown"); + } + catch(ConfigurationException e) + { + assertTrue(e.getMessage().contains("GROUP keyword not supported")); + } + } + + 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/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/PlainConfigurationTest.java b/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/PlainConfigurationTest.java deleted file mode 100644 index fa9e96ba1e..0000000000 --- a/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/PlainConfigurationTest.java +++ /dev/null @@ -1,463 +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 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()); - } - - public void testUserRuleParsing() throws Exception - { - validateRule(writeACLConfig("ACL ALLOW user1 CREATE USER"), - "user1", Operation.CREATE, ObjectType.USER, ObjectProperties.EMPTY); - validateRule(writeACLConfig("ACL ALLOW user1 CREATE USER name=\"otherUser\""), - "user1", Operation.CREATE, ObjectType.USER, new ObjectProperties("otherUser")); - - validateRule(writeACLConfig("ACL ALLOW user1 DELETE USER"), - "user1", Operation.DELETE, ObjectType.USER, ObjectProperties.EMPTY); - validateRule(writeACLConfig("ACL ALLOW user1 DELETE USER name=\"otherUser\""), - "user1", Operation.DELETE, ObjectType.USER, new ObjectProperties("otherUser")); - - validateRule(writeACLConfig("ACL ALLOW user1 UPDATE USER"), - "user1", Operation.UPDATE, ObjectType.USER, ObjectProperties.EMPTY); - validateRule(writeACLConfig("ACL ALLOW user1 UPDATE USER name=\"otherUser\""), - "user1", Operation.UPDATE, ObjectType.USER, new ObjectProperties("otherUser")); - - validateRule(writeACLConfig("ACL ALLOW user1 ALL USER"), - "user1", Operation.ALL, ObjectType.USER, ObjectProperties.EMPTY); - validateRule(writeACLConfig("ACL ALLOW user1 ALL USER name=\"otherUser\""), - "user1", Operation.ALL, ObjectType.USER, new ObjectProperties("otherUser")); - } - - public void testGroupRuleParsing() throws Exception - { - validateRule(writeACLConfig("ACL ALLOW user1 CREATE GROUP"), - "user1", Operation.CREATE, ObjectType.GROUP, ObjectProperties.EMPTY); - validateRule(writeACLConfig("ACL ALLOW user1 CREATE GROUP name=\"groupName\""), - "user1", Operation.CREATE, ObjectType.GROUP, new ObjectProperties("groupName")); - - validateRule(writeACLConfig("ACL ALLOW user1 DELETE GROUP"), - "user1", Operation.DELETE, ObjectType.GROUP, ObjectProperties.EMPTY); - validateRule(writeACLConfig("ACL ALLOW user1 DELETE GROUP name=\"groupName\""), - "user1", Operation.DELETE, ObjectType.GROUP, new ObjectProperties("groupName")); - - validateRule(writeACLConfig("ACL ALLOW user1 UPDATE GROUP"), - "user1", Operation.UPDATE, ObjectType.GROUP, ObjectProperties.EMPTY); - validateRule(writeACLConfig("ACL ALLOW user1 UPDATE GROUP name=\"groupName\""), - "user1", Operation.UPDATE, ObjectType.GROUP, new ObjectProperties("groupName")); - - validateRule(writeACLConfig("ACL ALLOW user1 ALL GROUP"), - "user1", Operation.ALL, ObjectType.GROUP, ObjectProperties.EMPTY); - validateRule(writeACLConfig("ACL ALLOW user1 ALL GROUP name=\"groupName\""), - "user1", Operation.ALL, ObjectType.GROUP, new ObjectProperties("groupName")); - } - - /** explicitly test for exception indicating that this functionality has been moved to Group Providers */ - public void testGroupDefinitionThrowsException() throws Exception - { - try - { - writeACLConfig("GROUP group1 bob alice"); - fail("Expected exception not thrown"); - } - catch(ConfigurationException e) - { - assertTrue(e.getMessage().contains("GROUP keyword not supported")); - } - } - - 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()); - } -} -- cgit v1.2.1