CAMEL-6424: camel-netty-http added support for basic auth. Work in progress.


Project: http://git-wip-us.apache.org/repos/asf/camel/repo
Commit: http://git-wip-us.apache.org/repos/asf/camel/commit/342bfe1d
Tree: http://git-wip-us.apache.org/repos/asf/camel/tree/342bfe1d
Diff: http://git-wip-us.apache.org/repos/asf/camel/diff/342bfe1d

Branch: refs/heads/master
Commit: 342bfe1dc3966621438b5923b5f0d4427f26c3d8
Parents: 8042c33
Author: Claus Ibsen <davscl...@apache.org>
Authored: Tue Jul 16 13:51:32 2013 +0200
Committer: Claus Ibsen <davscl...@apache.org>
Committed: Tue Jul 16 13:51:46 2013 +0200

----------------------------------------------------------------------
 components/camel-netty-http/pom.xml             |   2 +-
 .../netty/http/DefaultSecurityConstraint.java   | 127 ------------------
 .../netty/http/JAASSecurityAuthenticator.java   |  72 +---------
 .../netty/http/SecurityAuthenticator.java       |   9 ++
 .../http/SecurityAuthenticatorSupport.java      | 127 ++++++++++++++++++
 .../netty/http/SecurityConstraintMapping.java   | 133 +++++++++++++++++++
 .../http/DefaultSecurityConstraintTest.java     | 108 ---------------
 .../component/netty/http/MyLoginModule.java     |  10 ++
 .../component/netty/http/MyRolePrincipal.java   |  33 +++++
 .../NettyHttpBasicAuthConstraintMapperTest.java |   2 +-
 ...HttpSimpleBasicAuthConstraintMapperTest.java |   2 +-
 .../http/SecurityConstraintMappingTest.java     | 108 +++++++++++++++
 .../http/SpringNettyHttpBasicAuthTest.java      | 115 ++++++++++++++++
 .../netty/http/SpringNettyHttpBasicAuthTest.xml |  70 ++++++++++
 14 files changed, 609 insertions(+), 309 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/camel/blob/342bfe1d/components/camel-netty-http/pom.xml
----------------------------------------------------------------------
diff --git a/components/camel-netty-http/pom.xml 
b/components/camel-netty-http/pom.xml
index 4e8057a..ec51526 100644
--- a/components/camel-netty-http/pom.xml
+++ b/components/camel-netty-http/pom.xml
@@ -44,7 +44,7 @@
                <!-- testing -->
                <dependency>
                        <groupId>org.apache.camel</groupId>
-                       <artifactId>camel-test</artifactId>
+                       <artifactId>camel-test-spring</artifactId>
                        <scope>test</scope>
                </dependency>
                <dependency>

http://git-wip-us.apache.org/repos/asf/camel/blob/342bfe1d/components/camel-netty-http/src/main/java/org/apache/camel/component/netty/http/DefaultSecurityConstraint.java
----------------------------------------------------------------------
diff --git 
a/components/camel-netty-http/src/main/java/org/apache/camel/component/netty/http/DefaultSecurityConstraint.java
 
