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 79dbd01 GEODE-6450: ClientClusterManagementService supports ssl
connection (#3276)
79dbd01 is described below
commit 79dbd01d57ae7e9df32976aa993394bf5767df03
Author: jinmeiliao <[email protected]>
AuthorDate: Fri Mar 8 12:53:11 2019 -0800
GEODE-6450: ClientClusterManagementService supports ssl connection (#3276)
Co-authored-by: Jens Deppe <[email protected]>
* provide capability for the client to configure ssl connection when
getting the cluster management service.
* from the server side, create the SSLContext from the ssl configuration
specified on the server
* refactor ssl code
---
...tandaloneClientManagementAPIAcceptanceTest.java | 2 +
.../resources/ManagementClientCreateRegion.java | 2 +-
.../rest/ClientClusterManagementSSLTest.java | 182 +++++++++++++++++++++
.../ClientClusterManagementServiceDunitTest.java | 3 +-
.../integrationTest/resources/assembly_content.txt | 2 +
.../resources/dependency_classpath.txt | 2 +
.../integrationTest/resources/expected_jars.txt | 2 +
...ClusterManagementServiceRetrievalDUnitTest.java | 3 +-
.../apache/geode/internal/cache/HttpService.java | 35 +---
.../apache/geode/management/internal/SSLUtil.java | 114 +++++++++++--
.../api/GeodeClusterManagementServiceFactory.java | 74 ++++++---
.../internal/cli/commands/ConnectCommand.java | 83 +---------
.../internal/cli/domain/MemberInformation.java | 9 +
.../functions/GetMemberInformationFunction.java | 7 +
.../sanctioned-geode-core-serializables.txt | 2 +-
geode-management/build.gradle | 2 +
.../geode/cache/configuration/RegionConfig.java | 2 +-
.../management/api/ClusterManagementService.java | 12 ++
.../geode/management/api/RestfulEndpoint.java | 5 +
.../client/ClusterManagementServiceProvider.java | 77 +++++----
.../internal/ClientClusterManagementService.java | 56 +++++--
.../internal/ClusterManagementServiceFactory.java | 34 ++--
.../JavaClientClusterManagementServiceFactory.java | 28 ++--
.../src/test/resources/expected-pom.xml | 5 +
.../rest/security/RestSecurityConfiguration.java | 2 +-
25 files changed, 508 insertions(+), 237 deletions(-)
diff --git
a/geode-assembly/src/acceptanceTest/java/org/apache/geode/management/internal/rest/StandaloneClientManagementAPIAcceptanceTest.java
b/geode-assembly/src/acceptanceTest/java/org/apache/geode/management/internal/rest/StandaloneClientManagementAPIAcceptanceTest.java
index b0187dd..f2210e6 100644
---
a/geode-assembly/src/acceptanceTest/java/org/apache/geode/management/internal/rest/StandaloneClientManagementAPIAcceptanceTest.java
+++
b/geode-assembly/src/acceptanceTest/java/org/apache/geode/management/internal/rest/StandaloneClientManagementAPIAcceptanceTest.java
@@ -87,6 +87,8 @@ public class StandaloneClientManagementAPIAcceptanceTest {
"jackson-annotations",
"jackson-core",
"jackson-databind",
+ "httpclient",
+ "httpcore",
"spring-beans",
"spring-core",
"spring-web")) {
diff --git
a/geode-assembly/src/acceptanceTest/resources/ManagementClientCreateRegion.java
b/geode-assembly/src/acceptanceTest/resources/ManagementClientCreateRegion.java
index df612f9..2ed8e9b 100644
---
a/geode-assembly/src/acceptanceTest/resources/ManagementClientCreateRegion.java
+++
b/geode-assembly/src/acceptanceTest/resources/ManagementClientCreateRegion.java
@@ -23,7 +23,7 @@ public class ManagementClientTestCreateRegion {
String regionName = args[0];
ClusterManagementService cms =
-
ClusterManagementServiceProvider.getService("http://localhost:7070/geode-management");
+ ClusterManagementServiceProvider.getService("localhost", 7070);
RegionConfig config = new RegionConfig();
config.setName(regionName);
diff --git
a/geode-assembly/src/distributedTest/java/org/apache/geode/management/internal/rest/ClientClusterManagementSSLTest.java
b/geode-assembly/src/distributedTest/java/org/apache/geode/management/internal/rest/ClientClusterManagementSSLTest.java
new file mode 100644
index 0000000..6ef47cf
--- /dev/null
+++
b/geode-assembly/src/distributedTest/java/org/apache/geode/management/internal/rest/ClientClusterManagementSSLTest.java
@@ -0,0 +1,182 @@
+/*
+ * 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.rest;
+
+import static
org.apache.geode.distributed.ConfigurationProperties.SSL_ENABLED_COMPONENTS;
+import static
org.apache.geode.distributed.ConfigurationProperties.SSL_KEYSTORE;
+import static
org.apache.geode.distributed.ConfigurationProperties.SSL_KEYSTORE_PASSWORD;
+import static
org.apache.geode.distributed.ConfigurationProperties.SSL_TRUSTSTORE;
+import static
org.apache.geode.distributed.ConfigurationProperties.SSL_TRUSTSTORE_PASSWORD;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
+import java.io.File;
+import java.util.Properties;
+
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.SSLContext;
+
+import org.apache.http.conn.ssl.NoopHostnameVerifier;
+import org.junit.Before;
+import org.junit.BeforeClass;
+import org.junit.ClassRule;
+import org.junit.Test;
+import org.junit.contrib.java.lang.system.RestoreSystemProperties;
+import org.springframework.web.client.ResourceAccessException;
+
+import org.apache.geode.cache.configuration.CacheConfig;
+import org.apache.geode.cache.configuration.CacheElement;
+import org.apache.geode.cache.configuration.RegionConfig;
+import org.apache.geode.examples.SimpleSecurityManager;
+import org.apache.geode.internal.security.SecurableCommunicationChannel;
+import org.apache.geode.management.api.ClusterManagementResult;
+import org.apache.geode.management.api.ClusterManagementService;
+import org.apache.geode.management.client.ClusterManagementServiceProvider;
+import org.apache.geode.test.dunit.rules.ClusterStartupRule;
+import org.apache.geode.test.dunit.rules.MemberVM;
+
+public class ClientClusterManagementSSLTest {
+
+ @ClassRule
+ public static ClusterStartupRule cluster = new ClusterStartupRule(2);
+
+ private static MemberVM locator, server;
+ private ClusterManagementService cmsClient;
+ private RegionConfig region;
+ private static SSLContext sslContext;
+ private static HostnameVerifier hostnameVerifier;
+
+ @ClassRule
+ public static RestoreSystemProperties restoreSystemProperties = new
RestoreSystemProperties();
+
+ @BeforeClass
+ public static void beforeClass() throws Exception {
+ File keyFile = new
File(ClientClusterManagementSSLTest.class.getClassLoader()
+ .getResource("ssl/trusted.keystore").getFile());
+ Properties sslProps = new Properties();
+ sslProps.setProperty(SSL_KEYSTORE, keyFile.getCanonicalPath());
+ sslProps.setProperty(SSL_TRUSTSTORE, keyFile.getCanonicalPath());
+ sslProps.setProperty(SSL_KEYSTORE_PASSWORD, "password");
+ sslProps.setProperty(SSL_TRUSTSTORE_PASSWORD, "password");
+ sslProps.setProperty(SSL_ENABLED_COMPONENTS,
SecurableCommunicationChannel.WEB.getConstant());
+ locator = cluster.startLocatorVM(0, l ->
l.withHttpService().withProperties(sslProps)
+ .withSecurityManager(SimpleSecurityManager.class));
+ int locatorPort = locator.getPort();
+ server = cluster.startServerVM(1, s ->
s.withConnectionToLocator(locatorPort)
+ .withProperties(sslProps)
+ .withCredential("cluster", "cluster"));
+
+ System.setProperty("javax.net.ssl.keyStore", keyFile.getCanonicalPath());
+ System.setProperty("javax.net.ssl.keyStorePassword", "password");
+ System.setProperty("javax.net.ssl.keyStoreType", "JKS");
+ System.setProperty("javax.net.ssl.trustStore", keyFile.getCanonicalPath());
+ System.setProperty("javax.net.ssl.trustStorePassword", "password");
+ System.setProperty("javax.net.ssl.trustStoreType", "JKS");
+
+ sslContext = SSLContext.getDefault();
+ hostnameVerifier = new NoopHostnameVerifier();
+ }
+
+ @Before
+ public void before() throws Exception {
+ region = new RegionConfig();
+ region.setName("customer");
+ }
+
+ @Test
+ public void createRegion_Successful() throws Exception {
+ cmsClient = ClusterManagementServiceProvider.getService("localhost",
locator.getHttpPort(),
+ sslContext, hostnameVerifier, "dataManage", "dataManage");
+
+ ClusterManagementResult result = cmsClient.create(region);
+ assertThat(result.isSuccessful()).isTrue();
+
assertThat(result.getStatusCode()).isEqualTo(ClusterManagementResult.StatusCode.OK);
+ assertThat(result.getMemberStatuses()).containsKeys("server-1").hasSize(1);
+ }
+
+ @Test
+ public void createRegion_NoSsl() throws Exception {
+ cmsClient = ClusterManagementServiceProvider.getService("localhost",
locator.getHttpPort(),
+ null, null, "dataManage", "dataManage");
+ assertThatThrownBy(() ->
cmsClient.create(region)).isInstanceOf(ResourceAccessException.class);
+ }
+
+ @Test
+ public void createRegion_WrongPassword() throws Exception {
+ cmsClient = ClusterManagementServiceProvider.getService("localhost",
locator.getHttpPort(),
+ sslContext, hostnameVerifier, "dataManage", "wrongPswd");
+
+ ClusterManagementResult result = cmsClient.create(region);
+ assertThat(result.isSuccessful()).isFalse();
+ assertThat(result.getStatusCode())
+ .isEqualTo(ClusterManagementResult.StatusCode.UNAUTHENTICATED);
+ }
+
+ @Test
+ public void createRegion_NoUser() throws Exception {
+ cmsClient = ClusterManagementServiceProvider.getService("localhost",
locator.getHttpPort(),
+ sslContext, hostnameVerifier, null, null);
+
+ ClusterManagementResult result = cmsClient.create(region);
+ assertThat(result.isSuccessful()).isFalse();
+ assertThat(result.getStatusCode())
+ .isEqualTo(ClusterManagementResult.StatusCode.UNAUTHENTICATED);
+ }
+
+ @Test
+ public void createRegion_NoPassword() throws Exception {
+ cmsClient = ClusterManagementServiceProvider.getService("localhost",
locator.getHttpPort(),
+ sslContext, hostnameVerifier, "dataManage", null);
+
+ ClusterManagementResult result = cmsClient.create(region);
+ assertThat(result.isSuccessful()).isFalse();
+ assertThat(result.getStatusCode())
+ .isEqualTo(ClusterManagementResult.StatusCode.UNAUTHENTICATED);
+ }
+
+ @Test
+ public void createRegion_NoPrivilege() throws Exception {
+ cmsClient = ClusterManagementServiceProvider.getService("localhost",
locator.getHttpPort(),
+ sslContext, hostnameVerifier, "dataRead", "dataRead");
+
+ ClusterManagementResult result = cmsClient.create(region);
+ assertThat(result.isSuccessful()).isFalse();
+
assertThat(result.getStatusCode()).isEqualTo(ClusterManagementResult.StatusCode.UNAUTHORIZED);
+ }
+
+ @Test
+ public void invokeFromServer() throws Exception {
+ server.invoke(() -> {
+ // when getting the service from the server, we don't need to provide
the host information
+ ClusterManagementService cmsClient =
+ ClusterManagementServiceProvider.getService("dataManage",
"dataManage");
+ RegionConfig region = new RegionConfig();
+ region.setName("orders");
+ cmsClient.create(region);
+
+ // verify that the region is created on the server
+
assertThat(ClusterStartupRule.getCache().getRegion("/orders")).isNotNull();
+ });
+
+ // verify that the configuration is persisted on the locator
+ locator.invoke(() -> {
+ CacheConfig cacheConfig =
+ ClusterStartupRule.getLocator().getConfigurationPersistenceService()
+ .getCacheConfig("cluster");
+ assertThat(CacheElement.findElement(cacheConfig.getRegions(),
"orders")).isNotNull();
+ });
+ }
+}
diff --git
a/geode-assembly/src/distributedTest/java/org/apache/geode/management/internal/rest/ClientClusterManagementServiceDunitTest.java
b/geode-assembly/src/distributedTest/java/org/apache/geode/management/internal/rest/ClientClusterManagementServiceDunitTest.java
index 2063b15..e09e65a 100644
---
a/geode-assembly/src/distributedTest/java/org/apache/geode/management/internal/rest/ClientClusterManagementServiceDunitTest.java
+++
b/geode-assembly/src/distributedTest/java/org/apache/geode/management/internal/rest/ClientClusterManagementServiceDunitTest.java
@@ -39,8 +39,7 @@ public class ClientClusterManagementServiceDunitTest {
public static void beforeClass() {
locator = cluster.startLocatorVM(0, l -> l.withHttpService());
server = cluster.startServerVM(1, locator.getPort());
- cmsClient = ClusterManagementServiceProvider
- .getService("http://localhost:" + locator.getHttpPort() +
"/geode-management");
+ cmsClient = ClusterManagementServiceProvider.getService("localhost",
locator.getHttpPort());
}
@Test
diff --git a/geode-assembly/src/integrationTest/resources/assembly_content.txt
b/geode-assembly/src/integrationTest/resources/assembly_content.txt
index 6e2a71f..abca10f 100644
--- a/geode-assembly/src/integrationTest/resources/assembly_content.txt
+++ b/geode-assembly/src/integrationTest/resources/assembly_content.txt
@@ -908,6 +908,8 @@ lib/geode-wan-0.0.0.jar
lib/geode-web-0.0.0.jar
lib/gfsh-dependencies.jar
lib/grumpy-core-0.2.2.jar
+lib/httpclient-4.5.6.jar
+lib/httpcore-4.4.10.jar
lib/istack-commons-runtime-2.2.jar
lib/jackson-annotations-2.9.8.jar
lib/jackson-core-2.9.8.jar
diff --git
a/geode-assembly/src/integrationTest/resources/dependency_classpath.txt
b/geode-assembly/src/integrationTest/resources/dependency_classpath.txt
index ff5c134..e488c40 100644
--- a/geode-assembly/src/integrationTest/resources/dependency_classpath.txt
+++ b/geode-assembly/src/integrationTest/resources/dependency_classpath.txt
@@ -25,6 +25,8 @@ geode-protobuf-messages-0.0.0.jar
geode-rebalancer-0.0.0.jar
geode-wan-0.0.0.jar
grumpy-core-0.2.2.jar
+httpclient-4.5.6.jar
+httpcore-4.4.10.jar
istack-commons-runtime-2.2.jar
jackson-annotations-2.9.8.jar
jackson-core-2.9.8.jar
diff --git a/geode-assembly/src/integrationTest/resources/expected_jars.txt
b/geode-assembly/src/integrationTest/resources/expected_jars.txt
index 2f5ae83..1b3e988 100644
--- a/geode-assembly/src/integrationTest/resources/expected_jars.txt
+++ b/geode-assembly/src/integrationTest/resources/expected_jars.txt
@@ -25,6 +25,8 @@ geo
gfsh-dependencies.jar
grumpy-core
guava
+httpclient
+httpcore
istack-commons-runtime
j2objc-annotations
jackson-annotations
diff --git
a/geode-core/src/distributedTest/java/org/apache/geode/management/api/ClusterManagementServiceRetrievalDUnitTest.java
b/geode-core/src/distributedTest/java/org/apache/geode/management/api/ClusterManagementServiceRetrievalDUnitTest.java
index c83d9c6..f34f857 100644
---
a/geode-core/src/distributedTest/java/org/apache/geode/management/api/ClusterManagementServiceRetrievalDUnitTest.java
+++
b/geode-core/src/distributedTest/java/org/apache/geode/management/api/ClusterManagementServiceRetrievalDUnitTest.java
@@ -40,7 +40,8 @@ public class ClusterManagementServiceRetrievalDUnitTest {
x -> x.withHttpService());
server1 = cluster.startServerVM(1, locator.getPort());
- final String url = String.format("http://localhost:%d",
locator.getHttpPort());
+ final String url =
+ String.format("http://localhost:%d/geode-management/v2",
locator.getHttpPort());
server1.invoke(() -> {
ClientClusterManagementService cms =
(ClientClusterManagementService)
ClusterManagementServiceProvider.getService();
diff --git
a/geode-core/src/main/java/org/apache/geode/internal/cache/HttpService.java
b/geode-core/src/main/java/org/apache/geode/internal/cache/HttpService.java
index e7b0bcf..53c0e8a 100644
--- a/geode-core/src/main/java/org/apache/geode/internal/cache/HttpService.java
+++ b/geode-core/src/main/java/org/apache/geode/internal/cache/HttpService.java
@@ -36,7 +36,6 @@ import org.eclipse.jetty.server.handler.HandlerCollection;
import org.eclipse.jetty.util.ssl.SslContextFactory;
import org.eclipse.jetty.webapp.WebAppContext;
-import org.apache.geode.GemFireConfigException;
import org.apache.geode.internal.admin.SSLConfig;
import org.apache.geode.internal.logging.LogService;
import org.apache.geode.management.internal.SSLUtil;
@@ -95,39 +94,7 @@ public class HttpService {
sslContextFactory.setIncludeCipherSuites(SSLUtil.readArray(sslConfig.getCiphers()));
}
- String protocol =
SSLUtil.getSSLAlgo(SSLUtil.readArray(sslConfig.getProtocols()));
- if (protocol != null) {
- sslContextFactory.setProtocol(protocol);
- } else {
- logger.warn("SSL Protocol could not be determined. SSL settings might
not work correctly");
- }
-
- if (StringUtils.isBlank(sslConfig.getKeystore())) {
- throw new GemFireConfigException(
- "Key store can't be empty if SSL is enabled for HttpService");
- }
-
- sslContextFactory.setKeyStorePath(sslConfig.getKeystore());
-
- if (StringUtils.isNotBlank(sslConfig.getKeystoreType())) {
- sslContextFactory.setKeyStoreType(sslConfig.getKeystoreType());
- }
-
- if (StringUtils.isNotBlank(sslConfig.getKeystorePassword())) {
- sslContextFactory.setKeyStorePassword(sslConfig.getKeystorePassword());
- }
-
- if (StringUtils.isNotBlank(sslConfig.getTruststore())) {
- sslContextFactory.setTrustStorePath(sslConfig.getTruststore());
- }
-
- if (StringUtils.isNotBlank(sslConfig.getTruststorePassword())) {
-
sslContextFactory.setTrustStorePassword(sslConfig.getTruststorePassword());
- }
-
- if (StringUtils.isNotBlank(sslConfig.getTruststoreType())) {
- sslContextFactory.setTrustStoreType(sslConfig.getTruststoreType());
- }
+
sslContextFactory.setSslContext(SSLUtil.createAndConfigureSSLContext(sslConfig,
false));
if (logger.isDebugEnabled()) {
logger.debug(sslContextFactory.dump());
diff --git
a/geode-core/src/main/java/org/apache/geode/management/internal/SSLUtil.java
b/geode-core/src/main/java/org/apache/geode/management/internal/SSLUtil.java
index b974dff..931539c 100644
--- a/geode-core/src/main/java/org/apache/geode/management/internal/SSLUtil.java
+++ b/geode-core/src/main/java/org/apache/geode/management/internal/SSLUtil.java
@@ -14,27 +14,37 @@
*/
package org.apache.geode.management.internal;
+import java.io.FileInputStream;
+import java.security.KeyStore;
import java.security.NoSuchAlgorithmException;
+import java.security.SecureRandom;
+import java.security.cert.X509Certificate;
+import java.util.Objects;
+import javax.net.ssl.KeyManager;
+import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.TrustManagerFactory;
+import javax.net.ssl.X509TrustManager;
import org.apache.commons.lang3.StringUtils;
+import org.apache.geode.internal.admin.SSLConfig;
+
/**
*
* @since GemFire 8.1
*/
public class SSLUtil {
-
- public static String getSSLAlgo(String[] protocols) {
- String c = null;
-
+ public static SSLContext getSSLContextInstance(SSLConfig sslConfig) {
+ String[] protocols = sslConfig.getProtocolsAsStringArray();
+ SSLContext sslContext = null;
if (protocols != null && protocols.length > 0) {
for (String protocol : protocols) {
if (!protocol.equals("any")) {
try {
- SSLContext.getInstance(protocol);
- c = protocol;
+ sslContext = SSLContext.getInstance(protocol);
break;
} catch (NoSuchAlgorithmException e) {
// continue
@@ -42,21 +52,20 @@ public class SSLUtil {
}
}
}
- if (c != null) {
- return c;
+ if (sslContext != null) {
+ return sslContext;
}
// lookup known algorithms
String[] knownAlgorithms = {"SSL", "SSLv2", "SSLv3", "TLS", "TLSv1",
"TLSv1.1", "TLSv1.2"};
for (String algo : knownAlgorithms) {
try {
- SSLContext.getInstance(algo);
- c = algo;
+ sslContext = SSLContext.getInstance(algo);
break;
} catch (NoSuchAlgorithmException e) {
// continue
}
}
- return c;
+ return sslContext;
}
/** Read an array of values from a string, whitespace or comma separated. */
@@ -68,4 +77,87 @@ public class SSLUtil {
return text.split("[\\s,]+");
}
+ public static SSLContext createAndConfigureSSLContext(SSLConfig sslConfig,
+ boolean skipSslVerification) {
+ try {
+ if (sslConfig.useDefaultSSLContext()) {
+ return SSLContext.getDefault();
+ }
+ SSLContext ssl = getSSLContextInstance(sslConfig);
+
+ KeyManager[] keyManagers = getKeyManagers(sslConfig);
+ TrustManager[] trustManagers = getTrustManagers(sslConfig,
skipSslVerification);
+
+ ssl.init(keyManagers, trustManagers, new SecureRandom());
+ return ssl;
+ } catch (Exception e) {
+ throw new RuntimeException(e.getMessage(), e);
+ }
+ }
+
+ private static KeyManager[] getKeyManagers(SSLConfig sslConfig) throws
Exception {
+ FileInputStream keyStoreStream = null;
+ KeyManagerFactory keyManagerFactory = null;
+
+ try {
+ if (StringUtils.isNotBlank(sslConfig.getKeystore())) {
+ String keyStoreType = Objects.toString(sslConfig.getKeystoreType(),
"JKS");
+ KeyStore clientKeys = KeyStore.getInstance(keyStoreType);
+ keyStoreStream = new FileInputStream(sslConfig.getKeystore());
+ clientKeys.load(keyStoreStream,
sslConfig.getKeystorePassword().toCharArray());
+
+ keyManagerFactory =
+
KeyManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+ keyManagerFactory.init(clientKeys,
sslConfig.getKeystorePassword().toCharArray());
+ }
+ } finally {
+ if (keyStoreStream != null) {
+ keyStoreStream.close();
+ }
+ }
+
+ return keyManagerFactory != null ? keyManagerFactory.getKeyManagers() :
null;
+ }
+
+ private static TrustManager[] getTrustManagers(SSLConfig sslConfig, boolean
skipSslVerification)
+ throws Exception {
+ FileInputStream trustStoreStream = null;
+ TrustManagerFactory trustManagerFactory = null;
+
+ if (skipSslVerification) {
+ TrustManager[] trustAllCerts = new TrustManager[] {new
X509TrustManager() {
+ @Override
+ public java.security.cert.X509Certificate[] getAcceptedIssuers() {
+ return null;
+ }
+
+ @Override
+ public void checkClientTrusted(X509Certificate[] certs, String
authType) {}
+
+ @Override
+ public void checkServerTrusted(X509Certificate[] certs, String
authType) {}
+
+ }};
+ return trustAllCerts;
+ }
+
+ try {
+ // load server public key
+ if (StringUtils.isNotBlank(sslConfig.getTruststore())) {
+ String trustStoreType =
Objects.toString(sslConfig.getTruststoreType(), "JKS");
+ KeyStore serverPub = KeyStore.getInstance(trustStoreType);
+ trustStoreStream = new FileInputStream(sslConfig.getTruststore());
+ serverPub.load(trustStoreStream,
sslConfig.getTruststorePassword().toCharArray());
+ trustManagerFactory =
+
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
+ trustManagerFactory.init(serverPub);
+ }
+ } finally {
+ if (trustStoreStream != null) {
+ trustStoreStream.close();
+ }
+ }
+ return trustManagerFactory != null ?
trustManagerFactory.getTrustManagers() : null;
+ }
+
}
diff --git
a/geode-core/src/main/java/org/apache/geode/management/internal/api/GeodeClusterManagementServiceFactory.java
b/geode-core/src/main/java/org/apache/geode/management/internal/api/GeodeClusterManagementServiceFactory.java
index d013e43..69fa458 100644
---
a/geode-core/src/main/java/org/apache/geode/management/internal/api/GeodeClusterManagementServiceFactory.java
+++
b/geode-core/src/main/java/org/apache/geode/management/internal/api/GeodeClusterManagementServiceFactory.java
@@ -18,7 +18,11 @@ package org.apache.geode.management.internal.api;
import java.util.List;
import java.util.Set;
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.SSLContext;
+
import org.apache.commons.lang3.StringUtils;
+import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.logging.log4j.Logger;
import org.apache.geode.annotations.Immutable;
@@ -31,13 +35,16 @@ import org.apache.geode.cache.execute.FunctionService;
import org.apache.geode.cache.execute.ResultCollector;
import org.apache.geode.distributed.internal.InternalLocator;
import
org.apache.geode.distributed.internal.membership.InternalDistributedMember;
+import org.apache.geode.internal.admin.SSLConfig;
import org.apache.geode.internal.cache.GemFireCacheImpl;
import org.apache.geode.internal.logging.LogService;
+import org.apache.geode.internal.net.SSLConfigurationFactory;
+import org.apache.geode.internal.security.SecurableCommunicationChannel;
import org.apache.geode.management.api.ClusterManagementService;
import org.apache.geode.management.client.ClusterManagementServiceProvider;
-import org.apache.geode.management.internal.ClientClusterManagementService;
import org.apache.geode.management.internal.ClusterManagementServiceFactory;
import
org.apache.geode.management.internal.JavaClientClusterManagementServiceFactory;
+import org.apache.geode.management.internal.SSLUtil;
import org.apache.geode.management.internal.cli.domain.MemberInformation;
import
org.apache.geode.management.internal.cli.functions.GetMemberInformationFunction;
@@ -47,8 +54,8 @@ import
org.apache.geode.management.internal.cli.functions.GetMemberInformationFu
* address of the {@code ClusterManagementService} when using the {@code
create()} call. Otherwise
* an explicit can also be used.
*/
-public class GeodeClusterManagementServiceFactory extends
- JavaClientClusterManagementServiceFactory {
+public class GeodeClusterManagementServiceFactory
+ extends JavaClientClusterManagementServiceFactory {
@Immutable
private static final GetMemberInformationFunction
MEMBER_INFORMATION_FUNCTION =
@@ -61,8 +68,12 @@ public class GeodeClusterManagementServiceFactory extends
return ClusterManagementServiceProvider.GEODE_CONTEXT;
}
+ public ClusterManagementService create() {
+ return create(null, null);
+ }
+
@Override
- public ClusterManagementService create() throws IllegalStateException {
+ public ClusterManagementService create(String username, String password) {
if (InternalLocator.getLocator() != null) {
return InternalLocator.getLocator().getClusterManagementService();
}
@@ -74,45 +85,52 @@ public class GeodeClusterManagementServiceFactory extends
Set<InternalDistributedMember> locatorsWithClusterConfig =
cacheImpl.getDistributionManager().getAllHostedLocatorsWithSharedConfiguration()
.keySet();
- String serviceAddress = getHttpServiceAddress(locatorsWithClusterConfig);
- return new ClientClusterManagementService(serviceAddress);
+ MemberInformation memberInformation =
getHttpServiceAddress(locatorsWithClusterConfig);
+
+ SSLContext sslContext = null;
+ HostnameVerifier hostnameVerifier = null;
+ if (memberInformation.isSsl()) {
+ SSLConfig sslConfig = SSLConfigurationFactory.getSSLConfigForComponent(
+ ((GemFireCacheImpl) cache).getSystem().getConfig(),
SecurableCommunicationChannel.WEB);
+ if (sslConfig.getTruststore() == null) {
+ throw new IllegalStateException(
+ "The server needs to have truststore specified in order to use
cluster management service.");
+ }
+
+ sslContext = SSLUtil.createAndConfigureSSLContext(sslConfig, false);
+ hostnameVerifier = new NoopHostnameVerifier();
+ }
+
+ return create(getHostName(memberInformation),
memberInformation.getHttpServicePort(),
+ sslContext, hostnameVerifier, username, password);
}
ClientCache clientCache = ClientCacheFactory.getAnyInstance();
if (clientCache != null) {
throw new IllegalStateException(
- "Under construction. To retrieve an instance of
ClusterManagementService from a Geode client, please use either
create(clusterUrl) or create(requestFactory) methods");
+ "Under construction. To retrieve an instance of
ClusterManagementService from a Geode client, please use other methods");
}
// } catch( CacheClosedException e) {
throw new IllegalStateException("ClusterManagementService.create() " +
"must be executed on one of locator, server or client cache VMs");
}
- private String getHttpServiceAddress(Set<InternalDistributedMember>
locators) {
- for (InternalDistributedMember locator : locators) {
+ private MemberInformation
getHttpServiceAddress(Set<InternalDistributedMember> locators) {
+ for (InternalDistributedMember locator : locators) {
try {
ResultCollector resultCollector =
FunctionService.onMember(locator).execute(MEMBER_INFORMATION_FUNCTION);
- List<MemberInformation> memberInformation =
+ List<MemberInformation> memberInformations =
(List<MemberInformation>) resultCollector.getResult();
// Is this even possible?
- if (memberInformation.isEmpty()) {
+ if (memberInformations.isEmpty()) {
continue;
}
- // What address to use
- String host;
- if
(StringUtils.isNotBlank(memberInformation.get(0).getHttpServiceBindAddress())) {
- host = memberInformation.get(0).getHttpServiceBindAddress();
- } else if
(StringUtils.isNotBlank(memberInformation.get(0).getServerBindAddress())) {
- host = memberInformation.get(0).getServerBindAddress();
- } else {
- host = memberInformation.get(0).getHost();
- }
-
- return String.format("http://%s:%d", host,
memberInformation.get(0).getHttpServicePort());
+ // return the first available one. Later for HA, we can return the
entire list
+ return memberInformations.get(0);
} catch (FunctionException e) {
logger.warn("Unable to execute GetMemberInformationFunction on " +
locator.getId());
throw new IllegalStateException(e);
@@ -121,4 +139,16 @@ public class GeodeClusterManagementServiceFactory extends
throw new IllegalStateException("Unable to determine
ClusterManagementService endpoint");
}
+
+ private String getHostName(MemberInformation memberInformation) {
+ String host;
+ if (StringUtils.isNotBlank(memberInformation.getHttpServiceBindAddress()))
{
+ host = memberInformation.getHttpServiceBindAddress();
+ } else if
(StringUtils.isNotBlank(memberInformation.getServerBindAddress())) {
+ host = memberInformation.getServerBindAddress();
+ } else {
+ host = memberInformation.getHost();
+ }
+ return host;
+ }
}
diff --git
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ConnectCommand.java
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ConnectCommand.java
index 25d49d9..e8cfa3d 100644
---
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ConnectCommand.java
+++
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/commands/ConnectCommand.java
@@ -20,26 +20,17 @@ import static
org.apache.geode.distributed.ConfigurationProperties.HTTP_SERVICE_
import static
org.apache.geode.distributed.ConfigurationProperties.JMX_MANAGER_SSL_PREFIX;
import java.io.File;
-import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
-import java.security.KeyStore;
-import java.security.SecureRandom;
-import java.security.cert.X509Certificate;
import java.util.Arrays;
import java.util.Objects;
import java.util.Properties;
import javax.net.ssl.HttpsURLConnection;
-import javax.net.ssl.KeyManager;
-import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLSession;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.TrustManagerFactory;
-import javax.net.ssl.X509TrustManager;
import org.apache.commons.lang3.StringUtils;
import org.springframework.shell.core.annotation.CliCommand;
@@ -429,83 +420,13 @@ public class ConnectCommand extends OfflineGfshCommand {
locatorResponse.isJmxManagerSslEnabled());
}
- private KeyManager[] getKeyManagers(SSLConfig sslConfig) throws Exception {
- FileInputStream keyStoreStream = null;
- KeyManagerFactory keyManagerFactory = null;
- try {
- if (StringUtils.isNotBlank(sslConfig.getKeystore())) {
- KeyStore clientKeys =
KeyStore.getInstance(sslConfig.getKeystoreType());
- keyStoreStream = new FileInputStream(sslConfig.getKeystore());
- clientKeys.load(keyStoreStream,
sslConfig.getKeystorePassword().toCharArray());
-
- keyManagerFactory =
-
KeyManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
- keyManagerFactory.init(clientKeys,
sslConfig.getKeystorePassword().toCharArray());
- }
- } finally {
- if (keyStoreStream != null) {
- keyStoreStream.close();
- }
- }
-
- return keyManagerFactory != null ? keyManagerFactory.getKeyManagers() :
null;
- }
-
- private TrustManager[] getTrustManagers(SSLConfig sslConfig, boolean
skipSslVerification)
- throws Exception {
- FileInputStream trustStoreStream = null;
- TrustManagerFactory trustManagerFactory = null;
-
- if (skipSslVerification) {
- TrustManager[] trustAllCerts = new TrustManager[] {new
X509TrustManager() {
- @Override
- public java.security.cert.X509Certificate[] getAcceptedIssuers() {
- return null;
- }
-
- @Override
- public void checkClientTrusted(X509Certificate[] certs, String
authType) {}
-
- @Override
- public void checkServerTrusted(X509Certificate[] certs, String
authType) {}
-
- }};
- return trustAllCerts;
- }
-
- try {
- // load server public key
- if (StringUtils.isNotBlank(sslConfig.getTruststore())) {
- KeyStore serverPub =
KeyStore.getInstance(sslConfig.getTruststoreType());
- trustStoreStream = new FileInputStream(sslConfig.getTruststore());
- serverPub.load(trustStoreStream,
sslConfig.getTruststorePassword().toCharArray());
- trustManagerFactory =
-
TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
- trustManagerFactory.init(serverPub);
- }
- } finally {
- if (trustStoreStream != null) {
- trustStoreStream.close();
- }
- }
- return trustManagerFactory != null ?
trustManagerFactory.getTrustManagers() : null;
- }
-
- private void configureHttpsURLConnection(SSLConfig sslConfig, boolean
skipSslVerification)
- throws Exception {
- KeyManager[] keyManagers = getKeyManagers(sslConfig);
- TrustManager[] trustManagers = getTrustManagers(sslConfig,
skipSslVerification);
+ private void configureHttpsURLConnection(SSLConfig sslConfig, boolean
skipSslVerification) {
+ SSLContext ssl = SSLUtil.createAndConfigureSSLContext(sslConfig,
skipSslVerification);
if (skipSslVerification) {
HttpsURLConnection.setDefaultHostnameVerifier((String s, SSLSession
sslSession) -> true);
}
-
- SSLContext ssl =
-
SSLContext.getInstance(SSLUtil.getSSLAlgo(SSLUtil.readArray(sslConfig.getProtocols())));
-
- ssl.init(keyManagers, trustManagers, new SecureRandom());
-
HttpsURLConnection.setDefaultSSLSocketFactory(ssl.getSocketFactory());
}
diff --git
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/domain/MemberInformation.java
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/domain/MemberInformation.java
index 357b976..0d7b9ce 100644
---
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/domain/MemberInformation.java
+++
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/domain/MemberInformation.java
@@ -50,6 +50,7 @@ public class MemberInformation implements Serializable {
private double cpuUsage;
private Set<String> hostedRegions;
private String offHeapMemorySize;
+ private boolean ssl;
public String getName() {
return name;
@@ -239,4 +240,12 @@ public class MemberInformation implements Serializable {
public void setOffHeapMemorySize(String v) {
this.offHeapMemorySize = v;
}
+
+ public boolean isSsl() {
+ return ssl;
+ }
+
+ public void setSsl(boolean ssl) {
+ this.ssl = ssl;
+ }
}
diff --git
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/GetMemberInformationFunction.java
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/GetMemberInformationFunction.java
index 88c4ee4..0a248a4 100644
---
a/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/GetMemberInformationFunction.java
+++
b/geode-core/src/main/java/org/apache/geode/management/internal/cli/functions/GetMemberInformationFunction.java
@@ -28,11 +28,14 @@ import org.apache.geode.cache.server.CacheServer;
import org.apache.geode.distributed.DistributedMember;
import org.apache.geode.distributed.internal.DistributionConfig;
import org.apache.geode.distributed.internal.InternalDistributedSystem;
+import org.apache.geode.internal.admin.SSLConfig;
import org.apache.geode.internal.cache.CacheClientStatus;
import org.apache.geode.internal.cache.InternalCache;
import org.apache.geode.internal.cache.execute.InternalFunction;
import org.apache.geode.internal.cache.tier.InternalClientMembership;
import org.apache.geode.internal.cache.tier.sockets.ClientProxyMembershipID;
+import org.apache.geode.internal.net.SSLConfigurationFactory;
+import org.apache.geode.internal.security.SecurableCommunicationChannel;
import org.apache.geode.management.internal.cli.CliUtil;
import org.apache.geode.management.internal.cli.domain.CacheServerInfo;
import org.apache.geode.management.internal.cli.domain.MemberInformation;
@@ -87,6 +90,9 @@ public class GetMemberInformationFunction implements
InternalFunction {
memberInfo.setHost(member.getHost());
memberInfo.setProcessId("" + member.getProcessId());
+ SSLConfig sslConfig =
SSLConfigurationFactory.getSSLConfigForComponent(config,
+ SecurableCommunicationChannel.WEB);
+ memberInfo.setSsl(sslConfig.isEnabled());
memberInfo.setGroups(config.getGroups());
memberInfo.setLogFilePath(config.getLogFile().getCanonicalPath());
memberInfo.setStatArchiveFilePath(config.getStatisticArchiveFile().getCanonicalPath());
@@ -96,6 +102,7 @@ public class GetMemberInformationFunction implements
InternalFunction {
memberInfo.setServerBindAddress(config.getServerBindAddress());
memberInfo.setOffHeapMemorySize(config.getOffHeapMemorySize());
memberInfo.setHttpServicePort(config.getHttpServicePort());
+
memberInfo.setHttpServiceBindAddress(config.getHttpServiceBindAddress());
MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
diff --git
a/geode-core/src/main/resources/org/apache/geode/internal/sanctioned-geode-core-serializables.txt
b/geode-core/src/main/resources/org/apache/geode/internal/sanctioned-geode-core-serializables.txt
index 4d46693..de29bf1 100644
---
a/geode-core/src/main/resources/org/apache/geode/internal/sanctioned-geode-core-serializables.txt
+++
b/geode-core/src/main/resources/org/apache/geode/internal/sanctioned-geode-core-serializables.txt
@@ -525,7 +525,7 @@
org/apache/geode/management/internal/cli/domain/FixedPartitionAttributesInfo,tru
org/apache/geode/management/internal/cli/domain/IndexDetails,true,-2198907141534201288,fromClause:java/lang/String,indexName:java/lang/String,indexStatisticsDetails:org/apache/geode/management/internal/cli/domain/IndexDetails$IndexStatisticsDetails,indexType:org/apache/geode/cache/query/IndexType,indexedExpression:java/lang/String,isValid:boolean,memberId:java/lang/String,memberName:java/lang/String,projectionAttributes:java/lang/String,regionName:java/lang/String,regionPath:java/lang/String
org/apache/geode/management/internal/cli/domain/IndexDetails$IndexStatisticsDetails,false,numberOfKeys:java/lang/Long,numberOfUpdates:java/lang/Long,numberOfValues:java/lang/Long,totalUpdateTime:java/lang/Long,totalUses:java/lang/Long
org/apache/geode/management/internal/cli/domain/MemberConfigurationInfo,false,cacheAttributes:java/util/Map,cacheServerAttributes:java/util/List,gfePropsRuntime:java/util/Map,gfePropsSetFromFile:java/util/Map,gfePropsSetUsingApi:java/util/Map,gfePropsSetWithDefaults:java/util/Map,jvmInputArguments:java/util/List,pdxAttributes:java/util/Map,systemProperties:java/util/Properties
-org/apache/geode/management/internal/cli/domain/MemberInformation,true,1,cacheServerList:java/util/List,cacheXmlFilePath:java/lang/String,clientCount:int,cpuUsage:double,groups:java/lang/String,heapUsage:java/lang/String,host:java/lang/String,hostedRegions:java/util/Set,httpServiceBindAddress:java/lang/String,httpServicePort:int,id:java/lang/String,initHeapSize:java/lang/String,isServer:boolean,locatorPort:int,locators:java/lang/String,logFilePath:java/lang/String,maxHeapSize:java/lang/S
[...]
+org/apache/geode/management/internal/cli/domain/MemberInformation,true,1,cacheServerList:java/util/List,cacheXmlFilePath:java/lang/String,clientCount:int,cpuUsage:double,groups:java/lang/String,heapUsage:java/lang/String,host:java/lang/String,hostedRegions:java/util/Set,httpServiceBindAddress:java/lang/String,httpServicePort:int,id:java/lang/String,initHeapSize:java/lang/String,isServer:boolean,locatorPort:int,locators:java/lang/String,logFilePath:java/lang/String,maxHeapSize:java/lang/S
[...]
org/apache/geode/management/internal/cli/domain/PartitionAttributesInfo,true,1,colocatedWith:java/lang/String,fpaInfoList:java/util/List,localMaxMemory:int,nonDefaultAttributes:java/util/Map,partitionResolverName:java/lang/String,recoveryDelay:long,redundantCopies:int,startupRecoveryDelay:long,totalNumBuckets:int
org/apache/geode/management/internal/cli/domain/RegionAttributesInfo,true,336184564012988487,asyncEventQueueIDs:java/util/Set,cacheListenerClassNames:java/util/List,cacheLoaderClassName:java/lang/String,cacheWriterClassName:java/lang/String,cloningEnabled:boolean,compressorClassName:java/lang/String,concurrencyChecksEnabled:boolean,concurrencyLevel:int,customExpiryIdleTimeoutClass:java/lang/String,customExpiryTTLClass:java/lang/String,dataPolicy:org/apache/geode/cache/DataPolicy,diskStor
[...]
org/apache/geode/management/internal/cli/domain/RegionDescription,true,6461449275798378332,cndEvictionAttributes:java/util/Map,cndPartitionAttributes:java/util/Map,cndRegionAttributes:java/util/Map,dataPolicy:org/apache/geode/cache/DataPolicy,isAccessor:boolean,isLocal:boolean,isPartition:boolean,isPersistent:boolean,isReplicate:boolean,name:java/lang/String,regionDescPerMemberMap:java/util/Map,scope:org/apache/geode/cache/Scope
diff --git a/geode-management/build.gradle b/geode-management/build.gradle
index 091f79c..a30d1df 100755
--- a/geode-management/build.gradle
+++ b/geode-management/build.gradle
@@ -25,6 +25,8 @@ dependencies {
compile('com.fasterxml.jackson.core:jackson-annotations')
compile('org.springframework:spring-web')
compile('javax.xml.bind:jaxb-api')
+ compile('javax.xml.bind:jaxb-api')
+ compile('org.apache.httpcomponents:httpclient')
compileOnly(project(':geode-common')) {
exclude module: 'junit'
diff --git
a/geode-management/src/main/java/org/apache/geode/cache/configuration/RegionConfig.java
b/geode-management/src/main/java/org/apache/geode/cache/configuration/RegionConfig.java
index 45a063a..eae46ba 100644
---
a/geode-management/src/main/java/org/apache/geode/cache/configuration/RegionConfig.java
+++
b/geode-management/src/main/java/org/apache/geode/cache/configuration/RegionConfig.java
@@ -175,7 +175,7 @@ public class RegionConfig implements CacheElement,
RestfulEndpoint {
@Override
public String getEndpoint() {
- return "/v2/regions";
+ return "/regions";
}
public RegionAttributesType getRegionAttributes() {
diff --git
a/geode-management/src/main/java/org/apache/geode/management/api/ClusterManagementService.java
b/geode-management/src/main/java/org/apache/geode/management/api/ClusterManagementService.java
index 2b33cea..658906e 100644
---
a/geode-management/src/main/java/org/apache/geode/management/api/ClusterManagementService.java
+++
b/geode-management/src/main/java/org/apache/geode/management/api/ClusterManagementService.java
@@ -36,6 +36,10 @@ public interface ClusterManagementService {
*/
ClusterManagementResult create(CacheElement config, String group);
+ default ClusterManagementResult create(CacheElement config) {
+ return create(config, null);
+ }
+
/**
* This method will delete the element on all the applicable members in the
cluster and update the
* configuration in the cluster configuration if persistence is enabled.
@@ -48,6 +52,10 @@ public interface ClusterManagementService {
*/
ClusterManagementResult delete(CacheElement config, String group);
+ default ClusterManagementResult delete(CacheElement config) {
+ return delete(config, null);
+ }
+
/**
* This method will update the element on all the applicable members in the
cluster and persist
* the updated configuration in the cluster configuration if persistence is
enabled.
@@ -60,4 +68,8 @@ public interface ClusterManagementService {
*/
ClusterManagementResult update(CacheElement config, String group);
+ default ClusterManagementResult update(CacheElement config) {
+ return update(config, null);
+ }
+
}
diff --git
a/geode-management/src/main/java/org/apache/geode/management/api/RestfulEndpoint.java
b/geode-management/src/main/java/org/apache/geode/management/api/RestfulEndpoint.java
index 81736df..591c399 100644
---
a/geode-management/src/main/java/org/apache/geode/management/api/RestfulEndpoint.java
+++
b/geode-management/src/main/java/org/apache/geode/management/api/RestfulEndpoint.java
@@ -17,5 +17,10 @@ package org.apache.geode.management.api;
public interface RestfulEndpoint {
+ /**
+ * this needs to return the uri portion after the /geode-management/v2
+ *
+ * @return e.g. /regions
+ */
String getEndpoint();
}
diff --git
a/geode-management/src/main/java/org/apache/geode/management/client/ClusterManagementServiceProvider.java
b/geode-management/src/main/java/org/apache/geode/management/client/ClusterManagementServiceProvider.java
index a1fc1ce..ec2703a 100644
---
a/geode-management/src/main/java/org/apache/geode/management/client/ClusterManagementServiceProvider.java
+++
b/geode-management/src/main/java/org/apache/geode/management/client/ClusterManagementServiceProvider.java
@@ -19,6 +19,9 @@ import java.util.HashMap;
import java.util.Map;
import java.util.ServiceLoader;
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.SSLContext;
+
import org.springframework.http.client.ClientHttpRequestFactory;
import org.apache.geode.annotations.Experimental;
@@ -67,64 +70,58 @@ public class ClusterManagementServiceProvider {
private static Map<String, ClusterManagementServiceFactory> serviceFactories
= null;
/**
- * Without any options, this method will try to retrieve the correct
- * {@code ClusterManagementService} dependent on the context in which it is
called - relevant
- * contexts are locators, servers and geode clients (essentially wherever a
{@code Cache} or
- * {@code ClientCache} exist).
- *
- * @return a {@code ClusterManagementService} instance configured to connect
to the service
- * endpoint.
- * @throws IllegalArgumentException if the service instance cannot be
retrieved, for example if
- * not called from a suitable context.
+ * use this to get the ClusterManagementService from the locator, or from a
server that connects
+ * to a locator with no security manager.
*/
public static ClusterManagementService getService() {
return getServiceFactory(GEODE_CONTEXT).create();
}
/**
+ * use this retrieve a ClusterManagementService from a server that connects
to a secured locator
+ */
+ public static ClusterManagementService getService(String username, String
password) {
+ return getServiceFactory(GEODE_CONTEXT).create(username, password);
+ }
+
+ /**
* Retrieve a {@code ClusterManagementService} instance configured with an
explicit service
- * endpoint.
+ * endpoint. this is good for end point with no ssl nor security turned on.
* <p/>
* For example:
*
* <pre>
- *
ClusterManagementServiceProvider.getService("http://locator-host:7070/geode-management")
+ * ClusterManagementServiceProvider.getService("locatorHost", "7070")
* </pre>
*
- * @param clusterUrl the URL of the Cluster Management Service running on a
locator. The port
- * used is as configured by the <i>http-service-port</i> property on
the Geode locator.
- * @return a {@code ClusterManagementService} instance configured to connect
to the service
- * endpoint.
* @throws IllegalArgumentException if the provided url is malformed
*/
- public static ClusterManagementService getService(String clusterUrl) {
- return getServiceFactory(JAVA_CLIENT_CONTEXT).create(clusterUrl);
+ public static ClusterManagementService getService(String host, int port) {
+ return getServiceFactory(JAVA_CLIENT_CONTEXT).create(host, port, null,
null, null, null);
}
/**
- * Retrieve a {@code ClusterManagementService} instance configured with a
- * {@link ClientHttpRequestFactory}. This would be required when connecting
to a SSL enabled
- * endpoint.
- * <p/>
- * For example:
- *
- * <pre>
- * String clusterUrl = "https://locator-host:7070/geode-management";
- *
- * HttpComponentsClientHttpRequestFactory requestFactory = new
HttpComponentsClientHttpRequestFactory();
- * DefaultHttpClient httpClient = (DefaultHttpClient)
requestFactory.getHttpClient();
- * TrustStrategy acceptingTrustStrategy = (cert, authType) -> true;
- * SSLSocketFactory sf = new SSLSocketFactory(acceptingTrustStrategy,
ALLOW_ALL_HOSTNAME_VERIFIER);
- * httpClient.getConnectionManager().getSchemeRegistry().register(new
Scheme("https", 7070, sf));
- *
- * RestTemplate restTemplate = new RestTemplate(requestFactory);
- *
- * DefaultUriTemplateHandler templateHandler = new
DefaultUriTemplateHandler();
- * templateHandler.setBaseUrl(clusterUrl);
- * restTemplate.setUriTemplateHandler(templateHandler);
+ * Retrieve a {@code ClusterManagementService} instance configured with an
explicit service
+ * endpoint. This service will allow you to connect to ssl enabled and
security enabled end point
+ * with the specified sslContext and hostnameVerifier
*
- * ClusterManagementServiceProvider.getService(restTemplate);
- * </pre>
+ * @param host the locator's host name
+ * @param port http port of the locator
+ * @param sslContext a pre configured sslContext to connect with
+ * @param hostnameVerifier a pre configured hostnameVerifier to connect with
+ * @param username if cluster has security manager, use this username to
connect
+ * @param password if cluster has security manager, use this password to
connect
+ */
+ public static ClusterManagementService getService(String host, int port,
SSLContext sslContext,
+ HostnameVerifier hostnameVerifier, String username, String password) {
+ return getServiceFactory(JAVA_CLIENT_CONTEXT).create(host, port,
sslContext, hostnameVerifier,
+ username, password);
+ }
+
+ /**
+ * Retrieve a {@code ClusterManagementService} instance configured with a
+ * {@link ClientHttpRequestFactory} with a general requestFactory. you can
configure the
+ * requestFactory to tailor to your need to connect to the end point.
*
* @param requestFactory the Request Factory configured with the URL of the
Cluster Management
* Service running on a locator. The port used is as configured by the
@@ -155,4 +152,6 @@ public class ClusterManagementServiceProvider {
serviceFactories.put(factory.getContext(), factory);
}
}
+
+
}
diff --git
a/geode-management/src/main/java/org/apache/geode/management/internal/ClientClusterManagementService.java
b/geode-management/src/main/java/org/apache/geode/management/internal/ClientClusterManagementService.java
index 1ac48a0..840fd99 100644
---
a/geode-management/src/main/java/org/apache/geode/management/internal/ClientClusterManagementService.java
+++
b/geode-management/src/main/java/org/apache/geode/management/internal/ClientClusterManagementService.java
@@ -15,8 +15,19 @@
package org.apache.geode.management.internal;
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.SSLContext;
+
import org.apache.commons.lang3.NotImplementedException;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.CredentialsProvider;
+import org.apache.http.impl.client.BasicCredentialsProvider;
+import org.apache.http.impl.client.HttpClientBuilder;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpRequestFactory;
+import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.ResponseErrorHandler;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.DefaultUriTemplateHandler;
@@ -54,34 +65,58 @@ public class ClientClusterManagementService implements
ClusterManagementService
restTemplate.setErrorHandler(DEFAULT_ERROR_HANDLER);
}
- public ClientClusterManagementService(ClientHttpRequestFactory
requestFactory) {
+ public ClientClusterManagementService(String host, int port, SSLContext
sslContext,
+ HostnameVerifier hostnameVerifier, String username, String password) {
this();
- this.restTemplate.setRequestFactory(requestFactory);
- }
- public ClientClusterManagementService(String clusterUrl) {
- this();
DefaultUriTemplateHandler templateHandler = new
DefaultUriTemplateHandler();
- templateHandler.setBaseUrl(clusterUrl);
+ String schema = (sslContext == null) ? "http" : "https";
+ templateHandler.setBaseUrl(schema + "://" + host + ":" + port +
"/geode-management/v2");
restTemplate.setUriTemplateHandler(templateHandler);
+
+ // HttpComponentsClientHttpRequestFactory allows use to preconfigure
httpClient for
+ // authentication and ssl context
+ HttpComponentsClientHttpRequestFactory requestFactory =
+ new HttpComponentsClientHttpRequestFactory();
+
+ HttpClientBuilder clientBuilder = HttpClientBuilder.create();
+ // configures the clientBuilder
+ if (username != null) {
+ CredentialsProvider credsProvider = new BasicCredentialsProvider();
+ credsProvider.setCredentials(new AuthScope(host, port),
+ new UsernamePasswordCredentials(username, password));
+ clientBuilder.setDefaultCredentialsProvider(credsProvider);
+ }
+
+ clientBuilder.setSSLContext(sslContext);
+ clientBuilder.setSSLHostnameVerifier(hostnameVerifier);
+
+ requestFactory.setHttpClient(clientBuilder.build());
+ restTemplate.setRequestFactory(requestFactory);
+ }
+
+ public ClientClusterManagementService(ClientHttpRequestFactory
requestFactory) {
+ this();
+ this.restTemplate.setRequestFactory(requestFactory);
}
@Override
public ClusterManagementResult create(CacheElement config, String group) {
String endPoint = getEndpoint(config);
-
+ HttpHeaders headers = new HttpHeaders();
+ headers.setContentType(MediaType.APPLICATION_JSON);
// the response status code info is represented by the
ClusterManagementResult.errorCode already
- return restTemplate.postForEntity(endPoint, config,
ClusterManagementResult.class).getBody();
+ return restTemplate.postForObject(endPoint, config,
ClusterManagementResult.class);
}
@Override
public ClusterManagementResult delete(CacheElement config, String group) {
- throw new NotImplementedException("Not implemented");
+ throw new NotImplementedException("Not Implemented");
}
@Override
public ClusterManagementResult update(CacheElement config, String group) {
- throw new NotImplementedException("Not implemented");
+ throw new NotImplementedException("Not Implemented");
}
public RestTemplate getRestTemplate() {
@@ -97,4 +132,5 @@ public class ClientClusterManagementService implements
ClusterManagementService
return ((RestfulEndpoint) config).getEndpoint();
}
+
}
diff --git
a/geode-management/src/main/java/org/apache/geode/management/internal/ClusterManagementServiceFactory.java
b/geode-management/src/main/java/org/apache/geode/management/internal/ClusterManagementServiceFactory.java
index 4489905..814e8a2 100644
---
a/geode-management/src/main/java/org/apache/geode/management/internal/ClusterManagementServiceFactory.java
+++
b/geode-management/src/main/java/org/apache/geode/management/internal/ClusterManagementServiceFactory.java
@@ -15,6 +15,9 @@
package org.apache.geode.management.internal;
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.SSLContext;
+
import org.springframework.http.client.ClientHttpRequestFactory;
import org.apache.geode.management.api.ClusterManagementService;
@@ -30,29 +33,14 @@ public interface ClusterManagementServiceFactory {
*/
String getContext();
- /**
- * Create a {@code ClusterManagementService} instance. Throws an {@code
IllegalStateException}
- * if the instance cannot be created. This method would typically be used by
an implementation
- * that is able to infer the correct Cluster Management endpoint URL to use.
- *
- * @return an instance of the {@code ClusterManagementService}
- */
- ClusterManagementService create() throws IllegalStateException;
-
- /**
- * Create a {@code ClusterManagementService} that will use the given URL.
- *
- * @param clusterUrl the URL to conect to
- * @return an instance of {@code ClusterManagementService}
- */
- ClusterManagementService create(String clusterUrl);
+ // plain java client side
+ ClusterManagementService create(String host, int port, SSLContext sslContext,
+ HostnameVerifier hostnameVerifier, String username, String password);
- /**
- * Create a {@code ClusterManagementService} that will use the given {@link
- * ClientHttpRequestFactory} to establish connections with the Cluster
Management endpoint.
- *
- * @param requestFactory the {@code ClientHttpRequestFactory} to use for new
connections.
- * @return an instance of {@code ClusterManagementService}
- */
ClusterManagementService create(ClientHttpRequestFactory requestFactory);
+
+ // geode server side, we can infer host and port and useSSL properties from
the server side
+ ClusterManagementService create();
+
+ ClusterManagementService create(String username, String password);
}
diff --git
a/geode-management/src/main/java/org/apache/geode/management/internal/JavaClientClusterManagementServiceFactory.java
b/geode-management/src/main/java/org/apache/geode/management/internal/JavaClientClusterManagementServiceFactory.java
index 9acbd7c..0049f48 100644
---
a/geode-management/src/main/java/org/apache/geode/management/internal/JavaClientClusterManagementServiceFactory.java
+++
b/geode-management/src/main/java/org/apache/geode/management/internal/JavaClientClusterManagementServiceFactory.java
@@ -15,6 +15,9 @@
package org.apache.geode.management.internal;
+import javax.net.ssl.HostnameVerifier;
+import javax.net.ssl.SSLContext;
+
import org.springframework.http.client.ClientHttpRequestFactory;
import org.apache.geode.management.api.ClusterManagementService;
@@ -26,8 +29,7 @@ import
org.apache.geode.management.client.ClusterManagementServiceProvider;
* inferred from the implied runtime context but needs to be specifically
configured using a given
* URL or {@code ClientHttpRequestFactory}.
*/
-public class JavaClientClusterManagementServiceFactory
- implements ClusterManagementServiceFactory {
+public class JavaClientClusterManagementServiceFactory implements
ClusterManagementServiceFactory {
@Override
public String getContext() {
@@ -35,19 +37,25 @@ public class JavaClientClusterManagementServiceFactory
}
@Override
- public ClusterManagementService create() throws IllegalArgumentException {
- throw new IllegalArgumentException(String.format(
- "When using a %s context, you must call create(String) or
create(ClientHttpRequestFactory)",
- ClusterManagementServiceProvider.JAVA_CLIENT_CONTEXT));
+ public ClusterManagementService create(String host, int port, SSLContext
sslContext,
+ HostnameVerifier hostnameVerifier, String username,
+ String password) {
+ return new ClientClusterManagementService(host, port, sslContext,
hostnameVerifier, username,
+ password);
}
@Override
- public ClusterManagementService create(String clusterUrl) {
- return new ClientClusterManagementService(clusterUrl);
+ public ClusterManagementService create(ClientHttpRequestFactory
requestFactory) {
+ return new ClientClusterManagementService(requestFactory);
}
@Override
- public ClusterManagementService create(ClientHttpRequestFactory
requestFactory) {
- return new ClientClusterManagementService(requestFactory);
+ public ClusterManagementService create() {
+ throw new IllegalArgumentException("must be invoked with a host and port");
+ }
+
+ @Override
+ public ClusterManagementService create(String username, String password) {
+ throw new IllegalArgumentException("must be invoked with a host and port");
}
}
diff --git a/geode-management/src/test/resources/expected-pom.xml
b/geode-management/src/test/resources/expected-pom.xml
index 48766c6..3437c02 100644
--- a/geode-management/src/test/resources/expected-pom.xml
+++ b/geode-management/src/test/resources/expected-pom.xml
@@ -76,5 +76,10 @@
<artifactId>jaxb-api</artifactId>
<scope>compile</scope>
</dependency>
+ <dependency>
+ <groupId>org.apache.httpcomponents</groupId>
+ <artifactId>httpclient</artifactId>
+ <scope>compile</scope>
+ </dependency>
</dependencies>
</project>
diff --git
a/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/security/RestSecurityConfiguration.java
b/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/security/RestSecurityConfiguration.java
index a7b1f53..ddcc1c8 100644
---
a/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/security/RestSecurityConfiguration.java
+++
b/geode-web-management/src/main/java/org/apache/geode/management/internal/rest/security/RestSecurityConfiguration.java
@@ -80,7 +80,7 @@ public class RestSecurityConfiguration extends
WebSecurityConfigurerAdapter {
throws IOException, ServletException {
response.addHeader("WWW-Authenticate", "Basic realm=\"GEODE\"");
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
- response.setContentType(MediaType.APPLICATION_JSON_UTF8.getType());
+ response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
ClusterManagementResult result =
new
ClusterManagementResult(ClusterManagementResult.StatusCode.UNAUTHENTICATED,
authException.getMessage());