This is an automated email from the ASF dual-hosted git repository.

orudyy pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/qpid-broker-j.git


The following commit(s) were added to refs/heads/main by this push:
     new 0ecc652  QPID-8565: [Broker-J] Enhancement of ACL rule predicates 
evaluation
0ecc652 is described below

commit 0ecc652fb6767b6a48a3b3018cf2f88e405ad015
Author: Marek Laca <[email protected]>
AuthorDate: Mon Nov 1 10:50:34 2021 +0100

    QPID-8565: [Broker-J] Enhancement of ACL rule predicates evaluation
    
    This closes #113
---
 .../security/access/config/AclRulePredicates.java  |  25 +-
 .../access/config/AclRulePredicatesBuilder.java    |  35 ++-
 .../security/access/config/RuleCollector.java      |  28 +-
 .../security/access/config/RulePredicate.java      |  65 ++++-
 .../access/config/predicates/AnyValue.java         |   1 -
 .../access/config/predicates/AttributeNames.java   |   7 +-
 .../security/access/config/predicates/Equal.java   |   1 -
 .../config/predicates/RulePredicateBuilder.java    | 105 +++----
 .../access/config/predicates/WildCard.java         |   1 -
 .../access/firewall/AbstractFirewallRuleImpl.java  |   5 +-
 .../security/access/config/AclFileParserTest.java  |  10 +
 .../predicates/RulePredicateBuilderTest.java       | 308 +++++++++++++++++++++
 12 files changed, 495 insertions(+), 96 deletions(-)

diff --git 
a/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/AclRulePredicates.java
 
b/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/AclRulePredicates.java
index 3d4cad4..de222fd 100644
--- 
a/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/AclRulePredicates.java
+++ 
b/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/AclRulePredicates.java
@@ -23,16 +23,15 @@ import java.util.Collection;
 import java.util.Collections;
 import java.util.EnumMap;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
 import java.util.stream.Collectors;
 
 import javax.security.auth.Subject;
 
-import 
org.apache.qpid.server.security.access.config.predicates.RulePredicateBuilder;
 import org.apache.qpid.server.security.access.firewall.FirewallRuleFactory;
 
 import com.google.common.base.Joiner;
-import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Iterables;
 
 public final class AclRulePredicates extends AbstractMap<Property, Set<Object>>
@@ -54,29 +53,15 @@ public final class AclRulePredicates extends 
AbstractMap<Property, Set<Object>>
     AclRulePredicates(AclRulePredicatesBuilder builder)
     {
         super();
-        _properties = newProperties(builder);
-        _rulePredicate = 
RulePredicateBuilder.build(builder.getParsedProperties());
+        _properties = Objects.requireNonNull(builder.newProperties());
+        _rulePredicate = Objects.requireNonNull(builder.newRulePredicate());
     }
 
     AclRulePredicates(FirewallRuleFactory factory, AclRulePredicatesBuilder 
builder)
     {
         super();
-        _properties = newProperties(builder);
-        _rulePredicate = RulePredicateBuilder.build(factory, 
builder.getParsedProperties());
-    }
-
-    private Map<Property, Set<Object>> newProperties(AclRulePredicatesBuilder 
builder)
-    {
-        final Map<Property, Set<Object>> properties = new 
EnumMap<>(Property.class);
-        for (final Map.Entry<Property, Set<?>> entry : 
builder.getParsedProperties().entrySet())
-        {
-            final Set<?> values = entry.getValue();
-            if (values != null && !values.isEmpty())
-            {
-                properties.put(entry.getKey(), 
ImmutableSet.builder().addAll(values).build());
-            }
-        }
-        return properties;
+        _properties = Objects.requireNonNull(builder.newProperties());
+        _rulePredicate = 
Objects.requireNonNull(builder.newRulePredicate(factory));
     }
 
     public Map<Property, String> getParsedProperties()
diff --git 
a/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/AclRulePredicatesBuilder.java
 
