incubator-sling-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From stefane...@apache.org
Subject svn commit: r1564786 - in /sling/trunk/bundles/extensions/discovery/impl/src: main/java/org/apache/sling/discovery/impl/topology/connector/ main/java/org/apache/sling/discovery/impl/topology/connector/wl/ main/resources/OSGI-INF/metatype/ test/java/org...
Date Wed, 05 Feb 2014 14:29:12 GMT
Author: stefanegli
Date: Wed Feb  5 14:29:11 2014
New Revision: 1564786

URL: http://svn.apache.org/r1564786
Log:
SLING-3001 : support for wildcards (star, questionmark) and IP-subnets (CIDR or IP subnetmask)
added to whitelist

Added:
    sling/trunk/bundles/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/topology/connector/wl/
    sling/trunk/bundles/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/topology/connector/wl/SubnetWhitelistEntry.java
    sling/trunk/bundles/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/topology/connector/wl/WhitelistEntry.java
    sling/trunk/bundles/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/topology/connector/wl/WildcardWhitelistEntry.java
    sling/trunk/bundles/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/topology/connector/TopologyConnectorServletTest.java
Modified:
    sling/trunk/bundles/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/topology/connector/TopologyConnectorServlet.java
    sling/trunk/bundles/extensions/discovery/impl/src/main/resources/OSGI-INF/metatype/metatype.properties

Modified: sling/trunk/bundles/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/topology/connector/TopologyConnectorServlet.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/topology/connector/TopologyConnectorServlet.java?rev=1564786&r1=1564785&r2=1564786&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/topology/connector/TopologyConnectorServlet.java
(original)
+++ sling/trunk/bundles/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/topology/connector/TopologyConnectorServlet.java
Wed Feb  5 14:29:11 2014
@@ -20,10 +20,15 @@ package org.apache.sling.discovery.impl.
 
 import java.io.IOException;
 import java.io.PrintWriter;
+import java.util.ArrayList;
 import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
 import java.util.Set;
+import java.util.StringTokenizer;
 
 import javax.servlet.ServletException;
+import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
 import org.apache.felix.scr.annotations.Property;
@@ -40,6 +45,9 @@ import org.apache.sling.discovery.impl.c
 import org.apache.sling.discovery.impl.topology.announcement.Announcement;
 import org.apache.sling.discovery.impl.topology.announcement.AnnouncementFilter;
 import org.apache.sling.discovery.impl.topology.announcement.AnnouncementRegistry;
+import org.apache.sling.discovery.impl.topology.connector.wl.SubnetWhitelistEntry;
+import org.apache.sling.discovery.impl.topology.connector.wl.WhitelistEntry;
+import org.apache.sling.discovery.impl.topology.connector.wl.WildcardWhitelistEntry;
 import org.osgi.service.component.ComponentContext;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
@@ -69,25 +77,74 @@ public class TopologyConnectorServlet ex
     @Reference
     private Config config;
 
-    /** the set of ips/hostnames which are allowed to connect to this servlet **/
-    private final Set<String> whitelist = new HashSet<String>();
+    /** 
+     * This list contains WhitelistEntry (ips/hostnames, cidr, wildcards),
+     * each filtering some hostname/addresses that are allowed to connect to this servlet.
+     **/
+    private final List<WhitelistEntry> whitelist = new ArrayList<WhitelistEntry>();
+    
+    /** Set of plaintext whitelist entries - for faster lookups **/
+    private final Set<String> plaintextWhitelist = new HashSet<String>();
 
     private TopologyRequestValidator requestValidator;
 
-
     protected void activate(final ComponentContext context) {
         whitelist.clear();
         if (!config.isHmacEnabled()) {
             String[] whitelistConfig = config.getTopologyConnectorWhitelist();
-            for (int i = 0; i < whitelistConfig.length; i++) {
-                String aWhitelistEntry = whitelistConfig[i];
-                logger.info("activate: adding whitelist entry: " + aWhitelistEntry);
-                whitelist.add(aWhitelistEntry);
-            }
+            initWhitelist(whitelistConfig);
         }
         requestValidator = new TopologyRequestValidator(config);
     }
 
