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 2017/09/08 15:15:17 UTC
[24/24] knox git commit: Merge branch 'master' into
KNOX-998-Package_Restructuring
Merge branch 'master' into KNOX-998-Package_Restructuring
# Conflicts:
# gateway-provider-security-preauth/src/test/java/org/apache/knox/gateway/provider/federation/DefaultValidatorTest.java
# gateway-provider-security-preauth/src/test/java/org/apache/knox/gateway/provider/federation/HeaderPreAuthFederationFilterTest.java
# gateway-provider-security-preauth/src/test/java/org/apache/knox/gateway/provider/federation/IPValidatorTest.java
# gateway-provider-security-preauth/src/test/java/org/apache/knox/gateway/provider/federation/PreAuthServiceTest.java
# gateway-test/src/test/java/org/apache/knox/gateway/GatewayLdapDynamicGroupFuncTest.java
# gateway-test/src/test/java/org/apache/knox/gateway/GatewayLdapGroupFuncTest.java
# gateway-test/src/test/java/org/apache/knox/gateway/Knox242FuncTest.java
# gateway-test/src/test/java/org/apache/knox/gateway/KnoxCliLdapFuncTestNegative.java
Project: http://git-wip-us.apache.org/repos/asf/knox/repo
Commit: http://git-wip-us.apache.org/repos/asf/knox/commit/50f46e9e
Tree: http://git-wip-us.apache.org/repos/asf/knox/tree/50f46e9e
Diff: http://git-wip-us.apache.org/repos/asf/knox/diff/50f46e9e
Branch: refs/heads/KNOX-998-Package_Restructuring
Commit: 50f46e9eed9ccc27a54cb71a090322b023fd7a8b
Parents: 2e6713b e88c7a9
Author: Sandeep More <mo...@apache.org>
Authored: Fri Sep 8 10:53:16 2017 -0400
Committer: Sandeep More <mo...@apache.org>
Committed: Fri Sep 8 10:53:16 2017 -0400
----------------------------------------------------------------------
.../ha/dispatch/DefaultHaDispatchTest.java | 7 +-
.../function/UsernameFunctionProcessor.java | 2 +-
.../filter/HadoopGroupProviderFilterTest.java | 12 +-
.../SwitchCaseIdentityAssertionFilter.java | 2 +-
.../rewrite/impl/FrontendFunctionProcessor.java | 2 +-
.../impl/html/HtmlImportFunctionProcessor.java | 2 +-
.../rewrite/impl/html/HtmlPrefixProcessor.java | 2 +-
.../rewrite/impl/json/JsonFilterReader.java | 4 +-
.../gateway/filter/AclsAuthorizationFilter.java | 6 +-
.../jwt/filter/AbstractJWTFilter.java | 55 +++--
.../jwt/filter/JWTFederationFilter.java | 8 +-
.../jwt/filter/SSOCookieFederationFilter.java | 6 +-
.../federation/AbstractJWTFilterTest.java | 214 ++++++++++++++++---
.../federation/JWTFederationFilterTest.java | 14 +-
.../provider/federation/JWTTokenTest.java | 3 +-
.../federation/SSOCookieProviderTest.java | 61 +-----
.../knox/gateway/picketlink/PicketlinkTest.java | 3 +-
.../federation/DefaultValidatorTest.java | 2 +-
.../HeaderPreAuthFederationFilterTest.java | 7 +-
.../provider/federation/IPValidatorTest.java | 2 +-
.../provider/federation/PreAuthSSOTest.java | 3 +-
.../provider/federation/PreAuthServiceTest.java | 3 +-
.../webappsec/deploy/WebAppSecContributor.java | 6 +-
.../apache/knox/gateway/webappsec/CSRFTest.java | 3 +-
.../webappsec/XFrameOptionsFilterTest.java | 12 +-
.../home/conf/topologies/manager.xml | 2 +-
.../filter/CompositeEnumerationTest.java | 2 +-
.../org/apache/knox/gateway/GatewayServer.java | 8 +-
.../impl/ApplicationDeploymentContributor.java | 2 +-
.../ServiceDefinitionDeploymentContributor.java | 2 +-
.../gateway/dispatch/UrlConnectionDispatch.java | 2 +-
.../topology/validation/TopologyValidator.java | 2 +-
.../org/apache/knox/gateway/util/KnoxCLI.java | 2 +-
.../apache/knox/gateway/AuditLoggingTest.java | 13 +-
.../org/apache/knox/gateway/TempletonDemo.java | 8 +-
.../gateway/deploy/DeploymentFactoryTest.java | 2 +-
.../service/admin/TopologiesResource.java | 2 +-
.../gateway/rm/dispatch/RMHaDispatchTest.java | 11 +-
.../hdfs/dispatch/WebHdfsHaDispatchTest.java | 7 +-
.../knox/gateway/security/SubjectUtils.java | 4 +-
.../gateway/dispatch/DefaultDispatchTest.java | 16 +-
.../security/principal/PrincipalMapperTest.java | 8 +-
gateway-test-release-utils/pom.xml | 37 ----
.../apache/knox/gateway/GatewayTestConfig.java | 12 +-
.../apache/knox/gateway/GatewayTestDriver.java | 15 --
gateway-test-release/webhdfs-kerb-test/pom.xml | 30 +++
gateway-test-release/webhdfs-test/pom.xml | 30 +++
gateway-test/pom.xml | 30 +++
.../gateway/AmbariServiceDefinitionTest.java | 17 +-
.../knox/gateway/GatewayAdminFuncTest.java | 23 --
.../gateway/GatewayAdminTopologyFuncTest.java | 22 --
.../apache/knox/gateway/GatewayAppFuncTest.java | 2 +-
.../knox/gateway/GatewayBasicFuncTest.java | 65 ++++--
.../knox/gateway/GatewayDeployFuncTest.java | 22 --
.../knox/gateway/GatewayHealthFuncTest.java | 24 ---
.../GatewayLdapDynamicGroupFuncTest.java | 24 ---
.../knox/gateway/GatewayLdapGroupFuncTest.java | 27 +--
.../gateway/GatewayLdapPosixGroupFuncTest.java | 22 +-
.../gateway/GatewayLocalServiceFuncTest.java | 23 --
.../knox/gateway/GatewayMultiFuncTest.java | 3 +-
.../knox/gateway/GatewaySampleFuncTest.java | 23 --
.../apache/knox/gateway/GatewaySslFuncTest.java | 2 +-
.../apache/knox/gateway/Knox242FuncTest.java | 23 --
.../gateway/KnoxCliLdapFuncTestNegative.java | 29 ---
.../gateway/KnoxCliLdapFuncTestPositive.java | 27 ---
.../apache/knox/gateway/KnoxCliSysBindTest.java | 27 ---
.../deploy/DeploymentFactoryFuncTest.java | 25 ---
.../knox/gateway/util/IpAddressValidator.java | 2 +-
.../gateway/util/IpAddressValidatorTest.java | 3 +-
.../apache/knox/gateway/util/JsonUtilsTest.java | 3 +-
.../org/apache/knox/gateway/util/UrlsTest.java | 4 +-
.../knox/gateway/config/AdapterSampleTest.java | 19 +-
.../apache/knox/gateway/config/FuncTest.java | 12 +-
.../BeanConfigurationAdapterDescriptorTest.java | 2 +-
.../knox/gateway/util/urltemplate/Expander.java | 4 +-
.../knox/gateway/util/urltemplate/Matcher.java | 2 +-
.../knox/gateway/util/urltemplate/Template.java | 2 +-
.../gateway/util/urltemplate/ExpanderTest.java | 2 +-
78 files changed, 523 insertions(+), 650 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/knox/blob/50f46e9e/gateway-provider-ha/src/test/java/org/apache/knox/gateway/ha/dispatch/DefaultHaDispatchTest.java
----------------------------------------------------------------------
diff --cc gateway-provider-ha/src/test/java/org/apache/knox/gateway/ha/dispatch/DefaultHaDispatchTest.java
index 0f19e79,0000000..0470555
mode 100644,000000..100644
--- a/gateway-provider-ha/src/test/java/org/apache/knox/gateway/ha/dispatch/DefaultHaDispatchTest.java
+++ b/gateway-provider-ha/src/test/java/org/apache/knox/gateway/ha/dispatch/DefaultHaDispatchTest.java
@@@ -1,106 -1,0 +1,109 @@@
+/**
+ * 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.ha.dispatch;
+
+import org.apache.knox.gateway.ha.provider.HaDescriptor;
+import org.apache.knox.gateway.ha.provider.HaProvider;
+import org.apache.knox.gateway.ha.provider.HaServletContextListener;
+import org.apache.knox.gateway.ha.provider.impl.DefaultHaProvider;
+import org.apache.knox.gateway.ha.provider.impl.HaDescriptorFactory;
+import org.apache.knox.gateway.servlet.SynchronousServletOutputStreamAdapter;
+import org.apache.http.client.methods.HttpRequestBase;
+import org.apache.http.client.methods.HttpUriRequest;
- import org.apache.http.impl.client.DefaultHttpClient;
++import org.apache.http.impl.client.CloseableHttpClient;
++import org.apache.http.impl.client.HttpClientBuilder;
+import org.apache.http.params.BasicHttpParams;
+import org.easymock.EasyMock;
+import org.easymock.IAnswer;
+import org.junit.Assert;
+import org.junit.Test;
+
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.concurrent.atomic.AtomicInteger;
+
+public class DefaultHaDispatchTest {
+
+ @Test
+ public void testConnectivityFailover() throws Exception {
+ String serviceName = "OOZIE";
+ HaDescriptor descriptor = HaDescriptorFactory.createDescriptor();
+ descriptor.addServiceConfig(HaDescriptorFactory.createServiceConfig(serviceName, "true", "1", "1000", "2", "1000", null, null));
+ HaProvider provider = new DefaultHaProvider(descriptor);
+ URI uri1 = new URI( "http://unreachable-host" );
+ URI uri2 = new URI( "http://reachable-host" );
+ ArrayList<String> urlList = new ArrayList<String>();
+ urlList.add(uri1.toString());
+ urlList.add(uri2.toString());
+ provider.addHaService(serviceName, urlList);
+ FilterConfig filterConfig = EasyMock.createNiceMock(FilterConfig.class);
+ ServletContext servletContext = EasyMock.createNiceMock(ServletContext.class);
+
+ EasyMock.expect(filterConfig.getServletContext()).andReturn(servletContext).anyTimes();
+ EasyMock.expect(servletContext.getAttribute(HaServletContextListener.PROVIDER_ATTRIBUTE_NAME)).andReturn(provider).anyTimes();
+
+ BasicHttpParams params = new BasicHttpParams();
+
+ HttpUriRequest outboundRequest = EasyMock.createNiceMock(HttpRequestBase.class);
+ EasyMock.expect(outboundRequest.getMethod()).andReturn( "GET" ).anyTimes();
+ EasyMock.expect(outboundRequest.getURI()).andReturn( uri1 ).anyTimes();
+ EasyMock.expect(outboundRequest.getParams()).andReturn( params ).anyTimes();
+
+ HttpServletRequest inboundRequest = EasyMock.createNiceMock(HttpServletRequest.class);
+ EasyMock.expect(inboundRequest.getRequestURL()).andReturn( new StringBuffer(uri2.toString()) ).once();
+ EasyMock.expect(inboundRequest.getAttribute("dispatch.ha.failover.counter")).andReturn(new AtomicInteger(0)).once();
+ EasyMock.expect(inboundRequest.getAttribute("dispatch.ha.failover.counter")).andReturn(new AtomicInteger(1)).once();
+
+ HttpServletResponse outboundResponse = EasyMock.createNiceMock(HttpServletResponse.class);
+ EasyMock.expect(outboundResponse.getOutputStream()).andAnswer( new IAnswer<SynchronousServletOutputStreamAdapter>() {
+ @Override
+ public SynchronousServletOutputStreamAdapter answer() throws Throwable {
+ return new SynchronousServletOutputStreamAdapter() {
+ @Override
+ public void write( int b ) throws IOException {
+ throw new IOException( "unreachable-host" );
+ }
+ };
+ }
+ }).once();
+ EasyMock.replay(filterConfig, servletContext, outboundRequest, inboundRequest, outboundResponse);
+ Assert.assertEquals(uri1.toString(), provider.getActiveURL(serviceName));
+ DefaultHaDispatch dispatch = new DefaultHaDispatch();
- dispatch.setHttpClient(new DefaultHttpClient());
++ HttpClientBuilder builder = HttpClientBuilder.create();
++ CloseableHttpClient client = builder.build();
++ dispatch.setHttpClient(client);
+ dispatch.setHaProvider(provider);
+ dispatch.setServiceRole(serviceName);
+ dispatch.init();
+ long startTime = System.currentTimeMillis();
+ try {
+ dispatch.executeRequest(outboundRequest, inboundRequest, outboundResponse);
+ } catch (IOException e) {
+ //this is expected after the failover limit is reached
+ }
+ long elapsedTime = System.currentTimeMillis() - startTime;
+ Assert.assertEquals(uri2.toString(), provider.getActiveURL(serviceName));
+ //test to make sure the sleep took place
+ Assert.assertTrue(elapsedTime > 1000);
+ }
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/50f46e9e/gateway-provider-identity-assertion-common/src/main/java/org/apache/knox/gateway/identityasserter/common/function/UsernameFunctionProcessor.java
----------------------------------------------------------------------
diff --cc gateway-provider-identity-assertion-common/src/main/java/org/apache/knox/gateway/identityasserter/common/function/UsernameFunctionProcessor.java
index 7d3c4d0,0000000..25e1364
mode 100644,000000..100644
--- a/gateway-provider-identity-assertion-common/src/main/java/org/apache/knox/gateway/identityasserter/common/function/UsernameFunctionProcessor.java
+++ b/gateway-provider-identity-assertion-common/src/main/java/org/apache/knox/gateway/identityasserter/common/function/UsernameFunctionProcessor.java
@@@ -1,72 -1,0 +1,72 @@@
+/**
+ * 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.common.function;
+
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteEnvironment;
+import org.apache.knox.gateway.filter.rewrite.spi.UrlRewriteContext;
+import org.apache.knox.gateway.filter.rewrite.spi.UrlRewriteFunctionProcessor;
+import org.apache.knox.gateway.i18n.GatewaySpiMessages;
+import org.apache.knox.gateway.i18n.messages.MessagesFactory;
+import org.apache.knox.gateway.security.SubjectUtils;
+
+import javax.security.auth.Subject;
+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 ) {
++ } else if( parameters != null && !parameters.isEmpty() ) {
+ results = new ArrayList<String>( 1 );
+ results.add( parameters.get( 0 ) );
+ }
+ return results;
+ }
+
+}
+
http://git-wip-us.apache.org/repos/asf/knox/blob/50f46e9e/gateway-provider-identity-assertion-hadoop-groups/src/test/java/org/apache/knox/gateway/identityasserter/hadoop/groups/filter/HadoopGroupProviderFilterTest.java
----------------------------------------------------------------------
diff --cc gateway-provider-identity-assertion-hadoop-groups/src/test/java/org/apache/knox/gateway/identityasserter/hadoop/groups/filter/HadoopGroupProviderFilterTest.java
index d5f5501,0000000..91806fd
mode 100644,000000..100644
--- a/gateway-provider-identity-assertion-hadoop-groups/src/test/java/org/apache/knox/gateway/identityasserter/hadoop/groups/filter/HadoopGroupProviderFilterTest.java
+++ b/gateway-provider-identity-assertion-hadoop-groups/src/test/java/org/apache/knox/gateway/identityasserter/hadoop/groups/filter/HadoopGroupProviderFilterTest.java
@@@ -1,218 -1,0 +1,218 @@@
+/**
+ * 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.hadoop.groups.filter;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.hamcrest.MatcherAssert.assertThat;
+
+import java.security.Principal;
+import java.util.Arrays;
++import java.util.Collections;
+import java.util.List;
- import java.util.Vector;
+
+import javax.security.auth.Subject;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+
+import org.apache.knox.gateway.security.PrimaryPrincipal;
+import org.apache.hadoop.security.LdapGroupsMapping;
+import org.apache.hadoop.security.ShellBasedUnixGroupsMapping;
+import org.easymock.EasyMock;
+import org.junit.Test;
+
+/**
+ * Test for {@link HadoopGroupProviderFilter}
- *
++ *
+ * @since 0.11.0
+ */
+public class HadoopGroupProviderFilterTest {
+
+ /**
+ * System username
+ */
+ private static final String failUsername = "highly_unlikely_username_to_have";
+
+ /**
+ * System username
+ */
+ private static final String username = System.getProperty("user.name");
+
+ /**
+ * Configuration object needed by for hadoop classes
+ */
+
+ /**
+ * Hadoop Groups implementation.
+ */
+
+ /* create an instance */
+ public HadoopGroupProviderFilterTest() {
+ super();
+ }
+
+ /**
+ * Test that valid groups are retrieved for a legitimate user.
- *
++ *
+ * @throws ServletException
+ */
+ @Test
+ public void testGroups() throws ServletException {
+
+ final 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 );
+
+ final HadoopGroupProviderFilter filter = new HadoopGroupProviderFilter();
+
+ final Subject subject = new Subject();
+ subject.getPrincipals().add(new PrimaryPrincipal(username));
+
+ filter.init(config);
+ final String principal = filter.mapUserPrincipal(
+ ((Principal) subject.getPrincipals(PrimaryPrincipal.class).toArray()[0])
+ .getName());
+ final String[] groups = filter.mapGroupPrincipals(principal, subject);
+
+ assertThat(principal, is(username));
+ assertThat(
+ "No groups assosciated with the user, most likely this is a failure, it is only OK when 'bash -c groups' command returns 0 groups. ",
+ groups.length > 0);
+
+ }
+
+ /**
+ * Test that no groups are retrieved for a dummy user.
- *
++ *
+ * @throws ServletException
+ */
+ @Test
+ public void testUnknownUser() throws ServletException {
+
+ final 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 );
+
+ final HadoopGroupProviderFilter filter = new HadoopGroupProviderFilter();
+
+ final Subject subject = new Subject();
+ subject.getPrincipals().add(new PrimaryPrincipal(failUsername));
+
+ filter.init(config);
+ final String principal = filter.mapUserPrincipal(
+ ((Principal) subject.getPrincipals(PrimaryPrincipal.class).toArray()[0])
+ .getName());
+ final String[] groups = filter.mapGroupPrincipals(principal, subject);
+
+ assertThat(principal, is(failUsername));
+ assertThat(
+ "Somehow groups were found for this user, how is it possible ! check 'bash -c groups' command ",
+ groups.length == 0);
+
+ }
+
+ /**
+ * Test for a bad config (nonexistent). This test proves, we are not falling
+ * back on {@link ShellBasedUnixGroupsMapping} because we explicitly use
+ * {@link LdapGroupsMapping} and in case of bad config we get empty groups
+ * (Hadoop way).
- *
++ *
+ * @throws ServletException
+ */
+ @SuppressWarnings({ "unchecked", "rawtypes" })
+ @Test
+ public void badConfigTest() throws ServletException {
+
+ final List<String> keysList = Arrays.asList("hadoop.security.group.mapping",
+ "hadoop.security.group.mapping.ldap.bind.user",
+ "hadoop.security.group.mapping.ldap.bind.password",
+ "hadoop.security.group.mapping.ldap.url",
+ "hadoop.security.group.mapping.ldap.search.filter.group",
+ "hadoop.security.group.mapping.ldap.search.attr.member",
+ "hadoop.security.group.mapping.ldap.search.filter.user");
+
+ final 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.expect(config.getInitParameter("hadoop.security.group.mapping"))
+ .andReturn("org.apache.hadoop.security.LdapGroupsMapping").anyTimes();
+ EasyMock
+ .expect(config
+ .getInitParameter("hadoop.security.group.mapping.ldap.bind.user"))
+ .andReturn("uid=dummy,ou=people,dc=hadoop,dc=apache,dc=org").anyTimes();
+ EasyMock
+ .expect(config.getInitParameter(
+ "hadoop.security.group.mapping.ldap.bind.password"))
+ .andReturn("unbind-me-please").anyTimes();
+ EasyMock
+ .expect(
+ config.getInitParameter("hadoop.security.group.mapping.ldap.url"))
+ .andReturn("ldap://nomansland:33389").anyTimes();
+ EasyMock
+ .expect(config.getInitParameter(
+ "hadoop.security.group.mapping.ldap.search.filter.group"))
+ .andReturn("(objectclass=groupOfNames)").anyTimes();
+ EasyMock
+ .expect(config.getInitParameter(
+ "hadoop.security.group.mapping.ldap.search.attr.member"))
+ .andReturn("member").anyTimes();
+ EasyMock
+ .expect(config.getInitParameter(
+ "hadoop.security.group.mapping.ldap.search.filter.user"))
+ .andReturn(
+ "(&(|(objectclass=person)(objectclass=applicationProcess))(cn={0}))")
+ .anyTimes();
+ EasyMock.expect(config.getInitParameterNames())
- .andReturn(new Vector(keysList).elements()).anyTimes();
++ .andReturn(Collections.enumeration((keysList))).anyTimes();
+
+ EasyMock.replay( config );
+ EasyMock.replay( context );
+
+ final HadoopGroupProviderFilter filter = new HadoopGroupProviderFilter();
+
+ final Subject subject = new Subject();
+ subject.getPrincipals().add(new PrimaryPrincipal(username));
+
+ filter.init(config);
+ final String principal = filter.mapUserPrincipal(
+ ((Principal) subject.getPrincipals(PrimaryPrincipal.class).toArray()[0])
+ .getName());
+ final String[] groups = filter.mapGroupPrincipals(principal, subject);
+
+ assertThat(principal, is(username));
+
+ /*
+ * Unfortunately, Hadoop does not let us know what went wrong all we get is
+ * empty groups
+ */
+ assertThat(groups.length, is(0));
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/50f46e9e/gateway-provider-identity-assertion-switchcase/src/main/java/org/apache/knox/gateway/identityasserter/switchcase/SwitchCaseIdentityAssertionFilter.java
----------------------------------------------------------------------
diff --cc gateway-provider-identity-assertion-switchcase/src/main/java/org/apache/knox/gateway/identityasserter/switchcase/SwitchCaseIdentityAssertionFilter.java
index 9405c49,0000000..01e874d
mode 100644,000000..100644
--- a/gateway-provider-identity-assertion-switchcase/src/main/java/org/apache/knox/gateway/identityasserter/switchcase/SwitchCaseIdentityAssertionFilter.java
+++ b/gateway-provider-identity-assertion-switchcase/src/main/java/org/apache/knox/gateway/identityasserter/switchcase/SwitchCaseIdentityAssertionFilter.java
@@@ -1,98 -1,0 +1,98 @@@
+/**
+ * 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.switchcase;
+
+import java.util.Set;
+import javax.security.auth.Subject;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+
+import org.apache.knox.gateway.identityasserter.common.filter.CommonIdentityAssertionFilter;
+import org.apache.knox.gateway.security.GroupPrincipal;
+
+public class SwitchCaseIdentityAssertionFilter extends
+ CommonIdentityAssertionFilter {
+
+ private static final String USER_INIT_PARAM = "principal.case";
+ private static final String GROUP_INIT_PARAM = "group.principal.case";
+
+ private enum SwitchCase { UPPER, LOWER, NONE }
+
+ private SwitchCase userCase = SwitchCase.LOWER;
+ private SwitchCase groupCase = SwitchCase.LOWER;
+
+ @Override
+ public void init( FilterConfig filterConfig ) throws ServletException {
+ super.init(filterConfig);
+
+ String s;
+ s = filterConfig.getInitParameter( USER_INIT_PARAM );
+ if ( s != null ) {
+ s = s.trim().toUpperCase();
+ try {
+ userCase = SwitchCase.valueOf( s );
+ groupCase = userCase;
+ } catch ( IllegalArgumentException e ) {
+ // Ignore it and use the default.
+ }
+ }
+ s = filterConfig.getInitParameter( GROUP_INIT_PARAM );
+ if ( s != null ) {
+ s = s.trim().toUpperCase();
+ try {
+ groupCase = SwitchCase.valueOf( s );
+ } catch ( IllegalArgumentException e ) {
+ // Ignore it and use the default.
+ }
+ }
+ }
+
+ @Override
+ public String mapUserPrincipal( String principalName ) {
+ return switchCase( principalName, userCase );
+ }
+
+ @Override
+ public String[] mapGroupPrincipals( String mappedPrincipalName, Subject subject ) {
+ String[] groupNames = null;
+ if ( groupCase != SwitchCase.NONE ) {
+ Set<GroupPrincipal> groups = subject.getPrincipals( GroupPrincipal.class );
- if( groups != null && groups.size() > 0 ) {
++ if( groups != null && !groups.isEmpty() ) {
+ groupNames = new String[ groups.size() ];
+ int i = 0;
+ for( GroupPrincipal group : groups ) {
+ groupNames[ i++ ] = switchCase( group.getName(), groupCase );
+ }
+ }
+ }
+ return groupNames;
+ }
+
+ private String switchCase( String name, SwitchCase switchCase ) {
+ if ( name != null ) {
+ switch( switchCase ) {
+ case UPPER:
+ return name.toUpperCase();
+ case LOWER:
+ return name.toLowerCase();
+ }
+ }
+ return name;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/50f46e9e/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/FrontendFunctionProcessor.java
----------------------------------------------------------------------
diff --cc gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/FrontendFunctionProcessor.java
index 5964510,0000000..77ca25e
mode 100644,000000..100644
--- a/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/FrontendFunctionProcessor.java
+++ b/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/FrontendFunctionProcessor.java
@@@ -1,125 -1,0 +1,125 @@@
+/**
+ * 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.filter.rewrite.impl;
+
+import org.apache.knox.gateway.filter.rewrite.api.FrontendFunctionDescriptor;
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteEnvironment;
+import org.apache.knox.gateway.filter.rewrite.i18n.UrlRewriteResources;
+import org.apache.knox.gateway.filter.rewrite.spi.UrlRewriteContext;
+import org.apache.knox.gateway.filter.rewrite.spi.UrlRewriteFunctionProcessor;
+import org.apache.knox.gateway.filter.rewrite.spi.UrlRewriteResolver;
+import org.apache.knox.gateway.i18n.resources.ResourcesFactory;
+import org.apache.knox.gateway.services.GatewayServices;
+
+import java.net.URI;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+public class FrontendFunctionProcessor implements UrlRewriteFunctionProcessor<FrontendFunctionDescriptor> {
+
+ private static UrlRewriteResources RES = ResourcesFactory.get( UrlRewriteResources.class );
+
+ private Map<String,UrlRewriteResolver> resolvers;
+
+ @Override
+ public String name() {
+ return FrontendFunctionDescriptor.FUNCTION_NAME;
+ }
+
+ @Override
+ public void initialize( UrlRewriteEnvironment environment, FrontendFunctionDescriptor descriptor ) throws Exception {
+ if( environment == null ) {
+ throw new IllegalArgumentException( "environment==null" );
+ }
+ URI frontend = environment.getAttribute( FrontendFunctionDescriptor.FRONTEND_URI_ATTRIBUTE );
+ resolvers = new HashMap<>();
+ if( frontend == null ) {
+ resolvers.put( "url", new ParamResolver( "gateway.url" ) );
+ resolvers.put( "addr", new ParamResolver( "gateway.addr" ) );
+ resolvers.put( "scheme", new ParamResolver( "gateway.scheme" ) );
+ resolvers.put( "host", new ParamResolver( "gateway.host" ) );
+ resolvers.put( "port", new ParamResolver( "gateway.port" ) );
+ resolvers.put( "path", new ParamResolver( "gateway.path" ) );
+ } else {
+ resolvers.put( "url", new FixedResolver( frontend.toString() ) );
+ resolvers.put( "addr", new FixedResolver( frontend.getHost() + ":" + frontend.getPort() ) );
+ resolvers.put( "scheme", new FixedResolver( frontend.getScheme() ) );
+ resolvers.put( "host", new FixedResolver( frontend.getHost() ) );
+ resolvers.put( "port", new FixedResolver( Integer.toString( frontend.getPort() ) ) );
+ resolvers.put( "path", new FixedResolver( frontend.getPath() ) );
+ }
+ resolvers.put( "topology", new FixedResolver( (String)environment.getAttribute(GatewayServices.GATEWAY_CLUSTER_ATTRIBUTE) ) );
+ resolvers.put( "address", resolvers.get( "addr" ) );
+ }
+
+ @Override
+ public void destroy() throws Exception {
+ resolvers.clear();
+ }
+
+ @Override
+ public List<String> resolve( UrlRewriteContext context, List<String> parameters ) throws Exception {
+ String parameter = "url";
- if( parameters != null && parameters.size() > 0 ) {
++ if( parameters != null && !parameters.isEmpty() ) {
+ String first = parameters.get( 0 );
+ if( first != null ) {
+ parameter = first;
+ }
+ }
+ parameter = parameter.trim().toLowerCase();
+ UrlRewriteResolver resolver = resolvers.get( parameter );
+ if( resolver == null ) {
+ throw new IllegalArgumentException( RES.invalidFrontendFunctionParameter( parameter ) );
+ }
+ List<String> results = resolver.resolve( context, parameters );
+ return results;
+ }
+
+ private static class ParamResolver implements UrlRewriteResolver {
+
+ private String paramName;
+
+ private ParamResolver( String paramName ) {
+ this.paramName = paramName;
+ }
+
+ @Override
+ public List<String> resolve( UrlRewriteContext context, List<String> parameter ) throws Exception {
+ return context.getParameters().resolve( paramName );
+ }
+
+ }
+
+ private static class FixedResolver implements UrlRewriteResolver {
+
+ private List<String> fixedValues;
+
+ private FixedResolver( String... fixedValues ) {
+ this.fixedValues = Arrays.asList( fixedValues );
+ }
+
+ @Override
+ public List<String> resolve( UrlRewriteContext context, List<String> parameter ) throws Exception {
+ return fixedValues;
+ }
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/50f46e9e/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/html/HtmlImportFunctionProcessor.java
----------------------------------------------------------------------
diff --cc gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/html/HtmlImportFunctionProcessor.java
index 280f1b5,0000000..0b3b3c6
mode 100644,000000..100644
--- a/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/html/HtmlImportFunctionProcessor.java
+++ b/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/html/HtmlImportFunctionProcessor.java
@@@ -1,90 -1,0 +1,90 @@@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.filter.rewrite.impl.html;
+
+import org.apache.knox.gateway.filter.rewrite.api.FrontendFunctionDescriptor;
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteEnvironment;
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteFunctionDescriptor;
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteFunctionDescriptorFactory;
+import org.apache.knox.gateway.filter.rewrite.impl.UrlRewriteFunctionProcessorFactory;
+import org.apache.knox.gateway.filter.rewrite.spi.UrlRewriteContext;
+import org.apache.knox.gateway.filter.rewrite.spi.UrlRewriteFunctionProcessor;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * This function enhances the 'frontend' function with the ability to add a prefix to the rewritten frontend portion
+ * along with the '@import' literal. This is a workaround for the requirement to provide the ability to rewrite
+ * a portion of html content that contains a tag like the following
+ *
+ * <head> <style type=\"text/css\">@import "pretty.css";</style></head>
+ *
+ * and needs to be rewritten to something like
+ *
+ * <head> <style type=\"text/css\">@import "http://localhost:8443/sandbox/service/pretty.css";</style></head>
+ *
+ * The rewrite rule could then contain the $import function that would delegate to the frontend function.
+ *
+ * If there are more than one params passed, the first one is used as a prefix to the value of the frontend function.
+ *
+ */
+public class HtmlImportFunctionProcessor implements UrlRewriteFunctionProcessor<HtmlImportFunctionDescriptor> {
+
+ private static final String IMPORT_LITERAL = "@import";
+
+ private UrlRewriteFunctionProcessor frontend;
+
+ @Override
+ public void initialize(UrlRewriteEnvironment environment, HtmlImportFunctionDescriptor descriptor) throws Exception {
+ UrlRewriteFunctionDescriptor frontendDescriptor = UrlRewriteFunctionDescriptorFactory
+ .create(FrontendFunctionDescriptor.FUNCTION_NAME);
+ frontend = UrlRewriteFunctionProcessorFactory.create(FrontendFunctionDescriptor.FUNCTION_NAME, frontendDescriptor);
+ frontend.initialize(environment, frontendDescriptor);
+ }
+
+ @Override
+ public void destroy() throws Exception {
+ frontend.destroy();
+ }
+
+ @Override
+ public List<String> resolve(UrlRewriteContext context, List<String> parameters) throws Exception {
+ String prefix = "";
+ if ( parameters != null && parameters.size() > 1 ) {
+ prefix = parameters.get(0);
+ parameters = parameters.subList(1, parameters.size());
+ }
+ List<String> frontendValues = frontend.resolve(context, parameters);
+ StringBuffer buffer = new StringBuffer(IMPORT_LITERAL);
+ buffer.append(" ");
+ buffer.append(prefix);
- if ( frontendValues != null && frontendValues.size() > 0 ) {
++ if ( frontendValues != null && !frontendValues.isEmpty() ) {
+ for ( String value : frontendValues ) {
+ buffer.append(value);
+ }
+ }
+ return Arrays.asList(buffer.toString());
+ }
+
+ @Override
+ public String name() {
+ return HtmlImportFunctionDescriptor.FUNCTION_NAME;
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/50f46e9e/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/html/HtmlPrefixProcessor.java
----------------------------------------------------------------------
diff --cc gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/html/HtmlPrefixProcessor.java
index d7983ef,0000000..7fe26ad
mode 100644,000000..100644
--- a/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/html/HtmlPrefixProcessor.java
+++ b/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/html/HtmlPrefixProcessor.java
@@@ -1,104 -1,0 +1,104 @@@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.filter.rewrite.impl.html;
+
+import org.apache.knox.gateway.filter.rewrite.api.FrontendFunctionDescriptor;
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteEnvironment;
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteFunctionDescriptor;
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteFunctionDescriptorFactory;
+import org.apache.knox.gateway.filter.rewrite.impl.UrlRewriteFunctionProcessorFactory;
+import org.apache.knox.gateway.filter.rewrite.spi.UrlRewriteContext;
+import org.apache.knox.gateway.filter.rewrite.spi.UrlRewriteFunctionProcessor;
+
+import java.util.Arrays;
+import java.util.List;
+
+/**
+ * This function enhances the 'frontend' function with the ability to add a
+ * prefix to the rewritten frontend portion along with the literals
+ * provided as an argument.
+ * <p>
+ * <div ng-include src=\"'components/navbar/navbar.html?v=1498928142479'\"></div>
+ * <p>
+ * and needs to be rewritten to something like
+ * <p>
+ * <div ng-include src=\"'http://localhost:8443/sandbox/service/components/navbar/navbar.html?v=1498928142479'\"></div>
+ * <p>
+ * The rewrite rule could then contain the $prefix function that would delegate
+ * to the frontend function.
+ * <p>
+ * The parameter to the function would be the symbol used as a prefix.
+ */
+
+public class HtmlPrefixProcessor
+ implements UrlRewriteFunctionProcessor<HtmlPrefixDescriptor> {
+
+ private UrlRewriteFunctionProcessor frontend;
+
+ /**
+ * Create an instance
+ */
+ public HtmlPrefixProcessor() {
+ super();
+ }
+
+ @Override
+ public void initialize(final UrlRewriteEnvironment environment,
+ final HtmlPrefixDescriptor descriptor) throws Exception {
+
+ final UrlRewriteFunctionDescriptor frontendDescriptor = UrlRewriteFunctionDescriptorFactory
+ .create(FrontendFunctionDescriptor.FUNCTION_NAME);
+
+ frontend = UrlRewriteFunctionProcessorFactory
+ .create(FrontendFunctionDescriptor.FUNCTION_NAME, frontendDescriptor);
+
+ frontend.initialize(environment, frontendDescriptor);
+ }
+
+ @Override
+ public String name() {
+ return HtmlPrefixDescriptor.FUNCTION_NAME;
+ }
+
+ @Override
+ public void destroy() throws Exception {
+ frontend.destroy();
+ }
+
+ @Override
+ public List<String> resolve(UrlRewriteContext context,
+ List<String> parameters) throws Exception {
+ String prefix = "";
+
+ if ((parameters != null) && (parameters.size() > 1)) {
+ prefix = parameters.get(0);
+ parameters = parameters.subList(1, parameters.size());
+ }
+
+ final List<String> frontendValues = frontend.resolve(context, parameters);
+
+ final StringBuffer buffer = new StringBuffer();
+ buffer.append(prefix);
- if (frontendValues != null && frontendValues.size() > 0) {
++ if (frontendValues != null && !frontendValues.isEmpty()) {
+ for (final String value : frontendValues) {
+ buffer.append(value);
+ }
+ }
+
+ return Arrays.asList(buffer.toString());
+ }
+}
http://git-wip-us.apache.org/repos/asf/knox/blob/50f46e9e/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/json/JsonFilterReader.java
----------------------------------------------------------------------
diff --cc gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/json/JsonFilterReader.java
index 8286dbc,0000000..dfceb42
mode 100644,000000..100644
--- a/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/json/JsonFilterReader.java
+++ b/gateway-provider-rewrite/src/main/java/org/apache/knox/gateway/filter/rewrite/impl/json/JsonFilterReader.java
@@@ -1,644 -1,0 +1,644 @@@
+/**
+ * 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.filter.rewrite.impl.json;
+
+import com.fasterxml.jackson.core.JsonFactory;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonToken;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.fasterxml.jackson.databind.node.TextNode;
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteFilterApplyDescriptor;
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteFilterBufferDescriptor;
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteFilterContentDescriptor;
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteFilterDetectDescriptor;
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteFilterGroupDescriptor;
+import org.apache.knox.gateway.filter.rewrite.api.UrlRewriteFilterPathDescriptor;
+import org.apache.knox.gateway.filter.rewrite.i18n.UrlRewriteMessages;
+import org.apache.knox.gateway.i18n.messages.MessagesFactory;
+import org.apache.knox.gateway.util.JsonPath;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.io.StringWriter;
+import java.util.List;
+import java.util.Stack;
+import java.util.regex.Pattern;
+
+class JsonFilterReader extends Reader {
+
+ private static final UrlRewriteMessages LOG = MessagesFactory.get( UrlRewriteMessages.class );
+
+ private static final UrlRewriteFilterPathDescriptor.Compiler<JsonPath.Expression> JPATH_COMPILER = new JsonPathCompiler();
+ private static final UrlRewriteFilterPathDescriptor.Compiler<Pattern> REGEX_COMPILER = new RegexCompiler();
+
+ private JsonFactory factory;
+ private JsonParser parser;
+ private JsonGenerator generator;
+ private ObjectMapper mapper;
+
+ private Reader reader;
+ private int offset;
+ private StringWriter writer;
+ private StringBuffer buffer;
+ private Stack<Level> stack;
+ private Level bufferingLevel;
+ private UrlRewriteFilterBufferDescriptor bufferingConfig;
+ private UrlRewriteFilterGroupDescriptor config;
+
+
+ public JsonFilterReader( Reader reader, UrlRewriteFilterContentDescriptor config ) throws IOException {
+ this.reader = reader;
+ factory = new JsonFactory();
+ mapper = new ObjectMapper();
+ parser = factory.createParser( reader );
+ writer = new StringWriter();
+ buffer = writer.getBuffer();
+ offset = 0;
+ generator = factory.createGenerator( writer );
+ stack = new Stack<Level>();
+ bufferingLevel = null;
+ bufferingConfig = null;
+ this.config = config;
+ }
+
+ @Override
+ public int read( char[] destBuffer, int destOffset, int destCount ) throws IOException {
+ int count = 0;
+ int available = buffer.length() - offset;
+
+ if( available == 0 ) {
+ JsonToken token = parser.nextToken();
+ if( token == null ) {
+ count = -1;
+ } else {
+ processCurrentToken();
+ available = buffer.length() - offset;
+ }
+ }
+
+ if( available > 0 ) {
+ count = Math.min( destCount, available );
+ buffer.getChars( offset, offset+count, destBuffer, destOffset );
+ offset += count;
+ if( offset == buffer.length() ) {
+ offset = 0;
+ buffer.setLength( 0 );
+ }
+ }
+
+ return count;
+ }
+
+ private void processCurrentToken() throws IOException {
+ switch( parser.getCurrentToken() ) {
+ case START_OBJECT:
+ processStartObject();
+ break;
+ case END_OBJECT:
+ processEndObject();
+ break;
+ case START_ARRAY:
+ processStartArray();
+ break;
+ case END_ARRAY:
+ processEndArray();
+ break;
+ case FIELD_NAME:
+ processFieldName(); // Could be the name of an object, array or value.
+ break;
+ case VALUE_STRING:
+ processValueString();
+ break;
+ case VALUE_NUMBER_INT:
+ case VALUE_NUMBER_FLOAT:
+ processValueNumber();
+ break;
+ case VALUE_TRUE:
+ case VALUE_FALSE:
+ processValueBoolean();
+ break;
+ case VALUE_NULL:
+ processValueNull();
+ break;
+ case NOT_AVAILABLE:
+ // Ignore it.
+ break;
+ }
+ generator.flush();
+ }
+
+ private Level pushLevel( String field, JsonNode node, JsonNode scopeNode, UrlRewriteFilterGroupDescriptor scopeConfig ) {
+ if( !stack.isEmpty() ) {
+ Level top = stack.peek();
+ if( scopeNode == null ) {
+ scopeNode = top.scopeNode;
+ scopeConfig = top.scopeConfig;
+ }
+ }
+ Level level = new Level( field, node, scopeNode, scopeConfig );
+ stack.push( level );
+ return level;
+ }
+
+ private void processStartObject() throws IOException {
+ JsonNode node;
+ Level child;
+ Level parent;
+ if( stack.isEmpty() ) {
+ node = mapper.createObjectNode();
+ child = pushLevel( null, node, node, config );
+ } else {
+ child = stack.peek();
+ if( child.node == null ) {
+ child.node = mapper.createObjectNode();
+ parent = stack.get( stack.size()-2 );
+ switch( parent.node.asToken() ) {
+ case START_ARRAY:
+ ((ArrayNode)parent.node ).add( child.node );
+ break;
+ case START_OBJECT:
+ ((ObjectNode)parent.node ).put( child.field, child.node );
+ break;
+ default:
+ throw new IllegalStateException();
+ }
+ } else if( child.isArray() ) {
+ parent = child;
+ node = mapper.createObjectNode();
+ child = pushLevel( null, node, null, null );
+ ((ArrayNode)parent.node ).add( child.node );
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+ if( bufferingLevel == null ) {
+ if( !startBuffering( child ) ) {
+ generator.writeStartObject();
+ }
+ }
+ }
+
+ private void processEndObject() throws IOException {
+ Level child;
+ Level parent;
+ child = stack.pop();
+ if( bufferingLevel == child ) {
+ filterBufferedNode( child );
+ mapper.writeTree( generator, child.node );
+ bufferingLevel = null;
+ bufferingConfig = null;
+ } else if( bufferingLevel == null ) {
+ generator.writeEndObject();
+ if( !stack.isEmpty() ) {
+ parent = stack.peek();
+ switch( parent.node.asToken() ) {
+ case START_ARRAY:
+ ((ArrayNode)parent.node ).removeAll();
+ break;
+ case START_OBJECT:
+ ((ObjectNode)parent.node ).removeAll();
+ break;
+ default:
+ throw new IllegalStateException();
+ }
+ }
+ }
+ }
+
+ private void processStartArray() throws IOException {
+ JsonNode node;
+ Level child;
+ Level parent;
+ if( stack.isEmpty() ) {
+ node = mapper.createArrayNode();
+ child = pushLevel( null, node, node, config );
+ } else {
+ child = stack.peek();
+ if( child.node == null ) {
+ child.node = mapper.createArrayNode();
+ parent = stack.get( stack.size() - 2 );
+ switch( parent.node.asToken() ) {
+ case START_ARRAY:
+ ((ArrayNode)parent.node ).add( child.node );
+ break;
+ case START_OBJECT:
+ ((ObjectNode)parent.node ).put( child.field, child.node );
+ break;
+ default:
+ throw new IllegalStateException();
+ }
+ } else if( child.isArray() ) {
+ parent = child;
+ child = pushLevel( null, mapper.createArrayNode(), null, null );
+ ((ArrayNode)parent.node ).add( child.node );
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+ if( bufferingLevel == null ) {
+ if( !startBuffering( child ) ) {
+ generator.writeStartArray();
+ }
+ }
+ }
+
+ private void processEndArray() throws IOException {
+ Level child;
+ Level parent;
+ child = stack.pop();
+ if( bufferingLevel == child ) {
+ filterBufferedNode( child );
+ mapper.writeTree( generator, child.node );
+ bufferingLevel = null;
+ bufferingConfig = null;
+ } else if( bufferingLevel == null ) {
+ generator.writeEndArray();
+ if( !stack.isEmpty() ) {
+ parent = stack.peek();
+ switch( parent.node.asToken() ) {
+ case START_ARRAY:
+ ((ArrayNode)parent.node ).removeAll();
+ break;
+ case START_OBJECT:
+ ((ObjectNode)parent.node ).removeAll();
+ break;
+ default:
+ throw new IllegalStateException();
+ }
+ }
+ }
+ }
+
+ private void processFieldName() throws IOException {
+ Level child = pushLevel( parser.getCurrentName(), null, null, null );
+ try {
+ child.field = filterFieldName( child.field );
+ } catch( Exception e ) {
+ LOG.failedToFilterFieldName( child.field, e );
+ // Write original name.
+ }
+ if( bufferingLevel == null ) {
+ generator.writeFieldName( child.field );
+ }
+ }
+
+ private void processValueString() throws IOException {
+ Level child;
+ Level parent;
+ String value = null;
+ parent = stack.peek();
+ if( parent.isArray() ) {
+ ArrayNode array = (ArrayNode)parent.node;
+ array.add( parser.getText() );
+ if( bufferingLevel == null ) {
+ value = filterStreamValue( parent );
+ array.set( array.size()-1, new TextNode( value ) );
+ } else {
+ array.removeAll();
+ }
+ } else {
+ child = stack.pop();
+ parent = stack.peek();
+ ((ObjectNode)parent.node ).put( child.field, parser.getText() );
+ if( bufferingLevel == null ) {
+ child.node = parent.node; // Populate the JsonNode of the child for filtering.
+ value = filterStreamValue( child );
+ }
+ }
+ if( bufferingLevel == null ) {
+ if( parent.node.isArray() ) {
+ ((ArrayNode)parent.node).removeAll();
+ } else {
+ ((ObjectNode)parent.node).removeAll();
+ }
+ generator.writeString( value );
+ }
+ }
+
+ private void processValueNumber() throws IOException {
+ Level child;
+ Level parent;
+ parent = stack.peek();
+ if( parent.isArray() ) {
+ if( bufferingLevel != null ) {
+ ArrayNode array = (ArrayNode)parent.node;
+ processBufferedArrayValueNumber( array );
+ }
+ } else {
+ child = stack.pop();
+ if( bufferingLevel != null ) {
+ parent = stack.peek();
+ ObjectNode object = (ObjectNode)parent.node;
+ processBufferedFieldValueNumber( child, object );
+ }
+ }
+ if( bufferingLevel == null ) {
+ processedUnbufferedValueNumber();
+ }
+ }
+
+ private void processedUnbufferedValueNumber() throws IOException {
+ switch( parser.getNumberType() ) {
+ case INT:
+ generator.writeNumber( parser.getIntValue() );
+ break;
+ case LONG:
+ generator.writeNumber( parser.getLongValue() );
+ break;
+ case BIG_INTEGER:
+ generator.writeNumber( parser.getBigIntegerValue() );
+ break;
+ case FLOAT:
+ generator.writeNumber( parser.getFloatValue() );
+ break;
+ case DOUBLE:
+ generator.writeNumber( parser.getDoubleValue() );
+ break;
+ case BIG_DECIMAL:
+ generator.writeNumber( parser.getDecimalValue() );
+ break;
+ }
+ }
+
+ private void processBufferedFieldValueNumber( Level child, ObjectNode object ) throws IOException {
+ //object.put( child.field, parser.getDecimalValue() );
+ switch( parser.getNumberType() ) {
+ case INT:
+ object.put( child.field, parser.getIntValue() );
+ break;
+ case LONG:
+ object.put( child.field, parser.getLongValue() );
+ break;
+ case BIG_INTEGER:
+ object.put( child.field, parser.getDecimalValue() );
+ break;
+ case FLOAT:
+ object.put( child.field, parser.getFloatValue() );
+ break;
+ case DOUBLE:
+ object.put( child.field, parser.getDoubleValue() );
+ break;
+ case BIG_DECIMAL:
+ object.put( child.field, parser.getDecimalValue() );
+ break;
+ }
+ }
+
+ private void processBufferedArrayValueNumber( ArrayNode array ) throws IOException {
+ //array.add( parser.getDecimalValue() );
+ switch( parser.getNumberType() ) {
+ case INT:
+ array.add( parser.getIntValue() );
+ break;
+ case LONG:
+ array.add( parser.getLongValue() );
+ break;
+ case BIG_INTEGER:
+ array.add( parser.getDecimalValue() );
+ break;
+ case FLOAT:
+ array.add( parser.getFloatValue() );
+ break;
+ case DOUBLE:
+ array.add( parser.getDoubleValue() );
+ break;
+ case BIG_DECIMAL:
+ array.add( parser.getDecimalValue() );
+ break;
+ }
+ }
+
+ private void processValueBoolean() throws IOException {
+ Level child;
+ Level parent;
+ parent = stack.peek();
+ if( parent.isArray() ) {
+ ((ArrayNode)parent.node ).add( parser.getBooleanValue() );
+ //dump();
+ if( bufferingLevel == null ) {
+ ((ArrayNode)parent.node ).removeAll();
+ }
+ } else {
+ child = stack.pop();
+ parent = stack.peek();
+ ((ObjectNode)parent.node ).put( child.field, parser.getBooleanValue() );
+ //dump();
+ if( bufferingLevel == null ) {
+ ((ObjectNode)parent.node ).remove( child.field );
+ }
+ }
+ if( bufferingLevel == null ) {
+ generator.writeBoolean( parser.getBooleanValue() );
+ }
+ }
+
+ private void processValueNull() throws IOException {
+ Level child;
+ Level parent = stack.peek();
+ if( parent.isArray() ) {
+ ((ArrayNode)parent.node ).addNull();
+ //dump();
+ if( bufferingLevel == null ) {
+ ((ArrayNode)parent.node ).removeAll();
+ }
+ } else {
+ child = stack.pop();
+ parent = stack.peek();
+ ((ObjectNode)parent.node ).putNull( child.field );
+ //dump();
+ if( bufferingLevel == null ) {
+ ((ObjectNode)parent.node ).remove( child.field );
+ }
+ }
+ if( bufferingLevel == null ) {
+ generator.writeNull();
+ }
+ }
+
+ protected boolean startBuffering( Level node ) {
+ boolean buffered = false;
+ UrlRewriteFilterGroupDescriptor scope = node.scopeConfig;
+ if( scope != null ) {
+ for( UrlRewriteFilterPathDescriptor selector : scope.getSelectors() ) {
+ JsonPath.Expression path = (JsonPath.Expression)selector.compiledPath( JPATH_COMPILER );
+ List<JsonPath.Match> matches = path.evaluate( node.scopeNode );
- if( matches != null && matches.size() > 0 ) {
++ if( matches != null && !matches.isEmpty() ) {
+ if( selector instanceof UrlRewriteFilterBufferDescriptor ) {
+ bufferingLevel = node;
+ bufferingConfig = (UrlRewriteFilterBufferDescriptor)selector;
+ buffered = true;
+ }
+ break;
+ }
+ }
+ }
+ return buffered;
+ }
+
+ protected String filterStreamValue( Level node ) {
+ String value;
+ if( node.isArray() ) {
+ value = node.node.get( 0 ).asText();
+ } else {
+ value = node.node.get( node.field ).asText();
+ }
+ String rule = null;
+ UrlRewriteFilterGroupDescriptor scope = node.scopeConfig;
+ //TODO: Scan the top level apply rules for the first match.
+ if( scope != null ) {
+ for( UrlRewriteFilterPathDescriptor selector : scope.getSelectors() ) {
+ JsonPath.Expression path = (JsonPath.Expression)selector.compiledPath( JPATH_COMPILER );
+ List<JsonPath.Match> matches = path.evaluate( node.scopeNode );
- if( matches != null && matches.size() > 0 ) {
++ if( matches != null && !matches.isEmpty() ) {
+ JsonPath.Match match = matches.get( 0 );
+ if( match.getNode().isTextual() ) {
+ if( selector instanceof UrlRewriteFilterApplyDescriptor ) {
+ UrlRewriteFilterApplyDescriptor apply = (UrlRewriteFilterApplyDescriptor)selector;
+ rule = apply.rule();
+ break;
+ }
+ }
+ }
+ }
+ }
+ try {
+ value = filterValueString( node.field, value, rule );
+ if( node.isArray() ) {
+ ((ArrayNode)node.node).set( 0, new TextNode( value ) );
+ } else {
+ ((ObjectNode)node.node).put( node.field, value );
+ }
+ } catch( Exception e ) {
+ LOG.failedToFilterValue( value, rule, e );
+ }
+ return value;
+ }
+
+ private void filterBufferedNode( Level node ) {
+ for( UrlRewriteFilterPathDescriptor selector : bufferingConfig.getSelectors() ) {
+ JsonPath.Expression path = (JsonPath.Expression)selector.compiledPath( JPATH_COMPILER );
+ List<JsonPath.Match> matches = path.evaluate( node.node );
+ for( JsonPath.Match match : matches ) {
+ if( selector instanceof UrlRewriteFilterApplyDescriptor ) {
+ if( match.getNode().isTextual() ) {
+ filterBufferedValue( match, (UrlRewriteFilterApplyDescriptor)selector );
+ }
+ } else if( selector instanceof UrlRewriteFilterDetectDescriptor ) {
+ UrlRewriteFilterDetectDescriptor detectConfig = (UrlRewriteFilterDetectDescriptor)selector;
+ JsonPath.Expression detectPath = (JsonPath.Expression)detectConfig.compiledPath( JPATH_COMPILER );
+ List<JsonPath.Match> detectMatches = detectPath.evaluate( node.node );
+ for( JsonPath.Match detectMatch : detectMatches ) {
+ if( detectMatch.getNode().isTextual() ) {
+ String detectValue = detectMatch.getNode().asText();
+ Pattern detectPattern = detectConfig.compiledValue( REGEX_COMPILER );
+ if( detectPattern.matcher( detectValue ).matches() ) {
+ filterBufferedValues( node, detectConfig.getSelectors() );
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private void filterBufferedValues( Level node, List<UrlRewriteFilterPathDescriptor> selectors ) {
+ for( UrlRewriteFilterPathDescriptor selector : selectors ) {
+ JsonPath.Expression path = (JsonPath.Expression)selector.compiledPath( JPATH_COMPILER );
+ List<JsonPath.Match> matches = path.evaluate( node.node );
+ for( JsonPath.Match match : matches ) {
+ if( match.getNode().isTextual() ) {
+ if( selector instanceof UrlRewriteFilterApplyDescriptor ) {
+ filterBufferedValue( match, (UrlRewriteFilterApplyDescriptor)selector );
+ }
+ }
+ }
+ }
+ }
+
+ private void filterBufferedValue( JsonPath.Match match, UrlRewriteFilterApplyDescriptor apply ) {
+ String field = match.getField();
+ String value = match.getNode().asText();
+ try {
+ value = filterValueString( field, value, apply.rule() );
+ ((ObjectNode)match.getParent().getNode()).put( field, value );
+ } catch( Exception e ) {
+ LOG.failedToFilterValue( value, apply.rule(), e );
+ }
+ }
+
+ protected String filterFieldName( String field ) {
+ return field;
+ }
+
+ protected String filterValueString( String name, String value, String rule ) {
+ return value;
+ }
+
+ @Override
+ public void close() throws IOException {
+ generator.close();
+ writer.close();
+ parser.close();
+ reader.close();
+ }
+
+ private static class Level {
+ String field;
+ JsonNode node;
+ JsonNode scopeNode;
+ UrlRewriteFilterGroupDescriptor scopeConfig;
+ private Level( String field, JsonNode node, JsonNode scopeNode, UrlRewriteFilterGroupDescriptor scopeConfig ) {
+ this.field = field;
+ this.node = node;
+ this.scopeNode = scopeNode;
+ this.scopeConfig = scopeConfig;
+ }
+ public boolean isArray() {
+ return node != null && node.isArray();
+ }
+ }
+
+ private static class JsonPathCompiler implements UrlRewriteFilterPathDescriptor.Compiler<JsonPath.Expression> {
+ @Override
+ public JsonPath.Expression compile( String expression, JsonPath.Expression compiled ) {
+ return JsonPath.compile( expression );
+ }
+ }
+
+ private static class RegexCompiler implements UrlRewriteFilterPathDescriptor.Compiler<Pattern> {
+ @Override
+ public Pattern compile( String expression, Pattern compiled ) {
+ if( compiled != null ) {
+ return compiled;
+ } else {
+ return Pattern.compile( expression );
+ }
+ }
+ }
+
+// private void dump() throws IOException {
+// mapper.writeTree( factory.createGenerator( System.out ), stack.get( 0 ).node );
+// System.out.println();
+// }
+
+}
+
http://git-wip-us.apache.org/repos/asf/knox/blob/50f46e9e/gateway-provider-security-authz-acls/src/main/java/org/apache/knox/gateway/filter/AclsAuthorizationFilter.java
----------------------------------------------------------------------
diff --cc gateway-provider-security-authz-acls/src/main/java/org/apache/knox/gateway/filter/AclsAuthorizationFilter.java
index 0002974,0000000..f26c753
mode 100644,000000..100644
--- a/gateway-provider-security-authz-acls/src/main/java/org/apache/knox/gateway/filter/AclsAuthorizationFilter.java
+++ b/gateway-provider-security-authz-acls/src/main/java/org/apache/knox/gateway/filter/AclsAuthorizationFilter.java
@@@ -1,212 -1,0 +1,212 @@@
+/**
+ * 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.filter;
+
+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.knox.gateway.audit.api.Action;
+import org.apache.knox.gateway.audit.api.ActionOutcome;
+import org.apache.knox.gateway.audit.api.AuditServiceFactory;
+import org.apache.knox.gateway.audit.api.Auditor;
+import org.apache.knox.gateway.audit.api.ResourceType;
+import org.apache.knox.gateway.audit.log4j.audit.AuditConstants;
+import org.apache.knox.gateway.i18n.messages.MessagesFactory;
+import org.apache.knox.gateway.security.GroupPrincipal;
+import org.apache.knox.gateway.security.ImpersonatedPrincipal;
+import org.apache.knox.gateway.security.PrimaryPrincipal;
+
+import java.io.IOException;
+import java.security.AccessController;
+import java.security.Principal;
+
+public class AclsAuthorizationFilter implements Filter {
+ private static AclsAuthorizationMessages log = MessagesFactory.get( AclsAuthorizationMessages.class );
+ private static Auditor auditor = AuditServiceFactory.getAuditService().getAuditor( AuditConstants.DEFAULT_AUDITOR_NAME,
+ AuditConstants.KNOX_SERVICE_NAME, AuditConstants.KNOX_COMPONENT_NAME );
+
+ private String resourceRole = null;
+ private String aclProcessingMode = null;
+ private AclParser parser = new AclParser();
+
+
+ @Override
+ public void init(FilterConfig filterConfig) throws ServletException {
+ resourceRole = getInitParameter(filterConfig, "resource.role");
+ log.initializingForResourceRole(resourceRole);
+ aclProcessingMode = getInitParameter(filterConfig, resourceRole + ".acl.mode");
+ if (aclProcessingMode == null) {
+ aclProcessingMode = getInitParameter(filterConfig, "acl.mode");
+ if (aclProcessingMode == null) {
+ aclProcessingMode = "AND";
+ }
+ }
+ log.aclProcessingMode(aclProcessingMode);
+ String acls = getInitParameter(filterConfig, resourceRole + ".acl");
+ parser.parseAcls(resourceRole, acls);
+ }
+
+ private String getInitParameter(FilterConfig filterConfig, String paramName) {
+ return filterConfig.getInitParameter(paramName.toLowerCase());
+ }
+
+ public void destroy() {
+ }
+
+ public void doFilter(ServletRequest request, ServletResponse response,
+ FilterChain chain) throws IOException, ServletException {
+ boolean accessGranted = enforceAclAuthorizationPolicy(request, response, chain);
+ log.accessGranted(accessGranted);
+ String sourceUrl = (String)request.getAttribute( AbstractGatewayFilter.SOURCE_REQUEST_CONTEXT_URL_ATTRIBUTE_NAME );
+ if (accessGranted) {
+ auditor.audit( Action.AUTHORIZATION, sourceUrl, ResourceType.URI, ActionOutcome.SUCCESS );
+ chain.doFilter(request, response);
+ }
+ else {
+ auditor.audit( Action.AUTHORIZATION, sourceUrl, ResourceType.URI, ActionOutcome.FAILURE );
+ sendForbidden((HttpServletResponse) response);
+ }
+ }
+
+ private boolean enforceAclAuthorizationPolicy(ServletRequest request,
+ ServletResponse response, FilterChain chain) {
+ HttpServletRequest req = (HttpServletRequest) request;
+
+ // before enforcing acls check whether there are no acls defined
+ // which would mean that there are no restrictions
+ if (parser.users.size() == 0 && parser.groups.size() == 0 && parser.ipv.getIPAddresses().size() == 0) {
+ return true;
+ }
+
+ boolean userAccess = false;
+ boolean groupAccess = false;
+ boolean ipAddrAccess = false;
+
+ Subject subject = Subject.getSubject(AccessController.getContext());
+ Principal primaryPrincipal = (Principal)subject.getPrincipals(PrimaryPrincipal.class).toArray()[0];
+ log.primaryPrincipal(primaryPrincipal.getName());
+ Object[] impersonations = subject.getPrincipals(ImpersonatedPrincipal.class).toArray();
+ if (impersonations.length > 0) {
+ log.impersonatedPrincipal(((Principal)impersonations[0]).getName());
+ userAccess = checkUserAcls((Principal)impersonations[0]);
+ log.impersonatedPrincipalHasAccess(userAccess);
+ }
+ else {
+ userAccess = checkUserAcls(primaryPrincipal);
+ log.primaryPrincipalHasAccess(userAccess);
+ }
+ Object[] groups = subject.getPrincipals(GroupPrincipal.class).toArray();
+ if (groups.length > 0) {
+// System.out.println("GroupPrincipal: " + ((Principal)groups[0]).getName());
+ groupAccess = checkGroupAcls(groups);
+ log.groupPrincipalHasAccess(groupAccess);
+ }
+ else {
+ // if we have no groups in the subject then make
+ // it true if there is an anyGroup acl
+ // for AND mode and acls like *;*;127.0.0.* we need to
+ // make it pass
- if (parser.anyGroup && aclProcessingMode.equals("AND")) {
++ if (parser.anyGroup && "AND".equals(aclProcessingMode)) {
+ groupAccess = true;
+ }
+ }
+ log.remoteIPAddress(req.getRemoteAddr());
+ ipAddrAccess = checkRemoteIpAcls(req.getRemoteAddr());
+ log.remoteIPAddressHasAccess(ipAddrAccess);
+
- if (aclProcessingMode.equals("OR")) {
++ if ("OR".equals(aclProcessingMode)) {
+ // need to interpret '*' as excluded for OR semantics
+ // to make sense and not grant access to everyone by mistake.
+ // exclusion in OR is equivalent to denied
+ // so, let's set each one that contains '*' to false.
+ if (parser.anyUser) userAccess = false;
+ if (parser.anyGroup) groupAccess = false;
+ if (parser.ipv.allowsAnyIP()) ipAddrAccess = false;
+
+ return (userAccess || groupAccess || ipAddrAccess);
+ }
- else if (aclProcessingMode.equals("AND")) {
++ else if ("AND".equals(aclProcessingMode)) {
+ return (userAccess && groupAccess && ipAddrAccess);
+ }
+ return false;
+ }
+
+ private boolean checkRemoteIpAcls(String remoteAddr) {
+ boolean allowed = false;
+ if (remoteAddr == null) {
+ return false;
+ }
+ allowed = parser.ipv.validateIpAddress(remoteAddr);
+ return allowed;
+ }
+
+ private boolean checkUserAcls(Principal user) {
+ boolean allowed = false;
+ if (user == null) {
+ return false;
+ }
+ if (parser.anyUser) {
+ allowed = true;
+ }
+ else {
+ if (parser.users.contains(user.getName())) {
+ allowed = true;
+ }
+ }
+ return allowed;
+ }
+
+ private boolean checkGroupAcls(Object[] userGroups) {
+ boolean allowed = false;
+ if (userGroups == null) {
+ return false;
+ }
+ if (parser.anyGroup) {
+ allowed = true;
+ }
+ else {
+ for (int i = 0; i < userGroups.length; i++) {
+ if (parser.groups.contains(((Principal)userGroups[i]).getName())) {
+ allowed = true;
+ break;
+ }
+ }
+ }
+ return allowed;
+ }
+
+ private void sendForbidden(HttpServletResponse res) {
+ sendErrorCode(res, 403);
+ }
+
+ private void sendErrorCode(HttpServletResponse res, int code) {
+ try {
+ res.sendError(code);
+ } catch (IOException e) {
+ // TODO: log appropriately
+ e.printStackTrace();
+ }
+ }
+}