b/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/AclRulePredicatesBuilder.java
index a05317f..bd9d57a 100644
--- 
a/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/AclRulePredicatesBuilder.java
+++ 
b/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/AclRulePredicatesBuilder.java
@@ -27,8 +27,10 @@ import java.util.Map;
 import java.util.Objects;
 import java.util.Set;
 
+import 
org.apache.qpid.server.security.access.config.predicates.RulePredicateBuilder;
 import org.apache.qpid.server.security.access.firewall.FirewallRuleFactory;
 
+import com.google.common.collect.ImmutableSet;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
@@ -123,6 +125,16 @@ public final class AclRulePredicatesBuilder
         {
             _attributeNames.addAll(splitToSet(value));
         }
+        else if (property == Property.CONNECTION_LIMIT)
+        {
+            LOGGER.warn("The ACL Rule property 'connection_limit' was removed 
and it is not supported anymore");
+            return false;
+        }
+        else if (property == Property.CONNECTION_FREQUENCY_LIMIT)
+        {
+            LOGGER.warn("The ACL Rule property 'connection_frequency_limit' 
was removed and it is not supported anymore");
+            return false;
+        }
         else
         {
             _parsedProperties.put(property, 
Collections.singleton(sanitiseValue(property, value)));
@@ -192,8 +204,27 @@ public final class AclRulePredicatesBuilder
         }
     }
 
-    Map<Property, Set<?>> getParsedProperties()
+    Map<Property, Set<Object>> newProperties()
+    {
+        final Map<Property, Set<Object>> properties = new 
EnumMap<>(Property.class);
+        for (final Map.Entry<Property, Set<?>> entry : 
_parsedProperties.entrySet())
+        {
+            final Set<?> values = entry.getValue();
+            if (!values.isEmpty())
+            {
+                properties.put(entry.getKey(), 
ImmutableSet.builder().addAll(values).build());
+            }
+        }
+        return properties;
+    }
+
+    RulePredicate newRulePredicate()
+    {
+        return new RulePredicateBuilder().build(_parsedProperties);
+    }
+
+    RulePredicate newRulePredicate(FirewallRuleFactory factory)
     {
-        return Collections.unmodifiableMap(_parsedProperties);
+        return new RulePredicateBuilder(factory).build(_parsedProperties);
     }
 }
diff --git 
a/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/RuleCollector.java
 
b/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/RuleCollector.java
index 0981435..561b683 100644
--- 
a/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/RuleCollector.java
+++ 
b/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/RuleCollector.java
@@ -55,38 +55,38 @@ final class RuleCollector
 
     public void addRule(Integer position, Rule rule)
     {
-        final RuleKey key = new RuleKey(rule);
-        if (_ruleSet.containsKey(key))
+        // set rule number if needed
+        if (position == null)
         {
-            LOGGER.warn("Duplicate rule for the '{}'", key);
-            final Integer previousPosition = _ruleSet.get(key);
-            if (previousPosition > position)
+            if (_rules.isEmpty())
             {
-                _ruleSet.remove(key);
-                _rules.remove(previousPosition);
+                position = 0;
             }
             else
             {
-                return;
+                position = _rules.lastKey() + INCREMENT;
             }
         }
 
-        // set rule number if needed
-        if (position == null)
+        final RuleKey key = new RuleKey(rule);
+        if (_ruleSet.containsKey(key))
         {
-            if (_rules.isEmpty())
+            LOGGER.warn("Duplicate rule for the '{}'", key);
+            final Integer previousPosition = _ruleSet.get(key);
+            if (previousPosition > position)
             {
-                position = 0;
+                _ruleSet.remove(key);
+                _rules.remove(previousPosition);
             }
             else
             {
-                position = _rules.lastKey() + INCREMENT;
+                return;
             }
         }
 
         // save rule
         _rules.put(position, rule);
-        _ruleSet.put(new RuleKey(rule), position);
+        _ruleSet.put(key, position);
     }
 
     void setDefaultResult(final Result defaultResult)
diff --git 
a/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/RulePredicate.java
 
