You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by ji...@apache.org on 2020/03/07 03:21:22 UTC

[geode] branch develop updated: GEODE-7851: configure pulse security using java code instead of using xml (#4772)

This is an automated email from the ASF dual-hosted git repository.

jinmeiliao pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/geode.git


The following commit(s) were added to refs/heads/develop by this push:
     new 69ade72  GEODE-7851: configure pulse security using java code instead of using xml (#4772)
69ade72 is described below

commit 69ade72db301d2177b15f422342d198420021b73
Author: Jinmei Liao <ji...@pivotal.io>
AuthorDate: Fri Mar 6 19:20:57 2020 -0800

    GEODE-7851: configure pulse security using java code instead of using xml (#4772)
    
    Co-authored-by: Joris Melchior <jo...@gmail.com>
---
 .../geode/tools/pulse/PulseConnectivityTest.java   |  14 ---
 .../PulseSecurityConfigDefaultProfileTest.java     |  81 ++++++++++++++++
 .../PulseSecurityConfigGemfireProfileTest.java     | 101 +++++++++++++++++++
 .../controllers/PulseControllerJUnitTest.java      |   2 +-
 .../internal/security/CustomSecurityConfig.java    |  41 ++++++++
 .../internal/security/DefaultSecurityConfig.java   | 105 ++++++++++++++++++++
 .../internal/security/GemfireSecurityConfig.java   |  43 ++++++++
 ...vc-dispatcher-servlet.xml => pulse-servlet.xml} |   0
 .../src/main/webapp/WEB-INF/spring-security.xml    | 108 ---------------------
 geode-pulse/src/main/webapp/WEB-INF/web.xml        |  19 ++--
 10 files changed, 382 insertions(+), 132 deletions(-)

diff --git a/geode-assembly/src/integrationTest/java/org/apache/geode/tools/pulse/PulseConnectivityTest.java b/geode-assembly/src/integrationTest/java/org/apache/geode/tools/pulse/PulseConnectivityTest.java
index fe40776..061fe89 100644
--- a/geode-assembly/src/integrationTest/java/org/apache/geode/tools/pulse/PulseConnectivityTest.java
+++ b/geode-assembly/src/integrationTest/java/org/apache/geode/tools/pulse/PulseConnectivityTest.java
@@ -24,7 +24,6 @@ import java.util.Arrays;
 import java.util.Collection;
 import java.util.Properties;
 
-import org.apache.http.HttpResponse;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -34,7 +33,6 @@ import org.junit.runners.Parameterized;
 
 import org.apache.geode.test.junit.categories.PulseTest;
 import org.apache.geode.test.junit.rules.EmbeddedPulseRule;
-import org.apache.geode.test.junit.rules.GeodeHttpClientRule;
 import org.apache.geode.test.junit.rules.LocatorStarterRule;
 import org.apache.geode.test.junit.runners.CategoryWithParameterizedRunnerFactory;
 import org.apache.geode.tools.pulse.internal.data.Cluster;
@@ -49,9 +47,6 @@ public class PulseConnectivityTest {
   @Rule
   public EmbeddedPulseRule pulse = new EmbeddedPulseRule();
 
-  @Rule
-  public GeodeHttpClientRule client = new GeodeHttpClientRule(locator::getHttpPort);
-
   @Parameterized.Parameter
   public static String jmxBindAddress;
 
@@ -73,15 +68,6 @@ public class PulseConnectivityTest {
   }
 
   @Test
-  public void testLogin() throws Exception {
-    HttpResponse response = client.loginToPulse("admin", "wrongPassword");
-    assertThat(response.getStatusLine().getStatusCode()).isEqualTo(302);
-    assertThat(response.getFirstHeader("Location").getValue())
-        .contains("/pulse/login.html?error=BAD_CREDS");
-    client.loginToPulseAndVerify("admin", "admin");
-  }
-
-  @Test
   public void testConnectToJmx() throws Exception {
     pulse.useJmxManager(jmxBindAddress, locator.getJmxPort());
     Cluster cluster = pulse.getRepository().getCluster("admin", null);
diff --git a/geode-assembly/src/integrationTest/java/org/apache/geode/tools/pulse/PulseSecurityConfigDefaultProfileTest.java b/geode-assembly/src/integrationTest/java/org/apache/geode/tools/pulse/PulseSecurityConfigDefaultProfileTest.java
new file mode 100644
index 0000000..d121363
--- /dev/null
+++ b/geode-assembly/src/integrationTest/java/org/apache/geode/tools/pulse/PulseSecurityConfigDefaultProfileTest.java
@@ -0,0 +1,81 @@
+/*
+ * 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.geode.tools.pulse;
+
+import static org.apache.geode.test.junit.rules.HttpResponseAssert.assertResponse;
+
+import org.apache.http.HttpResponse;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import org.apache.geode.test.junit.categories.PulseTest;
+import org.apache.geode.test.junit.rules.GeodeHttpClientRule;
+import org.apache.geode.test.junit.rules.LocatorStarterRule;
+
+@Category({PulseTest.class})
+public class PulseSecurityConfigDefaultProfileTest {
+  @ClassRule
+  public static LocatorStarterRule locator =
+      new LocatorStarterRule().withHttpService().withAutoStart();
+
+  @Rule
+  public GeodeHttpClientRule client = new GeodeHttpClientRule(locator::getHttpPort);
+
+  @Test
+  public void testLogin() throws Exception {
+    HttpResponse response = client.loginToPulse("admin", "wrongPassword");
+    assertResponse(response).hasStatusCode(302).hasHeaderValue("Location")
+        .contains("/pulse/login.html?error=BAD_CREDS");
+    client.loginToPulseAndVerify("admin", "admin");
+  }
+
+  @Test
+  public void loginPage() throws Exception {
+    HttpResponse response = client.get("/pulse/login.html");
+    assertResponse(response).hasStatusCode(200).hasResponseBody().contains("<html>");
+  }
+
+  @Test
+  public void getQueryStatisticsGridModel() throws Exception {
+    client.loginToPulseAndVerify("admin", "admin");
+    HttpResponse httpResponse = client.get("/pulse/getQueryStatisticsGridModel");
+    assertResponse(httpResponse).hasStatusCode(200);
+  }
+
+  @Test
+  public void authenticateUser() throws Exception {
+    HttpResponse response = client.get("/pulse/authenticateUser");
+    assertResponse(response).hasStatusCode(200).hasResponseBody()
+        .isEqualTo("{\"isUserLoggedIn\":false}");
+  }
+
+  @Test
+  public void dataBrowserRegions() throws Exception {
+    HttpResponse response = client.get("/pulse/dataBrowserRegions");
+    // get a restricted page will result in login page
+    assertResponse(response).hasStatusCode(200).hasResponseBody()
+        .contains(
+            "<form method=\"POST\" action=\"login\" name=\"loginForm\" id=\"loginForm\" autocomplete=\"off\">");
+  }
+
+  @Test
+  public void pulseVersion() throws Exception {
+    HttpResponse response = client.get("/pulse/pulseVersion");
+    assertResponse(response).hasStatusCode(200).hasResponseBody().contains("{\"pulseVersion");
+  }
+}
diff --git a/geode-assembly/src/integrationTest/java/org/apache/geode/tools/pulse/PulseSecurityConfigGemfireProfileTest.java b/geode-assembly/src/integrationTest/java/org/apache/geode/tools/pulse/PulseSecurityConfigGemfireProfileTest.java
new file mode 100644
index 0000000..f34a37f
--- /dev/null
+++ b/geode-assembly/src/integrationTest/java/org/apache/geode/tools/pulse/PulseSecurityConfigGemfireProfileTest.java
@@ -0,0 +1,101 @@
+/*
+ * 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.geode.tools.pulse;
+
+import static org.apache.geode.test.junit.rules.HttpResponseAssert.assertResponse;
+
+import org.apache.http.HttpResponse;
+import org.junit.ClassRule;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+import org.apache.geode.examples.SimpleSecurityManager;
+import org.apache.geode.test.junit.categories.PulseTest;
+import org.apache.geode.test.junit.rules.GeodeHttpClientRule;
+import org.apache.geode.test.junit.rules.LocatorStarterRule;
+
+@Category({PulseTest.class})
+public class PulseSecurityConfigGemfireProfileTest {
+  @ClassRule
+  public static LocatorStarterRule locator =
+      new LocatorStarterRule().withHttpService()
+          .withSecurityManager(SimpleSecurityManager.class)
+          .withAutoStart();
+
+  @Rule
+  public GeodeHttpClientRule client = new GeodeHttpClientRule(locator::getHttpPort);
+
+  @Test
+  public void testLogin() throws Exception {
+    HttpResponse response = client.loginToPulse("admin", "wrongPassword");
+    assertResponse(response).hasStatusCode(302).hasHeaderValue("Location")
+        .contains("/pulse/login.html?error=BAD_CREDS");
+    client.loginToPulseAndVerify("cluster", "cluster");
+  }
+
+  @Test
+  public void dataBrowser() throws Exception {
+    client.loginToPulseAndVerify("cluster", "cluster");
+    HttpResponse httpResponse = client.get("/pulse/dataBrowser.html");
+    assertResponse(httpResponse).hasStatusCode(403)
+        .hasResponseBody()
+        .contains("You don't have permissions to access this resource.");
+  }
+
+  @Test
+  public void getQueryStatisticsGridModel() throws Exception {
+    client.loginToPulseAndVerify("cluster", "cluster");
+    HttpResponse httpResponse = client.get("/pulse/getQueryStatisticsGridModel");
+    assertResponse(httpResponse).hasStatusCode(403)
+        .hasResponseBody()
+        .contains("You don't have permissions to access this resource.");
+
+    client.logoutFromPulse();
+
+    client.loginToPulseAndVerify("cluster,data", "cluster,data");
+    httpResponse = client.get("/pulse/getQueryStatisticsGridModel");
+    assertResponse(httpResponse).hasStatusCode(200);
+  }
+
+  @Test
+  public void loginPage() throws Exception {
+    HttpResponse response = client.get("/pulse/login.html");
+    assertResponse(response).hasStatusCode(200).hasResponseBody().contains("<html>");
+  }
+
+  @Test
+  public void authenticateUser() throws Exception {
+    HttpResponse response = client.get("/pulse/authenticateUser");
+    assertResponse(response).hasStatusCode(200).hasResponseBody()
+        .isEqualTo("{\"isUserLoggedIn\":false}");
+  }
+
+  @Test
+  public void dataBrowserRegions() throws Exception {
+    HttpResponse response = client.get("/pulse/dataBrowserRegions");
+    // get a restricted page will result in login page
+    assertResponse(response).hasStatusCode(200).hasResponseBody()
+        .contains(
+            "<form method=\"POST\" action=\"login\" name=\"loginForm\" id=\"loginForm\" autocomplete=\"off\">");
+  }
+
+  @Test
+  public void pulseVersion() throws Exception {
+    HttpResponse response = client.get("/pulse/pulseVersion");
+    assertResponse(response).hasStatusCode(200).hasResponseBody().contains("{\"pulseVersion");
+  }
+}
diff --git a/geode-pulse/src/integrationTest/java/org/apache/geode/tools/pulse/controllers/PulseControllerJUnitTest.java b/geode-pulse/src/integrationTest/java/org/apache/geode/tools/pulse/controllers/PulseControllerJUnitTest.java
index e3c61ce..8077397 100644
--- a/geode-pulse/src/integrationTest/java/org/apache/geode/tools/pulse/controllers/PulseControllerJUnitTest.java
+++ b/geode-pulse/src/integrationTest/java/org/apache/geode/tools/pulse/controllers/PulseControllerJUnitTest.java
@@ -68,7 +68,7 @@ import org.apache.geode.tools.pulse.internal.data.Repository;
 @RunWith(PowerMockRunner.class)
 @PowerMockRunnerDelegate(SpringJUnit4ClassRunner.class)
 @WebAppConfiguration
-@ContextConfiguration("classpath*:mvc-dispatcher-servlet.xml")
+@ContextConfiguration("classpath*:pulse-servlet.xml")
 @PowerMockIgnore({"javax.management.*", "javax.xml.*", "org.xml.*", "org.w3c.*"})
 public class PulseControllerJUnitTest {
 
diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/security/CustomSecurityConfig.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/security/CustomSecurityConfig.java
new file mode 100644
index 0000000..6bb69e3
--- /dev/null
+++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/security/CustomSecurityConfig.java
@@ -0,0 +1,41 @@
+/*
+ * 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.geode.tools.pulse.internal.security;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.ImportResource;
+import org.springframework.context.annotation.Profile;
+import org.springframework.security.authentication.AuthenticationManager;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+
+@Configuration
+@EnableWebSecurity
+@EnableGlobalMethodSecurity(prePostEnabled = true)
+@Profile("pulse.authentication.custom")
+@ImportResource("classpath:pulse-authentication-custom.xml")
+public class CustomSecurityConfig extends DefaultSecurityConfig {
+  // the pulse-authentication-custom.xml should configure an <authentication-manager>
+  @Autowired
+  private AuthenticationManager authenticationManager;
+
+  @Override
+  protected void configure(AuthenticationManagerBuilder authenticationManagerBuilder) {
+    authenticationManagerBuilder.parentAuthenticationManager(authenticationManager);
+  }
+}
diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/security/DefaultSecurityConfig.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/security/DefaultSecurityConfig.java
new file mode 100644
index 0000000..2da31a6
--- /dev/null
+++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/security/DefaultSecurityConfig.java
@@ -0,0 +1,105 @@
+/*
+ * 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.geode.tools.pulse.internal.security;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.security.authentication.CredentialsExpiredException;
+import org.springframework.security.authentication.DisabledException;
+import org.springframework.security.authentication.LockedException;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.crypto.password.NoOpPasswordEncoder;
+import org.springframework.security.web.authentication.ExceptionMappingAuthenticationFailureHandler;
+
+@Configuration
+@EnableWebSecurity
+@EnableGlobalMethodSecurity(prePostEnabled = true)
+@Profile("pulse.authentication.default")
+public class DefaultSecurityConfig extends WebSecurityConfigurerAdapter {
+  @Bean
+  public LogoutHandler customLogoutSuccessHandler() {
+    return new LogoutHandler("/login.html");
+  }
+
+  @Bean
+  public ExceptionMappingAuthenticationFailureHandler authenticationFailureHandler() {
+    ExceptionMappingAuthenticationFailureHandler exceptionMappingAuthenticationFailureHandler =
+        new ExceptionMappingAuthenticationFailureHandler();
+    Map<String, String> exceptionMappings = new HashMap<>();
+    exceptionMappings.put(BadCredentialsException.class.getName(), "/login.html?error=BAD_CREDS");
+    exceptionMappings.put(CredentialsExpiredException.class.getName(),
+        "/login.html?error=CRED_EXP");
+    exceptionMappings.put(LockedException.class.getName(), "/login.html?error=ACC_LOCKED");
+    exceptionMappings.put(DisabledException.class.getName(), "/login.html?error=ACC_DISABLED");
+    exceptionMappingAuthenticationFailureHandler.setExceptionMappings(exceptionMappings);
+    return exceptionMappingAuthenticationFailureHandler;
+  }
+
+  @Autowired
+  private LogoutHandler logoutHandler;
+
+  @Autowired
+  private ExceptionMappingAuthenticationFailureHandler failureHandler;
+
+  @Override
+  protected void configure(HttpSecurity httpSecurity) throws Exception {
+    httpSecurity.authorizeRequests(authorize -> authorize
+        .mvcMatchers("/login.html", "/authenticateUser", "/pulseVersion", "/scripts/**",
+            "/images/**", "/css/**", "/properties/**")
+        .permitAll()
+        .mvcMatchers("/dataBrowser*", "/getQueryStatisticsGridModel*")
+        .access("hasRole('CLUSTER:READ') and hasRole('DATA:READ')")
+        .mvcMatchers("/*")
+        .hasRole("CLUSTER:READ")
+        .anyRequest().authenticated()).formLogin(form -> form
+            .loginPage("/login.html")
+            .loginProcessingUrl("/login")
+            .failureHandler(failureHandler)
+            .defaultSuccessUrl("/clusterDetail.html", true))
+        .logout(logout -> logout
+            .logoutUrl("/clusterLogout")
+            .logoutSuccessHandler(logoutHandler))
+        .exceptionHandling(exception -> exception
+            .accessDeniedPage("/accessDenied.html"))
+        .headers(header -> header
+            .frameOptions().deny()
+            .xssProtection(xss -> xss
+                .xssProtectionEnabled(true)
+                .block(true))
+            .contentTypeOptions())
+        .csrf().disable();
+  }
+
+  @Override
+  protected void configure(AuthenticationManagerBuilder authenticationManagerBuilder)
+      throws Exception {
+    authenticationManagerBuilder.inMemoryAuthentication()
+        .passwordEncoder(NoOpPasswordEncoder.getInstance())
+        .withUser("admin")
+        .password("admin")
+        .roles("CLUSTER:READ", "DATA:READ");
+  }
+}
diff --git a/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/security/GemfireSecurityConfig.java b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/security/GemfireSecurityConfig.java
new file mode 100644
index 0000000..917a698
--- /dev/null
+++ b/geode-pulse/src/main/java/org/apache/geode/tools/pulse/internal/security/GemfireSecurityConfig.java
@@ -0,0 +1,43 @@
+/*
+ * 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.geode.tools.pulse.internal.security;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.context.annotation.Profile;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+
+@Configuration
+@EnableWebSecurity
+@EnableGlobalMethodSecurity(prePostEnabled = true)
+@Profile("pulse.authentication.gemfire")
+public class GemfireSecurityConfig extends DefaultSecurityConfig {
+  @Bean
+  public GemFireAuthenticationProvider gemAuthenticationProvider() {
+    return new GemFireAuthenticationProvider();
+  }
+
+  @Autowired
+  GemFireAuthenticationProvider gemAuthenticationProvider;
+
+  @Override
+  protected void configure(AuthenticationManagerBuilder authenticationManagerBuilder) {
+    authenticationManagerBuilder.authenticationProvider(gemAuthenticationProvider);
+  }
+}
diff --git a/geode-pulse/src/main/webapp/WEB-INF/mvc-dispatcher-servlet.xml b/geode-pulse/src/main/webapp/WEB-INF/pulse-servlet.xml
similarity index 100%
rename from geode-pulse/src/main/webapp/WEB-INF/mvc-dispatcher-servlet.xml
rename to geode-pulse/src/main/webapp/WEB-INF/pulse-servlet.xml
diff --git a/geode-pulse/src/main/webapp/WEB-INF/spring-security.xml b/geode-pulse/src/main/webapp/WEB-INF/spring-security.xml
deleted file mode 100644
index a18f476..0000000
--- a/geode-pulse/src/main/webapp/WEB-INF/spring-security.xml
+++ /dev/null
@@ -1,108 +0,0 @@
-<!--
-  Licensed to the Apache Software Foundation (ASF) under one or more
-  contributor license agreements.  See the NOTICE file distributed with
-  this work for additional information regarding copyright ownership.
-  The ASF licenses this file to You under the Apache License, Version 2.0
-  (the "License"); you may not use this file except in compliance with
-  the License.  You may obtain a copy of the License at
-
-       http://www.apache.org/licenses/LICENSE-2.0
-
-  Unless required by applicable law or agreed to in writing, software
-  distributed under the License is distributed on an "AS IS" BASIS,
-  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-  See the License for the specific language governing permissions and
-  limitations under the License.
--->
-
-<beans:beans xmlns="http://www.springframework.org/schema/security"
-	xmlns:beans="http://www.springframework.org/schema/beans"
-	xmlns:context="http://www.springframework.org/schema/context"
-	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://www.springframework.org/schema/beans
-	https://www.springframework.org/schema/beans/spring-beans.xsd
-	http://www.springframework.org/schema/security
-	https://www.springframework.org/schema/security/spring-security.xsd">
-
-	<http auto-config="true" use-expressions="true">
-		<csrf disabled="true"/>
-		<!-- Can be invoked w/o auth -->
-		<intercept-url pattern="/login.html" access="permitAll"  />
-		<intercept-url pattern="/authenticateUser" access="permitAll" />
-		<intercept-url pattern="/pulseVersion" access="permitAll" />
-		<!-- Can be invoked w/o auth -->
-
-		<!-- Restricted urls -->
-		<intercept-url pattern="/accessDenied*" access="isAuthenticated()"/>
-		<intercept-url pattern="/dataBrowser*" access="hasRole('CLUSTER:READ') and hasRole('DATA:READ')" />
-		<intercept-url pattern="/getQueryStatisticsGridModel/*" access="hasRole('CLUSTER:READ') and hasRole('DATA:READ')" />
-		<intercept-url pattern="/*" access="hasRole('CLUSTER:READ')" />
-
-		<!-- Restricted urls -->
-        <form-login login-page="/login.html"
-                    authentication-failure-handler-ref="authenticationFailureHandler"
-                    default-target-url="/clusterDetail.html"
-                    always-use-default-target="true"/>
-		<headers>
-			<frame-options policy="DENY" />
-			<content-type-options  />
-			<xss-protection enabled="true" block="true" />
-		</headers>
-
-		<access-denied-handler error-page="/accessDenied.html"/>
-
-		<logout logout-url="/clusterLogout" success-handler-ref="customLogoutSuccessHandler"/>
-
-	</http>
-
-	<beans:bean name="customLogoutSuccessHandler" 
-	class="org.apache.geode.tools.pulse.internal.security.LogoutHandler">
-		<beans:constructor-arg value="/login.html"/>
-	</beans:bean>
-	
-	<beans:bean id="authenticationFailureHandler"
-		class="org.springframework.security.web.authentication.ExceptionMappingAuthenticationFailureHandler">
-		<beans:property name="exceptionMappings">
-			<beans:props>
-				<beans:prop key="org.springframework.security.authentication.BadCredentialsException">/login.html?error=BAD_CREDS</beans:prop>
-				<beans:prop key="org.springframework.security.authentication.CredentialsExpiredException">/login.html?error=CRED_EXP</beans:prop>
-				<beans:prop key="org.springframework.security.authentication.LockedException">/login.html?error=ACC_LOCKED</beans:prop>
-				<beans:prop key="org.springframework.security.authentication.DisabledException">/login.html?error=ACC_DISABLED</beans:prop>
-			</beans:props>
-		</beans:property>
-	</beans:bean>
-	
-	<beans:bean id="gemAuthenticationProvider" 
-		class="org.apache.geode.tools.pulse.internal.security.GemFireAuthenticationProvider">
-  </beans:bean>
-
-	<beans:bean id="passwordEncoder"
-	  class="org.springframework.security.crypto.password.NoOpPasswordEncoder"
-		factory-method="getInstance" />
-
-	<!-- Default user authentication -->
-	<beans:beans profile="pulse.authentication.default">
-		<authentication-manager>
-			<authentication-provider>
-				<password-encoder ref="passwordEncoder"/>
-				<user-service>
-					<user name="admin" password="admin"
-										authorities="ROLE_CLUSTER:READ,ROLE_DATA:READ"/>
-				</user-service>
-			</authentication-provider>
-		</authentication-manager>
-	</beans:beans>
-	
-	<!-- Default user authentication based on gemfire integrated security -->
-	<beans:beans profile="pulse.authentication.gemfire">
-		<authentication-manager alias="authenticationManager">
-			<authentication-provider ref="gemAuthenticationProvider"/>
-		</authentication-manager>
-	</beans:beans>
-
-	<!-- Custom user authentication specified externally -->
-	<beans:beans profile="pulse.authentication.custom">
-		<beans:import resource="classpath:pulse-authentication-custom.xml" />
-	</beans:beans>
-   
-</beans:beans>
diff --git a/geode-pulse/src/main/webapp/WEB-INF/web.xml b/geode-pulse/src/main/webapp/WEB-INF/web.xml
index 8aa78d7..19ad467 100644
--- a/geode-pulse/src/main/webapp/WEB-INF/web.xml
+++ b/geode-pulse/src/main/webapp/WEB-INF/web.xml
@@ -16,7 +16,10 @@
   limitations under the License.
 -->
 
-<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
+<web-app xmlns="http://java.sun.com/xml/ns/javaee"
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
+         version="3.0">
   <display-name>Pulse</display-name>
   <welcome-file-list>
     <welcome-file>index.html</welcome-file>
@@ -26,26 +29,24 @@
         <mime-type>text/x-java-properties</mime-type>
   </mime-mapping>
   <servlet>
-    <servlet-name>mvc-dispatcher</servlet-name>
+    <servlet-name>pulse</servlet-name>
     <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
     <load-on-startup>1</load-on-startup>
   </servlet>
+
   <servlet-mapping>
-    <servlet-name>mvc-dispatcher</servlet-name>
+    <servlet-name>pulse</servlet-name>
     <url-pattern>/</url-pattern>
-    <!-- We expect Pulse to receive requests to URLs like /pulse/pulseVersion, but Jetty will match /pulse/
-    to the web app context for this WAR and only pass /pulseVersion into the servlet configured with this <url-pattern/>
-  -->
   </servlet-mapping>
+
   <listener>
     <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
   </listener>
   <context-param>
     <param-name>contextConfigLocation</param-name>
     <param-value>
-			/WEB-INF/mvc-dispatcher-servlet.xml,
-			/WEB-INF/spring-security.xml
-		</param-value>
+			/WEB-INF/pulse-servlet.xml
+    </param-value>
   </context-param>
   <context-param>
     <param-name>spring.profiles.default</param-name>