b/components/camel-netty-http/src/main/java/org/apache/camel/component/netty/http/DefaultSecurityConstraint.java
deleted file mode 100644
index 91effe5..0000000
--- 
a/components/camel-netty-http/src/main/java/org/apache/camel/component/netty/http/DefaultSecurityConstraint.java
+++ /dev/null
@@ -1,127 +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.camel.component.netty.http;
-
-import java.util.LinkedHashSet;
-import java.util.Map;
-import java.util.Set;
-
-import org.apache.camel.util.EndpointHelper;
-
-/**
- * A default {@link SecurityConstraint} which can be used to define a set of 
mappings to
- * as constraints.
- * <p/>
- * This constraint will match as <tt>true</tt> if no inclusions has been 
defined.
- * First all the inclusions is check for matching. If a inclusion matches,
- * then the exclusion is checked, and if any of them matches, then the 
exclusion
- * will override the match and force returning <tt>false</tt>.
- * <p/>
- * Wildcards and regular expressions is supported as this implementation uses
- * {@link EndpointHelper#matchPattern(String, String)} method for matching.
- * <p/>
- * This restricted constraint allows you to setup context path rules that will 
restrict
- * access to paths, and then override and have exclusions that may allow 
access to
- * public paths.
- */
-public class DefaultSecurityConstraint implements SecurityConstraint {
-
-    // url -> roles
-    private Map<String, String> inclusions;
-    // url
-    private Set<String> exclusions;
-
-    @Override
-    public String restricted(String url) {
-        // check excluded first
-        if (excludedUrl(url)) {
-            return null;
-        }
-
-        // is the url restricted?
-        String constraint = includedUrl(url);
-        if (constraint == null) {
-            return null;
-        }
-
-        // is there any roles for the restricted url?
-        String roles = inclusions != null ? inclusions.get(constraint) : null;
-        if (roles == null) {
-            // use wildcard to indicate any role is accepted
-            return "*";
-        } else {
-            return roles;
-        }
-    }
-
-    private String includedUrl(String url) {
-        if (inclusions != null && !inclusions.isEmpty()) {
-            for (String constraint : inclusions.keySet()) {
-                if (EndpointHelper.matchPattern(url, constraint)) {
-                    return constraint;
-                }
-            }
-            // not in included so return null as its not restricted
-            return null;
-        }
-
-        // by default if no included has been configured then everything is 
restricted
-        return "*";
-    }
-
-    private boolean excludedUrl(String url) {
-        if (exclusions != null && !exclusions.isEmpty()) {
-            for (String constraint : exclusions) {
-                if (EndpointHelper.matchPattern(url, constraint)) {
-                    // force not matches if this was an exclusion
-                    return true;
-                }
-            }
-        }
-
-        return false;
-    }
-
-    public void addInclusion(String constraint) {
-        if (inclusions == null) {
-            inclusions = new java.util.LinkedHashMap<String, String>();
-        }
-        inclusions.put(constraint, null);
-    }
-
-    public void addInclusion(String constraint, String roles) {
-        if (inclusions == null) {
-            inclusions = new java.util.LinkedHashMap<String, String>();
-        }
-        inclusions.put(constraint, roles);
-    }
-
-    public void addExclusion(String constraint) {
-        if (exclusions == null) {
-            exclusions = new LinkedHashSet<String>();
-        }
-        exclusions.add(constraint);
-    }
-
-    public void setInclusions(Map<String, String> inclusions) {
-        this.inclusions = inclusions;
-    }
-
-    public void setExclusions(Set<String> exclusions) {
-        this.exclusions = exclusions;
-    }
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/342bfe1d/components/camel-netty-http/src/main/java/org/apache/camel/component/netty/http/JAASSecurityAuthenticator.java
----------------------------------------------------------------------
diff --git 
a/components/camel-netty-http/src/main/java/org/apache/camel/component/netty/http/JAASSecurityAuthenticator.java
 
b/components/camel-netty-http/src/main/java/org/apache/camel/component/netty/http/JAASSecurityAuthenticator.java
index fd52ca8..09204dd 100644
--- 
a/components/camel-netty-http/src/main/java/org/apache/camel/component/netty/http/JAASSecurityAuthenticator.java
+++ 
b/components/camel-netty-http/src/main/java/org/apache/camel/component/netty/http/JAASSecurityAuthenticator.java
@@ -16,15 +16,8 @@
  */
 package org.apache.camel.component.netty.http;
 
-import java.io.IOException;
 import java.security.Principal;
-import java.util.Locale;
 import javax.security.auth.Subject;
-import javax.security.auth.callback.Callback;
-import javax.security.auth.callback.CallbackHandler;
-import javax.security.auth.callback.NameCallback;
-import javax.security.auth.callback.PasswordCallback;
-import javax.security.auth.callback.UnsupportedCallbackException;
 import javax.security.auth.login.LoginContext;
 import javax.security.auth.login.LoginException;
 
@@ -35,23 +28,9 @@ import org.slf4j.LoggerFactory;
 /**
  * A JAAS based {@link SecurityAuthenticator} implementation.
  */
-public class JAASSecurityAuthenticator implements SecurityAuthenticator {
+public class JAASSecurityAuthenticator extends SecurityAuthenticatorSupport {
 
     private static final Logger LOG = 
LoggerFactory.getLogger(JAASSecurityAuthenticator.class);
-    private String name;
-    private String roleClassNames;
-
-    public void setName(String name) {
-        this.name = name;
-    }
-
-    public String getName() {
-        return name;
-    }
-
-    public void setRoleClassNames(String roleClassNames) {
-        this.roleClassNames = roleClassNames;
-    }
 
     @Override
     public Subject login(HttpPrincipal principal) throws LoginException {
@@ -90,53 +69,4 @@ public class JAASSecurityAuthenticator implements 
SecurityAuthenticator {
         LOG.debug("Logout username: {} successful", username);
     }
 
-    @Override
-    public String getUserRoles(Subject subject) {
-        StringBuilder sb = new StringBuilder();
-        for (Principal p : subject.getPrincipals()) {
-            if (roleClassNames == null) {
-                // by default assume its a role when the classname has role in 
its name
-                if (p.getName().toLowerCase(Locale.US).contains("role")) {
-                    if (sb.length() > 0) {
-                        sb.append(",");
-                    }
-                    sb.append(p.getName());
-                }
-            }
-        }
-        if (sb.length() > 0) {
-            return sb.toString();
-        } else {
-            return null;
-        }
-    }
-
-    /**
-     * {@link CallbackHandler} that provides the username and password.
-     */
-    private final class HttpPrincipalCallbackHandler implements 
CallbackHandler {
-
-        private final HttpPrincipal principal;
-
-        private HttpPrincipalCallbackHandler(HttpPrincipal principal) {
-            this.principal = principal;
-        }
-
-        @Override
-        public void handle(Callback[] callbacks) throws IOException, 
UnsupportedCallbackException {
-            for (Callback callback : callbacks) {
-                LOG.trace("Callback {}", callback);
-                if (callback instanceof PasswordCallback) {
-                    PasswordCallback pc = (PasswordCallback) callback;
-                    LOG.trace("Setting password on callback {}", pc);
-                    pc.setPassword(principal.getPassword().toCharArray());
-                } else if (callback instanceof NameCallback) {
-                    NameCallback nc = (NameCallback) callback;
-                    LOG.trace("Setting username on callback {}", nc);
-                    nc.setName(principal.getName());
-                }
-            }
-        }
-    }
-
 }

http://git-wip-us.apache.org/repos/asf/camel/blob/342bfe1d/components/camel-netty-http/src/main/java/org/apache/camel/component/netty/http/SecurityAuthenticator.java
----------------------------------------------------------------------
diff --git 
a/components/camel-netty-http/src/main/java/org/apache/camel/component/netty/http/SecurityAuthenticator.java
 
b/components/camel-netty-http/src/main/java/org/apache/camel/component/netty/http/SecurityAuthenticator.java
index e1be404..9e4ca53 100644
--- 
a/components/camel-netty-http/src/main/java/org/apache/camel/component/netty/http/SecurityAuthenticator.java
+++ 
b/components/camel-netty-http/src/main/java/org/apache/camel/component/netty/http/SecurityAuthenticator.java
@@ -35,6 +35,15 @@ public interface SecurityAuthenticator {
      */
     String getName();
 
+    /**
+     * Sets the role class names (separated by comma)
+     * <p/>
+     * By default if no explicit role class names has been configured, then 
this implementation
+     * will assume the {@link Subject} {@link java.security.Principal}s is a 
role if the classname
+     * contains the word <tt>role</tt> (lower cased).
+     *
+     * @param names a list of FQN class names for role {@link 
java.security.Principal} implementations.
+     */
     void setRoleClassNames(String names);
 
     /**

http://git-wip-us.apache.org/repos/asf/camel/blob/342bfe1d/components/camel-netty-http/src/main/java/org/apache/camel/component/netty/http/SecurityAuthenticatorSupport.java
----------------------------------------------------------------------
diff --git 
a/components/camel-netty-http/src/main/java/org/apache/camel/component/netty/http/SecurityAuthenticatorSupport.java
 
b/components/camel-netty-http/src/main/java/org/apache/camel/component/netty/http/SecurityAuthenticatorSupport.java
new file mode 100644
index 0000000..212736c
--- /dev/null
+++ 
b/components/camel-netty-http/src/main/java/org/apache/camel/component/netty/http/SecurityAuthenticatorSupport.java
@@ -0,0 +1,127 @@
+/**
+ * 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.camel.component.netty.http;
+
+import java.io.IOException;
+import java.security.Principal;
+import java.util.Iterator;
+import java.util.Locale;
+import javax.security.auth.Subject;
+import javax.security.auth.callback.Callback;
+import javax.security.auth.callback.CallbackHandler;
+import javax.security.auth.callback.NameCallback;
+import javax.security.auth.callback.PasswordCallback;
+import javax.security.auth.callback.UnsupportedCallbackException;
+
+import org.apache.camel.util.ObjectHelper;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * A base class for {@link SecurityAuthenticator}.
+ */
+public abstract class SecurityAuthenticatorSupport implements 
SecurityAuthenticator {
+
+    private String name;
+    private String roleClassNames;
+
+    public SecurityAuthenticatorSupport() {
+    }
+
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public void setRoleClassNames(String roleClassNames) {
+        this.roleClassNames = roleClassNames;
+    }
+
+    /**
+     * Is the given principal a role class?
+     *
+     * @param principal the principal
+     * @return <tt>true</tt> if role class, <tt>false</tt> if not
+     */
+    protected boolean isRoleClass(Principal principal) {
+        if (roleClassNames == null) {
+            // by default assume its a role when the classname has role in its 
name
+            return 
principal.getClass().getName().toLowerCase(Locale.US).contains("role");
+        }
+
+        // check each role class name if they match the principal class name
+        Iterator it = ObjectHelper.createIterator(roleClassNames);
+        while (it.hasNext()) {
+            String name = it.next().toString().trim();
+            if (principal.getClass().getName().equals(name)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public String getUserRoles(Subject subject) {
+        StringBuilder sb = new StringBuilder();
+        for (Principal p : subject.getPrincipals()) {
+            if (isRoleClass(p)) {
+                if (sb.length() > 0) {
+                    sb.append(",");
+                }
+                sb.append(p.getName());
+            }
+        }
+        if (sb.length() > 0) {
+            return sb.toString();
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * {@link javax.security.auth.callback.CallbackHandler} that provides the 
username and password.
+     */
+    public static final class HttpPrincipalCallbackHandler implements 
CallbackHandler {
+
+        private static final Logger LOG = 
LoggerFactory.getLogger(HttpPrincipalCallbackHandler.class);
+
+        private final HttpPrincipal principal;
+
+        public HttpPrincipalCallbackHandler(HttpPrincipal principal) {
+            this.principal = principal;
+        }
+
+        @Override
+        public void handle(Callback[] callbacks) throws IOException, 
UnsupportedCallbackException {
+            for (Callback callback : callbacks) {
+                LOG.trace("Callback {}", callback);
+                if (callback instanceof PasswordCallback) {
+                    PasswordCallback pc = (PasswordCallback) callback;
+                    LOG.trace("Setting password on callback {}", pc);
+                    pc.setPassword(principal.getPassword().toCharArray());
+                } else if (callback instanceof NameCallback) {
+                    NameCallback nc = (NameCallback) callback;
+                    LOG.trace("Setting username on callback {}", nc);
+                    nc.setName(principal.getName());
+                }
+            }
+        }
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/camel/blob/342bfe1d/components/camel-netty-http/src/main/java/org/apache/camel/component/netty/http/SecurityConstraintMapping.java
----------------------------------------------------------------------
diff --git 
a/components/camel-netty-http/src/main/java/org/apache/camel/component/netty/http/SecurityConstraintMapping.java
 
b/components/camel-netty-http/src/main/java/org/apache/camel/component/netty/http/SecurityConstraintMapping.java
new file mode 100644
index 0000000..7c84bd2
--- /dev/null
+++ 
b/components/camel-netty-http/src/main/java/org/apache/camel/component/netty/http/SecurityConstraintMapping.java
@@ -0,0 +1,133 @@
+/**
+ * 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.camel.component.netty.http;
+
+import java.util.LinkedHashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.camel.util.EndpointHelper;
+
+/**
+ * A default {@link SecurityConstraint} which can be used to define a set of 
mappings to
+ * as constraints.
+ * <p/>
+ * This constraint will match as <tt>true</tt> if no inclusions has been 
defined.
+ * First all the inclusions is check for matching. If a inclusion matches,
+ * then the exclusion is checked, and if any of them matches, then the 
exclusion
+ * will override the match and force returning <tt>false</tt>.
+ * <p/>
+ * Wildcards and regular expressions is supported as this implementation uses
+ * {@link EndpointHelper#matchPattern(String, String)} method for matching.
+ * <p/>
+ * This restricted constraint allows you to setup context path rules that will 
restrict
+ * access to paths, and then override and have exclusions that may allow 
access to
+ * public paths.
+ */
+public class SecurityConstraintMapping implements SecurityConstraint {
+
+    // url -> roles
+    private Map<String, String> inclusions;
+    // url
+    private Set<String> exclusions;
+
+    @Override
+    public String restricted(String url) {
+        // check excluded first
+        if (excludedUrl(url)) {
+            return null;
+        }
+
+        // is the url restricted?
+        String constraint = includedUrl(url);
+        if (constraint == null) {
+            return null;
+        }
+
+        // is there any roles for the restricted url?
+        String roles = inclusions != null ? inclusions.get(constraint) : null;
+        if (roles == null) {
+            // use wildcard to indicate any role is accepted
+            return "*";
+        } else {
+            return roles;
+        }
+    }
+
+    private String includedUrl(String url) {
+        String candidate = null;
+        if (inclusions != null && !inclusions.isEmpty()) {
+            for (String constraint : inclusions.keySet()) {
+                if (EndpointHelper.matchPattern(url, constraint)) {
+                    if (candidate == null) {
+                        candidate = constraint;
+                    } else if (constraint.length() > candidate.length()) {
+                        // we want the constraint that has the longest 
context-path matching as its
+                        // the most explicit for the target url
+                        candidate = constraint;
+                    }
+                }
+            }
+            return candidate;
+        }
+
+        // by default if no included has been configured then everything is 
restricted
+        return "*";
+    }
+
+    private boolean excludedUrl(String url) {
+        if (exclusions != null && !exclusions.isEmpty()) {
+            for (String constraint : exclusions) {
+                if (EndpointHelper.matchPattern(url, constraint)) {
+                    // force not matches if this was an exclusion
+                    return true;
+                }
+            }
+        }
+
+        return false;
+    }
+
+    public void addInclusion(String constraint) {
+        if (inclusions == null) {
+            inclusions = new java.util.LinkedHashMap<String, String>();
+        }
+        inclusions.put(constraint, null);
+    }
+
+    public void addInclusion(String constraint, String roles) {
+        if (inclusions == null) {
+            inclusions = new java.util.LinkedHashMap<String, String>();
+        }
+        inclusions.put(constraint, roles);
+    }
+
+    public void addExclusion(String constraint) {
+        if (exclusions == null) {
+            exclusions = new LinkedHashSet<String>();
+        }
+        exclusions.add(constraint);
+    }
+
+    public void setInclusions(Map<String, String> inclusions) {
+        this.inclusions = inclusions;
+    }
+
+    public void setExclusions(Set<String> exclusions) {
+        this.exclusions = exclusions;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/342bfe1d/components/camel-netty-http/src/test/java/org/apache/camel/component/netty/http/DefaultSecurityConstraintTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-netty-http/src/test/java/org/apache/camel/component/netty/http/DefaultSecurityConstraintTest.java
 
b/components/camel-netty-http/src/test/java/org/apache/camel/component/netty/http/DefaultSecurityConstraintTest.java
deleted file mode 100644
index 16790f7..0000000
--- 
a/components/camel-netty-http/src/test/java/org/apache/camel/component/netty/http/DefaultSecurityConstraintTest.java
+++ /dev/null
@@ -1,108 +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.camel.component.netty.http;
-
-import junit.framework.TestCase;
-
-public class DefaultSecurityConstraintTest extends TestCase {
-
-    public void testDefault() {
-        DefaultSecurityConstraint matcher = new DefaultSecurityConstraint();
-
-        assertNotNull(matcher.restricted("/"));
-        assertNotNull(matcher.restricted("/foo"));
-    }
-
-    public void testFoo() {
-        DefaultSecurityConstraint matcher = new DefaultSecurityConstraint();
-        matcher.addInclusion("/foo");
-
-        assertNull(matcher.restricted("/"));
-        assertNotNull(matcher.restricted("/foo"));
-        assertNull(matcher.restricted("/foobar"));
-        assertNull(matcher.restricted("/foo/bar"));
-    }
-
-    public void testFooWildcard() {
-        DefaultSecurityConstraint matcher = new DefaultSecurityConstraint();
-        matcher.addInclusion("/foo*");
-
-        assertNull(matcher.restricted("/"));
-        assertNotNull(matcher.restricted("/foo"));
-        assertNotNull(matcher.restricted("/foobar"));
-        assertNotNull(matcher.restricted("/foo/bar"));
-    }
-
-    public void testFooBar() {
-        DefaultSecurityConstraint matcher = new DefaultSecurityConstraint();
-        matcher.addInclusion("/foo");
-        matcher.addInclusion("/bar");
-
-        assertNull(matcher.restricted("/"));
-        assertNotNull(matcher.restricted("/foo"));
-        assertNull(matcher.restricted("/foobar"));
-        assertNull(matcher.restricted("/foo/bar"));
-
-        assertNotNull(matcher.restricted("/bar"));
-        assertNull(matcher.restricted("/barbar"));
-        assertNull(matcher.restricted("/bar/bar"));
-    }
-
-    public void testFooBarWildcard() {
-        DefaultSecurityConstraint matcher = new DefaultSecurityConstraint();
-        matcher.addInclusion("/foo*");
-        matcher.addInclusion("/bar*");
-
-        assertNull(matcher.restricted("/"));
-        assertNotNull(matcher.restricted("/foo"));
-        assertNotNull(matcher.restricted("/foobar"));
-        assertNotNull(matcher.restricted("/foo/bar"));
-
-        assertNotNull(matcher.restricted("/bar"));
-        assertNotNull(matcher.restricted("/barbar"));
-        assertNotNull(matcher.restricted("/bar/bar"));
-    }
-
-    public void testFooExclusion() {
-        DefaultSecurityConstraint matcher = new DefaultSecurityConstraint();
-        matcher.addInclusion("/foo/*");
-        matcher.addExclusion("/foo/public/*");
-
-        assertNull(matcher.restricted("/"));
-        assertNotNull(matcher.restricted("/foo"));
-        assertNotNull(matcher.restricted("/foo/bar"));
-        assertNull(matcher.restricted("/foo/public"));
-        assertNull(matcher.restricted("/foo/public/open"));
-    }
-
-    public void testDefaultExclusion() {
-        // everything is restricted unless its from the public
-        DefaultSecurityConstraint matcher = new DefaultSecurityConstraint();
-        matcher.addExclusion("/public/*");
-        matcher.addExclusion("/index");
-        matcher.addExclusion("/index.html");
-
-        assertNotNull(matcher.restricted("/"));
-        assertNotNull(matcher.restricted("/foo"));
-        assertNotNull(matcher.restricted("/foo/bar"));
-        assertNull(matcher.restricted("/public"));
-        assertNull(matcher.restricted("/public/open"));
-        assertNull(matcher.restricted("/index"));
-        assertNull(matcher.restricted("/index.html"));
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/camel/blob/342bfe1d/components/camel-netty-http/src/test/java/org/apache/camel/component/netty/http/MyLoginModule.java
----------------------------------------------------------------------
diff --git 
a/components/camel-netty-http/src/test/java/org/apache/camel/component/netty/http/MyLoginModule.java
 
b/components/camel-netty-http/src/test/java/org/apache/camel/component/netty/http/MyLoginModule.java
index ad5143a..f2bd5c9 100644
--- 
a/components/camel-netty-http/src/test/java/org/apache/camel/component/netty/http/MyLoginModule.java
+++ 
b/components/camel-netty-http/src/test/java/org/apache/camel/component/netty/http/MyLoginModule.java
@@ -58,6 +58,15 @@ public class MyLoginModule implements LoginModule {
             if (!"secret".equals(password)) {
                 throw new LoginException("Login denied");
             }
+
+            // add roles
+            if ("scott".equals(username)) {
+                subject.getPrincipals().add(new MyRolePrincipal("admin"));
+                subject.getPrincipals().add(new MyRolePrincipal("guest"));
+            } else if ("guest".equals(username)) {
+                subject.getPrincipals().add(new MyRolePrincipal("guest"));
+            }
+
         } catch (IOException ioe) {
             LoginException le = new LoginException(ioe.toString());
             le.initCause(ioe);
@@ -69,6 +78,7 @@ public class MyLoginModule implements LoginModule {
             throw le;
         }
 
+
         return true;
     }
 

http://git-wip-us.apache.org/repos/asf/camel/blob/342bfe1d/components/camel-netty-http/src/test/java/org/apache/camel/component/netty/http/MyRolePrincipal.java
----------------------------------------------------------------------
diff --git 
a/components/camel-netty-http/src/test/java/org/apache/camel/component/netty/http/MyRolePrincipal.java
 
b/components/camel-netty-http/src/test/java/org/apache/camel/component/netty/http/MyRolePrincipal.java
new file mode 100644
index 0000000..e912a07
--- /dev/null
+++ 
b/components/camel-netty-http/src/test/java/org/apache/camel/component/netty/http/MyRolePrincipal.java
@@ -0,0 +1,33 @@
+/**
+ * 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.camel.component.netty.http;
+
+import java.security.Principal;
+
+public class MyRolePrincipal implements Principal {
+
+    private final String role;
+
+    public MyRolePrincipal(String role) {
+        this.role = role;
+    }
+
+    @Override
+    public String getName() {
+        return role;
+    }
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/342bfe1d/components/camel-netty-http/src/test/java/org/apache/camel/component/netty/http/NettyHttpBasicAuthConstraintMapperTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-netty-http/src/test/java/org/apache/camel/component/netty/http/NettyHttpBasicAuthConstraintMapperTest.java
 
b/components/camel-netty-http/src/test/java/org/apache/camel/component/netty/http/NettyHttpBasicAuthConstraintMapperTest.java
index 890be6c..879b4f2 100644
--- 
a/components/camel-netty-http/src/test/java/org/apache/camel/component/netty/http/NettyHttpBasicAuthConstraintMapperTest.java
+++ 
b/components/camel-netty-http/src/test/java/org/apache/camel/component/netty/http/NettyHttpBasicAuthConstraintMapperTest.java
@@ -45,7 +45,7 @@ public class NettyHttpBasicAuthConstraintMapperTest extends 
BaseNettyTest {
         auth.setName("karaf");
         security.setSecurityAuthenticator(auth);
 
-        DefaultSecurityConstraint matcher = new DefaultSecurityConstraint();
+        SecurityConstraintMapping matcher = new SecurityConstraintMapping();
         matcher.addInclusion("/foo/*");
         matcher.addExclusion("/foo/public/*");
         security.setSecurityConstraint(matcher);

http://git-wip-us.apache.org/repos/asf/camel/blob/342bfe1d/components/camel-netty-http/src/test/java/org/apache/camel/component/netty/http/NettyHttpSimpleBasicAuthConstraintMapperTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-netty-http/src/test/java/org/apache/camel/component/netty/http/NettyHttpSimpleBasicAuthConstraintMapperTest.java
 
b/components/camel-netty-http/src/test/java/org/apache/camel/component/netty/http/NettyHttpSimpleBasicAuthConstraintMapperTest.java
index c68ba0d..a241a80 100644
--- 
a/components/camel-netty-http/src/test/java/org/apache/camel/component/netty/http/NettyHttpSimpleBasicAuthConstraintMapperTest.java
+++ 
b/components/camel-netty-http/src/test/java/org/apache/camel/component/netty/http/NettyHttpSimpleBasicAuthConstraintMapperTest.java
@@ -39,7 +39,7 @@ public class NettyHttpSimpleBasicAuthConstraintMapperTest 
extends BaseNettyTest
     protected JndiRegistry createRegistry() throws Exception {
         JndiRegistry jndi = super.createRegistry();
 
-        DefaultSecurityConstraint matcher = new DefaultSecurityConstraint();
+        SecurityConstraintMapping matcher = new SecurityConstraintMapping();
         matcher.addInclusion("/foo/*");
         matcher.addExclusion("/foo/public/*");
 

http://git-wip-us.apache.org/repos/asf/camel/blob/342bfe1d/components/camel-netty-http/src/test/java/org/apache/camel/component/netty/http/SecurityConstraintMappingTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-netty-http/src/test/java/org/apache/camel/component/netty/http/SecurityConstraintMappingTest.java
 
b/components/camel-netty-http/src/test/java/org/apache/camel/component/netty/http/SecurityConstraintMappingTest.java
new file mode 100644
index 0000000..5d95ae8
--- /dev/null
+++ 
b/components/camel-netty-http/src/test/java/org/apache/camel/component/netty/http/SecurityConstraintMappingTest.java
@@ -0,0 +1,108 @@
+/**
+ * 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.camel.component.netty.http;
+
+import junit.framework.TestCase;
+
+public class SecurityConstraintMappingTest extends TestCase {
+
+    public void testDefault() {
+        SecurityConstraintMapping matcher = new SecurityConstraintMapping();
+
+        assertNotNull(matcher.restricted("/"));
+        assertNotNull(matcher.restricted("/foo"));
+    }
+
+    public void testFoo() {
+        SecurityConstraintMapping matcher = new SecurityConstraintMapping();
+        matcher.addInclusion("/foo");
+
+        assertNull(matcher.restricted("/"));
+        assertNotNull(matcher.restricted("/foo"));
+        assertNull(matcher.restricted("/foobar"));
+        assertNull(matcher.restricted("/foo/bar"));
+    }
+
+    public void testFooWildcard() {
+        SecurityConstraintMapping matcher = new SecurityConstraintMapping();
+        matcher.addInclusion("/foo*");
+
+        assertNull(matcher.restricted("/"));
+        assertNotNull(matcher.restricted("/foo"));
+        assertNotNull(matcher.restricted("/foobar"));
+        assertNotNull(matcher.restricted("/foo/bar"));
+    }
+
+    public void testFooBar() {
+        SecurityConstraintMapping matcher = new SecurityConstraintMapping();
+        matcher.addInclusion("/foo");
+        matcher.addInclusion("/bar");
+
+        assertNull(matcher.restricted("/"));
+        assertNotNull(matcher.restricted("/foo"));
+        assertNull(matcher.restricted("/foobar"));
+        assertNull(matcher.restricted("/foo/bar"));
+
+        assertNotNull(matcher.restricted("/bar"));
+        assertNull(matcher.restricted("/barbar"));
+        assertNull(matcher.restricted("/bar/bar"));
+    }
+
+    public void testFooBarWildcard() {
+        SecurityConstraintMapping matcher = new SecurityConstraintMapping();
+        matcher.addInclusion("/foo*");
+        matcher.addInclusion("/bar*");
+
+        assertNull(matcher.restricted("/"));
+        assertNotNull(matcher.restricted("/foo"));
+        assertNotNull(matcher.restricted("/foobar"));
+        assertNotNull(matcher.restricted("/foo/bar"));
+
+        assertNotNull(matcher.restricted("/bar"));
+        assertNotNull(matcher.restricted("/barbar"));
+        assertNotNull(matcher.restricted("/bar/bar"));
+    }
+
+    public void testFooExclusion() {
+        SecurityConstraintMapping matcher = new SecurityConstraintMapping();
+        matcher.addInclusion("/foo/*");
+        matcher.addExclusion("/foo/public/*");
+
+        assertNull(matcher.restricted("/"));
+        assertNotNull(matcher.restricted("/foo"));
+        assertNotNull(matcher.restricted("/foo/bar"));
+        assertNull(matcher.restricted("/foo/public"));
+        assertNull(matcher.restricted("/foo/public/open"));
+    }
+
+    public void testDefaultExclusion() {
+        // everything is restricted unless its from the public
+        SecurityConstraintMapping matcher = new SecurityConstraintMapping();
+        matcher.addExclusion("/public/*");
+        matcher.addExclusion("/index");
+        matcher.addExclusion("/index.html");
+
+        assertNotNull(matcher.restricted("/"));
+        assertNotNull(matcher.restricted("/foo"));
+        assertNotNull(matcher.restricted("/foo/bar"));
+        assertNull(matcher.restricted("/public"));
+        assertNull(matcher.restricted("/public/open"));
+        assertNull(matcher.restricted("/index"));
+        assertNull(matcher.restricted("/index.html"));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/342bfe1d/components/camel-netty-http/src/test/java/org/apache/camel/component/netty/http/SpringNettyHttpBasicAuthTest.java
----------------------------------------------------------------------
diff --git 
a/components/camel-netty-http/src/test/java/org/apache/camel/component/netty/http/SpringNettyHttpBasicAuthTest.java
 
b/components/camel-netty-http/src/test/java/org/apache/camel/component/netty/http/SpringNettyHttpBasicAuthTest.java
new file mode 100644
index 0000000..01f875d
--- /dev/null
+++ 
b/components/camel-netty-http/src/test/java/org/apache/camel/component/netty/http/SpringNettyHttpBasicAuthTest.java
@@ -0,0 +1,115 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.camel.component.netty.http;
+
+import javax.annotation.Resource;
+
+import junit.framework.TestCase;
+import org.apache.camel.CamelExecutionException;
+import org.apache.camel.EndpointInject;
+import org.apache.camel.Produce;
+import org.apache.camel.ProducerTemplate;
+import org.apache.camel.component.mock.MockEndpoint;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.springframework.test.context.ContextConfiguration;
+import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+
+@RunWith(SpringJUnit4ClassRunner.class)
+@ContextConfiguration(locations = 
{"/org/apache/camel/component/netty/http/SpringNettyHttpBasicAuthTest.xml"})
+public class SpringNettyHttpBasicAuthTest extends TestCase {
+
+    @Produce
+    private ProducerTemplate template;
+
+    @EndpointInject(uri = "mock:input")
+    private MockEndpoint mockEndpoint;
+
+    private Integer port;
+
+    public Integer getPort() {
+        return port;
+    }
+
+    @Resource(name = "dynaPort")
+    public void setPort(Integer port) {
+        this.port = port;
+    }
+
+    @BeforeClass
+    public static void setUpJaas() throws Exception {
+        System.setProperty("java.security.auth.login.config", 
"src/test/resources/myjaas.config");
+    }
+
+    @AfterClass
+    public static void tearDownJaas() throws Exception {
+        System.clearProperty("java.security.auth.login.config");
+    }
+
+    @Test
+    public void testAdminAuth() throws Exception {
+        try {
+            template.requestBody("netty-http:http://localhost:"; + port + 
"/foo", "Hello Foo", String.class);
+            fail("Should send back 401");
+        } catch (CamelExecutionException e) {
+            NettyHttpOperationFailedException cause = 
(NettyHttpOperationFailedException) e.getCause();
+            assertEquals(401, cause.getStatusCode());
+        }
+
+        mockEndpoint.reset();
+        mockEndpoint.expectedBodiesReceived("Hello Public", "Hello Foo", 
"Hello Admin");
+
+        // public do not need authentication
+        String out = template.requestBody("netty-http:http://localhost:"; + 
port + "/foo/public/welcome", "Hello Public", String.class);
+        assertEquals("Bye /foo/public/welcome", out);
+
+        // username:password is scott:secret
+        String auth = "Basic c2NvdHQ6c2VjcmV0";
+        out = template.requestBodyAndHeader("netty-http:http://localhost:"; + 
port + "/foo", "Hello Foo", "Authorization", auth, String.class);
+        assertEquals("Bye /foo", out);
+
+        out = template.requestBodyAndHeader("netty-http:http://localhost:"; + 
port + "/foo/admin/users", "Hello Admin", "Authorization", auth, String.class);
+        assertEquals("Bye /foo/admin/users", out);
+
+        mockEndpoint.assertIsSatisfied();
+    }
+
+    @Test
+    public void testGuestAuth() throws Exception {
+        // username:password is guest:secret
+        String auth = "Basic Z3Vlc3Q6c2VjcmV0";
+        String out = 
template.requestBodyAndHeader("netty-http:http://localhost:"; + port + 
"/foo/guest/hello", "Hello Guest", "Authorization", auth, String.class);
+        assertEquals("Bye /foo/guest/hello", out);
+
+        // accessing admin is restricted for guest user
+        try {
+            template.requestBodyAndHeader("netty-http:http://localhost:"; + 
port + "/foo/admin/users", "Hello Admin", "Authorization", auth, String.class);
+            fail("Should send back 401");
+        } catch (CamelExecutionException e) {
+            NettyHttpOperationFailedException cause = 
(NettyHttpOperationFailedException) e.getCause();
+            assertEquals(401, cause.getStatusCode());
+        }
+
+        // but we can access foo as that is any roles
+        out = template.requestBodyAndHeader("netty-http:http://localhost:"; + 
port + "/foo", "Hello Foo", "Authorization", auth, String.class);
+        assertEquals("Bye /foo", out);
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/camel/blob/342bfe1d/components/camel-netty-http/src/test/resources/org/apache/camel/component/netty/http/SpringNettyHttpBasicAuthTest.xml
----------------------------------------------------------------------
diff --git 
a/components/camel-netty-http/src/test/resources/org/apache/camel/component/netty/http/SpringNettyHttpBasicAuthTest.xml
 
b/components/camel-netty-http/src/test/resources/org/apache/camel/component/netty/http/SpringNettyHttpBasicAuthTest.xml
new file mode 100644
index 0000000..7f423ce
--- /dev/null
+++ 
b/components/camel-netty-http/src/test/resources/org/apache/camel/component/netty/http/SpringNettyHttpBasicAuthTest.xml
@@ -0,0 +1,70 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    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.
+-->
+<beans xmlns="http://www.springframework.org/schema/beans";
+       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+       xsi:schemaLocation="
+       http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans.xsd
+       http://camel.apache.org/schema/spring 
http://camel.apache.org/schema/spring/camel-spring.xsd
+    ">
+
+  <bean id="dynaPort" 
class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
+    <property name="targetClass">
+      <value>org.apache.camel.test.AvailablePortFinder</value>
+    </property>
+    <property name="targetMethod">
+      <value>getNextAvailable</value>
+    </property>
+    <property name="arguments">
+      <list>
+        <value>9000</value>
+      </list>
+    </property>
+  </bean>
+
+  <bean id="constraint" 
class="org.apache.camel.component.netty.http.SecurityConstraintMapping">
+    <!-- inclusions defines url -> roles restrictions -->
+    <!-- a * should be used for any role accepted (or even no roles) -->
+    <property name="inclusions">
+      <map>
+        <entry key="/foo/*" value="*"/>
+        <entry key="/foo/admin/*" value="admin"/>
+        <entry key="/foo/guest/*" value="admin,guest"/>
+      </map>
+    </property>
+    <!-- exclusions is used to define public urls, which requires no 
authentication -->
+    <property name="exclusions">
+      <set>
+        <value>/foo/public/*</value>
+      </set>
+    </property>
+  </bean>
+
+  <camelContext id="camel" xmlns="http://camel.apache.org/schema/spring";>
+    <endpoint id="input1" 
uri="netty-http:http://0.0.0.0:#{dynaPort}/foo?matchOnUriPrefix=true&amp;securityConfiguration.realm=karaf&amp;securityConfiguration.securityConstraint=#constraint"/>
+
+    <route>
+      <from ref="input1"/>
+      <to uri="mock:input"/>
+      <transform>
+        <simple>Bye ${header.CamelHttpUri}</simple>
+      </transform>
+    </route>
+
+  </camelContext>
+
+</beans>

Reply via email to