b/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/RulePredicate.java
index 73792df..76a3022 100644
--- 
a/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/RulePredicate.java
+++ 
b/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/RulePredicate.java
@@ -29,13 +29,30 @@ public interface RulePredicate
 
     default RulePredicate and(RulePredicate other)
     {
+        if (other instanceof Any)
+        {
+            return this;
+        }
+        if (other instanceof None)
+        {
+            return other;
+        }
         Objects.requireNonNull(other);
         return (operation, objectProperties, subject) ->
                 RulePredicate.this.matches(operation, objectProperties, 
subject)
                 && other.matches(operation, objectProperties, subject);
     }
 
-    default RulePredicate or(RulePredicate other) {
+    default RulePredicate or(RulePredicate other)
+    {
+        if (other instanceof Any)
+        {
+            return other;
+        }
+        if (other instanceof None)
+        {
+            return this;
+        }
         Objects.requireNonNull(other);
         return (operation, objectProperties, subject) ->
                 RulePredicate.this.matches(operation, objectProperties, 
subject)
@@ -47,9 +64,14 @@ public interface RulePredicate
         return Any.INSTANCE;
     }
 
+    static RulePredicate none()
+    {
+        return None.INSTANCE;
+    }
+
     final class Any implements RulePredicate
     {
-        public static final RulePredicate INSTANCE = new Any();
+        static final RulePredicate INSTANCE = new Any();
 
         private Any()
         {
@@ -62,5 +84,44 @@ public interface RulePredicate
             return true;
         }
 
+        @Override
+        public RulePredicate and(RulePredicate other)
+        {
+            return other;
+        }
+
+        @Override
+        public RulePredicate or(RulePredicate other)
+        {
+            return this;
+        }
+    }
+
+    final class None implements RulePredicate
+    {
+        static final RulePredicate INSTANCE = new None();
+
+        private None()
+        {
+            super();
+        }
+
+        @Override
+        public boolean matches(LegacyOperation operation, ObjectProperties 
objectProperties, Subject subject)
+        {
+            return false;
+        }
+
+        @Override
+        public RulePredicate and(RulePredicate other)
+        {
+            return this;
+        }
+
+        @Override
+        public RulePredicate or(RulePredicate other)
+        {
+            return other;
+        }
     }
 }
diff --git 
a/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/predicates/AnyValue.java
 
b/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/predicates/AnyValue.java
index 2b39e7d..a421b26 100644
--- 
a/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/predicates/AnyValue.java
+++ 
b/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/predicates/AnyValue.java
@@ -47,5 +47,4 @@ final class AnyValue implements RulePredicate
     {
         return objectProperties.get(_property) != null;
     }
-
 }
diff --git 
a/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/predicates/AttributeNames.java
 
b/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/predicates/AttributeNames.java
index a54d72a..5015b90 100644
--- 
a/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/predicates/AttributeNames.java
+++ 
b/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/predicates/AttributeNames.java
@@ -31,7 +31,7 @@ final class AttributeNames implements RulePredicate
 {
     private final Set<String> _attributeNames;
 
-    public static RulePredicate newInstance(Set<String> attributeNames)
+    static RulePredicate newInstance(Set<String> attributeNames)
     {
         return attributeNames.isEmpty() ? RulePredicate.any() : new 
AttributeNames(attributeNames);
     }
@@ -45,8 +45,7 @@ final class AttributeNames implements RulePredicate
     @Override
     public boolean matches(LegacyOperation operation, ObjectProperties 
objectProperties, Subject subject)
     {
-        return (operation != LegacyOperation.UPDATE ||
-                
_attributeNames.containsAll(objectProperties.getAttributeNames()));
+        return operation != LegacyOperation.UPDATE ||
+                
_attributeNames.containsAll(objectProperties.getAttributeNames());
     }
-
 }
diff --git 
a/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/predicates/Equal.java
 
b/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/predicates/Equal.java
index 5656e3e..815091f 100644
--- 
a/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/predicates/Equal.java
+++ 
b/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/predicates/Equal.java
@@ -50,5 +50,4 @@ final class Equal implements RulePredicate
     {
         return _value.equals(objectProperties.get(_property));
     }
-
 }