+    void initWhitelist(String[] whitelistConfig) {
+        if (whitelistConfig==null) {
+            return;
+        }
+        for (int i = 0; i < whitelistConfig.length; i++) {
+            String aWhitelistEntry = whitelistConfig[i];
+            
+            WhitelistEntry whitelistEntry = null;
+            if (aWhitelistEntry.contains(".") && aWhitelistEntry.contains("/")) {
+                // then this is a CIDR notation
+                try{
+                    whitelistEntry = new SubnetWhitelistEntry(aWhitelistEntry);
+                } catch(Exception e) {
+                    logger.error("activate: wrongly formatted CIDR subnet definition. Expected
eg '1.2.3.4/24'. ignoring: "+aWhitelistEntry);
+                    continue;
+                }
+            } else if (aWhitelistEntry.contains(".") && aWhitelistEntry.contains("
")) {
+                // then this is a IP/subnet-mask notation
+                try{
+                    final StringTokenizer st = new StringTokenizer(aWhitelistEntry, " ");
+                    final String ip = st.nextToken();
+                    if (st.hasMoreTokens()) {
+                        final String mask = st.nextToken();
+                        if (st.hasMoreTokens()) {
+                            logger.error("activate: wrongly formatted ip subnet definition.
Expected '10.1.2.3 255.0.0.0'. Ignoring: "+aWhitelistEntry);
+                            continue;
+                        }
+                        whitelistEntry = new SubnetWhitelistEntry(ip, mask);
+                    }
+                } catch(Exception e) {
+                    logger.error("activate: wrongly formatted ip subnet definition. Expected
'10.1.2.3 255.0.0.0'. Ignoring: "+aWhitelistEntry);
+                    continue;
+                }
+            }
+            if (whitelistEntry==null) {
+                if (aWhitelistEntry.contains("*") || aWhitelistEntry.contains("?")) {
+                    whitelistEntry = new WildcardWhitelistEntry(aWhitelistEntry);
+                } else {
+                    plaintextWhitelist.add(aWhitelistEntry);
+                }
+            }
+            logger.info("activate: adding whitelist entry: " + aWhitelistEntry);
+            if (whitelistEntry!=null) {
+                whitelist.add(whitelistEntry);
+            }
+        }
+    }
+
     @Override
     protected void doDelete(SlingHttpServletRequest request,
             SlingHttpServletResponse response) throws ServletException,
@@ -214,15 +271,26 @@ public class TopologyConnectorServlet ex
         }
 
     }
-
+    
     /** Checks if the provided request's remote server is whitelisted **/
-    private boolean isWhitelisted(final SlingHttpServletRequest request) {
+    boolean isWhitelisted(final HttpServletRequest request) {
         if (config.isHmacEnabled()) {
-            return requestValidator.isTrusted(request);
-        } else {
-            if (whitelist.contains(request.getRemoteAddr())) {
-                return true;
-            } else if (whitelist.contains(request.getRemoteHost())) {
+            final boolean isTrusted = requestValidator.isTrusted(request);
+            if (!isTrusted) {
+                logger.info("isWhitelisted: rejecting distrusted " + request.getRemoteAddr()
+                        + ", " + request.getRemoteHost());
+            }
+            return isTrusted;
+        }
+        
+        if (plaintextWhitelist.contains(request.getRemoteHost()) ||
+                plaintextWhitelist.contains(request.getRemoteAddr())) {
+            return true;
+        }
+
+        for (Iterator<WhitelistEntry> it = whitelist.iterator(); it.hasNext();) {
+            WhitelistEntry whitelistEntry = it.next();
+            if (whitelistEntry.accepts(request)) {
                 return true;
             }
         }

Added: sling/trunk/bundles/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/topology/connector/wl/SubnetWhitelistEntry.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/topology/connector/wl/SubnetWhitelistEntry.java?rev=1564786&view=auto
==============================================================================
--- sling/trunk/bundles/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/topology/connector/wl/SubnetWhitelistEntry.java
(added)
+++ sling/trunk/bundles/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/topology/connector/wl/SubnetWhitelistEntry.java
Wed Feb  5 14:29:11 2014
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.discovery.impl.topology.connector.wl;
+
+import javax.servlet.ServletRequest;
+
+import org.apache.commons.net.util.SubnetUtils;
+import org.apache.commons.net.util.SubnetUtils.SubnetInfo;
+
+/**
+ * Implementation of a WhitelistEntry which accepts
+ * cidr and ip mask notations.
+ */
+public class SubnetWhitelistEntry implements WhitelistEntry {
+
+    private final SubnetInfo subnetInfo;
+    
+    public SubnetWhitelistEntry(String cidrNotation) {
+        subnetInfo = new SubnetUtils(cidrNotation).getInfo();
+    }
+    
+    public SubnetWhitelistEntry(String ip, String subnetMask) {
+        subnetInfo = new SubnetUtils(ip, subnetMask).getInfo();
+    }
+    
+    public boolean accepts(ServletRequest request) {
+        final String remoteAddr = request.getRemoteAddr();
+        return subnetInfo.isInRange(remoteAddr);
+    }
+
+}

Added: sling/trunk/bundles/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/topology/connector/wl/WhitelistEntry.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/topology/connector/wl/WhitelistEntry.java?rev=1564786&view=auto
==============================================================================
--- sling/trunk/bundles/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/topology/connector/wl/WhitelistEntry.java
(added)
+++ sling/trunk/bundles/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/topology/connector/wl/WhitelistEntry.java
Wed Feb  5 14:29:11 2014
@@ -0,0 +1,35 @@
+/*
+ * 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.sling.discovery.impl.topology.connector.wl;
+
+import javax.servlet.ServletRequest;
+
+/**
+ * A WhitelistEntry is capable of accepting certain requests
+ * depending on a configuration.
+ */
+public interface WhitelistEntry {
+
+    /**
+     * @param request the incoming request which should be accepted or rejected
+     * @return true if the request is accepted by this WhitelistEntry
+     */
+    public boolean accepts(ServletRequest request);
+    
+}

Added: sling/trunk/bundles/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/topology/connector/wl/WildcardWhitelistEntry.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/topology/connector/wl/WildcardWhitelistEntry.java?rev=1564786&view=auto
==============================================================================
--- sling/trunk/bundles/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/topology/connector/wl/WildcardWhitelistEntry.java
(added)
+++ sling/trunk/bundles/extensions/discovery/impl/src/main/java/org/apache/sling/discovery/impl/topology/connector/wl/WildcardWhitelistEntry.java
Wed Feb  5 14:29:11 2014
@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.sling.discovery.impl.topology.connector.wl;
+
+import javax.servlet.ServletRequest;
+
+import org.apache.sling.discovery.impl.common.WildcardHelper;
+
+/**
+ * Implementation of a WhitelistEntry which can accept
+ * wildcards (* and ?) in both IP and hostname
+ */
+public class WildcardWhitelistEntry implements WhitelistEntry {
+
+    private final String hostOrAddressWithWildcard;
+    
+    public WildcardWhitelistEntry(String hostOrAddressWithWildcard) {
+        this.hostOrAddressWithWildcard = hostOrAddressWithWildcard;
+    }
+    
+    public boolean accepts(ServletRequest request) {
+        if (WildcardHelper.matchesWildcard(request.getRemoteAddr(), hostOrAddressWithWildcard))
{
+            return true;
+        }
+        if (WildcardHelper.matchesWildcard(request.getRemoteHost(), hostOrAddressWithWildcard))
{
+            return true;
+        }
+        return false;
+    }
+
+}

Modified: sling/trunk/bundles/extensions/discovery/impl/src/main/resources/OSGI-INF/metatype/metatype.properties
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/discovery/impl/src/main/resources/OSGI-INF/metatype/metatype.properties?rev=1564786&r1=1564785&r2=1564786&view=diff
==============================================================================
--- sling/trunk/bundles/extensions/discovery/impl/src/main/resources/OSGI-INF/metatype/metatype.properties
(original)
+++ sling/trunk/bundles/extensions/discovery/impl/src/main/resources/OSGI-INF/metatype/metatype.properties
Wed Feb  5 14:29:11 2014
@@ -44,7 +44,10 @@ topologyConnectorUrls.description = URLs
 
 topologyConnectorWhitelist.name = Topology Connector Whitelist
 topologyConnectorWhitelist.description = List of IPs and/or hostnames which are allowed to
\
- connect to the connector URL.
+ connect to the connector URL. There are four variants here: 1. provide a plain hostname.
\
+ 2. provide an IP address. 3. provide a hostname or IP address with wildcards (* or ?). \
+ 4. provide an IP address with a subnet mask, either using the CIDR notation: 1.2.3.4/24
\
+ or an IP address, space, subnet mask: 1.2.3.4 255.255.255.0)
 
 discoveryResourcePath.name = Discovery Resource Path
 discoveryResourcePath.description = Path of resource where to keep discovery information.
\

Added: sling/trunk/bundles/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/topology/connector/TopologyConnectorServletTest.java
URL: http://svn.apache.org/viewvc/sling/trunk/bundles/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/topology/connector/TopologyConnectorServletTest.java?rev=1564786&view=auto
==============================================================================
--- sling/trunk/bundles/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/topology/connector/TopologyConnectorServletTest.java
(added)
+++ sling/trunk/bundles/extensions/discovery/impl/src/test/java/org/apache/sling/discovery/impl/topology/connector/TopologyConnectorServletTest.java
Wed Feb  5 14:29:11 2014
@@ -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.sling.discovery.impl.topology.connector;
+
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import javax.servlet.http.HttpServletRequest;
+
+import junitx.util.PrivateAccessor;
+
+import org.apache.sling.discovery.impl.Config;
+import org.junit.Before;
+import org.junit.Test;
+
+public class TopologyConnectorServletTest {
+
+    private TopologyConnectorServlet servlet;
+    
+    private HttpServletRequest getRequest(String host, String addr) {
+        HttpServletRequest result = mock(HttpServletRequest.class);
+        when(result.getRemoteAddr()).thenReturn(addr);
+        when(result.getRemoteHost()).thenReturn(host);
+        return result;
+    }
+    
+    @Before
+    public void setUp() throws Exception {
+        servlet = new TopologyConnectorServlet();
+        Config config = mock(Config.class);
+        PrivateAccessor.setField(servlet, "config", config);
+    }
+    
+    @Test
+    public void testNull() throws Exception {
+        servlet.initWhitelist(null); // should work fine
+        servlet.initWhitelist(new String[0]); // should also work fine
+    }
+    
+    @Test
+    public void testPlaintextWhitelist_enabled() throws Exception {
+        servlet.initWhitelist(new String[] {"foo", "bar"});
+        assertTrue(servlet.isWhitelisted(getRequest("foo", "x")));
+        assertTrue(servlet.isWhitelisted(getRequest("bar", "x")));
+        assertTrue(servlet.isWhitelisted(getRequest("y", "foo")));
+        assertTrue(servlet.isWhitelisted(getRequest("y", "bar")));
+    }
+    
+    @Test
+    public void testPlaintextWhitelist_disabled() throws Exception {
+        servlet.initWhitelist(new String[] {});
+        assertFalse(servlet.isWhitelisted(getRequest("foo", "x")));
+        assertFalse(servlet.isWhitelisted(getRequest("bar", "x")));
+        assertFalse(servlet.isWhitelisted(getRequest("y", "foo")));
+        assertFalse(servlet.isWhitelisted(getRequest("y", "bar")));
+    }
+    
+    @Test
+    public void testWildcardWhitelist() throws Exception {
+        servlet.initWhitelist(new String[] {"foo*", "b?r", "test"});
+        assertTrue(servlet.isWhitelisted(getRequest("foo", "x")));
+        assertTrue(servlet.isWhitelisted(getRequest("fooo", "x")));
+        assertTrue(servlet.isWhitelisted(getRequest("foooo", "x")));
+        assertTrue(servlet.isWhitelisted(getRequest("x", "foo")));
+        assertTrue(servlet.isWhitelisted(getRequest("x", "fooo")));
+        assertTrue(servlet.isWhitelisted(getRequest("x", "foooo")));
+        assertTrue(servlet.isWhitelisted(getRequest("bur", "x")));
+        assertTrue(servlet.isWhitelisted(getRequest("x", "bur")));
+        assertTrue(servlet.isWhitelisted(getRequest("x", "test")));
+        assertFalse(servlet.isWhitelisted(getRequest("fo", "x")));
+        assertFalse(servlet.isWhitelisted(getRequest("x", "testy")));
+    }
+    
+    @Test
+    public void testSubnetMaskWhitelist() throws Exception {
+        servlet.initWhitelist(new String[] {"1.2.3.4/24", "2.3.4.1/30", "3.4.5.6/31"});
+        
+        assertTrue(servlet.isWhitelisted(getRequest("foo", "1.2.3.4")));
+        assertFalse(servlet.isWhitelisted(getRequest("1.2.3.4", "1.2.4.3")));
+        assertTrue(servlet.isWhitelisted(getRequest("foo", "1.2.3.1")));
+        assertTrue(servlet.isWhitelisted(getRequest("foo", "1.2.3.254")));
+        assertFalse(servlet.isWhitelisted(getRequest("foo", "1.2.4.5")));
+
+        assertTrue(servlet.isWhitelisted(getRequest("foo", "2.3.4.1")));
+        assertTrue(servlet.isWhitelisted(getRequest("foo", "2.3.4.2")));
+        assertFalse(servlet.isWhitelisted(getRequest("foo", "2.3.4.3")));
+        assertFalse(servlet.isWhitelisted(getRequest("foo", "2.3.4.4")));
+
+        assertFalse(servlet.isWhitelisted(getRequest("foo", "3.4.5.1")));
+        assertFalse(servlet.isWhitelisted(getRequest("foo", "3.4.5.2")));
+        assertFalse(servlet.isWhitelisted(getRequest("foo", "3.4.5.3")));
+        assertFalse(servlet.isWhitelisted(getRequest("foo", "3.4.5.4")));
+        assertFalse(servlet.isWhitelisted(getRequest("foo", "3.4.5.5")));
+        assertFalse(servlet.isWhitelisted(getRequest("foo", "3.4.5.6")));
+        assertFalse(servlet.isWhitelisted(getRequest("foo", "3.4.5.7")));
+    }
+}



Mime
View raw message