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();
}