diff --git 
a/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/predicates/RulePredicateBuilder.java
 
b/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/predicates/RulePredicateBuilder.java
index 6f95ca8..b7c5332 100644
--- 
a/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/predicates/RulePredicateBuilder.java
+++ 
b/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/predicates/RulePredicateBuilder.java
@@ -18,86 +18,95 @@
  */
 package org.apache.qpid.server.security.access.config.predicates;
 
+import java.util.Collection;
 import java.util.Map;
+import java.util.Objects;
 import java.util.Set;
 import java.util.stream.Collectors;
 
 import org.apache.qpid.server.security.access.config.AclRulePredicatesBuilder;
-import org.apache.qpid.server.security.access.config.RulePredicate;
 import org.apache.qpid.server.security.access.config.Property;
+import org.apache.qpid.server.security.access.config.RulePredicate;
 import org.apache.qpid.server.security.access.firewall.FirewallRuleFactory;
 
 public final class RulePredicateBuilder
 {
-    private RulePredicateBuilder()
+    private final FirewallRuleFactory _factory;
+
+    public RulePredicateBuilder(FirewallRuleFactory factory)
     {
         super();
+        _factory = Objects.requireNonNull(factory);
     }
 
-    public static RulePredicate build(Map<Property, Set<?>> properties)
+    public RulePredicateBuilder()
     {
-        return build(new FirewallRuleFactory(), properties);
+        super();
+        _factory = new FirewallRuleFactory();
     }
 
-    public static RulePredicate build(FirewallRuleFactory firewallRuleFactory, 
Map<Property, Set<?>> properties)
+    public RulePredicate build(Map<Property, ? extends Collection<?>> 
properties)
     {
         RulePredicate predicate = RulePredicate.any();
-        for (final Map.Entry<Property, Set<?>> entry : properties.entrySet())
+        for (final Map.Entry<Property, ? extends Collection<?>> entry : 
properties.entrySet())
         {
-            predicate = predicate.and(build(firewallRuleFactory, 
entry.getKey(), entry.getValue()));
+            predicate = predicate.and(buildPredicate(entry.getKey(), 
entry.getValue()));
         }
         return predicate;
     }
 
-    public static RulePredicate build(FirewallRuleFactory firewallRuleFactory, 
Property property, Set<?> values)
+    private RulePredicate buildPredicate(Property property, Collection<?> 
values)
     {
-        RulePredicate predicate = RulePredicate.any();
+        if (values == null || values.isEmpty())
+        {
+            return RulePredicate.any();
+        }
         switch (property)
         {
             case FROM_HOSTNAME:
-                if (!values.isEmpty())
-                {
-                    predicate = firewallRuleFactory.createForHostname(
-                            
values.stream().map(Object::toString).collect(Collectors.toSet()));
-                }
-                break;
+                return _factory.createForHostname(toSet(values));
             case FROM_NETWORK:
-                if (!values.isEmpty())
-                {
-                    predicate = firewallRuleFactory.createForNetwork(
-                            
values.stream().map(Object::toString).collect(Collectors.toSet()));
-                }
-                break;
+                return _factory.createForNetwork(toSet(values));
             case ATTRIBUTES:
-                predicate = AttributeNames.newInstance(
-                        
values.stream().map(Object::toString).collect(Collectors.toSet()));
-                break;
+                return AttributeNames.newInstance(toSet(values));
             default:
-                for (final Object value : values)
-                {
-                    if (value instanceof String)
-                    {
-                        final String str = (String) value;
-                        if (AclRulePredicatesBuilder.WILD_CARD.equals(str))
-                        {
-                            predicate = 
predicate.and(AnyValue.newInstance(property));
-                        }
-                        else if 
(str.endsWith(AclRulePredicatesBuilder.WILD_CARD))
-                        {
-                            predicate = 
predicate.and(WildCard.newInstance(property,
-                                    str.substring(0, str.length() - 
AclRulePredicatesBuilder.WILD_CARD_LENGTH)));
-                        }
-                        else
-                        {
-                            predicate = 
predicate.and(Equal.newInstance(property, str));
-                        }
-                    }
-                    else
-                    {
-                        predicate = predicate.and(Equal.newInstance(property, 
value));
-                    }
-                }
+                return buildGenericPredicate(property, values);
+        }
+    }
+
+    private Set<String> toSet(Collection<?> hostnames)
+    {
+        return 
hostnames.stream().map(Object::toString).collect(Collectors.toSet());
+    }
+
+    private RulePredicate buildGenericPredicate(Property property, 
Collection<?> values)
+    {
+        RulePredicate predicate = RulePredicate.none();
+        for (final Object value : values)
+        {
+            if (value instanceof String)
+            {
+                predicate = predicate.or(string(property, (String) value));
+            }
+            else
+            {
+                predicate = predicate.or(Equal.newInstance(property, value));
+            }
         }
         return predicate;
     }
+
+    private RulePredicate string(Property property, String value)
+    {
+        if (AclRulePredicatesBuilder.WILD_CARD.equals(value))
+        {
+            return AnyValue.newInstance(property);
+        }
+        if (value.endsWith(AclRulePredicatesBuilder.WILD_CARD))
+        {
+            return WildCard.newInstance(property,
+                    value.substring(0, value.length() - 
AclRulePredicatesBuilder.WILD_CARD_LENGTH));
+        }
+        return Equal.newInstance(property, value);
+    }
 }
