You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@knox.apache.org by km...@apache.org on 2014/02/24 19:53:18 UTC

git commit: KNOX-269: Set JSSESSIONID cookie as HttpOnly and Secure.

Repository: incubator-knox
Updated Branches:
  refs/heads/master c926db698 -> cb5fce360


KNOX-269: Set JSSESSIONID cookie as HttpOnly and Secure.


Project: http://git-wip-us.apache.org/repos/asf/incubator-knox/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-knox/commit/cb5fce36
Tree: http://git-wip-us.apache.org/repos/asf/incubator-knox/tree/cb5fce36
Diff: http://git-wip-us.apache.org/repos/asf/incubator-knox/diff/cb5fce36

Branch: refs/heads/master
Commit: cb5fce360b06e7a1b77e58b6366075daccd3132e
Parents: c926db6
Author: Kevin Minder <ke...@hortonworks.com>
Authored: Mon Feb 24 13:48:38 2014 -0500
Committer: Kevin Minder <ke...@hortonworks.com>
Committed: Mon Feb 24 13:50:53 2014 -0500

----------------------------------------------------------------------
 .../deploy/impl/ShiroDeploymentContributor.java |  57 +++++-----
 .../impl/ShiroDeploymentContributorTest.java    | 108 +++++++++++++++++++
 .../hadoop/gateway/GatewayBasicFuncTest.java    |  11 +-
 3 files changed, 148 insertions(+), 28 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/cb5fce36/gateway-provider-security-shiro/src/main/java/org/apache/hadoop/gateway/deploy/impl/ShiroDeploymentContributor.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-shiro/src/main/java/org/apache/hadoop/gateway/deploy/impl/ShiroDeploymentContributor.java b/gateway-provider-security-shiro/src/main/java/org/apache/hadoop/gateway/deploy/impl/ShiroDeploymentContributor.java
index 1591968..04a194d 100644
--- a/gateway-provider-security-shiro/src/main/java/org/apache/hadoop/gateway/deploy/impl/ShiroDeploymentContributor.java
+++ b/gateway-provider-security-shiro/src/main/java/org/apache/hadoop/gateway/deploy/impl/ShiroDeploymentContributor.java
@@ -17,9 +17,6 @@
  */
 package org.apache.hadoop.gateway.deploy.impl;
 
-import java.util.List;
-import java.util.Map;
-
 import org.apache.hadoop.gateway.deploy.DeploymentContext;
 import org.apache.hadoop.gateway.deploy.ProviderDeploymentContributorBase;
 import org.apache.hadoop.gateway.descriptor.FilterParamDescriptor;
@@ -30,6 +27,9 @@ import org.jboss.shrinkwrap.api.asset.StringAsset;
 import org.jboss.shrinkwrap.descriptor.api.webapp30.WebAppDescriptor;
 import org.jboss.shrinkwrap.descriptor.api.webcommon30.SessionConfigType;
 
