You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@knox.apache.org by lm...@apache.org on 2015/03/22 16:49:11 UTC
[1/2] knox git commit: KNOX-521 - Enhance Principal Mapping to Handle
Dynamic Mappings
Repository: knox
Updated Branches:
refs/heads/master 68416ccfd -> ce3ca3ced
http://git-wip-us.apache.org/repos/asf/knox/blob/ce3ca3ce/gateway-provider-identity-assertion-concat/src/main/resources/META-INF/services/org.apache.hadoop.gateway.deploy.ProviderDeploymentContributor
----------------------------------------------------------------------
diff --git a/gateway-provider-identity-assertion-concat/src/main/resources/META-INF/services/org.apache.hadoop.gateway.deploy.ProviderDeploymentContributor b/gateway-provider-identity-assertion-concat/src/main/resources/META-INF/services/org.apache.hadoop.gateway.deploy.ProviderDeploymentContributor
new file mode 100644
index 0000000..bbfd4ae
--- /dev/null
+++ b/gateway-provider-identity-assertion-concat/src/main/resources/META-INF/services/org.apache.hadoop.gateway.deploy.ProviderDeploymentContributor
@@ -0,0 +1,19 @@
+##########################################################################
+# 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.
+##########################################################################
+
+org.apache.hadoop.gateway.identityasserter.concat.filter.ConcatIdentityAsserterDeploymentContributor
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/knox/blob/ce3ca3ce/gateway-provider-identity-assertion-concat/src/test/java/org/apache/hadoop/gateway/identityasserter/concat/filter/ConcatIdentityAsserterDeploymentContributorTest.java
----------------------------------------------------------------------
diff --git a/gateway-provider-identity-assertion-concat/src/test/java/org/apache/hadoop/gateway/identityasserter/concat/filter/ConcatIdentityAsserterDeploymentContributorTest.java b/gateway-provider-identity-assertion-concat/src/test/java/org/apache/hadoop/gateway/identityasserter/concat/filter/ConcatIdentityAsserterDeploymentContributorTest.java
new file mode 100644
index 0000000..b046ef6
--- /dev/null
+++ b/gateway-provider-identity-assertion-concat/src/test/java/org/apache/hadoop/gateway/identityasserter/concat/filter/ConcatIdentityAsserterDeploymentContributorTest.java
@@ -0,0 +1,45 @@
+/**
+ * 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.identityasserter.concat.filter;
+
+import org.apache.hadoop.gateway.deploy.ProviderDeploymentContributor;
+import org.apache.hadoop.gateway.identityasserter.concat.filter.ConcatIdentityAsserterDeploymentContributor;
+import org.junit.Test;
+
+import java.util.Iterator;
+import java.util.ServiceLoader;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.fail;
+
+public class ConcatIdentityAsserterDeploymentContributorTest {
+
+ @Test
+ public void testServiceLoader() throws Exception {
+ ServiceLoader<ProviderDeploymentContributor> loader = ServiceLoader.load( ProviderDeploymentContributor.class );
+ Iterator<ProviderDeploymentContributor> iterator = loader.iterator();
+ assertThat( "Service iterator empty.", iterator.hasNext() );
+ while( iterator.hasNext() ) {
+ Object object = iterator.next();
+ if( object instanceof ConcatIdentityAsserterDeploymentContributor ) {
+ return;
+ }
+ }
+ fail( "Failed to find " + ConcatIdentityAsserterDeploymentContributor.class.getName() + " via service loader." );
+ }
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/ce3ca3ce/gateway-provider-identity-assertion-concat/src/test/java/org/apache/hadoop/gateway/identityasserter/concat/filter/ConcatIdentityAssertionFilterTest.java
----------------------------------------------------------------------
diff --git a/gateway-provider-identity-assertion-concat/src/test/java/org/apache/hadoop/gateway/identityasserter/concat/filter/ConcatIdentityAssertionFilterTest.java b/gateway-provider-identity-assertion-concat/src/test/java/org/apache/hadoop/gateway/identityasserter/concat/filter/ConcatIdentityAssertionFilterTest.java
new file mode 100644
index 0000000..924f9d3
--- /dev/null
+++ b/gateway-provider-identity-assertion-concat/src/test/java/org/apache/hadoop/gateway/identityasserter/concat/filter/ConcatIdentityAssertionFilterTest.java
@@ -0,0 +1,78 @@
+/**
+ * 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.identityasserter.concat.filter;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+
+import java.security.Principal;
+
+import javax.security.auth.Subject;
+import javax.servlet.FilterConfig;
+
+import org.apache.hadoop.gateway.security.GroupPrincipal;
+import org.apache.hadoop.gateway.security.PrimaryPrincipal;
+import org.easymock.EasyMock;
+import org.junit.Test;
+
+/**
+ *
+ */
+public class ConcatIdentityAssertionFilterTest {
+
+ @Test
+ public void testPrefixAndSuffix() throws Exception {
+ FilterConfig config = EasyMock.createNiceMock( FilterConfig.class );
+ EasyMock.replay( config );
+
+ ConcatIdentityAssertionFilter filter = new ConcatIdentityAssertionFilter();
+ Subject subject = new Subject();
+
+ subject.getPrincipals().add(new PrimaryPrincipal("larry"));
+ subject.getPrincipals().add(new GroupPrincipal("users"));
+ subject.getPrincipals().add(new GroupPrincipal("admin"));
+
+ filter.init(config);
+ String username = filter.mapUserPrincipal(((Principal) subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName());
+ String[] groups = filter.mapGroupPrincipals(username, subject);
+ assertEquals(username, "larry");
+ assertNull(groups); // means for the caller to use the existing subject groups
+
+ config = EasyMock.createNiceMock( FilterConfig.class );
+ EasyMock.expect(config.getInitParameter("concat.prefix") ).andReturn( "sir-" ).anyTimes();
+ EasyMock.replay( config );
+ filter.init(config);
+ username = filter.mapUserPrincipal(((Principal) subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName());
+ assertEquals(username, "sir-larry");
+
+ config = EasyMock.createNiceMock( FilterConfig.class );
+ EasyMock.expect(config.getInitParameter("concat.suffix") ).andReturn( "-tenant-1" ).anyTimes();
+ EasyMock.replay( config );
+ filter.init(config);
+ username = filter.mapUserPrincipal(((Principal) subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName());
+ assertEquals(username, "larry-tenant-1");
+
+ config = EasyMock.createNiceMock( FilterConfig.class );
+ EasyMock.expect(config.getInitParameter("concat.prefix") ).andReturn( "sir-" ).anyTimes();
+ EasyMock.expect(config.getInitParameter("concat.suffix") ).andReturn( "-tenant-1" ).anyTimes();
+ EasyMock.replay( config );
+ filter.init(config);
+ username = filter.mapUserPrincipal(((Principal) subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName());
+ assertEquals(username, "sir-larry-tenant-1");
+ }
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/ce3ca3ce/gateway-provider-identity-assertion-pseudo/pom.xml
----------------------------------------------------------------------
diff --git a/gateway-provider-identity-assertion-pseudo/pom.xml b/gateway-provider-identity-assertion-pseudo/pom.xml
index 191c602..8fd7269 100644
--- a/gateway-provider-identity-assertion-pseudo/pom.xml
+++ b/gateway-provider-identity-assertion-pseudo/pom.xml
@@ -47,7 +47,7 @@
<dependency>
<groupId>${gateway-group}</groupId>
- <artifactId>gateway-spi</artifactId>
+ <artifactId>gateway-provider-identity-assertion-common</artifactId>
</dependency>
<dependency>
http://git-wip-us.apache.org/repos/asf/knox/blob/ce3ca3ce/gateway-provider-identity-assertion-pseudo/src/main/java/org/apache/hadoop/gateway/identityasserter/filter/IdentityAsserterDeploymentContributor.java
----------------------------------------------------------------------
diff --git a/gateway-provider-identity-assertion-pseudo/src/main/java/org/apache/hadoop/gateway/identityasserter/filter/IdentityAsserterDeploymentContributor.java b/gateway-provider-identity-assertion-pseudo/src/main/java/org/apache/hadoop/gateway/identityasserter/filter/IdentityAsserterDeploymentContributor.java
index bb5cd99..b261138 100644
--- a/gateway-provider-identity-assertion-pseudo/src/main/java/org/apache/hadoop/gateway/identityasserter/filter/IdentityAsserterDeploymentContributor.java
+++ b/gateway-provider-identity-assertion-pseudo/src/main/java/org/apache/hadoop/gateway/identityasserter/filter/IdentityAsserterDeploymentContributor.java
@@ -21,43 +21,38 @@ import org.apache.hadoop.gateway.deploy.DeploymentContext;
import org.apache.hadoop.gateway.deploy.ProviderDeploymentContributorBase;
import org.apache.hadoop.gateway.descriptor.FilterParamDescriptor;
import org.apache.hadoop.gateway.descriptor.ResourceDescriptor;
+import org.apache.hadoop.gateway.identityasserter.common.filter.AbstractIdentityAsserterDeploymentContributor;
import org.apache.hadoop.gateway.topology.Provider;
import org.apache.hadoop.gateway.topology.Service;
import java.util.List;
-public class IdentityAsserterDeploymentContributor extends ProviderDeploymentContributorBase {
+public class IdentityAsserterDeploymentContributor extends AbstractIdentityAsserterDeploymentContributor {
private static final String FILTER_CLASSNAME = IdentityAsserterFilter.class.getName();
private static final String PRINCIPAL_MAPPING_PARAM_NAME = "principal.mapping";
private static final String GROUP_PRINCIPAL_MAPPING_PARAM_NAME = "group.principal.mapping";
@Override
- public String getRole() {
- return "identity-assertion";
- }
-
- @Override
public String getName() {
return "Pseudo";
}
@Override
public void contributeProvider( DeploymentContext context, Provider provider ) {
+ super.contributeProvider(context, provider);
String mappings = provider.getParams().get(PRINCIPAL_MAPPING_PARAM_NAME);
String groupMappings = provider.getParams().get(GROUP_PRINCIPAL_MAPPING_PARAM_NAME);
-// ServletType<WebAppDescriptor> servlet = findServlet( context, context.getTopology().getName() );
-// servlet.createInitParam()
-// .paramName( PRINCIPAL_MAPPING_PARAM_NAME )
-// .paramValue( mappings );
-
context.getWebAppDescriptor().createContextParam().paramName(PRINCIPAL_MAPPING_PARAM_NAME).paramValue(mappings);
context.getWebAppDescriptor().createContextParam().paramName(GROUP_PRINCIPAL_MAPPING_PARAM_NAME).paramValue(groupMappings);
}
+ /* (non-Javadoc)
+ * @see org.apache.hadoop.gateway.identityasserter.common.filter.AbstractIdentityAsserterDeploymentContributor#getFilterClassname()
+ */
@Override
- public void contributeFilter( DeploymentContext context, Provider provider, Service service, ResourceDescriptor resource, List<FilterParamDescriptor> params ) {
- resource.addFilter().name( getName() ).role( getRole() ).impl( FILTER_CLASSNAME ).params( params );
+ protected String getFilterClassname() {
+ return FILTER_CLASSNAME;
}
}
http://git-wip-us.apache.org/repos/asf/knox/blob/ce3ca3ce/gateway-provider-identity-assertion-pseudo/src/main/java/org/apache/hadoop/gateway/identityasserter/filter/IdentityAsserterFilter.java
----------------------------------------------------------------------
diff --git a/gateway-provider-identity-assertion-pseudo/src/main/java/org/apache/hadoop/gateway/identityasserter/filter/IdentityAsserterFilter.java b/gateway-provider-identity-assertion-pseudo/src/main/java/org/apache/hadoop/gateway/identityasserter/filter/IdentityAsserterFilter.java
index b39fd90..c3fffba 100644
--- a/gateway-provider-identity-assertion-pseudo/src/main/java/org/apache/hadoop/gateway/identityasserter/filter/IdentityAsserterFilter.java
+++ b/gateway-provider-identity-assertion-pseudo/src/main/java/org/apache/hadoop/gateway/identityasserter/filter/IdentityAsserterFilter.java
@@ -19,39 +19,43 @@ package org.apache.hadoop.gateway.identityasserter.filter;
import javax.security.auth.Subject;
-import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-
-import org.apache.hadoop.gateway.filter.security.AbstractIdentityAssertionFilter;
-
-import java.io.IOException;
-import java.security.AccessController;
-
-public class IdentityAsserterFilter extends AbstractIdentityAssertionFilter {
-
- /**
- * Obtain the standard javax.security.auth.Subject, retrieve the caller principal, map
- * to the identity to be asserted as appropriate and create the provider specific
- * assertion token. Add the assertion token to the request.
- */
- public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
- throws IOException, ServletException {
-// System.out.println("+++++++++++++ Identity Assertion Filtering");
- Subject subject = Subject.getSubject(AccessController.getContext());
+import org.apache.hadoop.gateway.identityasserter.common.filter.CommonIdentityAssertionFilter;
+import org.apache.hadoop.gateway.security.principal.PrincipalMappingException;
+import org.apache.hadoop.gateway.security.principal.SimplePrincipalMapper;
+
+public class IdentityAsserterFilter extends CommonIdentityAssertionFilter {
+ private static final String GROUP_PRINCIPAL_MAPPING = "group.principal.mapping";
+ private static final String PRINCIPAL_MAPPING = "principal.mapping";
+ private SimplePrincipalMapper mapper = new SimplePrincipalMapper();
+
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException {
+ String principalMapping = filterConfig.getInitParameter(PRINCIPAL_MAPPING);
+ if (principalMapping == null || principalMapping.isEmpty()) {
+ principalMapping = filterConfig.getServletContext().getInitParameter(PRINCIPAL_MAPPING);
+ }
+ String groupPrincipalMapping = filterConfig.getInitParameter(GROUP_PRINCIPAL_MAPPING);
+ if (groupPrincipalMapping == null || groupPrincipalMapping.isEmpty()) {
+ groupPrincipalMapping = filterConfig.getServletContext().getInitParameter(GROUP_PRINCIPAL_MAPPING);
+ }
+ if (principalMapping != null && !principalMapping.isEmpty() || groupPrincipalMapping != null && !groupPrincipalMapping.isEmpty()) {
+ try {
+ mapper.loadMappingTable(principalMapping, groupPrincipalMapping);
+ } catch (PrincipalMappingException e) {
+ throw new ServletException("Unable to load principal mapping table.", e);
+ }
+ }
+ }
- String principalName = getPrincipalName(subject);
- String mappedPrincipalName = mapper.mapUserPrincipal(principalName);
-
- // wrap the request so that the proper principal is returned
- // from request methods
- IdentityAsserterHttpServletRequestWrapper wrapper =
- new IdentityAsserterHttpServletRequestWrapper(
- (HttpServletRequest)request,
- mappedPrincipalName);
+ @Override
+ public String[] mapGroupPrincipals(String mappedPrincipalName, Subject subject) {
+ return mapper.mapGroupPrincipal(mappedPrincipalName);
+ }
- continueChainAsPrincipal(wrapper, response, chain, mappedPrincipalName);
+ @Override
+ public String mapUserPrincipal(String principalName) {
+ return mapper.mapUserPrincipal(principalName);
}
}
http://git-wip-us.apache.org/repos/asf/knox/blob/ce3ca3ce/gateway-provider-identity-assertion-pseudo/src/main/java/org/apache/hadoop/gateway/identityasserter/filter/IdentityAsserterHttpServletRequestWrapper.java
----------------------------------------------------------------------
diff --git a/gateway-provider-identity-assertion-pseudo/src/main/java/org/apache/hadoop/gateway/identityasserter/filter/IdentityAsserterHttpServletRequestWrapper.java b/gateway-provider-identity-assertion-pseudo/src/main/java/org/apache/hadoop/gateway/identityasserter/filter/IdentityAsserterHttpServletRequestWrapper.java
deleted file mode 100644
index 633abee..0000000
--- a/gateway-provider-identity-assertion-pseudo/src/main/java/org/apache/hadoop/gateway/identityasserter/filter/IdentityAsserterHttpServletRequestWrapper.java
+++ /dev/null
@@ -1,227 +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.hadoop.gateway.identityasserter.filter;
-
-import org.apache.commons.io.IOUtils;
-import org.apache.hadoop.gateway.IdentityAsserterMessages;
-import org.apache.hadoop.gateway.config.GatewayConfig;
-import org.apache.hadoop.gateway.i18n.messages.MessagesFactory;
-
-import javax.servlet.ServletInputStream;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletRequestWrapper;
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.UnsupportedEncodingException;
-import java.net.URLEncoder;
-import java.nio.charset.Charset;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Enumeration;
-import java.util.HashMap;
-import java.util.Map;
-
-public class IdentityAsserterHttpServletRequestWrapper extends HttpServletRequestWrapper {
-
- private static IdentityAsserterMessages log = MessagesFactory.get( IdentityAsserterMessages.class );
-
- private static final String PRINCIPAL_PARAM = "user.name";
- private static final String DOAS_PRINCIPAL_PARAM = "doAs";
-
- String username = null;
-
- public IdentityAsserterHttpServletRequestWrapper( HttpServletRequest request, String principal ) {
- super(request);
- username = principal;
- }
-
- @Override
- public String getParameter(String name) {
- if (name.equals(PRINCIPAL_PARAM)) {
- return username;
- }
- return super.getParameter(name);
- }
-
- @SuppressWarnings("rawtypes")
- @Override
- public Map getParameterMap() {
- return getParams();
- }
-
- @SuppressWarnings({ "unchecked", "rawtypes" })
- @Override
- public Enumeration getParameterNames() {
- Map<String, String[]> params = getParams();
- Enumeration<String> e = Collections.enumeration((Collection<String>) params);
-
- return e;
- }
-
- @Override
- public String[] getParameterValues(String name) {
- Map<String, String[]> params = getParams();
-
- return params.get(name);
- }
-
- private Map<String, String[]> getParams( String qString ) {
- Map<String, String[]> params = null;
- if (getMethod().equals("GET")) {
- if (qString != null && qString.length() > 0) {
- params = parseQueryString(qString);
- }
- else {
- params = new HashMap<String, String[]>();
- }
- }
- else {
- if (qString == null || qString.length() == 0) {
- return null;
- }
- else {
- params = parseQueryString(qString);
- }
- }
- return params;
- }
-
- private Map<String, String[]> getParams() {
- return getParams( super.getQueryString() );
- }
-
- @Override
- public String getQueryString() {
- String q = null;
- Map<String, String[]> params = getParams();
-
- if (params == null) {
- params = new HashMap<String, String[]>();
- }
-
- ArrayList<String> al = new ArrayList<String>();
- al.add(username);
- String[] a = { "" };
-
- if ("true".equals(System.getProperty(GatewayConfig.HADOOP_KERBEROS_SECURED))) {
- params.put(DOAS_PRINCIPAL_PARAM, al.toArray(a));
- params.remove(PRINCIPAL_PARAM);
- } else {
- params.put(PRINCIPAL_PARAM, al.toArray(a));
- }
-
- String encoding = getCharacterEncoding();
- if (encoding == null) {
- encoding = Charset.defaultCharset().name();
- }
- q = urlEncode(params, encoding);
- return q;
- }
-
- @Override
- public int getContentLength() {
- int len;
- String contentType = getContentType();
- // If the content type is a form we might rewrite the body so default it to -1.
- if( contentType != null && contentType.startsWith( "application/x-www-form-urlencoded" ) ) {
- len = -1;
- } else {
- len = super.getContentLength();
- }
- return len;
- }
-
- @Override
- public ServletInputStream getInputStream() throws java.io.IOException {
- String contentType = getContentType();
- if( contentType != null && contentType.startsWith( "application/x-www-form-urlencoded" ) ) {
- String encoding = getCharacterEncoding();
- if( encoding == null ) {
- encoding = Charset.defaultCharset().name();
- }
- String body = IOUtils.toString( super.getInputStream(), encoding );
- Map<String, String[]> params = getParams( body );
- body = urlEncode( params, encoding );
- // ASCII is OK here because the urlEncode about should have already escaped
- return new ServletInputStreamWrapper( new ByteArrayInputStream( body.getBytes( "US-ASCII" ) ) );
- } else {
- return super.getInputStream();
- }
- }
-
- static String urlEncode( String string, String encoding ) {
- try {
- return URLEncoder.encode( string, encoding );
- } catch (UnsupportedEncodingException e) {
- throw new UnsupportedOperationException(e);
- }
- }
-
- static String urlEncode( Map<String, String[]> map, String encoding ) {
- StringBuilder sb = new StringBuilder();
- for( Map.Entry<String,String[]> entry : map.entrySet() ) {
- String name = entry.getKey();
- if( name != null && name.length() > 0 ) {
- String[] values = entry.getValue();
- if( values == null || values.length == 0 ) {
- sb.append( entry.getKey() );
- } else {
- for( int i = 0; i < values.length; i++ ) {
- String value = values[ i ];
- if( value != null ) {
- if( sb.length() > 0 ) {
- sb.append( "&" );
- }
- try {
- sb.append( urlEncode( name, encoding ) );
- sb.append( "=" );
- sb.append( urlEncode( value, encoding ) );
- } catch( IllegalArgumentException e ) {
- log.skippingUnencodableParameter( name, value, encoding, e );
- }
- }
- }
- }
- }
- }
- return sb.toString();
- }
-
- @SuppressWarnings({ "deprecation", "unchecked" })
- private static Map<String,String[]> parseQueryString( String queryString ) {
- return javax.servlet.http.HttpUtils.parseQueryString( queryString );
- }
-
- private class ServletInputStreamWrapper extends ServletInputStream {
-
- private InputStream stream;
-
- private ServletInputStreamWrapper( InputStream stream ) {
- this.stream = stream;
- }
-
- @Override
- public int read() throws IOException {
- return stream.read();
- }
-
- }
-
-}
http://git-wip-us.apache.org/repos/asf/knox/blob/ce3ca3ce/gateway-provider-identity-assertion-pseudo/src/main/java/org/apache/hadoop/gateway/identityasserter/function/UsernameFunctionDescriptor.java
----------------------------------------------------------------------
diff --git a/gateway-provider-identity-assertion-pseudo/src/main/java/org/apache/hadoop/gateway/identityasserter/function/UsernameFunctionDescriptor.java b/gateway-provider-identity-assertion-pseudo/src/main/java/org/apache/hadoop/gateway/identityasserter/function/UsernameFunctionDescriptor.java
deleted file mode 100644
index d2aa441..0000000
--- a/gateway-provider-identity-assertion-pseudo/src/main/java/org/apache/hadoop/gateway/identityasserter/function/UsernameFunctionDescriptor.java
+++ /dev/null
@@ -1,31 +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.hadoop.gateway.identityasserter.function;
-
-import org.apache.hadoop.gateway.filter.rewrite.api.UrlRewriteFunctionDescriptor;
-
-public class UsernameFunctionDescriptor implements UrlRewriteFunctionDescriptor<UsernameFunctionDescriptor> {
-
- public static final String FUNCTION_NAME = "username";
-
- @Override
- public String name() {
- return FUNCTION_NAME;
- }
-
-}
http://git-wip-us.apache.org/repos/asf/knox/blob/ce3ca3ce/gateway-provider-identity-assertion-pseudo/src/main/java/org/apache/hadoop/gateway/identityasserter/function/UsernameFunctionProcessor.java
----------------------------------------------------------------------
diff --git a/gateway-provider-identity-assertion-pseudo/src/main/java/org/apache/hadoop/gateway/identityasserter/function/UsernameFunctionProcessor.java b/gateway-provider-identity-assertion-pseudo/src/main/java/org/apache/hadoop/gateway/identityasserter/function/UsernameFunctionProcessor.java
deleted file mode 100644
index 1e65f89..0000000
--- a/gateway-provider-identity-assertion-pseudo/src/main/java/org/apache/hadoop/gateway/identityasserter/function/UsernameFunctionProcessor.java
+++ /dev/null
@@ -1,74 +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.hadoop.gateway.identityasserter.function;
-
-import org.apache.hadoop.gateway.filter.rewrite.api.UrlRewriteEnvironment;
-import org.apache.hadoop.gateway.filter.rewrite.spi.UrlRewriteContext;
-import org.apache.hadoop.gateway.filter.rewrite.spi.UrlRewriteFunctionProcessor;
-import org.apache.hadoop.gateway.filter.security.AbstractIdentityAssertionBase;
-import org.apache.hadoop.gateway.i18n.GatewaySpiMessages;
-import org.apache.hadoop.gateway.i18n.messages.MessagesFactory;
-import org.apache.hadoop.gateway.security.SubjectUtils;
-
-import javax.security.auth.Subject;
-import java.security.AccessController;
-import java.util.ArrayList;
-import java.util.List;
-
-public class UsernameFunctionProcessor
- implements UrlRewriteFunctionProcessor<UsernameFunctionDescriptor> {
-
- private static final GatewaySpiMessages LOG = MessagesFactory.get( GatewaySpiMessages.class );
-// private PrincipalMapper mapper = null;
-
- @Override
- public String name() {
- return UsernameFunctionDescriptor.FUNCTION_NAME;
- }
-
- @Override
- public void initialize( UrlRewriteEnvironment environment, UsernameFunctionDescriptor descriptor ) throws Exception {
-// if( environment != null ) {
-// GatewayServices services = environment.getAttribute( GatewayServices.GATEWAY_SERVICES_ATTRIBUTE );
-// if( services != null ) {
-// mapper = (PrincipalMapper)services.getService( "PrincipalMapperService" /*GatewayServices.PRINCIPAL_MAPPER_SERVICE*/ );
-// }
-// }
- }
-
- @Override
- public void destroy() throws Exception {
- }
-
- @Override
- public List<String> resolve( UrlRewriteContext context, List<String> parameters ) throws Exception {
- List<String> results = null;
- Subject subject = SubjectUtils.getCurrentSubject( );
- if( subject != null ) {
- results = new ArrayList<String>( 1 );
- String username = SubjectUtils.getEffectivePrincipalName(subject);
- results.add( username );
- } else if( parameters != null && parameters.size() > 0 ) {
- results = new ArrayList<String>( 1 );
- results.add( parameters.get( 0 ) );
- }
- return results;
- }
-
-}
-
http://git-wip-us.apache.org/repos/asf/knox/blob/ce3ca3ce/gateway-provider-identity-assertion-pseudo/src/main/resources/META-INF/services/org.apache.hadoop.gateway.filter.rewrite.api.UrlRewriteFunctionDescriptor
----------------------------------------------------------------------
diff --git a/gateway-provider-identity-assertion-pseudo/src/main/resources/META-INF/services/org.apache.hadoop.gateway.filter.rewrite.api.UrlRewriteFunctionDescriptor b/gateway-provider-identity-assertion-pseudo/src/main/resources/META-INF/services/org.apache.hadoop.gateway.filter.rewrite.api.UrlRewriteFunctionDescriptor
deleted file mode 100644
index b42eb32..0000000
--- a/gateway-provider-identity-assertion-pseudo/src/main/resources/META-INF/services/org.apache.hadoop.gateway.filter.rewrite.api.UrlRewriteFunctionDescriptor
+++ /dev/null
@@ -1,19 +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.
-##########################################################################
-
-org.apache.hadoop.gateway.identityasserter.function.UsernameFunctionDescriptor
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/knox/blob/ce3ca3ce/gateway-provider-identity-assertion-pseudo/src/main/resources/META-INF/services/org.apache.hadoop.gateway.filter.rewrite.spi.UrlRewriteFunctionProcessor
----------------------------------------------------------------------
diff --git a/gateway-provider-identity-assertion-pseudo/src/main/resources/META-INF/services/org.apache.hadoop.gateway.filter.rewrite.spi.UrlRewriteFunctionProcessor b/gateway-provider-identity-assertion-pseudo/src/main/resources/META-INF/services/org.apache.hadoop.gateway.filter.rewrite.spi.UrlRewriteFunctionProcessor
deleted file mode 100644
index 74e0a96..0000000
--- a/gateway-provider-identity-assertion-pseudo/src/main/resources/META-INF/services/org.apache.hadoop.gateway.filter.rewrite.spi.UrlRewriteFunctionProcessor
+++ /dev/null
@@ -1,19 +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.
-##########################################################################
-
-org.apache.hadoop.gateway.identityasserter.function.UsernameFunctionProcessor
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/knox/blob/ce3ca3ce/gateway-provider-identity-assertion-pseudo/src/test/java/org/apache/hadoop/gateway/identityasserter/filter/DefaultIdentityAssertionFilterTest.java
----------------------------------------------------------------------
diff --git a/gateway-provider-identity-assertion-pseudo/src/test/java/org/apache/hadoop/gateway/identityasserter/filter/DefaultIdentityAssertionFilterTest.java b/gateway-provider-identity-assertion-pseudo/src/test/java/org/apache/hadoop/gateway/identityasserter/filter/DefaultIdentityAssertionFilterTest.java
new file mode 100644
index 0000000..9795a99
--- /dev/null
+++ b/gateway-provider-identity-assertion-pseudo/src/test/java/org/apache/hadoop/gateway/identityasserter/filter/DefaultIdentityAssertionFilterTest.java
@@ -0,0 +1,173 @@
+/**
+ * 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.identityasserter.filter;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.security.Principal;
+
+import javax.security.auth.Subject;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletContext;
+
+import org.apache.hadoop.gateway.security.GroupPrincipal;
+import org.apache.hadoop.gateway.security.PrimaryPrincipal;
+import org.easymock.EasyMock;
+import org.junit.Test;
+
+/**
+ *
+ */
+public class DefaultIdentityAssertionFilterTest {
+
+ @Test
+ public void testInitParameters() throws Exception {
+ FilterConfig config = EasyMock.createNiceMock( FilterConfig.class );
+ EasyMock.expect(config.getInitParameter("principal.mapping") ).andReturn( "" ).anyTimes();
+ ServletContext context = EasyMock.createNiceMock(ServletContext.class);
+ EasyMock.expect(config.getServletContext() ).andReturn( context ).anyTimes();
+ EasyMock.expect(context.getInitParameter("principal.mapping") ).andReturn( "" ).anyTimes();
+ EasyMock.replay( config );
+ EasyMock.replay( context );
+
+ IdentityAsserterFilter filter = new IdentityAsserterFilter();
+ Subject subject = new Subject();
+
+ subject.getPrincipals().add(new PrimaryPrincipal("lmccay"));
+ subject.getPrincipals().add(new GroupPrincipal("users"));
+ subject.getPrincipals().add(new GroupPrincipal("admin"));
+
+ filter.init(config);
+ String username = filter.mapUserPrincipal(((Principal) subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName());
+ String[] groups = filter.mapGroupPrincipals(username, subject);
+ assertEquals("lmccay", username);
+ assertNull(groups); // means for the caller to use the existing subject groups
+
+ config = EasyMock.createNiceMock( FilterConfig.class );
+ EasyMock.expect(config.getInitParameter("principal.mapping") ).andReturn( "lmccay,kminder=hdfs;newuser=mapred" ).anyTimes();
+ EasyMock.expect(config.getInitParameter("group.principal.mapping") ).andReturn( "kminder=group1;lmccay=mrgroup,mrducks" ).anyTimes();
+ context = EasyMock.createNiceMock(ServletContext.class);
+ EasyMock.expect(config.getServletContext() ).andReturn( context ).anyTimes();
+ EasyMock.replay( config );
+ filter.init(config);
+ username = filter.mapUserPrincipal(((Principal) subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName());
+ String[] mappedGroups = filter.mapGroupPrincipals(((Principal) subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName(), subject);
+ assertEquals("hdfs", username);
+ assertTrue("mrgroup not found in groups: " + mappedGroups, groupFoundIn("mrgroup", mappedGroups));
+ assertTrue("mrducks not found in groups: " + mappedGroups, groupFoundIn("mrducks", mappedGroups));
+ assertFalse("group1 WAS found in groups: " + mappedGroups, groupFoundIn("group1", mappedGroups));
+
+ subject = new Subject();
+
+ subject.getPrincipals().add(new PrimaryPrincipal("kminder"));
+ subject.getPrincipals().add(new GroupPrincipal("users"));
+ subject.getPrincipals().add(new GroupPrincipal("admin"));
+
+ config = EasyMock.createNiceMock( FilterConfig.class );
+ EasyMock.expect(config.getInitParameter("principal.mapping") ).andReturn( "lmccay,kminder=hdfs;newuser=mapred" ).anyTimes();
+ EasyMock.expect(config.getInitParameter("group.principal.mapping") ).andReturn( "kminder=group1;lmccay=mrgroup,mrducks" ).anyTimes();
+ context = EasyMock.createNiceMock(ServletContext.class);
+ EasyMock.expect(config.getServletContext() ).andReturn( context ).anyTimes();
+ EasyMock.replay( config );
+ filter.init(config);
+ username = filter.mapUserPrincipal(((Principal) subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName());
+ mappedGroups = filter.mapGroupPrincipals(((Principal) subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName(), subject);
+ assertEquals("hdfs", username);
+ assertTrue("group1 not found in groups: " + mappedGroups, groupFoundIn("group1", mappedGroups));
+ }
+
+ /**
+ * @param string
+ * @return
+ */
+ private boolean groupFoundIn(String expected, String[] mappedGroups) {
+ if (mappedGroups == null) return false;
+ for(int i = 0; i < mappedGroups.length; i++) {
+ if (mappedGroups[i].equals(expected)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ @Test
+ public void testContextParameters() throws Exception {
+ // for backward compatibility of old deployment contributor's method
+ // of adding init params to the servlet context instead of to the filter.
+ // There is the possibility that previously deployed topologies will have
+ // init params in web.xml at the context level instead of the filter level.
+ FilterConfig config = EasyMock.createNiceMock( FilterConfig.class );
+ EasyMock.expect(config.getInitParameter("principal.mapping") ).andReturn( "" ).anyTimes();
+ ServletContext context = EasyMock.createNiceMock(ServletContext.class);
+ EasyMock.expect(config.getServletContext() ).andReturn( context ).anyTimes();
+ EasyMock.replay( config );
+ EasyMock.replay( context );
+
+ IdentityAsserterFilter filter = new IdentityAsserterFilter();
+ Subject subject = new Subject();
+
+ subject.getPrincipals().add(new PrimaryPrincipal("lmccay"));
+ subject.getPrincipals().add(new GroupPrincipal("users"));
+ subject.getPrincipals().add(new GroupPrincipal("admin"));
+
+ filter.init(config);
+ String username = filter.mapUserPrincipal(((Principal) subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName());
+ String[] groups = filter.mapGroupPrincipals(((Principal) subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName(), subject);
+// String[] groups = filter.mapGroupPrincipals(username, subject);
+ assertEquals("lmccay", username);
+ assertNull(groups); // means for the caller to use the existing subject groups
+
+ config = EasyMock.createNiceMock( FilterConfig.class );
+ EasyMock.expect(config.getInitParameter("principal.mapping") ).andReturn( "" ).anyTimes();
+ context = EasyMock.createNiceMock(ServletContext.class);
+ EasyMock.expect(config.getServletContext() ).andReturn( context ).anyTimes();
+ EasyMock.expect(context.getInitParameter("principal.mapping") ).andReturn( "lmccay,kminder=hdfs;newuser=mapred" ).anyTimes();
+ EasyMock.expect(context.getInitParameter("group.principal.mapping") ).andReturn( "kminder=group1;lmccay=mrgroup,mrducks" ).anyTimes();
+ EasyMock.replay( config );
+ EasyMock.replay( context );
+ filter.init(config);
+ username = filter.mapUserPrincipal(((Principal) subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName());
+ groups = filter.mapGroupPrincipals(((Principal) subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName(), subject);
+ assertEquals("hdfs", username);
+ assertTrue("mrgroup not found in groups: " + groups, groupFoundIn("mrgroup", groups));
+ assertTrue("mrducks not found in groups: " + groups, groupFoundIn("mrducks", groups));
+ assertFalse("group1 WAS found in groups: " + groups, groupFoundIn("group1", groups));
+
+ subject = new Subject();
+
+ subject.getPrincipals().add(new PrimaryPrincipal("kminder"));
+ subject.getPrincipals().add(new GroupPrincipal("users"));
+ subject.getPrincipals().add(new GroupPrincipal("admin"));
+
+ config = EasyMock.createNiceMock( FilterConfig.class );
+ EasyMock.expect(config.getInitParameter("principal.mapping") ).andReturn( "" ).anyTimes();
+ context = EasyMock.createNiceMock(ServletContext.class);
+ EasyMock.expect(config.getServletContext() ).andReturn( context ).anyTimes();
+ EasyMock.expect(context.getInitParameter("principal.mapping") ).andReturn( "lmccay,kminder=hdfs;newuser=mapred" ).anyTimes();
+ EasyMock.expect(context.getInitParameter("group.principal.mapping") ).andReturn( "kminder=group1;lmccay=mrgroup,mrducks" ).anyTimes();
+ EasyMock.replay( config );
+ EasyMock.replay( context );
+ filter.init(config);
+ username = filter.mapUserPrincipal(((Principal) subject.getPrincipals(PrimaryPrincipal.class).toArray()[0]).getName());
+ assertEquals("hdfs", username);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/ce3ca3ce/gateway-provider-identity-assertion-pseudo/src/test/java/org/apache/hadoop/gateway/identityasserter/filter/IdentityAssertionHttpServletRequestWrapperTest.java
----------------------------------------------------------------------
diff --git a/gateway-provider-identity-assertion-pseudo/src/test/java/org/apache/hadoop/gateway/identityasserter/filter/IdentityAssertionHttpServletRequestWrapperTest.java b/gateway-provider-identity-assertion-pseudo/src/test/java/org/apache/hadoop/gateway/identityasserter/filter/IdentityAssertionHttpServletRequestWrapperTest.java
deleted file mode 100644
index 079540e..0000000
--- a/gateway-provider-identity-assertion-pseudo/src/test/java/org/apache/hadoop/gateway/identityasserter/filter/IdentityAssertionHttpServletRequestWrapperTest.java
+++ /dev/null
@@ -1,233 +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.hadoop.gateway.identityasserter.filter;
-
-import org.apache.commons.io.IOUtils;
-import org.apache.hadoop.test.category.FastTests;
-import org.apache.hadoop.test.category.UnitTests;
-import org.apache.hadoop.test.mock.MockHttpServletRequest;
-import org.apache.hadoop.test.mock.MockServletInputStream;
-import org.junit.Test;
-import org.junit.experimental.categories.Category;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.util.HashMap;
-
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.containsString;
-import static org.hamcrest.Matchers.is;
-import static org.hamcrest.Matchers.not;
-
-@Category( { UnitTests.class, FastTests.class } )
-public class IdentityAssertionHttpServletRequestWrapperTest {
-
- @Test
- public void testInsertUserNameInPostMethod() throws IOException {
- String inputBody = "jar=%2Ftmp%2FGatewayWebHdfsFuncTest%2FtestJavaMapReduceViaWebHCat%2Fhadoop-examples.jar&class=org.apache.org.apache.hadoop.examples.WordCount&arg=%2Ftmp%2FGatewayWebHdfsFuncTest%2FtestJavaMapReduceViaTempleton%2Finput&arg=%2Ftmp%2FGatewayWebHdfsFuncTest%2FtestJavaMapReduceViaTempleton%2Foutput";
-
- MockHttpServletRequest request = new MockHttpServletRequest();
- request.setInputStream( new MockServletInputStream( new ByteArrayInputStream( inputBody.getBytes( "UTF-8" ) ) ) );
- request.setCharacterEncoding( "UTF-8" );
- request.setContentType( "application/x-www-form-urlencoded" );
- request.setMethod("POST");
-
- IdentityAsserterHttpServletRequestWrapper wrapper
- = new IdentityAsserterHttpServletRequestWrapper( request, "output-user" );
-
- String outputBody = IOUtils.toString( wrapper.getInputStream(), wrapper.getCharacterEncoding() );
- String output = wrapper.getQueryString();
- assertThat( output, containsString( "user.name=output-user" ) );
- }
-
- @Test
- public void testInsertUserNameInPostMethodWithoutEncoding() throws IOException {
- String inputBody = "jar=%2Ftmp%2FGatewayWebHdfsFuncTest%2FtestJavaMapReduceViaWebHCat%2Fhadoop-examples.jar&class=org.apache.org.apache.hadoop.examples.WordCount&arg=%2Ftmp%2FGatewayWebHdfsFuncTest%2FtestJavaMapReduceViaTempleton%2Finput&arg=%2Ftmp%2FGatewayWebHdfsFuncTest%2FtestJavaMapReduceViaTempleton%2Foutput";
-
- MockHttpServletRequest request = new MockHttpServletRequest();
- request.setInputStream( new MockServletInputStream( new ByteArrayInputStream( inputBody.getBytes( "UTF-8" ) ) ) );
- request.setContentType( "application/x-www-form-urlencoded" );
- request.setMethod("POST");
-
- IdentityAsserterHttpServletRequestWrapper wrapper
- = new IdentityAsserterHttpServletRequestWrapper( request, "output-user" );
-
- String outputBody = IOUtils.toString( wrapper.getInputStream(), wrapper.getCharacterEncoding() );
- String output = wrapper.getQueryString();
- assertThat( output, containsString( "user.name=output-user" ) );
- }
-
- @Test
- public void testInsertUserNameInPostMethodWithIso88591Encoding() throws IOException {
- String inputBody = "jar=%2Ftmp%2FGatewayWebHdfsFuncTest%2FtestJavaMapReduceViaWebHCat%2Fhadoop-examples.jar&class=org.apache.org.apache.hadoop.examples.WordCount&arg=%2Ftmp%2FGatewayWebHdfsFuncTest%2FtestJavaMapReduceViaTempleton%2Finput&arg=%2Ftmp%2FGatewayWebHdfsFuncTest%2FtestJavaMapReduceViaTempleton%2Foutput";
-
- MockHttpServletRequest request = new MockHttpServletRequest();
- request.setInputStream( new MockServletInputStream( new ByteArrayInputStream( inputBody.getBytes( "UTF-8" ) ) ) );
- request.setContentType( "application/x-www-form-urlencoded" );
- request.setCharacterEncoding( "ISO-8859-1" );
- request.setMethod("POST");
-
- IdentityAsserterHttpServletRequestWrapper wrapper
- = new IdentityAsserterHttpServletRequestWrapper( request, "output-user" );
-
- String outputBody = IOUtils.toString( wrapper.getInputStream(), wrapper.getCharacterEncoding() );
- String output = wrapper.getQueryString();
- assertThat( output, containsString( "user.name=output-user" ) );
- }
-
- @Test
- public void testOverwriteUserNameInPostMethod() throws IOException {
- String inputBody = "user.name=input-user&jar=%2Ftmp%2FGatewayWebHdfsFuncTest%2FtestJavaMapReduceViaWebHCat%2Fhadoop-examples.jar&class=org.apache.org.apache.hadoop.examples.WordCount&arg=%2Ftmp%2FGatewayWebHdfsFuncTest%2FtestJavaMapReduceViaTempleton%2Finput&arg=%2Ftmp%2FGatewayWebHdfsFuncTest%2FtestJavaMapReduceViaTempleton%2Foutput";
-
- MockHttpServletRequest request = new MockHttpServletRequest();
- request.setInputStream( new MockServletInputStream( new ByteArrayInputStream( inputBody.getBytes( "UTF-8" ) ) ) );
- request.setCharacterEncoding( "UTF-8" );
- request.setContentType( "application/x-www-form-urlencoded" );
- request.setMethod("POST");
-
- IdentityAsserterHttpServletRequestWrapper wrapper
- = new IdentityAsserterHttpServletRequestWrapper( request, "output-user" );
-
- String outputBody = IOUtils.toString( wrapper.getInputStream(), wrapper.getCharacterEncoding() );
- String output = wrapper.getQueryString();
- assertThat( output, containsString( "user.name=output-user" ) );
- assertThat( output, not( containsString( "input-user" ) ) );
- }
-
- @Test
- public void testIngoreNonFormBody() throws IOException {
- String inputBody = "user.name=input-user&jar=%2Ftmp%2FGatewayWebHdfsFuncTest%2FtestJavaMapReduceViaWebHCat%2Fhadoop-examples.jar&class=org.apache.org.apache.hadoop.examples.WordCount&arg=%2Ftmp%2FGatewayWebHdfsFuncTest%2FtestJavaMapReduceViaTempleton%2Finput&arg=%2Ftmp%2FGatewayWebHdfsFuncTest%2FtestJavaMapReduceViaTempleton%2Foutput";
-
- MockHttpServletRequest request = new MockHttpServletRequest();
- request.setInputStream( new MockServletInputStream( new ByteArrayInputStream( inputBody.getBytes( "UTF-8" ) ) ) );
- request.setCharacterEncoding( "UTF-8" );
- request.setContentType( "text/plain" );
-
- IdentityAsserterHttpServletRequestWrapper wrapper
- = new IdentityAsserterHttpServletRequestWrapper( request, "output-user" );
-
- String outputBody = IOUtils.toString( wrapper.getInputStream(), wrapper.getCharacterEncoding() );
-
- assertThat( outputBody, containsString( "user.name=input-user" ) );
- assertThat( outputBody, not( containsString( "output-user" ) ) );
- }
-
- @Test
- public void testInsertUserNameInQueryString() {
- String input = "param=value";
-
- MockHttpServletRequest request = new MockHttpServletRequest();
- request.setQueryString( input );
-
- IdentityAsserterHttpServletRequestWrapper wrapper
- = new IdentityAsserterHttpServletRequestWrapper( request, "output-user" );
-
- String output = wrapper.getQueryString();
-
- assertThat( output, containsString( "user.name=output-user" ) );
- }
-
- @Test
- public void testInsertUserNameInNullQueryString() {
- String input = null;
-
- MockHttpServletRequest request = new MockHttpServletRequest();
- request.setQueryString( input );
-
- IdentityAsserterHttpServletRequestWrapper wrapper
- = new IdentityAsserterHttpServletRequestWrapper( request, "output-user" );
-
- String output = wrapper.getQueryString();
-
- assertThat( output, containsString( "user.name=output-user" ) );
- }
-
- @Test
- public void testInsertUserNameInNullQueryStringForGET() {
- String input = null;
-
- MockHttpServletRequest request = new MockHttpServletRequest();
- request.setQueryString( input );
-
- IdentityAsserterHttpServletRequestWrapper wrapper
- = new IdentityAsserterHttpServletRequestWrapper( request, "output-user" );
-
- String output = wrapper.getQueryString();
-
- assertThat( output, containsString( "user.name=output-user" ) );
- }
-
- @Test
- public void testInsertUserNameInQueryStringForPOST() {
- String input = null;
-
- MockHttpServletRequest request = new MockHttpServletRequest();
- request.setQueryString( input );
- request.setMethod("POST");
-
- IdentityAsserterHttpServletRequestWrapper wrapper
- = new IdentityAsserterHttpServletRequestWrapper( request, "output-user" );
-
- String output = wrapper.getQueryString();
-
- assertThat( output, containsString( "user.name=output-user" ) );
- }
-
- @Test
- public void testOverwriteUserNameInQueryString() {
- String input = "user.name=input-user";
-
- MockHttpServletRequest request = new MockHttpServletRequest();
- request.setQueryString( input );
-
- IdentityAsserterHttpServletRequestWrapper wrapper
- = new IdentityAsserterHttpServletRequestWrapper( request, "output-user" );
-
- String output = wrapper.getQueryString();
-
- assertThat( output, containsString( "user.name=output-user" ) );
- assertThat( output, not( containsString( "input-user" ) ) );
- }
-
- @Test
- public void testUrlEncode() {
- String s;
- HashMap<String,String[]> m;
-
- m = new HashMap<String,String[]>();
- m.put( "null-values", null );
- s = IdentityAsserterHttpServletRequestWrapper.urlEncode( m, "UTF-8" );
- assertThat( s, is( "null-values" ) );
-
- m = new HashMap<String,String[]>();
- m.put( "no-values", new String[0] );
- s = IdentityAsserterHttpServletRequestWrapper.urlEncode( m, "UTF-8" );
- assertThat( s, is( "no-values" ) );
-
- m = new HashMap<String,String[]>();
- m.put( "one-value", new String[]{ "value1" } );
- s = IdentityAsserterHttpServletRequestWrapper.urlEncode( m, "UTF-8" );
- assertThat( s, is( "one-value=value1" ) );
-
- m = new HashMap<String,String[]>();
- m.put( "two-values", new String[]{ "value1", "value2" } );
- s = IdentityAsserterHttpServletRequestWrapper.urlEncode( m, "UTF-8" );
- assertThat( s, is( "two-values=value1&two-values=value2" ) );
- }
-
-}
http://git-wip-us.apache.org/repos/asf/knox/blob/ce3ca3ce/gateway-provider-identity-assertion-pseudo/src/test/java/org/apache/hadoop/gateway/identityasserter/function/UsernameFunctionDescriptorTest.java
----------------------------------------------------------------------
diff --git a/gateway-provider-identity-assertion-pseudo/src/test/java/org/apache/hadoop/gateway/identityasserter/function/UsernameFunctionDescriptorTest.java b/gateway-provider-identity-assertion-pseudo/src/test/java/org/apache/hadoop/gateway/identityasserter/function/UsernameFunctionDescriptorTest.java
deleted file mode 100644
index 3d835bf..0000000
--- a/gateway-provider-identity-assertion-pseudo/src/test/java/org/apache/hadoop/gateway/identityasserter/function/UsernameFunctionDescriptorTest.java
+++ /dev/null
@@ -1,51 +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.hadoop.gateway.identityasserter.function;
-
-import org.apache.hadoop.gateway.filter.rewrite.api.UrlRewriteFunctionDescriptor;
-import org.junit.Test;
-
-import java.util.Iterator;
-import java.util.ServiceLoader;
-
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.junit.Assert.fail;
-
-public class UsernameFunctionDescriptorTest {
-
- @Test
- public void testName() throws Exception {
- UsernameFunctionDescriptor descriptor = new UsernameFunctionDescriptor();
- assertThat( descriptor.name(), is( "username" ) );
- }
-
- @Test
- public void testServiceLoader() throws Exception {
- ServiceLoader loader = ServiceLoader.load( UrlRewriteFunctionDescriptor.class );
- Iterator iterator = loader.iterator();
- while( iterator.hasNext() ) {
- Object object = iterator.next();
- if( object instanceof UsernameFunctionDescriptor ) {
- return;
- }
- }
- fail( "Failed to find UsernameFunctionDescriptor via service loader." );
- }
-
-}
http://git-wip-us.apache.org/repos/asf/knox/blob/ce3ca3ce/gateway-provider-identity-assertion-pseudo/src/test/java/org/apache/hadoop/gateway/identityasserter/function/UsernameFunctionProcessorTest.java
----------------------------------------------------------------------
diff --git a/gateway-provider-identity-assertion-pseudo/src/test/java/org/apache/hadoop/gateway/identityasserter/function/UsernameFunctionProcessorTest.java b/gateway-provider-identity-assertion-pseudo/src/test/java/org/apache/hadoop/gateway/identityasserter/function/UsernameFunctionProcessorTest.java
deleted file mode 100644
index dffa4b0..0000000
--- a/gateway-provider-identity-assertion-pseudo/src/test/java/org/apache/hadoop/gateway/identityasserter/function/UsernameFunctionProcessorTest.java
+++ /dev/null
@@ -1,247 +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.hadoop.gateway.identityasserter.function;
-
-import org.apache.hadoop.gateway.filter.AbstractGatewayFilter;
-import org.apache.hadoop.gateway.filter.rewrite.api.UrlRewriteServletContextListener;
-import org.apache.hadoop.gateway.filter.rewrite.api.UrlRewriteServletFilter;
-import org.apache.hadoop.gateway.filter.rewrite.spi.UrlRewriteFunctionProcessor;
-import org.apache.hadoop.gateway.security.PrimaryPrincipal;
-import org.apache.hadoop.gateway.util.urltemplate.Parser;
-import org.apache.hadoop.test.log.NoOpLogger;
-import org.apache.hadoop.test.mock.MockInteraction;
-import org.apache.hadoop.test.mock.MockServlet;
-import org.apache.http.auth.BasicUserPrincipal;
-import org.eclipse.jetty.servlet.FilterHolder;
-import org.eclipse.jetty.servlet.ServletHolder;
-import org.eclipse.jetty.testing.HttpTester;
-import org.eclipse.jetty.testing.ServletTester;
-import org.eclipse.jetty.util.ArrayQueue;
-import org.eclipse.jetty.util.log.Log;
-import org.hamcrest.core.Is;
-import org.junit.After;
-import org.junit.Test;
-
-import javax.security.auth.Subject;
-import javax.servlet.DispatcherType;
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletRequest;
-import java.io.IOException;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.nio.charset.Charset;
-import java.security.PrivilegedActionException;
-import java.security.PrivilegedExceptionAction;
-import java.util.Arrays;
-import java.util.EnumSet;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.ServiceLoader;
-
-import static org.hamcrest.MatcherAssert.assertThat;
-import static org.hamcrest.Matchers.nullValue;
-import static org.hamcrest.collection.IsIterableContainingInOrder.contains;
-import static org.junit.Assert.fail;
-
-public class UsernameFunctionProcessorTest {
-
- private ServletTester server;
- private HttpTester request;
- private HttpTester response;
- private ArrayQueue<MockInteraction> interactions;
- private MockInteraction interaction;
-
- private static URL getTestResource( String name ) {
- name = UsernameFunctionProcessorTest.class.getName().replaceAll( "\\.", "/" ) + "/" + name;
- URL url = ClassLoader.getSystemResource( name );
- return url;
- }
-
- public void setUp( String username, Map<String,String> initParams ) throws Exception {
- String descriptorUrl = getTestResource( "rewrite.xml" ).toExternalForm();
-
- Log.setLog( new NoOpLogger() );
-
- server = new ServletTester();
- server.setContextPath( "/" );
- server.getContext().addEventListener( new UrlRewriteServletContextListener() );
- server.getContext().setInitParameter(
- UrlRewriteServletContextListener.DESCRIPTOR_LOCATION_INIT_PARAM_NAME, descriptorUrl );
-
- FilterHolder setupFilter = server.addFilter( SetupFilter.class, "/*", EnumSet.of( DispatcherType.REQUEST ) );
- setupFilter.setFilter( new SetupFilter( username ) );
- FilterHolder rewriteFilter = server.addFilter( UrlRewriteServletFilter.class, "/*", EnumSet.of( DispatcherType.REQUEST ) );
- if( initParams != null ) {
- for( Map.Entry<String,String> entry : initParams.entrySet() ) {
- rewriteFilter.setInitParameter( entry.getKey(), entry.getValue() );
- }
- }
- rewriteFilter.setFilter( new UrlRewriteServletFilter() );
-
- interactions = new ArrayQueue<MockInteraction>();
-
- ServletHolder servlet = server.addServlet( MockServlet.class, "/" );
- servlet.setServlet( new MockServlet( "mock-servlet", interactions ) );
-
- server.start();
-
- interaction = new MockInteraction();
- request = new HttpTester();
- response = new HttpTester();
- }
-
- @After
- public void tearDown() throws Exception {
- if( server != null ) {
- server.stop();
- }
- }
-
- @Test
- public void testInitialize() throws Exception {
- UsernameFunctionProcessor processor = new UsernameFunctionProcessor();
- // Shouldn't fail.
- processor.initialize( null, null );
- }
-
- @Test
- public void testDestroy() throws Exception {
- UsernameFunctionProcessor processor = new UsernameFunctionProcessor();
- // Shouldn't fail.
- processor.destroy();
- }
-
- @Test
- public void testResolve() throws Exception {
- final UsernameFunctionProcessor processor = new UsernameFunctionProcessor();
- assertThat( processor.resolve( null, null ), nullValue() );
- assertThat( processor.resolve( null, Arrays.asList( "test-input" ) ), contains( "test-input" ) );
- Subject subject = new Subject();
- subject.getPrincipals().add( new PrimaryPrincipal( "test-username" ) );
- subject.setReadOnly();
- Subject.doAs( subject, new PrivilegedExceptionAction<Object>() {
- @Override
- public Object run() throws Exception {
- assertThat( processor.resolve( null, null ), contains( "test-username" ) );
- assertThat( processor.resolve( null, Arrays.asList( "test-ignored" ) ), contains( "test-username" ) );
- return null;
- }
- } );
- }
-
- @Test
- public void testServiceLoader() throws Exception {
- ServiceLoader loader = ServiceLoader.load( UrlRewriteFunctionProcessor.class );
- Iterator iterator = loader.iterator();
- while( iterator.hasNext() ) {
- Object object = iterator.next();
- if( object instanceof UsernameFunctionProcessor ) {
- return;
- }
- }
- fail( "Failed to find UsernameFunctionProcessor via service loader." );
- }
-
- @Test
- public void testRequestUrlRewriteOfUsernameViaRewriteRule() throws Exception {
- Map<String,String> initParams = new HashMap<String,String>();
- initParams.put( "request.url", "test-rule-username" );
- setUp( "test-user", initParams );
-
- String input = "<root/>";
- String expect = "<root/>";
-
- // Setup the server side request/response interaction.
- interaction.expect()
- .method( "PUT" )
- .requestUrl( "test-output-scheme://test-input-host:777/test-output-path/test-input-path" )
- .queryParam( "user.name", "test-user" )
- .queryParam( "test-query-input-name", "test-query-input-value" )
- .queryParam( "test-query-output-name", "test-query-output-value" )
- .contentType( "text/xml" )
- .characterEncoding( "UTF-8" )
- .content( expect, Charset.forName( "UTF-8" ) );
- interaction.respond()
- .status( 200 );
- interactions.add( interaction );
- request.setMethod( "PUT" );
- request.setURI( "/test-input-path?test-query-input-name=test-query-input-value" );
- request.setVersion( "HTTP/1.1" );
- request.setHeader( "Host", "test-input-host:777" );
- request.setContentType( "text/xml; charset=UTF-8" );
- request.setContent( input );
-
- response.parse( server.getResponses( request.generate() ) );
-
- // Test the results.
- assertThat( response.getStatus(), Is.is( 200 ) );
- }
-
- private static class SetupFilter implements Filter {
- private Subject subject;
-
- public SetupFilter( String userName ) {
- subject = new Subject();
- subject.getPrincipals().add( new BasicUserPrincipal( userName ) );
- }
-
- @Override
- public void init( FilterConfig filterConfig ) throws ServletException {
- }
-
- @Override
- public void doFilter( final ServletRequest request, final ServletResponse response, final FilterChain chain ) throws IOException, ServletException {
- HttpServletRequest httpRequest = ((HttpServletRequest)request);
- StringBuffer sourceUrl = httpRequest.getRequestURL();
- String queryString = httpRequest.getQueryString();
- if( queryString != null ) {
- sourceUrl.append( "?" );
- sourceUrl.append( queryString );
- }
- try {
- request.setAttribute(
- AbstractGatewayFilter.SOURCE_REQUEST_URL_ATTRIBUTE_NAME,
- Parser.parse( sourceUrl.toString() ) );
- } catch( URISyntaxException e ) {
- throw new ServletException( e );
- }
- try {
- Subject.doAs( subject, new PrivilegedExceptionAction<Void>() {
- @Override
- public Void run() throws Exception {
- chain.doFilter( request, response );
- return null;
- }
- } );
- } catch( PrivilegedActionException e ) {
- throw new ServletException( e );
- }
- }
-
- @Override
- public void destroy() {
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/knox/blob/ce3ca3ce/gateway-release/pom.xml
----------------------------------------------------------------------
diff --git a/gateway-release/pom.xml b/gateway-release/pom.xml
index adb7c52..7f84ca7 100644
--- a/gateway-release/pom.xml
+++ b/gateway-release/pom.xml
@@ -220,6 +220,14 @@
</dependency>
<dependency>
<groupId>${gateway-group}</groupId>
+ <artifactId>gateway-provider-identity-assertion-common</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>${gateway-group}</groupId>
+ <artifactId>gateway-provider-identity-assertion-concat</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>${gateway-group}</groupId>
<artifactId>gateway-provider-identity-assertion-pseudo</artifactId>
</dependency>
<dependency>
http://git-wip-us.apache.org/repos/asf/knox/blob/ce3ca3ce/gateway-spi/src/main/java/org/apache/hadoop/gateway/SpiGatewayMessages.java
----------------------------------------------------------------------
diff --git a/gateway-spi/src/main/java/org/apache/hadoop/gateway/SpiGatewayMessages.java b/gateway-spi/src/main/java/org/apache/hadoop/gateway/SpiGatewayMessages.java
index 5ff8a86..34ec105 100644
--- a/gateway-spi/src/main/java/org/apache/hadoop/gateway/SpiGatewayMessages.java
+++ b/gateway-spi/src/main/java/org/apache/hadoop/gateway/SpiGatewayMessages.java
@@ -51,4 +51,8 @@ public interface SpiGatewayMessages {
@Message( level = MessageLevel.WARN, text = "Error occurred when closing HTTP client : {0}" )
void errorClosingHttpClient(@StackTrace(level=MessageLevel.WARN) Exception e);
+
+ @Message( level = MessageLevel.WARN, text = "Skipping unencodable parameter {0}={1}, {2}: {3}" )
+ void skippingUnencodableParameter( String name, String value, String encoding, @StackTrace( level = MessageLevel.DEBUG ) Exception e );
+
}
http://git-wip-us.apache.org/repos/asf/knox/blob/ce3ca3ce/pom.xml
----------------------------------------------------------------------
diff --git a/pom.xml b/pom.xml
index 2dcffea..9bba00a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -58,6 +58,8 @@
<module>gateway-provider-security-hadoopauth</module>
<module>gateway-provider-security-shiro</module>
<module>gateway-provider-security-authz-acls</module>
+ <module>gateway-provider-identity-assertion-common</module>
+ <module>gateway-provider-identity-assertion-concat</module>
<module>gateway-provider-identity-assertion-pseudo</module>
<module>gateway-provider-jersey</module>
<module>gateway-provider-ha</module>
@@ -416,6 +418,16 @@
</dependency>
<dependency>
<groupId>${gateway-group}</groupId>
+ <artifactId>gateway-provider-identity-assertion-common</artifactId>
+ <version>${gateway-version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${gateway-group}</groupId>
+ <artifactId>gateway-provider-identity-assertion-concat</artifactId>
+ <version>${gateway-version}</version>
+ </dependency>
+ <dependency>
+ <groupId>${gateway-group}</groupId>
<artifactId>gateway-provider-identity-assertion-pseudo</artifactId>
<version>${gateway-version}</version>
</dependency>
[2/2] knox git commit: KNOX-521 - Enhance Principal Mapping to Handle
Dynamic Mappings
Posted by lm...@apache.org.
KNOX-521 - Enhance Principal Mapping to Handle Dynamic Mappings
Project: http://git-wip-us.apache.org/repos/asf/knox/repo
Commit: http://git-wip-us.apache.org/repos/asf/knox/commit/ce3ca3ce
Tree: http://git-wip-us.apache.org/repos/asf/knox/tree/ce3ca3ce
Diff: http://git-wip-us.apache.org/repos/asf/knox/diff/ce3ca3ce
Branch: refs/heads/master
Commit: ce3ca3cedfd4390e3b95ce1c3ceded7e0bef4fc8
Parents: 68416cc
Author: Larry McCay <lm...@hortonworks.com>
Authored: Sun Mar 22 11:48:59 2015 -0400
Committer: Larry McCay <lm...@hortonworks.com>
Committed: Sun Mar 22 11:48:59 2015 -0400
----------------------------------------------------------------------
.../pom.xml | 99 ++++++++
.../gateway/IdentityAsserterMessages.java | 31 +++
...ctIdentityAsserterDeploymentContributor.java | 60 +++++
.../filter/AbstractIdentityAssertionFilter.java | 191 ++++++++++++++
.../filter/CommonIdentityAssertionFilter.java | 97 ++++++++
...entityAsserterHttpServletRequestWrapper.java | 227 +++++++++++++++++
.../function/UsernameFunctionDescriptor.java | 31 +++
.../function/UsernameFunctionProcessor.java | 74 ++++++
...gateway.deploy.ProviderDeploymentContributor | 18 ++
...ter.rewrite.api.UrlRewriteFunctionDescriptor | 19 ++
...lter.rewrite.spi.UrlRewriteFunctionProcessor | 19 ++
.../CommonIdentityAssertionFilterTest.java | 130 ++++++++++
...yAssertionHttpServletRequestWrapperTest.java | 234 +++++++++++++++++
.../UsernameFunctionDescriptorTest.java | 52 ++++
.../function/UsernameFunctionProcessorTest.java | 248 +++++++++++++++++++
.../UsernameFunctionProcessorTest/rewrite.xml | 24 ++
.../pom.xml | 99 ++++++++
.../gateway/ConcatIdentityAsserterMessages.java | 31 +++
...atIdentityAsserterDeploymentContributor.java | 32 +++
.../filter/ConcatIdentityAssertionFilter.java | 65 +++++
...gateway.deploy.ProviderDeploymentContributor | 19 ++
...entityAsserterDeploymentContributorTest.java | 45 ++++
.../ConcatIdentityAssertionFilterTest.java | 78 ++++++
.../pom.xml | 2 +-
.../IdentityAsserterDeploymentContributor.java | 21 +-
.../filter/IdentityAsserterFilter.java | 66 ++---
...entityAsserterHttpServletRequestWrapper.java | 227 -----------------
.../function/UsernameFunctionDescriptor.java | 31 ---
.../function/UsernameFunctionProcessor.java | 74 ------
...ter.rewrite.api.UrlRewriteFunctionDescriptor | 19 --
...lter.rewrite.spi.UrlRewriteFunctionProcessor | 19 --
.../DefaultIdentityAssertionFilterTest.java | 173 +++++++++++++
...yAssertionHttpServletRequestWrapperTest.java | 233 -----------------
.../UsernameFunctionDescriptorTest.java | 51 ----
.../function/UsernameFunctionProcessorTest.java | 247 ------------------
gateway-release/pom.xml | 8 +
.../hadoop/gateway/SpiGatewayMessages.java | 4 +
pom.xml | 12 +
38 files changed, 2164 insertions(+), 946 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/knox/blob/ce3ca3ce/gateway-provider-identity-assertion-common/pom.xml
----------------------------------------------------------------------
diff --git a/gateway-provider-identity-assertion-common/pom.xml b/gateway-provider-identity-assertion-common/pom.xml
new file mode 100644
index 0000000..86b7ddb
--- /dev/null
+++ b/gateway-provider-identity-assertion-common/pom.xml
@@ -0,0 +1,99 @@
+<?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.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.knox</groupId>
+ <artifactId>gateway</artifactId>
+ <version>0.6.0-SNAPSHOT</version>
+ </parent>
+ <artifactId>gateway-provider-identity-assertion-common</artifactId>
+
+ <name>gateway-provider-identity-assertion-common</name>
+ <description>An extension to the gateway that provides an easy integration point for asserting identity to Hadoop clusters using using some custom mapping facility.</description>
+
+ <licenses>
+ <license>
+ <name>The Apache Software License, Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+ <distribution>repo</distribution>
+ </license>
+ </licenses>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>${gateway-group}</groupId>
+ <artifactId>gateway-spi</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>${gateway-group}</groupId>
+ <artifactId>gateway-provider-rewrite</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>${gateway-group}</groupId>
+ <artifactId>gateway-test-utils</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>test-jetty-servlet</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-library</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.xmlmatchers</groupId>
+ <artifactId>xml-matchers</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ </dependencies>
+</project>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/knox/blob/ce3ca3ce/gateway-provider-identity-assertion-common/src/main/java/org/apache/hadoop/gateway/IdentityAsserterMessages.java
----------------------------------------------------------------------
diff --git a/gateway-provider-identity-assertion-common/src/main/java/org/apache/hadoop/gateway/IdentityAsserterMessages.java b/gateway-provider-identity-assertion-common/src/main/java/org/apache/hadoop/gateway/IdentityAsserterMessages.java
new file mode 100644
index 0000000..c4ada6b
--- /dev/null
+++ b/gateway-provider-identity-assertion-common/src/main/java/org/apache/hadoop/gateway/IdentityAsserterMessages.java
@@ -0,0 +1,31 @@
+/**
+ * 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;
+
+import org.apache.hadoop.gateway.i18n.messages.Message;
+import org.apache.hadoop.gateway.i18n.messages.MessageLevel;
+import org.apache.hadoop.gateway.i18n.messages.Messages;
+import org.apache.hadoop.gateway.i18n.messages.StackTrace;
+
+@Messages(logger="org.apache.hadoop.gateway")
+public interface IdentityAsserterMessages {
+
+ @Message( level = MessageLevel.WARN, text = "Skipping unencodable parameter {0}={1}, {2}: {3}" )
+ void skippingUnencodableParameter( String name, String value, String encoding, @StackTrace( level = MessageLevel.DEBUG ) Exception e );
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/ce3ca3ce/gateway-provider-identity-assertion-common/src/main/java/org/apache/hadoop/gateway/identityasserter/common/filter/AbstractIdentityAsserterDeploymentContributor.java
----------------------------------------------------------------------
diff --git a/gateway-provider-identity-assertion-common/src/main/java/org/apache/hadoop/gateway/identityasserter/common/filter/AbstractIdentityAsserterDeploymentContributor.java b/gateway-provider-identity-assertion-common/src/main/java/org/apache/hadoop/gateway/identityasserter/common/filter/AbstractIdentityAsserterDeploymentContributor.java
new file mode 100644
index 0000000..15ae296
--- /dev/null
+++ b/gateway-provider-identity-assertion-common/src/main/java/org/apache/hadoop/gateway/identityasserter/common/filter/AbstractIdentityAsserterDeploymentContributor.java
@@ -0,0 +1,60 @@
+/**
+ * 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.identityasserter.common.filter;
+
+import org.apache.hadoop.gateway.deploy.DeploymentContext;
+import org.apache.hadoop.gateway.deploy.ProviderDeploymentContributorBase;
+import org.apache.hadoop.gateway.descriptor.FilterParamDescriptor;
+import org.apache.hadoop.gateway.descriptor.ResourceDescriptor;
+import org.apache.hadoop.gateway.topology.Provider;
+import org.apache.hadoop.gateway.topology.Service;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+public abstract class AbstractIdentityAsserterDeploymentContributor extends ProviderDeploymentContributorBase {
+
+ @Override
+ public String getRole() {
+ return "identity-assertion";
+ }
+
+ @Override
+ public void contributeFilter( DeploymentContext context, Provider provider, Service service,
+ ResourceDescriptor resource, List<FilterParamDescriptor> params ) {
+ params = buildFilterInitParms(provider, resource, params);
+ resource.addFilter().name(getName()).role(getRole()).impl(getFilterClassname()).params(params);
+ }
+
+ public List<FilterParamDescriptor> buildFilterInitParms(Provider provider,
+ ResourceDescriptor resource, List<FilterParamDescriptor> params) {
+ // blindly add all the provider params as filter init params
+ if (params == null) {
+ params = new ArrayList<FilterParamDescriptor>();
+ }
+ Map<String, String> providerParams = provider.getParams();
+ for(Entry<String, String> entry : providerParams.entrySet()) {
+ params.add( resource.createFilterParam().name(entry.getKey().toLowerCase()).value(entry.getValue()));
+ }
+ return params;
+ }
+
+ protected abstract String getFilterClassname();
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/ce3ca3ce/gateway-provider-identity-assertion-common/src/main/java/org/apache/hadoop/gateway/identityasserter/common/filter/AbstractIdentityAssertionFilter.java
----------------------------------------------------------------------
diff --git a/gateway-provider-identity-assertion-common/src/main/java/org/apache/hadoop/gateway/identityasserter/common/filter/AbstractIdentityAssertionFilter.java b/gateway-provider-identity-assertion-common/src/main/java/org/apache/hadoop/gateway/identityasserter/common/filter/AbstractIdentityAssertionFilter.java
new file mode 100644
index 0000000..cabefd2
--- /dev/null
+++ b/gateway-provider-identity-assertion-common/src/main/java/org/apache/hadoop/gateway/identityasserter/common/filter/AbstractIdentityAssertionFilter.java
@@ -0,0 +1,191 @@
+/**
+ * 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.identityasserter.common.filter;
+
+import java.io.IOException;
+import java.security.AccessController;
+import java.security.Principal;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.Arrays;
+import java.util.Set;
+
+import javax.security.auth.Subject;
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+
+import org.apache.hadoop.gateway.audit.api.Action;
+import org.apache.hadoop.gateway.audit.api.ActionOutcome;
+import org.apache.hadoop.gateway.audit.api.AuditService;
+import org.apache.hadoop.gateway.audit.api.AuditServiceFactory;
+import org.apache.hadoop.gateway.audit.api.Auditor;
+import org.apache.hadoop.gateway.audit.api.ResourceType;
+import org.apache.hadoop.gateway.audit.log4j.audit.AuditConstants;
+import org.apache.hadoop.gateway.filter.security.AbstractIdentityAssertionBase;
+import org.apache.hadoop.gateway.i18n.GatewaySpiResources;
+import org.apache.hadoop.gateway.i18n.resources.ResourcesFactory;
+import org.apache.hadoop.gateway.security.GroupPrincipal;
+import org.apache.hadoop.gateway.security.ImpersonatedPrincipal;
+import org.apache.hadoop.gateway.security.PrimaryPrincipal;
+
+/**
+ *
+ */
+public abstract class AbstractIdentityAssertionFilter extends
+ AbstractIdentityAssertionBase implements Filter {
+
+ private static final GatewaySpiResources RES = ResourcesFactory.get( GatewaySpiResources.class );
+ private static AuditService auditService = AuditServiceFactory.getAuditService();
+ private static Auditor auditor = auditService.getAuditor(
+ AuditConstants.DEFAULT_AUDITOR_NAME, AuditConstants.KNOX_SERVICE_NAME,
+ AuditConstants.KNOX_COMPONENT_NAME );
+
+ /**
+ *
+ */
+ public AbstractIdentityAssertionFilter() {
+ super();
+ }
+
+ /**
+ * @param mappedPrincipalName
+ * @param subject
+ * @return
+ */
+ public abstract String[] mapGroupPrincipals(String mappedPrincipalName, Subject subject);
+
+ /**
+ * @param principalName
+ * @return
+ */
+ public abstract String mapUserPrincipal(String principalName);
+
+ /**
+ * @param wrapper
+ * @param response
+ * @param chain
+ * @param mappedPrincipalName
+ * @param groups
+ */
+ protected void continueChainAsPrincipal(HttpServletRequestWrapper request, ServletResponse response,
+ FilterChain chain, String mappedPrincipalName, String[] groups) throws IOException,
+ ServletException {
+ Subject subject = null;
+ Principal impersonationPrincipal = null;
+ Principal primaryPrincipal = null;
+
+ // get the current subject and determine whether we need another doAs with
+ // an impersonatedPrincipal and/or mapped group principals
+ boolean impersonationNeeded = false;
+ boolean groupsMapped = false;
+
+ // look up the current Java Subject and assosciated group principals
+ Subject currentSubject = Subject.getSubject(AccessController.getContext());
+ Set<?> currentGroups = currentSubject.getPrincipals(GroupPrincipal.class);
+
+ primaryPrincipal = (PrimaryPrincipal) currentSubject.getPrincipals(PrimaryPrincipal.class).toArray()[0];
+ if (primaryPrincipal != null) {
+ if (!primaryPrincipal.getName().equals(mappedPrincipalName)) {
+ impersonationNeeded = true;
+ auditService.getContext().setProxyUsername( mappedPrincipalName );
+ auditor.audit( Action.IDENTITY_MAPPING, primaryPrincipal.getName(), ResourceType.PRINCIPAL, ActionOutcome.SUCCESS );
+ }
+ }
+ else {
+ // something is amiss - authentication/federation providers should have run
+ // before identity assertion and should have ensured that the appropriate
+ // principals were added to the current subject
+ // TODO: log as appropriate
+ primaryPrincipal = new PrimaryPrincipal(((HttpServletRequest) request).getUserPrincipal().getName());
+ }
+
+ groupsMapped = groups != null || !currentGroups.isEmpty();
+
+ if (impersonationNeeded || groupsMapped) {
+ // gonna need a new subject and doAs
+ subject = new Subject();
+ Set<Principal> principals = subject.getPrincipals();
+ principals.add(primaryPrincipal);
+
+ // map group principals from current Subject into newly created Subject
+ for (Object obj : currentGroups) {
+ principals.add((Principal)obj);
+ }
+
+ if (impersonationNeeded) {
+ impersonationPrincipal = new ImpersonatedPrincipal(mappedPrincipalName);
+ subject.getPrincipals().add(impersonationPrincipal);
+ }
+ if (groupsMapped) {
+ addMappedGroupsToSubject(mappedPrincipalName, groups, subject);
+ addMappedGroupsToSubject("*", groups, subject);
+ }
+ doAs(request, response, chain, subject);
+ }
+ else {
+ doFilterInternal(request, response, chain);
+ }
+ }
+
+ private void doAs(final ServletRequest request, final ServletResponse response, final FilterChain chain, Subject subject)
+ throws IOException, ServletException {
+ try {
+ Subject.doAs(
+ subject,
+ new PrivilegedExceptionAction<Object>() {
+ public Object run() throws Exception {
+ doFilterInternal(request, response, chain);
+ return null;
+ }
+ });
+ }
+ catch (PrivilegedActionException e) {
+ Throwable t = e.getCause();
+ if (t instanceof IOException) {
+ throw (IOException) t;
+ }
+ else if (t instanceof ServletException) {
+ throw (ServletException) t;
+ }
+ else {
+ throw new ServletException(t);
+ }
+ }
+ }
+
+ private void addMappedGroupsToSubject(String mappedPrincipalName, String[] groups, Subject subject) {
+ if (groups != null) {
+ auditor.audit( Action.IDENTITY_MAPPING, mappedPrincipalName, ResourceType.PRINCIPAL,
+ ActionOutcome.SUCCESS, RES.groupsList( Arrays.toString( groups ) ) );
+
+ for (int i = 0; i < groups.length; i++) {
+ subject.getPrincipals().add(new GroupPrincipal(groups[i]));
+ }
+ }
+ }
+
+ private void doFilterInternal(ServletRequest request, ServletResponse response, FilterChain chain)
+ throws IOException, ServletException {
+ chain.doFilter(request, response);
+ }
+}
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/knox/blob/ce3ca3ce/gateway-provider-identity-assertion-common/src/main/java/org/apache/hadoop/gateway/identityasserter/common/filter/CommonIdentityAssertionFilter.java
----------------------------------------------------------------------
diff --git a/gateway-provider-identity-assertion-common/src/main/java/org/apache/hadoop/gateway/identityasserter/common/filter/CommonIdentityAssertionFilter.java b/gateway-provider-identity-assertion-common/src/main/java/org/apache/hadoop/gateway/identityasserter/common/filter/CommonIdentityAssertionFilter.java
new file mode 100644
index 0000000..1a20c39
--- /dev/null
+++ b/gateway-provider-identity-assertion-common/src/main/java/org/apache/hadoop/gateway/identityasserter/common/filter/CommonIdentityAssertionFilter.java
@@ -0,0 +1,97 @@
+/**
+ * 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.identityasserter.common.filter;
+
+import javax.security.auth.Subject;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+
+import org.apache.hadoop.gateway.identityasserter.common.filter.AbstractIdentityAssertionFilter;
+
+import java.io.IOException;
+import java.security.AccessController;
+
+public class CommonIdentityAssertionFilter extends AbstractIdentityAssertionFilter {
+ /* (non-Javadoc)
+ * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
+ */
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException {
+ }
+
+ /* (non-Javadoc)
+ * @see javax.servlet.Filter#destroy()
+ */
+ @Override
+ public void destroy() {
+ }
+
+ /**
+ * Obtain the standard javax.security.auth.Subject, retrieve the caller principal, map
+ * to the identity to be asserted as appropriate and create the provider specific
+ * assertion token. Add the assertion token to the request.
+ */
+ public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
+ throws IOException, ServletException {
+ Subject subject = Subject.getSubject(AccessController.getContext());
+
+ String principalName = getPrincipalName(subject);
+
+ String mappedPrincipalName = mapUserPrincipal(principalName);
+ String[] groups = mapGroupPrincipals(mappedPrincipalName, subject);
+
+ HttpServletRequestWrapper wrapper = wrapHttpServletRequest(
+ request, mappedPrincipalName);
+
+ continueChainAsPrincipal(wrapper, response, chain, mappedPrincipalName, groups);
+ }
+
+ public HttpServletRequestWrapper wrapHttpServletRequest(
+ ServletRequest request, String mappedPrincipalName) {
+ // wrap the request so that the proper principal is returned
+ // from request methods
+ IdentityAsserterHttpServletRequestWrapper wrapper =
+ new IdentityAsserterHttpServletRequestWrapper(
+ (HttpServletRequest)request,
+ mappedPrincipalName);
+ return wrapper;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.hadoop.gateway.identityasserter.common.filter.AbstractIdentityAssertionFilter#mapGroupPrincipals(java.lang.String, javax.security.auth.Subject)
+ */
+ @Override
+ public String[] mapGroupPrincipals(String mappedPrincipalName, Subject subject) {
+ // NOP
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.hadoop.gateway.identityasserter.common.filter.AbstractIdentityAssertionFilter#mapUserPrincipal(java.lang.String)
+ */
+ @Override
+ public String mapUserPrincipal(String principalName) {
+ // NOP
+ return principalName;
+ }
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/ce3ca3ce/gateway-provider-identity-assertion-common/src/main/java/org/apache/hadoop/gateway/identityasserter/common/filter/IdentityAsserterHttpServletRequestWrapper.java
----------------------------------------------------------------------
diff --git a/gateway-provider-identity-assertion-common/src/main/java/org/apache/hadoop/gateway/identityasserter/common/filter/IdentityAsserterHttpServletRequestWrapper.java b/gateway-provider-identity-assertion-common/src/main/java/org/apache/hadoop/gateway/identityasserter/common/filter/IdentityAsserterHttpServletRequestWrapper.java
new file mode 100644
index 0000000..63a1e4d
--- /dev/null
+++ b/gateway-provider-identity-assertion-common/src/main/java/org/apache/hadoop/gateway/identityasserter/common/filter/IdentityAsserterHttpServletRequestWrapper.java
@@ -0,0 +1,227 @@
+/**
+ * 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.identityasserter.common.filter;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.hadoop.gateway.SpiGatewayMessages;
+import org.apache.hadoop.gateway.config.GatewayConfig;
+import org.apache.hadoop.gateway.i18n.messages.MessagesFactory;
+
+import javax.servlet.ServletInputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.URLEncoder;
+import java.nio.charset.Charset;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+
+public class IdentityAsserterHttpServletRequestWrapper extends HttpServletRequestWrapper {
+
+ private static SpiGatewayMessages log = MessagesFactory.get( SpiGatewayMessages.class );
+
+ private static final String PRINCIPAL_PARAM = "user.name";
+ private static final String DOAS_PRINCIPAL_PARAM = "doAs";
+
+ String username = null;
+
+ public IdentityAsserterHttpServletRequestWrapper( HttpServletRequest request, String principal ) {
+ super(request);
+ username = principal;
+ }
+
+ @Override
+ public String getParameter(String name) {
+ if (name.equals(PRINCIPAL_PARAM)) {
+ return username;
+ }
+ return super.getParameter(name);
+ }
+
+ @SuppressWarnings("rawtypes")
+ @Override
+ public Map getParameterMap() {
+ return getParams();
+ }
+
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ @Override
+ public Enumeration getParameterNames() {
+ Map<String, String[]> params = getParams();
+ Enumeration<String> e = Collections.enumeration((Collection<String>) params);
+
+ return e;
+ }
+
+ @Override
+ public String[] getParameterValues(String name) {
+ Map<String, String[]> params = getParams();
+
+ return params.get(name);
+ }
+
+ private Map<String, String[]> getParams( String qString ) {
+ Map<String, String[]> params = null;
+ if (getMethod().equals("GET")) {
+ if (qString != null && qString.length() > 0) {
+ params = parseQueryString(qString);
+ }
+ else {
+ params = new HashMap<String, String[]>();
+ }
+ }
+ else {
+ if (qString == null || qString.length() == 0) {
+ return null;
+ }
+ else {
+ params = parseQueryString(qString);
+ }
+ }
+ return params;
+ }
+
+ private Map<String, String[]> getParams() {
+ return getParams( super.getQueryString() );
+ }
+
+ @Override
+ public String getQueryString() {
+ String q = null;
+ Map<String, String[]> params = getParams();
+
+ if (params == null) {
+ params = new HashMap<String, String[]>();
+ }
+
+ ArrayList<String> al = new ArrayList<String>();
+ al.add(username);
+ String[] a = { "" };
+
+ if ("true".equals(System.getProperty(GatewayConfig.HADOOP_KERBEROS_SECURED))) {
+ params.put(DOAS_PRINCIPAL_PARAM, al.toArray(a));
+ params.remove(PRINCIPAL_PARAM);
+ } else {
+ params.put(PRINCIPAL_PARAM, al.toArray(a));
+ }
+
+ String encoding = getCharacterEncoding();
+ if (encoding == null) {
+ encoding = Charset.defaultCharset().name();
+ }
+ q = urlEncode(params, encoding);
+ return q;
+ }
+
+ @Override
+ public int getContentLength() {
+ int len;
+ String contentType = getContentType();
+ // If the content type is a form we might rewrite the body so default it to -1.
+ if( contentType != null && contentType.startsWith( "application/x-www-form-urlencoded" ) ) {
+ len = -1;
+ } else {
+ len = super.getContentLength();
+ }
+ return len;
+ }
+
+ @Override
+ public ServletInputStream getInputStream() throws java.io.IOException {
+ String contentType = getContentType();
+ if( contentType != null && contentType.startsWith( "application/x-www-form-urlencoded" ) ) {
+ String encoding = getCharacterEncoding();
+ if( encoding == null ) {
+ encoding = Charset.defaultCharset().name();
+ }
+ String body = IOUtils.toString( super.getInputStream(), encoding );
+ Map<String, String[]> params = getParams( body );
+ body = urlEncode( params, encoding );
+ // ASCII is OK here because the urlEncode about should have already escaped
+ return new ServletInputStreamWrapper( new ByteArrayInputStream( body.getBytes( "US-ASCII" ) ) );
+ } else {
+ return super.getInputStream();
+ }
+ }
+
+ static String urlEncode( String string, String encoding ) {
+ try {
+ return URLEncoder.encode( string, encoding );
+ } catch (UnsupportedEncodingException e) {
+ throw new UnsupportedOperationException(e);
+ }
+ }
+
+ public static String urlEncode( Map<String, String[]> map, String encoding ) {
+ StringBuilder sb = new StringBuilder();
+ for( Map.Entry<String,String[]> entry : map.entrySet() ) {
+ String name = entry.getKey();
+ if( name != null && name.length() > 0 ) {
+ String[] values = entry.getValue();
+ if( values == null || values.length == 0 ) {
+ sb.append( entry.getKey() );
+ } else {
+ for( int i = 0; i < values.length; i++ ) {
+ String value = values[ i ];
+ if( value != null ) {
+ if( sb.length() > 0 ) {
+ sb.append( "&" );
+ }
+ try {
+ sb.append( urlEncode( name, encoding ) );
+ sb.append( "=" );
+ sb.append( urlEncode( value, encoding ) );
+ } catch( IllegalArgumentException e ) {
+ log.skippingUnencodableParameter( name, value, encoding, e );
+ }
+ }
+ }
+ }
+ }
+ }
+ return sb.toString();
+ }
+
+ @SuppressWarnings({ "deprecation", "unchecked" })
+ private static Map<String,String[]> parseQueryString( String queryString ) {
+ return javax.servlet.http.HttpUtils.parseQueryString( queryString );
+ }
+
+ private class ServletInputStreamWrapper extends ServletInputStream {
+
+ private InputStream stream;
+
+ private ServletInputStreamWrapper( InputStream stream ) {
+ this.stream = stream;
+ }
+
+ @Override
+ public int read() throws IOException {
+ return stream.read();
+ }
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/ce3ca3ce/gateway-provider-identity-assertion-common/src/main/java/org/apache/hadoop/gateway/identityasserter/common/function/UsernameFunctionDescriptor.java
----------------------------------------------------------------------
diff --git a/gateway-provider-identity-assertion-common/src/main/java/org/apache/hadoop/gateway/identityasserter/common/function/UsernameFunctionDescriptor.java b/gateway-provider-identity-assertion-common/src/main/java/org/apache/hadoop/gateway/identityasserter/common/function/UsernameFunctionDescriptor.java
new file mode 100644
index 0000000..f997de8
--- /dev/null
+++ b/gateway-provider-identity-assertion-common/src/main/java/org/apache/hadoop/gateway/identityasserter/common/function/UsernameFunctionDescriptor.java
@@ -0,0 +1,31 @@
+/**
+ * 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.identityasserter.common.function;
+
+import org.apache.hadoop.gateway.filter.rewrite.api.UrlRewriteFunctionDescriptor;
+
+public class UsernameFunctionDescriptor implements UrlRewriteFunctionDescriptor<UsernameFunctionDescriptor> {
+
+ public static final String FUNCTION_NAME = "username";
+
+ @Override
+ public String name() {
+ return FUNCTION_NAME;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/ce3ca3ce/gateway-provider-identity-assertion-common/src/main/java/org/apache/hadoop/gateway/identityasserter/common/function/UsernameFunctionProcessor.java
----------------------------------------------------------------------
diff --git a/gateway-provider-identity-assertion-common/src/main/java/org/apache/hadoop/gateway/identityasserter/common/function/UsernameFunctionProcessor.java b/gateway-provider-identity-assertion-common/src/main/java/org/apache/hadoop/gateway/identityasserter/common/function/UsernameFunctionProcessor.java
new file mode 100644
index 0000000..cc5d39d
--- /dev/null
+++ b/gateway-provider-identity-assertion-common/src/main/java/org/apache/hadoop/gateway/identityasserter/common/function/UsernameFunctionProcessor.java
@@ -0,0 +1,74 @@
+/**
+ * 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.identityasserter.common.function;
+
+import org.apache.hadoop.gateway.filter.rewrite.api.UrlRewriteEnvironment;
+import org.apache.hadoop.gateway.filter.rewrite.spi.UrlRewriteContext;
+import org.apache.hadoop.gateway.filter.rewrite.spi.UrlRewriteFunctionProcessor;
+import org.apache.hadoop.gateway.filter.security.AbstractIdentityAssertionBase;
+import org.apache.hadoop.gateway.i18n.GatewaySpiMessages;
+import org.apache.hadoop.gateway.i18n.messages.MessagesFactory;
+import org.apache.hadoop.gateway.security.SubjectUtils;
+
+import javax.security.auth.Subject;
+import java.security.AccessController;
+import java.util.ArrayList;
+import java.util.List;
+
+public class UsernameFunctionProcessor
+ implements UrlRewriteFunctionProcessor<UsernameFunctionDescriptor> {
+
+ private static final GatewaySpiMessages LOG = MessagesFactory.get( GatewaySpiMessages.class );
+// private PrincipalMapper mapper = null;
+
+ @Override
+ public String name() {
+ return UsernameFunctionDescriptor.FUNCTION_NAME;
+ }
+
+ @Override
+ public void initialize( UrlRewriteEnvironment environment, UsernameFunctionDescriptor descriptor ) throws Exception {
+// if( environment != null ) {
+// GatewayServices services = environment.getAttribute( GatewayServices.GATEWAY_SERVICES_ATTRIBUTE );
+// if( services != null ) {
+// mapper = (PrincipalMapper)services.getService( "PrincipalMapperService" /*GatewayServices.PRINCIPAL_MAPPER_SERVICE*/ );
+// }
+// }
+ }
+
+ @Override
+ public void destroy() throws Exception {
+ }
+
+ @Override
+ public List<String> resolve( UrlRewriteContext context, List<String> parameters ) throws Exception {
+ List<String> results = null;
+ Subject subject = SubjectUtils.getCurrentSubject( );
+ if( subject != null ) {
+ results = new ArrayList<String>( 1 );
+ String username = SubjectUtils.getEffectivePrincipalName(subject);
+ results.add( username );
+ } else if( parameters != null && parameters.size() > 0 ) {
+ results = new ArrayList<String>( 1 );
+ results.add( parameters.get( 0 ) );
+ }
+ return results;
+ }
+
+}
+
http://git-wip-us.apache.org/repos/asf/knox/blob/ce3ca3ce/gateway-provider-identity-assertion-common/src/main/resources/META-INF/services/org.apache.hadoop.gateway.deploy.ProviderDeploymentContributor
----------------------------------------------------------------------
diff --git a/gateway-provider-identity-assertion-common/src/main/resources/META-INF/services/org.apache.hadoop.gateway.deploy.ProviderDeploymentContributor b/gateway-provider-identity-assertion-common/src/main/resources/META-INF/services/org.apache.hadoop.gateway.deploy.ProviderDeploymentContributor
new file mode 100644
index 0000000..2545fb6
--- /dev/null
+++ b/gateway-provider-identity-assertion-common/src/main/resources/META-INF/services/org.apache.hadoop.gateway.deploy.ProviderDeploymentContributor
@@ -0,0 +1,18 @@
+##########################################################################
+# 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.
+##########################################################################
+
http://git-wip-us.apache.org/repos/asf/knox/blob/ce3ca3ce/gateway-provider-identity-assertion-common/src/main/resources/META-INF/services/org.apache.hadoop.gateway.filter.rewrite.api.UrlRewriteFunctionDescriptor
----------------------------------------------------------------------
diff --git a/gateway-provider-identity-assertion-common/src/main/resources/META-INF/services/org.apache.hadoop.gateway.filter.rewrite.api.UrlRewriteFunctionDescriptor b/gateway-provider-identity-assertion-common/src/main/resources/META-INF/services/org.apache.hadoop.gateway.filter.rewrite.api.UrlRewriteFunctionDescriptor
new file mode 100644
index 0000000..9671caf
--- /dev/null
+++ b/gateway-provider-identity-assertion-common/src/main/resources/META-INF/services/org.apache.hadoop.gateway.filter.rewrite.api.UrlRewriteFunctionDescriptor
@@ -0,0 +1,19 @@
+##########################################################################
+# 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.
+##########################################################################
+
+org.apache.hadoop.gateway.identityasserter.common.function.UsernameFunctionDescriptor
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/knox/blob/ce3ca3ce/gateway-provider-identity-assertion-common/src/main/resources/META-INF/services/org.apache.hadoop.gateway.filter.rewrite.spi.UrlRewriteFunctionProcessor
----------------------------------------------------------------------
diff --git a/gateway-provider-identity-assertion-common/src/main/resources/META-INF/services/org.apache.hadoop.gateway.filter.rewrite.spi.UrlRewriteFunctionProcessor b/gateway-provider-identity-assertion-common/src/main/resources/META-INF/services/org.apache.hadoop.gateway.filter.rewrite.spi.UrlRewriteFunctionProcessor
new file mode 100644
index 0000000..5038d11
--- /dev/null
+++ b/gateway-provider-identity-assertion-common/src/main/resources/META-INF/services/org.apache.hadoop.gateway.filter.rewrite.spi.UrlRewriteFunctionProcessor
@@ -0,0 +1,19 @@
+##########################################################################
+# 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.
+##########################################################################
+
+org.apache.hadoop.gateway.identityasserter.common.function.UsernameFunctionProcessor
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/knox/blob/ce3ca3ce/gateway-provider-identity-assertion-common/src/test/java/org/apache/hadoop/gateway/identityasserter/filter/CommonIdentityAssertionFilterTest.java
----------------------------------------------------------------------
diff --git a/gateway-provider-identity-assertion-common/src/test/java/org/apache/hadoop/gateway/identityasserter/filter/CommonIdentityAssertionFilterTest.java b/gateway-provider-identity-assertion-common/src/test/java/org/apache/hadoop/gateway/identityasserter/filter/CommonIdentityAssertionFilterTest.java
new file mode 100644
index 0000000..4d53dbb
--- /dev/null
+++ b/gateway-provider-identity-assertion-common/src/test/java/org/apache/hadoop/gateway/identityasserter/filter/CommonIdentityAssertionFilterTest.java
@@ -0,0 +1,130 @@
+/**
+ * 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.identityasserter.filter;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+
+import javax.security.auth.Subject;
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.hadoop.gateway.identityasserter.common.filter.CommonIdentityAssertionFilter;
+import org.apache.hadoop.gateway.security.GroupPrincipal;
+import org.apache.hadoop.gateway.security.PrimaryPrincipal;
+import org.easymock.EasyMock;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author larry
+ *
+ */
+public class CommonIdentityAssertionFilterTest {
+
+ private String username = null;
+ private String[] mappedGroups = null;
+ private Filter filter = null;
+
+ @Before
+ public void setup() {
+ filter = new CommonIdentityAssertionFilter() {
+ @Override
+ public String mapUserPrincipal(String principalName) {
+ username = principalName.toUpperCase();
+ return principalName;
+ }
+
+ @Override
+ public String[] mapGroupPrincipals(String principalName, Subject subject) {
+ String[] groups = new String[2];
+ int i = 0;
+ for(GroupPrincipal p : subject.getPrincipals(GroupPrincipal.class)) {
+ groups[i] = p.getName().toUpperCase();
+ i++;
+ }
+ mappedGroups = groups;
+ return groups;
+ }
+ };
+ }
+
+ @Test
+ public void testSimpleFilter() throws ServletException, IOException,
+ URISyntaxException {
+
+ FilterConfig config = EasyMock.createNiceMock( FilterConfig.class );
+ EasyMock.replay( config );
+
+ final HttpServletRequest request = EasyMock.createNiceMock( HttpServletRequest.class );
+ EasyMock.replay( request );
+
+ final HttpServletResponse response = EasyMock.createNiceMock( HttpServletResponse.class );
+ EasyMock.replay( response );
+
+ final FilterChain chain = new FilterChain() {
+ @Override
+ public void doFilter(ServletRequest request, ServletResponse response)
+ throws IOException, ServletException {
+ }
+ };
+
+ Subject subject = new Subject();
+ subject.getPrincipals().add(new PrimaryPrincipal("larry"));
+ subject.getPrincipals().add(new GroupPrincipal("users"));
+ subject.getPrincipals().add(new GroupPrincipal("admin"));
+ try {
+ Subject.doAs(
+ subject,
+ new PrivilegedExceptionAction<Object>() {
+ public Object run() throws Exception {
+ filter.doFilter(request, response, chain);
+ return null;
+ }
+ });
+ }
+ catch (PrivilegedActionException e) {
+ Throwable t = e.getCause();
+ if (t instanceof IOException) {
+ throw (IOException) t;
+ }
+ else if (t instanceof ServletException) {
+ throw (ServletException) t;
+ }
+ else {
+ throw new ServletException(t);
+ }
+ }
+ assertEquals("LARRY", username);
+ assertEquals(mappedGroups.length, 2);
+ assertTrue(mappedGroups[0].equals("USERS") || mappedGroups[0].equals("ADMIN"));
+ assertTrue(mappedGroups[1], mappedGroups[1].equals("USERS") || mappedGroups[1].equals("ADMIN"));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/ce3ca3ce/gateway-provider-identity-assertion-common/src/test/java/org/apache/hadoop/gateway/identityasserter/filter/IdentityAssertionHttpServletRequestWrapperTest.java
----------------------------------------------------------------------
diff --git a/gateway-provider-identity-assertion-common/src/test/java/org/apache/hadoop/gateway/identityasserter/filter/IdentityAssertionHttpServletRequestWrapperTest.java b/gateway-provider-identity-assertion-common/src/test/java/org/apache/hadoop/gateway/identityasserter/filter/IdentityAssertionHttpServletRequestWrapperTest.java
new file mode 100644
index 0000000..8bb0420
--- /dev/null
+++ b/gateway-provider-identity-assertion-common/src/test/java/org/apache/hadoop/gateway/identityasserter/filter/IdentityAssertionHttpServletRequestWrapperTest.java
@@ -0,0 +1,234 @@
+/**
+ * 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.identityasserter.filter;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.hadoop.gateway.identityasserter.common.filter.IdentityAsserterHttpServletRequestWrapper;
+import org.apache.hadoop.test.category.FastTests;
+import org.apache.hadoop.test.category.UnitTests;
+import org.apache.hadoop.test.mock.MockHttpServletRequest;
+import org.apache.hadoop.test.mock.MockServletInputStream;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.HashMap;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.not;
+
+@Category( { UnitTests.class, FastTests.class } )
+public class IdentityAssertionHttpServletRequestWrapperTest {
+
+ @Test
+ public void testInsertUserNameInPostMethod() throws IOException {
+ String inputBody = "jar=%2Ftmp%2FGatewayWebHdfsFuncTest%2FtestJavaMapReduceViaWebHCat%2Fhadoop-examples.jar&class=org.apache.org.apache.hadoop.examples.WordCount&arg=%2Ftmp%2FGatewayWebHdfsFuncTest%2FtestJavaMapReduceViaTempleton%2Finput&arg=%2Ftmp%2FGatewayWebHdfsFuncTest%2FtestJavaMapReduceViaTempleton%2Foutput";
+
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.setInputStream( new MockServletInputStream( new ByteArrayInputStream( inputBody.getBytes( "UTF-8" ) ) ) );
+ request.setCharacterEncoding( "UTF-8" );
+ request.setContentType( "application/x-www-form-urlencoded" );
+ request.setMethod("POST");
+
+ IdentityAsserterHttpServletRequestWrapper wrapper
+ = new IdentityAsserterHttpServletRequestWrapper( request, "output-user" );
+
+ String outputBody = IOUtils.toString( wrapper.getInputStream(), wrapper.getCharacterEncoding() );
+ String output = wrapper.getQueryString();
+ assertThat( output, containsString( "user.name=output-user" ) );
+ }
+
+ @Test
+ public void testInsertUserNameInPostMethodWithoutEncoding() throws IOException {
+ String inputBody = "jar=%2Ftmp%2FGatewayWebHdfsFuncTest%2FtestJavaMapReduceViaWebHCat%2Fhadoop-examples.jar&class=org.apache.org.apache.hadoop.examples.WordCount&arg=%2Ftmp%2FGatewayWebHdfsFuncTest%2FtestJavaMapReduceViaTempleton%2Finput&arg=%2Ftmp%2FGatewayWebHdfsFuncTest%2FtestJavaMapReduceViaTempleton%2Foutput";
+
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.setInputStream( new MockServletInputStream( new ByteArrayInputStream( inputBody.getBytes( "UTF-8" ) ) ) );
+ request.setContentType( "application/x-www-form-urlencoded" );
+ request.setMethod("POST");
+
+ IdentityAsserterHttpServletRequestWrapper wrapper
+ = new IdentityAsserterHttpServletRequestWrapper( request, "output-user" );
+
+ String outputBody = IOUtils.toString( wrapper.getInputStream(), wrapper.getCharacterEncoding() );
+ String output = wrapper.getQueryString();
+ assertThat( output, containsString( "user.name=output-user" ) );
+ }
+
+ @Test
+ public void testInsertUserNameInPostMethodWithIso88591Encoding() throws IOException {
+ String inputBody = "jar=%2Ftmp%2FGatewayWebHdfsFuncTest%2FtestJavaMapReduceViaWebHCat%2Fhadoop-examples.jar&class=org.apache.org.apache.hadoop.examples.WordCount&arg=%2Ftmp%2FGatewayWebHdfsFuncTest%2FtestJavaMapReduceViaTempleton%2Finput&arg=%2Ftmp%2FGatewayWebHdfsFuncTest%2FtestJavaMapReduceViaTempleton%2Foutput";
+
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.setInputStream( new MockServletInputStream( new ByteArrayInputStream( inputBody.getBytes( "UTF-8" ) ) ) );
+ request.setContentType( "application/x-www-form-urlencoded" );
+ request.setCharacterEncoding( "ISO-8859-1" );
+ request.setMethod("POST");
+
+ IdentityAsserterHttpServletRequestWrapper wrapper
+ = new IdentityAsserterHttpServletRequestWrapper( request, "output-user" );
+
+ String outputBody = IOUtils.toString( wrapper.getInputStream(), wrapper.getCharacterEncoding() );
+ String output = wrapper.getQueryString();
+ assertThat( output, containsString( "user.name=output-user" ) );
+ }
+
+ @Test
+ public void testOverwriteUserNameInPostMethod() throws IOException {
+ String inputBody = "user.name=input-user&jar=%2Ftmp%2FGatewayWebHdfsFuncTest%2FtestJavaMapReduceViaWebHCat%2Fhadoop-examples.jar&class=org.apache.org.apache.hadoop.examples.WordCount&arg=%2Ftmp%2FGatewayWebHdfsFuncTest%2FtestJavaMapReduceViaTempleton%2Finput&arg=%2Ftmp%2FGatewayWebHdfsFuncTest%2FtestJavaMapReduceViaTempleton%2Foutput";
+
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.setInputStream( new MockServletInputStream( new ByteArrayInputStream( inputBody.getBytes( "UTF-8" ) ) ) );
+ request.setCharacterEncoding( "UTF-8" );
+ request.setContentType( "application/x-www-form-urlencoded" );
+ request.setMethod("POST");
+
+ IdentityAsserterHttpServletRequestWrapper wrapper
+ = new IdentityAsserterHttpServletRequestWrapper( request, "output-user" );
+
+ String outputBody = IOUtils.toString( wrapper.getInputStream(), wrapper.getCharacterEncoding() );
+ String output = wrapper.getQueryString();
+ assertThat( output, containsString( "user.name=output-user" ) );
+ assertThat( output, not( containsString( "input-user" ) ) );
+ }
+
+ @Test
+ public void testIngoreNonFormBody() throws IOException {
+ String inputBody = "user.name=input-user&jar=%2Ftmp%2FGatewayWebHdfsFuncTest%2FtestJavaMapReduceViaWebHCat%2Fhadoop-examples.jar&class=org.apache.org.apache.hadoop.examples.WordCount&arg=%2Ftmp%2FGatewayWebHdfsFuncTest%2FtestJavaMapReduceViaTempleton%2Finput&arg=%2Ftmp%2FGatewayWebHdfsFuncTest%2FtestJavaMapReduceViaTempleton%2Foutput";
+
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.setInputStream( new MockServletInputStream( new ByteArrayInputStream( inputBody.getBytes( "UTF-8" ) ) ) );
+ request.setCharacterEncoding( "UTF-8" );
+ request.setContentType( "text/plain" );
+
+ IdentityAsserterHttpServletRequestWrapper wrapper
+ = new IdentityAsserterHttpServletRequestWrapper( request, "output-user" );
+
+ String outputBody = IOUtils.toString( wrapper.getInputStream(), wrapper.getCharacterEncoding() );
+
+ assertThat( outputBody, containsString( "user.name=input-user" ) );
+ assertThat( outputBody, not( containsString( "output-user" ) ) );
+ }
+
+ @Test
+ public void testInsertUserNameInQueryString() {
+ String input = "param=value";
+
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.setQueryString( input );
+
+ IdentityAsserterHttpServletRequestWrapper wrapper
+ = new IdentityAsserterHttpServletRequestWrapper( request, "output-user" );
+
+ String output = wrapper.getQueryString();
+
+ assertThat( output, containsString( "user.name=output-user" ) );
+ }
+
+ @Test
+ public void testInsertUserNameInNullQueryString() {
+ String input = null;
+
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.setQueryString( input );
+
+ IdentityAsserterHttpServletRequestWrapper wrapper
+ = new IdentityAsserterHttpServletRequestWrapper( request, "output-user" );
+
+ String output = wrapper.getQueryString();
+
+ assertThat( output, containsString( "user.name=output-user" ) );
+ }
+
+ @Test
+ public void testInsertUserNameInNullQueryStringForGET() {
+ String input = null;
+
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.setQueryString( input );
+
+ IdentityAsserterHttpServletRequestWrapper wrapper
+ = new IdentityAsserterHttpServletRequestWrapper( request, "output-user" );
+
+ String output = wrapper.getQueryString();
+
+ assertThat( output, containsString( "user.name=output-user" ) );
+ }
+
+ @Test
+ public void testInsertUserNameInQueryStringForPOST() {
+ String input = null;
+
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.setQueryString( input );
+ request.setMethod("POST");
+
+ IdentityAsserterHttpServletRequestWrapper wrapper
+ = new IdentityAsserterHttpServletRequestWrapper( request, "output-user" );
+
+ String output = wrapper.getQueryString();
+
+ assertThat( output, containsString( "user.name=output-user" ) );
+ }
+
+ @Test
+ public void testOverwriteUserNameInQueryString() {
+ String input = "user.name=input-user";
+
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.setQueryString( input );
+
+ IdentityAsserterHttpServletRequestWrapper wrapper
+ = new IdentityAsserterHttpServletRequestWrapper( request, "output-user" );
+
+ String output = wrapper.getQueryString();
+
+ assertThat( output, containsString( "user.name=output-user" ) );
+ assertThat( output, not( containsString( "input-user" ) ) );
+ }
+
+ @Test
+ public void testUrlEncode() {
+ String s;
+ HashMap<String,String[]> m;
+
+ m = new HashMap<String,String[]>();
+ m.put( "null-values", null );
+ s = IdentityAsserterHttpServletRequestWrapper.urlEncode( m, "UTF-8" );
+ assertThat( s, is( "null-values" ) );
+
+ m = new HashMap<String,String[]>();
+ m.put( "no-values", new String[0] );
+ s = IdentityAsserterHttpServletRequestWrapper.urlEncode( m, "UTF-8" );
+ assertThat( s, is( "no-values" ) );
+
+ m = new HashMap<String,String[]>();
+ m.put( "one-value", new String[]{ "value1" } );
+ s = IdentityAsserterHttpServletRequestWrapper.urlEncode( m, "UTF-8" );
+ assertThat( s, is( "one-value=value1" ) );
+
+ m = new HashMap<String,String[]>();
+ m.put( "two-values", new String[]{ "value1", "value2" } );
+ s = IdentityAsserterHttpServletRequestWrapper.urlEncode( m, "UTF-8" );
+ assertThat( s, is( "two-values=value1&two-values=value2" ) );
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/ce3ca3ce/gateway-provider-identity-assertion-common/src/test/java/org/apache/hadoop/gateway/identityasserter/function/UsernameFunctionDescriptorTest.java
----------------------------------------------------------------------
diff --git a/gateway-provider-identity-assertion-common/src/test/java/org/apache/hadoop/gateway/identityasserter/function/UsernameFunctionDescriptorTest.java b/gateway-provider-identity-assertion-common/src/test/java/org/apache/hadoop/gateway/identityasserter/function/UsernameFunctionDescriptorTest.java
new file mode 100644
index 0000000..51f9d57
--- /dev/null
+++ b/gateway-provider-identity-assertion-common/src/test/java/org/apache/hadoop/gateway/identityasserter/function/UsernameFunctionDescriptorTest.java
@@ -0,0 +1,52 @@
+/**
+ * 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.identityasserter.function;
+
+import org.apache.hadoop.gateway.filter.rewrite.api.UrlRewriteFunctionDescriptor;
+import org.apache.hadoop.gateway.identityasserter.common.function.UsernameFunctionDescriptor;
+import org.junit.Test;
+
+import java.util.Iterator;
+import java.util.ServiceLoader;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.junit.Assert.fail;
+
+public class UsernameFunctionDescriptorTest {
+
+ @Test
+ public void testName() throws Exception {
+ UsernameFunctionDescriptor descriptor = new UsernameFunctionDescriptor();
+ assertThat( descriptor.name(), is( "username" ) );
+ }
+
+ @Test
+ public void testServiceLoader() throws Exception {
+ ServiceLoader loader = ServiceLoader.load( UrlRewriteFunctionDescriptor.class );
+ Iterator iterator = loader.iterator();
+ while( iterator.hasNext() ) {
+ Object object = iterator.next();
+ if( object instanceof UsernameFunctionDescriptor ) {
+ return;
+ }
+ }
+ fail( "Failed to find UsernameFunctionDescriptor via service loader." );
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/ce3ca3ce/gateway-provider-identity-assertion-common/src/test/java/org/apache/hadoop/gateway/identityasserter/function/UsernameFunctionProcessorTest.java
----------------------------------------------------------------------
diff --git a/gateway-provider-identity-assertion-common/src/test/java/org/apache/hadoop/gateway/identityasserter/function/UsernameFunctionProcessorTest.java b/gateway-provider-identity-assertion-common/src/test/java/org/apache/hadoop/gateway/identityasserter/function/UsernameFunctionProcessorTest.java
new file mode 100644
index 0000000..ebbe6ec
--- /dev/null
+++ b/gateway-provider-identity-assertion-common/src/test/java/org/apache/hadoop/gateway/identityasserter/function/UsernameFunctionProcessorTest.java
@@ -0,0 +1,248 @@
+/**
+ * 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.identityasserter.function;
+
+import org.apache.hadoop.gateway.filter.AbstractGatewayFilter;
+import org.apache.hadoop.gateway.filter.rewrite.api.UrlRewriteServletContextListener;
+import org.apache.hadoop.gateway.filter.rewrite.api.UrlRewriteServletFilter;
+import org.apache.hadoop.gateway.filter.rewrite.spi.UrlRewriteFunctionProcessor;
+import org.apache.hadoop.gateway.identityasserter.common.function.UsernameFunctionProcessor;
+import org.apache.hadoop.gateway.security.PrimaryPrincipal;
+import org.apache.hadoop.gateway.util.urltemplate.Parser;
+import org.apache.hadoop.test.log.NoOpLogger;
+import org.apache.hadoop.test.mock.MockInteraction;
+import org.apache.hadoop.test.mock.MockServlet;
+import org.apache.http.auth.BasicUserPrincipal;
+import org.eclipse.jetty.servlet.FilterHolder;
+import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.testing.HttpTester;
+import org.eclipse.jetty.testing.ServletTester;
+import org.eclipse.jetty.util.ArrayQueue;
+import org.eclipse.jetty.util.log.Log;
+import org.hamcrest.core.Is;
+import org.junit.After;
+import org.junit.Test;
+
+import javax.security.auth.Subject;
+import javax.servlet.DispatcherType;
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.nio.charset.Charset;
+import java.security.PrivilegedActionException;
+import java.security.PrivilegedExceptionAction;
+import java.util.Arrays;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.ServiceLoader;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.nullValue;
+import static org.hamcrest.collection.IsIterableContainingInOrder.contains;
+import static org.junit.Assert.fail;
+
+public class UsernameFunctionProcessorTest {
+
+ private ServletTester server;
+ private HttpTester request;
+ private HttpTester response;
+ private ArrayQueue<MockInteraction> interactions;
+ private MockInteraction interaction;
+
+ private static URL getTestResource( String name ) {
+ name = UsernameFunctionProcessorTest.class.getName().replaceAll( "\\.", "/" ) + "/" + name;
+ URL url = ClassLoader.getSystemResource( name );
+ return url;
+ }
+
+ public void setUp( String username, Map<String,String> initParams ) throws Exception {
+ String descriptorUrl = getTestResource( "rewrite.xml" ).toExternalForm();
+
+ Log.setLog( new NoOpLogger() );
+
+ server = new ServletTester();
+ server.setContextPath( "/" );
+ server.getContext().addEventListener( new UrlRewriteServletContextListener() );
+ server.getContext().setInitParameter(
+ UrlRewriteServletContextListener.DESCRIPTOR_LOCATION_INIT_PARAM_NAME, descriptorUrl );
+
+ FilterHolder setupFilter = server.addFilter( SetupFilter.class, "/*", EnumSet.of( DispatcherType.REQUEST ) );
+ setupFilter.setFilter( new SetupFilter( username ) );
+ FilterHolder rewriteFilter = server.addFilter( UrlRewriteServletFilter.class, "/*", EnumSet.of( DispatcherType.REQUEST ) );
+ if( initParams != null ) {
+ for( Map.Entry<String,String> entry : initParams.entrySet() ) {
+ rewriteFilter.setInitParameter( entry.getKey(), entry.getValue() );
+ }
+ }
+ rewriteFilter.setFilter( new UrlRewriteServletFilter() );
+
+ interactions = new ArrayQueue<MockInteraction>();
+
+ ServletHolder servlet = server.addServlet( MockServlet.class, "/" );
+ servlet.setServlet( new MockServlet( "mock-servlet", interactions ) );
+
+ server.start();
+
+ interaction = new MockInteraction();
+ request = new HttpTester();
+ response = new HttpTester();
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ if( server != null ) {
+ server.stop();
+ }
+ }
+
+ @Test
+ public void testInitialize() throws Exception {
+ UsernameFunctionProcessor processor = new UsernameFunctionProcessor();
+ // Shouldn't fail.
+ processor.initialize( null, null );
+ }
+
+ @Test
+ public void testDestroy() throws Exception {
+ UsernameFunctionProcessor processor = new UsernameFunctionProcessor();
+ // Shouldn't fail.
+ processor.destroy();
+ }
+
+ @Test
+ public void testResolve() throws Exception {
+ final UsernameFunctionProcessor processor = new UsernameFunctionProcessor();
+ assertThat( processor.resolve( null, null ), nullValue() );
+ assertThat( processor.resolve( null, Arrays.asList( "test-input" ) ), contains( "test-input" ) );
+ Subject subject = new Subject();
+ subject.getPrincipals().add( new PrimaryPrincipal( "test-username" ) );
+ subject.setReadOnly();
+ Subject.doAs( subject, new PrivilegedExceptionAction<Object>() {
+ @Override
+ public Object run() throws Exception {
+ assertThat( processor.resolve( null, null ), contains( "test-username" ) );
+ assertThat( processor.resolve( null, Arrays.asList( "test-ignored" ) ), contains( "test-username" ) );
+ return null;
+ }
+ } );
+ }
+
+ @Test
+ public void testServiceLoader() throws Exception {
+ ServiceLoader loader = ServiceLoader.load( UrlRewriteFunctionProcessor.class );
+ Iterator iterator = loader.iterator();
+ while( iterator.hasNext() ) {
+ Object object = iterator.next();
+ if( object instanceof UsernameFunctionProcessor ) {
+ return;
+ }
+ }
+ fail( "Failed to find UsernameFunctionProcessor via service loader." );
+ }
+
+ @Test
+ public void testRequestUrlRewriteOfUsernameViaRewriteRule() throws Exception {
+ Map<String,String> initParams = new HashMap<String,String>();
+ initParams.put( "request.url", "test-rule-username" );
+ setUp( "test-user", initParams );
+
+ String input = "<root/>";
+ String expect = "<root/>";
+
+ // Setup the server side request/response interaction.
+ interaction.expect()
+ .method( "PUT" )
+ .requestUrl( "test-output-scheme://test-input-host:777/test-output-path/test-input-path" )
+ .queryParam( "user.name", "test-user" )
+ .queryParam( "test-query-input-name", "test-query-input-value" )
+ .queryParam( "test-query-output-name", "test-query-output-value" )
+ .contentType( "text/xml" )
+ .characterEncoding( "UTF-8" )
+ .content( expect, Charset.forName( "UTF-8" ) );
+ interaction.respond()
+ .status( 200 );
+ interactions.add( interaction );
+ request.setMethod( "PUT" );
+ request.setURI( "/test-input-path?test-query-input-name=test-query-input-value" );
+ request.setVersion( "HTTP/1.1" );
+ request.setHeader( "Host", "test-input-host:777" );
+ request.setContentType( "text/xml; charset=UTF-8" );
+ request.setContent( input );
+
+ response.parse( server.getResponses( request.generate() ) );
+
+ // Test the results.
+ assertThat( response.getStatus(), Is.is( 200 ) );
+ }
+
+ private static class SetupFilter implements Filter {
+ private Subject subject;
+
+ public SetupFilter( String userName ) {
+ subject = new Subject();
+ subject.getPrincipals().add( new BasicUserPrincipal( userName ) );
+ }
+
+ @Override
+ public void init( FilterConfig filterConfig ) throws ServletException {
+ }
+
+ @Override
+ public void doFilter( final ServletRequest request, final ServletResponse response, final FilterChain chain ) throws IOException, ServletException {
+ HttpServletRequest httpRequest = ((HttpServletRequest)request);
+ StringBuffer sourceUrl = httpRequest.getRequestURL();
+ String queryString = httpRequest.getQueryString();
+ if( queryString != null ) {
+ sourceUrl.append( "?" );
+ sourceUrl.append( queryString );
+ }
+ try {
+ request.setAttribute(
+ AbstractGatewayFilter.SOURCE_REQUEST_URL_ATTRIBUTE_NAME,
+ Parser.parse( sourceUrl.toString() ) );
+ } catch( URISyntaxException e ) {
+ throw new ServletException( e );
+ }
+ try {
+ Subject.doAs( subject, new PrivilegedExceptionAction<Void>() {
+ @Override
+ public Void run() throws Exception {
+ chain.doFilter( request, response );
+ return null;
+ }
+ } );
+ } catch( PrivilegedActionException e ) {
+ throw new ServletException( e );
+ }
+ }
+
+ @Override
+ public void destroy() {
+ }
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/ce3ca3ce/gateway-provider-identity-assertion-common/src/test/resources/org/apache/hadoop/gateway/identityasserter/function/UsernameFunctionProcessorTest/rewrite.xml
----------------------------------------------------------------------
diff --git a/gateway-provider-identity-assertion-common/src/test/resources/org/apache/hadoop/gateway/identityasserter/function/UsernameFunctionProcessorTest/rewrite.xml b/gateway-provider-identity-assertion-common/src/test/resources/org/apache/hadoop/gateway/identityasserter/function/UsernameFunctionProcessorTest/rewrite.xml
new file mode 100644
index 0000000..cf28b92
--- /dev/null
+++ b/gateway-provider-identity-assertion-common/src/test/resources/org/apache/hadoop/gateway/identityasserter/function/UsernameFunctionProcessorTest/rewrite.xml
@@ -0,0 +1,24 @@
+<!--
+ 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.
+-->
+<rules>
+
+ <rule name="test-rule-username">
+ <match pattern="*://{host}:{port}/{path=**}?{**}"/>
+ <rewrite template="test-output-scheme://{host}:{port}/test-output-path/{path=**}?user.name={$username}?{**}?test-query-output-name=test-query-output-value"/>
+ </rule>
+
+</rules>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/knox/blob/ce3ca3ce/gateway-provider-identity-assertion-concat/pom.xml
----------------------------------------------------------------------
diff --git a/gateway-provider-identity-assertion-concat/pom.xml b/gateway-provider-identity-assertion-concat/pom.xml
new file mode 100644
index 0000000..13b64ba
--- /dev/null
+++ b/gateway-provider-identity-assertion-concat/pom.xml
@@ -0,0 +1,99 @@
+<?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.
+-->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <parent>
+ <groupId>org.apache.knox</groupId>
+ <artifactId>gateway</artifactId>
+ <version>0.6.0-SNAPSHOT</version>
+ </parent>
+ <artifactId>gateway-provider-identity-assertion-concat</artifactId>
+
+ <name>gateway-provider-identity-assertion-concat</name>
+ <description>An extension to the gateway that provides an easy integration point for asserting identity to Hadoop clusters using using some custom mapping facility.</description>
+
+ <licenses>
+ <license>
+ <name>The Apache Software License, Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+ <distribution>repo</distribution>
+ </license>
+ </licenses>
+
+ <dependencies>
+
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>${gateway-group}</groupId>
+ <artifactId>gateway-spi</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>${gateway-group}</groupId>
+ <artifactId>gateway-provider-identity-assertion-common</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>${gateway-group}</groupId>
+ <artifactId>gateway-test-utils</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>test-jetty-servlet</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-core</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-library</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.xmlmatchers</groupId>
+ <artifactId>xml-matchers</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.easymock</groupId>
+ <artifactId>easymock</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ </dependencies>
+</project>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/knox/blob/ce3ca3ce/gateway-provider-identity-assertion-concat/src/main/java/org/apache/hadoop/gateway/ConcatIdentityAsserterMessages.java
----------------------------------------------------------------------
diff --git a/gateway-provider-identity-assertion-concat/src/main/java/org/apache/hadoop/gateway/ConcatIdentityAsserterMessages.java b/gateway-provider-identity-assertion-concat/src/main/java/org/apache/hadoop/gateway/ConcatIdentityAsserterMessages.java
new file mode 100644
index 0000000..548f3cc
--- /dev/null
+++ b/gateway-provider-identity-assertion-concat/src/main/java/org/apache/hadoop/gateway/ConcatIdentityAsserterMessages.java
@@ -0,0 +1,31 @@
+/**
+ * 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;
+
+import org.apache.hadoop.gateway.i18n.messages.Message;
+import org.apache.hadoop.gateway.i18n.messages.MessageLevel;
+import org.apache.hadoop.gateway.i18n.messages.Messages;
+import org.apache.hadoop.gateway.i18n.messages.StackTrace;
+
+@Messages(logger="org.apache.hadoop.gateway")
+public interface ConcatIdentityAsserterMessages {
+
+ @Message( level = MessageLevel.WARN, text = "Skipping unencodable parameter {0}={1}, {2}: {3}" )
+ void skippingUnencodableParameter( String name, String value, String encoding, @StackTrace( level = MessageLevel.DEBUG ) Exception e );
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/ce3ca3ce/gateway-provider-identity-assertion-concat/src/main/java/org/apache/hadoop/gateway/identityasserter/concat/filter/ConcatIdentityAsserterDeploymentContributor.java
----------------------------------------------------------------------
diff --git a/gateway-provider-identity-assertion-concat/src/main/java/org/apache/hadoop/gateway/identityasserter/concat/filter/ConcatIdentityAsserterDeploymentContributor.java b/gateway-provider-identity-assertion-concat/src/main/java/org/apache/hadoop/gateway/identityasserter/concat/filter/ConcatIdentityAsserterDeploymentContributor.java
new file mode 100644
index 0000000..5eb2ca1
--- /dev/null
+++ b/gateway-provider-identity-assertion-concat/src/main/java/org/apache/hadoop/gateway/identityasserter/concat/filter/ConcatIdentityAsserterDeploymentContributor.java
@@ -0,0 +1,32 @@
+/**
+ * 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.identityasserter.concat.filter;
+
+import org.apache.hadoop.gateway.identityasserter.common.filter.AbstractIdentityAsserterDeploymentContributor;
+
+public class ConcatIdentityAsserterDeploymentContributor extends AbstractIdentityAsserterDeploymentContributor {
+
+ @Override
+ public String getName() {
+ return "Concat";
+ }
+
+ protected String getFilterClassname() {
+ return ConcatIdentityAssertionFilter.class.getName();
+ }
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/ce3ca3ce/gateway-provider-identity-assertion-concat/src/main/java/org/apache/hadoop/gateway/identityasserter/concat/filter/ConcatIdentityAssertionFilter.java
----------------------------------------------------------------------
diff --git a/gateway-provider-identity-assertion-concat/src/main/java/org/apache/hadoop/gateway/identityasserter/concat/filter/ConcatIdentityAssertionFilter.java b/gateway-provider-identity-assertion-concat/src/main/java/org/apache/hadoop/gateway/identityasserter/concat/filter/ConcatIdentityAssertionFilter.java
new file mode 100644
index 0000000..08022b6
--- /dev/null
+++ b/gateway-provider-identity-assertion-concat/src/main/java/org/apache/hadoop/gateway/identityasserter/concat/filter/ConcatIdentityAssertionFilter.java
@@ -0,0 +1,65 @@
+/**
+ * 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.identityasserter.concat.filter;
+
+import java.security.Principal;
+import java.util.ArrayList;
+import java.util.Set;
+
+import javax.security.auth.Subject;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import org.apache.hadoop.gateway.identityasserter.common.filter.CommonIdentityAssertionFilter;
+import org.apache.hadoop.gateway.security.GroupPrincipal;
+
+public class ConcatIdentityAssertionFilter extends CommonIdentityAssertionFilter {
+ private String prefix = null;
+ private String suffix = null;
+
+ /* (non-Javadoc)
+ * @see javax.servlet.Filter#init(javax.servlet.FilterConfig)
+ */
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException {
+ prefix = filterConfig.getInitParameter("concat.prefix");
+ suffix = filterConfig.getInitParameter("concat.suffix");
+ if (prefix == null) {
+ prefix = "";
+ }
+ if (suffix == null) {
+ suffix = "";
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.hadoop.gateway.identityasserter.common.filter.AbstractIdentityAssertionFilter#mapGroupPrincipals(java.lang.String, javax.security.auth.Subject)
+ */
+ @Override
+ public String[] mapGroupPrincipals(String mappedPrincipalName, Subject subject) {
+ // NOP - returning null will allow existing Subject group principals to remain the same
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.hadoop.gateway.identityasserter.common.filter.AbstractIdentityAssertionFilter#mapUserPrincipal(java.lang.String)
+ */
+ @Override
+ public String mapUserPrincipal(String principalName) {
+ return prefix + principalName + suffix;
+ }
+}