diff --git 
a/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/predicates/WildCard.java
 
b/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/predicates/WildCard.java
index aa6dd1f..a3ab5df 100644
--- 
a/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/predicates/WildCard.java
+++ 
b/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/config/predicates/WildCard.java
@@ -51,5 +51,4 @@ final class WildCard implements RulePredicate
         final Object value = objectProperties.get(_property);
         return (value instanceof String) && ((String) 
value).startsWith(_prefix);
     }
-
 }
diff --git 
a/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/AbstractFirewallRuleImpl.java
 
b/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/AbstractFirewallRuleImpl.java
index e335b2f..fc31e5c 100644
--- 
a/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/AbstractFirewallRuleImpl.java
+++ 
b/broker-plugins/access-control/src/main/java/org/apache/qpid/server/security/access/firewall/AbstractFirewallRuleImpl.java
@@ -34,6 +34,8 @@ abstract class AbstractFirewallRuleImpl implements 
FirewallRule
         super();
     }
 
+    abstract boolean matches(InetAddress addressOfClient);
+
     @Override
     public boolean matches(final Subject subject)
     {
@@ -47,7 +49,4 @@ abstract class AbstractFirewallRuleImpl implements 
FirewallRule
         }
         return true;
     }
-
-    abstract boolean matches(InetAddress addressOfClient);
-
 }
diff --git 
a/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/AclFileParserTest.java
 
b/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/AclFileParserTest.java
index 247e569..486ae2e 100644
--- 
a/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/AclFileParserTest.java
+++ 
b/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/AclFileParserTest.java
@@ -711,4 +711,14 @@ public class AclFileParserTest extends UnitTestBase
         assertEquals("Rule has unexpected object type", objectType, 
rule.getObjectType());
         assertEquals("Rule has unexpected predicates", predicates, 
rule.getPredicates());
     }
+
+    @Test
+    public void testConnectionLimitParsing() throws Exception
+    {
+        validateRule(writeACLConfig("ACL ALLOW all ACCESS VIRTUALHOST 
connection_limit=10 connection_frequency_limit=12"),
+                Rule.ALL,
+                LegacyOperation.ACCESS,
+                ObjectType.VIRTUALHOST,
+                EMPTY);
+    }
 }
diff --git 
a/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/predicates/RulePredicateBuilderTest.java
 
