You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@geode.apache.org by GitBox <gi...@apache.org> on 2019/01/15 17:57:46 UTC
[geode] Diff for: [GitHub] jinmeiliao merged pull request #3066: GEODE-6174: Added rest controller to process post request to /geode-m…
diff --git a/geode-assembly/build.gradle b/geode-assembly/build.gradle
index 33da4a219b7..b3bd90ec97e 100755
--- a/geode-assembly/build.gradle
+++ b/geode-assembly/build.gradle
@@ -140,6 +140,7 @@ dependencies {
archives project(':geode-protobuf-messages')
archives project(':geode-web')
archives project(':geode-web-api')
+ archives project(':geode-web-management')
archives project(':geode-wan')
archives project(':geode-cq')
archives project(':geode-rebalancer')
@@ -463,6 +464,9 @@ distributions {
from (project(':geode-web-api').configurations.archives.allArtifacts.files) {
exclude '*.jar'
}
+ from (project(':geode-web-management').configurations.archives.allArtifacts.files) {
+ exclude '*.jar'
+ }
}
into('tools/ClientProtocol') {
diff --git a/geode-assembly/geode-assembly-test/src/main/java/org/apache/geode/test/junit/rules/GeodeDevRestClient.java b/geode-assembly/geode-assembly-test/src/main/java/org/apache/geode/test/junit/rules/GeodeDevRestClient.java
index 2369460985e..5bb9b245222 100644
--- a/geode-assembly/geode-assembly-test/src/main/java/org/apache/geode/test/junit/rules/GeodeDevRestClient.java
+++ b/geode-assembly/geode-assembly-test/src/main/java/org/apache/geode/test/junit/rules/GeodeDevRestClient.java
@@ -52,20 +52,23 @@
public class GeodeDevRestClient {
public static final String CONTEXT = "/geode/v1";
+ private String context;
private String bindAddress;
private int restPort;
private boolean useSsl;
private HttpHost host;
- public GeodeDevRestClient(int restPort) {
- this("localhost", restPort, false);
- }
public GeodeDevRestClient(String bindAddress, int restPort) {
- this(bindAddress, restPort, false);
+ this(CONTEXT, bindAddress, restPort, false);
}
public GeodeDevRestClient(String bindAddress, int restPort, boolean useSsl) {
+ this(CONTEXT, bindAddress, restPort, useSsl);
+ }
+
+ public GeodeDevRestClient(String context, String bindAddress, int restPort, boolean useSsl) {
+ this.context = context;
this.bindAddress = bindAddress;
this.restPort = restPort;
this.useSsl = useSsl;
@@ -73,31 +76,31 @@ public GeodeDevRestClient(String bindAddress, int restPort, boolean useSsl) {
}
public HttpResponse doHEAD(String query, String username, String password) {
- HttpHead httpHead = new HttpHead(CONTEXT + query);
+ HttpHead httpHead = new HttpHead(context + query);
return doRequest(httpHead, username, password);
}
public HttpResponse doPost(String query, String username, String password, String body) {
- HttpPost httpPost = new HttpPost(CONTEXT + query);
+ HttpPost httpPost = new HttpPost(context + query);
httpPost.addHeader("content-type", "application/json");
httpPost.setEntity(new StringEntity(body, StandardCharsets.UTF_8));
return doRequest(httpPost, username, password);
}
public HttpResponse doPut(String query, String username, String password, String body) {
- HttpPut httpPut = new HttpPut(CONTEXT + query);
+ HttpPut httpPut = new HttpPut(context + query);
httpPut.addHeader("content-type", "application/json");
httpPut.setEntity(new StringEntity(body, StandardCharsets.UTF_8));
return doRequest(httpPut, username, password);
}
public HttpResponse doGet(String uri, String username, String password) {
- HttpGet getRequest = new HttpGet(CONTEXT + uri);
+ HttpGet getRequest = new HttpGet(context + uri);
return doRequest(getRequest, username, password);
}
public HttpResponse doDelete(String uri, String username, String password) {
- HttpDelete httpDelete = new HttpDelete(CONTEXT + uri);
+ HttpDelete httpDelete = new HttpDelete(context + uri);
return doRequest(httpDelete, username, password);
}
@@ -118,6 +121,11 @@ public HttpResponseAssert doPostAndAssert(String uri, String body) {
return new HttpResponseAssert("Post " + uri, doPost(uri, null, null, body));
}
+ public HttpResponseAssert doPostAndAssert(String uri, String body, String username,
+ String password) {
+ return new HttpResponseAssert("Post " + uri, doPost(uri, username, password, body));
+ }
+
public HttpResponseAssert doDeleteAndAssert(String uri) {
return new HttpResponseAssert("Delete " + uri, doDelete(uri, null, null));
}
diff --git a/geode-assembly/src/integrationTest/java/org/apache/geode/management/internal/RegionManagementIntegrationTest.java b/geode-assembly/src/integrationTest/java/org/apache/geode/management/internal/RegionManagementIntegrationTest.java
new file mode 100644
index 00000000000..b7ad6090e61
--- /dev/null
+++ b/geode-assembly/src/integrationTest/java/org/apache/geode/management/internal/RegionManagementIntegrationTest.java
@@ -0,0 +1,58 @@
+/*
+ * 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.management.internal;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Test;
+
+import org.apache.geode.cache.configuration.RegionConfig;
+import org.apache.geode.test.junit.rules.GeodeDevRestClient;
+import org.apache.geode.test.junit.rules.LocatorStarterRule;
+import org.apache.geode.test.junit.rules.RequiresGeodeHome;
+
+public class RegionManagementIntegrationTest {
+
+ @ClassRule
+ public static LocatorStarterRule locator =
+ new LocatorStarterRule().withHttpService().withAutoStart();
+
+ @ClassRule
+ public static RequiresGeodeHome requiresGeodeHome = new RequiresGeodeHome();
+
+ public static GeodeDevRestClient restClient;
+
+ @BeforeClass
+ public static void setUpClass() throws Exception {
+ restClient =
+ new GeodeDevRestClient("/geode-management/v2", "localhost", locator.getHttpPort(), false);
+ }
+
+ @Test
+ public void sanityCheck() throws Exception {
+ RegionConfig regionConfig = new RegionConfig();
+ regionConfig.setName("customers");
+ regionConfig.setRefid("REPLICATE");
+
+ ObjectMapper mapper = new ObjectMapper();
+ String json = mapper.writeValueAsString(regionConfig);
+
+ restClient.doPostAndAssert("/regions", json, null, null)
+ .hasStatusCode(201)
+ .hasResponseBody().isEqualTo("customers");
+ }
+}
diff --git a/geode-assembly/src/integrationTest/java/org/apache/geode/management/internal/RegionManagementSecurityIntegrationTest.java b/geode-assembly/src/integrationTest/java/org/apache/geode/management/internal/RegionManagementSecurityIntegrationTest.java
new file mode 100644
index 00000000000..6351faaac82
--- /dev/null
+++ b/geode-assembly/src/integrationTest/java/org/apache/geode/management/internal/RegionManagementSecurityIntegrationTest.java
@@ -0,0 +1,86 @@
+/*
+ * 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.management.internal;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Test;
+
+import org.apache.geode.cache.configuration.RegionConfig;
+import org.apache.geode.security.SimpleTestSecurityManager;
+import org.apache.geode.test.junit.rules.GeodeDevRestClient;
+import org.apache.geode.test.junit.rules.LocatorStarterRule;
+import org.apache.geode.test.junit.rules.RequiresGeodeHome;
+
+public class RegionManagementSecurityIntegrationTest {
+
+ @ClassRule
+ public static LocatorStarterRule locator = new LocatorStarterRule().withHttpService()
+ .withSecurityManager(SimpleTestSecurityManager.class).withAutoStart();
+
+ @ClassRule
+ public static RequiresGeodeHome requiresGeodeHome = new RequiresGeodeHome();
+
+ public static GeodeDevRestClient restClient;
+
+ @BeforeClass
+ public static void setUpClass() {
+ restClient =
+ new GeodeDevRestClient("/geode-management/v2", "localhost", locator.getHttpPort(), false);
+ }
+
+ private RegionConfig regionConfig;
+ private String json;
+
+ @Before
+ public void before() throws JsonProcessingException {
+ regionConfig = new RegionConfig();
+ regionConfig.setName("customers");
+ regionConfig.setRefid("REPLICATE");
+ ObjectMapper mapper = new ObjectMapper();
+ json = mapper.writeValueAsString(regionConfig);
+ }
+
+ @Test
+ public void sanityCheck_not_authorized() throws Exception {
+ restClient.doPostAndAssert("/regions", json, "test", "test")
+ .hasStatusCode(403)
+ .hasResponseBody().isEqualTo("Access is denied");
+ }
+
+ @Test
+ public void sanityCheckWithNoCredentials() throws Exception {
+ restClient.doPostAndAssert("/regions", json, null, null)
+ .hasStatusCode(401);
+ }
+
+ @Test
+ public void sanityCheckWithWrongCredentials() throws Exception {
+ restClient.doPostAndAssert("/regions", json, "test", "invalid_pswd")
+ .hasStatusCode(401);
+ }
+
+ @Test
+ public void sanityCheck_success() throws Exception {
+ restClient.doPostAndAssert("/regions", json, "dataManage", "dataManage")
+ .hasStatusCode(201)
+ .hasResponseBody().isEqualTo("customers");
+ }
+
+}
diff --git a/geode-assembly/src/integrationTest/resources/assembly_content.txt b/geode-assembly/src/integrationTest/resources/assembly_content.txt
index 7501b75b5d1..ef6ed79b0ee 100644
--- a/geode-assembly/src/integrationTest/resources/assembly_content.txt
+++ b/geode-assembly/src/integrationTest/resources/assembly_content.txt
@@ -956,6 +956,7 @@ lib/spring-web-4.3.20.RELEASE.jar
tools/ClientProtocol/geode-protobuf-messages-definitions-0.0.0.zip
tools/Extensions/geode-web-0.0.0.war
tools/Extensions/geode-web-api-0.0.0.war
+tools/Extensions/geode-web-management-0.0.0.war
tools/Modules/Apache_Geode_Modules-0.0.0-AppServer.zip
tools/Modules/Apache_Geode_Modules-0.0.0-Tomcat.zip
tools/Modules/Apache_Geode_Modules-0.0.0-tcServer.zip
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/AgentUtil.java b/geode-core/src/main/java/org/apache/geode/management/internal/AgentUtil.java
index 8b22f7d71f7..24f280131a5 100755
--- a/geode-core/src/main/java/org/apache/geode/management/internal/AgentUtil.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/AgentUtil.java
@@ -130,13 +130,9 @@ private String lookupWarLocationFromClasspath(String versionedWarFileName,
.findFirst().orElse(null);
}
- boolean isWebApplicationAvailable(final String warFileLocation) {
- return StringUtils.isNotBlank(warFileLocation);
- }
-
- boolean isWebApplicationAvailable(final String... warFileLocations) {
+ boolean isAnyWarFileAvailable(final String... warFileLocations) {
for (String warFileLocation : warFileLocations) {
- if (isWebApplicationAvailable(warFileLocation)) {
+ if (StringUtils.isNotBlank(warFileLocation)) {
return true;
}
}
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/ManagementAgent.java b/geode-core/src/main/java/org/apache/geode/management/internal/ManagementAgent.java
index ddd60a9556b..b37c1d5ef8e 100755
--- a/geode-core/src/main/java/org/apache/geode/management/internal/ManagementAgent.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/ManagementAgent.java
@@ -215,7 +215,16 @@ private void startHttpService(boolean isServer) {
if (gemfireWar == null) {
if (logger.isDebugEnabled()) {
logger.debug(
- "Unable to find GemFire Management REST API WAR file; the Management REST Interface for GemFire will not be accessible.");
+ "Unable to find GemFire V1 Management REST API WAR file; the Management REST Interface for GemFire will not be accessible.");
+ }
+ }
+
+ // Find the V2 Management rest WAR file
+ final String gemfireManagementWar = agentUtil.findWarLocation("geode-web-management");
+ if (gemfireManagementWar == null) {
+ if (logger.isDebugEnabled()) {
+ logger.debug(
+ "Unable to find GemFire V2 Management REST API WAR file; the Management REST Interface for GemFire will not be accessible.");
}
}
@@ -248,7 +257,8 @@ private void startHttpService(boolean isServer) {
}
try {
- if (agentUtil.isWebApplicationAvailable(gemfireWar, pulseWar, gemfireAPIWar)) {
+ if (agentUtil.isAnyWarFileAvailable(gemfireWar, gemfireManagementWar, pulseWar,
+ gemfireAPIWar)) {
final String bindAddress = this.config.getHttpServiceBindAddress();
final int port = this.config.getHttpServicePort();
@@ -258,20 +268,25 @@ private void startHttpService(boolean isServer) {
this.httpServer = JettyHelper.initJetty(bindAddress, port, SSLConfigurationFactory
.getSSLConfigForComponent(config, SecurableCommunicationChannel.WEB));
- if (agentUtil.isWebApplicationAvailable(gemfireWar)) {
+ if (agentUtil.isAnyWarFileAvailable(gemfireWar)) {
this.httpServer = JettyHelper.addWebApplication(this.httpServer, "/gemfire", gemfireWar,
securityService, null);
this.httpServer = JettyHelper.addWebApplication(this.httpServer, "/geode-mgmt",
gemfireWar, securityService, null);
}
- if (agentUtil.isWebApplicationAvailable(pulseWar)) {
+ if (agentUtil.isAnyWarFileAvailable(gemfireManagementWar)) {
+ this.httpServer = JettyHelper.addWebApplication(this.httpServer, "/geode-management",
+ gemfireManagementWar, securityService, null);
+ }
+
+ if (agentUtil.isAnyWarFileAvailable(pulseWar)) {
this.httpServer = JettyHelper.addWebApplication(this.httpServer, "/pulse", pulseWar,
securityService, createSslProps());
}
if (isServer && this.config.getStartDevRestApi()) {
- if (agentUtil.isWebApplicationAvailable(gemfireAPIWar)) {
+ if (agentUtil.isAnyWarFileAvailable(gemfireAPIWar)) {
this.httpServer = JettyHelper.addWebApplication(this.httpServer, "/geode",
gemfireAPIWar, securityService, null);
this.httpServer = JettyHelper.addWebApplication(this.httpServer, "/gemfire-api",
@@ -307,7 +322,7 @@ private void startHttpService(boolean isServer) {
// now, that Tomcat has been started, we can set the URL used by web
// clients to connect to Pulse
- if (agentUtil.isWebApplicationAvailable(pulseWar)) {
+ if (agentUtil.isAnyWarFileAvailable(pulseWar)) {
managerBean.setPulseURL("http://".concat(getHost(bindAddress)).concat(":")
.concat(String.valueOf(port)).concat("/pulse/"));
}
diff --git a/geode-core/src/main/java/org/apache/geode/management/internal/RestAgent.java b/geode-core/src/main/java/org/apache/geode/management/internal/RestAgent.java
index fa0f25ca576..6405c52b94f 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/RestAgent.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/RestAgent.java
@@ -130,7 +130,7 @@ public void startHttpService() {
if (isRunningInTomcat()) {
logger.warn(
"Detected presence of catalina system properties. HTTP service will not be started. To enable the GemFire Developer REST API, please deploy the /geode-web-api WAR file in your application server.");
- } else if (agentUtil.isWebApplicationAvailable(gemfireAPIWar)) {
+ } else if (agentUtil.isAnyWarFileAvailable(gemfireAPIWar)) {
final int port = this.config.getHttpServicePort();
diff --git a/geode-web-api/src/integrationTest/java/org/apache/geode/rest/internal/web/controllers/RestAccessControllerTest.java b/geode-web-api/src/integrationTest/java/org/apache/geode/rest/internal/web/controllers/RestAccessControllerTest.java
index f8df307fc78..ec177bf60f3 100644
--- a/geode-web-api/src/integrationTest/java/org/apache/geode/rest/internal/web/controllers/RestAccessControllerTest.java
+++ b/geode-web-api/src/integrationTest/java/org/apache/geode/rest/internal/web/controllers/RestAccessControllerTest.java
@@ -49,12 +49,15 @@
import org.springframework.security.test.context.support.WithMockUser;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
+import org.springframework.test.context.web.GenericXmlWebContextLoader;
import org.springframework.test.context.web.WebAppConfiguration;
+import org.springframework.test.context.web.WebMergedContextConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
import org.springframework.test.web.servlet.request.RequestPostProcessor;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
+import org.springframework.web.context.support.GenericWebApplicationContext;
import org.apache.geode.cache.CacheLoader;
import org.apache.geode.cache.CacheWriter;
@@ -67,11 +70,13 @@
import org.apache.geode.cache.RegionShortcut;
import org.apache.geode.cache.TimeoutException;
import org.apache.geode.cache.execute.FunctionService;
+import org.apache.geode.management.internal.JettyHelper;
import org.apache.geode.management.internal.RestAgent;
import org.apache.geode.test.junit.rules.ServerStarterRule;
@RunWith(SpringJUnit4ClassRunner.class)
-@ContextConfiguration(locations = {"classpath*:WEB-INF/geode-servlet.xml"})
+@ContextConfiguration(locations = {"classpath*:WEB-INF/geode-servlet.xml"},
+ loader = TestContextLoader.class)
@WebAppConfiguration
public class RestAccessControllerTest {
@@ -135,8 +140,7 @@ private static void loadResource(String name) throws Exception {
@Before
public void setup() {
- mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext)
- .build();
+ mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
rule.getCache().getRegion("customers").clear();
rule.getCache().getRegion("orders").clear();
@@ -923,5 +927,16 @@ public void beforeRegionClear(RegionEvent event) throws CacheWriterException {
// nothing
}
}
+}
+
+
+class TestContextLoader extends GenericXmlWebContextLoader {
+ @Override
+ protected void loadBeanDefinitions(GenericWebApplicationContext context,
+ WebMergedContextConfiguration webMergedConfig) {
+ super.loadBeanDefinitions(context, webMergedConfig);
+ context.getServletContext().setAttribute(JettyHelper.SECURITY_SERVICE_SERVLET_CONTEXT_PARAM,
+ RestAccessControllerTest.rule.getCache().getSecurityService());
+ }
}
diff --git a/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/security/GeodeAuthenticationProvider.java b/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/security/GeodeAuthenticationProvider.java
index 1f028183958..db5bf5cf2d7 100644
--- a/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/security/GeodeAuthenticationProvider.java
+++ b/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/security/GeodeAuthenticationProvider.java
@@ -18,6 +18,8 @@
import java.util.Properties;
+import javax.servlet.ServletContext;
+
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
@@ -25,33 +27,18 @@
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.stereotype.Component;
+import org.springframework.web.context.ServletContextAware;
-import org.apache.geode.internal.cache.GemFireCacheImpl;
-import org.apache.geode.internal.cache.InternalCache;
import org.apache.geode.internal.security.SecurityService;
-import org.apache.geode.internal.security.SecurityServiceFactory;
+import org.apache.geode.management.internal.JettyHelper;
import org.apache.geode.management.internal.security.ResourceConstants;
import org.apache.geode.security.GemFireSecurityException;
@Component
-public class GeodeAuthenticationProvider implements AuthenticationProvider {
-
- private final SecurityService securityService;
+public class GeodeAuthenticationProvider implements AuthenticationProvider, ServletContextAware {
- public GeodeAuthenticationProvider() {
- // TODO: can we pass SecurityService in?
- this.securityService = findSecurityService();
- }
-
- private static SecurityService findSecurityService() {
- InternalCache cache = GemFireCacheImpl.getInstance();
- if (cache != null) {
- return cache.getSecurityService();
- } else {
- return SecurityServiceFactory.create();
- }
- }
+ private SecurityService securityService;
public SecurityService getSecurityService() {
return this.securityService;
@@ -80,4 +67,10 @@ public Authentication authenticate(Authentication authentication) throws Authent
public boolean supports(Class<?> authentication) {
return authentication.isAssignableFrom(UsernamePasswordAuthenticationToken.class);
}
+
+ @Override
+ public void setServletContext(ServletContext servletContext) {
+ securityService = (SecurityService) servletContext
+ .getAttribute(JettyHelper.SECURITY_SERVICE_SERVLET_CONTEXT_PARAM);
+ }
}
diff --git a/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/security/RestSecurityService.java b/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/security/RestSecurityService.java
index b3fe666b7d2..4020ddc3639 100644
--- a/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/security/RestSecurityService.java
+++ b/geode-web-api/src/main/java/org/apache/geode/rest/internal/web/security/RestSecurityService.java
@@ -14,30 +14,22 @@
*/
package org.apache.geode.rest.internal.web.security;
+import javax.servlet.ServletContext;
+
import org.springframework.stereotype.Component;
+import org.springframework.web.context.ServletContextAware;
-import org.apache.geode.internal.cache.GemFireCacheImpl;
-import org.apache.geode.internal.cache.InternalCache;
import org.apache.geode.internal.security.SecurityService;
-import org.apache.geode.internal.security.SecurityServiceFactory;
+import org.apache.geode.management.internal.JettyHelper;
import org.apache.geode.security.GemFireSecurityException;
import org.apache.geode.security.ResourcePermission;
import org.apache.geode.security.ResourcePermission.Operation;
import org.apache.geode.security.ResourcePermission.Resource;
@Component("securityService")
-public class RestSecurityService {
+public class RestSecurityService implements ServletContextAware {
- private final SecurityService securityService;
-
- public RestSecurityService() {
- InternalCache cache = GemFireCacheImpl.getInstance();
- if (cache != null) {
- this.securityService = cache.getSecurityService();
- } else {
- this.securityService = SecurityServiceFactory.create();
- }
- }
+ private SecurityService securityService;
public boolean authorize(String resource, String operation) {
return authorize(resource, operation, null, null);
@@ -83,4 +75,9 @@ public Object postProcess(String regionPath, Object key, Object value,
return securityService.postProcess(regionPath, key, value, valueIsSerialized);
}
+ @Override
+ public void setServletContext(ServletContext servletContext) {
+ securityService = (SecurityService) servletContext
+ .getAttribute(JettyHelper.SECURITY_SERVICE_SERVLET_CONTEXT_PARAM);
+ }
}
diff --git a/geode-web-management/build.gradle b/geode-web-management/build.gradle
new file mode 100644
index 00000000000..3b55c61b6b9
--- /dev/null
+++ b/geode-web-management/build.gradle
@@ -0,0 +1,97 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ * agreements. See the NOTICE file distributed with this work for additional information regarding
+ * copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance with the License. You may obtain a
+ * copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software distributed under the License
+ * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions and limitations under
+ * the License.
+ */
+
+apply plugin: 'war'
+
+apply from: "${project.projectDir}/../gradle/geode-dependency-management.gradle"
+apply from: "${project.projectDir}/../gradle/publish.gradle"
+
+
+dependencies {
+
+ compileOnly(project(':geode-core'))
+
+ compileOnly('javax.servlet:javax.servlet-api')
+
+ compile('org.apache.commons:commons-lang3')
+ compile('commons-fileupload:commons-fileupload') {
+ exclude module: 'commons-io'
+ }
+ compile('com.fasterxml.jackson.core:jackson-annotations')
+ compile('com.fasterxml.jackson.core:jackson-core')
+ compile('com.fasterxml.jackson.core:jackson-databind')
+ compile('com.fasterxml.jackson.module:jackson-module-scala_2.10')
+ compile('io.springfox:springfox-swagger2') {
+ exclude module: 'slf4j-api'
+ }
+ compile('io.springfox:springfox-swagger-ui') {
+ exclude module: 'slf4j-api'
+ }
+ compile('org.springframework:spring-beans')
+ compile('org.springframework.security:spring-security-core')
+ compile('org.springframework.security:spring-security-web')
+ compile('org.springframework.security:spring-security-config')
+ compile('org.springframework:spring-web')
+ compile('org.springframework:spring-webmvc')
+ compile('org.springframework.hateoas:spring-hateoas') {
+ exclude module: 'aopalliance'
+ exclude module: 'commons-logging'
+ exclude module: 'objenesis'
+ exclude module: 'slf4j-api'
+ exclude module: 'spring-core'
+ }
+ compile('org.springframework:spring-aspects') {
+ exclude module: 'aopalliance'
+ exclude module: 'aspectjweaver'
+ }
+ compile('org.springframework:spring-oxm') {
+ exclude module: 'commons-logging'
+ exclude module: 'spring-core'
+ exclude module: 'spring-beans'
+ }
+
+
+ testCompile(project(':geode-junit')) {
+ exclude module: 'geode-core'
+ }
+ testCompile(project(':geode-core'))
+ testCompile('javax.servlet:javax.servlet-api')
+
+ integrationTestCompile('org.springframework:spring-test')
+ integrationTestCompile('org.springframework.security:spring-security-test')
+
+ integrationTestCompile(project(':geode-junit')) {
+ exclude module: 'geode-core'
+ }
+ integrationTestCompile(project(':geode-dunit')) {
+ exclude module: 'geode-core'
+ }
+}
+
+sourceSets {
+ integrationTest {
+ resources {
+ srcDir "${projectDir}/src/main/webapp"
+ }
+ }
+}
+
+war {
+ rootSpec.exclude("**/*commons-logging-*.jar")
+ duplicatesStrategy = DuplicatesStrategy.EXCLUDE
+ // this shouldn't be necessary but if it's not specified we're missing some of the jars
+ // from the runtime classpath
+ classpath configurations.runtimeClasspath
+}
diff --git a/geode-web-management/src/main/java/org/apache/geode/management/internal/web/controllers/AbstractAdminRestController.java b/geode-web-management/src/main/java/org/apache/geode/management/internal/web/controllers/AbstractAdminRestController.java
new file mode 100644
index 00000000000..fa37da7b0c5
--- /dev/null
+++ b/geode-web-management/src/main/java/org/apache/geode/management/internal/web/controllers/AbstractAdminRestController.java
@@ -0,0 +1,126 @@
+/*
+ * 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.management.internal.web.controllers;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+import javax.management.InstanceNotFoundException;
+import javax.management.MalformedObjectNameException;
+
+import org.apache.logging.log4j.Logger;
+import org.springframework.beans.propertyeditors.StringArrayPropertyEditor;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.access.AccessDeniedException;
+import org.springframework.web.bind.WebDataBinder;
+import org.springframework.web.bind.annotation.ExceptionHandler;
+import org.springframework.web.bind.annotation.InitBinder;
+
+import org.apache.geode.internal.logging.LogService;
+import org.apache.geode.management.MemberMXBean;
+import org.apache.geode.management.internal.cli.shell.Gfsh;
+import org.apache.geode.security.AuthenticationFailedException;
+import org.apache.geode.security.NotAuthorizedException;
+
+/**
+ * The AbstractCommandsController class is the abstract base class encapsulating common
+ * functionality across all Management Controller classes that expose REST API web service endpoints
+ * (URLs/URIs) for GemFire shell (Gfsh) commands.
+ *
+ * @see MemberMXBean
+ * @see Gfsh
+ * @see ResponseEntity
+ * @see org.springframework.stereotype.Controller
+ * @see ExceptionHandler
+ * @see InitBinder
+ * @see org.springframework.web.bind.annotation.ResponseBody
+ * @since GemFire 8.0
+ */
+@SuppressWarnings("unused")
+public abstract class AbstractAdminRestController {
+ protected static final String REST_API_VERSION = "/v1";
+ private static final Logger logger = LogService.getLogger();
+
+ @ExceptionHandler(Exception.class)
+ public ResponseEntity<String> internalError(final Exception e) {
+ final String stackTrace = getPrintableStackTrace(e);
+ logger.fatal(stackTrace);
+ return new ResponseEntity<>(stackTrace, HttpStatus.INTERNAL_SERVER_ERROR);
+ }
+
+ @ExceptionHandler(AuthenticationFailedException.class)
+ public ResponseEntity<String> unauthorized(AuthenticationFailedException e) {
+ return new ResponseEntity<>(e.getMessage(), HttpStatus.UNAUTHORIZED);
+ }
+
+ @ExceptionHandler({NotAuthorizedException.class, SecurityException.class})
+ public ResponseEntity<String> forbidden(Exception e) {
+ return new ResponseEntity<>(e.getMessage(), HttpStatus.FORBIDDEN);
+ }
+
+ @ExceptionHandler(MalformedObjectNameException.class)
+ public ResponseEntity<String> badRequest(final MalformedObjectNameException e) {
+ logger.info(e);
+ return new ResponseEntity<>(getPrintableStackTrace(e), HttpStatus.BAD_REQUEST);
+ }
+
+ @ExceptionHandler(InstanceNotFoundException.class)
+ public ResponseEntity<String> notFound(final InstanceNotFoundException e) {
+ logger.info(e);
+ return new ResponseEntity<>(getPrintableStackTrace(e), HttpStatus.NOT_FOUND);
+ }
+
+ /**
+ * Handles an AccessDenied Exception thrown by a REST API web service endpoint, HTTP request
+ * handler method.
+ * <p/>
+ *
+ * @param cause the Exception causing the error.
+ * @return a ResponseEntity with an appropriate HTTP status code (403 - Forbidden)
+ */
+ @ExceptionHandler(AccessDeniedException.class)
+ public ResponseEntity<String> handleException(final AccessDeniedException cause) {
+ logger.info(cause);
+ return new ResponseEntity<>(cause.getMessage(), HttpStatus.FORBIDDEN);
+ }
+
+ /**
+ * Writes the stack trace of the Throwable to a String.
+ *
+ * @param t a Throwable object who's stack trace will be written to a String.
+ * @return a String containing the stack trace of the Throwable.
+ * @see StringWriter
+ * @see Throwable#printStackTrace(PrintWriter)
+ */
+ private static String getPrintableStackTrace(final Throwable t) {
+ final StringWriter stackTraceWriter = new StringWriter();
+ t.printStackTrace(new PrintWriter(stackTraceWriter));
+ return stackTraceWriter.toString();
+ }
+
+ /**
+ * Initializes data bindings for various HTTP request handler method parameter Java class types.
+ *
+ * @param dataBinder the DataBinder implementation used for Web transactions.
+ * @see WebDataBinder
+ * @see InitBinder
+ */
+ @InitBinder
+ public void initBinder(final WebDataBinder dataBinder) {
+ dataBinder.registerCustomEditor(String[].class,
+ new StringArrayPropertyEditor(StringArrayPropertyEditor.DEFAULT_SEPARATOR, false));
+ }
+}
diff --git a/geode-web-management/src/main/java/org/apache/geode/management/internal/web/controllers/AbstractManagementController.java b/geode-web-management/src/main/java/org/apache/geode/management/internal/web/controllers/AbstractManagementController.java
new file mode 100644
index 00000000000..9fbb1c789e2
--- /dev/null
+++ b/geode-web-management/src/main/java/org/apache/geode/management/internal/web/controllers/AbstractManagementController.java
@@ -0,0 +1,36 @@
+/*
+ * 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.management.internal.web.controllers;
+
+import javax.servlet.ServletContext;
+
+import org.springframework.web.context.ServletContextAware;
+
+import org.apache.geode.internal.security.SecurityService;
+import org.apache.geode.management.internal.JettyHelper;
+
+public class AbstractManagementController extends AbstractAdminRestController implements
+ ServletContextAware {
+
+ protected static final String MANAGEMENT_API_VERSION = "/v2";
+ protected SecurityService securityService;
+
+ @Override
+ public void setServletContext(ServletContext servletContext) {
+ securityService = (SecurityService) servletContext
+ .getAttribute(JettyHelper.SECURITY_SERVICE_SERVLET_CONTEXT_PARAM);
+ }
+}
diff --git a/geode-web-management/src/main/java/org/apache/geode/management/internal/web/controllers/RegionManagementController.java b/geode-web-management/src/main/java/org/apache/geode/management/internal/web/controllers/RegionManagementController.java
new file mode 100644
index 00000000000..9f016e8d072
--- /dev/null
+++ b/geode-web-management/src/main/java/org/apache/geode/management/internal/web/controllers/RegionManagementController.java
@@ -0,0 +1,40 @@
+/*
+ * 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.management.internal.web.controllers;
+
+import static org.apache.geode.management.internal.web.controllers.AbstractManagementController.MANAGEMENT_API_VERSION;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+import org.apache.geode.cache.configuration.RegionConfig;
+
+@Controller("regionManagement")
+@RequestMapping(MANAGEMENT_API_VERSION)
+public class RegionManagementController extends AbstractManagementController {
+
+ @PreAuthorize("@securityService.authorize('DATA', 'MANAGE')")
+ @RequestMapping(method = RequestMethod.POST, value = "/regions")
+ public ResponseEntity<String> createRegion(@RequestBody RegionConfig regionConfig) {
+ return new ResponseEntity(regionConfig.getName(), HttpStatus.CREATED);
+ }
+
+}
diff --git a/geode-web-management/src/main/java/org/apache/geode/management/internal/web/converter/CustomMappingJackson2HttpMessageConverter.java b/geode-web-management/src/main/java/org/apache/geode/management/internal/web/converter/CustomMappingJackson2HttpMessageConverter.java
new file mode 100644
index 00000000000..2d4dc0113db
--- /dev/null
+++ b/geode-web-management/src/main/java/org/apache/geode/management/internal/web/converter/CustomMappingJackson2HttpMessageConverter.java
@@ -0,0 +1,149 @@
+/*
+ * 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.management.internal.web.converter;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.HttpOutputMessage;
+import org.springframework.http.converter.HttpMessageNotWritableException;
+import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
+import org.springframework.util.Assert;
+
+/**
+ * The CustomMappingJackson2HttpMessageConverter class...
+ *
+ * @see org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
+ * @since GemFire 0.0.1
+ */
+@SuppressWarnings("unused")
+public class CustomMappingJackson2HttpMessageConverter extends MappingJackson2HttpMessageConverter {
+
+ protected static final int INITIAL_BYTE_ARRAY_BUFFER_SIZE = 8192;
+
+ @Override
+ protected void writeInternal(final Object object, final HttpOutputMessage outputMessage)
+ throws IOException, HttpMessageNotWritableException {
+ HttpOutputMessageWrapper outputMessageWrapper =
+ new BufferingHttpOutputMessageWrapper(outputMessage);
+ super.writeInternal(object, outputMessageWrapper);
+ outputMessageWrapper.flush();
+ }
+
+ protected static class BufferingHttpOutputMessageWrapper implements HttpOutputMessageWrapper {
+
+ private final ByteArrayOutputStream outputStream;
+
+ private final HttpOutputMessage httpOutputMessage;
+
+ protected BufferingHttpOutputMessageWrapper(final HttpOutputMessage httpOutputMessage) {
+ Assert.notNull(httpOutputMessage, "The HttpOutputMessage instance to wrap must not be null!");
+ this.httpOutputMessage = httpOutputMessage;
+ this.outputStream = new ByteArrayOutputStream(INITIAL_BYTE_ARRAY_BUFFER_SIZE);
+ }
+
+ @Override
+ public OutputStream getBody() throws IOException {
+ return outputStream;
+ }
+
+ public long getContentLength() {
+ return outputStream.size();
+ }
+
+ @Override
+ public HttpHeaders getHeaders() {
+ return httpOutputMessage.getHeaders();
+ }
+
+ public void flush() throws IOException {
+ getHeaders().setContentLength(getContentLength());
+ outputStream.writeTo(httpOutputMessage.getBody());
+ outputStream.reset();
+ }
+ }
+
+ /**
+ * While sound idea in theory to "count the bytes as you stream/write", thus preserving memory,
+ * this does not work in practice since the HTTP headers must be written to the HTTP output stream
+ * response before the body!
+ */
+ protected static class ContentLengthAccessibleHttpOutputMessageWrapper
+ implements HttpOutputMessageWrapper {
+
+ private final ByteCountingOutputStream outputStream;
+
+ private final HttpOutputMessage httpOutputMessage;
+
+ protected ContentLengthAccessibleHttpOutputMessageWrapper(
+ final HttpOutputMessage httpOutputMessage) throws IOException {
+ Assert.notNull(httpOutputMessage, "The HttpOutputMessage instance to wrap must not be null!");
+ this.httpOutputMessage = httpOutputMessage;
+ this.outputStream = new ByteCountingOutputStream(this.httpOutputMessage.getBody());
+ }
+
+ @Override
+ public OutputStream getBody() throws IOException {
+ return outputStream;
+ }
+
+ public long getContentLength() {
+ return outputStream.getByteCount();
+ }
+
+ @Override
+ public HttpHeaders getHeaders() {
+ return httpOutputMessage.getHeaders();
+ }
+
+ public void flush() throws IOException {
+ getHeaders().setContentLength(getContentLength());
+ }
+ }
+
+ protected interface HttpOutputMessageWrapper extends HttpOutputMessage {
+
+ long getContentLength();
+
+ void flush() throws IOException;
+
+ }
+
+ protected static class ByteCountingOutputStream extends OutputStream {
+
+ private AtomicLong byteCount = new AtomicLong(0l);
+
+ private final OutputStream outputStream;
+
+ protected ByteCountingOutputStream(final OutputStream outputStream) {
+ Assert.notNull(outputStream, "The OutputStream to wrap must not be null!");
+ this.outputStream = outputStream;
+ }
+
+ protected long getByteCount() {
+ return byteCount.get();
+ }
+
+ @Override
+ public void write(final int byteData) throws IOException {
+ outputStream.write(byteData);
+ byteCount.incrementAndGet();
+ }
+ }
+
+}
diff --git a/geode-web-management/src/main/java/org/apache/geode/management/internal/web/security/GeodeAuthenticationProvider.java b/geode-web-management/src/main/java/org/apache/geode/management/internal/web/security/GeodeAuthenticationProvider.java
new file mode 100644
index 00000000000..1d8ef564780
--- /dev/null
+++ b/geode-web-management/src/main/java/org/apache/geode/management/internal/web/security/GeodeAuthenticationProvider.java
@@ -0,0 +1,76 @@
+/*
+ * 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.management.internal.web.security;
+
+import java.util.Properties;
+
+import javax.servlet.ServletContext;
+
+import org.springframework.security.authentication.AuthenticationProvider;
+import org.springframework.security.authentication.BadCredentialsException;
+import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.AuthenticationException;
+import org.springframework.security.core.authority.AuthorityUtils;
+import org.springframework.stereotype.Component;
+import org.springframework.web.context.ServletContextAware;
+
+import org.apache.geode.internal.security.SecurityService;
+import org.apache.geode.management.internal.JettyHelper;
+import org.apache.geode.management.internal.security.ResourceConstants;
+import org.apache.geode.security.GemFireSecurityException;
+
+
+@Component
+public class GeodeAuthenticationProvider implements AuthenticationProvider, ServletContextAware {
+
+ private SecurityService securityService;
+
+
+ public SecurityService getSecurityService() {
+ return this.securityService;
+ }
+
+ @Override
+ public Authentication authenticate(Authentication authentication) throws AuthenticationException {
+ String username = authentication.getName();
+ String password = authentication.getCredentials().toString();
+ Properties credentials = new Properties();
+ if (username != null)
+ credentials.put(ResourceConstants.USER_NAME, username);
+ if (password != null)
+ credentials.put(ResourceConstants.PASSWORD, password);
+
+ try {
+ securityService.login(credentials);
+ return new UsernamePasswordAuthenticationToken(username, password,
+ AuthorityUtils.NO_AUTHORITIES);
+ } catch (GemFireSecurityException e) {
+ throw new BadCredentialsException(e.getLocalizedMessage(), e);
+ }
+ }
+
+ @Override
+ public boolean supports(Class<?> authentication) {
+ return authentication.isAssignableFrom(UsernamePasswordAuthenticationToken.class);
+ }
+
+ @Override
+ public void setServletContext(ServletContext servletContext) {
+ securityService = (SecurityService) servletContext
+ .getAttribute(JettyHelper.SECURITY_SERVICE_SERVLET_CONTEXT_PARAM);
+ }
+}
diff --git a/geode-web-management/src/main/java/org/apache/geode/management/internal/web/security/RestSecurityConfiguration.java b/geode-web-management/src/main/java/org/apache/geode/management/internal/web/security/RestSecurityConfiguration.java
new file mode 100644
index 00000000000..106741c4280
--- /dev/null
+++ b/geode-web-management/src/main/java/org/apache/geode/management/internal/web/security/RestSecurityConfiguration.java
@@ -0,0 +1,63 @@
+/*
+ * 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.management.internal.web.security;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.ComponentScan;
+import org.springframework.context.annotation.Configuration;
+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.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
+import org.springframework.security.config.http.SessionCreationPolicy;
+
+@Configuration
+@EnableWebSecurity
+@EnableGlobalMethodSecurity(prePostEnabled = true)
+@ComponentScan("org.apache.geode.management.internal.web")
+public class RestSecurityConfiguration extends WebSecurityConfigurerAdapter {
+
+ @Autowired
+ private GeodeAuthenticationProvider authProvider;
+
+ @Override
+ protected void configure(AuthenticationManagerBuilder auth) throws Exception {
+ auth.authenticationProvider(authProvider);
+ }
+
+ @Bean
+ @Override
+ public AuthenticationManager authenticationManagerBean() throws Exception {
+ return super.authenticationManagerBean();
+ }
+
+ protected void configure(HttpSecurity http) throws Exception {
+ http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
+ .authorizeRequests()
+ // .antMatchers("/ping", "/docs/**", "/swagger-ui.html", "/v2/api-docs/**",
+ // "/webjars/springfox-swagger-ui/**", "/swagger-resources/**")
+ // .permitAll()
+ .anyRequest().authenticated().and().csrf().disable();
+
+ if (this.authProvider.getSecurityService().isIntegratedSecurity()) {
+ http.httpBasic();
+ } else {
+ http.authorizeRequests().anyRequest().permitAll();
+ }
+ }
+}
diff --git a/geode-web-management/src/main/java/org/apache/geode/management/internal/web/security/RestSecurityService.java b/geode-web-management/src/main/java/org/apache/geode/management/internal/web/security/RestSecurityService.java
new file mode 100644
index 00000000000..4259f7fe08f
--- /dev/null
+++ b/geode-web-management/src/main/java/org/apache/geode/management/internal/web/security/RestSecurityService.java
@@ -0,0 +1,83 @@
+/*
+ * 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.management.internal.web.security;
+
+import javax.servlet.ServletContext;
+
+import org.springframework.stereotype.Component;
+import org.springframework.web.context.ServletContextAware;
+
+import org.apache.geode.internal.security.SecurityService;
+import org.apache.geode.management.internal.JettyHelper;
+import org.apache.geode.security.GemFireSecurityException;
+import org.apache.geode.security.ResourcePermission;
+import org.apache.geode.security.ResourcePermission.Operation;
+import org.apache.geode.security.ResourcePermission.Resource;
+
+@Component("securityService")
+public class RestSecurityService implements ServletContextAware {
+
+ private SecurityService securityService;
+
+ public boolean authorize(String resource, String operation) {
+ return authorize(resource, operation, null, null);
+ }
+
+ public boolean authorize(String resource, String operation, String region) {
+ return authorize(resource, operation, region, null);
+ }
+
+ /**
+ * this does not need to return a boolean since it's not used in the @PreAuthorize tag
+ */
+ public void authorize(ResourcePermission permission) {
+ securityService.authorize(permission);
+ }
+
+
+ /**
+ * calls used in @PreAuthorize tag needs to return a boolean
+ */
+ public boolean authorize(String resource, String operation, String region, String key) {
+ try {
+ securityService.authorize(Resource.valueOf(resource), Operation.valueOf(operation), region,
+ key);
+ return true;
+ } catch (GemFireSecurityException ex) {
+ return false;
+ }
+ }
+
+ public boolean authorize(String operation, String region, String[] keys) {
+ boolean authorized = false;
+ for (String key : keys) {
+ authorized = authorize("DATA", operation, region, key);
+ if (!authorized)
+ return false;
+ }
+ return true;
+ }
+
+ public Object postProcess(String regionPath, Object key, Object value,
+ boolean valueIsSerialized) {
+ return securityService.postProcess(regionPath, key, value, valueIsSerialized);
+ }
+
+ @Override
+ public void setServletContext(ServletContext servletContext) {
+ securityService = (SecurityService) servletContext
+ .getAttribute(JettyHelper.SECURITY_SERVICE_SERVLET_CONTEXT_PARAM);
+ }
+}
diff --git a/geode-web-management/src/main/webapp/META-INF/NOTICE b/geode-web-management/src/main/webapp/META-INF/NOTICE
new file mode 100644
index 00000000000..d4746dd46dd
--- /dev/null
+++ b/geode-web-management/src/main/webapp/META-INF/NOTICE
@@ -0,0 +1,73 @@
+Apache Geode
+Copyright 2016-2018 The Apache Software Foundation.
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
+
+
+The following NOTICEs pertain to software distributed with this project.
+
+stream-lib
+Copyright 2016 AddThis
+
+ This product includes software developed by AddThis.
+
+ This product also includes code adapted from:
+
+ Apache Solr (http://lucene.apache.org/solr/)
+ Copyright 2014 The Apache Software Foundation
+
+This product includes software developed by the MX4J
+project (http://mx4j.sourceforge.net).
+
+Java ClassMate library was originally written by Tatu Saloranta (tatu.saloranta@iki.fi)
+
+ Other developers who have contributed code are:
+
+ * Brian Langel
+
+Jackson Core
+
+ # Jackson JSON processor
+
+ Jackson is a high-performance, Free/Open Source JSON processing library.
+ It was originally written by Tatu Saloranta (tatu.saloranta@iki.fi), and has
+ been in development since 2007.
+ It is currently developed by a community of developers, as well as supported
+ commercially by FasterXML.com.
+
+ ## Licensing
+
+ Jackson core and extension components may licensed under different licenses.
+ To find the details that apply to this artifact see the accompanying LICENSE file.
+ For more information, including possible other licensing options, contact
+ FasterXML.com (http://fasterxml.com).
+
+ ## Credits
+
+ A list of contributors may be found from CREDITS file, which is included
+ in some artifacts (usually source distributions); but is always available
+ from the source code management (SCM) system project uses.
+
+Spring Framework
+Copyright (c) 2002-2017 Pivotal, Inc.
+
+ This product is licensed to you under the Apache License, Version 2.0
+ (the "License"). You may not use this product except in compliance with
+ the License.
+
+ This product may include a number of subcomponents with separate
+ copyright notices and license terms. Your use of the source code for
+ these subcomponents is subject to the terms and conditions of the
+ subcomponent's license, as noted in the license.txt file.
+
+Spring Hateoas
+Copyright (c) [2012-2014] Pivotal Software, Inc.
+
+ This product is licensed to you under the Apache License, Version 2.0 (the "License").
+ You may not use this product except in compliance with the License.
+
+ This product may include a number of subcomponents with
+ separate copyright notices and license terms. Your use of the source
+ code for the these subcomponents is subject to the terms and
+ conditions of the subcomponent's license, as noted in the LICENSE file.
diff --git a/geode-web-management/src/main/webapp/WEB-INF/geode-management-servlet.xml b/geode-web-management/src/main/webapp/WEB-INF/geode-management-servlet.xml
new file mode 100644
index 00000000000..f0d54fe3e17
--- /dev/null
+++ b/geode-web-management/src/main/webapp/WEB-INF/geode-management-servlet.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ ~ agreements. See the NOTICE file distributed with this work for additional information regarding
+ ~ copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance with the License. You may obtain a
+ ~ copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software distributed under the License
+ ~ is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ ~ or implied. See the License for the specific language governing permissions and limitations under
+ ~ the License.
+ -->
+<beans xmlns="http://www.springframework.org/schema/beans"
+ xmlns:context="http://www.springframework.org/schema/context"
+ xmlns:mvc="http://www.springframework.org/schema/mvc"
+ xmlns:p="http://www.springframework.org/schema/p"
+ xmlns:util="http://www.springframework.org/schema/util"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ http://www.springframework.org/schema/beans
+ http://www.springframework.org/schema/beans/spring-beans.xsd
+ http://www.springframework.org/schema/context
+ http://www.springframework.org/schema/context/spring-context.xsd
+ http://www.springframework.org/schema/mvc
+ http://www.springframework.org/schema/mvc/spring-mvc.xsd
+ http://www.springframework.org/schema/util
+ http://www.springframework.org/schema/util/spring-util.xsd
+ ">
+ <context:annotation-config />
+
+ <mvc:annotation-driven content-negotiation-manager="contentNegotiationManager">
+ <mvc:message-converters register-defaults="false">
+ <bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter"/>
+ <bean class="org.springframework.http.converter.ResourceHttpMessageConverter"/>
+ <bean class="org.springframework.http.converter.StringHttpMessageConverter"/>
+ <bean class="org.apache.geode.management.internal.web.converter.CustomMappingJackson2HttpMessageConverter" p:objectMapper-ref="objectMapper"/>
+ </mvc:message-converters>
+ </mvc:annotation-driven>
+
+ <mvc:default-servlet-handler/>
+
+ <bean id="contentNegotiationManager" class="org.springframework.web.accept.ContentNegotiationManagerFactoryBean"
+ p:favorPathExtension="true"
+ p:favorParameter="false"
+ p:ignoreAcceptHeader="false"
+ p:useJaf="false"
+ p:defaultContentType="application/json">
+ <property name="mediaTypes">
+ <value>
+ json=application/json
+ </value>
+ </property>
+ </bean>
+
+ <bean id="objectMapper" class="org.springframework.http.converter.json.Jackson2ObjectMapperFactoryBean"
+ p:failOnEmptyBeans="true"
+ p:indentOutput="true"
+ p:simpleDateFormat="MM/dd/yyyy"
+ >
+ <property name="featuresToEnable">
+ <array>
+ <util:constant static-field="com.fasterxml.jackson.core.JsonParser.Feature.ALLOW_COMMENTS"/>
+ <util:constant static-field="com.fasterxml.jackson.core.JsonParser.Feature.ALLOW_SINGLE_QUOTES"/>
+ <util:constant static-field="com.fasterxml.jackson.databind.DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT"/>
+ </array>
+ </property>
+ <property name="featuresToDisable">
+ <array>
+ <util:constant static-field="com.fasterxml.jackson.databind.DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES"/>
+ </array>
+ </property>
+ </bean>
+
+ <bean class="org.apache.geode.management.internal.web.security.RestSecurityConfiguration" />
+</beans>
diff --git a/geode-web-management/src/main/webapp/WEB-INF/web.xml b/geode-web-management/src/main/webapp/WEB-INF/web.xml
new file mode 100644
index 00000000000..026b0d1101d
--- /dev/null
+++ b/geode-web-management/src/main/webapp/WEB-INF/web.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ ~ agreements. See the NOTICE file distributed with this work for additional information regarding
+ ~ copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance with the License. You may obtain a
+ ~ copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software distributed under the License
+ ~ is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ ~ or implied. See the License for the specific language governing permissions and limitations under
+ ~ the License.
+ -->
+<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>Geode Management REST API</display-name>
+
+ <description>
+ Web deployment descriptor declaring the Geode Management API for Geode.
+ </description>
+
+ <filter>
+ <filter-name>springSecurityFilterChain</filter-name>
+ <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
+ </filter>
+
+ <filter-mapping>
+ <filter-name>springSecurityFilterChain</filter-name>
+ <url-pattern>/*</url-pattern>
+ </filter-mapping>
+
+ <servlet>
+ <description>
+ The Spring DispatcherServlet (FrontController) handling all HTTP requests to the Geode Management REST API.
+ </description>
+ <servlet-name>geode-management</servlet-name>
+ <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
+ <load-on-startup>1</load-on-startup>
+ <async-supported>true</async-supported>
+ </servlet>
+
+ <servlet-mapping>
+ <servlet-name>geode-management</servlet-name>
+ <url-pattern>/*</url-pattern>
+ </servlet-mapping>
+
+</web-app>
diff --git a/geode-web-management/src/test/resources/expected-pom.xml b/geode-web-management/src/test/resources/expected-pom.xml
new file mode 100644
index 00000000000..bc51ae13094
--- /dev/null
+++ b/geode-web-management/src/test/resources/expected-pom.xml
@@ -0,0 +1,877 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ~ Licensed to the Apache Software Foundation (ASF) under one or more contributor license
+ ~ agreements. See the NOTICE file distributed with this work for additional information regarding
+ ~ copyright ownership. The ASF licenses this file to You under the Apache License, Version 2.0 (the
+ ~ "License"); you may not use this file except in compliance with the License. You may obtain a
+ ~ copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software distributed under the License
+ ~ is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ ~ or implied. See the License for the specific language governing permissions and limitations under
+ ~ the License.
+ -->
+
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <!--
+ 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.
+ -->
+ <modelVersion>4.0.0</modelVersion>
+ <groupId>org.apache.geode</groupId>
+ <artifactId>geode-web-api</artifactId>
+ <version>1.9.0-SNAPSHOT</version>
+ <name>Apache Geode</name>
+ <description>Apache Geode provides a database-like consistency model, reliable transaction processing and a shared-nothing architecture to maintain very low latency performance with high concurrency processing</description>
+ <url>http://geode.apache.org</url>
+ <licenses>
+ <license>
+ <name>The Apache Software License, Version 2.0</name>
+ <url>http://www.apache.org/licenses/LICENSE-2.0.txt</url>
+ </license>
+ </licenses>
+ <scm>
+ <connection>scm:git:https://github.com:apache/geode.git</connection>
+ <developerConnection>scm:git:https://github.com:apache/geode.git</developerConnection>
+ <url>https://github.com/apache/geode</url>
+ </scm>
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-lang3</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>commons-fileupload</groupId>
+ <artifactId>commons-fileupload</artifactId>
+ <scope>compile</scope>
+ <exclusions>
+ <exclusion>
+ <artifactId>commons-io</artifactId>
+ <groupId>*</groupId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-annotations</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-core</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.module</groupId>
+ <artifactId>jackson-module-scala_2.10</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>io.springfox</groupId>
+ <artifactId>springfox-swagger2</artifactId>
+ <scope>compile</scope>
+ <exclusions>
+ <exclusion>
+ <artifactId>slf4j-api</artifactId>
+ <groupId>*</groupId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>io.springfox</groupId>
+ <artifactId>springfox-swagger-ui</artifactId>
+ <scope>compile</scope>
+ <exclusions>
+ <exclusion>
+ <artifactId>slf4j-api</artifactId>
+ <groupId>*</groupId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-beans</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.security</groupId>
+ <artifactId>spring-security-core</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.security</groupId>
+ <artifactId>spring-security-web</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.security</groupId>
+ <artifactId>spring-security-config</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-web</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-webmvc</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.hateoas</groupId>
+ <artifactId>spring-hateoas</artifactId>
+ <scope>compile</scope>
+ <exclusions>
+ <exclusion>
+ <artifactId>slf4j-api</artifactId>
+ <groupId>*</groupId>
+ </exclusion>
+ <exclusion>
+ <artifactId>objenesis</artifactId>
+ <groupId>*</groupId>
+ </exclusion>
+ <exclusion>
+ <artifactId>spring-core</artifactId>
+ <groupId>*</groupId>
+ </exclusion>
+ <exclusion>
+ <artifactId>commons-logging</artifactId>
+ <groupId>*</groupId>
+ </exclusion>
+ <exclusion>
+ <artifactId>aopalliance</artifactId>
+ <groupId>*</groupId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-aspects</artifactId>
+ <scope>compile</scope>
+ <exclusions>
+ <exclusion>
+ <artifactId>aopalliance</artifactId>
+ <groupId>*</groupId>
+ </exclusion>
+ <exclusion>
+ <artifactId>aspectjweaver</artifactId>
+ <groupId>*</groupId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-oxm</artifactId>
+ <scope>compile</scope>
+ <exclusions>
+ <exclusion>
+ <artifactId>spring-beans</artifactId>
+ <groupId>*</groupId>
+ </exclusion>
+ <exclusion>
+ <artifactId>spring-core</artifactId>
+ <groupId>*</groupId>
+ </exclusion>
+ <exclusion>
+ <artifactId>commons-logging</artifactId>
+ <groupId>*</groupId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ </dependencies>
+ <dependencyManagement>
+ <dependencies>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-core</artifactId>
+ <version>2.0.0-beta.5</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geode</groupId>
+ <artifactId>geode-wan</artifactId>
+ <version>1.9.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.assertj</groupId>
+ <artifactId>assertj-core</artifactId>
+ <version>3.11.1</version>
+ </dependency>
+ <dependency>
+ <groupId>mx4j</groupId>
+ <artifactId>mx4j-tools</artifactId>
+ <version>3.0.1</version>
+ </dependency>
+ <dependency>
+ <groupId>com.palantir.docker.compose</groupId>
+ <artifactId>docker-compose-rule-core</artifactId>
+ <version>0.31.1</version>
+ </dependency>
+ <dependency>
+ <groupId>com.pholser</groupId>
+ <artifactId>junit-quickcheck-generators</artifactId>
+ <version>0.8.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.lucene</groupId>
+ <artifactId>lucene-core</artifactId>
+ <version>6.6.2</version>
+ </dependency>
+ <dependency>
+ <groupId>redis.clients</groupId>
+ <artifactId>jedis</artifactId>
+ <version>2.9.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.seleniumhq.selenium</groupId>
+ <artifactId>selenium-chrome-driver</artifactId>
+ <version>3.13.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-core</artifactId>
+ <version>1.3</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.protobuf</groupId>
+ <artifactId>protobuf-java</artifactId>
+ <version>3.6.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geode</groupId>
+ <artifactId>geode-core</artifactId>
+ <version>1.9.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-configuration</groupId>
+ <artifactId>commons-configuration</artifactId>
+ <version>1.10</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geode</groupId>
+ <artifactId>geode-old-versions</artifactId>
+ <version>1.9.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-test</artifactId>
+ <version>4.3.20.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>com.carrotsearch.randomizedtesting</groupId>
+ <artifactId>randomizedtesting-runner</artifactId>
+ <version>2.5.0</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <version>27.0-jre</version>
+ </dependency>
+ <dependency>
+ <groupId>org.codehaus.cargo</groupId>
+ <artifactId>cargo-core-uberjar</artifactId>
+ <version>1.6.10</version>
+ </dependency>
+ <dependency>
+ <groupId>com.healthmarketscience.rmiio</groupId>
+ <artifactId>rmiio</artifactId>
+ <version>2.1.2</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.ejb</groupId>
+ <artifactId>ejb-api</artifactId>
+ <version>3.0</version>
+ </dependency>
+ <dependency>
+ <groupId>com.github.stephenc.findbugs</groupId>
+ <artifactId>findbugs-annotations</artifactId>
+ <version>1.3.9-1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geode</groupId>
+ <artifactId>geode-cq</artifactId>
+ <version>1.9.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.annotation</groupId>
+ <artifactId>jsr250-api</artifactId>
+ <version>1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.xml.bind</groupId>
+ <artifactId>jaxb-api</artifactId>
+ <version>2.3.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-library</artifactId>
+ <version>1.3</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geode</groupId>
+ <artifactId>geode-experimental-driver</artifactId>
+ <version>1.9.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.security</groupId>
+ <artifactId>spring-security-web</artifactId>
+ <version>4.2.8.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-api-mockito2</artifactId>
+ <version>2.0.0-beta.5</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-beanutils</groupId>
+ <artifactId>commons-beanutils</artifactId>
+ <version>1.9.3</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.annotation</groupId>
+ <artifactId>javax.annotation-api</artifactId>
+ <version>1.3.2</version>
+ </dependency>
+ <dependency>
+ <groupId>net.sf.jopt-simple</groupId>
+ <artifactId>jopt-simple</artifactId>
+ <version>5.0.4</version>
+ </dependency>
+ <dependency>
+ <groupId>org.jgroups</groupId>
+ <artifactId>jgroups</artifactId>
+ <version>3.6.14.Final</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-core</artifactId>
+ <version>4.3.20.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-modeler</groupId>
+ <artifactId>commons-modeler</artifactId>
+ <version>2.0.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geode</groupId>
+ <artifactId>geode-connectors</artifactId>
+ <version>1.9.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.logging.log4j</groupId>
+ <artifactId>log4j-jul</artifactId>
+ <version>2.11.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.shell</groupId>
+ <artifactId>spring-shell</artifactId>
+ <version>1.2.0.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-collections</groupId>
+ <artifactId>commons-collections</artifactId>
+ <version>3.2.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.hamcrest</groupId>
+ <artifactId>hamcrest-all</artifactId>
+ <version>1.3</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geode</groupId>
+ <artifactId>geode-junit</artifactId>
+ <version>1.9.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <version>4.12</version>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.activation</groupId>
+ <artifactId>javax.activation</artifactId>
+ <version>1.2.0</version>
+ </dependency>
+ <dependency>
+ <groupId>io.springfox</groupId>
+ <artifactId>springfox-swagger-ui</artifactId>
+ <version>2.9.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geode</groupId>
+ <artifactId>geode-rebalancer</artifactId>
+ <version>1.9.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.postgresql</groupId>
+ <artifactId>postgresql</artifactId>
+ <version>42.2.2</version>
+ </dependency>
+ <dependency>
+ <groupId>net.java.dev.jna</groupId>
+ <artifactId>jna</artifactId>
+ <version>4.1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>it.unimi.dsi</groupId>
+ <artifactId>fastutil</artifactId>
+ <version>8.2.2</version>
+ </dependency>
+ <dependency>
+ <groupId>io.springfox</groupId>
+ <artifactId>springfox-swagger2</artifactId>
+ <version>2.9.2</version>
+ </dependency>
+ <dependency>
+ <groupId>com.github.davidmoten</groupId>
+ <artifactId>geo</artifactId>
+ <version>0.7.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-webmvc</artifactId>
+ <version>4.3.20.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geode</groupId>
+ <artifactId>geode-old-client-support</artifactId>
+ <version>1.9.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.ldap</groupId>
+ <artifactId>spring-ldap-core</artifactId>
+ <version>2.3.2.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpcore</artifactId>
+ <version>4.4.10</version>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.module</groupId>
+ <artifactId>jackson-module-scala_2.10</artifactId>
+ <version>2.9.6</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.lucene</groupId>
+ <artifactId>lucene-test-framework</artifactId>
+ <version>6.6.2</version>
+ </dependency>
+ <dependency>
+ <groupId>net.spy</groupId>
+ <artifactId>spymemcached</artifactId>
+ <version>2.12.2</version>
+ </dependency>
+ <dependency>
+ <groupId>mx4j</groupId>
+ <artifactId>mx4j</artifactId>
+ <version>3.0.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-context</artifactId>
+ <version>4.3.20.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>io.github.classgraph</groupId>
+ <artifactId>classgraph</artifactId>
+ <version>4.0.6</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ <version>4.5.6</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.logging.log4j</groupId>
+ <artifactId>log4j-jcl</artifactId>
+ <version>2.11.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.commons</groupId>
+ <artifactId>commons-lang3</artifactId>
+ <version>3.8.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-beans</artifactId>
+ <version>4.3.20.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geode</groupId>
+ <artifactId>geode-web-api</artifactId>
+ <version>1.9.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.mortbay.jetty</groupId>
+ <artifactId>servlet-api</artifactId>
+ <version>3.0.20100224</version>
+ </dependency>
+ <dependency>
+ <groupId>org.fusesource.jansi</groupId>
+ <artifactId>jansi</artifactId>
+ <version>1.17.1</version>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-core</artifactId>
+ <version>2.9.7</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-web</artifactId>
+ <version>4.3.20.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>pl.pragmatists</groupId>
+ <artifactId>JUnitParams</artifactId>
+ <version>1.1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ <version>3.1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.xml.bind</groupId>
+ <artifactId>jaxb-impl</artifactId>
+ <version>2.3.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.bouncycastle</groupId>
+ <artifactId>bcpkix-jdk15on</artifactId>
+ <version>1.60</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.hateoas</groupId>
+ <artifactId>spring-hateoas</artifactId>
+ <version>0.25.0.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-validator</groupId>
+ <artifactId>commons-validator</artifactId>
+ <version>1.6</version>
+ </dependency>
+ <dependency>
+ <groupId>cglib</groupId>
+ <artifactId>cglib</artifactId>
+ <version>3.2.9</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geode</groupId>
+ <artifactId>geode-pulse</artifactId>
+ <version>1.9.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>com.mockrunner</groupId>
+ <artifactId>mockrunner-servlet</artifactId>
+ <version>1.1.2</version>
+ </dependency>
+ <dependency>
+ <groupId>io.netty</groupId>
+ <artifactId>netty-all</artifactId>
+ <version>4.1.31.Final</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.lucene</groupId>
+ <artifactId>lucene-queryparser</artifactId>
+ <version>6.6.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ <version>1.7.25</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.security</groupId>
+ <artifactId>spring-security-core</artifactId>
+ <version>4.2.8.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.security</groupId>
+ <artifactId>spring-security-test</artifactId>
+ <version>4.2.8.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-aspects</artifactId>
+ <version>4.3.20.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.mail</groupId>
+ <artifactId>javax.mail-api</artifactId>
+ <version>1.6.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.httpunit</groupId>
+ <artifactId>httpunit</artifactId>
+ <version>1.7.3</version>
+ </dependency>
+ <dependency>
+ <groupId>org.seleniumhq.selenium</groupId>
+ <artifactId>selenium-support</artifactId>
+ <version>3.13.0</version>
+ </dependency>
+ <dependency>
+ <groupId>com.jayway.jsonpath</groupId>
+ <artifactId>json-path</artifactId>
+ <version>2.4.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geode</groupId>
+ <artifactId>geode-dunit</artifactId>
+ <version>1.9.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.logging.log4j</groupId>
+ <artifactId>log4j-slf4j-impl</artifactId>
+ <version>2.11.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.security</groupId>
+ <artifactId>spring-security-config</artifactId>
+ <version>4.2.8.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.logging.log4j</groupId>
+ <artifactId>log4j-api</artifactId>
+ <version>2.11.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-oxm</artifactId>
+ <version>4.3.20.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.istack</groupId>
+ <artifactId>istack-commons-runtime</artifactId>
+ <version>2.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geode</groupId>
+ <artifactId>apache-geode</artifactId>
+ <version>1.9.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geode</groupId>
+ <artifactId>geode-protobuf-messages</artifactId>
+ <version>1.9.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>com.jayway.jsonpath</groupId>
+ <artifactId>json-path-assert</artifactId>
+ <version>2.4.0</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-logging</groupId>
+ <artifactId>commons-logging</artifactId>
+ <version>1.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geode</groupId>
+ <artifactId>geode-common</artifactId>
+ <version>1.9.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geode</groupId>
+ <artifactId>geode-json</artifactId>
+ <version>1.9.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-annotations</artifactId>
+ <version>2.9.7</version>
+ </dependency>
+ <dependency>
+ <groupId>mx4j</groupId>
+ <artifactId>mx4j-remote</artifactId>
+ <version>3.0.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geode</groupId>
+ <artifactId>geode-web</artifactId>
+ <version>1.9.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>com.github.stefanbirkner</groupId>
+ <artifactId>system-rules</artifactId>
+ <version>1.19.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.persistence</groupId>
+ <artifactId>javax.persistence</artifactId>
+ <version>2.2.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.seleniumhq.selenium</groupId>
+ <artifactId>selenium-remote-driver</artifactId>
+ <version>3.13.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.lucene</groupId>
+ <artifactId>lucene-analyzers-phonetic</artifactId>
+ <version>6.6.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.derby</groupId>
+ <artifactId>derby</artifactId>
+ <version>10.14.2.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework.security</groupId>
+ <artifactId>spring-security-ldap</artifactId>
+ <version>4.2.8.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>mysql</groupId>
+ <artifactId>mysql-connector-java</artifactId>
+ <version>5.1.46</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.lucene</groupId>
+ <artifactId>lucene-analyzers-common</artifactId>
+ <version>6.6.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.powermock</groupId>
+ <artifactId>powermock-module-junit4</artifactId>
+ <version>2.0.0-beta.5</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>2.6</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.logging.log4j</groupId>
+ <artifactId>log4j-core</artifactId>
+ <version>2.11.1</version>
+ </dependency>
+ <dependency>
+ <groupId>javax.resource</groupId>
+ <artifactId>javax.resource-api</artifactId>
+ <version>1.7.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geode</groupId>
+ <artifactId>geode-protobuf</artifactId>
+ <version>1.9.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-tx</artifactId>
+ <version>4.3.20.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>org.seleniumhq.selenium</groupId>
+ <artifactId>selenium-api</artifactId>
+ <version>3.13.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.springframework</groupId>
+ <artifactId>spring-expression</artifactId>
+ <version>4.3.20.RELEASE</version>
+ </dependency>
+ <dependency>
+ <groupId>org.iq80.snappy</groupId>
+ <artifactId>snappy</artifactId>
+ <version>0.4</version>
+ </dependency>
+ <dependency>
+ <groupId>com.zaxxer</groupId>
+ <artifactId>HikariCP</artifactId>
+ <version>3.2.0</version>
+ </dependency>
+ <dependency>
+ <groupId>antlr</groupId>
+ <artifactId>antlr</artifactId>
+ <version>2.7.7</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geode</groupId>
+ <artifactId>geode-lucene</artifactId>
+ <version>1.9.0-SNAPSHOT</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.shiro</groupId>
+ <artifactId>shiro-core</artifactId>
+ <version>1.4.0</version>
+ </dependency>
+ <dependency>
+ <groupId>com.fasterxml.jackson.core</groupId>
+ <artifactId>jackson-databind</artifactId>
+ <version>2.9.7</version>
+ </dependency>
+ <dependency>
+ <groupId>com.palantir.docker.compose</groupId>
+ <artifactId>docker-compose-rule-junit4</artifactId>
+ <version>0.31.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.awaitility</groupId>
+ <artifactId>awaitility</artifactId>
+ <version>3.1.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.mockito</groupId>
+ <artifactId>mockito-core</artifactId>
+ <version>2.23.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.skyscreamer</groupId>
+ <artifactId>jsonassert</artifactId>
+ <version>1.5.0</version>
+ </dependency>
+ <dependency>
+ <groupId>xerces</groupId>
+ <artifactId>xercesImpl</artifactId>
+ <version>2.12.0</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-fileupload</groupId>
+ <artifactId>commons-fileupload</artifactId>
+ <version>1.3.3</version>
+ </dependency>
+ <dependency>
+ <groupId>commons-digester</groupId>
+ <artifactId>commons-digester</artifactId>
+ <version>2.1</version>
+ </dependency>
+ <dependency>
+ <groupId>com.pholser</groupId>
+ <artifactId>junit-quickcheck-core</artifactId>
+ <version>0.8.1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.bcel</groupId>
+ <artifactId>bcel</artifactId>
+ <version>6.2</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.geode</groupId>
+ <artifactId>geode-concurrency-test</artifactId>
+ <version>1.9.0-SNAPSHOT</version>
+ </dependency>
+ </dependencies>
+ </dependencyManagement>
+</project>
diff --git a/gradle/geode-dependency-management.gradle b/gradle/geode-dependency-management.gradle
index c935ee10331..3a27c35181d 100644
--- a/gradle/geode-dependency-management.gradle
+++ b/gradle/geode-dependency-management.gradle
@@ -67,6 +67,7 @@ class GeodeDependencyManagementPlugin implements Plugin<Project> {
entry('geode-wan')
entry('geode-web')
entry('geode-web-api')
+ entry('geode-management-rest-api')
}
// informal, inter-group dependencySet
diff --git a/settings.gradle b/settings.gradle
index a9acd43a3e9..d584f0cb29d 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -30,6 +30,7 @@ include 'geode-dunit'
include 'geode-core'
include 'geode-web'
include 'geode-web-api'
+include 'geode-web-management'
include 'geode-pulse'
include 'geode-pulse:geode-pulse-test'
include 'geode-assembly'
With regards,
Apache Git Services