Added: qpid/trunk/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/firewall/NetworkFirewallRuleTest.java URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/firewall/NetworkFirewallRuleTest.java?rev=1391430&view=auto ============================================================================== --- qpid/trunk/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/firewall/NetworkFirewallRuleTest.java (added) +++ qpid/trunk/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/firewall/NetworkFirewallRuleTest.java Fri Sep 28 12:46:06 2012 @@ -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))); + } +}
Modified: qpid/trunk/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/AccessControlTest.java URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/AccessControlTest.java?rev=1391430&r1=1391429&r2=1391430&view=diff ============================================================================== --- qpid/trunk/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/AccessControlTest.java (original) +++ qpid/trunk/qpid/java/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/plugins/AccessControlTest.java Fri Sep 28 12:46:06 2012 @@ -20,6 +20,13 @@ */ 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; @@ -194,6 +201,49 @@ public class AccessControlTest extends T assertEquals(Result.DEFER, result); } + public void testAccess() throws Exception + { + Subject subject = TestPrincipalUtils.createTestSubject("user1"); + SecurityManager.setThreadSubject(subject); + + RuleSet mockRuleSet = mock(RuleSet.class); + ConfigurationPlugin accessControlConfiguration = createConfiguration(mockRuleSet); + + InetAddress inetAddress = InetAddress.getLocalHost(); + InetSocketAddress inetSocketAddress = new InetSocketAddress(inetAddress, 1); + + AccessControl accessControl = AccessControl.FACTORY.newInstance(accessControlConfiguration); + + accessControl.access(ObjectType.VIRTUALHOST, inetSocketAddress); + + verify(mockRuleSet).check(subject, Operation.ACCESS, ObjectType.VIRTUALHOST, ObjectProperties.EMPTY, inetAddress); + } + + public void testAccessIsDeniedIfRuleThrowsException() throws Exception + { + Subject subject = TestPrincipalUtils.createTestSubject("user1"); + SecurityManager.setThreadSubject(subject); + + InetAddress inetAddress = InetAddress.getLocalHost(); + InetSocketAddress inetSocketAddress = new InetSocketAddress(inetAddress, 1); + + RuleSet mockRuleSet = mock(RuleSet.class); + when(mockRuleSet.check( + subject, + Operation.ACCESS, + ObjectType.VIRTUALHOST, + ObjectProperties.EMPTY, + inetAddress)).thenThrow(new RuntimeException()); + + ConfigurationPlugin accessControlConfiguration = createConfiguration(mockRuleSet); + + AccessControl accessControl = AccessControl.FACTORY.newInstance(accessControlConfiguration); + Result result = accessControl.access(ObjectType.VIRTUALHOST, inetSocketAddress); + + assertEquals(Result.DENIED, result); + } + + /** * Tests that a grant access method rule allows any access operation to be performed on a specified component */ @@ -332,7 +382,7 @@ public class AccessControlTest extends T final ConfigurationPlugin cp = new ConfigurationPlugin() { @SuppressWarnings("unchecked") - public AccessControlConfiguration getConfiguration(final String plugin) + public AccessControlConfiguration getConfiguration(final String plugin) { return new AccessControlConfiguration() { Modified: qpid/trunk/qpid/java/broker/etc/broker_example.acl URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/etc/broker_example.acl?rev=1391430&r1=1391429&r2=1391430&view=diff ============================================================================== --- qpid/trunk/qpid/java/broker/etc/broker_example.acl (original) +++ qpid/trunk/qpid/java/broker/etc/broker_example.acl Fri Sep 28 12:46:06 2012 @@ -78,11 +78,24 @@ ACL ALLOW-LOG webadmins UPDATE METHOD #ACL ALLOW-LOG webadmins UPDATE METHOD component="VirtualHost.Queue" name="deleteMessages" ### MESSAGING ### +# The 'ACCESS VIRTUALHOST' rules below apply to messaging operations (as opposed to management operations) -#Example permissions for request-response based messaging. +# Firewall examples -#Allow 'messaging-users' group to connect to all virtualhosts +# Deny access to all users from *.example.company1.com and *.example.company2.com +ACL DENY-LOG all ACCESS VIRTUALHOST from_hostname=".*\.example\.company1.com,.*\.example\.company2.com" + +# Deny access to all users in the IP ranges 192.168.1.0-192.168.1.255 and 192.168.2.0-192.168.2.255, +# using the notation specified in RFC 4632, "Classless Inter-domain Routing (CIDR)" +ACL DENY-LOG messaging-users ACCESS VIRTUALHOST from_network="192.168.1.0/24,192.168.2.0/24" + +# Deny access to all users in the IP ranges 192.169.1.0-192.169.1.255 and 192.169.2.0-192.169.2.255, +# using wildcard notation. +ACL DENY-LOG messaging-users ACCESS VIRTUALHOST from_network="192.169.1.*,192.169.2.*" + +# Allow 'messaging-users' group to connect to all virtualhosts ACL ALLOW-LOG messaging-users ACCESS VIRTUALHOST + # Deny messaging-users management ACL DENY-LOG messaging-users ACCESS MANAGEMENT Modified: qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectProperties.java URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectProperties.java?rev=1391430&r1=1391429&r2=1391430&view=diff ============================================================================== --- qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectProperties.java (original) +++ qpid/trunk/qpid/java/broker/src/main/java/org/apache/qpid/server/security/access/ObjectProperties.java Fri Sep 28 12:46:06 2012 @@ -18,33 +18,31 @@ */ package org.apache.qpid.server.security.access; -import org.apache.commons.lang.StringUtils; - -import org.apache.qpid.framing.AMQShortString; -import org.apache.qpid.server.exchange.Exchange; -import org.apache.qpid.server.queue.AMQQueue; - import java.util.ArrayList; import java.util.EnumMap; +import java.util.HashMap; import java.util.List; import java.util.Map; +import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang.builder.EqualsBuilder; +import org.apache.qpid.framing.AMQShortString; +import org.apache.qpid.server.exchange.Exchange; +import org.apache.qpid.server.queue.AMQQueue; + /** * An set of properties for an access control v2 rule {@link ObjectType}. - * + * * The {@link #matches(ObjectProperties)} method is intended to be used when determining precedence of rules, and * {@link #equals(Object)} and {@link #hashCode()} are intended for use in maps. This is due to the wildcard matching * described above. */ public class ObjectProperties { - /** serialVersionUID */ - private static final long serialVersionUID = -1356019341374170495L; - public static final String STAR= "*"; public static final ObjectProperties EMPTY = new ObjectProperties(); - + public enum Property { ROUTING_KEY, @@ -65,81 +63,89 @@ public class ObjectProperties AUTO_DELETE, COMPONENT, PACKAGE, - CLASS; - - public static Property parse(String text) + CLASS, + FROM_NETWORK, + FROM_HOSTNAME; + + private static final Map<String, Property> _canonicalNameToPropertyMap = new HashMap<String, ObjectProperties.Property>(); + + static { for (Property property : values()) { - if (property.getName().equalsIgnoreCase(text)) - { - return property; - } + _canonicalNameToPropertyMap.put(getCanonicalName(property.name()), property); } - throw new IllegalArgumentException("Not a valid property: " + text); } - - public String getName() + + /** + * Properties are parsed using their canonical name (see {@link #getCanonicalName(String)}) + * so that, for the sake of user-friendliness, the ACL file parses is insensitive to + * case and underscores. + */ + public static Property parse(String text) { - return StringUtils.remove(name(), '_').toLowerCase(); + String propertyName = getCanonicalName(text); + Property property = _canonicalNameToPropertyMap.get(propertyName); + + if(property == null) + { + throw new IllegalArgumentException("Not a valid property: " + text + + " because " + propertyName + + " is not in " + _canonicalNameToPropertyMap.keySet()); + } + else + { + return property; + } + } + + private static String getCanonicalName(String name) + { + return StringUtils.remove(name, '_').toLowerCase(); } - - public static List<String> getPropertyNames() - { - List<String> properties = new ArrayList<String>(); - for (Property property : values()) - { - properties.add(property.getName()); - } - return properties; - } } private final EnumMap<Property, String> _properties = new EnumMap<Property, String>(Property.class); - public static List<String> getAllPropertyNames() + public static List<String> getAllPropertyNames() { - List<String> properties = new ArrayList<String>(); - for (Property property : Property.values()) - { - properties.add(StringUtils.remove(property.name(), '_').toLowerCase()); - } - return properties; - } - + List<String> properties = new ArrayList<String>(); + for (Property property : Property.values()) + { + properties.add(StringUtils.remove(property.name(), '_').toLowerCase()); + } + return properties; + } + public ObjectProperties() { - super(); } - + + public ObjectProperties(Property property, String value) + { + _properties.put(property, value); + } + public ObjectProperties(ObjectProperties copy) { - super(); - _properties.putAll(copy._properties); } - + public ObjectProperties(String name) { - super(); - setName(name); } - + public ObjectProperties(AMQShortString name) { - super(); - setName(name); } - + public ObjectProperties(AMQQueue queue) { - super(); - setName(queue.getName()); - + put(Property.AUTO_DELETE, queue.isAutoDelete()); put(Property.TEMPORARY, queue.isAutoDelete()); put(Property.DURABLE, queue.isDurable()); @@ -157,45 +163,45 @@ public class ObjectProperties put(Property.OWNER, queue.getAuthorizationHolder().getAuthorizedPrincipal().getName()); } } - + public ObjectProperties(Exchange exch, AMQQueue queue, AMQShortString routingKey) { this(queue); - - setName(exch.getName()); - + + setName(exch.getName()); + put(Property.QUEUE_NAME, queue.getName()); put(Property.ROUTING_KEY, routingKey); } - + public ObjectProperties(Exchange exch, AMQShortString routingKey) { this(exch.getName(), routingKey.asString()); } - + public ObjectProperties(String exchangeName, String routingKey, Boolean immediate) { this(exchangeName, routingKey); - + put(Property.IMMEDIATE, immediate); } - + public ObjectProperties(String exchangeName, String routingKey) { super(); - + setName(exchangeName); - + put(Property.ROUTING_KEY, routingKey); } - + public ObjectProperties(Boolean autoDelete, Boolean durable, AMQShortString exchangeName, Boolean internal, Boolean nowait, Boolean passive, AMQShortString exchangeType) { super(); - + setName(exchangeName); - + put(Property.AUTO_DELETE, autoDelete); put(Property.TEMPORARY, autoDelete); put(Property.DURABLE, durable); @@ -204,14 +210,14 @@ public class ObjectProperties put(Property.PASSIVE, passive); put(Property.TYPE, exchangeType); } - + public ObjectProperties(Boolean autoDelete, Boolean durable, Boolean exclusive, Boolean nowait, Boolean passive, AMQShortString queueName, String owner) { super(); - + setName(queueName); - + put(Property.AUTO_DELETE, autoDelete); put(Property.TEMPORARY, autoDelete); put(Property.DURABLE, durable); @@ -220,7 +226,7 @@ public class ObjectProperties put(Property.PASSIVE, passive); put(Property.OWNER, owner); } - + public ObjectProperties(Boolean exclusive, Boolean noAck, Boolean noLocal, Boolean nowait, AMQQueue queue) { this(queue); @@ -230,17 +236,7 @@ public class ObjectProperties put(Property.EXCLUSIVE, exclusive); put(Property.NO_WAIT, nowait); } - - public List<String> getPropertyNames() - { - List<String> properties = new ArrayList<String>(); - for (Property property : _properties.keySet()) - { - properties.add(property.getName()); - } - return properties; - } - + public Boolean isSet(Property key) { return _properties.containsKey(key) && Boolean.valueOf(_properties.get(key)); @@ -255,17 +251,17 @@ public class ObjectProperties { return _properties.get(Property.NAME); } - + public void setName(String name) { _properties.put(Property.NAME, name); } - + public void setName(AMQShortString name) { put(Property.NAME, name); } - + public String put(Property key, AMQShortString value) { return put(key, value == null ? "" : value.asString()); @@ -275,7 +271,7 @@ public class ObjectProperties { return _properties.put(key, value == null ? "" : value.trim()); } - + public void put(Property key, Boolean value) { if (value != null) @@ -283,66 +279,64 @@ public class ObjectProperties _properties.put(key, Boolean.toString(value)); } } - + public boolean matches(ObjectProperties properties) { if (properties._properties.keySet().isEmpty()) { return true; } - + if (!_properties.keySet().containsAll(properties._properties.keySet())) { return false; } - + for (Map.Entry<Property,String> entry : properties._properties.entrySet()) { Property key = entry.getKey(); String ruleValue = entry.getValue(); - + String thisValue = _properties.get(key); - if (!valueMatches(thisValue, ruleValue)) + if (!valueMatches(thisValue, ruleValue)) { return false; } } - + return true; } - + private boolean valueMatches(String thisValue, String ruleValue) { return (StringUtils.isEmpty(ruleValue) || StringUtils.equals(thisValue, ruleValue)) || ruleValue.equals(STAR) - || (ruleValue.endsWith(STAR) + || (ruleValue.endsWith(STAR) && thisValue != null && thisValue.length() >= ruleValue.length() - 1 && thisValue.startsWith(ruleValue.substring(0, ruleValue.length() - 1))); } @Override - public boolean equals(Object o) + public boolean equals(Object obj) { - if (this == o) + if (obj == null) { - return true; + return false; } - if (o == null || getClass() != o.getClass()) + if (obj == this) { - return false; + return true; } - - ObjectProperties that = (ObjectProperties) o; - - if (_properties != null ? !_properties.equals(that._properties) : that._properties != null) + if (obj.getClass() != getClass()) { return false; } - - return true; + ObjectProperties rhs = (ObjectProperties) obj; + return new EqualsBuilder() + .append(_properties, rhs._properties).isEquals(); } @Override Modified: qpid/trunk/qpid/java/ivy.nexus.xml URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/ivy.nexus.xml?rev=1391430&r1=1391429&r2=1391430&view=diff ============================================================================== --- qpid/trunk/qpid/java/ivy.nexus.xml (original) +++ qpid/trunk/qpid/java/ivy.nexus.xml Fri Sep 28 12:46:06 2012 @@ -45,12 +45,6 @@ <artifact name="qpid-broker-plugins-access-control" type="jar.asc" ext="jar.asc"/> <artifact name="qpid-broker-plugins-access-control" type="source" ext="jar" e:classifier="sources"/> <artifact name="qpid-broker-plugins-access-control" type="source.asc" ext="jar.asc" e:classifier="sources"/> - <artifact name="qpid-broker-plugins-firewall" type="pom" ext="pom"/> - <artifact name="qpid-broker-plugins-firewall" type="pom.asc" ext="pom.asc"/> - <artifact name="qpid-broker-plugins-firewall" type="jar" ext="jar"/> - <artifact name="qpid-broker-plugins-firewall" type="jar.asc" ext="jar.asc"/> - <artifact name="qpid-broker-plugins-firewall" type="source" ext="jar" e:classifier="sources"/> - <artifact name="qpid-broker-plugins-firewall" type="source.asc" ext="jar.asc" e:classifier="sources"/> <artifact name="qpid-broker-plugins-management-http" type="pom" ext="pom"/> <artifact name="qpid-broker-plugins-management-http" type="pom.asc" ext="pom.asc"/> <artifact name="qpid-broker-plugins-management-http" type="jar" ext="jar"/> Modified: qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLTest.java URL: http://svn.apache.org/viewvc/qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLTest.java?rev=1391430&r1=1391429&r2=1391430&view=diff ============================================================================== --- qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLTest.java (original) +++ qpid/trunk/qpid/java/systests/src/main/java/org/apache/qpid/server/security/acl/ExternalACLTest.java Fri Sep 28 12:46:06 2012 @@ -404,4 +404,33 @@ public class ExternalACLTest extends Abs sess.rollback(); conn.close(); } + + public void setUpFirewallAllow() throws Exception + { + writeACLFile("test", "ACL ALLOW client ACCESS VIRTUALHOST from_network=\"127.0.0.1\""); + } + + public void testFirewallAllow() throws Exception + { + getConnection("test", "client", "guest"); + // test pass because we successfully connected + } + + public void setUpFirewallDeny() throws Exception + { + writeACLFile("test", "ACL DENY client ACCESS VIRTUALHOST from_network=\"127.0.0.1\""); + } + + public void testFirewallDeny() throws Exception + { + try + { + getConnection("test", "client", "guest"); + fail("We expected the connection to fail"); + } + catch(JMSException e) + { + // pass + } + } } --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