b/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/predicates/RulePredicateBuilderTest.java
new file mode 100644
index 0000000..bfbebe4
--- /dev/null
+++ 
b/broker-plugins/access-control/src/test/java/org/apache/qpid/server/security/access/config/predicates/RulePredicateBuilderTest.java
@@ -0,0 +1,308 @@
+/*
+ * 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.predicates;
+
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.security.auth.Subject;
+
+import org.apache.qpid.server.security.access.config.LegacyOperation;
+import org.apache.qpid.server.security.access.config.ObjectProperties;
+import org.apache.qpid.server.security.access.config.Property;
+import org.apache.qpid.server.security.access.config.RulePredicate;
+import org.apache.qpid.server.security.access.firewall.FirewallRuleFactory;
+import org.apache.qpid.server.security.auth.TestPrincipalUtils;
+import org.apache.qpid.test.utils.UnitTestBase;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import static 
org.apache.qpid.server.security.access.config.Property.ATTRIBUTES;
+import static org.apache.qpid.server.security.access.config.Property.COMPONENT;
+import static org.apache.qpid.server.security.access.config.Property.DURABLE;
+import static 
org.apache.qpid.server.security.access.config.Property.FROM_HOSTNAME;
+import static 
org.apache.qpid.server.security.access.config.Property.FROM_NETWORK;
+import static 
org.apache.qpid.server.security.access.config.Property.METHOD_NAME;
+import static org.apache.qpid.server.security.access.config.Property.NAME;
+import static 
org.apache.qpid.server.security.access.config.Property.ROUTING_KEY;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class RulePredicateBuilderTest extends UnitTestBase
+{
+    private final FirewallRuleFactory _firewallRuleFactory = 
mock(FirewallRuleFactory.class);
+    private final Subject _subject = 
TestPrincipalUtils.createTestSubject("TEST_USER");
+
+    private TestFirewallRule _firewallRule;
+    private RulePredicateBuilder _builder;
+
+    @Before
+    public void setUp() throws Exception
+    {
+        _firewallRule = new TestFirewallRule();
+        
when(_firewallRuleFactory.createForHostname(any())).thenReturn(_firewallRule);
+        
when(_firewallRuleFactory.createForNetwork(any())).thenReturn(_firewallRule);
+        _builder = new RulePredicateBuilder(_firewallRuleFactory);
+    }
+
+    @Test
+    public void testMatch_Attributes()
+    {
+        final RulePredicate predicate = _builder.build(
+                Collections.singletonMap(ATTRIBUTES, Arrays.asList("name", 
"port", "host", "active")));
+
+        final ObjectProperties action = new ObjectProperties();
+        action.addAttributeNames("name", "host", "port");
+
+        assertTrue(predicate.matches(LegacyOperation.UPDATE, action, 
_subject));
+        assertTrue(predicate.matches(LegacyOperation.ACCESS, action, 
_subject));
+    }
+
+    @Test
+    public void testMatch_Attributes_empty()
+    {
+        final RulePredicate predicate = _builder.build(
+                Collections.singletonMap(ATTRIBUTES, Collections.emptySet()));
+
+        final ObjectProperties action = new ObjectProperties();
+        action.addAttributeNames("name", "host", "port");
+
+        assertTrue(predicate.matches(LegacyOperation.UPDATE, action, 
_subject));
+        assertTrue(predicate.matches(LegacyOperation.ACCESS, action, 
_subject));
+    }
+
+    @Test
+    public void testDoesNotMatch_Attributes()
+    {
+        final RulePredicate predicate = _builder.build(
+                Collections.singletonMap(ATTRIBUTES, Arrays.asList("name", 
"port")));
+
+        final ObjectProperties action = new ObjectProperties();
+        action.addAttributeNames("name", "host", "port");
+
+        assertFalse(predicate.matches(LegacyOperation.UPDATE, action, 
_subject));
+        assertTrue(predicate.matches(LegacyOperation.ACCESS, action, 
_subject));
+    }
+
+    @Test
+    public void testMatch_Hostname()
+    {
+        _firewallRule.setSubject(_subject);
+        final RulePredicate predicate = _builder.build(
+                Collections.singletonMap(FROM_HOSTNAME, 
Collections.singleton("localhost")));
+
+        assertTrue(predicate.matches(LegacyOperation.PUBLISH, new 
ObjectProperties(), _subject));
+    }
+
+    @Test
+    public void testMatch_Hostname_empty()
+    {
+        _firewallRule.setSubject(_subject);
+        final RulePredicate predicate = _builder.build(
+                Collections.singletonMap(FROM_HOSTNAME, 
Collections.emptySet()));
+
+        assertTrue(predicate.matches(LegacyOperation.PUBLISH, new 
ObjectProperties(), _subject));
+    }
+
+    @Test
+    public void testDoesNotMatch_Hostname()
+    {
+        final RulePredicate predicate = _builder.build(
+                Collections.singletonMap(FROM_HOSTNAME, 
Collections.singleton("localhost")));
+
+        assertFalse(predicate.matches(LegacyOperation.PUBLISH, new 
ObjectProperties(), _subject));
+    }
+
+    @Test
+    public void testMatch_Network()
+    {
+        _firewallRule.setSubject(_subject);
+        final RulePredicate predicate = _builder.build(
+                Collections.singletonMap(FROM_NETWORK, 
Collections.singleton("localhost")));
+
+        assertTrue(predicate.matches(LegacyOperation.PUBLISH, new 
ObjectProperties(), _subject));
+    }
+
+    @Test
+    public void testMatch_Network_empty()
+    {
+        _firewallRule.setSubject(_subject);
+        final RulePredicate predicate = _builder.build(
+                Collections.singletonMap(FROM_NETWORK, 
Collections.emptySet()));
+
+        assertTrue(predicate.matches(LegacyOperation.PUBLISH, new 
ObjectProperties(), _subject));
+    }
+
+    @Test
+    public void testDoesNotMatch_Network()
+    {
+        final RulePredicate predicate = _builder.build(
+                Collections.singletonMap(FROM_NETWORK, 
Collections.singleton("localhost")));
+
+        assertFalse(predicate.matches(LegacyOperation.PUBLISH, new 
ObjectProperties(), _subject));
+    }
+
+    @Test
+    public void testMatch_Boolean()
+    {
+        final RulePredicate predicate = _builder.build(
+                Collections.singletonMap(DURABLE, 
Collections.singleton(Boolean.TRUE)));
+        final ObjectProperties op = new ObjectProperties();
+        op.put(DURABLE, true);
+        assertTrue(predicate.matches(LegacyOperation.PUBLISH, op, _subject));
+    }
+
+    @Test
+    public void testDoesNotMatch_Boolean()
+    {
+        final RulePredicate predicate = _builder.build(
+                Collections.singletonMap(DURABLE, 
Collections.singleton(Boolean.TRUE)));
+        final ObjectProperties op = new ObjectProperties();
+        op.put(DURABLE, false);
+        assertFalse(predicate.matches(LegacyOperation.PUBLISH, op, _subject));
+    }
+
+    @Test
+    public void testMatch_String()
+    {
+        final RulePredicate predicate = _builder.build(
+                Collections.singletonMap(NAME, 
Arrays.asList("Exchange.public.*", "Exchange.private.A")));
+
+        ObjectProperties op = new ObjectProperties(NAME, "Exchange.private.A");
+        assertTrue(predicate.matches(LegacyOperation.PUBLISH, op, _subject));
+
+        op = new ObjectProperties(NAME, "Exchange.public.ABC");
+        assertTrue(predicate.matches(LegacyOperation.PUBLISH, op, _subject));
+    }
+
+    @Test
+    public void testDoesNotMatch_String()
+    {
+        final RulePredicate predicate = _builder.build(
+                Collections.singletonMap(NAME, 
Arrays.asList("Exchange.public.*", "Exchange.private.A")));
+
+        final ObjectProperties op = new ObjectProperties(NAME, 
"Exchange.private.B");
+        assertFalse(predicate.matches(LegacyOperation.PUBLISH, op, _subject));
+    }
+
+    @Test
+    public void testMatch_AnyString()
+    {
+        final RulePredicate predicate = _builder.build(
+                Collections.singletonMap(NAME, Arrays.asList("*", 
"Exchange.private.ABC")));
+
+        final ObjectProperties op = new ObjectProperties(NAME, "ABC");
+        assertTrue(predicate.matches(LegacyOperation.PUBLISH, op, _subject));
+    }
+
+    @Test
+    public void testDoesNotMatch_AnyString()
+    {
+        final RulePredicate predicate = _builder.build(
+                Collections.singletonMap(NAME, Arrays.asList("*", 
"Exchange.private.ABC")));
+
+        assertFalse(predicate.matches(LegacyOperation.PUBLISH, new 
ObjectProperties(), _subject));
+    }
+
+    @Test
+    public void testMatch_Mixing()
+    {
+        final RulePredicate predicate = _builder.build(
+                Collections.singletonMap(DURABLE, Arrays.asList(Boolean.TRUE, 
"Yes")));
+
+        ObjectProperties op = new ObjectProperties();
+        op.put(DURABLE, true);
+        assertTrue(predicate.matches(LegacyOperation.PUBLISH, op, _subject));
+
+        op = new ObjectProperties();
+        op.put(DURABLE, "Yes");
+        assertTrue(predicate.matches(LegacyOperation.PUBLISH, op, _subject));
+    }
+
+    @Test
+    public void testDoesNotMatch_Mixing()
+    {
+        final RulePredicate predicate = _builder.build(
+                Collections.singletonMap(DURABLE, Arrays.asList(Boolean.TRUE, 
"Y*")));
+
+        ObjectProperties op = new ObjectProperties();
+        op.put(DURABLE, false);
+        assertFalse(predicate.matches(LegacyOperation.PUBLISH, op, _subject));
+
+        op = new ObjectProperties();
+        op.put(DURABLE, "Not");
+        assertFalse(predicate.matches(LegacyOperation.PUBLISH, op, _subject));
+    }
+
+    @Test
+    public void testMatch_Multiple()
+    {
+        final Map<Property, List<?>> properties = new HashMap<>();
+        properties.put(DURABLE, Collections.singletonList(Boolean.TRUE));
+        properties.put(NAME, Arrays.asList("Exchange.public.*", 
"Exchange.private.A", "Exchange.private.B"));
+        properties.put(COMPONENT, Collections.singletonList("*"));
+        properties.put(METHOD_NAME, Collections.emptyList());
+        properties.put(ROUTING_KEY, null);
+        final RulePredicate predicate = _builder.build(properties);
+
+        final ObjectProperties op = new ObjectProperties();
+        op.put(DURABLE, true);
+        op.put(COMPONENT, "queue");
+        op.setName("Exchange.public.A");
+        assertTrue(predicate.matches(LegacyOperation.PUBLISH, op, _subject));
+    }
+
+    @Test
+    public void testDoesNotMatch_Multiple()
+    {
+        final Map<Property, List<?>> properties = new HashMap<>();
+        properties.put(DURABLE, Collections.singletonList(Boolean.TRUE));
+        properties.put(NAME, Arrays.asList("Exchange.public.*", 
"Exchange.private.A", "Exchange.private.B"));
+        properties.put(COMPONENT, Collections.singletonList("*"));
+        properties.put(METHOD_NAME, Collections.emptyList());
+        properties.put(ROUTING_KEY, null);
+        final RulePredicate predicate = _builder.build(properties);
+
+        ObjectProperties op = new ObjectProperties();
+        op.put(DURABLE, false);
+        op.put(COMPONENT, "exchange");
+        op.setName("Exchange.public.A");
+        assertFalse(predicate.matches(LegacyOperation.PUBLISH, op, _subject));
+
+        op = new ObjectProperties();
+        op.put(DURABLE, true);
+        op.setName("Exchange.public.A");
+        assertFalse(predicate.matches(LegacyOperation.PUBLISH, op, _subject));
+
+        op = new ObjectProperties();
+        op.put(DURABLE, true);
+        op.put(COMPONENT, "exchange");
+        op.setName("Exchange.private.C");
+        assertFalse(predicate.matches(LegacyOperation.PUBLISH, op, _subject));
+
+        assertFalse(predicate.matches(LegacyOperation.PUBLISH, new 
ObjectProperties(), _subject));
+    }
+}

---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to