+import java.util.List;
+import java.util.Map;
+
 public class ShiroDeploymentContributor extends ProviderDeploymentContributorBase {
 
   private static final String LISTENER_CLASSNAME = "org.apache.shiro.web.env.EnvironmentLoaderListener";
@@ -37,6 +37,7 @@ public class ShiroDeploymentContributor extends ProviderDeploymentContributorBas
   private static final String POST_FILTER_CLASSNAME = "org.apache.hadoop.gateway.filter.ShiroSubjectIdentityAdapter";
   private static final String COOKIE_FILTER_CLASSNAME = "org.apache.hadoop.gateway.filter.ResponseCookieFilter";
   private static final String SESSION_TIMEOUT = "sessionTimeout";
+  private static final String SHRIO_CONFIG_FILE_NAME = "shiro.ini";
   private static final int DEFAULT_SESSION_TIMEOUT = 30; // 30min
 
   @Override
@@ -51,47 +52,51 @@ public class ShiroDeploymentContributor extends ProviderDeploymentContributorBas
 
   @Override
   public void contributeProvider( DeploymentContext context, Provider provider ) {
-	// Many filter based authentication mechanisms require a ServletContextListener
-	// to be added and the Knox deployment machinery provides the ability to add this
-	// through the DeploymentContext.
-	
+    // Many filter based authentication mechanisms require a ServletContextListener
+    // to be added and the Knox deployment machinery provides the ability to add this
+    // through the DeploymentContext.
+
+    // Writing provider specific config out to the war for cluster specific config can be
+    // accomplished through the DeploymentContext as well. The JBoss shrinkwrap API can be
+    // used to write the asset to the war.
+
     // add servletContextListener
     context.getWebAppDescriptor().createListener().listenerClass( LISTENER_CLASSNAME );
-    
+
     // add session timeout
     int st = DEFAULT_SESSION_TIMEOUT;
     SessionConfigType<WebAppDescriptor> sessionConfig = context.getWebAppDescriptor().createSessionConfig();
     Map<String, String> params = provider.getParams();
-    String sts = params.get(SESSION_TIMEOUT);
-    if (sts != null && sts.trim().length() != 0) {
-      st = Integer.valueOf(sts.trim());
+    String sts = params.get( SESSION_TIMEOUT );
+    if( sts != null && sts.trim().length() != 0 ) {
+      st = Integer.valueOf( sts.trim() );
     }
-    if (st <= 0) {
+    if( st <= 0 ) {
       // user default session timeout
       st = DEFAULT_SESSION_TIMEOUT;
     }
-    sessionConfig.sessionTimeout(st);
+    sessionConfig.sessionTimeout( st );
+    sessionConfig.getOrCreateCookieConfig().httpOnly( true );
+    sessionConfig.getOrCreateCookieConfig().secure( true );
 
-    // Writing provider specific config out to the war for cluster specific config can be
-	  // accomplished through the DeploymentContext as well. The JBoss shrinkwrap API can be
-	  // used to write the asset to the war.
     String clusterName = context.getTopology().getName();
-    String config = new ShiroConfig( provider, clusterName ).toString();
+    ShiroConfig config = new ShiroConfig( provider, clusterName );
+    String configStr = config.toString();
     if( config != null ) {
-      context.getWebArchive().addAsWebInfResource( new StringAsset( config ), "shiro.ini" );
+      context.getWebArchive().addAsWebInfResource( new StringAsset( configStr ), SHRIO_CONFIG_FILE_NAME );
     }
   }
 
   @Override
   public void contributeFilter( DeploymentContext context, Provider provider, Service service, ResourceDescriptor resource, List<FilterParamDescriptor> params ) {
-	// Leveraging a third party filter is a primary usecase for Knox
-	// in order to do so, we need to make sure that the end result of the third party integration
-	// puts a standard javax.security.auth.Subject on the current thread through a doAs.
-	// As many filters do not use the standard java Subject, often times a post processing filter will
-	// need to be added in order to canonicalize the result into an expected security context.
-	
-	// You may also need to do some additional processing of the response in order to not return cookies or other
-	// filter specifics that are not needed for integration with Knox. Below we do that in the pre-processing filter.
+    // Leveraging a third party filter is a primary usecase for Knox
+    // in order to do so, we need to make sure that the end result of the third party integration
+    // puts a standard javax.security.auth.Subject on the current thread through a doAs.
+    // As many filters do not use the standard java Subject, often times a post processing filter will
+    // need to be added in order to canonicalize the result into an expected security context.
+
+    // You may also need to do some additional processing of the response in order to not return cookies or other
+    // filter specifics that are not needed for integration with Knox. Below we do that in the pre-processing filter.
     resource.addFilter().name( "Pre" + getName() ).role( getRole() ).impl( COOKIE_FILTER_CLASSNAME ).params( params );
     resource.addFilter().name( getName() ).role( getRole() ).impl( SHIRO_FILTER_CLASSNAME ).params( params );
     resource.addFilter().name( "Post" + getName() ).role( getRole() ).impl( POST_FILTER_CLASSNAME ).params( params );

http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/cb5fce36/gateway-provider-security-shiro/src/test/java/org/apache/hadoop/gateway/deploy/impl/ShiroDeploymentContributorTest.java
----------------------------------------------------------------------
diff --git a/gateway-provider-security-shiro/src/test/java/org/apache/hadoop/gateway/deploy/impl/ShiroDeploymentContributorTest.java b/gateway-provider-security-shiro/src/test/java/org/apache/hadoop/gateway/deploy/impl/ShiroDeploymentContributorTest.java
new file mode 100644
index 0000000..bf8263b
--- /dev/null
+++ b/gateway-provider-security-shiro/src/test/java/org/apache/hadoop/gateway/deploy/impl/ShiroDeploymentContributorTest.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.hadoop.gateway.deploy.impl;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.hadoop.gateway.deploy.DeploymentContext;
+import org.apache.hadoop.gateway.deploy.ProviderDeploymentContributor;
+import org.apache.hadoop.gateway.services.GatewayServices;
+import org.apache.hadoop.gateway.services.security.AliasService;
+import org.apache.hadoop.gateway.services.security.CryptoService;
+import org.apache.hadoop.gateway.services.security.impl.DefaultCryptoService;
+import org.apache.hadoop.gateway.topology.Provider;
+import org.apache.hadoop.gateway.topology.Topology;
+import org.easymock.EasyMock;
+import org.jboss.shrinkwrap.api.ShrinkWrap;
+import org.jboss.shrinkwrap.api.asset.StringAsset;
+import org.jboss.shrinkwrap.api.spec.WebArchive;
+import org.jboss.shrinkwrap.descriptor.api.Descriptors;
+import org.jboss.shrinkwrap.descriptor.api.webapp30.WebAppDescriptor;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.ServiceLoader;
+
+import static org.hamcrest.CoreMatchers.containsString;
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.fail;
+
+public class ShiroDeploymentContributorTest {
+
+  @Test
+  public void testServiceLoader() throws Exception {
+    ServiceLoader loader = ServiceLoader.load( ProviderDeploymentContributor.class );
+    Iterator iterator = loader.iterator();
+    assertThat( "Service iterator empty.", iterator.hasNext() );
+    while( iterator.hasNext() ) {
+      Object object = iterator.next();
+      if( object instanceof ShiroDeploymentContributor ) {
+        return;
+      }
+    }
+    fail( "Failed to find " + ShiroDeploymentContributor.class.getName() + " via service loader." );
+  }
+
+  @Test
+  public void testDeployment() throws IOException {
+    WebArchive webArchive = ShrinkWrap.create( WebArchive.class, "test-archive" );
+
+    Map<String,String> providerParams = new HashMap<String, String>();
+    Provider provider = new Provider();
+    provider.setEnabled( true );
+    provider.setName( "shiro" );
+    provider.setParams(  providerParams );
+
+    Topology topology = new Topology();
+    topology.setName( "Sample" );
+
+    DeploymentContext context = EasyMock.createNiceMock( DeploymentContext.class );
+    EasyMock.expect( context.getWebArchive() ).andReturn( webArchive ).anyTimes();
+    EasyMock.expect( context.getWebAppDescriptor() ).andReturn( Descriptors.create( WebAppDescriptor.class ) ).anyTimes();
+    EasyMock.expect( context.getTopology() ).andReturn( topology ).anyTimes();
+    EasyMock.replay( context );
+
+    AliasService as = EasyMock.createNiceMock( AliasService.class );
+    CryptoService cryptoService = new DefaultCryptoService();
+    ((DefaultCryptoService)cryptoService).setAliasService( as );
+
+    GatewayServices gatewayServices = EasyMock.createNiceMock( GatewayServices.class );
+    EasyMock.expect( gatewayServices.getService( GatewayServices.CRYPTO_SERVICE ) ).andReturn( cryptoService ).anyTimes();
+
+    ShiroDeploymentContributor contributor = new ShiroDeploymentContributor();
+
+    assertThat( contributor.getRole(), is( "authentication" ) );
+    assertThat( contributor.getName(), is( "ShiroProvider" ) );
+
+    // Just make sure it doesn't blow up.
+    contributor.initializeContribution( context );
+
+    contributor.contributeProvider( context, provider );
+
+    // Just make sure it doesn't blow up.
+    contributor.finalizeContribution( context );
+
+    assertThat( context.getWebAppDescriptor().getOrCreateSessionConfig().getOrCreateCookieConfig().isHttpOnly(), is( true ) );
+    assertThat( context.getWebAppDescriptor().getOrCreateSessionConfig().getOrCreateCookieConfig().isSecure(), is( true ) );
+  }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-knox/blob/cb5fce36/gateway-test/src/test/java/org/apache/hadoop/gateway/GatewayBasicFuncTest.java
----------------------------------------------------------------------
diff --git a/gateway-test/src/test/java/org/apache/hadoop/gateway/GatewayBasicFuncTest.java b/gateway-test/src/test/java/org/apache/hadoop/gateway/GatewayBasicFuncTest.java
index c68bbac..70d2a35 100644
--- a/gateway-test/src/test/java/org/apache/hadoop/gateway/GatewayBasicFuncTest.java
+++ b/gateway-test/src/test/java/org/apache/hadoop/gateway/GatewayBasicFuncTest.java
@@ -18,6 +18,7 @@
 package org.apache.hadoop.gateway;
 
 import com.jayway.restassured.http.ContentType;
+import com.jayway.restassured.response.Cookie;
 import com.jayway.restassured.response.Response;
 import com.mycila.xmltool.XMLDoc;
 import com.mycila.xmltool.XMLTag;
@@ -58,6 +59,7 @@ import static org.hamcrest.CoreMatchers.is;
 import static org.hamcrest.CoreMatchers.not;
 import static org.hamcrest.CoreMatchers.startsWith;
 import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.greaterThan;
 import static org.xmlmatchers.XmlMatchers.isEquivalentTo;
 import static org.xmlmatchers.transform.XmlConverters.the;
 import static uk.co.datumedge.hamcrest.json.SameJSONAs.sameJSONAs;
@@ -244,7 +246,7 @@ public class GatewayBasicFuncTest {
         .status( HttpStatus.SC_OK )
         .content( driver.getResourceBytes( "webhdfs-success.json" ) )
         .contentType( "application/json" );
-    given()
+    Cookie cookie = given()
         //.log().all()
         .auth().preemptive().basic( username, password )
         .header("X-XSRF-Header", "jksdhfkhdsf")
@@ -252,9 +254,14 @@ public class GatewayBasicFuncTest {
         .expect()
         //.log().all()
         .statusCode( HttpStatus.SC_OK )
+        .header( "Set-Cookie", containsString( "JSESSIONID" ) )
+        .header( "Set-Cookie", containsString( "HttpOnly" ) )
         .contentType( "application/json" )
         .content( "boolean", is( true ) )
-        .when().put( driver.getUrl( "WEBHDFS" ) + "/v1" + root + "/dir" );
+        .when().put( driver.getUrl( "WEBHDFS" ) + "/v1" + root + "/dir" ).getDetailedCookie( "JSESSIONID" );
+    assertThat( cookie.isSecured(), is( true ) );
+    assertThat( cookie.getPath(), is( "/gateway/cluster" ) );
+    assertThat( cookie.getValue().length(), greaterThan( 16 ) );
     driver.assertComplete();
   }