You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@knox.apache.org by mo...@apache.org on 2022/03/11 11:37:53 UTC
[knox] branch master updated: KNOX-2710 - Support for identityassertion filter with no doAs query param (#544)
This is an automated email from the ASF dual-hosted git repository.
more pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/knox.git
The following commit(s) were added to refs/heads/master by this push:
new cbae31d KNOX-2710 - Support for identityassertion filter with no doAs query param (#544)
cbae31d is described below
commit cbae31d384f2343f9af4f1851f2fae60c82b8e56
Author: Sandeep Moré <mo...@gmail.com>
AuthorDate: Fri Mar 11 06:37:47 2022 -0500
KNOX-2710 - Support for identityassertion filter with no doAs query param (#544)
---
.../IdentityAsserterHttpServletRequestWrapper.java | 8 +-
.../pom.xml | 88 +++++++++++
...ImpersonationAsserterDeploymentContributor.java | 53 +++++++
.../NoImpersonationAsserterRequestWrapper.java | 64 ++++++++
.../filter/NoImpersonationFilter.java | 54 +++++++
...ox.gateway.deploy.ProviderDeploymentContributor | 19 +++
.../filter/NoImpersonationFilterTest.java | 167 ++++++++++++++++++++
...ImpersonationHttpServletRequestWrapperTest.java | 169 +++++++++++++++++++++
.../UsernameFunctionProcessorTest/rewrite.xml | 24 +++
gateway-release/pom.xml | 4 +
pom.xml | 6 +
11 files changed, 652 insertions(+), 4 deletions(-)
diff --git a/gateway-provider-identity-assertion-common/src/main/java/org/apache/knox/gateway/identityasserter/common/filter/IdentityAsserterHttpServletRequestWrapper.java b/gateway-provider-identity-assertion-common/src/main/java/org/apache/knox/gateway/identityasserter/common/filter/IdentityAsserterHttpServletRequestWrapper.java
index de844ca..ba72fd1 100644
--- a/gateway-provider-identity-assertion-common/src/main/java/org/apache/knox/gateway/identityasserter/common/filter/IdentityAsserterHttpServletRequestWrapper.java
+++ b/gateway-provider-identity-assertion-common/src/main/java/org/apache/knox/gateway/identityasserter/common/filter/IdentityAsserterHttpServletRequestWrapper.java
@@ -46,7 +46,7 @@ import java.util.Map;
public class IdentityAsserterHttpServletRequestWrapper extends HttpServletRequestWrapper {
-private static SpiGatewayMessages log = MessagesFactory.get( SpiGatewayMessages.class );
+ protected static final SpiGatewayMessages log = MessagesFactory.get( SpiGatewayMessages.class );
private static final String PRINCIPAL_PARAM = "user.name";
private static final String DOAS_PRINCIPAL_PARAM = "doAs";
@@ -143,7 +143,7 @@ private static SpiGatewayMessages log = MessagesFactory.get( SpiGatewayMessages.
return params;
}
- private Map<String, List<String>> getParams()
+ protected Map<String, List<String>> getParams()
throws UnsupportedEncodingException {
return getParams( super.getQueryString() );
}
@@ -181,7 +181,7 @@ private static SpiGatewayMessages log = MessagesFactory.get( SpiGatewayMessages.
return q;
}
- private List<String> getImpersonationParamNames() {
+ protected List<String> getImpersonationParamNames() {
// TODO: let's have service definitions register their impersonation
// params in a future release and get this list from a central registry.
// This will provide better coverage of protection by removing any
@@ -192,7 +192,7 @@ private static SpiGatewayMessages log = MessagesFactory.get( SpiGatewayMessages.
return principalParamNames;
}
- private Map<String, List<String>> scrubOfExistingPrincipalParams(
+ protected Map<String, List<String>> scrubOfExistingPrincipalParams(
Map<String, List<String>> params, List<String> principalParamNames) {
HashSet<String> remove = new HashSet<>();
for (String paramKey : params.keySet()) {
diff --git a/gateway-provider-identity-assertion-no-doas/pom.xml b/gateway-provider-identity-assertion-no-doas/pom.xml
new file mode 100644
index 0000000..2fbba2b
--- /dev/null
+++ b/gateway-provider-identity-assertion-no-doas/pom.xml
@@ -0,0 +1,88 @@
+<?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>2.0.0-SNAPSHOT</version>
+ </parent>
+
+ <artifactId>gateway-provider-identity-assertion-no-doas</artifactId>
+ <name>gateway-provider-identity-assertion-no-doas</name>
+ <description>An extension to the gateway that asserts identity to Hadoop clusters that excludes doAs parameter.</description>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.knox</groupId>
+ <artifactId>gateway-i18n</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.knox</groupId>
+ <artifactId>gateway-spi</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.knox</groupId>
+ <artifactId>gateway-provider-identity-assertion-common</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.knox</groupId>
+ <artifactId>gateway-provider-rewrite</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.jboss.shrinkwrap.descriptors</groupId>
+ <artifactId>shrinkwrap-descriptors-api-javaee</artifactId>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-lang3</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.apache.knox</groupId>
+ <artifactId>gateway-test-utils</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.eclipse.jetty</groupId>
+ <artifactId>jetty-servlet</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>org.xmlmatchers</groupId>
+ <artifactId>xml-matchers</artifactId>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+</project>
diff --git a/gateway-provider-identity-assertion-no-doas/src/main/java/org/apache/knox/gateway/identityasserter/filter/NoImpersonationAsserterDeploymentContributor.java b/gateway-provider-identity-assertion-no-doas/src/main/java/org/apache/knox/gateway/identityasserter/filter/NoImpersonationAsserterDeploymentContributor.java
new file mode 100644
index 0000000..c33d683
--- /dev/null
+++ b/gateway-provider-identity-assertion-no-doas/src/main/java/org/apache/knox/gateway/identityasserter/filter/NoImpersonationAsserterDeploymentContributor.java
@@ -0,0 +1,53 @@
+/*
+ * 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.knox.gateway.identityasserter.filter;
+
+import org.apache.knox.gateway.deploy.DeploymentContext;
+import org.apache.knox.gateway.identityasserter.common.filter.AbstractIdentityAsserterDeploymentContributor;
+import org.apache.knox.gateway.topology.Provider;
+
+public class NoImpersonationAsserterDeploymentContributor extends AbstractIdentityAsserterDeploymentContributor {
+
+ /**
+ * Name of our <b>identity-assertion</b> provider.
+ */
+ public static final String NO_DOAS_PROVIDER = "NoImpersonationProvider";
+ private static final String FILTER_CLASSNAME = NoImpersonationFilter.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 getName() {
+ return NO_DOAS_PROVIDER;
+ }
+
+ @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);
+
+ context.getWebAppDescriptor().createContextParam().paramName(PRINCIPAL_MAPPING_PARAM_NAME).paramValue(mappings);
+ context.getWebAppDescriptor().createContextParam().paramName(GROUP_PRINCIPAL_MAPPING_PARAM_NAME).paramValue(groupMappings);
+ }
+
+ @Override
+ protected String getFilterClassname() {
+ return FILTER_CLASSNAME;
+ }
+}
diff --git a/gateway-provider-identity-assertion-no-doas/src/main/java/org/apache/knox/gateway/identityasserter/filter/NoImpersonationAsserterRequestWrapper.java b/gateway-provider-identity-assertion-no-doas/src/main/java/org/apache/knox/gateway/identityasserter/filter/NoImpersonationAsserterRequestWrapper.java
new file mode 100644
index 0000000..6ef7dd0
--- /dev/null
+++ b/gateway-provider-identity-assertion-no-doas/src/main/java/org/apache/knox/gateway/identityasserter/filter/NoImpersonationAsserterRequestWrapper.java
@@ -0,0 +1,64 @@
+/*
+ * 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.knox.gateway.identityasserter.filter;
+
+import org.apache.knox.gateway.identityasserter.common.filter.IdentityAsserterHttpServletRequestWrapper;
+import javax.servlet.http.HttpServletRequest;
+import java.io.UnsupportedEncodingException;
+import java.nio.charset.Charset;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+public class NoImpersonationAsserterRequestWrapper extends
+ IdentityAsserterHttpServletRequestWrapper {
+
+ public NoImpersonationAsserterRequestWrapper(
+ HttpServletRequest request, String principal) {
+ super(request, principal);
+ }
+
+ /**
+ * Skip adding doAs as query param
+ * @return
+ */
+ @Override
+ public String getQueryString() {
+ String q = null;
+ Map<String, List<String>> params;
+ try {
+ params = getParams();
+ if (params == null) {
+ params = new LinkedHashMap<>();
+ }
+
+ List<String> principalParamNames = getImpersonationParamNames();
+ params = scrubOfExistingPrincipalParams(params, principalParamNames);
+
+ String encoding = getCharacterEncoding();
+ if (encoding == null) {
+ encoding = Charset.defaultCharset().name();
+ }
+ q = urlEncode(params, encoding);
+ } catch (UnsupportedEncodingException e) {
+ log.unableToGetParamsFromQueryString(e);
+ }
+
+ return q;
+ }
+}
diff --git a/gateway-provider-identity-assertion-no-doas/src/main/java/org/apache/knox/gateway/identityasserter/filter/NoImpersonationFilter.java b/gateway-provider-identity-assertion-no-doas/src/main/java/org/apache/knox/gateway/identityasserter/filter/NoImpersonationFilter.java
new file mode 100644
index 0000000..a09255b
--- /dev/null
+++ b/gateway-provider-identity-assertion-no-doas/src/main/java/org/apache/knox/gateway/identityasserter/filter/NoImpersonationFilter.java
@@ -0,0 +1,54 @@
+/*
+ * 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.knox.gateway.identityasserter.filter;
+
+
+import javax.security.auth.Subject;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+
+import org.apache.knox.gateway.identityasserter.common.filter.CommonIdentityAssertionFilter;
+
+public class NoImpersonationFilter extends CommonIdentityAssertionFilter {
+
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException {
+ super.init(filterConfig);
+ }
+
+ @Override
+ public String[] mapGroupPrincipals(String mappedPrincipalName, Subject subject) {
+ return mapGroupPrincipalsBase(mappedPrincipalName, subject);
+ }
+
+ @Override
+ public String mapUserPrincipal(String principalName) {
+ return mapUserPrincipalBase(principalName);
+ }
+
+ @Override
+ public HttpServletRequestWrapper wrapHttpServletRequest(
+ ServletRequest request, String mappedPrincipalName) {
+ return new NoImpersonationAsserterRequestWrapper(
+ (HttpServletRequest) request,
+ mappedPrincipalName);
+ }
+}
diff --git a/gateway-provider-identity-assertion-no-doas/src/main/resources/META-INF/services/org.apache.knox.gateway.deploy.ProviderDeploymentContributor b/gateway-provider-identity-assertion-no-doas/src/main/resources/META-INF/services/org.apache.knox.gateway.deploy.ProviderDeploymentContributor
new file mode 100644
index 0000000..c5570a1
--- /dev/null
+++ b/gateway-provider-identity-assertion-no-doas/src/main/resources/META-INF/services/org.apache.knox.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.knox.gateway.identityasserter.filter.NoImpersonationAsserterDeploymentContributor
\ No newline at end of file
diff --git a/gateway-provider-identity-assertion-no-doas/src/test/java/org/apache/knox/gateway/identityasserter/filter/NoImpersonationFilterTest.java b/gateway-provider-identity-assertion-no-doas/src/test/java/org/apache/knox/gateway/identityasserter/filter/NoImpersonationFilterTest.java
new file mode 100644
index 0000000..53f1457
--- /dev/null
+++ b/gateway-provider-identity-assertion-no-doas/src/test/java/org/apache/knox/gateway/identityasserter/filter/NoImpersonationFilterTest.java
@@ -0,0 +1,167 @@
+/*
+ * 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.knox.gateway.identityasserter.filter;
+
+import org.apache.knox.gateway.security.GroupPrincipal;
+import org.apache.knox.gateway.security.PrimaryPrincipal;
+import org.easymock.EasyMock;
+import org.junit.Test;
+
+import javax.security.auth.Subject;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletContext;
+import java.security.Principal;
+import java.util.Arrays;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+public class NoImpersonationFilterTest {
+
+ @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 );
+
+ NoImpersonationFilter filter = new NoImpersonationFilter();
+ 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: " + Arrays.toString(mappedGroups), groupFoundIn("mrgroup", mappedGroups));
+ assertTrue("mrducks not found in groups: " + Arrays.toString(mappedGroups), groupFoundIn("mrducks", mappedGroups));
+ assertFalse("group1 WAS found in groups: " + Arrays.toString(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: " + Arrays.toString(mappedGroups), groupFoundIn("group1", mappedGroups));
+ }
+
+ private boolean groupFoundIn(String expected, String[] mappedGroups) {
+ if (mappedGroups == null) {
+ return false;
+ }
+ for (String mappedGroup : mappedGroups) {
+ if (mappedGroup.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 );
+
+ NoImpersonationFilter filter = new NoImpersonationFilter();
+ 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);
+
+ 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: " + Arrays.toString(groups), groupFoundIn("mrgroup", groups));
+ assertTrue("mrducks not found in groups: " + Arrays.toString(groups), groupFoundIn("mrducks", groups));
+ assertFalse("group1 WAS found in groups: " + Arrays.toString(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);
+ }
+}
diff --git a/gateway-provider-identity-assertion-no-doas/src/test/java/org/apache/knox/gateway/identityasserter/filter/NoImpersonationHttpServletRequestWrapperTest.java b/gateway-provider-identity-assertion-no-doas/src/test/java/org/apache/knox/gateway/identityasserter/filter/NoImpersonationHttpServletRequestWrapperTest.java
new file mode 100644
index 0000000..95fafcb
--- /dev/null
+++ b/gateway-provider-identity-assertion-no-doas/src/test/java/org/apache/knox/gateway/identityasserter/filter/NoImpersonationHttpServletRequestWrapperTest.java
@@ -0,0 +1,169 @@
+/*
+ * 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.knox.gateway.identityasserter.filter;
+
+import org.apache.commons.lang3.StringUtils;
+import org.apache.knox.gateway.config.GatewayConfig;
+import org.apache.knox.test.mock.MockHttpServletRequest;
+import org.apache.knox.test.mock.MockServletInputStream;
+import org.junit.After;
+import org.junit.Test;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.containsString;
+import static org.hamcrest.Matchers.is;
+import static org.hamcrest.Matchers.not;
+import static org.junit.Assert.assertTrue;
+
+public class NoImpersonationHttpServletRequestWrapperTest {
+ @After
+ public void resetSystemProps() {
+ System.setProperty(GatewayConfig.HADOOP_KERBEROS_SECURED, "false");
+ }
+
+ @Test
+ public void testNoUserNameInPostMethod() 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( StandardCharsets.UTF_8 ) ) ) );
+ request.setCharacterEncoding( StandardCharsets.UTF_8.name() );
+ request.setContentType( "application/x-www-form-urlencoded" );
+ request.setMethod("POST");
+
+ NoImpersonationAsserterRequestWrapper wrapper
+ = new NoImpersonationAsserterRequestWrapper( request, "output-user" );
+
+ String output = wrapper.getQueryString();
+ assertThat( output, containsString( "" ) );
+ }
+
+ @Test
+ public void testNoUserNameInPostMethodWithoutEncoding() 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( StandardCharsets.UTF_8 ) ) ) );
+ request.setContentType( "application/x-www-form-urlencoded" );
+ request.setMethod("POST");
+
+ NoImpersonationAsserterRequestWrapper wrapper
+ = new NoImpersonationAsserterRequestWrapper( request, "output-user" );
+
+ String output = wrapper.getQueryString();
+ // make sure principal is not added
+ assertTrue(StringUtils.isBlank(output));
+ }
+
+ @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( StandardCharsets.UTF_8 ) ) ) );
+ request.setCharacterEncoding( StandardCharsets.UTF_8.name() );
+ request.setContentType( "application/x-www-form-urlencoded" );
+ request.setMethod("POST");
+
+ NoImpersonationAsserterRequestWrapper wrapper
+ = new NoImpersonationAsserterRequestWrapper( request, "output-user" );
+
+ String output = wrapper.getQueryString();
+ assertThat( output, containsString( "" ) );
+ assertThat( output, not( containsString( "input-user" ) ) );
+ }
+
+
+ @Test
+ public void testInsertUserNameInQueryString() {
+ String input = "param=value";
+
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.setQueryString( input );
+
+ NoImpersonationAsserterRequestWrapper wrapper
+ = new NoImpersonationAsserterRequestWrapper( request, "output-user" );
+
+ String output = wrapper.getQueryString();
+
+ assertThat( output, containsString( "" ) );
+ }
+
+ @Test
+ public void testInsertNoDoAsInQueryString() {
+ System.setProperty(GatewayConfig.HADOOP_KERBEROS_SECURED, "true");
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.setQueryString("op=LISTSTATUS&user.name=jack&User.Name=jill&DOas=admin&doas=root");
+
+ NoImpersonationAsserterRequestWrapper wrapper
+ = new NoImpersonationAsserterRequestWrapper( request, "output-user" );
+
+ String output = wrapper.getQueryString();
+ assertThat(output, is("op=LISTSTATUS"));
+ }
+
+ @Test
+ public void testNoUserNameInNullQueryString() {
+ String input = null;
+
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.setQueryString( input );
+
+ NoImpersonationAsserterRequestWrapper wrapper
+ = new NoImpersonationAsserterRequestWrapper( request, "output-user" );
+
+ String output = wrapper.getQueryString();
+
+ assertThat( output, containsString( "" ) );
+ }
+
+ @Test
+ public void testNoUserNameInNullQueryStringForGET() {
+ String input = null;
+
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.setQueryString( input );
+
+ NoImpersonationAsserterRequestWrapper wrapper
+ = new NoImpersonationAsserterRequestWrapper( request, "output-user" );
+
+ String output = wrapper.getQueryString();
+
+ assertThat( output, containsString( "" ) );
+ }
+
+ @Test
+ public void testNoUserNameInQueryStringForPOST() {
+ String input = null;
+
+ MockHttpServletRequest request = new MockHttpServletRequest();
+ request.setQueryString( input );
+ request.setMethod("POST");
+
+ NoImpersonationAsserterRequestWrapper wrapper
+ = new NoImpersonationAsserterRequestWrapper( request, "output-user" );
+
+ String output = wrapper.getQueryString();
+
+ assertThat( output, containsString( "" ) );
+ }
+}
diff --git a/gateway-provider-identity-assertion-no-doas/src/test/resources/org/apache/knox/gateway/identityasserter/function/UsernameFunctionProcessorTest/rewrite.xml b/gateway-provider-identity-assertion-no-doas/src/test/resources/org/apache/knox/gateway/identityasserter/function/UsernameFunctionProcessorTest/rewrite.xml
new file mode 100644
index 0000000..cf28b92
--- /dev/null
+++ b/gateway-provider-identity-assertion-no-doas/src/test/resources/org/apache/knox/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
diff --git a/gateway-release/pom.xml b/gateway-release/pom.xml
index aafd9e6..e86449c 100644
--- a/gateway-release/pom.xml
+++ b/gateway-release/pom.xml
@@ -385,6 +385,10 @@
</dependency>
<dependency>
<groupId>org.apache.knox</groupId>
+ <artifactId>gateway-provider-identity-assertion-no-doas</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.knox</groupId>
<artifactId>gateway-provider-ha</artifactId>
</dependency>
diff --git a/pom.xml b/pom.xml
index 888701b..adeb0d6 100644
--- a/pom.xml
+++ b/pom.xml
@@ -99,6 +99,7 @@
<module>gateway-provider-identity-assertion-regex</module>
<module>gateway-provider-identity-assertion-switchcase</module>
<module>gateway-provider-identity-assertion-pseudo</module>
+ <module>gateway-provider-identity-assertion-no-doas</module>
<module>gateway-provider-jersey</module>
<module>gateway-provider-ha</module>
<module>gateway-service-admin</module>
@@ -979,6 +980,11 @@
</dependency>
<dependency>
<groupId>org.apache.knox</groupId>
+ <artifactId>gateway-provider-identity-assertion-no-doas</artifactId>
+ <version>${project.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.knox</groupId>
<artifactId>gateway-provider-rewrite</artifactId>
<version>${project.version}</version>
</dependency>